mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-23 17:22:29 +00:00
Compare commits
855 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c1bcf4dfeb | |||
| ec58d92e42 | |||
| 15c92f019a | |||
| 913fb6c22e | |||
| 76f3bb1ce6 | |||
| c4cdf811e3 | |||
| 211306f9be | |||
| a22df6da33 | |||
| b4b28e5eb8 | |||
| d86307c720 | |||
| 04b7ba7a1d | |||
| 66c952eff0 | |||
| 946cee01fc | |||
| 978650eb1f | |||
| a6a06de994 | |||
| 10952932d3 | |||
| 14b9b22ca3 | |||
| a2136e5ee4 | |||
| 1ddbfdf4e9 | |||
| 600866f573 | |||
| ad1c91f204 | |||
| 8f0d9015be | |||
| 281344b049 | |||
| 84dec889da | |||
| 1d055b5364 | |||
| d7e44643b5 | |||
| 42f7e03b04 | |||
| f33f3bd4f5 | |||
| 14d8683227 | |||
| 9c3e957d4e | |||
| b94b59cf9b | |||
| ca817051e7 | |||
| 1cb07d055e | |||
| e161805bc9 | |||
| 6db397f07d | |||
| 23758d5e90 | |||
| f8ce556acb | |||
| 3048eca5ad | |||
| 11a61f3e35 | |||
| 192dadad8c | |||
| 092fa4a3bc | |||
| 0fec2fdfdd | |||
| 09b6adf726 | |||
| edeb7d79d1 | |||
| e61e2e7f02 | |||
| 21fc487c33 | |||
| c6e9fbc878 | |||
| acb1d14fbd | |||
| 2cb58e9d02 | |||
| 1711b06836 | |||
| 6fc5f8fba2 | |||
| 909cbd8b97 | |||
| 2ed348f23d | |||
| 1aa98d34ca | |||
| 2b0ee55752 | |||
| 2f129da08a | |||
| 17c45c8d36 | |||
| 3a20bbd834 | |||
| 20f5c42c3e | |||
| 9174ccd635 | |||
| 2155a53a0d | |||
| 6a404a5a26 | |||
| 5bcb9f0b35 | |||
| 05de206ace | |||
| 28848fa913 | |||
| 51b74f47e3 | |||
| f754f06bec | |||
| d1d963df10 | |||
| a56f17a9e5 | |||
| 11f3e30245 | |||
| 707d2c8635 | |||
| dfdfb18a7e | |||
| 647fbcd6b6 | |||
| 50a8a3017b | |||
| 9ea9ed2590 | |||
| 3996a70037 | |||
| aad1396c73 | |||
| 45d81b71d6 | |||
| e70b34f245 | |||
| fe61abc3cd | |||
| 2d375eb565 | |||
| 7045581fdc | |||
| 7bf114a0bc | |||
| 2bf6c2788e | |||
| 8b35ae9921 | |||
| 8425607460 | |||
| f25246e1a0 | |||
| 3af9aeeeaf | |||
| c2c08b85f1 | |||
| 9757c38017 | |||
| 34e1dc9829 | |||
| ff876bd558 | |||
| b9d00f91de | |||
| ce71b6d9f0 | |||
| 17c41a1364 | |||
| bda39c4f77 | |||
| e423165bcb | |||
| 1b4dbd1ce7 | |||
| 3a7d7c727f | |||
| dc58173f15 | |||
| f883e085e3 | |||
| 4b2f12cd67 | |||
| 7223f2da06 | |||
| 9a1271805a | |||
| c168d7b7b6 | |||
| 7ad33f2445 | |||
| fc33a10ec0 | |||
| 8133f5312f | |||
| dfc5699403 | |||
| 0177c8d7d9 | |||
| b4b1324ace | |||
| 03592e58f9 | |||
| f8867ea73d | |||
| 488be05e0e | |||
| 78c99d0be0 | |||
| f4479c5cd7 | |||
| d449d4f54c | |||
| 17bbd8dfbe | |||
| c1feb93e2e | |||
| 07ab58483d | |||
| 2865278987 | |||
| bc77439d11 | |||
| 78f22599f4 | |||
| 24ea7e03f1 | |||
| 101bbdfd29 | |||
| c9ecca1a56 | |||
| f0222bb94b | |||
| 2fb63d4d26 | |||
| 6949f29295 | |||
| b3afc684de | |||
| baaf5801ff | |||
| ee644f7b3e | |||
| cfde67fcb3 | |||
| fa872c6030 | |||
| 6802f2a9e8 | |||
| 80ef4c7f9f | |||
| c2af87431a | |||
| ffe46bd4d2 | |||
| d7ca2440d3 | |||
| 7a17089b8a | |||
| efe09f6fe5 | |||
| 75cddbea71 | |||
| 22496e2ae2 | |||
| acb8e63d9c | |||
| e297de3830 | |||
| f474e171ed | |||
| b499dcc89d | |||
| 98f7766875 | |||
| 2159d18920 | |||
| 6f1ad1fbc1 | |||
| 1c0192dce3 | |||
| f07e708f22 | |||
| a936796b45 | |||
| 2fbf047853 | |||
| af18377505 | |||
| fe48f18f71 | |||
| a483d37c26 | |||
| 549cabe7e8 | |||
| 6f8600b885 | |||
| 3135c92340 | |||
| c2b0e00cdd | |||
| c0081a0983 | |||
| 6016ba5140 | |||
| 4bc844fe3b | |||
| faa8c35554 | |||
| d383ecc5b7 | |||
| b7dc3db703 | |||
| 0fa5b8d3f2 | |||
| 0c56660692 | |||
| f3120f26ee | |||
| 8464a0e3b5 | |||
| 525a39912f | |||
| 7c41472877 | |||
| 7c4abcc68d | |||
| f188851bfb | |||
| ee2d8a3d6d | |||
| f6c2c07a94 | |||
| 78c75501f7 | |||
| 9e5bfabf91 | |||
| 07f7b18b10 | |||
| 992797f610 | |||
| ad04b308c0 | |||
| 18c97ca637 | |||
| d64205124f | |||
| 86f35e45d3 | |||
| a6f6e18969 | |||
| 9d01e832a8 | |||
| 8d80f39ead | |||
| 63ae7ac315 | |||
| e7184f402d | |||
| 835fbb81cb | |||
| 27c8a85f61 | |||
| 67c7254fd1 | |||
| 9304e09eca | |||
| 63051dda9c | |||
| f884d8d738 | |||
| 21acd79acf | |||
| 7b819c9edf | |||
| f4983f090d | |||
| 0ee70a663c | |||
| e8d18cb014 | |||
| 6de2bb720f | |||
| 66c7deb2ac | |||
| ce0011ab18 | |||
| 2a69ae42ee | |||
| e5ad5e13db | |||
| 624c7341c5 | |||
| 53c8d63981 | |||
| 33917fe2a9 | |||
| ab3e31154c | |||
| 1dd911b150 | |||
| ec36a3787d | |||
| 376b04a37b | |||
| 861d057fe5 | |||
| 85adea631d | |||
| d91e7731c3 | |||
| 190ebbbc6f | |||
| e2f1456624 | |||
| efeb80cc8b | |||
| 98bc7f0ccd | |||
| 285bd3a627 | |||
| d3755cdb08 | |||
| 0a27ab372d | |||
| b85850052a | |||
| d83cd0ce89 | |||
| e2e8d444e9 | |||
| 4a61558de8 | |||
| eeab7baef9 | |||
| df88107697 | |||
| 79eb2d3d4b | |||
| 8ed255ad01 | |||
| eb4e970c30 | |||
| 71d36af3ef | |||
| f19648f615 | |||
| c508b48b42 | |||
| e1a5853389 | |||
| b923c69f39 | |||
| 261b6a4623 | |||
| 531cbf79f5 | |||
| ecd695ff9b | |||
| 817059a2e8 | |||
| aae073f588 | |||
| 79c9862131 | |||
| 902a850c71 | |||
| 2cf59ae2f2 | |||
| 3bdd954ac0 | |||
| 43671fa749 | |||
| 4835e87142 | |||
| 20bdbdd52d | |||
| 9bff5baa1c | |||
| 5aa99aeef1 | |||
| c35eacbc99 | |||
| 893f752520 | |||
| ffe1bede52 | |||
| 2680fc1a83 | |||
| aaae583dab | |||
| 8973059961 | |||
| 658b6ba570 | |||
| bcf2a5c852 | |||
| 9bf4f399da | |||
| 625df2ad9b | |||
| 3e42cae123 | |||
| 3ac87c8e31 | |||
| 07ee9901b7 | |||
| 1e3f7b14c8 | |||
| cbcfa2f2df | |||
| 75da37b7b4 | |||
| a5f805e1f7 | |||
| 0999278b75 | |||
| 321fa9cd50 | |||
| 8323f6af7b | |||
| a1089fccd6 | |||
| 41d19c4e8a | |||
| 370b5d7810 | |||
| eb1d43020e | |||
| a11816fddf | |||
| 957aba7ae5 | |||
| d0f9a14217 | |||
| 41dc7622f9 | |||
| cc0d0cc126 | |||
| b3ded44a59 | |||
| ccbaccd0c1 | |||
| bc525e33c5 | |||
| 13ba997589 | |||
| 4c0a9562ee | |||
| 72aaf56c79 | |||
| 9408403a00 | |||
| 211462456c | |||
| b24f1914ab | |||
| 548701cba6 | |||
| 0d3bd5988b | |||
| 5126104fd6 | |||
| 64deca11b2 | |||
| 4ae02e5efe | |||
| b7ee4634be | |||
| b868cbbcfe | |||
| 7002ee184a | |||
| 53292a99a2 | |||
| 43586a33cd | |||
| 839b6e25d8 | |||
| 39e35fa011 | |||
| 1d6a185f0f | |||
| 60c6583c54 | |||
| bc9f85843e | |||
| ce2c1b585f | |||
| a2c5f359d8 | |||
| a4d0db8e0a | |||
| fe0758c984 | |||
| 1fc23beb78 | |||
| f46b88bbde | |||
| 4a3701f05a | |||
| ede969a614 | |||
| e0d65df4de | |||
| 4e538d14c8 | |||
| a04e78cfd1 | |||
| 4106251497 | |||
| 892fb58b18 | |||
| 7fc8841a67 | |||
| b98bc207fb | |||
| f380519803 | |||
| 0513f1ad5d | |||
| 4c9a3b7c29 | |||
| be459de555 | |||
| 4258e5cebc | |||
| 22a157787e | |||
| 26e153727e | |||
| 97e47dcbfb | |||
| fb4cc70999 | |||
| 918bdd73f4 | |||
| 234b7a3c57 | |||
| 638c96f24a | |||
| 8f78a3fd35 | |||
| 8a55106288 | |||
| 76b29c04e5 | |||
| a2f39e22d1 | |||
| 5dc63a6d35 | |||
| c2cbf7a2ab | |||
| 5952610a7b | |||
| 87b4640ff0 | |||
| 663ff55271 | |||
| c91374444b | |||
| be16e558ff | |||
| 7cef9a05dd | |||
| a245fceddd | |||
| a52ab7ae48 | |||
| eb5e0ee72c | |||
| 417b034273 | |||
| 4d68ddc82f | |||
| 87d42931aa | |||
| cb874ad4e2 | |||
| 1b8f613391 | |||
| d64f79cb2a | |||
| c8f6b098c2 | |||
| b7cd0b223f | |||
| 9f1f36cca6 | |||
| 3cd474e960 | |||
| 8dd362a101 | |||
| 7909270527 | |||
| 3c1b499485 | |||
| a69fbb9e0b | |||
| 753f53be1b | |||
| 3455d70ca2 | |||
| e70e11f86c | |||
| 2ca5a4ade6 | |||
| 1e75b4ba77 | |||
| 5a73d26d12 | |||
| 61c9a07596 | |||
| 88dfc4abd8 | |||
| e2ac647e03 | |||
| 1d29c873fb | |||
| 70577584ab | |||
| dcd1a07553 | |||
| d083262555 | |||
| fe97af4d89 | |||
| 22efe33f9b | |||
| 82fe15190b | |||
| 7c89ab3fec | |||
| 578bbf657a | |||
| 99620f8535 | |||
| 8d3d3d2af2 | |||
| 947145a642 | |||
| fe98b3363d | |||
| 49e9c9ee34 | |||
| 80c2d9d68d | |||
| 0372651613 | |||
| f2e0384cb8 | |||
| 59e40b3fbe | |||
| 927a88cf96 | |||
| 803fa48c05 | |||
| 81e827481b | |||
| 214873c139 | |||
| 233b096c17 | |||
| cca7a7899a | |||
| 25c6ddd631 | |||
| 35991b68a0 | |||
| da1167671b | |||
| 2bf49be855 | |||
| b71e856c8c | |||
| 88659b5f7e | |||
| 895f27a6c1 | |||
| ea18238a12 | |||
| 56b57d2ca6 | |||
| fdfd602bd2 | |||
| 850a908874 | |||
| c61feffe26 | |||
| 74aec82d2a | |||
| b11fea91a6 | |||
| 009918cbd1 | |||
| 5a6685d129 | |||
| 337ce2d74b | |||
| cee7e401dd | |||
| cb525156ef | |||
| 4b64e8c39c | |||
| c3a805923c | |||
| 476ee10ca0 | |||
| 31301e0a26 | |||
| 3dd89b0daa | |||
| 67143f1b8a | |||
| 8f156b3c91 | |||
| a41570677f | |||
| ce5e185738 | |||
| fd989cdbc8 | |||
| 51caa3c577 | |||
| 77f050b653 | |||
| c0ea82f9e1 | |||
| d34b4a786b | |||
| d5098a56e0 | |||
| 32e880f571 | |||
| 635ac692ea | |||
| 6621a125e6 | |||
| 5481847987 | |||
| 6503e6371a | |||
| ca311c8990 | |||
| c5609db8d1 | |||
| 6ffe7a9563 | |||
| 0dcf34d62b | |||
| 08f8e2e55c | |||
| 34655e7753 | |||
| 56e064751b | |||
| a583391319 | |||
| de81850dd9 | |||
| 94f47e7adf | |||
| 065363480f | |||
| 0447321d92 | |||
| c445f63186 | |||
| 33b6748c1b | |||
| 60f2e31240 | |||
| f4c22d7111 | |||
| d3280c9676 | |||
| 1b088b7157 | |||
| a984e9bd7c | |||
| 34f0106437 | |||
| 335470d3db | |||
| 121af489c4 | |||
| 106e0c69ab | |||
| 4898bfd822 | |||
| d68075a5dc | |||
| ed11ee8bea | |||
| b1829e929e | |||
| 65ac9683a3 | |||
| e5d1e98793 | |||
| afaa9ee6c9 | |||
| dd345c01de | |||
| 63928caace | |||
| 985d969384 | |||
| bad4a94b84 | |||
| 416538764a | |||
| 1589169200 | |||
| 8dccc8bf90 | |||
| 8174428189 | |||
| 8422ce6f25 | |||
| 963eb91669 | |||
| d5e697c061 | |||
| 33c1c7c3e4 | |||
| dbbe6b5a91 | |||
| 250d0cc903 | |||
| 5186d3a2ef | |||
| 361c93b689 | |||
| 3ee1c43ac4 | |||
| 226bb4f3b2 | |||
| 6229b90451 | |||
| db307d865b | |||
| 4bb2bb1438 | |||
| 6515879c14 | |||
| 3d1dc6314d | |||
| f198ab714f | |||
| c2e4365214 | |||
| 4a036bede2 | |||
| f35594947c | |||
| f57734e591 | |||
| 42a5ddcf77 | |||
| 03bc245318 | |||
| a9b98ed057 | |||
| b45f0f9dbc | |||
| 6cb1861c91 | |||
| 0b17dc73f1 | |||
| fafbecb055 | |||
| a5d9faf8ea | |||
| 00d258a952 | |||
| 64caf298fb | |||
| 7f30950fdb | |||
| dbd07106d7 | |||
| 328b7bb93c | |||
| c351a9b54f | |||
| 6ff06ded43 | |||
| 2c6fd44811 | |||
| 66d37cabe4 | |||
| 9a5ff58213 | |||
| c3c6d18979 | |||
| aacd288ad7 | |||
| 46dd1511af | |||
| 7011395d4c | |||
| 03c006bef5 | |||
| bfb40f6c5f | |||
| 38cdea7d7e | |||
| d9cab4820a | |||
| 96264cb688 | |||
| b0d85e3558 | |||
| 0348c0817d | |||
| a41fd122bc | |||
| 8646791d1d | |||
| 070183789b | |||
| 36de3879f8 | |||
| e588af2e79 | |||
| 2416960818 | |||
| be210950d7 | |||
| 5917052a6d | |||
| d7b9d7c990 | |||
| 235d6b6c48 | |||
| 95243fd6ce | |||
| e5f979665d | |||
| 22ef16947c | |||
| dbbae0e735 | |||
| 24917257e6 | |||
| dbd615572c | |||
| 92c756c820 | |||
| 76d7fe1586 | |||
| 4424afac94 | |||
| 2b495cea5a | |||
| e7902342dd | |||
| 5c194c7087 | |||
| b6091c1960 | |||
| d2a1fb7acf | |||
| ee136881c8 | |||
| b06e1c2041 | |||
| 41ca23eb7c | |||
| 5c4389effb | |||
| 788959a5e2 | |||
| aaca6fd2d9 | |||
| 1bcb5c72a5 | |||
| 249d67a1c3 | |||
| 85bdcf413b | |||
| 93942fa82b | |||
| 8922c72452 | |||
| ec8e7139ec | |||
| a882397eb6 | |||
| 7d61934ce6 | |||
| 7041db7480 | |||
| 70048eb6e1 | |||
| a46b1ac18b | |||
| 00721f4a96 | |||
| 8aadc36320 | |||
| 351e63ae72 | |||
| 9cbda0f81b | |||
| ea44b4b3b1 | |||
| ea5a1dd6f1 | |||
| 2ef0fc9342 | |||
| 02c3fd0905 | |||
| 4266f45295 | |||
| 553b7c9f8c | |||
| 79a87fac1d | |||
| 2308d3e880 | |||
| cbcaead8df | |||
| 4b7871a665 | |||
| 052f343e4d | |||
| e6f6da7845 | |||
| cc2a60feb2 | |||
| d5eeaf4f47 | |||
| 6fad93aeee | |||
| d1fbd086d7 | |||
| c360aa9b0f | |||
| f68952c168 | |||
| bf4ff03641 | |||
| 103d808925 | |||
| 53a139256d | |||
| 7bcfaf60ab | |||
| ebe2ea697e | |||
| 8224a9e776 | |||
| be0507c4d3 | |||
| cfedf53dc0 | |||
| 4a4a0c5e8b | |||
| 77dca484fe | |||
| 690274338d | |||
| 59ab7071b7 | |||
| 1438c1a9c3 | |||
| 72702be820 | |||
| 1ab3cf53e2 | |||
| 79928c190b | |||
| 6c8dfbdc4d | |||
| 1f56c7476e | |||
| eda74e66e0 | |||
| 80fd71a406 | |||
| 399942f6f4 | |||
| 3846dc2bbc | |||
| 06f4fd49ef | |||
| eea667e22d | |||
| 8b4d601027 | |||
| a1960d4a4a | |||
| d7c556c672 | |||
| 2c4ca77ffc | |||
| 7bde00c63b | |||
| 46d7019909 | |||
| 41f3b721d6 | |||
| cafac36bed | |||
| 0d84ede3d6 | |||
| d7e3a33179 | |||
| c84f56f1f5 | |||
| 47c9690a32 | |||
| de57c94d3e | |||
| c974b30192 | |||
| 23dd560a72 | |||
| 0eda3efe6a | |||
| a4ac2b3831 | |||
| ea240f7814 | |||
| 0d4775a9df | |||
| 0321bf72a5 | |||
| 739a7b6f75 | |||
| 979590db9f | |||
| 7bd185b7b7 | |||
| 7662eaf983 | |||
| 78eb8747aa | |||
| fc1d6c0676 | |||
| 7e1c296ecf | |||
| 51a314fa31 | |||
| b3efd8a817 | |||
| bf93d72a43 | |||
| 026278504f | |||
| a5872b165f | |||
| 8bd22e8c38 | |||
| e304e67cf1 | |||
| b6a01871d8 | |||
| a569e20110 | |||
| 75146350fc | |||
| 2635d37095 | |||
| a75f4e70a1 | |||
| b6cc070633 | |||
| 94d118fdf8 | |||
| 4dcb679c53 | |||
| ad9e9ba2d6 | |||
| c4a7acb6d1 | |||
| e6835804af | |||
| 9598ce45c9 | |||
| 9ef4825a72 | |||
| eed57ddf97 | |||
| 202c59eb48 | |||
| f86c6d9c5e | |||
| 340ed6c59d | |||
| 0cf5cca415 | |||
| f021ee5491 | |||
| 6c26bc9c8f | |||
| 93eb727ade | |||
| 1c454d9569 | |||
| 3b9f62f0a1 | |||
| cd82aae183 | |||
| d08d50f4b5 | |||
| c5fb9ba6dd | |||
| 2bcb964326 | |||
| b3a0370e71 | |||
| 9344cfb4e3 | |||
| bcf8b1af8e | |||
| 2003efb5ab | |||
| 13743caf19 | |||
| 6a241d44cc | |||
| b36d9fe115 | |||
| c313bd8d07 | |||
| be9066235b | |||
| 1f540666f8 | |||
| 2cf2ef4fac | |||
| c305582c77 | |||
| 69d02b7e72 | |||
| c96ee79b1e | |||
| bd9665e35b | |||
| 0210d6f6bf | |||
| fe294e60b5 | |||
| f95806b47b | |||
| 10f1e69ad8 | |||
| d3249397f3 | |||
| 69e9adf796 | |||
| 4835b7063c | |||
| 8dfa0a7220 | |||
| 2b8bdb9158 | |||
| 7851f272e5 | |||
| e15ee6e320 | |||
| 1f0b86a0d5 | |||
| e47f9d95b0 | |||
| 0b6d71181f | |||
| 318a664b09 | |||
| 180c4c3286 | |||
| 221c1f17c7 | |||
| d601a70546 | |||
| ba49e5f696 | |||
| 19fc02c284 | |||
| b05581499a | |||
| 9d866c1889 | |||
| a567812f35 | |||
| 167b6f5ebf | |||
| 2bed129037 | |||
| a0ea6066ed | |||
| c8c2209617 | |||
| eff818ca42 | |||
| a537981ad0 | |||
| 32cb219e64 | |||
| 4f3360aa49 | |||
| e61f647bf2 | |||
| 7afb29cf02 | |||
| 0a351bf6e1 | |||
| 9a19d59cf7 | |||
| c5a217842f | |||
| 921a292f5b | |||
| 3b45a66498 | |||
| 414db873b7 | |||
| 7deb4d5e78 | |||
| fe77c6fb3f | |||
| aaa9595b59 | |||
| 2d40adcf66 | |||
| 57ccddbb36 | |||
| b6dd604de2 | |||
| 911a515923 | |||
| ea38fd2421 | |||
| e7fc6420f2 | |||
| 766641cd15 | |||
| e4be4d6895 | |||
| 53a1faa36f | |||
| 20249cec67 | |||
| dedbb3f6c8 | |||
| 5a3b10a11c | |||
| f1a25da065 | |||
| f9dbea531c | |||
| b48a712887 | |||
| 28be3b87b7 | |||
| db3feafe48 | |||
| 9a78bac0d0 | |||
| f95e211d9b | |||
| 75809fc3bb | |||
| 811e8809cc | |||
| eaf5cea908 | |||
| 7ac7914f33 | |||
| da425195f9 | |||
| a544c681c7 | |||
| fd45e8d21d | |||
| 1966324112 | |||
| d1be53bef2 | |||
| 16002eb62e | |||
| 2774d8e761 | |||
| e07704e36b | |||
| 9f400c8d14 | |||
| 2c31b348c3 | |||
| cefff6506f | |||
| 7f65080c45 | |||
| c8acb7bd43 | |||
| 69d727cbe5 | |||
| 9daf572ea7 | |||
| f613d12c61 | |||
| 927e4f83ff | |||
| 82b9af3956 | |||
| 82933a80d1 | |||
| 543e265b0a | |||
| c4eb6e2881 | |||
| e6eb4e16d1 | |||
| 95b66583b3 | |||
| 8cde649e39 | |||
| 45e7ff9193 | |||
| 48c65628d8 | |||
| 0521cae8d0 | |||
| 4629c7c8c4 | |||
| 8b925f549b | |||
| cb81d956f6 | |||
| 1149f04389 | |||
| 9aac1b0081 | |||
| 3392f4b1c3 | |||
| 20712ce0e6 | |||
| 9a15361e93 | |||
| 452b1a1eae | |||
| edbd055277 | |||
| 7bf054bd58 | |||
| 67ee327f5b | |||
| 63810d5c1b | |||
| d5047da637 | |||
| 9446d75444 | |||
| c9cd733d9a | |||
| 5a619bddaf | |||
| 5d64012d74 | |||
| 2bf2485b4c | |||
| 8acaa47b8f | |||
| bc6199a86f | |||
| f26d303ee1 | |||
| b96e5a7f4d | |||
| 36d53f69d6 | |||
| ef5d475978 | |||
| dce6ccf4de | |||
| b169544711 | |||
| 1495eb42a3 | |||
| dd17597c92 | |||
| 54c3f9ab94 | |||
| ecd05d821e | |||
| 4bd2e04482 | |||
| cafd0eaba1 | |||
| facd7d357d | |||
| 8bc5e5eee1 | |||
| bfa6bd3458 | |||
| 33767aeb91 | |||
| ff8a19b1cb | |||
| 356316db84 | |||
| 379219aff1 | |||
| a677d40f6d | |||
| aed3d9ef85 | |||
| f2667cee23 | |||
| e1c49f93e2 | |||
| d2b9d4ab20 | |||
| 20c99e36d8 | |||
| 3ec39ce06b | |||
| 10e3c31ad6 | |||
| 4b08c75527 | |||
| 8aa8982b66 | |||
| 5daa29aa3f | |||
| 75c48e5800 | |||
| 6c982179bc | |||
| 02e56331ec | |||
| 774e429d87 | |||
| 3340d01902 | |||
| 180612bb21 | |||
| 8649ed1dcb | |||
| f9ba99e99f | |||
| 1d40f20da0 | |||
| 614014a238 | |||
| 1ff2a043f4 | |||
| 115d0d14ac | |||
| b3ea1a9da7 | |||
| 5fcd3eb38e | |||
| e35205eaf4 | |||
| 081a61a948 | |||
| d75c632d73 | |||
| d9c47fcd41 | |||
| 387b445685 | |||
| 46ac254b3a | |||
| 5f64b1e1c8 | |||
| 5c729e65c9 | |||
| 4f4eee2b16 | |||
| ed9bdaf60c | |||
| a6b95aeceb | |||
| 54fae508c5 | |||
| 0cd320dd75 | |||
| 725c5633f6 | |||
| ef082b9144 | |||
| 7fed01ddea |
+10
-8
@@ -1,16 +1,18 @@
|
||||
language: cpp
|
||||
compiler: gcc
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -y libmysqlclient-dev libperl-dev libboost-dev liblua5.1-0-dev zlib1g-dev
|
||||
sudo: false
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libmysqlclient-dev
|
||||
- libperl-dev
|
||||
- libboost-dev
|
||||
- liblua5.1-0-dev
|
||||
- zlib1g-dev
|
||||
script:
|
||||
- cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON
|
||||
- make
|
||||
- make -j8
|
||||
- ./bin/tests
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- stable
|
||||
notifications:
|
||||
email: false
|
||||
irc:
|
||||
|
||||
@@ -331,8 +331,14 @@ IF(EQEMU_BUILD_LUA)
|
||||
ADD_SUBDIRECTORY(luabind)
|
||||
ENDIF(EQEMU_BUILD_LUA)
|
||||
|
||||
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/recast/debug_utils/include")
|
||||
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/recast/detour/include")
|
||||
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/recast/detour_tile_cache/include")
|
||||
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/recast/recast/include")
|
||||
|
||||
IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS)
|
||||
ADD_SUBDIRECTORY(common)
|
||||
ADD_SUBDIRECTORY(recast)
|
||||
ENDIF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS)
|
||||
IF(EQEMU_BUILD_SERVER)
|
||||
ADD_SUBDIRECTORY(shared_memory)
|
||||
|
||||
+620
-205
File diff suppressed because it is too large
Load Diff
@@ -32,6 +32,7 @@ EQEmuLogSys Log;
|
||||
void ExportSpells(SharedDatabase *db);
|
||||
void ExportSkillCaps(SharedDatabase *db);
|
||||
void ExportBaseData(SharedDatabase *db);
|
||||
void ExportDBStrings(SharedDatabase *db);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
RegisterExecutablePlatform(ExePlatformClientExport);
|
||||
@@ -62,6 +63,7 @@ int main(int argc, char **argv) {
|
||||
ExportSpells(&database);
|
||||
ExportSkillCaps(&database);
|
||||
ExportBaseData(&database);
|
||||
ExportDBStrings(&database);
|
||||
|
||||
Log.CloseFileLogs();
|
||||
|
||||
@@ -194,7 +196,38 @@ void ExportBaseData(SharedDatabase *db) {
|
||||
|
||||
fprintf(f, "%s\n", line.c_str());
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void ExportDBStrings(SharedDatabase *db) {
|
||||
Log.Out(Logs::General, Logs::Status, "Exporting DB Strings...");
|
||||
|
||||
FILE *f = fopen("export/dbstr_us.txt", "w");
|
||||
if(!f) {
|
||||
Log.Out(Logs::General, Logs::Error, "Unable to open export/dbstr_us.txt to write, skipping.");
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(f, "Major^Minor^String(New)\n");
|
||||
const std::string query = "SELECT * FROM db_str ORDER BY id, type";
|
||||
auto results = db->QueryDatabase(query);
|
||||
if(results.Success()) {
|
||||
for(auto row = results.begin(); row != results.end(); ++row) {
|
||||
std::string line;
|
||||
unsigned int fields = results.ColumnCount();
|
||||
for(unsigned int rowIndex = 0; rowIndex < fields; ++rowIndex) {
|
||||
if(rowIndex != 0)
|
||||
line.push_back('^');
|
||||
|
||||
if(row[rowIndex] != nullptr) {
|
||||
line += row[rowIndex];
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(f, "%s\n", line.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
@@ -30,6 +30,7 @@ EQEmuLogSys Log;
|
||||
void ImportSpells(SharedDatabase *db);
|
||||
void ImportSkillCaps(SharedDatabase *db);
|
||||
void ImportBaseData(SharedDatabase *db);
|
||||
void ImportDBStrings(SharedDatabase *db);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
RegisterExecutablePlatform(ExePlatformClientImport);
|
||||
@@ -59,6 +60,7 @@ int main(int argc, char **argv) {
|
||||
ImportSpells(&database);
|
||||
ImportSkillCaps(&database);
|
||||
ImportBaseData(&database);
|
||||
ImportDBStrings(&database);
|
||||
|
||||
Log.CloseFileLogs();
|
||||
|
||||
@@ -76,6 +78,24 @@ int GetSpellColumns(SharedDatabase *db) {
|
||||
return results.RowCount();
|
||||
}
|
||||
|
||||
bool IsStringField(int i) {
|
||||
switch(i)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ImportSpells(SharedDatabase *db) {
|
||||
Log.Out(Logs::General, Logs::Status, "Importing Spells...");
|
||||
FILE *f = fopen("import/spells_us.txt", "r");
|
||||
@@ -113,7 +133,12 @@ void ImportSpells(SharedDatabase *db) {
|
||||
sql += "'";
|
||||
}
|
||||
|
||||
sql += split[i];
|
||||
if(split[i].compare("") == 0 && !IsStringField(i)) {
|
||||
sql += "0";
|
||||
}
|
||||
else {
|
||||
sql += split[i];
|
||||
}
|
||||
sql += "'";
|
||||
}
|
||||
|
||||
@@ -128,7 +153,12 @@ void ImportSpells(SharedDatabase *db) {
|
||||
sql += "'";
|
||||
}
|
||||
|
||||
sql += split[i];
|
||||
if(split[i].compare("") == 0 && !IsStringField(i)) {
|
||||
sql += "0";
|
||||
} else {
|
||||
sql += split[i];
|
||||
}
|
||||
|
||||
sql += "'";
|
||||
}
|
||||
|
||||
@@ -174,7 +204,6 @@ void ImportSkillCaps(SharedDatabase *db) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
int class_id, skill_id, level, cap;
|
||||
class_id = atoi(split[0].c_str());
|
||||
skill_id = atoi(split[1].c_str());
|
||||
@@ -234,3 +263,56 @@ void ImportBaseData(SharedDatabase *db) {
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void ImportDBStrings(SharedDatabase *db) {
|
||||
Log.Out(Logs::General, Logs::Status, "Importing DB Strings...");
|
||||
|
||||
FILE *f = fopen("import/dbstr_us.txt", "r");
|
||||
if(!f) {
|
||||
Log.Out(Logs::General, Logs::Error, "Unable to open import/dbstr_us.txt to read, skipping.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string delete_sql = "DELETE FROM db_str";
|
||||
db->QueryDatabase(delete_sql);
|
||||
|
||||
char buffer[2048];
|
||||
bool first = true;
|
||||
while(fgets(buffer, 2048, f)) {
|
||||
if(first) {
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
for(int i = 0; i < 2048; ++i) {
|
||||
if(buffer[i] == '\n') {
|
||||
buffer[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto split = SplitString(buffer, '^');
|
||||
|
||||
if(split.size() < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string sql;
|
||||
int id, type;
|
||||
std::string value;
|
||||
|
||||
id = atoi(split[0].c_str());
|
||||
type = atoi(split[1].c_str());
|
||||
|
||||
if(split.size() >= 3) {
|
||||
value = ::EscapeString(split[2]);
|
||||
}
|
||||
|
||||
sql = StringFormat("INSERT INTO db_str(id, type, value) VALUES(%u, %u, '%s')",
|
||||
id, type, value.c_str());
|
||||
|
||||
db->QueryDatabase(sql);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
+23
-20
@@ -21,6 +21,12 @@ IF(MYSQL_ROOT)
|
||||
NAMES mysql.h
|
||||
PATHS ${MYSQL_ROOT}/include
|
||||
PATH_SUFFIXES mysql
|
||||
NO_DEFAULT_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH
|
||||
)
|
||||
FIND_PATH(MySQL_INCLUDE_DIR
|
||||
NAMES mysql.h
|
||||
PATH_SUFFIXES mysql
|
||||
)
|
||||
ELSE(MYSQL_ROOT)
|
||||
FIND_PATH(MySQL_INCLUDE_DIR
|
||||
@@ -30,49 +36,46 @@ ELSE(MYSQL_ROOT)
|
||||
ENDIF(MYSQL_ROOT)
|
||||
|
||||
# Library
|
||||
SET(MySQL_NAMES mysqlclient_r mysqlclient)
|
||||
SET(MySQL_NAMES libmysql)
|
||||
IF(MYSQL_ROOT)
|
||||
FIND_LIBRARY(MySQL_LIBRARY_DEBUG
|
||||
FIND_LIBRARY(MySQL_LIBRARY
|
||||
NAMES ${MySQL_NAMES}
|
||||
PATHS ${MYSQL_ROOT}/lib/debug /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
|
||||
PATHS ${MYSQL_ROOT}/lib
|
||||
PATH_SUFFIXES mysql
|
||||
NO_DEFAULT_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH
|
||||
)
|
||||
|
||||
FIND_LIBRARY(MySQL_LIBRARY_RELEASE
|
||||
|
||||
FIND_LIBRARY(MySQL_LIBRARY
|
||||
NAMES ${MySQL_NAMES}
|
||||
PATHS ${MYSQL_ROOT}/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
|
||||
PATH_SUFFIXES mysql
|
||||
)
|
||||
ELSE(MYSQL_ROOT)
|
||||
FIND_LIBRARY(MySQL_LIBRARY_DEBUG
|
||||
NAMES ${MySQL_NAMES}
|
||||
PATHS /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
|
||||
PATH_SUFFIXES mysql
|
||||
)
|
||||
|
||||
FIND_LIBRARY(MySQL_LIBRARY_RELEASE
|
||||
NAMES ${MySQL_NAMES}
|
||||
FIND_LIBRARY(MySQL_LIBRARY
|
||||
NAMES ${MySQL_NAMES} mysqlclient_r mysqlclient
|
||||
PATHS /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
|
||||
PATH_SUFFIXES mysql
|
||||
)
|
||||
ENDIF(MYSQL_ROOT)
|
||||
|
||||
IF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY_DEBUG AND MySQL_LIBRARY_RELEASE)
|
||||
IF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY)
|
||||
SET(MySQL_FOUND TRUE)
|
||||
SET( MySQL_LIBRARIES ${MySQL_LIBRARY_DEBUG} ${MySQL_LIBRARY_RELEASE} )
|
||||
ELSE (MySQL_INCLUDE_DIR AND MySQL_LIBRARY_DEBUG AND MySQL_LIBRARY_RELEASE)
|
||||
SET( MySQL_LIBRARIES ${MySQL_LIBRARY} )
|
||||
ELSE (MySQL_INCLUDE_DIR AND MySQL_LIBRARY)
|
||||
SET(MySQL_FOUND FALSE)
|
||||
SET( MySQL_LIBRARIES )
|
||||
ENDIF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY_DEBUG AND MySQL_LIBRARY_RELEASE)
|
||||
ENDIF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY)
|
||||
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set MySQL_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MySQL DEFAULT_MSG MySQL_LIBRARY_DEBUG MySQL_LIBRARY_RELEASE MySQL_INCLUDE_DIR)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MySQL DEFAULT_MSG MySQL_LIBRARY MySQL_INCLUDE_DIR)
|
||||
|
||||
IF(MySQL_FOUND)
|
||||
SET( MySQL_LIBRARIES ${MySQL_LIBRARY_DEBUG} ${MySQL_LIBRARY_RELEASE} )
|
||||
SET( MySQL_LIBRARY_RELEASE ${MySQL_LIBRARY} )
|
||||
SET( MySQL_LIBRARY_DEBUG ${MySQL_LIBRARY} )
|
||||
SET( MySQL_LIBRARIES ${MySQL_LIBRARY_RELEASE} ${MySQL_LIBRARY_DEBUG} )
|
||||
ELSE(MySQL_FOUND)
|
||||
SET( MySQL_LIBRARIES )
|
||||
ENDIF(MySQL_FOUND)
|
||||
|
||||
@@ -64,6 +64,7 @@ SET(common_sources
|
||||
unix.cpp
|
||||
worldconn.cpp
|
||||
xml_parser.cpp
|
||||
pathfind.cpp
|
||||
platform.cpp
|
||||
patches/patches.cpp
|
||||
patches/sod.cpp
|
||||
@@ -156,6 +157,7 @@ SET(common_headers
|
||||
packet_dump.h
|
||||
packet_dump_file.h
|
||||
packet_functions.h
|
||||
pathfind.h
|
||||
platform.h
|
||||
proc_launcher.h
|
||||
profiler.h
|
||||
|
||||
@@ -63,9 +63,12 @@ public:
|
||||
void WriteFloat(float value) { *(float *)(pBuffer + _wpos) = value; _wpos += sizeof(float); }
|
||||
void WriteDouble(double value) { *(double *)(pBuffer + _wpos) = value; _wpos += sizeof(double); }
|
||||
void WriteString(const char * str) { uint32 len = static_cast<uint32>(strlen(str)) + 1; memcpy(pBuffer + _wpos, str, len); _wpos += len; }
|
||||
void WriteData(const void *ptr, size_t n) { memcpy(pBuffer + _wpos, ptr, n); _wpos += (uint32)n; }
|
||||
|
||||
uint8 ReadUInt8() { uint8 value = *(uint8 *)(pBuffer + _rpos); _rpos += sizeof(uint8); return value; }
|
||||
uint8 ReadUInt8(uint32 Offset) const { uint8 value = *(uint8 *)(pBuffer + Offset); return value; }
|
||||
uint16 ReadUInt16() { uint16 value = *(uint16 *)(pBuffer + _rpos); _rpos += sizeof(uint16); return value; }
|
||||
uint16 ReadUInt16(uint32 Offset) const { uint16 value = *(uint16 *)(pBuffer + Offset); return value; }
|
||||
uint32 ReadUInt32() { uint32 value = *(uint32 *)(pBuffer + _rpos); _rpos += sizeof(uint32); return value; }
|
||||
uint32 ReadUInt32(uint32 Offset) const { uint32 value = *(uint32 *)(pBuffer + Offset); return value; }
|
||||
void ReadString(char *str) { uint32 len = static_cast<uint32>(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; }
|
||||
|
||||
+130
-25
@@ -1,22 +1,50 @@
|
||||
/*
|
||||
EQEMu: Everquest Server Emulator
|
||||
|
||||
Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef CLIENTVERSIONS_H
|
||||
#define CLIENTVERSIONS_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
static const uint32 BIT_Client62 = 1;
|
||||
static const uint32 BIT_Titanium = 2;
|
||||
static const uint32 BIT_SoF = 4;
|
||||
static const uint32 BIT_SoD = 8;
|
||||
static const uint32 BIT_UF = 16;
|
||||
static const uint32 BIT_RoF = 32;
|
||||
static const uint32 BIT_RoF2 = 64;
|
||||
static const uint32 BIT_Client62 = 0x00000001; // 1 (unsupported - placeholder for scripts)
|
||||
|
||||
static const uint32 BIT_Titanium = 0x00000002; // 2
|
||||
static const uint32 BIT_SoF = 0x00000004; // 4
|
||||
static const uint32 BIT_SoD = 0x00000008; // 8
|
||||
static const uint32 BIT_UF = 0x00000010; // 16
|
||||
static const uint32 BIT_RoF = 0x00000020; // 32
|
||||
static const uint32 BIT_RoF2 = 0x00000040; // 64
|
||||
|
||||
static const uint32 BIT_TitaniumAndEarlier = 0x00000003; // 3
|
||||
static const uint32 BIT_SoFAndEarlier = 0x00000007; // 7
|
||||
static const uint32 BIT_SoDAndEarlier = 0x0000000F; // 15
|
||||
static const uint32 BIT_UFAndEarlier = 0x0000001F; // 31
|
||||
static const uint32 BIT_RoFAndEarlier = 0x0000003F; // 63
|
||||
|
||||
static const uint32 BIT_SoFAndLater = 0xFFFFFFFC; // 4294967292
|
||||
static const uint32 BIT_SoDAndLater = 0xFFFFFFF8; // 4294967288
|
||||
static const uint32 BIT_UFAndLater = 0xFFFFFFF0; // 4294967280
|
||||
static const uint32 BIT_RoFAndLater = 0xFFFFFFE0; // 4294967264
|
||||
static const uint32 BIT_RoF2AndLater = 0xFFFFFFC0; // 4294967232
|
||||
|
||||
static const uint32 BIT_TitaniumAndEarlier = 0x00000003;
|
||||
static const uint32 BIT_SoFAndLater = 0xFFFFFFFC;
|
||||
static const uint32 BIT_SoDAndLater = 0xFFFFFFF8;
|
||||
static const uint32 BIT_UFAndLater = 0xFFFFFFF0;
|
||||
static const uint32 BIT_RoFAndLater = 0xFFFFFFE0;
|
||||
static const uint32 BIT_RoF2AndLater = 0xFFFFFFC0;
|
||||
static const uint32 BIT_AllClients = 0xFFFFFFFF;
|
||||
|
||||
enum class ClientVersion
|
||||
@@ -46,32 +74,109 @@ static const char* ClientVersionName(ClientVersion version)
|
||||
switch (version)
|
||||
{
|
||||
case ClientVersion::Unknown:
|
||||
return "ClientVersion::Unknown";
|
||||
return "Unknown";
|
||||
case ClientVersion::Client62:
|
||||
return "ClientVersion::Client62";
|
||||
return "Client62";
|
||||
case ClientVersion::Titanium:
|
||||
return "ClientVersion::Titanium";
|
||||
return "Titanium";
|
||||
case ClientVersion::SoF:
|
||||
return "ClientVersion::SoF";
|
||||
return "SoF";
|
||||
case ClientVersion::SoD:
|
||||
return "ClientVersion::SoD";
|
||||
return "SoD";
|
||||
case ClientVersion::UF:
|
||||
return "ClientVersion::UF";
|
||||
return "UF";
|
||||
case ClientVersion::RoF:
|
||||
return "ClientVersion::RoF";
|
||||
return "RoF";
|
||||
case ClientVersion::RoF2:
|
||||
return "ClientVersion::RoF2";
|
||||
return "RoF2";
|
||||
case ClientVersion::MobNPC:
|
||||
return "ClientVersion::MobNPC";
|
||||
return "MobNPC";
|
||||
case ClientVersion::MobMerc:
|
||||
return "ClientVersion::MobMerc";
|
||||
return "MobMerc";
|
||||
case ClientVersion::MobBot:
|
||||
return "ClientVersion::MobBot";
|
||||
return "MobBot";
|
||||
case ClientVersion::MobPet:
|
||||
return "ClientVersion::MobPet";
|
||||
return "MobPet";
|
||||
default:
|
||||
return "<ERROR> Invalid ClientVersion";
|
||||
};
|
||||
}
|
||||
|
||||
static uint32 ClientBitFromVersion(ClientVersion clientVersion)
|
||||
{
|
||||
switch (clientVersion)
|
||||
{
|
||||
case ClientVersion::Unknown:
|
||||
case ClientVersion::Client62:
|
||||
return 0;
|
||||
case ClientVersion::Titanium:
|
||||
case ClientVersion::SoF:
|
||||
case ClientVersion::SoD:
|
||||
case ClientVersion::UF:
|
||||
case ClientVersion::RoF:
|
||||
case ClientVersion::RoF2:
|
||||
case ClientVersion::MobNPC:
|
||||
case ClientVersion::MobMerc:
|
||||
case ClientVersion::MobBot:
|
||||
case ClientVersion::MobPet:
|
||||
return ((uint32)1 << (static_cast<unsigned int>(clientVersion) - 1));
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static ClientVersion ClientVersionFromBit(uint32 clientVersionBit)
|
||||
{
|
||||
switch (clientVersionBit)
|
||||
{
|
||||
case (uint32)static_cast<unsigned int>(ClientVersion::Unknown):
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::Client62) - 1)):
|
||||
return ClientVersion::Unknown;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::Titanium) - 1)):
|
||||
return ClientVersion::Titanium;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::SoF) - 1)):
|
||||
return ClientVersion::SoF;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::SoD) - 1)):
|
||||
return ClientVersion::SoD;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::UF) - 1)):
|
||||
return ClientVersion::UF;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::RoF) - 1)):
|
||||
return ClientVersion::RoF;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::RoF2) - 1)):
|
||||
return ClientVersion::RoF2;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::MobNPC) - 1)):
|
||||
return ClientVersion::MobNPC;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::MobMerc) - 1)):
|
||||
return ClientVersion::MobMerc;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::MobBot) - 1)):
|
||||
return ClientVersion::MobBot;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::MobPet) - 1)):
|
||||
return ClientVersion::MobPet;
|
||||
default:
|
||||
return ClientVersion::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32 ExpansionFromClientVersion(ClientVersion clientVersion)
|
||||
{
|
||||
switch(clientVersion)
|
||||
{
|
||||
case ClientVersion::Unknown:
|
||||
case ClientVersion::Client62:
|
||||
case ClientVersion::Titanium:
|
||||
return 0x000007FFU;
|
||||
case ClientVersion::SoF:
|
||||
return 0x00007FFFU;
|
||||
case ClientVersion::SoD:
|
||||
return 0x0000FFFFU;
|
||||
case ClientVersion::UF:
|
||||
return 0x0001FFFFU;
|
||||
case ClientVersion::RoF:
|
||||
case ClientVersion::RoF2:
|
||||
return 0x000FFFFFU;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CLIENTVERSIONS_H */
|
||||
|
||||
+73
-20
@@ -348,11 +348,11 @@ bool Database::DeleteCharacter(char *name) {
|
||||
query = StringFormat("DELETE FROM `character_inspect_messages` WHERE `id` = %u", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_leadership_abilities` WHERE `id` = %u", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_alt_currency` WHERE `char_id` = '%d'", charid); QueryDatabase(query);
|
||||
#ifdef BOTS
|
||||
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", charid);
|
||||
#else
|
||||
#ifdef BOTS
|
||||
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", charid); // note: only use of GetMobTypeById()
|
||||
#else
|
||||
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d'", charid);
|
||||
#endif
|
||||
#endif
|
||||
QueryDatabase(query);
|
||||
|
||||
return true;
|
||||
@@ -1183,21 +1183,16 @@ bool Database::CheckNameFilter(const char* name, bool surname)
|
||||
{
|
||||
std::string str_name = name;
|
||||
|
||||
if(surname)
|
||||
// the minimum 4 is enforced by the client too
|
||||
if (!name || strlen(name) < 4)
|
||||
{
|
||||
// the minimum 4 is enforced by the client too
|
||||
if(!name || strlen(name) < 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
||||
// Given name length is enforced by the client too
|
||||
if (!surname && strlen(name) > 15)
|
||||
{
|
||||
// the minimum 4 is enforced by the client too
|
||||
if(!name || strlen(name) < 4 || strlen(name) > 15)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < str_name.size(); i++)
|
||||
@@ -1384,7 +1379,7 @@ bool Database::MoveCharacterToZone(const char* charname, const char* zonename) {
|
||||
}
|
||||
|
||||
bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) {
|
||||
std::string query = StringFormat("UPDATE `character_data` SET `zone_id` = %i, `x` = -1, `y` = -1, `z` = -1 WHERE `id` = %i", iZonename, GetZoneID(iZonename), iCharID);
|
||||
std::string query = StringFormat("UPDATE `character_data` SET `zone_id` = %i, `x` = -1, `y` = -1, `z` = -1 WHERE `id` = %i", GetZoneID(iZonename), iCharID);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success()) {
|
||||
@@ -1564,7 +1559,7 @@ void Database::AddReport(std::string who, std::string against, std::string lines
|
||||
char *escape_str = new char[lines.size()*2+1];
|
||||
DoEscapeString(escape_str, lines.c_str(), lines.size());
|
||||
|
||||
std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", who.c_str(), against.c_str(), escape_str);
|
||||
std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", EscapeString(who).c_str(), EscapeString(against).c_str(), escape_str);
|
||||
QueryDatabase(query);
|
||||
safe_delete_array(escape_str);
|
||||
}
|
||||
@@ -1984,7 +1979,7 @@ void Database::GetRaidLeadershipInfo(uint32 rid, char *maintank,
|
||||
|
||||
void Database::SetRaidGroupLeaderInfo(uint32 gid, uint32 rid)
|
||||
{
|
||||
std::string query = StringFormat("UPDATE raid_leaders SET leadershipaa = '', WHERE gid = %lu AND rid = %lu",
|
||||
std::string query = StringFormat("UPDATE raid_leaders SET leadershipaa = '' WHERE gid = %lu AND rid = %lu",
|
||||
(unsigned long)gid, (unsigned long)rid);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
@@ -2154,6 +2149,16 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings)
|
||||
log_settings[log_category].log_to_file = atoi(row[3]);
|
||||
log_settings[log_category].log_to_gmsay = atoi(row[4]);
|
||||
|
||||
/* Determine if any output method is enabled for the category
|
||||
and set it to 1 so it can used to check if category is enabled */
|
||||
const bool log_to_console = log_settings[log_category].log_to_console > 0;
|
||||
const bool log_to_file = log_settings[log_category].log_to_file > 0;
|
||||
const bool log_to_gmsay = log_settings[log_category].log_to_gmsay > 0;
|
||||
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay;
|
||||
|
||||
if (is_category_enabled)
|
||||
log_settings[log_category].is_category_enabled = 1;
|
||||
|
||||
/*
|
||||
This determines whether or not the process needs to actually file log anything.
|
||||
If we go through this whole loop and nothing is set to any debug level, there is no point to create a file or keep anything open
|
||||
@@ -2162,4 +2167,52 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings)
|
||||
Log.file_logs_enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Database::ClearInvSnapshots(bool use_rule)
|
||||
{
|
||||
uint32 del_time = time(nullptr);
|
||||
if (use_rule) { del_time -= RuleI(Character, InvSnapshotHistoryD) * 86400; }
|
||||
|
||||
std::string query = StringFormat("DELETE FROM inventory_snapshots WHERE time_index <= %lu", (unsigned long)del_time);
|
||||
QueryDatabase(query);
|
||||
}
|
||||
|
||||
struct TimeOfDay_Struct Database::LoadTime(time_t &realtime)
|
||||
{
|
||||
|
||||
TimeOfDay_Struct eqTime;
|
||||
std::string query = StringFormat("SELECT minute,hour,day,month,year,realtime FROM eqtime limit 1");
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success() || results.RowCount() == 0){
|
||||
Log.Out(Logs::Detail, Logs::World_Server, "Loading EQ time of day failed. Using defaults.");
|
||||
eqTime.minute = 0;
|
||||
eqTime.hour = 9;
|
||||
eqTime.day = 1;
|
||||
eqTime.month = 1;
|
||||
eqTime.year = 3100;
|
||||
realtime = time(0);
|
||||
}
|
||||
else{
|
||||
auto row = results.begin();
|
||||
|
||||
eqTime.minute = atoi(row[0]);
|
||||
eqTime.hour = atoi(row[1]);
|
||||
eqTime.day = atoi(row[2]);
|
||||
eqTime.month = atoi(row[3]);
|
||||
eqTime.year = atoi(row[4]);
|
||||
realtime = atoi(row[5]);
|
||||
}
|
||||
|
||||
return eqTime;
|
||||
}
|
||||
|
||||
bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year)
|
||||
{
|
||||
std::string query = StringFormat("UPDATE eqtime set minute = %d, hour = %d, day = %d, month = %d, year = %d, realtime = %d limit 1", minute, hour, day, month, year, time(0));
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
return results.Success();
|
||||
|
||||
}
|
||||
|
||||
+5
-1
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "global_define.h"
|
||||
#include "eqemu_logsys.h"
|
||||
|
||||
#include "types.h"
|
||||
#include "dbcore.h"
|
||||
#include "linked_list.h"
|
||||
@@ -209,7 +210,6 @@ public:
|
||||
/* Database Conversions 'database_conversions.cpp' */
|
||||
|
||||
bool CheckDatabaseConversions();
|
||||
bool CheckDatabaseConvertBotsPostPPDeblob();
|
||||
bool CheckDatabaseConvertCorpseDeblob();
|
||||
bool CheckDatabaseConvertPPDeblob();
|
||||
|
||||
@@ -241,6 +241,8 @@ public:
|
||||
uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level);
|
||||
|
||||
void AddReport(std::string who, std::string against, std::string lines);
|
||||
struct TimeOfDay_Struct LoadTime(time_t &realtime);
|
||||
bool SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year);
|
||||
void ClearMerchantTemp();
|
||||
void ClearPTimers(uint32 charid);
|
||||
void SetFirstLogon(uint32 CharID, uint8 firstlogon);
|
||||
@@ -248,6 +250,8 @@ public:
|
||||
void SetLFP(uint32 CharID, bool LFP);
|
||||
void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon);
|
||||
|
||||
void ClearInvSnapshots(bool use_rule = true);
|
||||
|
||||
/* EQEmuLogSys */
|
||||
void LoadLogSettings(EQEmuLogSys::LogSettings* log_settings);
|
||||
|
||||
|
||||
+29
-176
@@ -157,18 +157,29 @@ namespace Convert {
|
||||
/*84*/ uint32 Points;
|
||||
/*88*/
|
||||
} PVPStatsEntry_Struct;
|
||||
|
||||
static const size_t BANDOLIERS_SIZE = 4;
|
||||
static const size_t BANDOLIER_ITEM_COUNT = 4;
|
||||
struct BandolierItem_Struct {
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
char item_name[64];
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
struct Bandolier_Struct {
|
||||
char name[32];
|
||||
Convert::BandolierItem_Struct items[EmuConstants::BANDOLIER_SIZE];
|
||||
char Name[32];
|
||||
Convert::BandolierItem_Struct Items[Convert::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
static const size_t POTION_BELT_ITEM_COUNT = 4;
|
||||
struct PotionBeltItem_Struct {
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
struct PotionBelt_Struct {
|
||||
Convert::BandolierItem_Struct items[EmuConstants::POTION_BELT_SIZE];
|
||||
Convert::PotionBeltItem_Struct Items[Convert::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct SuspendedMinion_Struct
|
||||
{
|
||||
/*000*/ uint16 SpellID;
|
||||
@@ -346,7 +357,7 @@ namespace Convert {
|
||||
/*12800*/ uint32 expAA;
|
||||
/*12804*/ uint32 aapoints; //avaliable, unspent
|
||||
/*12808*/ uint8 unknown12844[36];
|
||||
/*12844*/ Convert::Bandolier_Struct bandoliers[EmuConstants::BANDOLIERS_COUNT];
|
||||
/*12844*/ Convert::Bandolier_Struct bandoliers[Convert::BANDOLIERS_SIZE];
|
||||
/*14124*/ uint8 unknown14160[4506];
|
||||
/*18630*/ Convert::SuspendedMinion_Struct SuspendedMinion; // No longer in use
|
||||
/*19240*/ uint32 timeentitledonaccount;
|
||||
@@ -459,7 +470,6 @@ static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50)
|
||||
|
||||
bool Database::CheckDatabaseConversions() {
|
||||
CheckDatabaseConvertPPDeblob();
|
||||
CheckDatabaseConvertBotsPostPPDeblob();
|
||||
CheckDatabaseConvertCorpseDeblob();
|
||||
|
||||
/* Fetch Automatic Upgrade Script */
|
||||
@@ -483,7 +493,7 @@ bool Database::CheckDatabaseConversions() {
|
||||
/* Check for a new version of this script, the arg passed
|
||||
would have to be higher than the copy they have downloaded
|
||||
locally and they will re fetch */
|
||||
system("perl eqemu_update.pl V 2");
|
||||
system("perl eqemu_update.pl V 14");
|
||||
|
||||
/* Run Automatic Database Upgrade Script */
|
||||
system("perl eqemu_update.pl ran_from_world");
|
||||
@@ -1430,15 +1440,15 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
/* Run Bandolier Convert */
|
||||
first_entry = 0; rquery = "";
|
||||
for (i = 0; i < EmuConstants::BANDOLIERS_COUNT; i++){
|
||||
if (strlen(pp->bandoliers[i].name) < 32) {
|
||||
for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){
|
||||
if (pp->bandoliers[i].items[si].item_id > 0){
|
||||
for (i = 0; i < Convert::BANDOLIERS_SIZE; i++){
|
||||
if (strlen(pp->bandoliers[i].Name) < 32) {
|
||||
for (int si = 0; si < Convert::BANDOLIER_ITEM_COUNT; si++){
|
||||
if (pp->bandoliers[i].Items[si].ID > 0){
|
||||
if (first_entry != 1) {
|
||||
rquery = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name);
|
||||
rquery = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].Items[si].ID, pp->bandoliers[i].Items[si].Icon, pp->bandoliers[i].Name);
|
||||
first_entry = 1;
|
||||
}
|
||||
rquery = rquery + StringFormat(", (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name);
|
||||
rquery = rquery + StringFormat(", (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].Items[si].ID, pp->bandoliers[i].Items[si].Icon, pp->bandoliers[i].Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1446,13 +1456,13 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
/* Run Potion Belt Convert */
|
||||
first_entry = 0; rquery = "";
|
||||
for (i = 0; i < EmuConstants::POTION_BELT_SIZE; i++){
|
||||
if (pp->potionbelt.items[i].item_id > 0){
|
||||
for (i = 0; i < Convert::POTION_BELT_ITEM_COUNT; i++){
|
||||
if (pp->potionbelt.Items[i].ID > 0){
|
||||
if (first_entry != 1){
|
||||
rquery = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon);
|
||||
rquery = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%i, %u, %u, %u)", character_id, i, pp->potionbelt.Items[i].ID, pp->potionbelt.Items[i].Icon);
|
||||
first_entry = 1;
|
||||
}
|
||||
rquery = rquery + StringFormat(", (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon);
|
||||
rquery = rquery + StringFormat(", (%i, %u, %u, %u)", character_id, i, pp->potionbelt.Items[i].ID, pp->potionbelt.Items[i].Icon);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1480,163 +1490,6 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Database::CheckDatabaseConvertBotsPostPPDeblob(){
|
||||
#ifdef BOTS
|
||||
int runbotsconvert = 0;
|
||||
|
||||
/* Check For Legacy Bot References */
|
||||
std::string rquery = StringFormat("SHOW CREATE VIEW `vwBotCharacterMobs`");
|
||||
auto results = QueryDatabase(rquery);
|
||||
if (results.RowCount() == 1){
|
||||
auto row = results.begin();
|
||||
std::string table_check = row[1];
|
||||
|
||||
if (table_check.find("character_data") == -1){
|
||||
runbotsconvert = 1;
|
||||
printf("\n\n::: Legacy Bot Views and Function Detected... \n");
|
||||
printf("----------------------------------------------------------\n\n");
|
||||
printf(" Database currently has bot view/function linkage to obselete \n");
|
||||
printf(" table references and will now be converted...\n\n");
|
||||
printf(" It is recommended that you backup your database \n");
|
||||
printf(" before continuing the automatic conversion process...\n\n");
|
||||
printf("----------------------------------------------------------\n\n");
|
||||
std::cout << "Press ENTER to continue....." << std::endl << std::endl;
|
||||
std::cin.ignore(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (runbotsconvert == 1){
|
||||
printf("Running bot views/function database conversion... \n");
|
||||
|
||||
/* Update view `vwbotcharactermobs` */
|
||||
rquery = StringFormat("DROP VIEW `vwBotCharacterMobs`;");
|
||||
results = QueryDatabase(rquery);
|
||||
|
||||
rquery = StringFormat(
|
||||
"CREATE VIEW `vwBotCharacterMobs` AS\n"
|
||||
"SELECT _utf8'C' AS mobtype,\n" // Natedog: '_utf8'
|
||||
"c.`id`,\n"
|
||||
"c.`name`,\n"
|
||||
"c.`class`,\n"
|
||||
"c.`level`,\n"
|
||||
"c.`last_login`,\n"
|
||||
"c.`zone_id`\n"
|
||||
"FROM `character_data` AS c\n"
|
||||
"UNION ALL\n"
|
||||
"SELECT _utf8'B' AS mobtype,\n" // Natedog: '_utf8'
|
||||
"b.`BotID` AS id,\n"
|
||||
"b.`Name` AS name,\n"
|
||||
"b.`Class` AS class,\n"
|
||||
"b.`BotLevel` AS level,\n"
|
||||
"0 AS timelaston,\n"
|
||||
"0 AS zoneid\n"
|
||||
"FROM bots AS b;"
|
||||
);
|
||||
results = QueryDatabase(rquery);
|
||||
|
||||
|
||||
/* Update function `GetMobType` */
|
||||
rquery = StringFormat("DROP FUNCTION IF EXISTS `GetMobType`;");
|
||||
results = QueryDatabase(rquery);
|
||||
|
||||
rquery = StringFormat(
|
||||
"CREATE FUNCTION `GetMobType` (mobname VARCHAR(64)) RETURNS CHAR(1)\n"
|
||||
"BEGIN\n"
|
||||
" DECLARE Result CHAR(1);\n"
|
||||
"\n"
|
||||
" SET Result = NULL;\n"
|
||||
"\n"
|
||||
" IF (SELECT COUNT(*) FROM `character_data` WHERE `name` = mobname) > 0 THEN\n"
|
||||
" SET Result = 'C';\n"
|
||||
" ELSEIF (SELECT COUNT(*) FROM `bots` WHERE `Name` = mobname) > 0 THEN\n"
|
||||
" SET Result = 'B';\n"
|
||||
" END IF;\n "
|
||||
"\n"
|
||||
" RETURN Result;\n"
|
||||
"END"
|
||||
);
|
||||
results = QueryDatabase(rquery);
|
||||
|
||||
|
||||
/* Update view `vwgroups` */
|
||||
rquery = StringFormat("DROP VIEW IF EXISTS `vwGroups`;");
|
||||
results = QueryDatabase(rquery);
|
||||
|
||||
rquery = StringFormat(
|
||||
"CREATE VIEW `vwGroups` AS\n"
|
||||
"SELECT g.`groupid` AS groupid,\n"
|
||||
"GetMobType(g.`name`) AS mobtype,\n"
|
||||
"g.`name` AS name,\n"
|
||||
"g.`charid` AS mobid,\n"
|
||||
"IFNULL(c.`level`, b.`BotLevel`) AS level\n"
|
||||
"FROM `group_id` AS g\n"
|
||||
"LEFT JOIN `character_data` AS c ON g.`name` = c.`name`\n"
|
||||
"LEFT JOIN `bots` AS b ON g.`name` = b.`Name`;"
|
||||
);
|
||||
results = QueryDatabase(rquery);
|
||||
|
||||
|
||||
/* Update view `vwbotgroups` */
|
||||
rquery = StringFormat("DROP VIEW IF EXISTS `vwBotGroups`;");
|
||||
results = QueryDatabase(rquery);
|
||||
|
||||
rquery = StringFormat(
|
||||
"CREATE VIEW `vwBotGroups` AS\n"
|
||||
"SELECT g.`BotGroupId`,\n"
|
||||
"g.`BotGroupName`,\n"
|
||||
"g.`BotGroupLeaderBotId`,\n"
|
||||
"b.`Name` AS BotGroupLeaderName,\n"
|
||||
"b.`BotOwnerCharacterId`,\n"
|
||||
"c.`name` AS BotOwnerCharacterName\n"
|
||||
"FROM `botgroup` AS g\n"
|
||||
"JOIN `bots` AS b ON g.`BotGroupLeaderBotId` = b.`BotID`\n"
|
||||
"JOIN `character_data` AS c ON b.`BotOwnerCharacterID` = c.`id`\n"
|
||||
"ORDER BY b.`BotOwnerCharacterId`, g.`BotGroupName`;"
|
||||
);
|
||||
results = QueryDatabase(rquery);
|
||||
|
||||
|
||||
/* Update view `vwguildmembers` */
|
||||
rquery = StringFormat("DROP VIEW IF EXISTS `vwGuildMembers`;");
|
||||
results = QueryDatabase(rquery);
|
||||
|
||||
rquery = StringFormat(
|
||||
"CREATE VIEW `vwGuildMembers` AS\n"
|
||||
"SELECT 'C' AS mobtype,\n"
|
||||
"cm.`char_id`,\n"
|
||||
"cm.`guild_id`,\n"
|
||||
"cm.`rank`,\n"
|
||||
"cm.`tribute_enable`,\n"
|
||||
"cm.`total_tribute`,\n"
|
||||
"cm.`last_tribute`,\n"
|
||||
"cm.`banker`,\n"
|
||||
"cm.`public_note`,\n"
|
||||
"cm.`alt`\n"
|
||||
"FROM `guild_members` AS cm\n"
|
||||
"UNION ALL\n"
|
||||
"SELECT 'B' AS mobtype,\n"
|
||||
"bm.`char_id`,\n"
|
||||
"bm.`guild_id`,\n"
|
||||
"bm.`rank`,\n"
|
||||
"bm.`tribute_enable`,\n"
|
||||
"bm.`total_tribute`,\n"
|
||||
"bm.`last_tribute`,\n"
|
||||
"bm.`banker`,\n"
|
||||
"bm.`public_note`,\n"
|
||||
"bm.`alt`\n"
|
||||
"FROM `botguildmembers` AS bm;"
|
||||
);
|
||||
results = QueryDatabase(rquery);
|
||||
}
|
||||
|
||||
if (runbotsconvert == 1){
|
||||
printf("\n\nBot views/function conversion complete, continuing world bootup...\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Database::CheckDatabaseConvertCorpseDeblob(){
|
||||
Convert::DBPlayerCorpse_Struct_temp* dbpc;
|
||||
Convert::classic_db_temp::DBPlayerCorpse_Struct_temp* dbpc_c;
|
||||
|
||||
+10
-3
@@ -110,7 +110,8 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo
|
||||
|
||||
/* Implement Logging at the Root */
|
||||
if (mysql_errno(&mysql) > 0 && strlen(query) > 0){
|
||||
Log.Out(Logs::General, Logs::MySQLError, "%i: %s \n %s", mysql_errno(&mysql), mysql_error(&mysql), query);
|
||||
if (Log.log_settings[Logs::MySQLError].is_category_enabled == 1)
|
||||
Log.Out(Logs::General, Logs::MySQLError, "%i: %s \n %s", mysql_errno(&mysql), mysql_error(&mysql), query);
|
||||
}
|
||||
|
||||
return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql),errorBuffer);
|
||||
@@ -125,8 +126,14 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo
|
||||
rowCount = (uint32)mysql_num_rows(res);
|
||||
|
||||
MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), rowCount, (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql));
|
||||
|
||||
Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u rows returned)", query, rowCount, requestResult.RowCount());
|
||||
|
||||
if (Log.log_settings[Logs::MySQLQuery].is_category_enabled == 1)
|
||||
{
|
||||
if ((strncasecmp(query, "select", 6) == 0))
|
||||
Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u row%s returned)", query, requestResult.RowCount(), requestResult.RowCount() == 1 ? "" : "s");
|
||||
else
|
||||
Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u row%s affected)", query, requestResult.RowsAffected(), requestResult.RowsAffected() == 1 ? "" : "s");
|
||||
}
|
||||
|
||||
return requestResult;
|
||||
}
|
||||
|
||||
+7
-2
@@ -215,6 +215,7 @@ N(OP_GroupUpdate),
|
||||
N(OP_GroupUpdateB),
|
||||
N(OP_GroupUpdateLeaderAA),
|
||||
N(OP_GuildBank),
|
||||
N(OP_GuildBankItemList),
|
||||
N(OP_GuildCreate),
|
||||
N(OP_GuildDelete),
|
||||
N(OP_GuildDemote),
|
||||
@@ -348,6 +349,7 @@ N(OP_OpenTributeMaster),
|
||||
N(OP_PDeletePetition),
|
||||
N(OP_PetBuffWindow),
|
||||
N(OP_PetCommands),
|
||||
N(OP_PetHoTT),
|
||||
N(OP_Petition),
|
||||
N(OP_PetitionBug),
|
||||
N(OP_PetitionCheckIn),
|
||||
@@ -364,6 +366,8 @@ N(OP_PetitionUnCheckout),
|
||||
N(OP_PetitionUpdate),
|
||||
N(OP_PickPocket),
|
||||
N(OP_PlayerProfile),
|
||||
N(OP_PlayerStateAdd),
|
||||
N(OP_PlayerStateRemove),
|
||||
N(OP_PlayEverquestRequest),
|
||||
N(OP_PlayEverquestResponse),
|
||||
N(OP_PlayMP3),
|
||||
@@ -519,8 +523,6 @@ N(OP_VetRewardsAvaliable),
|
||||
N(OP_VoiceMacroIn),
|
||||
N(OP_VoiceMacroOut),
|
||||
N(OP_WeaponEquip1),
|
||||
N(OP_WeaponEquip2),
|
||||
N(OP_WeaponUnequip2),
|
||||
N(OP_WearChange),
|
||||
N(OP_Weather),
|
||||
N(OP_Weblink),
|
||||
@@ -534,6 +536,8 @@ N(OP_WorldLogout),
|
||||
N(OP_WorldObjectsSent),
|
||||
N(OP_WorldUnknown001),
|
||||
N(OP_XTargetAutoAddHaters),
|
||||
N(OP_XTargetOpen),
|
||||
N(OP_XTargetOpenResponse),
|
||||
N(OP_XTargetRequest),
|
||||
N(OP_XTargetResponse),
|
||||
N(OP_YellForHelp),
|
||||
@@ -547,4 +551,5 @@ N(OP_ZoneServerInfo),
|
||||
N(OP_ZoneServerReady),
|
||||
N(OP_ZoneSpawns),
|
||||
N(OP_ZoneUnavail),
|
||||
N(OP_ResetAA),
|
||||
// mail and chat opcodes located in ../mail_oplist.h
|
||||
|
||||
+48
-1
@@ -21,6 +21,53 @@
|
||||
#include "skills.h"
|
||||
#include "types.h"
|
||||
|
||||
/*
|
||||
** Light Types
|
||||
**
|
||||
*/
|
||||
enum LightTypes
|
||||
{
|
||||
lightTypeNone = 0,
|
||||
lightTypeCandle,
|
||||
lightTypeTorch,
|
||||
lightTypeTinyGlowingSkull,
|
||||
lightTypeSmallLantern,
|
||||
lightTypeSteinOfMoggok,
|
||||
lightTypeLargeLantern,
|
||||
lightTypeFlamelessLantern,
|
||||
lightTypeGlobeOfStars,
|
||||
lightTypeLightGlobe,
|
||||
lightTypeLightstone,
|
||||
lightTypeGreaterLightstone,
|
||||
lightTypeFireBeetleEye,
|
||||
lightTypeColdlight,
|
||||
lightTypeUnknown1,
|
||||
lightTypeUnknown2
|
||||
};
|
||||
|
||||
#define LIGHT_TYPES_COUNT 16
|
||||
|
||||
/*
|
||||
** Light Levels
|
||||
**
|
||||
*/
|
||||
enum LightLevels
|
||||
{
|
||||
lightLevelUnlit = 0,
|
||||
lightLevelCandle,
|
||||
lightLevelTorch,
|
||||
lightLevelSmallMagic,
|
||||
lightLevelRedLight,
|
||||
lightLevelBlueLight,
|
||||
lightLevelSmallLantern,
|
||||
lightLevelMagicLantern,
|
||||
lightLevelLargeLantern,
|
||||
lightLevelLargeMagic,
|
||||
lightLevelBrilliant
|
||||
};
|
||||
|
||||
#define LIGHT_LEVELS_COUNT 11
|
||||
|
||||
/*
|
||||
** Item attributes
|
||||
**
|
||||
@@ -55,7 +102,7 @@ enum ItemClassTypes
|
||||
**
|
||||
** (ref: database and eqstr_us.txt)
|
||||
**
|
||||
** (Looking at a recent database, it's possible that some of the item values may be off [10-27-2013] -U)
|
||||
** (Looking at a recent database, it's possible that some of the item values may be off [10-27-2013])
|
||||
*/
|
||||
enum ItemUseTypes : uint8
|
||||
{
|
||||
|
||||
+102
-115
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
EQEMu: Everquest Server Emulator
|
||||
|
||||
Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net)
|
||||
Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -25,8 +25,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// class EmuConstants
|
||||
//
|
||||
uint16 EmuConstants::InventoryMapSize(int16 indexMap) {
|
||||
switch (indexMap) {
|
||||
uint16 EmuConstants::InventoryMapSize(int16 indexMap)
|
||||
{
|
||||
switch (indexMap)
|
||||
{
|
||||
case MapPossessions:
|
||||
return MAP_POSSESSIONS_SIZE;
|
||||
case MapBank:
|
||||
@@ -83,7 +85,8 @@ uint16 EmuConstants::InventoryMapSize(int16 indexMap) {
|
||||
}
|
||||
|
||||
/*
|
||||
std::string EmuConstants::InventoryLocationName(Location_Struct location) {
|
||||
std::string EmuConstants::InventoryLocationName(Location_Struct location)
|
||||
{
|
||||
// not ready for implementation...
|
||||
std::string ret_str;
|
||||
StringFormat(ret_str, "%s, %s, %s, %s", InventoryMapName(location.map), InventoryMainName(location.main), InventorySubName(location.sub), InventoryAugName(location.aug));
|
||||
@@ -91,8 +94,10 @@ std::string EmuConstants::InventoryLocationName(Location_Struct location) {
|
||||
}
|
||||
*/
|
||||
|
||||
std::string EmuConstants::InventoryMapName(int16 indexMap) {
|
||||
switch (indexMap) {
|
||||
std::string EmuConstants::InventoryMapName(int16 indexMap)
|
||||
{
|
||||
switch (indexMap)
|
||||
{
|
||||
case INVALID_INDEX:
|
||||
return "Invalid Map";
|
||||
case MapPossessions:
|
||||
@@ -100,7 +105,7 @@ std::string EmuConstants::InventoryMapName(int16 indexMap) {
|
||||
case MapBank:
|
||||
return "Bank";
|
||||
case MapSharedBank:
|
||||
return "Shared Bank";
|
||||
return "SharedBank";
|
||||
case MapTrade:
|
||||
return "Trade";
|
||||
case MapWorld:
|
||||
@@ -110,9 +115,9 @@ std::string EmuConstants::InventoryMapName(int16 indexMap) {
|
||||
case MapTribute:
|
||||
return "Tribute";
|
||||
case MapTrophyTribute:
|
||||
return "Trophy Tribute";
|
||||
return "TrophyTribute";
|
||||
case MapGuildTribute:
|
||||
return "Guild Tribute";
|
||||
return "GuildTribute";
|
||||
case MapMerchant:
|
||||
return "Merchant";
|
||||
case MapDeleted:
|
||||
@@ -124,23 +129,23 @@ std::string EmuConstants::InventoryMapName(int16 indexMap) {
|
||||
case MapInspect:
|
||||
return "Inspect";
|
||||
case MapRealEstate:
|
||||
return "Real Estate";
|
||||
return "RealEstate";
|
||||
case MapViewMODPC:
|
||||
return "View MOD PC";
|
||||
return "ViewMODPC";
|
||||
case MapViewMODBank:
|
||||
return "View MOD Bank";
|
||||
return "ViewMODBank";
|
||||
case MapViewMODSharedBank:
|
||||
return "View MOD Shared Bank";
|
||||
return "ViewMODSharedBank";
|
||||
case MapViewMODLimbo:
|
||||
return "View MOD Limbo";
|
||||
return "ViewMODLimbo";
|
||||
case MapAltStorage:
|
||||
return "Alt Storage";
|
||||
return "AltStorage";
|
||||
case MapArchived:
|
||||
return "Archived";
|
||||
case MapMail:
|
||||
return "Mail";
|
||||
case MapGuildTrophyTribute:
|
||||
return "Guild Trophy Tribute";
|
||||
return "GuildTrophyTribute";
|
||||
case MapKrono:
|
||||
return "Krono";
|
||||
case MapOther:
|
||||
@@ -150,20 +155,22 @@ std::string EmuConstants::InventoryMapName(int16 indexMap) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string EmuConstants::InventoryMainName(int16 indexMain) {
|
||||
switch (indexMain) {
|
||||
std::string EmuConstants::InventoryMainName(int16 indexMain)
|
||||
{
|
||||
switch (indexMain)
|
||||
{
|
||||
case INVALID_INDEX:
|
||||
return "Invalid Main";
|
||||
case MainCharm:
|
||||
return "Charm";
|
||||
case MainEar1:
|
||||
return "Ear 1";
|
||||
return "Ear1";
|
||||
case MainHead:
|
||||
return "Head";
|
||||
case MainFace:
|
||||
return "Face";
|
||||
case MainEar2:
|
||||
return "Ear 2";
|
||||
return "Ear2";
|
||||
case MainNeck:
|
||||
return "Neck";
|
||||
case MainShoulders:
|
||||
@@ -173,9 +180,9 @@ std::string EmuConstants::InventoryMainName(int16 indexMain) {
|
||||
case MainBack:
|
||||
return "Back";
|
||||
case MainWrist1:
|
||||
return "Wrist 1";
|
||||
return "Wrist1";
|
||||
case MainWrist2:
|
||||
return "Wrist 2";
|
||||
return "Wrist2";
|
||||
case MainRange:
|
||||
return "Range";
|
||||
case MainHands:
|
||||
@@ -185,9 +192,9 @@ std::string EmuConstants::InventoryMainName(int16 indexMain) {
|
||||
case MainSecondary:
|
||||
return "Secondary";
|
||||
case MainFinger1:
|
||||
return "Finger 1";
|
||||
return "Finger1";
|
||||
case MainFinger2:
|
||||
return "Finger 2";
|
||||
return "Finger2";
|
||||
case MainChest:
|
||||
return "Chest";
|
||||
case MainLegs:
|
||||
@@ -197,30 +204,30 @@ std::string EmuConstants::InventoryMainName(int16 indexMain) {
|
||||
case MainWaist:
|
||||
return "Waist";
|
||||
case MainPowerSource:
|
||||
return "Power Source";
|
||||
return "PowerSource";
|
||||
case MainAmmo:
|
||||
return "Ammo";
|
||||
case MainGeneral1:
|
||||
return "General 1";
|
||||
return "General1";
|
||||
case MainGeneral2:
|
||||
return "General 2";
|
||||
return "General2";
|
||||
case MainGeneral3:
|
||||
return "General 3";
|
||||
return "General3";
|
||||
case MainGeneral4:
|
||||
return "General 4";
|
||||
return "General4";
|
||||
case MainGeneral5:
|
||||
return "General 5";
|
||||
return "General5";
|
||||
case MainGeneral6:
|
||||
return "General 6";
|
||||
return "General6";
|
||||
case MainGeneral7:
|
||||
return "General 7";
|
||||
return "General7";
|
||||
case MainGeneral8:
|
||||
return "General 8";
|
||||
return "General8";
|
||||
/*
|
||||
case MainGeneral9:
|
||||
return "General 9";
|
||||
return "General9";
|
||||
case MainGeneral10:
|
||||
return "General 10";
|
||||
return "General10";
|
||||
*/
|
||||
case MainCursor:
|
||||
return "Cursor";
|
||||
@@ -229,7 +236,8 @@ std::string EmuConstants::InventoryMainName(int16 indexMain) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string EmuConstants::InventorySubName(int16 indexSub) {
|
||||
std::string EmuConstants::InventorySubName(int16 indexSub)
|
||||
{
|
||||
if (indexSub == INVALID_INDEX)
|
||||
return "Invalid Sub";
|
||||
|
||||
@@ -237,12 +245,13 @@ std::string EmuConstants::InventorySubName(int16 indexSub) {
|
||||
return "Unknown Sub";
|
||||
|
||||
std::string ret_str;
|
||||
ret_str = StringFormat("Container %i", (indexSub + 1)); // zero-based index..but, count starts at one
|
||||
ret_str = StringFormat("Container%i", (indexSub + 1)); // zero-based index..but, count starts at one
|
||||
|
||||
return ret_str;
|
||||
}
|
||||
|
||||
std::string EmuConstants::InventoryAugName(int16 indexAug) {
|
||||
std::string EmuConstants::InventoryAugName(int16 indexAug)
|
||||
{
|
||||
if (indexAug == INVALID_INDEX)
|
||||
return "Invalid Aug";
|
||||
|
||||
@@ -250,7 +259,7 @@ std::string EmuConstants::InventoryAugName(int16 indexAug) {
|
||||
return "Unknown Aug";
|
||||
|
||||
std::string ret_str;
|
||||
ret_str = StringFormat("Augment %i", (indexAug + 1)); // zero-based index..but, count starts at one
|
||||
ret_str = StringFormat("Augment%i", (indexAug + 1)); // zero-based index..but, count starts at one
|
||||
|
||||
return ret_str;
|
||||
}
|
||||
@@ -260,14 +269,16 @@ std::string EmuConstants::InventoryAugName(int16 indexAug) {
|
||||
// class EQLimits
|
||||
//
|
||||
// client validation
|
||||
bool EQLimits::IsValidPCClientVersion(ClientVersion clientVersion) {
|
||||
bool EQLimits::IsValidPCClientVersion(ClientVersion clientVersion)
|
||||
{
|
||||
if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ClientVersion EQLimits::ValidatePCClientVersion(ClientVersion clientVersion) {
|
||||
ClientVersion EQLimits::ValidatePCClientVersion(ClientVersion clientVersion)
|
||||
{
|
||||
if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT)
|
||||
return clientVersion;
|
||||
|
||||
@@ -275,14 +286,16 @@ ClientVersion EQLimits::ValidatePCClientVersion(ClientVersion clientVersion) {
|
||||
}
|
||||
|
||||
// npc validation
|
||||
bool EQLimits::IsValidNPCClientVersion(ClientVersion clientVersion) {
|
||||
bool EQLimits::IsValidNPCClientVersion(ClientVersion clientVersion)
|
||||
{
|
||||
if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ClientVersion EQLimits::ValidateNPCClientVersion(ClientVersion clientVersion) {
|
||||
ClientVersion EQLimits::ValidateNPCClientVersion(ClientVersion clientVersion)
|
||||
{
|
||||
if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT)
|
||||
return clientVersion;
|
||||
|
||||
@@ -290,22 +303,47 @@ ClientVersion EQLimits::ValidateNPCClientVersion(ClientVersion clientVersion) {
|
||||
}
|
||||
|
||||
// mob validation
|
||||
bool EQLimits::IsValidMobClientVersion(ClientVersion clientVersion) {
|
||||
bool EQLimits::IsValidMobClientVersion(ClientVersion clientVersion)
|
||||
{
|
||||
if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_NPC_CLIENT)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ClientVersion EQLimits::ValidateMobClientVersion(ClientVersion clientVersion) {
|
||||
ClientVersion EQLimits::ValidateMobClientVersion(ClientVersion clientVersion)
|
||||
{
|
||||
if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_NPC_CLIENT)
|
||||
return clientVersion;
|
||||
|
||||
return ClientVersion::Unknown;
|
||||
}
|
||||
|
||||
// database
|
||||
size_t EQLimits::CharacterCreationLimit(ClientVersion clientVersion)
|
||||
{
|
||||
static const size_t local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*Client62*/ NOT_USED,
|
||||
/*Titanium*/ Titanium::consts::CHARACTER_CREATION_LIMIT,
|
||||
/*SoF*/ SoF::consts::CHARACTER_CREATION_LIMIT,
|
||||
/*SoD*/ SoD::consts::CHARACTER_CREATION_LIMIT,
|
||||
/*UF*/ UF::consts::CHARACTER_CREATION_LIMIT,
|
||||
/*RoF*/ RoF::consts::CHARACTER_CREATION_LIMIT,
|
||||
/*RoF2*/ RoF2::consts::CHARACTER_CREATION_LIMIT,
|
||||
|
||||
/*MobNPC*/ NOT_USED,
|
||||
/*MobMerc*/ NOT_USED,
|
||||
/*MobBot*/ NOT_USED,
|
||||
/*MobPet*/ NOT_USED
|
||||
};
|
||||
|
||||
return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
// inventory
|
||||
uint16 EQLimits::InventoryMapSize(int16 indexMap, ClientVersion clientVersion) {
|
||||
uint16 EQLimits::InventoryMapSize(int16 indexMap, ClientVersion clientVersion)
|
||||
{
|
||||
// not all maps will have an instantiated container..some are references for queue generators (i.e., bazaar, mail, etc...)
|
||||
// a zero '0' indicates a needed value..otherwise, change to '_NOTUSED' for a null value so indices requiring research can be identified
|
||||
// ALL of these values need to be verified before pushing to live
|
||||
@@ -704,7 +742,8 @@ uint16 EQLimits::InventoryMapSize(int16 indexMap, ClientVersion clientVersion) {
|
||||
return NOT_USED;
|
||||
}
|
||||
|
||||
uint64 EQLimits::PossessionsBitmask(ClientVersion clientVersion) {
|
||||
uint64 EQLimits::PossessionsBitmask(ClientVersion clientVersion)
|
||||
{
|
||||
// these are for the new inventory system (RoF)..not the current (Ti) one...
|
||||
// 0x0000000000200000 is SlotPowerSource (SoF+)
|
||||
// 0x0000000080000000 is SlotGeneral9 (RoF+)
|
||||
@@ -730,7 +769,8 @@ uint64 EQLimits::PossessionsBitmask(ClientVersion clientVersion) {
|
||||
//return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
uint64 EQLimits::EquipmentBitmask(ClientVersion clientVersion) {
|
||||
uint64 EQLimits::EquipmentBitmask(ClientVersion clientVersion)
|
||||
{
|
||||
static const uint64 local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*62*/ 0x00000000005FFFFF,
|
||||
@@ -751,7 +791,8 @@ uint64 EQLimits::EquipmentBitmask(ClientVersion clientVersion) {
|
||||
//return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
uint64 EQLimits::GeneralBitmask(ClientVersion clientVersion) {
|
||||
uint64 EQLimits::GeneralBitmask(ClientVersion clientVersion)
|
||||
{
|
||||
static const uint64 local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*62*/ 0x000000007F800000,
|
||||
@@ -772,7 +813,8 @@ uint64 EQLimits::GeneralBitmask(ClientVersion clientVersion) {
|
||||
//return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
uint64 EQLimits::CursorBitmask(ClientVersion clientVersion) {
|
||||
uint64 EQLimits::CursorBitmask(ClientVersion clientVersion)
|
||||
{
|
||||
static const uint64 local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*62*/ 0x0000000200000000,
|
||||
@@ -793,7 +835,8 @@ uint64 EQLimits::CursorBitmask(ClientVersion clientVersion) {
|
||||
//return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
bool EQLimits::AllowsEmptyBagInBag(ClientVersion clientVersion) {
|
||||
bool EQLimits::AllowsEmptyBagInBag(ClientVersion clientVersion)
|
||||
{
|
||||
static const bool local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ false,
|
||||
/*62*/ false,
|
||||
@@ -814,7 +857,8 @@ bool EQLimits::AllowsEmptyBagInBag(ClientVersion clientVersion) {
|
||||
//return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
bool EQLimits::AllowsClickCastFromBag(ClientVersion clientVersion) {
|
||||
bool EQLimits::AllowsClickCastFromBag(ClientVersion clientVersion)
|
||||
{
|
||||
static const bool local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ false,
|
||||
/*62*/ false,
|
||||
@@ -835,7 +879,8 @@ bool EQLimits::AllowsClickCastFromBag(ClientVersion clientVersion) {
|
||||
}
|
||||
|
||||
// items
|
||||
uint16 EQLimits::ItemCommonSize(ClientVersion clientVersion) {
|
||||
uint16 EQLimits::ItemCommonSize(ClientVersion clientVersion)
|
||||
{
|
||||
static const uint16 local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*62*/ EmuConstants::ITEM_COMMON_SIZE,
|
||||
@@ -855,7 +900,8 @@ uint16 EQLimits::ItemCommonSize(ClientVersion clientVersion) {
|
||||
return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
uint16 EQLimits::ItemContainerSize(ClientVersion clientVersion) {
|
||||
uint16 EQLimits::ItemContainerSize(ClientVersion clientVersion)
|
||||
{
|
||||
static const uint16 local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*62*/ EmuConstants::ITEM_CONTAINER_SIZE,
|
||||
@@ -875,7 +921,8 @@ uint16 EQLimits::ItemContainerSize(ClientVersion clientVersion) {
|
||||
return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
bool EQLimits::CoinHasWeight(ClientVersion clientVersion) {
|
||||
bool EQLimits::CoinHasWeight(ClientVersion clientVersion)
|
||||
{
|
||||
static const bool local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ true,
|
||||
/*62*/ true,
|
||||
@@ -894,63 +941,3 @@ bool EQLimits::CoinHasWeight(ClientVersion clientVersion) {
|
||||
|
||||
return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
uint32 EQLimits::BandoliersCount(ClientVersion clientVersion) {
|
||||
static const uint32 local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*62*/ EmuConstants::BANDOLIERS_COUNT,
|
||||
/*Titanium*/ EmuConstants::BANDOLIERS_COUNT,
|
||||
/*SoF*/ EmuConstants::BANDOLIERS_COUNT,
|
||||
/*SoD*/ EmuConstants::BANDOLIERS_COUNT,
|
||||
/*Underfoot*/ EmuConstants::BANDOLIERS_COUNT,
|
||||
/*RoF*/ EmuConstants::BANDOLIERS_COUNT,
|
||||
/*RoF2*/ EmuConstants::BANDOLIERS_COUNT,
|
||||
|
||||
/*NPC*/ NOT_USED,
|
||||
/*Merc*/ NOT_USED,
|
||||
/*Bot*/ NOT_USED,
|
||||
/*Pet*/ NOT_USED
|
||||
};
|
||||
|
||||
return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
uint32 EQLimits::BandolierSize(ClientVersion clientVersion) {
|
||||
static const uint32 local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*62*/ EmuConstants::BANDOLIER_SIZE,
|
||||
/*Titanium*/ EmuConstants::BANDOLIER_SIZE,
|
||||
/*SoF*/ EmuConstants::BANDOLIER_SIZE,
|
||||
/*SoD*/ EmuConstants::BANDOLIER_SIZE,
|
||||
/*Underfoot*/ EmuConstants::BANDOLIER_SIZE,
|
||||
/*RoF*/ EmuConstants::BANDOLIER_SIZE,
|
||||
/*RoF2*/ EmuConstants::BANDOLIER_SIZE,
|
||||
|
||||
/*NPC*/ NOT_USED,
|
||||
/*Merc*/ NOT_USED,
|
||||
/*Bot*/ NOT_USED,
|
||||
/*Pet*/ NOT_USED
|
||||
};
|
||||
|
||||
return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
uint32 EQLimits::PotionBeltSize(ClientVersion clientVersion) {
|
||||
static const uint32 local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*62*/ EmuConstants::POTION_BELT_SIZE,
|
||||
/*Titanium*/ EmuConstants::POTION_BELT_SIZE,
|
||||
/*SoF*/ EmuConstants::POTION_BELT_SIZE,
|
||||
/*SoD*/ EmuConstants::POTION_BELT_SIZE,
|
||||
/*Underfoot*/ EmuConstants::POTION_BELT_SIZE,
|
||||
/*RoF*/ EmuConstants::POTION_BELT_SIZE,
|
||||
/*RoF2*/ EmuConstants::POTION_BELT_SIZE,
|
||||
|
||||
/*NPC*/ NOT_USED,
|
||||
/*Merc*/ NOT_USED,
|
||||
/*Bot*/ NOT_USED,
|
||||
/*Pet*/ NOT_USED
|
||||
};
|
||||
|
||||
return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
+16
-20
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
EQEMu: Everquest Server Emulator
|
||||
|
||||
Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net)
|
||||
Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -42,12 +42,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//using namespace RoF2::maps; // server inventory maps enumeration (code and database sync'd to reference)
|
||||
//using namespace RoF::slots; // server possessions slots enumeration (code and database sync'd to reference)
|
||||
|
||||
class EmuConstants {
|
||||
class EmuConstants
|
||||
{
|
||||
// an immutable value is required to initialize arrays, etc... use this class as a repository for those
|
||||
public:
|
||||
// database
|
||||
static const ClientVersion CHARACTER_CREATION_CLIENT = ClientVersion::RoF2; // adjust according to starting item placement and target client
|
||||
|
||||
static const size_t CHARACTER_CREATION_LIMIT = RoF2::consts::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
// inventory
|
||||
static uint16 InventoryMapSize(int16 indexMap);
|
||||
//static std::string InventoryLocationName(Location_Struct location);
|
||||
@@ -140,23 +143,18 @@ public:
|
||||
static const uint16 ITEM_COMMON_SIZE = RoF::consts::ITEM_COMMON_SIZE;
|
||||
static const uint16 ITEM_CONTAINER_SIZE = Titanium::consts::ITEM_CONTAINER_SIZE;
|
||||
|
||||
// player profile
|
||||
//static const uint32 CLASS_BITMASK = 0; // needs value
|
||||
//static const uint32 RACE_BITMASK = 0; // needs value
|
||||
// BANDOLIERS_SIZE sets maximum limit..active limit will need to be handled by the appropriate AA or spell (or item?)
|
||||
static const size_t BANDOLIERS_SIZE = RoF2::consts::BANDOLIERS_SIZE; // number of bandolier instances
|
||||
static const size_t BANDOLIER_ITEM_COUNT = RoF2::consts::BANDOLIER_ITEM_COUNT; // number of equipment slots in bandolier instance
|
||||
|
||||
// BANDOLIERS_COUNT sets maximum limit..active limit will need to be handled by the appropriate AA
|
||||
static const uint32 BANDOLIERS_COUNT = Titanium::consts::BANDOLIERS_COUNT; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = Titanium::consts::BANDOLIER_SIZE; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = Titanium::consts::POTION_BELT_SIZE;
|
||||
// POTION_BELT_SIZE sets maximum limit..active limit will need to be handled by the appropriate AA or spell (or item?)
|
||||
static const size_t POTION_BELT_ITEM_COUNT = RoF2::consts::POTION_BELT_ITEM_COUNT;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 56;
|
||||
|
||||
// legacy-related functions
|
||||
//static int ServerToPerlSlot(int slot); // encode
|
||||
//static int PerlToServerSlot(int slot); // decode
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = RoF2::consts::TEXT_LINK_BODY_LENGTH;
|
||||
};
|
||||
|
||||
class EQLimits {
|
||||
class EQLimits
|
||||
{
|
||||
// values should default to a non-beneficial value..unless value conflicts with intended operation
|
||||
//
|
||||
// EmuConstants may be used as references..but, not every reference needs to be in EmuConstants (i.e., AllowsEmptyBagInBag(), CoinHasWeight(), etc...)
|
||||
@@ -174,6 +172,9 @@ public:
|
||||
static bool IsValidMobClientVersion(ClientVersion clientVersion);
|
||||
static ClientVersion ValidateMobClientVersion(ClientVersion clientVersion);
|
||||
|
||||
// database
|
||||
static size_t CharacterCreationLimit(ClientVersion clientVersion);
|
||||
|
||||
// inventory
|
||||
static uint16 InventoryMapSize(int16 indexMap, ClientVersion clientVersion);
|
||||
static uint64 PossessionsBitmask(ClientVersion clientVersion);
|
||||
@@ -190,11 +191,6 @@ public:
|
||||
|
||||
// player profile
|
||||
static bool CoinHasWeight(ClientVersion clientVersion);
|
||||
|
||||
static uint32 BandoliersCount(ClientVersion clientVersion);
|
||||
static uint32 BandolierSize(ClientVersion clientVersion);
|
||||
|
||||
static uint32 PotionBeltSize(ClientVersion clientVersion);
|
||||
};
|
||||
|
||||
#endif /* EQ_DICTIONARY_H */
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "platform.h"
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef STATIC_OPCODE
|
||||
@@ -510,3 +511,8 @@ void DumpPacket(const EQApplicationPacket* app, bool iShowInfo) {
|
||||
// DumpPacketAscii(app->pBuffer, app->size);
|
||||
}
|
||||
|
||||
std::string DumpPacketToString(const EQApplicationPacket* app){
|
||||
std::ostringstream out;
|
||||
out << DumpPacketHexToString(app->pBuffer, app->size);
|
||||
return out.str();
|
||||
}
|
||||
+2
-1
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "base_packet.h"
|
||||
#include "platform.h"
|
||||
#include <iostream>
|
||||
|
||||
#ifdef STATIC_OPCODE
|
||||
typedef unsigned short EmuOpcode;
|
||||
@@ -146,6 +147,6 @@ protected:
|
||||
};
|
||||
|
||||
extern void DumpPacket(const EQApplicationPacket* app, bool iShowInfo = false);
|
||||
|
||||
extern std::string DumpPacketToString(const EQApplicationPacket* app);
|
||||
|
||||
#endif
|
||||
|
||||
+249
-175
@@ -15,6 +15,7 @@
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef EQ_PACKET_STRUCTS_H
|
||||
#define EQ_PACKET_STRUCTS_H
|
||||
|
||||
@@ -123,83 +124,81 @@ struct LDoNTrapTemplate
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/*
|
||||
** Color_Struct
|
||||
** Size: 4 bytes
|
||||
** Used for convenience
|
||||
** Merth: Gave struct a name so gcc 2.96 would compile
|
||||
**
|
||||
*/
|
||||
// All clients translate the character select information to some degree
|
||||
|
||||
struct Color_Struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 blue;
|
||||
uint8 green;
|
||||
uint8 red;
|
||||
uint8 use_tint; // if there's a tint this is FF
|
||||
} rgb;
|
||||
uint32 color;
|
||||
union {
|
||||
struct {
|
||||
uint8 Blue;
|
||||
uint8 Green;
|
||||
uint8 Red;
|
||||
uint8 UseTint; // if there's a tint this is FF
|
||||
} RGB;
|
||||
uint32 Color;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Visible equiptment.
|
||||
* Size: 20 Octets
|
||||
*/
|
||||
struct EquipStruct {
|
||||
/*00*/ uint32 material;
|
||||
/*04*/ uint32 unknown1;
|
||||
/*08*/ uint32 elitematerial;
|
||||
/*12*/ uint32 heroforgemodel;
|
||||
/*16*/ uint32 material2; // Same as material?
|
||||
/*20*/
|
||||
struct EquipStruct
|
||||
{
|
||||
uint32 Material;
|
||||
uint32 Unknown1;
|
||||
uint32 EliteMaterial;
|
||||
uint32 HeroForgeModel;
|
||||
uint32 Material2; // Same as material?
|
||||
};
|
||||
|
||||
struct CharSelectEquip {
|
||||
uint32 material;
|
||||
uint32 unknown1;
|
||||
uint32 elitematerial;
|
||||
uint32 heroforgemodel;
|
||||
uint32 material2;
|
||||
Color_Struct color;
|
||||
struct CharSelectEquip
|
||||
{
|
||||
uint32 Material;
|
||||
uint32 Unknown1;
|
||||
uint32 EliteMaterial;
|
||||
uint32 HeroForgeModel;
|
||||
uint32 Material2;
|
||||
Color_Struct Color;
|
||||
};
|
||||
|
||||
/*
|
||||
** Character Selection Struct
|
||||
** Length: 1704 Bytes
|
||||
**
|
||||
*/
|
||||
struct CharacterSelect_Struct {
|
||||
/*0000*/ uint32 race[10]; // Characters Race
|
||||
/*0040*/ //Color_Struct cs_colors[10][9]; // Characters Equipment Colors
|
||||
/*0400*/ uint8 beardcolor[10]; // Characters beard Color
|
||||
/*0410*/ uint8 hairstyle[10]; // Characters hair style
|
||||
/*0420*/ //uint32 equip[10][9]; // 0=helm, 1=chest, 2=arm, 3=bracer, 4=hand, 5=leg, 6=boot, 7=melee1, 8=melee2 (Might not be)
|
||||
/*0000*/ CharSelectEquip equip[10][9];
|
||||
/*0780*/ uint32 secondary[10]; // Characters secondary IDFile number
|
||||
/*0820*/ uint32 drakkin_heritage[10]; // added for SoF
|
||||
/*0860*/ uint32 drakkin_tattoo[10]; // added for SoF
|
||||
/*0900*/ uint32 drakkin_details[10]; // added for SoF
|
||||
/*0940*/ uint32 deity[10]; // Characters Deity
|
||||
/*0980*/ uint8 gohome[10]; // 1=Go Home available, 0=not
|
||||
/*0990*/ uint8 tutorial[10]; // 1=Tutorial available, 0=not
|
||||
/*1000*/ uint8 beard[10]; // Characters Beard Type
|
||||
/*1010*/ uint8 unknown902[10]; // 10x ff
|
||||
/*1020*/ uint32 primary[10]; // Characters primary IDFile number
|
||||
/*1060*/ uint8 haircolor[10]; // Characters Hair Color
|
||||
/*1070*/ uint8 unknown0962[2]; // 2x 00
|
||||
/*1072*/ uint32 zone[10]; // Characters Current Zone
|
||||
/*1112*/ uint8 class_[10]; // Characters Classes
|
||||
/*1022*/ uint8 face[10]; // Characters Face Type
|
||||
/*1032*/ char name[10][64]; // Characters Names
|
||||
/*1672*/ uint8 gender[10]; // Characters Gender
|
||||
/*1682*/ uint8 eyecolor1[10]; // Characters Eye Color
|
||||
/*1692*/ uint8 eyecolor2[10]; // Characters Eye 2 Color
|
||||
/*1702*/ uint8 level[10]; // Characters Levels
|
||||
/*1712*/
|
||||
// RoF2-based hybrid struct
|
||||
struct CharacterSelectEntry_Struct
|
||||
{
|
||||
char Name[64];
|
||||
uint8 Class;
|
||||
uint32 Race;
|
||||
uint8 Level;
|
||||
uint8 ShroudClass;
|
||||
uint32 ShroudRace;
|
||||
uint16 Zone;
|
||||
uint16 Instance;
|
||||
uint8 Gender;
|
||||
uint8 Face;
|
||||
CharSelectEquip Equip[9];
|
||||
uint8 Unknown15; // Seen FF
|
||||
uint8 Unknown19; // Seen FF
|
||||
uint32 DrakkinTattoo;
|
||||
uint32 DrakkinDetails;
|
||||
uint32 Deity;
|
||||
uint32 PrimaryIDFile;
|
||||
uint32 SecondaryIDFile;
|
||||
uint8 HairColor;
|
||||
uint8 BeardColor;
|
||||
uint8 EyeColor1;
|
||||
uint8 EyeColor2;
|
||||
uint8 HairStyle;
|
||||
uint8 Beard;
|
||||
uint8 GoHome; // Seen 0 for new char and 1 for existing
|
||||
uint8 Tutorial; // Seen 1 for new char or 0 for existing
|
||||
uint32 DrakkinHeritage;
|
||||
uint8 Unknown1; // Seen 0
|
||||
uint8 Enabled; // Originally labeled as 'CharEnabled' - unknown purpose and setting
|
||||
uint32 LastLogin;
|
||||
uint8 Unknown2; // Seen 0
|
||||
};
|
||||
|
||||
struct CharacterSelect_Struct
|
||||
{
|
||||
uint32 CharCount; //number of chars in this packet
|
||||
uint32 TotalChars; //total number of chars allowed?
|
||||
CharacterSelectEntry_Struct Entries[0];
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -274,7 +273,8 @@ struct Spawn_Struct {
|
||||
/*0146*/ uint8 beard; // Beard style (not totally, sure but maybe!)
|
||||
/*0147*/ uint8 unknown0147[4];
|
||||
/*0151*/ uint8 level; // Spawn Level
|
||||
/*0152*/ uint8 unknown0259[4]; // ***Placeholder
|
||||
// None = 0, Open = 1, WeaponSheathed = 2, Aggressive = 4, ForcedAggressive = 8, InstrumentEquipped = 16, Stunned = 32, PrimaryWeaponEquipped = 64, SecondaryWeaponEquipped = 128
|
||||
/*0152*/ uint32 PlayerState; // Controls animation stuff
|
||||
/*0156*/ uint8 beardcolor; // Beard color
|
||||
/*0157*/ char suffix[32]; // Player's suffix (of Veeshan, etc.)
|
||||
/*0189*/ uint32 petOwnerId; // If this is a pet, the spawn id of owner
|
||||
@@ -367,6 +367,11 @@ union
|
||||
|
||||
};
|
||||
|
||||
struct PlayerState_Struct {
|
||||
/*00*/ uint32 spawn_id;
|
||||
/*04*/ uint32 state;
|
||||
};
|
||||
|
||||
/*
|
||||
** New Spawn
|
||||
** Length: 176 Bytes
|
||||
@@ -548,7 +553,7 @@ struct SpellBuff_Struct
|
||||
/*002*/ uint8 bard_modifier;
|
||||
/*003*/ uint8 effect; //not real
|
||||
/*004*/ uint32 spellid;
|
||||
/*008*/ uint32 duration;
|
||||
/*008*/ int32 duration;
|
||||
/*012*/ uint32 counters;
|
||||
/*016*/ uint32 player_id; //'global' ID of the caster, for wearoff messages
|
||||
/*020*/
|
||||
@@ -561,7 +566,7 @@ struct SpellBuffFade_Struct {
|
||||
/*006*/ uint8 effect;
|
||||
/*007*/ uint8 unknown7;
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 num_hits;
|
||||
/*020*/ uint32 unknown020; //prolly global player ID
|
||||
/*024*/ uint32 slotid;
|
||||
@@ -579,14 +584,8 @@ struct BuffRemoveRequest_Struct
|
||||
|
||||
struct PetBuff_Struct {
|
||||
/*000*/ uint32 petid;
|
||||
/*004*/ uint32 spellid[BUFF_COUNT];
|
||||
/*104*/ uint32 unknown700;
|
||||
/*108*/ uint32 unknown701;
|
||||
/*112*/ uint32 unknown702;
|
||||
/*116*/ uint32 unknown703;
|
||||
/*120*/ uint32 unknown704;
|
||||
/*124*/ uint32 ticsremaining[BUFF_COUNT];
|
||||
/*224*/ uchar unknown705[20];
|
||||
/*004*/ uint32 spellid[BUFF_COUNT+5];
|
||||
/*124*/ int32 ticsremaining[BUFF_COUNT+5];
|
||||
/*244*/ uint32 buffcount;
|
||||
};
|
||||
|
||||
@@ -727,6 +726,7 @@ struct AA_Array
|
||||
{
|
||||
uint32 AA;
|
||||
uint32 value;
|
||||
uint32 charges;
|
||||
};
|
||||
|
||||
|
||||
@@ -756,29 +756,46 @@ struct Tribute_Struct {
|
||||
uint32 tier;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct {
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
char item_name[64];
|
||||
};
|
||||
|
||||
//len = 320
|
||||
enum { //bandolier item positions
|
||||
bandolierMainHand = 0,
|
||||
bandolierOffHand,
|
||||
// Bandolier item positions
|
||||
enum
|
||||
{
|
||||
bandolierPrimary = 0,
|
||||
bandolierSecondary,
|
||||
bandolierRange,
|
||||
bandolierAmmo
|
||||
};
|
||||
struct Bandolier_Struct {
|
||||
char name[32];
|
||||
BandolierItem_Struct items[EmuConstants::BANDOLIER_SIZE];
|
||||
};
|
||||
struct PotionBelt_Struct {
|
||||
BandolierItem_Struct items[EmuConstants::POTION_BELT_SIZE];
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
struct MovePotionToBelt_Struct {
|
||||
//len = 320
|
||||
struct Bandolier_Struct
|
||||
{
|
||||
char Name[32];
|
||||
BandolierItem_Struct Items[EmuConstants::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct PotionBeltItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
//len = 288
|
||||
struct PotionBelt_Struct
|
||||
{
|
||||
PotionBeltItem_Struct Items[EmuConstants::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct MovePotionToBelt_Struct
|
||||
{
|
||||
uint32 Action;
|
||||
uint32 SlotNumber;
|
||||
uint32 ItemID;
|
||||
@@ -1103,7 +1120,7 @@ struct PlayerProfile_Struct
|
||||
/*12800*/ uint32 expAA;
|
||||
/*12804*/ uint32 aapoints; //avaliable, unspent
|
||||
/*12808*/ uint8 unknown12844[36];
|
||||
/*12844*/ Bandolier_Struct bandoliers[EmuConstants::BANDOLIERS_COUNT];
|
||||
/*12844*/ Bandolier_Struct bandoliers[EmuConstants::BANDOLIERS_SIZE];
|
||||
/*14124*/ uint8 unknown14160[4506];
|
||||
/*18630*/ SuspendedMinion_Struct SuspendedMinion; // No longer in use
|
||||
/*19240*/ uint32 timeentitledonaccount;
|
||||
@@ -1144,7 +1161,7 @@ struct TargetReject_Struct {
|
||||
|
||||
struct PetCommand_Struct {
|
||||
/*000*/ uint32 command;
|
||||
/*004*/ uint32 unknown;
|
||||
/*004*/ uint32 target;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1249,7 +1266,7 @@ struct ZoneChange_Struct {
|
||||
|
||||
// Whatever you send to the client in RequestClientZoneChange_Struct.type, the client will send back
|
||||
// to the server in ZoneChange_Struct.zone_reason. My guess is this is a memo field of sorts.
|
||||
// WildcardX 27 January 2008
|
||||
// 27 January 2008
|
||||
|
||||
struct RequestClientZoneChange_Struct {
|
||||
/*00*/ uint16 zone_id;
|
||||
@@ -1263,8 +1280,8 @@ struct RequestClientZoneChange_Struct {
|
||||
|
||||
struct Animation_Struct {
|
||||
/*00*/ uint16 spawnid;
|
||||
/*02*/ uint8 action;
|
||||
/*03*/ uint8 value;
|
||||
/*02*/ uint8 speed;
|
||||
/*03*/ uint8 action;
|
||||
/*04*/
|
||||
};
|
||||
|
||||
@@ -1302,10 +1319,10 @@ struct CombatDamage_Struct
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||
/* 05 */ uint16 spellid;
|
||||
/* 07 */ uint32 damage;
|
||||
/* 11 */ uint32 unknown11;
|
||||
/* 15 */ uint32 sequence; // see above notes in Action_Struct
|
||||
/* 19 */ uint32 unknown19;
|
||||
/* 23 */
|
||||
/* 11 */ float force;
|
||||
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 19 */ float meleepush_z;
|
||||
/* 23 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -2132,24 +2149,24 @@ struct Illusion_Struct_Old {
|
||||
// OP_Sound - Size: 68
|
||||
struct QuestReward_Struct
|
||||
{
|
||||
/*000*/ uint32 from_mob; // ID of mob awarding the client
|
||||
/*004*/ uint32 unknown004;
|
||||
/*008*/ uint32 unknown008;
|
||||
/*012*/ uint32 unknown012;
|
||||
/*016*/ uint32 unknown016;
|
||||
/*020*/ uint32 unknown020;
|
||||
/*024*/ uint32 silver; // Gives silver to the client
|
||||
/*028*/ uint32 gold; // Gives gold to the client
|
||||
/*032*/ uint32 platinum; // Gives platinum to the client
|
||||
/*036*/ uint32 unknown036;
|
||||
/*040*/ uint32 unknown040;
|
||||
/*044*/ uint32 unknown044;
|
||||
/*048*/ uint32 unknown048;
|
||||
/*052*/ uint32 unknown052;
|
||||
/*056*/ uint32 unknown056;
|
||||
/*060*/ uint32 unknown060;
|
||||
/*064*/ uint32 unknown064;
|
||||
/*068*/
|
||||
/*000*/ uint32 mob_id; // ID of mob awarding the client
|
||||
/*004*/ uint32 target_id;
|
||||
/*008*/ uint32 exp_reward;
|
||||
/*012*/ uint32 faction;
|
||||
/*016*/ int32 faction_mod;
|
||||
/*020*/ uint32 copper; // Gives copper to the client
|
||||
/*024*/ uint32 silver; // Gives silver to the client
|
||||
/*028*/ uint32 gold; // Gives gold to the client
|
||||
/*032*/ uint32 platinum; // Gives platinum to the client
|
||||
/*036*/ uint32 item_id;
|
||||
/*040*/ uint32 unknown040;
|
||||
/*044*/ uint32 unknown044;
|
||||
/*048*/ uint32 unknown048;
|
||||
/*052*/ uint32 unknown052;
|
||||
/*056*/ uint32 unknown056;
|
||||
/*060*/ uint32 unknown060;
|
||||
/*064*/ uint32 unknown064;
|
||||
/*068*/
|
||||
};
|
||||
|
||||
// Size: 8
|
||||
@@ -2405,11 +2422,11 @@ struct InspectResponse_Struct {
|
||||
/*004*/ uint32 playerid;
|
||||
/*008*/ char itemnames[23][64];
|
||||
/*1480*/uint32 itemicons[23];
|
||||
/*1572*/char text[288]; // Max number of chars in Inspect Window appears to be 254 // Msg struct property is 256 (254 + '\0' is my guess) -U
|
||||
/*1572*/char text[288]; // Max number of chars in Inspect Window appears to be 254 // Msg struct property is 256 (254 + '\0' is my guess)
|
||||
/*1860*/
|
||||
};
|
||||
|
||||
//OP_InspectMessageUpdate - Size: 256 (SoF+ clients after self-inspect window is closed) -U
|
||||
//OP_InspectMessageUpdate - Size: 256 (SoF+ clients after self-inspect window is closed)
|
||||
struct InspectMessage_Struct {
|
||||
/*000*/ char text[256];
|
||||
/*256*/
|
||||
@@ -2518,9 +2535,9 @@ struct BookRequest_Struct {
|
||||
**
|
||||
*/
|
||||
struct Object_Struct {
|
||||
/*00*/ uint32 linked_list_addr[2];// <Zaphod> They are, get this, prev and next, ala linked list
|
||||
/*08*/ uint16 unknown008; //
|
||||
/*10*/ uint16 unknown010; //
|
||||
/*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list
|
||||
/*08*/ uint16 size; //
|
||||
/*10*/ uint16 solidtype; //
|
||||
/*12*/ uint32 drop_id; // Unique object id for zone
|
||||
/*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in
|
||||
/*18*/ uint16 zone_instance; //
|
||||
@@ -2537,8 +2554,8 @@ struct Object_Struct {
|
||||
/*88*/ uint32 spawn_id; // Spawn Id of client interacting with object
|
||||
/*92*/
|
||||
};
|
||||
//<Zaphod> 01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] <Zaphod> and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
// 01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
|
||||
/*
|
||||
** Click Object Struct
|
||||
@@ -2595,7 +2612,7 @@ struct CloseContainer_Struct {
|
||||
*/
|
||||
struct Door_Struct
|
||||
{
|
||||
/*0000*/ char name[32]; // Filename of Door // Was 10char long before... added the 6 in the next unknown to it: Daeken M. BlackBlade //changed both to 32: Trevius
|
||||
/*0000*/ char name[32]; // Filename of Door // Was 10char long before... added the 6 in the next unknown to it //changed both to 32
|
||||
/*0032*/ float yPos; // y loc
|
||||
/*0036*/ float xPos; // x loc
|
||||
/*0040*/ float zPos; // z loc
|
||||
@@ -2761,7 +2778,8 @@ struct BazaarWelcome_Struct {
|
||||
BazaarWindowStart_Struct Beginning;
|
||||
uint32 Traders;
|
||||
uint32 Items;
|
||||
uint8 Unknown012[8];
|
||||
uint32 Unknown012;
|
||||
uint32 Unknown016;
|
||||
};
|
||||
|
||||
struct BazaarSearch_Struct {
|
||||
@@ -3146,6 +3164,7 @@ struct Trader_ShowItems_Struct{
|
||||
/*000*/ uint32 Code;
|
||||
/*004*/ uint32 TraderID;
|
||||
/*008*/ uint32 Unknown08[3];
|
||||
/*020*/
|
||||
};
|
||||
|
||||
struct TraderBuy_Struct{
|
||||
@@ -3191,9 +3210,10 @@ struct TraderDelItem_Struct{
|
||||
|
||||
struct TraderClick_Struct{
|
||||
/*000*/ uint32 TraderID;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*004*/ uint32 Code;
|
||||
/*008*/ uint32 Unknown008;
|
||||
/*012*/ uint32 Approval;
|
||||
/*016*/
|
||||
};
|
||||
|
||||
struct FormattedMessage_Struct{
|
||||
@@ -4011,7 +4031,7 @@ struct MarkNPC_Struct
|
||||
|
||||
struct InspectBuffs_Struct {
|
||||
/*000*/ uint32 spell_id[BUFF_COUNT];
|
||||
/*100*/ uint32 tics_remaining[BUFF_COUNT];
|
||||
/*100*/ int32 tics_remaining[BUFF_COUNT];
|
||||
};
|
||||
|
||||
struct RaidGeneral_Struct {
|
||||
@@ -4104,30 +4124,35 @@ struct DynamicWall_Struct {
|
||||
/*80*/
|
||||
};
|
||||
|
||||
enum { //bandolier actions
|
||||
BandolierCreate = 0,
|
||||
BandolierRemove = 1,
|
||||
BandolierSet = 2
|
||||
// Bandolier actions
|
||||
enum
|
||||
{
|
||||
bandolierCreate = 0,
|
||||
bandolierRemove,
|
||||
bandolierSet
|
||||
};
|
||||
|
||||
struct BandolierCreate_Struct {
|
||||
/*00*/ uint32 action; //0 for create
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ char name[32];
|
||||
/*37*/ uint16 unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 unknown39; //0
|
||||
struct BandolierCreate_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; //0 for create
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ char Name[32];
|
||||
/*37*/ uint16 Unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 Unknown39; //0
|
||||
};
|
||||
|
||||
struct BandolierDelete_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierDelete_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct BandolierSet_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierSet_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct Arrow_Struct {
|
||||
@@ -4194,6 +4219,52 @@ struct UseAA_Struct {
|
||||
uint32 end;
|
||||
};
|
||||
|
||||
//new AA stuff
|
||||
//reference only
|
||||
struct AARankInfo_Struct
|
||||
{
|
||||
uint32 id;
|
||||
int32 upper_hotkey_sid;
|
||||
int32 lower_hotkey_sid;
|
||||
int32 title_sid;
|
||||
int32 desc_sid;
|
||||
int32 level_req;
|
||||
int32 cost;
|
||||
uint32 seq;
|
||||
uint32 current_level;
|
||||
uint32 type;
|
||||
int32 spell;
|
||||
int32 spell_type;
|
||||
int32 spell_refresh;
|
||||
int32 classes;
|
||||
int32 max_level;
|
||||
int32 prev_id;
|
||||
int32 next_id;
|
||||
int32 total_cost;
|
||||
int32 expansion;
|
||||
int32 category;
|
||||
uint32 charges;
|
||||
uint8 grant_only;
|
||||
uint32 total_effects;
|
||||
uint32 total_prereqs;
|
||||
};
|
||||
|
||||
struct AARankPrereq_Struct
|
||||
{
|
||||
int32 aa_id;
|
||||
int32 points;
|
||||
};
|
||||
|
||||
struct AARankEffect_Struct
|
||||
{
|
||||
int32 effect_id;
|
||||
int32 base1;
|
||||
int32 base2;
|
||||
int32 slot;
|
||||
};
|
||||
|
||||
//old AA stuff
|
||||
|
||||
struct AA_Ability {
|
||||
/*00*/ uint32 skill_id;
|
||||
/*04*/ uint32 base1;
|
||||
@@ -4248,18 +4319,10 @@ struct SendAA_Struct {
|
||||
struct AA_Action {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint32 ability;
|
||||
/*08*/ uint32 unknown08;
|
||||
/*08*/ uint32 target_id;
|
||||
/*12*/ uint32 exp_value;
|
||||
};
|
||||
|
||||
|
||||
struct AA_Skills { //this should be removed and changed to AA_Array
|
||||
/*00*/ uint32 aa_skill; // Total AAs Spent
|
||||
/*04*/ uint32 aa_value;
|
||||
/*08*/ uint32 unknown08;
|
||||
/*12*/
|
||||
};
|
||||
|
||||
struct AAExpUpdate_Struct {
|
||||
/*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability
|
||||
/*04*/ uint32 aapoints_unspent;
|
||||
@@ -4277,12 +4340,12 @@ struct AltAdvStats_Struct {
|
||||
};
|
||||
|
||||
struct PlayerAA_Struct { // Is this still used?
|
||||
AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AATable_Struct {
|
||||
/*00*/ int32 aa_spent; // Total AAs Spent
|
||||
/*04*/ AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
/*04*/ AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct Weather_Struct {
|
||||
@@ -4530,19 +4593,12 @@ struct InternalVeteranReward
|
||||
/*012*/ InternalVeteranRewardItem items[8];
|
||||
};
|
||||
|
||||
struct VeteranClaimReply
|
||||
struct VeteranClaim
|
||||
{
|
||||
/*000*/ char name[64];
|
||||
/*064*/ uint32 claim_id;
|
||||
/*068*/ uint32 reject_field;
|
||||
/*072*/ uint32 unknown072;
|
||||
};
|
||||
|
||||
struct VeteranClaimRequest
|
||||
{
|
||||
/*000*/ char name_data[64]; //name + other data
|
||||
/*000*/ char name[64]; //name + other data
|
||||
/*064*/ uint32 claim_id;
|
||||
/*068*/ uint32 unknown068;
|
||||
/*072*/ uint32 action;
|
||||
};
|
||||
|
||||
struct GMSearchCorpse_Struct
|
||||
@@ -4668,6 +4724,22 @@ struct GuildBankItemUpdate_Struct
|
||||
/*226*/ uint16 Unknown226;
|
||||
};
|
||||
|
||||
// newer clients (RoF+) send a list that contains 240 entries
|
||||
// The packets don't actually use all 64 chars in the strings, but we'll just overallocate for these
|
||||
struct GuildBankItemListEntry_Struct
|
||||
{
|
||||
uint8 vaild;
|
||||
uint32 permissions;
|
||||
char whofor[64];
|
||||
char donator[64];
|
||||
uint32 item_id;
|
||||
uint32 item_icon;
|
||||
uint32 quantity;
|
||||
uint8 allow_merge; // 1 here for non-full stacks
|
||||
uint8 usable;
|
||||
char item_name[64];
|
||||
};
|
||||
|
||||
struct GuildBankClear_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
@@ -4714,7 +4786,7 @@ struct BuffIconEntry_Struct
|
||||
{
|
||||
uint32 buff_slot;
|
||||
uint32 spell_id;
|
||||
uint32 tics_remaining;
|
||||
int32 tics_remaining;
|
||||
uint32 num_hits;
|
||||
};
|
||||
|
||||
@@ -4723,6 +4795,8 @@ struct BuffIcon_Struct
|
||||
uint32 entity_id;
|
||||
uint8 all_buffs;
|
||||
uint16 count;
|
||||
uint8 type; // 0 = self buff window, 1 = self target window, 4 = group, 5 = PC, 7 = NPC
|
||||
int32 tic_timer;
|
||||
BuffIconEntry_Struct entries[0];
|
||||
};
|
||||
|
||||
|
||||
+50
-27
@@ -23,6 +23,7 @@
|
||||
#include "op_codes.h"
|
||||
#include "crc16.h"
|
||||
#include "platform.h"
|
||||
#include "string_util.h"
|
||||
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
@@ -71,6 +72,8 @@ void EQStream::init(bool resetSession) {
|
||||
RateThreshold=RATEBASE/250;
|
||||
DecayRate=DECAYBASE/250;
|
||||
BytesWritten=0;
|
||||
sent_packet_count = 0;
|
||||
received_packet_count = 0;
|
||||
SequencedBase = 0;
|
||||
NextSequencedSend = 0;
|
||||
|
||||
@@ -463,37 +466,45 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
||||
}
|
||||
break;
|
||||
case OP_SessionStatRequest: {
|
||||
if(p->Size() < sizeof(SessionStats))
|
||||
if(p->Size() < sizeof(ClientSessionStats))
|
||||
{
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_SessionStatRequest that was of malformed size" __L);
|
||||
break;
|
||||
}
|
||||
#ifndef COLLECTOR
|
||||
SessionStats *Stats=(SessionStats *)p->pBuffer;
|
||||
ClientSessionStats *ClientStats=(ClientSessionStats *)p->pBuffer;
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "Received Stats: %lu packets received, %lu packets sent, Deltas: local %lu, (%lu <- %lu -> %lu) remote %lu" __L,
|
||||
(unsigned long)ntohl(Stats->packets_received), (unsigned long)ntohl(Stats->packets_sent), (unsigned long)ntohl(Stats->last_local_delta),
|
||||
(unsigned long)ntohl(Stats->low_delta), (unsigned long)ntohl(Stats->average_delta),
|
||||
(unsigned long)ntohl(Stats->high_delta), (unsigned long)ntohl(Stats->last_remote_delta));
|
||||
uint64 x=Stats->packets_received;
|
||||
Stats->packets_received=Stats->packets_sent;
|
||||
Stats->packets_sent=x;
|
||||
NonSequencedPush(new EQProtocolPacket(OP_SessionStatResponse,p->pBuffer,p->size));
|
||||
AdjustRates(ntohl(Stats->average_delta));
|
||||
(unsigned long)ntohl(ClientStats->packets_received), (unsigned long)ntohl(ClientStats->packets_sent), (unsigned long)ntohl(ClientStats->last_local_delta),
|
||||
(unsigned long)ntohl(ClientStats->low_delta), (unsigned long)ntohl(ClientStats->average_delta),
|
||||
(unsigned long)ntohl(ClientStats->high_delta), (unsigned long)ntohl(ClientStats->last_remote_delta));
|
||||
|
||||
AdjustRates(ntohl(ClientStats->average_delta));
|
||||
|
||||
if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) {
|
||||
if(RETRANSMIT_TIMEOUT_MULT && ntohl(Stats->average_delta)) {
|
||||
if (RETRANSMIT_TIMEOUT_MULT && ntohl(ClientStats->average_delta)) {
|
||||
//recalculate retransmittimeout using the larger of the last rtt or average rtt, which is multiplied by the rule value
|
||||
if((ntohl(Stats->last_local_delta) + ntohl(Stats->last_remote_delta)) > (ntohl(Stats->average_delta) * 2)) {
|
||||
retransmittimeout = (ntohl(Stats->last_local_delta) + ntohl(Stats->last_remote_delta))
|
||||
if ((ntohl(ClientStats->last_local_delta) + ntohl(ClientStats->last_remote_delta)) > (ntohl(ClientStats->average_delta) * 2)) {
|
||||
retransmittimeout = (ntohl(ClientStats->last_local_delta) + ntohl(ClientStats->last_remote_delta))
|
||||
* RETRANSMIT_TIMEOUT_MULT;
|
||||
} else {
|
||||
retransmittimeout = ntohl(Stats->average_delta) * 2 * RETRANSMIT_TIMEOUT_MULT;
|
||||
retransmittimeout = ntohl(ClientStats->average_delta) * 2 * RETRANSMIT_TIMEOUT_MULT;
|
||||
}
|
||||
if(retransmittimeout > RETRANSMIT_TIMEOUT_MAX)
|
||||
retransmittimeout = RETRANSMIT_TIMEOUT_MAX;
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "Retransmit timeout recalculated to %dms" __L, retransmittimeout);
|
||||
}
|
||||
}
|
||||
|
||||
ServerSessionStats *ServerStats = (ServerSessionStats *)p->pBuffer;
|
||||
|
||||
//ServerStats->RequestID = ClientStats->RequestID; // no change
|
||||
ServerStats->ServerTime = htonl(Timer::GetCurrentTime());
|
||||
ServerStats->packets_sent_echo = ClientStats->packets_sent; // still in htonll format
|
||||
ServerStats->packets_received_echo = ClientStats->packets_received; // still in htonll format
|
||||
ServerStats->packets_sent = htonll(GetPacketsSent());
|
||||
ServerStats->packets_received = htonll(GetPacketsReceived());
|
||||
|
||||
NonSequencedPush(new EQProtocolPacket(OP_SessionStatResponse, p->pBuffer, p->size));
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
@@ -555,21 +566,35 @@ void EQStream::FastQueuePacket(EQApplicationPacket **p, bool ack_req)
|
||||
|
||||
void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p)
|
||||
{
|
||||
uint32 chunksize,used;
|
||||
uint32 chunksize, used;
|
||||
uint32 length;
|
||||
|
||||
if (Log.log_settings[Logs::Server_Client_Packet].is_category_enabled == 1){
|
||||
if (p->GetOpcode() != OP_SpecialMesg){
|
||||
Log.Out(Logs::General, Logs::Server_Client_Packet, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size());
|
||||
}
|
||||
}
|
||||
|
||||
if (Log.log_settings[Logs::Server_Client_Packet_With_Dump].is_category_enabled == 1){
|
||||
if (p->GetOpcode() != OP_SpecialMesg){
|
||||
Log.Out(Logs::General, Logs::Server_Client_Packet_With_Dump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size(), DumpPacketToString(p).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the EQApplicationPacket to 1 or more EQProtocolPackets
|
||||
if (p->size>(MaxLen-8)) { // proto-op(2), seq(2), app-op(2) ... data ... crc(2)
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "Making oversized packet, len %d" __L, p->size);
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "Making oversized packet, len %d" __L, p->Size());
|
||||
|
||||
unsigned char *tmpbuff=new unsigned char[p->size+3];
|
||||
length=p->serialize(opcode, tmpbuff);
|
||||
if (length != p->Size())
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "Packet adjustment, len %d to %d" __L, p->Size(), length);
|
||||
|
||||
EQProtocolPacket *out=new EQProtocolPacket(OP_Fragment,nullptr,MaxLen-4);
|
||||
*(uint32 *)(out->pBuffer+2)=htonl(p->Size());
|
||||
*(uint32 *)(out->pBuffer+2)=htonl(length);
|
||||
used=MaxLen-10;
|
||||
memcpy(out->pBuffer+6,tmpbuff,used);
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "First fragment: used %d/%d. Put size %d in the packet" __L, used, p->size, p->Size());
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "First fragment: used %d/%d. Payload size %d in the packet" __L, used, length, p->size);
|
||||
SequencedPush(out);
|
||||
|
||||
|
||||
@@ -580,7 +605,7 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p)
|
||||
out->size=chunksize+2;
|
||||
SequencedPush(out);
|
||||
used+=chunksize;
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "Subsequent fragment: len %d, used %d/%d." __L, chunksize, used, p->size);
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "Subsequent fragment: len %d, used %d/%d." __L, chunksize, used, length);
|
||||
}
|
||||
delete p;
|
||||
delete[] tmpbuff;
|
||||
@@ -951,14 +976,12 @@ EQRawApplicationPacket *p=nullptr;
|
||||
}
|
||||
MInboundQueue.unlock();
|
||||
|
||||
//resolve the opcode if we can.
|
||||
if(p) {
|
||||
if(OpMgr != nullptr && *OpMgr != nullptr) {
|
||||
if (p) {
|
||||
if (OpMgr != nullptr && *OpMgr != nullptr) {
|
||||
EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode);
|
||||
if (emu_op == OP_Unknown) {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Unable to convert EQ opcode 0x%.4x to an Application opcode.", p->opcode);
|
||||
}
|
||||
|
||||
// Log.Out(Logs::General, Logs::Client_Server_Packet_Unhandled, "Unknown :: [%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->opcode, p->Size(), DumpPacketToString(p).c_str());
|
||||
}
|
||||
p->SetOpcode(emu_op);
|
||||
}
|
||||
}
|
||||
@@ -1090,8 +1113,8 @@ EQProtocolPacket *p=nullptr;
|
||||
|
||||
void EQStream::Process(const unsigned char *buffer, const uint32 length)
|
||||
{
|
||||
static unsigned char newbuffer[2048];
|
||||
uint32 newlength=0;
|
||||
static unsigned char newbuffer[2048];
|
||||
uint32 newlength=0;
|
||||
if (EQProtocolPacket::ValidateCRC(buffer,length,Key)) {
|
||||
if (compressed) {
|
||||
newlength=EQProtocolPacket::Decompress(buffer,length,newbuffer,2048);
|
||||
|
||||
+19
-1
@@ -71,7 +71,7 @@ struct SessionResponse {
|
||||
};
|
||||
|
||||
//Deltas are in ms, representing round trip times
|
||||
struct SessionStats {
|
||||
struct ClientSessionStats {
|
||||
/*000*/ uint16 RequestID;
|
||||
/*002*/ uint32 last_local_delta;
|
||||
/*006*/ uint32 average_delta;
|
||||
@@ -83,6 +83,16 @@ struct SessionStats {
|
||||
/*038*/
|
||||
};
|
||||
|
||||
struct ServerSessionStats {
|
||||
/*000*/ uint16 RequestID;
|
||||
/*002*/ uint32 ServerTime;
|
||||
/*006*/ uint64 packets_sent_echo;
|
||||
/*014*/ uint64 packets_received_echo;
|
||||
/*022*/ uint64 packets_sent;
|
||||
/*030*/ uint64 packets_received;
|
||||
/*038*/
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
class OpcodeManager;
|
||||
@@ -158,6 +168,9 @@ class EQStream : public EQStreamInterface {
|
||||
|
||||
int32 BytesWritten;
|
||||
|
||||
uint64 sent_packet_count;
|
||||
uint64 received_packet_count;
|
||||
|
||||
Mutex MRate;
|
||||
int32 RateThreshold;
|
||||
int32 DecayRate;
|
||||
@@ -265,11 +278,13 @@ class EQStream : public EQStreamInterface {
|
||||
void AddBytesSent(uint32 bytes)
|
||||
{
|
||||
bytes_sent += bytes;
|
||||
++sent_packet_count;
|
||||
}
|
||||
|
||||
void AddBytesRecv(uint32 bytes)
|
||||
{
|
||||
bytes_recv += bytes;
|
||||
++received_packet_count;
|
||||
}
|
||||
|
||||
virtual const uint32 GetBytesSent() const { return bytes_sent; }
|
||||
@@ -288,6 +303,9 @@ class EQStream : public EQStreamInterface {
|
||||
return bytes_recv / (Timer::GetTimeSeconds() - create_time);
|
||||
}
|
||||
|
||||
const uint64 GetPacketsSent() { return sent_packet_count; }
|
||||
const uint64 GetPacketsReceived() { return received_packet_count; }
|
||||
|
||||
//used for dynamic stream identification
|
||||
class Signature {
|
||||
public:
|
||||
|
||||
@@ -254,10 +254,6 @@ void EQEmuConfig::do_files(TiXmlElement *ele)
|
||||
if (text) {
|
||||
OpCodesFile = text;
|
||||
}
|
||||
text = ParseTextBlock(ele, "eqtime", true);
|
||||
if (text) {
|
||||
EQTimeFile = text;
|
||||
}
|
||||
}
|
||||
|
||||
void EQEmuConfig::do_directories(TiXmlElement *ele)
|
||||
@@ -408,9 +404,6 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const
|
||||
if (var_name == "OpCodesFile") {
|
||||
return (OpCodesFile);
|
||||
}
|
||||
if (var_name == "EQTimeFile") {
|
||||
return (EQTimeFile);
|
||||
}
|
||||
if (var_name == "MapDir") {
|
||||
return (MapDir);
|
||||
}
|
||||
@@ -475,7 +468,6 @@ void EQEmuConfig::Dump() const
|
||||
std::cout << "QSDatabasePort = " << QSDatabasePort << std::endl;
|
||||
std::cout << "SpellsFile = " << SpellsFile << std::endl;
|
||||
std::cout << "OpCodesFile = " << OpCodesFile << std::endl;
|
||||
std::cout << "EQTimeFile = " << EQTimeFile << std::endl;
|
||||
std::cout << "MapDir = " << MapDir << std::endl;
|
||||
std::cout << "QuestDir = " << QuestDir << std::endl;
|
||||
std::cout << "PluginDir = " << PluginDir << std::endl;
|
||||
|
||||
@@ -79,7 +79,6 @@ class EQEmuConfig : public XMLParser
|
||||
// From <files/>
|
||||
std::string SpellsFile;
|
||||
std::string OpCodesFile;
|
||||
std::string EQTimeFile;
|
||||
|
||||
// From <directories/>
|
||||
std::string MapDir;
|
||||
@@ -154,7 +153,6 @@ class EQEmuConfig : public XMLParser
|
||||
// Files
|
||||
SpellsFile = "spells_us.txt";
|
||||
OpCodesFile = "opcodes.conf";
|
||||
EQTimeFile = "eqtime.cfg";
|
||||
// Dirs
|
||||
MapDir = "Maps";
|
||||
QuestDir = "quests";
|
||||
|
||||
+29
-36
@@ -102,6 +102,7 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
|
||||
log_settings[Logs::UCS_Server].log_to_console = Logs::General;
|
||||
log_settings[Logs::Crash].log_to_console = Logs::General;
|
||||
log_settings[Logs::MySQLError].log_to_console = Logs::General;
|
||||
log_settings[Logs::Login_Server].log_to_console = Logs::General;
|
||||
|
||||
/* Declare process file names for log writing
|
||||
If there is no process_file_name declared, no log file will be written, simply
|
||||
@@ -116,32 +117,27 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
|
||||
platform_file_name = "ucs";
|
||||
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin)
|
||||
platform_file_name = "login";
|
||||
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin)
|
||||
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLaunch)
|
||||
platform_file_name = "launcher";
|
||||
}
|
||||
|
||||
std::string EQEmuLogSys::FormatOutMessageString(uint16 log_category, const std::string &in_message)
|
||||
{
|
||||
std::string category_string;
|
||||
if (log_category > 0 && Logs::LogCategoryName[log_category])
|
||||
category_string = StringFormat("[%s] ", Logs::LogCategoryName[log_category]);
|
||||
return StringFormat("%s%s", category_string.c_str(), in_message.c_str());
|
||||
std::string ret;
|
||||
ret.push_back('[');
|
||||
ret.append(Logs::LogCategoryName[log_category]);
|
||||
ret.push_back(']');
|
||||
ret.push_back(' ');
|
||||
ret.append(in_message);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void EQEmuLogSys::ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message)
|
||||
{
|
||||
/* Check if category enabled for process */
|
||||
if (log_settings[log_category].log_to_gmsay == 0)
|
||||
return;
|
||||
|
||||
/* Enabling Netcode based GMSay output creates a feedback loop that ultimately ends in a crash */
|
||||
if (log_category == Logs::LogCategory::Netcode)
|
||||
return;
|
||||
|
||||
/* Make sure the message inbound is at a debug level we're set at */
|
||||
if (log_settings[log_category].log_to_gmsay < debug_level)
|
||||
return;
|
||||
|
||||
/* Check to see if the process that actually ran this is zone */
|
||||
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone)
|
||||
on_log_gmsay_hook(log_category, message);
|
||||
@@ -159,14 +155,6 @@ void EQEmuLogSys::ProcessLogWrite(uint16 debug_level, uint16 log_category, const
|
||||
crash_log.close();
|
||||
}
|
||||
|
||||
/* Check if category enabled for process */
|
||||
if (log_settings[log_category].log_to_file == 0)
|
||||
return;
|
||||
|
||||
/* Make sure the message inbound is at a debug level we're set at */
|
||||
if (log_settings[log_category].log_to_file < debug_level)
|
||||
return;
|
||||
|
||||
char time_stamp[80];
|
||||
EQEmuLogSys::SetCurrentTimeStamp(time_stamp);
|
||||
|
||||
@@ -245,13 +233,6 @@ uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category) {
|
||||
|
||||
void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message)
|
||||
{
|
||||
/* Check if category enabled for process */
|
||||
if (log_settings[log_category].log_to_console == 0)
|
||||
return;
|
||||
|
||||
/* Make sure the message inbound is at a debug level we're set at */
|
||||
if (log_settings[log_category].log_to_console < debug_level)
|
||||
return;
|
||||
|
||||
#ifdef _WINDOWS
|
||||
HANDLE console_handle;
|
||||
@@ -272,23 +253,35 @@ void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category,
|
||||
|
||||
void EQEmuLogSys::Out(Logs::DebugLevel debug_level, uint16 log_category, std::string message, ...)
|
||||
{
|
||||
const bool log_to_console = log_settings[log_category].log_to_console > 0;
|
||||
const bool log_to_file = log_settings[log_category].log_to_file > 0;
|
||||
const bool log_to_gmsay = log_settings[log_category].log_to_gmsay > 0;
|
||||
const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay;
|
||||
bool log_to_console = true;
|
||||
if (log_settings[log_category].log_to_console < debug_level) {
|
||||
log_to_console = false;
|
||||
}
|
||||
|
||||
if (nothing_to_log) return;
|
||||
bool log_to_file = true;
|
||||
if (log_settings[log_category].log_to_file < debug_level) {
|
||||
log_to_file = false;
|
||||
}
|
||||
|
||||
bool log_to_gmsay = true;
|
||||
if (log_settings[log_category].log_to_gmsay < debug_level) {
|
||||
log_to_gmsay = false;
|
||||
}
|
||||
|
||||
const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay;
|
||||
if (nothing_to_log)
|
||||
return;
|
||||
|
||||
va_list args;
|
||||
va_start(args, message);
|
||||
std::string output_message = vStringFormat(message.c_str(), args);
|
||||
va_end(args);
|
||||
|
||||
|
||||
std::string output_debug_message = EQEmuLogSys::FormatOutMessageString(log_category, output_message);
|
||||
|
||||
|
||||
if (log_to_console) EQEmuLogSys::ProcessConsoleMessage(debug_level, log_category, output_debug_message);
|
||||
if (log_to_gmsay) EQEmuLogSys::ProcessGMSay(debug_level, log_category, output_debug_message);
|
||||
if (log_to_file) EQEmuLogSys::ProcessLogWrite(debug_level, log_category, output_message);
|
||||
if (log_to_file) EQEmuLogSys::ProcessLogWrite(debug_level, log_category, output_debug_message);
|
||||
}
|
||||
|
||||
void EQEmuLogSys::SetCurrentTimeStamp(char* time_stamp)
|
||||
|
||||
+13
-2
@@ -78,6 +78,11 @@ namespace Logs {
|
||||
MySQLQuery,
|
||||
Mercenaries,
|
||||
QuestDebug,
|
||||
Server_Client_Packet,
|
||||
Client_Server_Packet_Unhandled,
|
||||
Server_Client_Packet_With_Dump,
|
||||
Client_Server_Packet_With_Dump,
|
||||
Login_Server,
|
||||
MaxCategoryID /* Don't Remove this*/
|
||||
};
|
||||
|
||||
@@ -88,7 +93,7 @@ namespace Logs {
|
||||
"AI",
|
||||
"Aggro",
|
||||
"Attack",
|
||||
"Client Server Packet",
|
||||
"Packet :: Client -> Server",
|
||||
"Combat",
|
||||
"Commands",
|
||||
"Crash",
|
||||
@@ -121,7 +126,12 @@ namespace Logs {
|
||||
"MySQL Error",
|
||||
"MySQL Query",
|
||||
"Mercenaries",
|
||||
"Quest Debug"
|
||||
"Quest Debug",
|
||||
"Packet :: Server -> Client",
|
||||
"Packet :: Client -> Server Unhandled",
|
||||
"Packet :: Server -> Client (Dump)",
|
||||
"Packet :: Client -> Server (Dump)",
|
||||
"Login Server"
|
||||
};
|
||||
}
|
||||
|
||||
@@ -160,6 +170,7 @@ public:
|
||||
uint8 log_to_file;
|
||||
uint8 log_to_console;
|
||||
uint8 log_to_gmsay;
|
||||
uint8 is_category_enabled; /* When any log output in a category > 0, set this to 1 as (Enabled) */
|
||||
};
|
||||
|
||||
/* Internally used memory reference for all log settings per category.
|
||||
|
||||
+40
-107
@@ -43,19 +43,19 @@ EQTime::EQTime(TimeOfDay_Struct start_eq, time_t start_real)
|
||||
|
||||
EQTime::EQTime()
|
||||
{
|
||||
timezone=0;
|
||||
timezone = 0;
|
||||
memset(&eqTime, 0, sizeof(eqTime));
|
||||
//Defaults for time
|
||||
TimeOfDay_Struct start;
|
||||
start.day=1;
|
||||
start.hour=9;
|
||||
start.minute=0;
|
||||
start.month=1;
|
||||
start.year=3100;
|
||||
start.day = 1;
|
||||
start.hour = 9;
|
||||
start.minute = 0;
|
||||
start.month = 1;
|
||||
start.year = 3100;
|
||||
//Set default time zone
|
||||
timezone=0;
|
||||
timezone = 0;
|
||||
//Start EQTimer
|
||||
setEQTimeOfDay(start, time(0));
|
||||
SetCurrentEQTimeOfDay(start, time(0));
|
||||
}
|
||||
|
||||
EQTime::~EQTime()
|
||||
@@ -67,10 +67,10 @@ EQTime::~EQTime()
|
||||
//Input: Current Time (as a time_t), a pointer to the TimeOfDay_Struct that will be written to.
|
||||
//Output: 0=Error, 1=Sucess
|
||||
|
||||
int EQTime::getEQTimeOfDay( time_t timeConvert, struct TimeOfDay_Struct *eqTimeOfDay )
|
||||
int EQTime::GetCurrentEQTimeOfDay(time_t timeConvert, struct TimeOfDay_Struct *eqTimeOfDay)
|
||||
{
|
||||
/* check to see if we have a reference time to go by. */
|
||||
if( eqTime.start_realtime == 0 )
|
||||
if (eqTime.start_realtime == 0)
|
||||
return 0;
|
||||
|
||||
unsigned long diff = timeConvert - eqTime.start_realtime;
|
||||
@@ -83,7 +83,7 @@ int EQTime::getEQTimeOfDay( time_t timeConvert, struct TimeOfDay_Struct *eqTimeO
|
||||
int32 ntz = timezone;
|
||||
|
||||
/* The minutes range from 0 - 59 */
|
||||
diff += eqTime.start_eqtime.minute + (ntz%60);
|
||||
diff += eqTime.start_eqtime.minute + (ntz % 60);
|
||||
eqTimeOfDay->minute = diff % 60;
|
||||
diff /= 60;
|
||||
ntz /= 60;
|
||||
@@ -97,24 +97,24 @@ int EQTime::getEQTimeOfDay( time_t timeConvert, struct TimeOfDay_Struct *eqTimeO
|
||||
//
|
||||
// Modify it so that it works from
|
||||
// 0-23 for our calculations
|
||||
diff += ( eqTime.start_eqtime.hour - 1) + (ntz%24);
|
||||
eqTimeOfDay->hour = (diff%24) + 1;
|
||||
diff += (eqTime.start_eqtime.hour - 1) + (ntz % 24);
|
||||
eqTimeOfDay->hour = (diff % 24) + 1;
|
||||
diff /= 24;
|
||||
ntz /= 24;
|
||||
|
||||
// The days range from 1-28
|
||||
// Modify it so that it works from
|
||||
// 0-27 for our calculations
|
||||
diff += ( eqTime.start_eqtime.day - 1 ) + (ntz%28);
|
||||
eqTimeOfDay->day = (diff%28) + 1;
|
||||
diff += (eqTime.start_eqtime.day - 1) + (ntz % 28);
|
||||
eqTimeOfDay->day = (diff % 28) + 1;
|
||||
diff /= 28;
|
||||
ntz /= 28;
|
||||
|
||||
// The months range from 1-12
|
||||
// Modify it so that it works from
|
||||
// 0-11 for our calculations
|
||||
diff += ( eqTime.start_eqtime.month - 1 ) + (ntz%12);
|
||||
eqTimeOfDay->month = (diff%12) + 1;
|
||||
diff += (eqTime.start_eqtime.month - 1) + (ntz % 12);
|
||||
eqTimeOfDay->month = (diff % 12) + 1;
|
||||
diff /= 12;
|
||||
ntz /= 12;
|
||||
|
||||
@@ -124,100 +124,34 @@ int EQTime::getEQTimeOfDay( time_t timeConvert, struct TimeOfDay_Struct *eqTimeO
|
||||
}
|
||||
|
||||
//setEQTimeOfDay
|
||||
int EQTime::setEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real)
|
||||
int EQTime::SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real)
|
||||
{
|
||||
if(start_real==0)
|
||||
if (start_real == 0)
|
||||
return 0;
|
||||
eqTime.start_eqtime=start_eq;
|
||||
eqTime.start_realtime=start_real;
|
||||
eqTime.start_eqtime = start_eq;
|
||||
eqTime.start_realtime = start_real;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//saveFile and loadFile need to use long for the save datatype...
|
||||
//For some reason, ifstream/ofstream have problems with EQEmu datatypes in files.
|
||||
bool EQTime::saveFile(const char *filename)
|
||||
{
|
||||
std::ofstream of;
|
||||
of.open(filename);
|
||||
if(!of)
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Error, "EQTime::saveFile failed: Unable to open file '%s'", filename);
|
||||
return false;
|
||||
}
|
||||
//Enable for debugging
|
||||
of << EQT_VERSION << std::endl;
|
||||
of << (long)eqTime.start_eqtime.day << std::endl;
|
||||
of << (long)eqTime.start_eqtime.hour << std::endl;
|
||||
of << (long)eqTime.start_eqtime.minute << std::endl;
|
||||
of << (long)eqTime.start_eqtime.month << std::endl;
|
||||
of << eqTime.start_eqtime.year << std::endl;
|
||||
of << eqTime.start_realtime << std::endl;
|
||||
of.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EQTime::loadFile(const char *filename)
|
||||
{
|
||||
int version=0;
|
||||
long in_data=0;
|
||||
std::ifstream in;
|
||||
in.open(filename);
|
||||
if(!in)
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Error, "Could not load EQTime file %s", filename);
|
||||
return false;
|
||||
}
|
||||
in >> version;
|
||||
in.ignore(80, '\n');
|
||||
if(version != EQT_VERSION)
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Error, "'%s' is NOT a valid EQTime file. File version is %i, EQTime version is %i", filename, version, EQT_VERSION);
|
||||
return false;
|
||||
}
|
||||
//in >> eqTime.start_eqtime.day;
|
||||
in >> in_data;
|
||||
in.ignore(80, '\n');
|
||||
eqTime.start_eqtime.day = in_data;
|
||||
//in >> eqTime.start_eqtime.hour;
|
||||
in >> in_data;
|
||||
eqTime.start_eqtime.hour = in_data;
|
||||
in.ignore(80, '\n');
|
||||
//in >> eqTime.start_eqtime.minute;
|
||||
in >> in_data;
|
||||
in.ignore(80, '\n');
|
||||
eqTime.start_eqtime.minute = in_data;
|
||||
//in >> eqTime.start_eqtime.month;
|
||||
in >> in_data;
|
||||
in.ignore(80, '\n');
|
||||
eqTime.start_eqtime.month = in_data;
|
||||
in >> eqTime.start_eqtime.year;
|
||||
in.ignore(80, '\n');
|
||||
in >> eqTime.start_realtime;
|
||||
//Enable for debugging...
|
||||
in.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool EQTime::IsTimeBefore(TimeOfDay_Struct *base, TimeOfDay_Struct *test) {
|
||||
if(base->year > test->year)
|
||||
if (base->year > test->year)
|
||||
return(true);
|
||||
if(base->year < test->year)
|
||||
if (base->year < test->year)
|
||||
return(false);
|
||||
//same years
|
||||
if(base->month > test->month)
|
||||
if (base->month > test->month)
|
||||
return(true);
|
||||
if(base->month < test->month)
|
||||
if (base->month < test->month)
|
||||
return(false);
|
||||
//same month
|
||||
if(base->day > test->day)
|
||||
if (base->day > test->day)
|
||||
return(true);
|
||||
if(base->day < test->day)
|
||||
if (base->day < test->day)
|
||||
return(false);
|
||||
//same day
|
||||
if(base->hour > test->hour)
|
||||
if (base->hour > test->hour)
|
||||
return(true);
|
||||
if(base->hour < test->hour)
|
||||
if (base->hour < test->hour)
|
||||
return(false);
|
||||
//same hour...
|
||||
return(base->minute > test->minute);
|
||||
@@ -230,7 +164,7 @@ void EQTime::AddMinutes(uint32 minutes, TimeOfDay_Struct *to) {
|
||||
//minutes start at 0, everything else starts at 1
|
||||
cur = to->minute;
|
||||
cur += minutes;
|
||||
if(cur < 60) {
|
||||
if (cur < 60) {
|
||||
to->minute = cur;
|
||||
return;
|
||||
}
|
||||
@@ -238,29 +172,29 @@ void EQTime::AddMinutes(uint32 minutes, TimeOfDay_Struct *to) {
|
||||
//carry hours
|
||||
cur /= 60;
|
||||
cur += to->hour;
|
||||
if(cur <= 24) {
|
||||
if (cur <= 24) {
|
||||
to->hour = cur;
|
||||
return;
|
||||
}
|
||||
to->hour = ((cur-1) % 24) + 1;
|
||||
to->hour = ((cur - 1) % 24) + 1;
|
||||
//carry days
|
||||
cur = (cur-1) / 24;
|
||||
cur = (cur - 1) / 24;
|
||||
cur += to->day;
|
||||
if(cur <= 28) {
|
||||
if (cur <= 28) {
|
||||
to->day = cur;
|
||||
return;
|
||||
}
|
||||
to->day = ((cur-1) % 28) + 1;
|
||||
to->day = ((cur - 1) % 28) + 1;
|
||||
//carry months
|
||||
cur = (cur-1) / 28;
|
||||
cur = (cur - 1) / 28;
|
||||
cur += to->month;
|
||||
if(cur <= 12) {
|
||||
if (cur <= 12) {
|
||||
to->month = cur;
|
||||
return;
|
||||
}
|
||||
to->month = ((cur-1) % 12) + 1;
|
||||
to->month = ((cur - 1) % 12) + 1;
|
||||
//carry years
|
||||
to->year += (cur-1) / 12;
|
||||
to->year += (cur - 1) / 12;
|
||||
}
|
||||
|
||||
void EQTime::ToString(TimeOfDay_Struct *t, std::string &str) {
|
||||
@@ -269,5 +203,4 @@ void EQTime::ToString(TimeOfDay_Struct *t, std::string &str) {
|
||||
t->month, t->day, t->year, t->hour, t->minute);
|
||||
buf[127] = '\0';
|
||||
str = buf;
|
||||
}
|
||||
|
||||
}
|
||||
+3
-9
@@ -21,8 +21,8 @@ public:
|
||||
~EQTime();
|
||||
|
||||
//Get functions
|
||||
int getEQTimeOfDay( TimeOfDay_Struct *eqTimeOfDay ) { return(getEQTimeOfDay(time(nullptr), eqTimeOfDay)); }
|
||||
int getEQTimeOfDay( time_t timeConvert, TimeOfDay_Struct *eqTimeOfDay );
|
||||
int GetCurrentEQTimeOfDay( TimeOfDay_Struct *eqTimeOfDay ) { return(GetCurrentEQTimeOfDay(time(nullptr), eqTimeOfDay)); }
|
||||
int GetCurrentEQTimeOfDay( time_t timeConvert, TimeOfDay_Struct *eqTimeOfDay );
|
||||
TimeOfDay_Struct getStartEQTime() { return eqTime.start_eqtime; }
|
||||
time_t getStartRealTime() { return eqTime.start_realtime; }
|
||||
uint32 getEQTimeZone() { return timezone; }
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
uint32 getEQTimeZoneMin() { return timezone%60; }
|
||||
|
||||
//Set functions
|
||||
int setEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real);
|
||||
int SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real);
|
||||
void setEQTimeZone(int32 in_timezone) { timezone=in_timezone; }
|
||||
|
||||
//Time math/logic functions
|
||||
@@ -39,12 +39,6 @@ public:
|
||||
|
||||
static void ToString(TimeOfDay_Struct *t, std::string &str);
|
||||
|
||||
//Database functions
|
||||
//bool loadDB(Database q);
|
||||
//bool setDB(Database q);
|
||||
bool loadFile(const char *filename);
|
||||
bool saveFile(const char *filename);
|
||||
|
||||
private:
|
||||
//This is our reference clock.
|
||||
eqTimeOfDay eqTime;
|
||||
|
||||
@@ -54,6 +54,8 @@ struct ExtendedProfile_Struct {
|
||||
uint32 mercTimerRemaining; /* Not Used */
|
||||
uint8 mercGender; /* Not Used */
|
||||
int32 mercState; /* Not Used */
|
||||
uint32 last_invsnapshot_time; /* Used */
|
||||
uint32 next_invsnapshot_time; /* Used */
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
+7
-1
@@ -154,11 +154,12 @@ enum { //reuse times
|
||||
enum { //timer settings, all in milliseconds
|
||||
AImovement_duration = 100,
|
||||
AIthink_duration = 150,
|
||||
AIscanarea_delay = 500,
|
||||
AIscanarea_delay = 6000,
|
||||
AIfeignremember_delay = 500,
|
||||
AItarget_check_duration = 500,
|
||||
AIClientScanarea_delay = 750, //used in REVERSE_AGGRO
|
||||
AIassistcheck_delay = 3000, //now often a fighting NPC will yell for help
|
||||
AI_check_signal_timer_delay = 500, // How often EVENT_SIGNAL checks are processed
|
||||
ClientProximity_interval = 150,
|
||||
CombatEventTimer_expire = 12000,
|
||||
Tribute_duration = 600000,
|
||||
@@ -232,6 +233,8 @@ enum { //some random constants
|
||||
#define GROUP_EXP_PER_POINT 1000
|
||||
#define RAID_EXP_PER_POINT 2000
|
||||
|
||||
#define ZONE_CONTROLLER_NPC_ID 10
|
||||
|
||||
//Some hard coded statuses from commands and other places:
|
||||
enum {
|
||||
minStatusToBeGM = 40,
|
||||
@@ -270,6 +273,9 @@ enum {
|
||||
#define NPC_DEFAULT_LOGGING_ENABLED false
|
||||
|
||||
|
||||
// This is the item ID we use for say links, we use the max that fits in 5 ASCII chars
|
||||
#define SAYLINK_ITEM_ID 0xFFFFF
|
||||
|
||||
|
||||
/*
|
||||
|
||||
|
||||
@@ -867,16 +867,16 @@ bool BaseGuildManager::QueryWithLogging(std::string query, const char *errmsg) {
|
||||
//factored out so I dont have to copy this crap.
|
||||
#ifdef BOTS
|
||||
#define GuildMemberBaseQuery \
|
||||
"SELECT c.id,c.name,c.class,c.level,c.timelaston,c.zoneid," \
|
||||
" g.guild_id,g.rank,g.tribute_enable,g.total_tribute,g.last_tribute," \
|
||||
" g.banker,g.public_note,g.alt" \
|
||||
" FROM vwBotCharacterMobs AS c LEFT JOIN vwGuildMembers AS g ON c.id=g.char_id AND c.mobtype = g.mobtype "
|
||||
"SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \
|
||||
" g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \
|
||||
" g.`banker`, g.`public_note`, g.`alt`" \
|
||||
" FROM `vw_bot_character_mobs` AS c LEFT JOIN `vw_guild_members` AS g ON c.`id` = g.`char_id` AND c.`mob_type` = g.`mob_type` "
|
||||
#else
|
||||
#define GuildMemberBaseQuery \
|
||||
"SELECT c.id,c.name,c.class,c.level,c.last_login,c.zone_id," \
|
||||
" g.guild_id,g.rank,g.tribute_enable,g.total_tribute,g.last_tribute," \
|
||||
" g.banker,g.public_note,g.alt " \
|
||||
" FROM `character_data` AS c LEFT JOIN guild_members AS g ON c.id=g.char_id "
|
||||
"SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \
|
||||
" g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \
|
||||
" g.`banker`, g.`public_note`, g.`alt` " \
|
||||
" FROM `character_data` AS c LEFT JOIN `guild_members` AS g ON c.`id` = g.`char_id` "
|
||||
#endif
|
||||
static void ProcessGuildMember(MySQLRequestRow row, CharGuildInfo &into) {
|
||||
//fields from `characer_`
|
||||
@@ -969,7 +969,7 @@ bool BaseGuildManager::GetCharInfo(uint32 char_id, CharGuildInfo &into) {
|
||||
//load up the rank info for each guild.
|
||||
std::string query;
|
||||
#ifdef BOTS
|
||||
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mobtype = 'C'", char_id);
|
||||
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mob_type = 'C'", char_id);
|
||||
#else
|
||||
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d", char_id);
|
||||
#endif
|
||||
|
||||
+844
-44
File diff suppressed because it is too large
Load Diff
+100
-11
@@ -29,13 +29,11 @@ class EvolveInfo; // Stores information about an evolving item family
|
||||
#include "../common/eq_constants.h"
|
||||
#include "../common/item_struct.h"
|
||||
#include "../common/timer.h"
|
||||
#include "../common/bodytypes.h"
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
// Helper typedefs
|
||||
typedef std::map<int16, ItemInst*>::const_iterator iter_inst;
|
||||
typedef std::map<uint8, ItemInst*>::const_iterator iter_contents;
|
||||
|
||||
namespace ItemField
|
||||
{
|
||||
@@ -86,8 +84,8 @@ public:
|
||||
// Public Methods
|
||||
/////////////////////////
|
||||
|
||||
inline std::list<ItemInst*>::const_iterator begin() { return m_list.begin(); }
|
||||
inline std::list<ItemInst*>::const_iterator end() { return m_list.end(); }
|
||||
inline std::list<ItemInst*>::const_iterator cbegin() { return m_list.cbegin(); }
|
||||
inline std::list<ItemInst*>::const_iterator cend() { return m_list.cend(); }
|
||||
|
||||
inline int size() { return static_cast<int>(m_list.size()); } // TODO: change to size_t
|
||||
inline bool empty() { return m_list.empty(); }
|
||||
@@ -140,8 +138,8 @@ public:
|
||||
ItemInst* GetItem(int16 slot_id) const;
|
||||
ItemInst* GetItem(int16 slot_id, uint8 bagidx) const;
|
||||
|
||||
inline std::list<ItemInst*>::const_iterator cursor_begin() { return m_cursor.begin(); }
|
||||
inline std::list<ItemInst*>::const_iterator cursor_end() { return m_cursor.end(); }
|
||||
inline std::list<ItemInst*>::const_iterator cursor_cbegin() { return m_cursor.cbegin(); }
|
||||
inline std::list<ItemInst*>::const_iterator cursor_cend() { return m_cursor.cend(); }
|
||||
|
||||
inline int CursorSize() { return m_cursor.size(); }
|
||||
inline bool CursorEmpty() { return m_cursor.empty(); }
|
||||
@@ -207,7 +205,7 @@ public:
|
||||
|
||||
int GetSlotByItemInst(ItemInst *inst);
|
||||
|
||||
uint8 FindHighestLightValue();
|
||||
uint8 FindBrightestLightType();
|
||||
|
||||
void dumpEntireInventory();
|
||||
void dumpWornItems();
|
||||
@@ -227,7 +225,7 @@ protected:
|
||||
|
||||
int GetSlotByItemInstCollection(const std::map<int16, ItemInst*> &collection, ItemInst *inst);
|
||||
void dumpItemCollection(const std::map<int16, ItemInst*> &collection);
|
||||
void dumpBagContents(ItemInst *inst, iter_inst *it);
|
||||
void dumpBagContents(ItemInst *inst, std::map<int16, ItemInst*>::const_iterator *it);
|
||||
|
||||
// Retrieves item within an inventory bucket
|
||||
ItemInst* _GetItem(const std::map<int16, ItemInst*>& bucket, int16 slot_id) const;
|
||||
@@ -421,12 +419,64 @@ public:
|
||||
void StopTimer(std::string name);
|
||||
void ClearTimers();
|
||||
|
||||
// Get a total of a stat, including augs
|
||||
// These functions should be used in place of other code manually totaling
|
||||
// to centralize where it is done to make future changes easier (ex. whenever powersources come around)
|
||||
// and to minimize errors. CalcItemBonuses however doesn't use these in interest of performance
|
||||
// by default these do not recurse into augs
|
||||
int GetItemArmorClass(bool augments = false) const;
|
||||
int GetItemElementalDamage(int &magic, int &fire, int &cold, int &poison, int &disease, int &chromatic, int &prismatic, int &physical, int &corruption, bool augments = false) const;
|
||||
// These two differ in the fact that they're quick checks (they are checked BEFORE the one above
|
||||
int GetItemElementalFlag(bool augments = false) const;
|
||||
int GetItemElementalDamage(bool augments = false) const;
|
||||
int GetItemRecommendedLevel(bool augments = false) const;
|
||||
int GetItemRequiredLevel(bool augments = false) const;
|
||||
int GetItemWeaponDamage(bool augments = false) const;
|
||||
int GetItemBackstabDamage(bool augments = false) const;
|
||||
// these two are just quick checks
|
||||
int GetItemBaneDamageBody(bool augments = false) const;
|
||||
int GetItemBaneDamageRace(bool augments = false) const;
|
||||
int GetItemBaneDamageBody(bodyType against, bool augments = false) const;
|
||||
int GetItemBaneDamageRace(uint16 against, bool augments = false) const;
|
||||
int GetItemMagical(bool augments = false) const;
|
||||
int GetItemHP(bool augments = false) const;
|
||||
int GetItemMana(bool augments = false) const;
|
||||
int GetItemEndur(bool augments = false) const;
|
||||
int GetItemAttack(bool augments = false) const;
|
||||
int GetItemStr(bool augments = false) const;
|
||||
int GetItemSta(bool augments = false) const;
|
||||
int GetItemDex(bool augments = false) const;
|
||||
int GetItemAgi(bool augments = false) const;
|
||||
int GetItemInt(bool augments = false) const;
|
||||
int GetItemWis(bool augments = false) const;
|
||||
int GetItemCha(bool augments = false) const;
|
||||
int GetItemMR(bool augments = false) const;
|
||||
int GetItemFR(bool augments = false) const;
|
||||
int GetItemCR(bool augments = false) const;
|
||||
int GetItemPR(bool augments = false) const;
|
||||
int GetItemDR(bool augments = false) const;
|
||||
int GetItemCorrup(bool augments = false) const;
|
||||
int GetItemHeroicStr(bool augments = false) const;
|
||||
int GetItemHeroicSta(bool augments = false) const;
|
||||
int GetItemHeroicDex(bool augments = false) const;
|
||||
int GetItemHeroicAgi(bool augments = false) const;
|
||||
int GetItemHeroicInt(bool augments = false) const;
|
||||
int GetItemHeroicWis(bool augments = false) const;
|
||||
int GetItemHeroicCha(bool augments = false) const;
|
||||
int GetItemHeroicMR(bool augments = false) const;
|
||||
int GetItemHeroicFR(bool augments = false) const;
|
||||
int GetItemHeroicCR(bool augments = false) const;
|
||||
int GetItemHeroicPR(bool augments = false) const;
|
||||
int GetItemHeroicDR(bool augments = false) const;
|
||||
int GetItemHeroicCorrup(bool augments = false) const;
|
||||
int GetItemHaste(bool augments = false) const;
|
||||
|
||||
protected:
|
||||
//////////////////////////
|
||||
// Protected Members
|
||||
//////////////////////////
|
||||
iter_contents _begin() { return m_contents.begin(); }
|
||||
iter_contents _end() { return m_contents.end(); }
|
||||
std::map<uint8, ItemInst*>::const_iterator _cbegin() { return m_contents.cbegin(); }
|
||||
std::map<uint8, ItemInst*>::const_iterator _cend() { return m_contents.cend(); }
|
||||
|
||||
friend class Inventory;
|
||||
|
||||
@@ -475,4 +525,43 @@ public:
|
||||
~EvolveInfo();
|
||||
};
|
||||
|
||||
struct LightProfile_Struct
|
||||
{
|
||||
/*
|
||||
Current criteria (light types):
|
||||
Equipment: { 0 .. 15 }
|
||||
General: { 9 .. 13 }
|
||||
|
||||
Notes:
|
||||
- Initial character load and item movement updates use different light source update behaviors
|
||||
-- Server procedure matches the item movement behavior since most updates occur post-character load
|
||||
- MainAmmo is not considered when determining light sources
|
||||
- No 'Sub' or 'Aug' items are recognized as light sources
|
||||
- Light types '< 9' and '> 13' are not considered for general (carried) light sources
|
||||
- If values > 0x0F are valid, then assignment limiters will need to be removed
|
||||
- MainCursor 'appears' to be a valid light source update slot..but, have not experienced updates during debug sessions
|
||||
- All clients have a bug regarding stackable items (light and sound updates are not processed when picking up an item)
|
||||
-- The timer-based update cancels out the invalid light source
|
||||
*/
|
||||
|
||||
static uint8 TypeToLevel(uint8 lightType);
|
||||
static bool IsLevelGreater(uint8 leftType, uint8 rightType);
|
||||
|
||||
// Light types (classifications)
|
||||
struct {
|
||||
uint8 Innate; // Defined by db field `npc_types`.`light` - where appropriate
|
||||
uint8 Equipment; // Item_Struct::light value of worn/carried equipment
|
||||
uint8 Spell; // Set value of any light-producing spell (can be modded to mimic equip_light behavior)
|
||||
uint8 Active; // Highest value of all light sources
|
||||
} Type;
|
||||
|
||||
// Light levels (intensities) - used to determine which light source should be active
|
||||
struct {
|
||||
uint8 Innate;
|
||||
uint8 Equipment;
|
||||
uint8 Spell;
|
||||
uint8 Active;
|
||||
} Level;
|
||||
};
|
||||
|
||||
#endif // #define __ITEM_H
|
||||
|
||||
@@ -41,6 +41,7 @@ F(ac)
|
||||
F(deity)
|
||||
F(skillmodvalue)
|
||||
F(UNK033)
|
||||
F(skillmodmax)
|
||||
F(skillmodtype)
|
||||
F(banedmgrace)
|
||||
F(banedmgamt)
|
||||
@@ -172,7 +173,10 @@ F(bardlevel)
|
||||
F(questitemflag)
|
||||
F(svcorruption)
|
||||
F(purity)
|
||||
F(evoitem)
|
||||
F(evoid)
|
||||
F(evolvinglevel)
|
||||
F(evomax)
|
||||
F(backstabdmg)
|
||||
F(dsmitigation)
|
||||
F(heroic_str)
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
**
|
||||
*/
|
||||
struct ItemEffect_Struct {
|
||||
int16 Effect;
|
||||
int32 Effect;
|
||||
uint8 Type;
|
||||
uint8 Level;
|
||||
uint8 Level2;
|
||||
@@ -130,6 +130,7 @@ struct Item_Struct {
|
||||
uint32 Deity; // Bitmask of Deities that can equip this item
|
||||
//uint32 Unk033
|
||||
int32 SkillModValue; // % Mod to skill specified in SkillModType
|
||||
int32 SkillModMax; // Max skill point modification
|
||||
uint32 SkillModType; // Type of skill for SkillModValue to apply to
|
||||
uint32 BaneDmgRace; // Bane Damage Race
|
||||
int8 BaneDmgAmt; // Bane Damage Body Amount
|
||||
@@ -185,7 +186,7 @@ struct Item_Struct {
|
||||
uint32 AugType;
|
||||
uint8 AugSlotType[EmuConstants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Type
|
||||
uint8 AugSlotVisible[EmuConstants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Visible
|
||||
uint8 AugSlotUnk2[EmuConstants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Unknown
|
||||
uint8 AugSlotUnk2[EmuConstants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related
|
||||
uint32 LDoNTheme;
|
||||
uint32 LDoNPrice;
|
||||
uint32 LDoNSold;
|
||||
@@ -218,7 +219,10 @@ struct Item_Struct {
|
||||
// Begin SoF Fields
|
||||
int32 SVCorruption;
|
||||
uint32 Purity;
|
||||
uint8 EvolvingItem;
|
||||
uint32 EvolvingID;
|
||||
uint8 EvolvingLevel;
|
||||
uint8 EvolvingMax;
|
||||
uint32 BackstabDmg;
|
||||
uint32 DSMitigation;
|
||||
int32 HeroicStr;
|
||||
|
||||
@@ -146,6 +146,7 @@ INr(OP_GuildDelete); //?
|
||||
IN(OP_GuildPublicNote, GuildUpdate_PublicNote);
|
||||
INz(OP_GetGuildsList); //?
|
||||
IN(OP_SetGuildMOTD, GuildMOTD_Struct);
|
||||
IN(OP_SetRunMode, SetRunMode_Struct);
|
||||
INz(OP_GuildPeace); //?
|
||||
INz(OP_GuildWar); //?
|
||||
IN(OP_GuildLeader, GuildMakeLeader);
|
||||
@@ -180,7 +181,7 @@ IN(OP_GMLastName, GMLastName_Struct);
|
||||
IN(OP_GMToggle, GMToggle_Struct);
|
||||
IN(OP_LFGCommand, LFG_Struct);
|
||||
IN(OP_GMGoto, GMSummon_Struct);
|
||||
IN(OP_TraderShop, TraderClick_Struct);
|
||||
INv(OP_TraderShop, TraderClick_Struct);
|
||||
IN(OP_ShopRequest, Merchant_Click_Struct);
|
||||
IN(OP_Bazaar, BazaarSearch_Struct);
|
||||
//alt:IN(OP_Bazaar, BazaarWelcome_Struct); //alternate structure for OP_Bazaar
|
||||
@@ -399,7 +400,7 @@ OUT(OP_Weather, Weather_Struct);
|
||||
OUT(OP_ZoneChange, ZoneChange_Struct);
|
||||
OUT(OP_ZoneInUnknown, ZoneInUnknown_Struct);
|
||||
|
||||
//this is the set of opcodes which are allready listed
|
||||
//this is the set of opcodes which are already listed
|
||||
//in the IN section above, but are also sent OUT
|
||||
#ifdef DISJOINT_DIRECTIONS
|
||||
OUTz(OP_ClientReady); //follows OP_SetServerFilter
|
||||
@@ -449,7 +450,7 @@ OUT(OP_Trader, TraderBuy_Struct); //3 possible lengths
|
||||
//alt:OUT(OP_Trader, Trader_ShowItems_Struct);
|
||||
//alt:OUT(OP_Trader, Trader_Struct);
|
||||
OUT(OP_TraderBuy, TraderBuy_Struct);
|
||||
OUT(OP_TraderShop, TraderClick_Struct);
|
||||
OUTv(OP_TraderShop, TraderClick_Struct);
|
||||
OUT(OP_WearChange, WearChange_Struct);
|
||||
OUT(OP_ZoneEntry, ServerZoneEntry_Struct);
|
||||
#endif
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -89,6 +90,54 @@ void DumpPacketHex(const uchar* buf, uint32 size, uint32 cols, uint32 skip) {
|
||||
safe_delete_array(ascii);
|
||||
}
|
||||
|
||||
std::string DumpPacketHexToString(const uchar* buf, uint32 size, uint32 cols, uint32 skip) {
|
||||
std::ostringstream out;
|
||||
if (size == 0 || size > 39565)
|
||||
return "";
|
||||
|
||||
out << "\n";
|
||||
|
||||
// Output as HEX
|
||||
char output[4];
|
||||
int j = 0;
|
||||
char* ascii = new char[cols + 1];
|
||||
memset(ascii, 0, cols + 1);
|
||||
uint32 i;
|
||||
for (i = skip; i < size; i++)
|
||||
{
|
||||
if ((i - skip) % cols == 0) {
|
||||
if (i != skip)
|
||||
out << " | " << ascii << std::endl;
|
||||
out << std::setw(4) << std::setfill(' ') << i - skip << ": ";
|
||||
memset(ascii, 0, cols + 1);
|
||||
j = 0;
|
||||
}
|
||||
else if ((i - skip) % (cols / 2) == 0) {
|
||||
out << "- ";
|
||||
}
|
||||
sprintf(output, "%02X ", (unsigned char)buf[i]);
|
||||
out << output;
|
||||
|
||||
if (buf[i] >= 32 && buf[i] < 127) {
|
||||
ascii[j++] = buf[i];
|
||||
}
|
||||
else {
|
||||
ascii[j++] = '.';
|
||||
}
|
||||
// std::cout << std::setfill(0) << std::setw(2) << std::hex << (int)buf[i] << " "; // unknown intent [CODEBUG]
|
||||
}
|
||||
uint32 k = ((i - skip) - 1) % cols;
|
||||
if (k < 8)
|
||||
out << " ";
|
||||
for (uint32 h = k + 1; h < cols; h++) {
|
||||
out << " ";
|
||||
}
|
||||
out << " | " << ascii << std::endl;
|
||||
safe_delete_array(ascii);
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
void DumpPacket(const uchar* buf, uint32 size)
|
||||
{
|
||||
DumpPacketHex(buf, size);
|
||||
|
||||
@@ -24,6 +24,7 @@ class ServerPacket;
|
||||
|
||||
void DumpPacketAscii(const uchar* buf, uint32 size, uint32 cols=16, uint32 skip=0);
|
||||
void DumpPacketHex(const uchar* buf, uint32 size, uint32 cols=16, uint32 skip=0);
|
||||
std::string DumpPacketHexToString(const uchar* buf, uint32 size, uint32 cols = 16, uint32 skip = 0);
|
||||
void DumpPacketBin(const void* data, uint32 len);
|
||||
void DumpPacket(const uchar* buf, uint32 size);
|
||||
void DumpPacket(const ServerPacket* pack, bool iShowInfo = false);
|
||||
|
||||
+476
-250
File diff suppressed because it is too large
Load Diff
+638
-280
File diff suppressed because it is too large
Load Diff
@@ -103,6 +103,8 @@ namespace RoF2 {
|
||||
}
|
||||
|
||||
namespace consts {
|
||||
static const size_t CHARACTER_CREATION_LIMIT = 12;
|
||||
|
||||
static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount;
|
||||
static const uint16 MAP_BANK_SIZE = 24;
|
||||
static const uint16 MAP_SHARED_BANK_SIZE = 2;
|
||||
@@ -178,9 +180,10 @@ namespace RoF2 {
|
||||
static const uint16 ITEM_COMMON_SIZE = 6;
|
||||
static const uint16 ITEM_CONTAINER_SIZE = 255; // 255; (server max will be 255..unsure what actual client is - test)
|
||||
|
||||
static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 5;
|
||||
static const size_t BANDOLIERS_SIZE = 20; // number of bandolier instances
|
||||
static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance
|
||||
|
||||
static const size_t POTION_BELT_ITEM_COUNT = 5;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 56;
|
||||
}
|
||||
|
||||
@@ -2,10 +2,14 @@
|
||||
// Begin RoF2 Encodes
|
||||
|
||||
E(OP_SendMembershipDetails)
|
||||
E(OP_TraderShop)
|
||||
E(OP_TraderDelItem)
|
||||
|
||||
// incoming packets that require a DECODE translation:
|
||||
// Begin RoF2 Decodes
|
||||
|
||||
D(OP_TraderShop)
|
||||
|
||||
// End RoF2 Encodes/Decodes
|
||||
|
||||
// These require Encodes/Decodes for RoF, so they do for RoF2 as well
|
||||
@@ -53,6 +57,7 @@ E(OP_GroupFollow)
|
||||
E(OP_GroupFollow2)
|
||||
E(OP_GroupInvite)
|
||||
E(OP_GroupUpdate)
|
||||
E(OP_GuildBank)
|
||||
E(OP_GuildMemberList)
|
||||
E(OP_GuildMemberUpdate)
|
||||
E(OP_GuildsList)
|
||||
@@ -107,6 +112,7 @@ E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
E(OP_TributeInfo)
|
||||
E(OP_TributeItem)
|
||||
E(OP_VetClaimReply)
|
||||
E(OP_VetRewardsAvaliable)
|
||||
E(OP_WearChange)
|
||||
E(OP_WhoAllResponse)
|
||||
@@ -119,6 +125,7 @@ E(OP_ZoneSpawns)
|
||||
D(OP_AdventureMerchantSell)
|
||||
D(OP_AltCurrencySell)
|
||||
D(OP_AltCurrencySellSelection)
|
||||
D(OP_Animation)
|
||||
D(OP_ApplyPoison)
|
||||
D(OP_AugmentInfo)
|
||||
D(OP_AugmentItem)
|
||||
@@ -146,6 +153,7 @@ D(OP_GroupFollow)
|
||||
D(OP_GroupFollow2)
|
||||
D(OP_GroupInvite)
|
||||
D(OP_GroupInvite2)
|
||||
D(OP_GuildBank)
|
||||
D(OP_GuildDemote)
|
||||
D(OP_GuildRemove)
|
||||
D(OP_GuildStatus)
|
||||
@@ -170,6 +178,7 @@ D(OP_Trader)
|
||||
D(OP_TraderBuy)
|
||||
D(OP_TradeSkillCombine)
|
||||
D(OP_TributeItem)
|
||||
D(OP_VetClaimRequest)
|
||||
D(OP_WhoAllRequest)
|
||||
D(OP_ZoneChange)
|
||||
D(OP_ZoneEntry)
|
||||
|
||||
+363
-184
@@ -97,11 +97,6 @@ static const uint32 MAX_PLAYER_TRIBUTES = 5;
|
||||
static const uint32 MAX_TRIBUTE_TIERS = 10;
|
||||
static const uint32 TRIBUTE_NONE = 0xFFFFFFFF;
|
||||
|
||||
static const uint32 MAX_PLAYER_BANDOLIER = 20;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER_ITEMS = 4;
|
||||
|
||||
static const uint32 MAX_POTIONS_IN_BELT = 5;
|
||||
|
||||
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
|
||||
static const uint32 MAX_RAID_LEADERSHIP_AA_ARRAY = 16;
|
||||
static const uint32 MAX_LEADERSHIP_AA_ARRAY = (MAX_GROUP_LEADERSHIP_AA_ARRAY+MAX_RAID_LEADERSHIP_AA_ARRAY);
|
||||
@@ -114,7 +109,7 @@ static const uint32 MAX_PP_SPELLBOOK = 720; // was 480
|
||||
static const uint32 MAX_PP_MEMSPELL = 16; // was 12
|
||||
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
|
||||
static const uint32 MAX_PP_AA_ARRAY = 300;
|
||||
static const uint32 MAX_PP_DISCIPLINES = 200; // was 100
|
||||
static const uint32 MAX_PP_DISCIPLINES = 300; // was 200
|
||||
static const uint32 MAX_GROUP_MEMBERS = 6;
|
||||
static const uint32 MAX_RECAST_TYPES = 20;
|
||||
|
||||
@@ -147,84 +142,87 @@ struct AdventureInfo {
|
||||
*/
|
||||
struct Color_Struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 blue;
|
||||
uint8 green;
|
||||
uint8 red;
|
||||
uint8 use_tint; // if there's a tint this is FF
|
||||
} rgb;
|
||||
uint32 color;
|
||||
union {
|
||||
struct {
|
||||
uint8 Blue;
|
||||
uint8 Green;
|
||||
uint8 Red;
|
||||
uint8 UseTint; // if there's a tint this is FF
|
||||
} RGB;
|
||||
uint32 Color;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Visible equiptment.
|
||||
* Size: 20 Octets
|
||||
*/
|
||||
struct EquipStruct {
|
||||
/*00*/ uint32 material;
|
||||
/*04*/ uint32 unknown1;
|
||||
/*08*/ uint32 elitematerial;
|
||||
/*12*/ uint32 heroforgemodel;
|
||||
/*16*/ uint32 material2; // Same as material?
|
||||
/*20*/
|
||||
struct CharSelectEquip
|
||||
{
|
||||
uint32 Material;
|
||||
uint32 Unknown1;
|
||||
uint32 EliteMaterial;
|
||||
uint32 HeroForgeModel;
|
||||
uint32 Material2;
|
||||
Color_Struct Color;
|
||||
};
|
||||
|
||||
struct CharSelectEquip {
|
||||
uint32 material;
|
||||
uint32 unknown1;
|
||||
uint32 elitematerial;
|
||||
uint32 heroforgemodel;
|
||||
uint32 material2;
|
||||
Color_Struct color;
|
||||
};
|
||||
|
||||
struct CharacterSelectEntry_Struct {
|
||||
/*0000*/ char name[1]; // Name null terminated
|
||||
/*0000*/ uint8 class_;
|
||||
/*0000*/ uint32 race;
|
||||
/*0000*/ uint8 level;
|
||||
/*0000*/ uint8 class_2;
|
||||
/*0000*/ uint32 race2;
|
||||
/*0000*/ uint16 zone;
|
||||
/*0000*/ uint16 instance;
|
||||
/*0000*/ uint8 gender;
|
||||
/*0000*/ uint8 face;
|
||||
/*0000*/ CharSelectEquip equip[9];
|
||||
/*0000*/ uint8 u15; // Seen FF
|
||||
/*0000*/ uint8 u19; // Seen FF
|
||||
/*0000*/ uint32 drakkin_tattoo;
|
||||
/*0000*/ uint32 drakkin_details;
|
||||
/*0000*/ uint32 deity;
|
||||
/*0000*/ uint32 primary;
|
||||
/*0000*/ uint32 secondary;
|
||||
/*0000*/ uint8 haircolor;
|
||||
/*0000*/ uint8 beardcolor;
|
||||
/*0000*/ uint8 eyecolor1;
|
||||
/*0000*/ uint8 eyecolor2;
|
||||
/*0000*/ uint8 hairstyle;
|
||||
/*0000*/ uint8 beard;
|
||||
/*0000*/ uint8 char_enabled;
|
||||
/*0000*/ uint8 tutorial; // Seen 1 for new char or 0 for existing
|
||||
/*0000*/ uint32 drakkin_heritage;
|
||||
/*0000*/ uint8 unknown1; // Seen 0
|
||||
/*0000*/ uint8 gohome; // Seen 0 for new char and 1 for existing
|
||||
struct CharacterSelectEntry_Struct
|
||||
{
|
||||
/*0000*/ char Name[1]; // Name null terminated
|
||||
/*0000*/ uint8 Class;
|
||||
/*0000*/ uint32 Race;
|
||||
/*0000*/ uint8 Level;
|
||||
/*0000*/ uint8 ShroudClass;
|
||||
/*0000*/ uint32 ShroudRace;
|
||||
/*0000*/ uint16 Zone;
|
||||
/*0000*/ uint16 Instance;
|
||||
/*0000*/ uint8 Gender;
|
||||
/*0000*/ uint8 Face;
|
||||
/*0000*/ CharSelectEquip Equip[9];
|
||||
/*0000*/ uint8 Unknown15; // Seen FF
|
||||
/*0000*/ uint8 Unknown19; // Seen FF
|
||||
/*0000*/ uint32 DrakkinTattoo;
|
||||
/*0000*/ uint32 DrakkinDetails;
|
||||
/*0000*/ uint32 Deity;
|
||||
/*0000*/ uint32 PrimaryIDFile;
|
||||
/*0000*/ uint32 SecondaryIDFile;
|
||||
/*0000*/ uint8 HairColor;
|
||||
/*0000*/ uint8 BeardColor;
|
||||
/*0000*/ uint8 EyeColor1;
|
||||
/*0000*/ uint8 EyeColor2;
|
||||
/*0000*/ uint8 HairStyle;
|
||||
/*0000*/ uint8 Beard;
|
||||
/*0000*/ uint8 GoHome; // Seen 0 for new char and 1 for existing
|
||||
/*0000*/ uint8 Tutorial; // Seen 1 for new char or 0 for existing
|
||||
/*0000*/ uint32 DrakkinHeritage;
|
||||
/*0000*/ uint8 Unknown1; // Seen 0
|
||||
/*0000*/ uint8 Enabled; // Swapped position with 'GoHome' 02/23/2015
|
||||
/*0000*/ uint32 LastLogin;
|
||||
/*0000*/ uint8 unknown2; // Seen 0
|
||||
/*0000*/ uint8 Unknown2; // Seen 0
|
||||
};
|
||||
|
||||
/*
|
||||
** Character Selection Struct
|
||||
**
|
||||
*/
|
||||
struct CharacterSelect_Struct {
|
||||
/*000*/ uint32 char_count; //number of chars in this packet
|
||||
/*004*/ CharacterSelectEntry_Struct entries[0];
|
||||
struct CharacterSelect_Struct
|
||||
{
|
||||
/*000*/ uint32 CharCount; //number of chars in this packet
|
||||
/*004*/ CharacterSelectEntry_Struct Entries[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* Visible equiptment.
|
||||
* Size: 20 Octets
|
||||
*/
|
||||
struct EquipStruct
|
||||
{
|
||||
/*00*/ uint32 Material;
|
||||
/*04*/ uint32 Unknown1;
|
||||
/*08*/ uint32 EliteMaterial;
|
||||
/*12*/ uint32 HeroForgeModel;
|
||||
/*16*/ uint32 Material2; // Same as material?
|
||||
/*20*/
|
||||
};
|
||||
|
||||
|
||||
struct Membership_Entry_Struct
|
||||
{
|
||||
/*000*/ uint32 purchase_id; // Seen 1, then increments 90287 to 90300
|
||||
@@ -418,7 +416,7 @@ struct Spawn_Struct
|
||||
/*0000*/ uint8 unknown12;
|
||||
/*0000*/ uint32 petOwnerId;
|
||||
/*0000*/ uint8 unknown13;
|
||||
/*0000*/ uint32 unknown14; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
/*0000*/ uint32 PlayerState; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
/*0000*/ uint32 unknown15;
|
||||
/*0000*/ uint32 unknown16;
|
||||
/*0000*/ uint32 unknown17;
|
||||
@@ -660,7 +658,10 @@ struct CastSpell_Struct
|
||||
/*04*/ uint32 spell_id;
|
||||
/*08*/ ItemSlotStruct inventoryslot; // slot for clicky item, Seen unknown of 131 = normal cast
|
||||
/*20*/ uint32 target_id;
|
||||
/*24*/ uint32 cs_unknown[5];
|
||||
/*24*/ uint32 cs_unknown[2];
|
||||
/*32*/ float y_pos;
|
||||
/*36*/ float x_pos;
|
||||
/*40*/ float z_pos;
|
||||
/*44*/
|
||||
};
|
||||
|
||||
@@ -686,7 +687,7 @@ struct SpellBuff_Struct
|
||||
/*005*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages
|
||||
/*009*/ uint32 unknown016;
|
||||
/*013*/ uint8 bard_modifier;
|
||||
/*014*/ uint32 duration;
|
||||
/*014*/ int32 duration;
|
||||
/*018*/ uint8 level;
|
||||
/*019*/ uint32 spellid;
|
||||
/*023*/ uint32 counters;
|
||||
@@ -702,7 +703,7 @@ struct SpellBuff_Struct_Old
|
||||
/*003*/ uint8 effect; // not real
|
||||
/*004*/ float unknown004; // Seen 1 for no buff
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 unknown016;
|
||||
/*020*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages
|
||||
/*024*/ uint32 counters;
|
||||
@@ -719,7 +720,7 @@ struct SpellBuffFade_Struct_Live {
|
||||
/*007*/ uint8 unknown007;
|
||||
/*008*/ float unknown008;
|
||||
/*012*/ uint32 spellid;
|
||||
/*016*/ uint32 duration;
|
||||
/*016*/ int32 duration;
|
||||
/*020*/ uint32 playerId; // Global player ID?
|
||||
/*024*/ uint32 num_hits;
|
||||
/*028*/ uint8 unknown0028[64];
|
||||
@@ -735,7 +736,7 @@ struct SpellBuffFade_Struct {
|
||||
/*006*/ uint8 effect;
|
||||
/*007*/ uint8 unknown7;
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 num_hits;
|
||||
/*020*/ uint32 unknown020; // Global player ID?
|
||||
/*024*/ uint32 playerId; // Player id who cast the buff
|
||||
@@ -876,7 +877,7 @@ struct AA_Array
|
||||
{
|
||||
uint32 AA;
|
||||
uint32 value;
|
||||
uint32 unknown08; // Looks like AA_Array is now 12 bytes in Live
|
||||
uint32 charges; // expendable charges
|
||||
};
|
||||
|
||||
struct Disciplines_Struct {
|
||||
@@ -896,38 +897,66 @@ struct Tribute_Struct {
|
||||
uint32 tier;
|
||||
};
|
||||
|
||||
struct BandolierItem_Struct {
|
||||
char item_name[1]; // Variable Length
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct_Old {
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
char item_name[64];
|
||||
};
|
||||
|
||||
//len = 320
|
||||
enum { //bandolier item positions
|
||||
bandolierMainHand = 0,
|
||||
bandolierOffHand,
|
||||
// Bandolier item positions
|
||||
enum
|
||||
{
|
||||
bandolierPrimary = 0,
|
||||
bandolierSecondary,
|
||||
bandolierRange,
|
||||
bandolierAmmo
|
||||
};
|
||||
struct Bandolier_Struct {
|
||||
char name[1]; // Variable Length
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
|
||||
struct BandolierItem_Struct
|
||||
{
|
||||
char Name[1]; // Variable Length
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
};
|
||||
|
||||
struct Bandolier_Struct_Old {
|
||||
char name[32];
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
//len = 72
|
||||
struct BandolierItem_Struct_Old
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
struct PotionBelt_Struct {
|
||||
BandolierItem_Struct items[MAX_POTIONS_IN_BELT];
|
||||
//len = 320
|
||||
struct Bandolier_Struct
|
||||
{
|
||||
char Name[1]; // Variable Length
|
||||
BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct Bandolier_Struct_Old
|
||||
{
|
||||
char Name[32];
|
||||
BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct PotionBeltItem_Struct
|
||||
{
|
||||
char Name[1]; // Variable Length
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct PotionBeltItem_Struct_Old
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
struct PotionBelt_Struct
|
||||
{
|
||||
PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct PotionBelt_Struct_Old
|
||||
{
|
||||
PotionBeltItem_Struct_Old Items[consts::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct GroupLeadershipAA_Struct {
|
||||
@@ -1137,7 +1166,7 @@ union
|
||||
/*12949*/ uint32 aapoints; // Unspent AA points - Seen 1
|
||||
/*12953*/ uint16 unknown_rof20; //
|
||||
/*12955*/ uint32 bandolier_count; // Seen 20
|
||||
/*12959*/ Bandolier_Struct bandoliers[MAX_PLAYER_BANDOLIER]; // [20] 740 bytes (Variable Name Sizes) - bandolier contents
|
||||
/*12959*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // [20] 740 bytes (Variable Name Sizes) - bandolier contents
|
||||
/*13699*/ uint32 potionbelt_count; // Seen 5
|
||||
/*13703*/ PotionBelt_Struct potionbelt; // [5] 45 bytes potion belt - (Variable Name Sizes)
|
||||
/*13748*/ int32 unknown_rof21; // Seen -1
|
||||
@@ -1264,7 +1293,7 @@ struct TargetReject_Struct {
|
||||
|
||||
struct PetCommand_Struct {
|
||||
/*00*/ uint32 command;
|
||||
/*04*/ uint32 unknown04;
|
||||
/*04*/ uint32 target;
|
||||
/*08*/ uint32 unknown08;
|
||||
};
|
||||
|
||||
@@ -1389,8 +1418,8 @@ struct RequestClientZoneChange_Struct {
|
||||
|
||||
struct Animation_Struct {
|
||||
/*00*/ uint16 spawnid;
|
||||
/*02*/ uint8 value;
|
||||
/*03*/ uint8 action;
|
||||
/*02*/ uint8 action;
|
||||
/*03*/ uint8 speed;
|
||||
/*04*/
|
||||
};
|
||||
|
||||
@@ -1455,9 +1484,11 @@ struct CombatDamage_Struct
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||
/* 05 */ uint32 spellid;
|
||||
/* 09 */ int32 damage;
|
||||
/* 13 */ float unknown11; // cd cc cc 3d
|
||||
/* 17 */ float sequence; // see above notes in Action_Struct
|
||||
/* 21 */ uint8 unknown19[9]; // was [9]
|
||||
/* 13 */ float force; // cd cc cc 3d
|
||||
/* 17 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 21 */ float meleepush_z;
|
||||
/* 25 */ uint8 unknown25; // was [9]
|
||||
/* 26 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
|
||||
/* 30 */
|
||||
};
|
||||
|
||||
@@ -1828,6 +1859,114 @@ struct GuildUpdate_Struct {
|
||||
GuildsListEntry_Struct entry;
|
||||
};
|
||||
|
||||
struct GuildBankAck_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; // 10
|
||||
/*04*/ uint32 Unknown04;
|
||||
/*08*/ uint32 Unknown08;
|
||||
};
|
||||
|
||||
struct GuildBankDepositAck_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; // 10
|
||||
/*04*/ uint32 Unknown04;
|
||||
/*08*/ uint32 Unknown08;
|
||||
/*08*/ uint32 Fail; //1 = Fail, 0 = Success
|
||||
};
|
||||
|
||||
struct GuildBankPromote_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; // 3
|
||||
/*04*/ uint32 Unknown04;
|
||||
/*08*/ uint32 Unknown08;
|
||||
/*12*/ uint32 Slot;
|
||||
/*16*/ uint32 Slot2; // Always appears to be the same as Slot for Action code 3
|
||||
/*20*/ uint32 unknown20;
|
||||
};
|
||||
|
||||
struct GuildBankPermissions_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; // 6
|
||||
/*04*/ uint32 Unknown04;
|
||||
/*08*/ uint32 Unknown08;
|
||||
/*08*/ uint16 SlotID;
|
||||
/*10*/ uint16 Unknown10; // Saw 1, probably indicating it is the main area rather than deposits
|
||||
/*12*/ uint32 ItemID;
|
||||
/*16*/ uint32 Permissions;
|
||||
/*20*/ char MemberName[64];
|
||||
};
|
||||
|
||||
struct GuildBankViewItem_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint32 Unknown04;
|
||||
/*08*/ uint32 Unknown08;
|
||||
/*08*/ uint16 SlotID; // 0 = Deposit area, 1 = Main area
|
||||
/*10*/ uint16 Area;
|
||||
/*12*/ uint32 Unknown12;
|
||||
/*16*/ uint32 Unknown16;
|
||||
};
|
||||
|
||||
struct GuildBankWithdrawItem_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint32 Unknown04;
|
||||
/*08*/ uint32 Unknown08;
|
||||
/*08*/ uint16 SlotID;
|
||||
/*10*/ uint16 Area;
|
||||
/*12*/ uint32 Unknown12;
|
||||
/*16*/ uint32 Quantity;
|
||||
/*20*/
|
||||
};
|
||||
|
||||
struct GuildBankItemUpdate_Struct
|
||||
{
|
||||
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
|
||||
uint32 inPermissions, uint32 inAllowMerge, bool inUseable)
|
||||
{
|
||||
Action = inAction;
|
||||
Unknown004 = inUnknown004;
|
||||
SlotID = inSlotID;
|
||||
Area = inArea;
|
||||
Unknown012 = inUnknown012;
|
||||
ItemID = inItemID;
|
||||
Icon = inIcon;
|
||||
Quantity = inQuantity;
|
||||
Permissions = inPermissions;
|
||||
AllowMerge = inAllowMerge;
|
||||
Useable = inUseable;
|
||||
ItemName[0] = '\0';
|
||||
Donator[0] = '\0';
|
||||
WhoFor[0] = '\0';
|
||||
};
|
||||
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*008*/ uint32 Unknown08;
|
||||
/*012*/ uint16 SlotID;
|
||||
/*014*/ uint16 Area;
|
||||
/*016*/ uint32 Unknown012;
|
||||
/*020*/ uint32 ItemID;
|
||||
/*024*/ uint32 Icon;
|
||||
/*028*/ uint32 Quantity;
|
||||
/*032*/ uint32 Permissions;
|
||||
/*036*/ uint8 AllowMerge;
|
||||
/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission.
|
||||
/*038*/ char ItemName[64];
|
||||
/*102*/ char Donator[64];
|
||||
/*166*/ char WhoFor[64];
|
||||
/*230*/ uint16 Unknown226;
|
||||
};
|
||||
|
||||
struct GuildBankClear_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint32 Unknown04;
|
||||
/*08*/ uint32 Unknown08;
|
||||
/*12*/ uint32 DepositAreaCount;
|
||||
/*16*/ uint32 MainAreaCount;
|
||||
};
|
||||
|
||||
/*
|
||||
** Money Loot
|
||||
** Length: 22 Bytes
|
||||
@@ -2443,7 +2582,7 @@ struct GroupFollow_Struct { // Live Follow Struct
|
||||
|
||||
struct InspectBuffs_Struct {
|
||||
/*000*/ uint32 spell_id[BUFF_COUNT];
|
||||
/*168*/ uint32 tics_remaining[BUFF_COUNT];
|
||||
/*168*/ int32 tics_remaining[BUFF_COUNT];
|
||||
};
|
||||
|
||||
struct LFG_Struct {
|
||||
@@ -2865,7 +3004,7 @@ struct SetRunMode_Struct {
|
||||
};
|
||||
|
||||
// EnvDamage is EnvDamage2 without a few bytes at the end.
|
||||
// Size: 37 bytes
|
||||
// Size: 39 bytes
|
||||
struct EnvDamage2_Struct {
|
||||
/*0000*/ uint32 id;
|
||||
/*0004*/ uint16 unknown4;
|
||||
@@ -2877,7 +3016,8 @@ struct EnvDamage2_Struct {
|
||||
/*0031*/ uint16 unknown31; // New to Underfoot - Seen 66
|
||||
/*0033*/ uint16 constant; // Always FFFF
|
||||
/*0035*/ uint16 unknown35;
|
||||
/*0037*/
|
||||
/*0037*/ uint16 unknown37;
|
||||
/*0039*/
|
||||
};
|
||||
|
||||
//Bazaar Stuff
|
||||
@@ -2913,10 +3053,12 @@ struct BazaarWindowStart_Struct {
|
||||
|
||||
|
||||
struct BazaarWelcome_Struct {
|
||||
BazaarWindowStart_Struct Beginning;
|
||||
uint32 Traders;
|
||||
uint32 Items;
|
||||
uint8 Unknown012[8];
|
||||
uint32 Code;
|
||||
uint32 EntityID;
|
||||
uint32 Traders;
|
||||
uint32 Items;
|
||||
uint32 Traders2;
|
||||
uint32 Items2;
|
||||
};
|
||||
|
||||
struct BazaarSearch_Struct {
|
||||
@@ -3199,6 +3341,13 @@ struct BecomeTrader_Struct {
|
||||
};
|
||||
|
||||
struct Trader_ShowItems_Struct {
|
||||
/*000*/ uint32 Code;
|
||||
/*004*/ uint16 TraderID;
|
||||
/*008*/ uint32 Unknown08;
|
||||
/*012*/
|
||||
};
|
||||
|
||||
struct Trader_ShowItems_Struct_WIP {
|
||||
/*000*/ uint32 Code;
|
||||
/*004*/ char SerialNumber[17];
|
||||
/*021*/ uint8 Unknown21;
|
||||
@@ -3216,6 +3365,26 @@ struct TraderStatus_Struct {
|
||||
};
|
||||
|
||||
struct TraderBuy_Struct {
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*008*/ uint32 Unknown008;
|
||||
/*012*/ uint32 Unknown012;
|
||||
/*016*/ uint32 TraderID;
|
||||
/*020*/ char BuyerName[64];
|
||||
/*084*/ char SellerName[64];
|
||||
/*148*/ char Unknown148[32];
|
||||
/*180*/ char ItemName[64];
|
||||
/*244*/ char SerialNumber[16];
|
||||
/*260*/ uint32 Unknown076;
|
||||
/*264*/ uint32 ItemID;
|
||||
/*268*/ uint32 Price;
|
||||
/*272*/ uint32 AlreadySold;
|
||||
/*276*/ uint32 Unknown276;
|
||||
/*280*/ uint32 Quantity;
|
||||
/*284*/
|
||||
};
|
||||
|
||||
struct TraderBuy_Struct_OLD {
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*008*/ uint32 Price;
|
||||
@@ -3245,25 +3414,19 @@ struct MoneyUpdate_Struct{
|
||||
int32 copper;
|
||||
};
|
||||
|
||||
//struct MoneyUpdate_Struct
|
||||
//{
|
||||
//*0000*/ uint32 spawn_id; // ***Placeholder
|
||||
//*0004*/ uint32 cointype; // Coin Type
|
||||
//*0008*/ uint32 amount; // Amount
|
||||
//*0012*/
|
||||
//};
|
||||
|
||||
|
||||
struct TraderDelItem_Struct{
|
||||
uint32 slotid;
|
||||
uint32 quantity;
|
||||
uint32 unknown;
|
||||
/*000*/ uint32 Unknown000;
|
||||
/*004*/ uint32 TraderID;
|
||||
/*008*/ char SerialNumber[16];
|
||||
/*024*/ uint32 Unknown012;
|
||||
/*028*/
|
||||
};
|
||||
|
||||
struct TraderClick_Struct{
|
||||
uint32 traderid;
|
||||
uint32 unknown4[2];
|
||||
uint32 approval;
|
||||
/*000*/ uint32 Code;
|
||||
/*004*/ uint32 TraderID;
|
||||
/*008*/ uint32 Approval;
|
||||
/*012*/
|
||||
};
|
||||
|
||||
struct FormattedMessage_Struct{
|
||||
@@ -3566,7 +3729,7 @@ struct Split_Struct
|
||||
*/
|
||||
struct NewCombine_Struct {
|
||||
/*00*/ ItemSlotStruct container_slot;
|
||||
/*12*/ ItemSlotStruct guildtribute_slot; // Slot type is 8? (MapGuildTribute = 8 -U)
|
||||
/*12*/ ItemSlotStruct guildtribute_slot; // Slot type is 8? (MapGuildTribute = 8)
|
||||
/*24*/
|
||||
};
|
||||
|
||||
@@ -4087,30 +4250,35 @@ struct DynamicWall_Struct {
|
||||
/*80*/
|
||||
};
|
||||
|
||||
enum { //bandolier actions
|
||||
BandolierCreate = 0,
|
||||
BandolierRemove = 1,
|
||||
BandolierSet = 2
|
||||
// Bandolier actions
|
||||
enum
|
||||
{
|
||||
bandolierCreate = 0,
|
||||
bandolierRemove,
|
||||
bandolierSet
|
||||
};
|
||||
|
||||
struct BandolierCreate_Struct {
|
||||
/*00*/ uint32 action; //0 for create
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ char name[32];
|
||||
/*37*/ uint16 unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 unknown39; //0
|
||||
struct BandolierCreate_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; //0 for create
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ char Name[32];
|
||||
/*37*/ uint16 Unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 Unknown39; //0
|
||||
};
|
||||
|
||||
struct BandolierDelete_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierDelete_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct BandolierSet_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierSet_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct Arrow_Struct {
|
||||
@@ -4131,9 +4299,11 @@ struct Arrow_Struct {
|
||||
/*068*/ uint8 unknown068;
|
||||
/*069*/ uint8 unknown069;
|
||||
/*070*/ uint8 unknown070;
|
||||
/*071*/ uint8 item_type;
|
||||
/*072*/ uint8 skill;
|
||||
/*073*/ uint8 unknown073[16];
|
||||
/*071*/ uint8 unknown071;
|
||||
/*072*/ uint8 unknown072;
|
||||
/*073*/ uint8 skill;
|
||||
/*074*/ uint8 item_type;
|
||||
/*075*/ uint8 unknown075[14];
|
||||
/*089*/ char model_name[27];
|
||||
/*116*/
|
||||
};
|
||||
@@ -4192,9 +4362,9 @@ struct SendAA_Struct {
|
||||
/*0025*/ uint32 cost;
|
||||
/*0029*/ uint32 seq;
|
||||
/*0033*/ uint32 current_level; //1s, MQ2 calls this AARankRequired
|
||||
/*0037*/ uint32 unknown037; // Introduced during HoT
|
||||
/*0037*/ uint32 prereq_skill_count; // mutliple prereqs at least 1, even no prereqs
|
||||
/*0041*/ uint32 prereq_skill; //is < 0, abs() is category #
|
||||
/*0045*/ uint32 unknown045; // New Mar 21 2012 - Seen 1
|
||||
/*0045*/ uint32 prereq_minpoints_count; // mutliple prereqs at least 1, even no prereqs
|
||||
/*0049*/ uint32 prereq_minpoints; //min points in the prereq
|
||||
/*0053*/ uint32 type;
|
||||
/*0057*/ uint32 spellid;
|
||||
@@ -4207,10 +4377,16 @@ struct SendAA_Struct {
|
||||
/*0081*/ uint32 last_id;
|
||||
/*0085*/ uint32 next_id;
|
||||
/*0089*/ uint32 cost2;
|
||||
/*0093*/ uint8 unknown80[7];
|
||||
/*0093*/ uint8 unknown93;
|
||||
/*0094*/ uint8 grant_only; // VetAAs, progression, etc
|
||||
/*0095*/ uint8 unknown95; // 1 for skill cap increase AAs, Mystical Attuning, and RNG attack inc, doesn't seem to matter though
|
||||
/*0096*/ uint32 expendable_charges; // max charges of the AA
|
||||
/*0100*/ uint32 aa_expansion;
|
||||
/*0104*/ uint32 special_category;
|
||||
/*0108*/ uint32 unknown0096;
|
||||
/*0108*/ uint8 shroud;
|
||||
/*0109*/ uint8 unknown109;
|
||||
/*0110*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter?
|
||||
/*0111*/ uint8 unknown111;
|
||||
/*0112*/ uint32 total_abilities;
|
||||
/*0116*/ AA_Ability abilities[0];
|
||||
};
|
||||
@@ -4222,17 +4398,11 @@ struct AA_List {
|
||||
struct AA_Action {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint32 ability;
|
||||
/*08*/ uint32 unknown08;
|
||||
/*08*/ uint32 target_id;
|
||||
/*12*/ uint32 exp_value;
|
||||
/*16*/
|
||||
};
|
||||
|
||||
struct AA_Skills { //this should be removed and changed to AA_Array
|
||||
/*00*/ uint32 aa_skill; // Total AAs Spent
|
||||
/*04*/ uint32 aa_value;
|
||||
/*08*/ uint32 unknown08;
|
||||
/*12*/
|
||||
};
|
||||
|
||||
struct AAExpUpdate_Struct {
|
||||
/*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability
|
||||
@@ -4252,14 +4422,7 @@ struct AltAdvStats_Struct {
|
||||
};
|
||||
|
||||
struct PlayerAA_Struct { // Is this still used?
|
||||
AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AA_Values {
|
||||
/*00*/ uint32 aa_skill;
|
||||
/*04*/ uint32 aa_value;
|
||||
/*08*/ uint32 unknown08;
|
||||
/*12*/
|
||||
AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AATable_Struct {
|
||||
@@ -4269,7 +4432,7 @@ struct AATable_Struct {
|
||||
/*12*/ uint32 aa_spent_archetype; // Seen 40
|
||||
/*16*/ uint32 aa_spent_class; // Seen 103
|
||||
/*20*/ uint32 aa_spent_special; // Seen 0
|
||||
/*24*/ AA_Values aa_list[MAX_PP_AA_ARRAY];
|
||||
/*24*/ AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct Weather_Struct {
|
||||
@@ -4352,7 +4515,7 @@ struct RoF2SlotStruct
|
||||
|
||||
struct ItemSerializationHeader
|
||||
{
|
||||
/*000*/ char unknown000[13]; // New for HoT. Looks like a string.
|
||||
/*000*/ char unknown000[17]; // New for HoT. Looks like a string.
|
||||
/*017*/ uint32 stacksize;
|
||||
/*021*/ uint32 unknown004;
|
||||
/*025*/ uint8 slot_type; // 0 = normal, 1 = bank, 2 = shared bank, 9 = merchant, 20 = ?
|
||||
@@ -4497,7 +4660,7 @@ struct ItemSecondaryBodyStruct
|
||||
uint32 augtype;
|
||||
// swapped augrestrict and augdistiller positions
|
||||
// (this swap does show the proper augment restrictions in Item Information window now)
|
||||
// unsure what the purpose of augdistiller is at this time -U 3/17/2014
|
||||
// unsure what the purpose of augdistiller is at this time 3/17/2014
|
||||
int32 augrestrict2; // New to December 10th 2012 client - Hidden Aug Restriction
|
||||
uint32 augrestrict;
|
||||
AugSlotStruct augslots[6];
|
||||
@@ -4569,7 +4732,7 @@ struct ClickEffectStruct
|
||||
|
||||
struct ProcEffectStruct
|
||||
{
|
||||
uint32 effect;
|
||||
int32 effect;
|
||||
uint8 level2;
|
||||
uint32 type;
|
||||
uint8 level;
|
||||
@@ -4584,7 +4747,7 @@ struct ProcEffectStruct
|
||||
|
||||
struct WornEffectStruct //worn, focus and scroll effect
|
||||
{
|
||||
uint32 effect;
|
||||
int32 effect;
|
||||
uint8 level2;
|
||||
uint32 type;
|
||||
uint8 level;
|
||||
@@ -4672,17 +4835,33 @@ struct AugmentInfo_Struct
|
||||
|
||||
struct VeteranRewardItem
|
||||
{
|
||||
/*000*/ uint32 item_id;
|
||||
/*004*/ uint32 charges;
|
||||
/*008*/ char item_name[64];
|
||||
/*000*/ uint32 name_length;
|
||||
/*004*/ //char item_name[0]; // THIS IS NOT NULL TERMED
|
||||
/*???*/ uint32 item_id;
|
||||
/*???*/ uint32 charges;
|
||||
};
|
||||
|
||||
struct VeteranRewardEntry
|
||||
{
|
||||
/*000*/ uint32 claim_id; // guessed
|
||||
/*004*/ uint32 avaliable_count;
|
||||
/*008*/ uint32 claim_count;
|
||||
/*012*/ char enabled;
|
||||
/*013*/ //VeteranRewardItem items[0];
|
||||
};
|
||||
|
||||
struct VeteranReward
|
||||
{
|
||||
/*000*/ uint32 claim_id;
|
||||
/*004*/ uint32 number_available;
|
||||
/*008*/ uint32 claim_count;
|
||||
/*012*/ VeteranRewardItem items[8];
|
||||
/*000*/ uint32 claim_count;
|
||||
/*004*/ //VeteranRewardEntry entries[0];
|
||||
};
|
||||
|
||||
struct VeteranClaim
|
||||
{
|
||||
/*000*/ char name[68]; //name + other data
|
||||
/*068*/ uint32 claim_id;
|
||||
/*072*/ uint32 unknown072;
|
||||
/*076*/ uint32 action;
|
||||
};
|
||||
|
||||
struct ExpeditionEntryHeader_Struct
|
||||
|
||||
@@ -102,6 +102,8 @@ namespace RoF {
|
||||
}
|
||||
|
||||
namespace consts {
|
||||
static const size_t CHARACTER_CREATION_LIMIT = 12;
|
||||
|
||||
static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount;
|
||||
static const uint16 MAP_BANK_SIZE = 24;
|
||||
static const uint16 MAP_SHARED_BANK_SIZE = 2;
|
||||
@@ -177,9 +179,10 @@ namespace RoF {
|
||||
static const uint16 ITEM_COMMON_SIZE = 6;
|
||||
static const uint16 ITEM_CONTAINER_SIZE = 255; // 255; (server max will be 255..unsure what actual client is - test)
|
||||
|
||||
static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 5;
|
||||
static const size_t BANDOLIERS_SIZE = 20; // number of bandolier instances
|
||||
static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance
|
||||
|
||||
static const size_t POTION_BELT_ITEM_COUNT = 5;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 55;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ E(OP_GroupFollow)
|
||||
E(OP_GroupFollow2)
|
||||
E(OP_GroupInvite)
|
||||
E(OP_GroupUpdate)
|
||||
E(OP_GuildBank)
|
||||
E(OP_GuildMemberList)
|
||||
E(OP_GuildMemberUpdate)
|
||||
E(OP_GuildsList)
|
||||
@@ -96,6 +97,7 @@ E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
E(OP_TributeInfo)
|
||||
E(OP_TributeItem)
|
||||
E(OP_VetClaimReply)
|
||||
E(OP_VetRewardsAvaliable)
|
||||
E(OP_WearChange)
|
||||
E(OP_WhoAllResponse)
|
||||
@@ -108,6 +110,7 @@ E(OP_ZoneSpawns)
|
||||
D(OP_AdventureMerchantSell)
|
||||
D(OP_AltCurrencySell)
|
||||
D(OP_AltCurrencySellSelection)
|
||||
D(OP_Animation)
|
||||
D(OP_ApplyPoison)
|
||||
D(OP_AugmentInfo)
|
||||
D(OP_AugmentItem)
|
||||
@@ -135,6 +138,7 @@ D(OP_GroupFollow)
|
||||
D(OP_GroupFollow2)
|
||||
D(OP_GroupInvite)
|
||||
D(OP_GroupInvite2)
|
||||
D(OP_GuildBank)
|
||||
D(OP_GuildDemote)
|
||||
D(OP_GuildRemove)
|
||||
D(OP_GuildStatus)
|
||||
@@ -159,6 +163,7 @@ D(OP_Trader)
|
||||
D(OP_TraderBuy)
|
||||
D(OP_TradeSkillCombine)
|
||||
D(OP_TributeItem)
|
||||
D(OP_VetClaimRequest)
|
||||
D(OP_WhoAllRequest)
|
||||
D(OP_ZoneChange)
|
||||
D(OP_ZoneEntry)
|
||||
|
||||
+312
-161
@@ -97,11 +97,6 @@ static const uint32 MAX_PLAYER_TRIBUTES = 5;
|
||||
static const uint32 MAX_TRIBUTE_TIERS = 10;
|
||||
static const uint32 TRIBUTE_NONE = 0xFFFFFFFF;
|
||||
|
||||
static const uint32 MAX_PLAYER_BANDOLIER = 20;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER_ITEMS = 4;
|
||||
|
||||
static const uint32 MAX_POTIONS_IN_BELT = 5;
|
||||
|
||||
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
|
||||
static const uint32 MAX_RAID_LEADERSHIP_AA_ARRAY = 16;
|
||||
static const uint32 MAX_LEADERSHIP_AA_ARRAY = (MAX_GROUP_LEADERSHIP_AA_ARRAY+MAX_RAID_LEADERSHIP_AA_ARRAY);
|
||||
@@ -147,71 +142,87 @@ struct AdventureInfo {
|
||||
*/
|
||||
struct Color_Struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 blue;
|
||||
uint8 green;
|
||||
uint8 red;
|
||||
uint8 use_tint; // if there's a tint this is FF
|
||||
} rgb;
|
||||
uint32 color;
|
||||
union {
|
||||
struct {
|
||||
uint8 Blue;
|
||||
uint8 Green;
|
||||
uint8 Red;
|
||||
uint8 UseTint; // if there's a tint this is FF
|
||||
} RGB;
|
||||
uint32 Color;
|
||||
};
|
||||
};
|
||||
|
||||
struct CharSelectEquip {
|
||||
uint32 material;
|
||||
uint32 unknown1;
|
||||
uint32 elitematerial;
|
||||
uint32 heroforgemodel;
|
||||
uint32 material2;
|
||||
Color_Struct color;
|
||||
struct CharSelectEquip
|
||||
{
|
||||
uint32 Material;
|
||||
uint32 Unknown1;
|
||||
uint32 EliteMaterial;
|
||||
uint32 HeroForgeModel;
|
||||
uint32 Material2;
|
||||
Color_Struct Color;
|
||||
};
|
||||
|
||||
struct CharacterSelectEntry_Struct {
|
||||
/*0000*/ char name[1]; // Name null terminated
|
||||
/*0000*/ uint8 class_;
|
||||
/*0000*/ uint32 race;
|
||||
/*0000*/ uint8 level;
|
||||
/*0000*/ uint8 class_2;
|
||||
/*0000*/ uint32 race2;
|
||||
/*0000*/ uint16 zone;
|
||||
/*0000*/ uint16 instance;
|
||||
/*0000*/ uint8 gender;
|
||||
/*0000*/ uint8 face;
|
||||
/*0000*/ CharSelectEquip equip[9];
|
||||
/*0000*/ uint8 u15; // Seen FF
|
||||
/*0000*/ uint8 u19; // Seen FF
|
||||
/*0000*/ uint32 drakkin_tattoo;
|
||||
/*0000*/ uint32 drakkin_details;
|
||||
/*0000*/ uint32 deity;
|
||||
/*0000*/ uint32 primary;
|
||||
/*0000*/ uint32 secondary;
|
||||
/*0000*/ uint8 haircolor;
|
||||
/*0000*/ uint8 beardcolor;
|
||||
/*0000*/ uint8 eyecolor1;
|
||||
/*0000*/ uint8 eyecolor2;
|
||||
/*0000*/ uint8 hairstyle;
|
||||
/*0000*/ uint8 beard;
|
||||
/*0000*/ uint8 char_enabled;
|
||||
/*0000*/ uint8 tutorial; // Seen 1 for new char or 0 for existing
|
||||
/*0000*/ uint32 drakkin_heritage;
|
||||
/*0000*/ uint8 unknown1; // Seen 0
|
||||
/*0000*/ uint8 gohome; // Seen 0 for new char and 1 for existing
|
||||
struct CharacterSelectEntry_Struct
|
||||
{
|
||||
/*0000*/ char Name[1]; // Name null terminated
|
||||
/*0000*/ uint8 Class;
|
||||
/*0000*/ uint32 Race;
|
||||
/*0000*/ uint8 Level;
|
||||
/*0000*/ uint8 ShroudClass;
|
||||
/*0000*/ uint32 ShroudRace;
|
||||
/*0000*/ uint16 Zone;
|
||||
/*0000*/ uint16 Instance;
|
||||
/*0000*/ uint8 Gender;
|
||||
/*0000*/ uint8 Face;
|
||||
/*0000*/ CharSelectEquip Equip[9];
|
||||
/*0000*/ uint8 Unknown15; // Seen FF
|
||||
/*0000*/ uint8 Unknown19; // Seen FF
|
||||
/*0000*/ uint32 DrakkinTattoo;
|
||||
/*0000*/ uint32 DrakkinDetails;
|
||||
/*0000*/ uint32 Deity;
|
||||
/*0000*/ uint32 PrimaryIDFile;
|
||||
/*0000*/ uint32 SecondaryIDFile;
|
||||
/*0000*/ uint8 HairColor;
|
||||
/*0000*/ uint8 BeardColor;
|
||||
/*0000*/ uint8 EyeColor1;
|
||||
/*0000*/ uint8 EyeColor2;
|
||||
/*0000*/ uint8 HairStyle;
|
||||
/*0000*/ uint8 Beard;
|
||||
/*0000*/ uint8 GoHome; // Seen 0 for new char and 1 for existing
|
||||
/*0000*/ uint8 Tutorial; // Seen 1 for new char or 0 for existing
|
||||
/*0000*/ uint32 DrakkinHeritage;
|
||||
/*0000*/ uint8 Unknown1; // Seen 0
|
||||
/*0000*/ uint8 Enabled; // Swapped position with 'GoHome' 02/23/2015
|
||||
/*0000*/ uint32 LastLogin;
|
||||
/*0000*/ uint8 unknown2; // Seen 0
|
||||
/*0000*/ uint8 Unknown2; // Seen 0
|
||||
};
|
||||
|
||||
/*
|
||||
** Character Selection Struct
|
||||
**
|
||||
*/
|
||||
struct CharacterSelect_Struct {
|
||||
/*000*/ uint32 char_count; //number of chars in this packet
|
||||
/*004*/ CharacterSelectEntry_Struct entries[0];
|
||||
struct CharacterSelect_Struct
|
||||
{
|
||||
/*000*/ uint32 CharCount; //number of chars in this packet
|
||||
/*004*/ CharacterSelectEntry_Struct Entries[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* Visible equiptment.
|
||||
* Size: 20 Octets
|
||||
*/
|
||||
struct EquipStruct
|
||||
{
|
||||
/*00*/ uint32 Material;
|
||||
/*04*/ uint32 Unknown1;
|
||||
/*08*/ uint32 EliteMaterial;
|
||||
/*12*/ uint32 HeroForgeModel;
|
||||
/*16*/ uint32 Material2; // Same as material?
|
||||
/*20*/
|
||||
};
|
||||
|
||||
|
||||
struct Membership_Entry_Struct
|
||||
{
|
||||
/*000*/ uint32 purchase_id; // Seen 1, then increments 90287 to 90300
|
||||
@@ -252,20 +263,6 @@ struct Membership_Struct
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Visible equiptment.
|
||||
* Size: 20 Octets
|
||||
*/
|
||||
struct EquipStruct {
|
||||
/*00*/ uint32 material;
|
||||
/*04*/ uint32 unknown1;
|
||||
/*08*/ uint32 elitematerial;
|
||||
/*12*/ uint32 heroforgemodel;
|
||||
/*16*/ uint32 material2; // Same as material?
|
||||
/*20*/
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Generic Spawn Struct
|
||||
** Length: 897 Octets
|
||||
@@ -413,7 +410,7 @@ struct Spawn_Struct
|
||||
/*0000*/ uint8 unknown12;
|
||||
/*0000*/ uint32 petOwnerId;
|
||||
/*0000*/ uint8 unknown13;
|
||||
/*0000*/ uint32 unknown14; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
/*0000*/ uint32 PlayerState; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
/*0000*/ uint32 unknown15;
|
||||
/*0000*/ uint32 unknown16;
|
||||
/*0000*/ uint32 unknown17;
|
||||
@@ -650,7 +647,10 @@ struct CastSpell_Struct
|
||||
/*04*/ uint32 spell_id;
|
||||
/*08*/ ItemSlotStruct inventoryslot; // slot for clicky item, Seen unknown of 131 = normal cast
|
||||
/*20*/ uint32 target_id;
|
||||
/*24*/ uint32 cs_unknown[5];
|
||||
/*24*/ uint32 cs_unknown[2];
|
||||
/*32*/ float y_pos;
|
||||
/*36*/ float x_pos;
|
||||
/*40*/ float z_pos;
|
||||
/*44*/
|
||||
};
|
||||
|
||||
@@ -676,7 +676,7 @@ struct SpellBuff_Struct
|
||||
/*005*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages
|
||||
/*009*/ uint32 unknown016;
|
||||
/*013*/ uint8 bard_modifier;
|
||||
/*014*/ uint32 duration;
|
||||
/*014*/ int32 duration;
|
||||
/*018*/ uint8 level;
|
||||
/*019*/ uint32 spellid;
|
||||
/*023*/ uint32 counters;
|
||||
@@ -692,7 +692,7 @@ struct SpellBuff_Struct_Old
|
||||
/*003*/ uint8 effect; // not real
|
||||
/*004*/ float unknown004; // Seen 1 for no buff
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 unknown016;
|
||||
/*020*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages
|
||||
/*024*/ uint32 counters;
|
||||
@@ -709,7 +709,7 @@ struct SpellBuffFade_Struct_Live {
|
||||
/*007*/ uint8 unknown007;
|
||||
/*008*/ float unknown008;
|
||||
/*012*/ uint32 spellid;
|
||||
/*016*/ uint32 duration;
|
||||
/*016*/ int32 duration;
|
||||
/*020*/ uint32 playerId; // Global player ID?
|
||||
/*024*/ uint32 num_hits;
|
||||
/*028*/ uint8 unknown0028[64];
|
||||
@@ -725,7 +725,7 @@ struct SpellBuffFade_Struct {
|
||||
/*006*/ uint8 effect;
|
||||
/*007*/ uint8 unknown7;
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 num_hits;
|
||||
/*020*/ uint32 unknown020; // Global player ID?
|
||||
/*024*/ uint32 playerId; // Player id who cast the buff
|
||||
@@ -866,7 +866,7 @@ struct AA_Array
|
||||
{
|
||||
uint32 AA;
|
||||
uint32 value;
|
||||
uint32 unknown08; // Looks like AA_Array is now 12 bytes in Live
|
||||
uint32 charges; // expendable charges
|
||||
};
|
||||
|
||||
struct Disciplines_Struct {
|
||||
@@ -880,38 +880,66 @@ struct Tribute_Struct {
|
||||
uint32 tier;
|
||||
};
|
||||
|
||||
struct BandolierItem_Struct {
|
||||
char item_name[1]; // Variable Length
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct_Old {
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
char item_name[64];
|
||||
};
|
||||
|
||||
//len = 320
|
||||
enum { //bandolier item positions
|
||||
bandolierMainHand = 0,
|
||||
bandolierOffHand,
|
||||
// Bandolier item positions
|
||||
enum
|
||||
{
|
||||
bandolierPrimary = 0,
|
||||
bandolierSecondary,
|
||||
bandolierRange,
|
||||
bandolierAmmo
|
||||
};
|
||||
struct Bandolier_Struct {
|
||||
char name[1]; // Variable Length
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
|
||||
struct BandolierItem_Struct
|
||||
{
|
||||
char Name[1]; // Variable Length
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
};
|
||||
|
||||
struct Bandolier_Struct_Old {
|
||||
char name[32];
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
//len = 72
|
||||
struct BandolierItem_Struct_Old
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
struct PotionBelt_Struct {
|
||||
BandolierItem_Struct items[MAX_POTIONS_IN_BELT];
|
||||
//len = 320
|
||||
struct Bandolier_Struct
|
||||
{
|
||||
char Name[1]; // Variable Length
|
||||
BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct Bandolier_Struct_Old
|
||||
{
|
||||
char Name[32];
|
||||
BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct PotionBeltItem_Struct
|
||||
{
|
||||
char Name[1]; // Variable Length
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct PotionBeltItem_Struct_Old
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
struct PotionBelt_Struct
|
||||
{
|
||||
PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct PotionBelt_Struct_Old
|
||||
{
|
||||
PotionBeltItem_Struct_Old Items[consts::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct GroupLeadershipAA_Struct {
|
||||
@@ -1121,7 +1149,7 @@ union
|
||||
/*12949*/ uint32 aapoints; // Unspent AA points - Seen 1
|
||||
/*12953*/ uint16 unknown_rof20; //
|
||||
/*12955*/ uint32 bandolier_count; // Seen 20
|
||||
/*12959*/ Bandolier_Struct bandoliers[MAX_PLAYER_BANDOLIER]; // [20] 740 bytes (Variable Name Sizes) - bandolier contents
|
||||
/*12959*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // [20] 740 bytes (Variable Name Sizes) - bandolier contents
|
||||
/*13699*/ uint32 potionbelt_count; // Seen 5
|
||||
/*13703*/ PotionBelt_Struct potionbelt; // [5] 45 bytes potion belt - (Variable Name Sizes)
|
||||
/*13748*/ int32 unknown_rof21; // Seen -1
|
||||
@@ -1295,7 +1323,7 @@ struct TargetReject_Struct {
|
||||
|
||||
struct PetCommand_Struct {
|
||||
/*00*/ uint32 command;
|
||||
/*04*/ uint32 unknown04;
|
||||
/*04*/ uint32 target;
|
||||
/*08*/ uint32 unknown08;
|
||||
};
|
||||
|
||||
@@ -1420,8 +1448,8 @@ struct RequestClientZoneChange_Struct {
|
||||
|
||||
struct Animation_Struct {
|
||||
/*00*/ uint16 spawnid;
|
||||
/*02*/ uint8 value;
|
||||
/*03*/ uint8 action;
|
||||
/*02*/ uint8 action;
|
||||
/*03*/ uint8 speed;
|
||||
/*04*/
|
||||
};
|
||||
|
||||
@@ -1486,9 +1514,11 @@ struct CombatDamage_Struct
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||
/* 05 */ uint32 spellid;
|
||||
/* 09 */ int32 damage;
|
||||
/* 13 */ float unknown11; // cd cc cc 3d
|
||||
/* 17 */ float sequence; // see above notes in Action_Struct
|
||||
/* 21 */ uint8 unknown19[9]; // was [9]
|
||||
/* 13 */ float force; // cd cc cc 3d
|
||||
/* 17 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 21 */ float meleepush_z;
|
||||
/* 25 */ uint8 unknown25; // was [9]
|
||||
/* 26 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
|
||||
/* 30 */
|
||||
};
|
||||
|
||||
@@ -1859,6 +1889,114 @@ struct GuildUpdate_Struct {
|
||||
GuildsListEntry_Struct entry;
|
||||
};
|
||||
|
||||
struct GuildBankAck_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; // 10
|
||||
/*04*/ uint32 Unknown04;
|
||||
/*08*/ uint32 Unknown08;
|
||||
};
|
||||
|
||||
struct GuildBankDepositAck_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; // 10
|
||||
/*04*/ uint32 Unknown04;
|
||||
/*08*/ uint32 Unknown08;
|
||||
/*08*/ uint32 Fail; //1 = Fail, 0 = Success
|
||||
};
|
||||
|
||||
struct GuildBankPromote_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; // 3
|
||||
/*04*/ uint32 Unknown04;
|
||||
/*08*/ uint32 Unknown08;
|
||||
/*12*/ uint32 Slot;
|
||||
/*16*/ uint32 Slot2; // Always appears to be the same as Slot for Action code 3
|
||||
/*20*/ uint32 unknown20;
|
||||
};
|
||||
|
||||
struct GuildBankPermissions_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; // 6
|
||||
/*04*/ uint32 Unknown04;
|
||||
/*08*/ uint32 Unknown08;
|
||||
/*08*/ uint16 SlotID;
|
||||
/*10*/ uint16 Unknown10; // Saw 1, probably indicating it is the main area rather than deposits
|
||||
/*12*/ uint32 ItemID;
|
||||
/*16*/ uint32 Permissions;
|
||||
/*20*/ char MemberName[64];
|
||||
};
|
||||
|
||||
struct GuildBankViewItem_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint32 Unknown04;
|
||||
/*08*/ uint32 Unknown08;
|
||||
/*08*/ uint16 SlotID; // 0 = Deposit area, 1 = Main area
|
||||
/*10*/ uint16 Area;
|
||||
/*12*/ uint32 Unknown12;
|
||||
/*16*/ uint32 Unknown16;
|
||||
};
|
||||
|
||||
struct GuildBankWithdrawItem_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint32 Unknown04;
|
||||
/*08*/ uint32 Unknown08;
|
||||
/*08*/ uint16 SlotID;
|
||||
/*10*/ uint16 Area;
|
||||
/*12*/ uint32 Unknown12;
|
||||
/*16*/ uint32 Quantity;
|
||||
/*20*/
|
||||
};
|
||||
|
||||
struct GuildBankItemUpdate_Struct
|
||||
{
|
||||
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
|
||||
uint32 inPermissions, uint32 inAllowMerge, bool inUseable)
|
||||
{
|
||||
Action = inAction;
|
||||
Unknown004 = inUnknown004;
|
||||
SlotID = inSlotID;
|
||||
Area = inArea;
|
||||
Unknown012 = inUnknown012;
|
||||
ItemID = inItemID;
|
||||
Icon = inIcon;
|
||||
Quantity = inQuantity;
|
||||
Permissions = inPermissions;
|
||||
AllowMerge = inAllowMerge;
|
||||
Useable = inUseable;
|
||||
ItemName[0] = '\0';
|
||||
Donator[0] = '\0';
|
||||
WhoFor[0] = '\0';
|
||||
};
|
||||
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*008*/ uint32 Unknown08;
|
||||
/*012*/ uint16 SlotID;
|
||||
/*014*/ uint16 Area;
|
||||
/*016*/ uint32 Unknown012;
|
||||
/*020*/ uint32 ItemID;
|
||||
/*024*/ uint32 Icon;
|
||||
/*028*/ uint32 Quantity;
|
||||
/*032*/ uint32 Permissions;
|
||||
/*036*/ uint8 AllowMerge;
|
||||
/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission.
|
||||
/*038*/ char ItemName[64];
|
||||
/*102*/ char Donator[64];
|
||||
/*166*/ char WhoFor[64];
|
||||
/*230*/ uint16 Unknown226;
|
||||
};
|
||||
|
||||
struct GuildBankClear_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint32 Unknown04;
|
||||
/*08*/ uint32 Unknown08;
|
||||
/*12*/ uint32 DepositAreaCount;
|
||||
/*16*/ uint32 MainAreaCount;
|
||||
};
|
||||
|
||||
/*
|
||||
** Money Loot
|
||||
** Length: 22 Bytes
|
||||
@@ -2472,7 +2610,7 @@ struct GroupFollow_Struct { // Live Follow Struct
|
||||
|
||||
struct InspectBuffs_Struct {
|
||||
/*000*/ uint32 spell_id[BUFF_COUNT];
|
||||
/*168*/ uint32 tics_remaining[BUFF_COUNT];
|
||||
/*168*/ int32 tics_remaining[BUFF_COUNT];
|
||||
};
|
||||
|
||||
struct LFG_Struct {
|
||||
@@ -3592,7 +3730,7 @@ struct Split_Struct
|
||||
*/
|
||||
struct NewCombine_Struct {
|
||||
/*00*/ ItemSlotStruct container_slot;
|
||||
/*12*/ ItemSlotStruct guildtribute_slot; // Slot type is 8? (MapGuildTribute = 8 -U)
|
||||
/*12*/ ItemSlotStruct guildtribute_slot; // Slot type is 8? (MapGuildTribute = 8)
|
||||
/*24*/
|
||||
};
|
||||
|
||||
@@ -4113,30 +4251,35 @@ struct DynamicWall_Struct {
|
||||
/*80*/
|
||||
};
|
||||
|
||||
enum { //bandolier actions
|
||||
BandolierCreate = 0,
|
||||
BandolierRemove = 1,
|
||||
BandolierSet = 2
|
||||
// Bandolier actions
|
||||
enum
|
||||
{
|
||||
bandolierCreate = 0,
|
||||
bandolierRemove,
|
||||
bandolierSet
|
||||
};
|
||||
|
||||
struct BandolierCreate_Struct {
|
||||
/*00*/ uint32 action; //0 for create
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ char name[32];
|
||||
/*37*/ uint16 unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 unknown39; //0
|
||||
struct BandolierCreate_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; //0 for create
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ char Name[32];
|
||||
/*37*/ uint16 Unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 Unknown39; //0
|
||||
};
|
||||
|
||||
struct BandolierDelete_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierDelete_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct BandolierSet_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierSet_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct Arrow_Struct {
|
||||
@@ -4218,9 +4361,9 @@ struct SendAA_Struct {
|
||||
/*0025*/ uint32 cost;
|
||||
/*0029*/ uint32 seq;
|
||||
/*0033*/ uint32 current_level; //1s, MQ2 calls this AARankRequired
|
||||
/*0037*/ uint32 unknown037; // Introduced during HoT
|
||||
/*0037*/ uint32 prereq_skill_count; // mutliple prereqs at least 1, even no prereqs
|
||||
/*0041*/ uint32 prereq_skill; //is < 0, abs() is category #
|
||||
/*0045*/ uint32 unknown045; // New Mar 21 2012 - Seen 1
|
||||
/*0045*/ uint32 prereq_minpoints_count; // mutliple prereqs at least 1, even no prereqs
|
||||
/*0049*/ uint32 prereq_minpoints; //min points in the prereq
|
||||
/*0053*/ uint32 type;
|
||||
/*0057*/ uint32 spellid;
|
||||
@@ -4233,10 +4376,16 @@ struct SendAA_Struct {
|
||||
/*0081*/ uint32 last_id;
|
||||
/*0085*/ uint32 next_id;
|
||||
/*0089*/ uint32 cost2;
|
||||
/*0093*/ uint8 unknown80[7];
|
||||
/*0093*/ uint8 unknown93;
|
||||
/*0094*/ uint8 grant_only; // VetAAs, progression, etc
|
||||
/*0095*/ uint8 unknown95; // 1 for skill cap increase AAs, Mystical Attuning, and RNG attack inc, doesn't seem to matter though
|
||||
/*0096*/ uint32 expendable_charges; // max charges of the AA
|
||||
/*0100*/ uint32 aa_expansion;
|
||||
/*0104*/ uint32 special_category;
|
||||
/*0108*/ uint32 unknown0096;
|
||||
/*0108*/ uint8 shroud;
|
||||
/*0109*/ uint8 unknown109;
|
||||
/*0110*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter?
|
||||
/*0111*/ uint8 unknown111;
|
||||
/*0112*/ uint32 total_abilities;
|
||||
/*0116*/ AA_Ability abilities[0];
|
||||
};
|
||||
@@ -4248,18 +4397,11 @@ struct AA_List {
|
||||
struct AA_Action {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint32 ability;
|
||||
/*08*/ uint32 unknown08;
|
||||
/*08*/ uint32 target_id;
|
||||
/*12*/ uint32 exp_value;
|
||||
/*16*/
|
||||
};
|
||||
|
||||
struct AA_Skills { //this should be removed and changed to AA_Array
|
||||
/*00*/ uint32 aa_skill; // Total AAs Spent
|
||||
/*04*/ uint32 aa_value;
|
||||
/*08*/ uint32 unknown08;
|
||||
/*12*/
|
||||
};
|
||||
|
||||
struct AAExpUpdate_Struct {
|
||||
/*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability
|
||||
/*04*/ uint32 aapoints_unspent;
|
||||
@@ -4278,14 +4420,7 @@ struct AltAdvStats_Struct {
|
||||
};
|
||||
|
||||
struct PlayerAA_Struct { // Is this still used?
|
||||
AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AA_Values {
|
||||
/*00*/ uint32 aa_skill;
|
||||
/*04*/ uint32 aa_value;
|
||||
/*08*/ uint32 unknown08;
|
||||
/*12*/
|
||||
AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AATable_Struct {
|
||||
@@ -4295,7 +4430,7 @@ struct AATable_Struct {
|
||||
/*12*/ uint32 aa_spent_archetype; // Seen 40
|
||||
/*16*/ uint32 aa_spent_class; // Seen 103
|
||||
/*20*/ uint32 aa_spent_special; // Seen 0
|
||||
/*24*/ AA_Values aa_list[MAX_PP_AA_ARRAY];
|
||||
/*24*/ AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct Weather_Struct {
|
||||
@@ -4378,7 +4513,7 @@ struct RoFSlotStruct
|
||||
|
||||
struct ItemSerializationHeader
|
||||
{
|
||||
/*000*/ char unknown000[13]; // New for HoT. Looks like a string.
|
||||
/*000*/ char unknown000[17]; // New for HoT. Looks like a string.
|
||||
/*017*/ uint32 stacksize;
|
||||
/*021*/ uint32 unknown004;
|
||||
/*025*/ uint8 slot_type; // 0 = normal, 1 = bank, 2 = shared bank, 9 = merchant, 20 = ?
|
||||
@@ -4524,7 +4659,7 @@ struct ItemSecondaryBodyStruct
|
||||
uint32 augtype;
|
||||
// swapped augrestrict and augdistiller positions
|
||||
// (this swap does show the proper augment restrictions in Item Information window now)
|
||||
// unsure what the purpose of augdistiller is at this time -U 3/17/2014
|
||||
// unsure what the purpose of augdistiller is at this time 3/17/2014
|
||||
uint32 augdistiller; // New to December 10th 2012 client - NEW
|
||||
uint32 augrestrict;
|
||||
AugSlotStruct augslots[6];
|
||||
@@ -4596,7 +4731,7 @@ struct ClickEffectStruct
|
||||
|
||||
struct ProcEffectStruct
|
||||
{
|
||||
uint32 effect;
|
||||
int32 effect;
|
||||
uint8 level2;
|
||||
uint32 type;
|
||||
uint8 level;
|
||||
@@ -4611,7 +4746,7 @@ struct ProcEffectStruct
|
||||
|
||||
struct WornEffectStruct //worn, focus and scroll effect
|
||||
{
|
||||
uint32 effect;
|
||||
int32 effect;
|
||||
uint8 level2;
|
||||
uint32 type;
|
||||
uint8 level;
|
||||
@@ -4688,17 +4823,33 @@ struct AugmentInfo_Struct
|
||||
|
||||
struct VeteranRewardItem
|
||||
{
|
||||
/*000*/ uint32 item_id;
|
||||
/*004*/ uint32 charges;
|
||||
/*008*/ char item_name[64];
|
||||
/*000*/ uint32 name_length;
|
||||
/*004*/ //char item_name[0]; // THIS IS NOT NULL TERMED
|
||||
/*???*/ uint32 item_id;
|
||||
/*???*/ uint32 charges;
|
||||
};
|
||||
|
||||
struct VeteranRewardEntry
|
||||
{
|
||||
/*000*/ uint32 claim_id; // guessed
|
||||
/*004*/ uint32 avaliable_count;
|
||||
/*008*/ uint32 claim_count;
|
||||
/*012*/ char enabled;
|
||||
/*013*/ //VeteranRewardItem items[0];
|
||||
};
|
||||
|
||||
struct VeteranReward
|
||||
{
|
||||
/*000*/ uint32 claim_id;
|
||||
/*004*/ uint32 number_available;
|
||||
/*008*/ uint32 claim_count;
|
||||
/*012*/ VeteranRewardItem items[8];
|
||||
/*000*/ uint32 claim_count;
|
||||
/*004*/ //VeteranRewardEntry entries[0];
|
||||
};
|
||||
|
||||
struct VeteranClaim
|
||||
{
|
||||
/*000*/ char name[68]; //name + other data
|
||||
/*068*/ uint32 claim_id;
|
||||
/*072*/ uint32 unknown072;
|
||||
/*076*/ uint32 action;
|
||||
};
|
||||
|
||||
struct ExpeditionEntryHeader_Struct
|
||||
|
||||
+196
-188
@@ -446,7 +446,10 @@ namespace SoD
|
||||
OUT(type);
|
||||
OUT(spellid);
|
||||
OUT(damage);
|
||||
eq->sequence = emu->sequence;
|
||||
OUT(force);
|
||||
OUT(meleepush_xy);
|
||||
OUT(meleepush_z);
|
||||
OUT(special);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@@ -1542,13 +1545,13 @@ namespace SoD
|
||||
OUT(beard);
|
||||
// OUT(unknown00178[10]);
|
||||
for (r = 0; r < 9; r++) {
|
||||
eq->equipment[r].material = emu->item_material[r];
|
||||
eq->equipment[r].unknown1 = 0;
|
||||
eq->equipment[r].elitematerial = 0;
|
||||
eq->equipment[r].Material = emu->item_material[r];
|
||||
eq->equipment[r].Unknown1 = 0;
|
||||
eq->equipment[r].EliteMaterial = 0;
|
||||
//eq->colors[r].color = emu->colors[r].color;
|
||||
}
|
||||
for (r = 0; r < 7; r++) {
|
||||
OUT(item_tint[r].color);
|
||||
OUT(item_tint[r].Color);
|
||||
}
|
||||
// OUT(unknown00224[48]);
|
||||
//NOTE: new client supports 300 AAs, our internal rep/PP
|
||||
@@ -1556,6 +1559,7 @@ namespace SoD
|
||||
for (r = 0; r < MAX_PP_AA_ARRAY; r++) {
|
||||
OUT(aa_array[r].AA);
|
||||
OUT(aa_array[r].value);
|
||||
OUT(aa_array[r].charges);
|
||||
}
|
||||
// OUT(unknown02220[4]);
|
||||
OUT(mana);
|
||||
@@ -1606,26 +1610,46 @@ namespace SoD
|
||||
OUT(endurance);
|
||||
OUT(aapoints_spent);
|
||||
OUT(aapoints);
|
||||
|
||||
// OUT(unknown06160[4]);
|
||||
//NOTE: new client supports 20 bandoliers, our internal rep
|
||||
//only supports 4..
|
||||
for (r = 0; r < 4; r++) {
|
||||
OUT_str(bandoliers[r].name);
|
||||
uint32 k;
|
||||
for (k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) {
|
||||
OUT(bandoliers[r].items[k].item_id);
|
||||
OUT(bandoliers[r].items[k].icon);
|
||||
OUT_str(bandoliers[r].items[k].item_name);
|
||||
|
||||
// Copy bandoliers where server and client indexes converge
|
||||
for (r = 0; r < EmuConstants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
OUT_str(bandoliers[r].Name);
|
||||
for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true
|
||||
OUT(bandoliers[r].Items[k].ID);
|
||||
OUT(bandoliers[r].Items[k].Icon);
|
||||
OUT_str(bandoliers[r].Items[k].Name);
|
||||
}
|
||||
}
|
||||
// OUT(unknown07444[5120]);
|
||||
for (r = 0; r < structs::MAX_POTIONS_IN_BELT; r++) {
|
||||
OUT(potionbelt.items[r].item_id);
|
||||
OUT(potionbelt.items[r].icon);
|
||||
OUT_str(potionbelt.items[r].item_name);
|
||||
// Nullify bandoliers where server and client indexes diverge, with a client bias
|
||||
for (r = EmuConstants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
eq->bandoliers[r].Name[0] = '\0';
|
||||
for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true
|
||||
eq->bandoliers[r].Items[k].ID = 0;
|
||||
eq->bandoliers[r].Items[k].Icon = 0;
|
||||
eq->bandoliers[r].Items[k].Name[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
// OUT(unknown07444[5120]);
|
||||
|
||||
// Copy potion belt where server and client indexes converge
|
||||
for (r = 0; r < EmuConstants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
OUT(potionbelt.Items[r].ID);
|
||||
OUT(potionbelt.Items[r].Icon);
|
||||
OUT_str(potionbelt.Items[r].Name);
|
||||
}
|
||||
// Nullify potion belt where server and client indexes diverge, with a client bias
|
||||
for (r = EmuConstants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
eq->potionbelt.Items[r].ID = 0;
|
||||
eq->potionbelt.Items[r].Icon = 0;
|
||||
eq->potionbelt.Items[r].Name[0] = '\0';
|
||||
}
|
||||
|
||||
// OUT(unknown12852[8]);
|
||||
// OUT(unknown12864[76]);
|
||||
|
||||
OUT_str(name);
|
||||
OUT_str(last_name);
|
||||
OUT(guild_id);
|
||||
@@ -1654,8 +1678,8 @@ namespace SoD
|
||||
OUT(copper_bank);
|
||||
OUT(platinum_shared);
|
||||
// OUT(unknown13156[84]);
|
||||
//OUT(expansions);
|
||||
eq->expansions = 16383;
|
||||
OUT(expansions);
|
||||
//eq->expansions = 16383;
|
||||
// OUT(unknown13244[12]);
|
||||
OUT(autosplit);
|
||||
// OUT(unknown13260[16]);
|
||||
@@ -1839,128 +1863,150 @@ namespace SoD
|
||||
|
||||
ENCODE(OP_SendAATable)
|
||||
{
|
||||
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
|
||||
SETUP_VAR_ENCODE(SendAA_Struct);
|
||||
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
|
||||
EQApplicationPacket *inapp = *p;
|
||||
*p = nullptr;
|
||||
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
|
||||
|
||||
// Check clientver field to verify this AA should be sent for SoF
|
||||
// clientver 1 is for all clients and 5 is for SoD
|
||||
if (emu->clientver <= 5)
|
||||
{
|
||||
OUT(id);
|
||||
eq->unknown004 = 1;
|
||||
//eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1);
|
||||
//eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1);
|
||||
//eq->title_sid = emu->id - emu->current_level + 1;
|
||||
//eq->desc_sid = emu->id - emu->current_level + 1;
|
||||
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->sof_next_skill);
|
||||
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->sof_next_skill);
|
||||
eq->title_sid = emu->sof_next_skill;
|
||||
eq->desc_sid = emu->sof_next_skill;
|
||||
OUT(class_type);
|
||||
OUT(cost);
|
||||
OUT(seq);
|
||||
OUT(current_level);
|
||||
OUT(prereq_skill);
|
||||
OUT(prereq_minpoints);
|
||||
eq->type = emu->sof_type;
|
||||
OUT(spellid);
|
||||
OUT(spell_type);
|
||||
OUT(spell_refresh);
|
||||
OUT(classes);
|
||||
OUT(berserker);
|
||||
//eq->max_level = emu->sof_max_level;
|
||||
OUT(max_level);
|
||||
OUT(last_id);
|
||||
OUT(next_id);
|
||||
OUT(cost2);
|
||||
eq->aa_expansion = emu->aa_expansion;
|
||||
eq->special_category = emu->special_category;
|
||||
OUT(total_abilities);
|
||||
unsigned int r;
|
||||
for (r = 0; r < emu->total_abilities; r++) {
|
||||
OUT(abilities[r].skill_id);
|
||||
OUT(abilities[r].base1);
|
||||
OUT(abilities[r].base2);
|
||||
OUT(abilities[r].slot);
|
||||
}
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability));
|
||||
structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer;
|
||||
|
||||
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
|
||||
outapp->SetWritePosition(sizeof(structs::SendAA_Struct));
|
||||
|
||||
eq->id = emu->id;
|
||||
eq->unknown004 = 1;
|
||||
eq->id = emu->id;
|
||||
eq->hotkey_sid = emu->upper_hotkey_sid;
|
||||
eq->hotkey_sid2 = emu->lower_hotkey_sid;
|
||||
eq->desc_sid = emu->desc_sid;
|
||||
eq->title_sid = emu->title_sid;
|
||||
eq->class_type = emu->level_req;
|
||||
eq->cost = emu->cost;
|
||||
eq->seq = emu->seq;
|
||||
eq->current_level = emu->current_level;
|
||||
eq->type = emu->type;
|
||||
eq->spellid = emu->spell;
|
||||
eq->spell_type = emu->spell_type;
|
||||
eq->spell_refresh = emu->spell_refresh;
|
||||
eq->classes = emu->classes;
|
||||
eq->max_level = emu->max_level;
|
||||
eq->last_id = emu->prev_id;
|
||||
eq->next_id = emu->next_id;
|
||||
eq->cost2 = emu->total_cost;
|
||||
eq->grant_only = emu->grant_only;
|
||||
eq->expendable_charges = emu->charges;
|
||||
eq->aa_expansion = emu->expansion;
|
||||
eq->special_category = emu->category;
|
||||
eq->total_abilities = emu->total_effects;
|
||||
|
||||
for(auto i = 0; i < eq->total_abilities; ++i) {
|
||||
eq->abilities[i].skill_id = inapp->ReadUInt32();
|
||||
eq->abilities[i].base1 = inapp->ReadUInt32();
|
||||
eq->abilities[i].base2 = inapp->ReadUInt32();
|
||||
eq->abilities[i].slot = inapp->ReadUInt32();
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
if(emu->total_prereqs > 0) {
|
||||
eq->prereq_skill = inapp->ReadUInt32();
|
||||
eq->prereq_minpoints = inapp->ReadUInt32();
|
||||
}
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
delete inapp;
|
||||
}
|
||||
|
||||
ENCODE(OP_SendCharInfo)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(CharacterSelect_Struct);
|
||||
ENCODE_LENGTH_ATLEAST(CharacterSelect_Struct);
|
||||
SETUP_VAR_ENCODE(CharacterSelect_Struct);
|
||||
|
||||
//EQApplicationPacket *packet = *p;
|
||||
//const CharacterSelect_Struct *emu = (CharacterSelect_Struct *) packet->pBuffer;
|
||||
// Zero-character count shunt
|
||||
if (emu->CharCount == 0) {
|
||||
ALLOC_VAR_ENCODE(structs::CharacterSelect_Struct, sizeof(structs::CharacterSelect_Struct));
|
||||
eq->CharCount = emu->CharCount;
|
||||
eq->TotalChars = emu->TotalChars;
|
||||
|
||||
int char_count;
|
||||
int namelen = 0;
|
||||
for (char_count = 0; char_count < 10; char_count++) {
|
||||
if (emu->name[char_count][0] == '\0')
|
||||
break;
|
||||
if (strcmp(emu->name[char_count], "<none>") == 0)
|
||||
break;
|
||||
namelen += strlen(emu->name[char_count]);
|
||||
if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT)
|
||||
eq->TotalChars = consts::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
FINISH_ENCODE();
|
||||
return;
|
||||
}
|
||||
|
||||
int total_length = sizeof(structs::CharacterSelect_Struct)
|
||||
+ char_count * sizeof(structs::CharacterSelectEntry_Struct)
|
||||
+ namelen;
|
||||
unsigned char *emu_ptr = __emu_buffer;
|
||||
emu_ptr += sizeof(CharacterSelect_Struct);
|
||||
CharacterSelectEntry_Struct *emu_cse = (CharacterSelectEntry_Struct *)nullptr;
|
||||
|
||||
size_t names_length = 0;
|
||||
size_t character_count = 0;
|
||||
for (; character_count < emu->CharCount && character_count < consts::CHARACTER_CREATION_LIMIT; ++character_count) {
|
||||
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
||||
names_length += strlen(emu_cse->Name);
|
||||
emu_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
size_t total_length = sizeof(structs::CharacterSelect_Struct)
|
||||
+ character_count * sizeof(structs::CharacterSelectEntry_Struct)
|
||||
+ names_length;
|
||||
|
||||
ALLOC_VAR_ENCODE(structs::CharacterSelect_Struct, total_length);
|
||||
structs::CharacterSelectEntry_Struct *eq_cse = (structs::CharacterSelectEntry_Struct *)nullptr;
|
||||
|
||||
//unsigned char *eq_buffer = new unsigned char[total_length];
|
||||
//structs::CharacterSelect_Struct *eq_head = (structs::CharacterSelect_Struct *) eq_buffer;
|
||||
eq->CharCount = character_count;
|
||||
eq->TotalChars = emu->TotalChars;
|
||||
|
||||
eq->char_count = char_count;
|
||||
eq->total_chars = 10;
|
||||
if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT)
|
||||
eq->TotalChars = consts::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
unsigned char *bufptr = (unsigned char *)eq->entries;
|
||||
int r;
|
||||
for (r = 0; r < char_count; r++) {
|
||||
{ //pre-name section...
|
||||
structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr;
|
||||
eq2->level = emu->level[r];
|
||||
eq2->hairstyle = emu->hairstyle[r];
|
||||
eq2->gender = emu->gender[r];
|
||||
memcpy(eq2->name, emu->name[r], strlen(emu->name[r]) + 1);
|
||||
emu_ptr = __emu_buffer;
|
||||
emu_ptr += sizeof(CharacterSelect_Struct);
|
||||
|
||||
unsigned char *eq_ptr = __packet->pBuffer;
|
||||
eq_ptr += sizeof(structs::CharacterSelect_Struct);
|
||||
|
||||
for (int counter = 0; counter < character_count; ++counter) {
|
||||
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
||||
eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // base address
|
||||
|
||||
eq_cse->Level = emu_cse->Level;
|
||||
eq_cse->HairStyle = emu_cse->HairStyle;
|
||||
eq_cse->Gender = emu_cse->Gender;
|
||||
|
||||
strcpy(eq_cse->Name, emu_cse->Name);
|
||||
eq_ptr += strlen(emu_cse->Name);
|
||||
eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // offset address (base + name length offset)
|
||||
eq_cse->Name[0] = '\0'; // (offset)eq_cse->Name[0] = (base)eq_cse->Name[strlen(emu_cse->Name)]
|
||||
|
||||
eq_cse->Beard = emu_cse->Beard;
|
||||
eq_cse->HairColor = emu_cse->HairColor;
|
||||
eq_cse->Face = emu_cse->Face;
|
||||
|
||||
for (int equip_index = 0; equip_index < _MaterialCount; equip_index++) {
|
||||
eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material;
|
||||
eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1;
|
||||
eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial;
|
||||
eq_cse->Equip[equip_index].Color.Color = emu_cse->Equip[equip_index].Color.Color;
|
||||
}
|
||||
//adjust for name.
|
||||
bufptr += strlen(emu->name[r]);
|
||||
{ //post-name section...
|
||||
structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr;
|
||||
eq2->beard = emu->beard[r];
|
||||
eq2->haircolor = emu->haircolor[r];
|
||||
eq2->face = emu->face[r];
|
||||
int k;
|
||||
for (k = 0; k < _MaterialCount; k++) {
|
||||
eq2->equip[k].material = emu->equip[r][k].material;
|
||||
eq2->equip[k].unknown1 = emu->equip[r][k].unknown1;
|
||||
eq2->equip[k].elitematerial = emu->equip[r][k].elitematerial;
|
||||
eq2->equip[k].color.color = emu->equip[r][k].color.color;
|
||||
}
|
||||
eq2->primary = emu->primary[r];
|
||||
eq2->secondary = emu->secondary[r];
|
||||
eq2->tutorial = emu->tutorial[r]; // was u15
|
||||
eq2->u15 = 0xff;
|
||||
eq2->deity = emu->deity[r];
|
||||
eq2->zone = emu->zone[r];
|
||||
eq2->u19 = 0xFF;
|
||||
eq2->race = emu->race[r];
|
||||
eq2->gohome = emu->gohome[r];
|
||||
eq2->class_ = emu->class_[r];
|
||||
eq2->eyecolor1 = emu->eyecolor1[r];
|
||||
eq2->beardcolor = emu->beardcolor[r];
|
||||
eq2->eyecolor2 = emu->eyecolor2[r];
|
||||
eq2->drakkin_heritage = emu->drakkin_heritage[r];
|
||||
eq2->drakkin_tattoo = emu->drakkin_tattoo[r];
|
||||
eq2->drakkin_details = emu->drakkin_details[r];
|
||||
}
|
||||
bufptr += sizeof(structs::CharacterSelectEntry_Struct);
|
||||
|
||||
eq_cse->PrimaryIDFile = emu_cse->PrimaryIDFile;
|
||||
eq_cse->SecondaryIDFile = emu_cse->SecondaryIDFile;
|
||||
eq_cse->Tutorial = emu_cse->Tutorial;
|
||||
eq_cse->Unknown15 = emu_cse->Unknown15;
|
||||
eq_cse->Deity = emu_cse->Deity;
|
||||
eq_cse->Zone = emu_cse->Zone;
|
||||
eq_cse->Unknown19 = emu_cse->Unknown19;
|
||||
eq_cse->Race = emu_cse->Race;
|
||||
eq_cse->GoHome = emu_cse->GoHome;
|
||||
eq_cse->Class = emu_cse->Class;
|
||||
eq_cse->EyeColor1 = emu_cse->EyeColor1;
|
||||
eq_cse->BeardColor = emu_cse->BeardColor;
|
||||
eq_cse->EyeColor2 = emu_cse->EyeColor2;
|
||||
eq_cse->DrakkinHeritage = emu_cse->DrakkinHeritage;
|
||||
eq_cse->DrakkinTattoo = emu_cse->DrakkinTattoo;
|
||||
eq_cse->DrakkinDetails = emu_cse->DrakkinDetails;
|
||||
|
||||
emu_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
eq_ptr += sizeof(structs::CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -2161,25 +2207,6 @@ namespace SoD
|
||||
ptr += sizeof(uint32);
|
||||
ptr += 1;
|
||||
}
|
||||
/*std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
||||
|
||||
uint8 write_var8 = 1;
|
||||
ss.write((const char*)&emu->entity_id, sizeof(uint32));
|
||||
ss.write((const char*)&emu->count, sizeof(uint16));
|
||||
write_var8 = 0;
|
||||
for(uint16 i = 0; i < emu->count; ++i)
|
||||
{
|
||||
ss.write((const char*)&emu->entries[i].buff_slot, sizeof(uint32));
|
||||
ss.write((const char*)&emu->entries[i].spell_id, sizeof(uint32));
|
||||
ss.write((const char*)&emu->entries[i].tics_remaining, sizeof(uint32));
|
||||
ss.write((const char*)&write_var8, sizeof(uint8));
|
||||
}
|
||||
|
||||
__packet->size = ss.str().length();
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
||||
*/
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
@@ -2355,7 +2382,7 @@ namespace SoD
|
||||
OUT(material);
|
||||
OUT(unknown06);
|
||||
OUT(elite_material);
|
||||
OUT(color.color);
|
||||
OUT(color.Color);
|
||||
OUT(wear_slot_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -2427,42 +2454,23 @@ namespace SoD
|
||||
|
||||
ENCODE(OP_ZonePlayerToBind)
|
||||
{
|
||||
ENCODE_LENGTH_ATLEAST(ZonePlayerToBind_Struct);
|
||||
SETUP_VAR_ENCODE(ZonePlayerToBind_Struct);
|
||||
ALLOC_LEN_ENCODE(sizeof(structs::ZonePlayerToBind_Struct) + strlen(emu->zone_name));
|
||||
|
||||
ZonePlayerToBind_Struct *zps = (ZonePlayerToBind_Struct*)(*p)->pBuffer;
|
||||
__packet->SetWritePosition(0);
|
||||
__packet->WriteUInt16(emu->bind_zone_id);
|
||||
__packet->WriteUInt16(emu->bind_instance_id);
|
||||
__packet->WriteFloat(emu->x);
|
||||
__packet->WriteFloat(emu->y);
|
||||
__packet->WriteFloat(emu->z);
|
||||
__packet->WriteFloat(emu->heading);
|
||||
__packet->WriteString(emu->zone_name);
|
||||
__packet->WriteUInt8(1); // save items
|
||||
__packet->WriteUInt32(0); // hp
|
||||
__packet->WriteUInt32(0); // mana
|
||||
__packet->WriteUInt32(0); // endurance
|
||||
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
||||
|
||||
unsigned char *buffer1 = new unsigned char[sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)];
|
||||
structs::ZonePlayerToBindHeader_Struct *zph = (structs::ZonePlayerToBindHeader_Struct*)buffer1;
|
||||
unsigned char *buffer2 = new unsigned char[sizeof(structs::ZonePlayerToBindFooter_Struct)];
|
||||
structs::ZonePlayerToBindFooter_Struct *zpf = (structs::ZonePlayerToBindFooter_Struct*)buffer2;
|
||||
|
||||
zph->x = zps->x;
|
||||
zph->y = zps->y;
|
||||
zph->z = zps->z;
|
||||
zph->heading = zps->heading;
|
||||
zph->bind_zone_id = zps->bind_zone_id;
|
||||
zph->bind_instance_id = zps->bind_instance_id;
|
||||
strcpy(zph->zone_name, zps->zone_name);
|
||||
|
||||
zpf->unknown021 = 1;
|
||||
zpf->unknown022 = 0;
|
||||
zpf->unknown023 = 0;
|
||||
zpf->unknown024 = 0;
|
||||
|
||||
ss.write((const char*)buffer1, (sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)));
|
||||
ss.write((const char*)buffer2, sizeof(structs::ZonePlayerToBindFooter_Struct));
|
||||
|
||||
delete[] buffer1;
|
||||
delete[] buffer2;
|
||||
delete[](*p)->pBuffer;
|
||||
|
||||
(*p)->pBuffer = new unsigned char[ss.str().size()];
|
||||
(*p)->size = ss.str().size();
|
||||
|
||||
memcpy((*p)->pBuffer, ss.str().c_str(), ss.str().size());
|
||||
dest->FastQueuePacket(&(*p));
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ZoneServerInfo)
|
||||
@@ -2715,7 +2723,7 @@ namespace SoD
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown12
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petOwnerId);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown13
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown14 - Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->PlayerState);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown15
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown16
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown17
|
||||
@@ -2742,7 +2750,7 @@ namespace SoD
|
||||
for (k = 0; k < 9; ++k)
|
||||
{
|
||||
{
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].color);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].Color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2752,11 +2760,11 @@ namespace SoD
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].material);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].Material);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].material);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].Material);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
}
|
||||
@@ -2767,9 +2775,9 @@ namespace SoD
|
||||
structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer;
|
||||
|
||||
for (k = 0; k < 9; k++) {
|
||||
Equipment[k].material = emu->equipment[k].material;
|
||||
Equipment[k].unknown1 = emu->equipment[k].unknown1;
|
||||
Equipment[k].elitematerial = emu->equipment[k].elitematerial;
|
||||
Equipment[k].Material = emu->equipment[k].Material;
|
||||
Equipment[k].Unknown1 = emu->equipment[k].Unknown1;
|
||||
Equipment[k].EliteMaterial = emu->equipment[k].EliteMaterial;
|
||||
}
|
||||
|
||||
Buffer += (sizeof(structs::EquipStruct) * 9);
|
||||
@@ -3329,7 +3337,7 @@ namespace SoD
|
||||
default:
|
||||
emu->command = eq->command;
|
||||
}
|
||||
OUT(unknown);
|
||||
IN(target);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -3484,7 +3492,7 @@ namespace SoD
|
||||
IN(material);
|
||||
IN(unknown06);
|
||||
IN(elite_material);
|
||||
IN(color.color);
|
||||
IN(color.Color);
|
||||
IN(wear_slot_id);
|
||||
emu->hero_forge_model = 0;
|
||||
emu->unknown18 = 0;
|
||||
|
||||
@@ -101,6 +101,8 @@ namespace SoD {
|
||||
}
|
||||
|
||||
namespace consts {
|
||||
static const size_t CHARACTER_CREATION_LIMIT = 12;
|
||||
|
||||
static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount;
|
||||
static const uint16 MAP_BANK_SIZE = 24;
|
||||
static const uint16 MAP_SHARED_BANK_SIZE = 2;
|
||||
@@ -174,9 +176,10 @@ namespace SoD {
|
||||
static const uint16 ITEM_COMMON_SIZE = 5;
|
||||
static const uint16 ITEM_CONTAINER_SIZE = 10;
|
||||
|
||||
static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 5;
|
||||
static const size_t BANDOLIERS_SIZE = 20; // number of bandolier instances
|
||||
static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance
|
||||
|
||||
static const size_t POTION_BELT_ITEM_COUNT = 5;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 50;
|
||||
}
|
||||
|
||||
+137
-117
@@ -103,54 +103,53 @@ struct AdventureInfo {
|
||||
*/
|
||||
struct Color_Struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 blue;
|
||||
uint8 green;
|
||||
uint8 red;
|
||||
uint8 use_tint; // if there's a tint this is FF
|
||||
} rgb;
|
||||
uint32 color;
|
||||
union {
|
||||
struct {
|
||||
uint8 Blue;
|
||||
uint8 Green;
|
||||
uint8 Red;
|
||||
uint8 UseTint; // if there's a tint this is FF
|
||||
} RGB;
|
||||
uint32 Color;
|
||||
};
|
||||
};
|
||||
|
||||
struct CharSelectEquip {
|
||||
//totally guessed;
|
||||
uint32 material;
|
||||
uint32 unknown1;
|
||||
uint32 elitematerial;
|
||||
Color_Struct color;
|
||||
struct CharSelectEquip
|
||||
{
|
||||
uint32 Material;
|
||||
uint32 Unknown1;
|
||||
uint32 EliteMaterial;
|
||||
Color_Struct Color;
|
||||
};
|
||||
|
||||
struct CharacterSelectEntry_Struct {
|
||||
/*0000*/ uint8 level; //
|
||||
/*0000*/ uint8 hairstyle; //
|
||||
/*0002*/ uint8 gender; //
|
||||
/*0003*/ char name[1]; //variable length, edi+0
|
||||
/*0000*/ uint8 beard; //
|
||||
/*0001*/ uint8 haircolor; //
|
||||
/*0000*/ uint8 face; //
|
||||
/*0000*/ CharSelectEquip equip[9];
|
||||
/*0000*/ uint32 primary; //
|
||||
/*0000*/ uint32 secondary; //
|
||||
/*0000*/ uint8 u15; // 0xff
|
||||
/*0000*/ uint32 deity; //
|
||||
/*0000*/ uint16 zone; //
|
||||
/*0000*/ uint16 instance;
|
||||
/*0000*/ uint8 gohome; //
|
||||
/*0000*/ uint8 u19; // 0xff
|
||||
/*0000*/ uint32 race; //
|
||||
/*0000*/ uint8 tutorial; //
|
||||
/*0000*/ uint8 class_; //
|
||||
/*0000*/ uint8 eyecolor1; //
|
||||
/*0000*/ uint8 beardcolor; //
|
||||
/*0000*/ uint8 eyecolor2; //
|
||||
/*0000*/ uint32 drakkin_heritage; // Drakkin Heritage
|
||||
/*0000*/ uint32 drakkin_tattoo; // Drakkin Tattoo
|
||||
/*0000*/ uint32 drakkin_details; // Drakkin Details (Facial Spikes)
|
||||
/*0000*/ uint8 unknown; // New field to SoD
|
||||
struct CharacterSelectEntry_Struct
|
||||
{
|
||||
/*0000*/ uint8 Level; //
|
||||
/*0000*/ uint8 HairStyle; //
|
||||
/*0002*/ uint8 Gender; //
|
||||
/*0003*/ char Name[1]; // variable length, edi+0
|
||||
/*0000*/ uint8 Beard; //
|
||||
/*0001*/ uint8 HairColor; //
|
||||
/*0000*/ uint8 Face; //
|
||||
/*0000*/ CharSelectEquip Equip[9];
|
||||
/*0000*/ uint32 PrimaryIDFile; //
|
||||
/*0000*/ uint32 SecondaryIDFile; //
|
||||
/*0000*/ uint8 Unknown15; // 0xff
|
||||
/*0000*/ uint32 Deity; //
|
||||
/*0000*/ uint16 Zone; //
|
||||
/*0000*/ uint16 Instance;
|
||||
/*0000*/ uint8 GoHome; //
|
||||
/*0000*/ uint8 Unknown19; // 0xff
|
||||
/*0000*/ uint32 Race; //
|
||||
/*0000*/ uint8 Tutorial; //
|
||||
/*0000*/ uint8 Class; //
|
||||
/*0000*/ uint8 EyeColor1; //
|
||||
/*0000*/ uint8 BeardColor; //
|
||||
/*0000*/ uint8 EyeColor2; //
|
||||
/*0000*/ uint32 DrakkinHeritage; // Drakkin Heritage
|
||||
/*0000*/ uint32 DrakkinTattoo; // Drakkin Tattoo
|
||||
/*0000*/ uint32 DrakkinDetails; // Drakkin Details (Facial Spikes)
|
||||
/*0000*/ uint8 Unknown; // New field to SoD
|
||||
|
||||
};
|
||||
|
||||
@@ -158,20 +157,22 @@ struct CharacterSelectEntry_Struct {
|
||||
** Character Selection Struct
|
||||
**
|
||||
*/
|
||||
struct CharacterSelect_Struct {
|
||||
/*0000*/ uint32 char_count; //number of chars in this packet
|
||||
/*0004*/ uint32 total_chars; //total number of chars allowed?
|
||||
/*0008*/ CharacterSelectEntry_Struct entries[0];
|
||||
struct CharacterSelect_Struct
|
||||
{
|
||||
/*0000*/ uint32 CharCount; //number of chars in this packet
|
||||
/*0004*/ uint32 TotalChars; //total number of chars allowed?
|
||||
/*0008*/ CharacterSelectEntry_Struct Entries[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* Visible equiptment.
|
||||
* Size: 12 Octets
|
||||
*/
|
||||
struct EquipStruct {
|
||||
/*00*/ uint32 material;
|
||||
/*04*/ uint32 unknown1;
|
||||
/*08*/ uint32 elitematerial;
|
||||
struct EquipStruct
|
||||
{
|
||||
/*00*/ uint32 Material;
|
||||
/*04*/ uint32 Unknown1;
|
||||
/*08*/ uint32 EliteMaterial;
|
||||
/*12*/
|
||||
};
|
||||
|
||||
@@ -285,7 +286,7 @@ struct Spawn_Struct
|
||||
/*0000*/ uint8 unknown12;
|
||||
/*0000*/ uint32 petOwnerId;
|
||||
/*0000*/ uint8 unknown13;
|
||||
/*0000*/ uint32 unknown14; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
/*0000*/ uint32 PlayerState; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
/*0000*/ uint32 unknown15;
|
||||
/*0000*/ uint32 unknown16;
|
||||
/*0000*/ uint32 unknown17;
|
||||
@@ -546,7 +547,7 @@ struct SpellBuff_Struct
|
||||
/*002*/ uint8 bard_modifier;
|
||||
/*003*/ uint8 effect; //not real
|
||||
/*004*/ uint32 spellid;
|
||||
/*008*/ uint32 duration;
|
||||
/*008*/ int32 duration;
|
||||
/*012*/ uint32 counters;
|
||||
/*016*/ uint32 unknown004; //Might need to be swapped with player_id
|
||||
/*020*/ uint32 player_id; //'global' ID of the caster, for wearoff messages
|
||||
@@ -563,7 +564,7 @@ struct SpellBuffFade_Struct {
|
||||
/*006*/ uint8 effect;
|
||||
/*007*/ uint8 unknown7;
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 unknown016;
|
||||
/*020*/ uint32 unknown020; //prolly global player ID
|
||||
/*024*/ uint32 playerId; // Player id who cast the buff
|
||||
@@ -665,7 +666,7 @@ struct AA_Array
|
||||
{
|
||||
uint32 AA;
|
||||
uint32 value;
|
||||
uint32 unknown08; // Looks like AA_Array is now 12 bytes in Live
|
||||
uint32 charges; // expendable
|
||||
};
|
||||
|
||||
|
||||
@@ -676,9 +677,6 @@ struct Disciplines_Struct {
|
||||
};
|
||||
|
||||
static const uint32 MAX_PLAYER_TRIBUTES = 5;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER = 20;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER_ITEMS = 4;
|
||||
static const uint32 MAX_POTIONS_IN_BELT = 5;
|
||||
static const uint32 TRIBUTE_NONE = 0xFFFFFFFF;
|
||||
|
||||
struct Tribute_Struct {
|
||||
@@ -686,26 +684,42 @@ struct Tribute_Struct {
|
||||
uint32 tier;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct {
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
char item_name[64];
|
||||
};
|
||||
|
||||
//len = 320
|
||||
enum { //bandolier item positions
|
||||
bandolierMainHand = 0,
|
||||
bandolierOffHand,
|
||||
// Bandolier item positions
|
||||
enum
|
||||
{
|
||||
bandolierPrimary = 0,
|
||||
bandolierSecondary,
|
||||
bandolierRange,
|
||||
bandolierAmmo
|
||||
};
|
||||
struct Bandolier_Struct {
|
||||
char name[32];
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
struct PotionBelt_Struct {
|
||||
BandolierItem_Struct items[MAX_POTIONS_IN_BELT];
|
||||
|
||||
//len = 320
|
||||
struct Bandolier_Struct
|
||||
{
|
||||
char Name[32];
|
||||
BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct PotionBeltItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
//len = 288
|
||||
struct PotionBelt_Struct
|
||||
{
|
||||
PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
|
||||
@@ -925,7 +939,7 @@ struct PlayerProfile_Struct
|
||||
/*08288*/ uint32 aapoints_spent; // Number of spent AA points
|
||||
/*08292*/ uint32 aapoints; // Unspent AA points
|
||||
/*08296*/ uint8 unknown06160[4];
|
||||
/*08300*/ Bandolier_Struct bandoliers[MAX_PLAYER_BANDOLIER]; // [6400] bandolier contents
|
||||
/*08300*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // [6400] bandolier contents
|
||||
/*14700*/ PotionBelt_Struct potionbelt; // [360] potion belt 72 extra octets by adding 1 more belt slot
|
||||
/*15060*/ uint8 unknown12852[8];
|
||||
/*15068*/ uint32 available_slots;
|
||||
@@ -1077,7 +1091,7 @@ struct TargetReject_Struct {
|
||||
|
||||
struct PetCommand_Struct {
|
||||
/*000*/ uint32 command;
|
||||
/*004*/ uint32 unknown;
|
||||
/*004*/ uint32 target;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1191,8 +1205,8 @@ struct RequestClientZoneChange_Struct {
|
||||
|
||||
struct Animation_Struct {
|
||||
/*00*/ uint16 spawnid;
|
||||
/*02*/ uint8 action;
|
||||
/*03*/ uint8 value;
|
||||
/*02*/ uint8 speed;
|
||||
/*03*/ uint8 action;
|
||||
/*04*/
|
||||
};
|
||||
|
||||
@@ -1258,9 +1272,11 @@ struct CombatDamage_Struct
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||
/* 05 */ uint16 spellid;
|
||||
/* 07 */ int32 damage;
|
||||
/* 11 */ float unknown11; // cd cc cc 3d
|
||||
/* 15 */ float sequence; // see above notes in Action_Struct
|
||||
/* 19 */ uint8 unknown19[9]; // was [9]
|
||||
/* 11 */ float force; // cd cc cc 3d
|
||||
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 19 */ float meleepush_z;
|
||||
/* 23 */ uint8 unknown23; // was [9]
|
||||
/* 24 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
|
||||
/* 28 */
|
||||
};
|
||||
|
||||
@@ -2357,7 +2373,7 @@ struct BookRequest_Struct {
|
||||
**
|
||||
*/
|
||||
struct Object_Struct {
|
||||
/*00*/ uint32 linked_list_addr[2];// <Zaphod> They are, get this, prev and next, ala linked list
|
||||
/*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list
|
||||
/*08*/ uint32 unknown008; // Something related to the linked list?
|
||||
/*12*/ uint32 drop_id; // Unique object id for zone
|
||||
/*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in
|
||||
@@ -2377,8 +2393,8 @@ struct Object_Struct {
|
||||
/*100*/ uint32 spawn_id; // Spawn Id of client interacting with object
|
||||
/*104*/
|
||||
};
|
||||
//<Zaphod> 01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] <Zaphod> and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
//01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
|
||||
/*
|
||||
** Click Object Struct
|
||||
@@ -3686,30 +3702,35 @@ struct DynamicWall_Struct {
|
||||
/*80*/
|
||||
};
|
||||
|
||||
enum { //bandolier actions
|
||||
BandolierCreate = 0,
|
||||
BandolierRemove = 1,
|
||||
BandolierSet = 2
|
||||
// Bandolier actions
|
||||
enum
|
||||
{
|
||||
bandolierCreate = 0,
|
||||
bandolierRemove,
|
||||
bandolierSet
|
||||
};
|
||||
|
||||
struct BandolierCreate_Struct {
|
||||
/*00*/ uint32 action; //0 for create
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ char name[32];
|
||||
/*37*/ uint16 unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 unknown39; //0
|
||||
struct BandolierCreate_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; //0 for create
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ char Name[32];
|
||||
/*37*/ uint16 Unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 Unknown39; //0
|
||||
};
|
||||
|
||||
struct BandolierDelete_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierDelete_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct BandolierSet_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierSet_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct Arrow_Struct {
|
||||
@@ -3793,16 +3814,21 @@ struct SendAA_Struct {
|
||||
/*0049*/ uint32 spellid;
|
||||
/*0053*/ uint32 spell_type;
|
||||
/*0057*/ uint32 spell_refresh;
|
||||
/*0061*/ uint16 classes;
|
||||
/*0063*/ uint16 berserker; //seems to be 1 if its a berserker ability
|
||||
/*0061*/ uint32 classes;
|
||||
/*0065*/ uint32 max_level;
|
||||
/*0069*/ uint32 last_id;
|
||||
/*0073*/ uint32 next_id;
|
||||
/*0077*/ uint32 cost2;
|
||||
/*0081*/ uint8 unknown80[7];
|
||||
/*0081*/ uint8 unknown81;
|
||||
/*0082*/ uint8 grant_only; // VetAAs, progression, etc
|
||||
/*0083*/ uint8 unknown83; // 1 for skill cap increase AAs, Mystical Attuning, and RNG attack inc, doesn't seem to matter though
|
||||
/*0084*/ uint32 expendable_charges; // max charges of the AA
|
||||
/*0088*/ uint32 aa_expansion;
|
||||
/*0092*/ uint32 special_category;
|
||||
/*0096*/ uint32 unknown0096;
|
||||
/*0096*/ uint8 shroud;
|
||||
/*0097*/ uint8 unknown97;
|
||||
/*0098*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter?
|
||||
/*0099*/ uint8 unknown99;
|
||||
/*0100*/ uint32 total_abilities;
|
||||
/*0104*/ AA_Ability abilities[0];
|
||||
};
|
||||
@@ -3814,16 +3840,10 @@ struct AA_List {
|
||||
struct AA_Action {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint32 ability;
|
||||
/*08*/ uint32 unknown08;
|
||||
/*08*/ uint32 target_id;
|
||||
/*12*/ uint32 exp_value;
|
||||
};
|
||||
|
||||
struct AA_Skills { //this should be removed and changed to AA_Array
|
||||
/*00*/ uint32 aa_skill; // Total AAs Spent
|
||||
/*04*/ uint32 aa_value;
|
||||
/*08*/ uint32 unknown08;
|
||||
};
|
||||
|
||||
struct AAExpUpdate_Struct {
|
||||
/*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability
|
||||
/*04*/ uint32 aapoints_unspent;
|
||||
@@ -3841,12 +3861,12 @@ struct AltAdvStats_Struct {
|
||||
};
|
||||
|
||||
struct PlayerAA_Struct { // Is this still used?
|
||||
AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AATable_Struct {
|
||||
/*00*/ int32 aa_spent; // Total AAs Spent
|
||||
/*04*/ AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
/*04*/ AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct Weather_Struct {
|
||||
@@ -4091,7 +4111,7 @@ struct ClickEffectStruct
|
||||
|
||||
struct ProcEffectStruct
|
||||
{
|
||||
uint32 effect;
|
||||
int32 effect;
|
||||
uint8 level2;
|
||||
uint32 type;
|
||||
uint8 level;
|
||||
@@ -4106,7 +4126,7 @@ struct ProcEffectStruct
|
||||
|
||||
struct WornEffectStruct //worn, focus and scroll effect
|
||||
{
|
||||
uint32 effect;
|
||||
int32 effect;
|
||||
uint8 level2;
|
||||
uint32 type;
|
||||
uint8 level;
|
||||
|
||||
+193
-167
@@ -426,7 +426,9 @@ namespace SoF
|
||||
OUT(type);
|
||||
OUT(spellid);
|
||||
OUT(damage);
|
||||
eq->sequence = emu->sequence;
|
||||
OUT(force);
|
||||
OUT(meleepush_xy);
|
||||
OUT(meleepush_z);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@@ -1200,13 +1202,13 @@ namespace SoF
|
||||
OUT(beard);
|
||||
// OUT(unknown00178[10]);
|
||||
for (r = 0; r < 9; r++) {
|
||||
eq->equipment[r].material = emu->item_material[r];
|
||||
eq->equipment[r].unknown1 = 0;
|
||||
eq->equipment[r].elitematerial = 0;
|
||||
eq->equipment[r].Material = emu->item_material[r];
|
||||
eq->equipment[r].Unknown1 = 0;
|
||||
eq->equipment[r].EliteMaterial = 0;
|
||||
//eq->colors[r].color = emu->colors[r].color;
|
||||
}
|
||||
for (r = 0; r < 7; r++) {
|
||||
OUT(item_tint[r].color);
|
||||
OUT(item_tint[r].Color);
|
||||
}
|
||||
// OUT(unknown00224[48]);
|
||||
//NOTE: new client supports 300 AAs, our internal rep/PP
|
||||
@@ -1214,6 +1216,7 @@ namespace SoF
|
||||
for (r = 0; r < MAX_PP_AA_ARRAY; r++) {
|
||||
OUT(aa_array[r].AA);
|
||||
OUT(aa_array[r].value);
|
||||
OUT(aa_array[r].charges);
|
||||
}
|
||||
// OUT(unknown02220[4]);
|
||||
OUT(mana);
|
||||
@@ -1264,26 +1267,46 @@ namespace SoF
|
||||
OUT(endurance);
|
||||
OUT(aapoints_spent);
|
||||
OUT(aapoints);
|
||||
|
||||
// OUT(unknown06160[4]);
|
||||
//NOTE: new client supports 20 bandoliers, our internal rep
|
||||
//only supports 4..
|
||||
for (r = 0; r < 4; r++) {
|
||||
OUT_str(bandoliers[r].name);
|
||||
uint32 k;
|
||||
for (k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) {
|
||||
OUT(bandoliers[r].items[k].item_id);
|
||||
OUT(bandoliers[r].items[k].icon);
|
||||
OUT_str(bandoliers[r].items[k].item_name);
|
||||
|
||||
// Copy bandoliers where server and client indexes converge
|
||||
for (r = 0; r < EmuConstants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
OUT_str(bandoliers[r].Name);
|
||||
for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true
|
||||
OUT(bandoliers[r].Items[k].ID);
|
||||
OUT(bandoliers[r].Items[k].Icon);
|
||||
OUT_str(bandoliers[r].Items[k].Name);
|
||||
}
|
||||
}
|
||||
// OUT(unknown07444[5120]);
|
||||
for (r = 0; r < structs::MAX_POTIONS_IN_BELT; r++) {
|
||||
OUT(potionbelt.items[r].item_id);
|
||||
OUT(potionbelt.items[r].icon);
|
||||
OUT_str(potionbelt.items[r].item_name);
|
||||
// Nullify bandoliers where server and client indexes diverge, with a client bias
|
||||
for (r = EmuConstants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
eq->bandoliers[r].Name[0] = '\0';
|
||||
for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true
|
||||
eq->bandoliers[r].Items[k].ID = 0;
|
||||
eq->bandoliers[r].Items[k].Icon = 0;
|
||||
eq->bandoliers[r].Items[k].Name[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
// OUT(unknown07444[5120]);
|
||||
|
||||
// Copy potion belt where server and client indexes converge
|
||||
for (r = 0; r < EmuConstants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
OUT(potionbelt.Items[r].ID);
|
||||
OUT(potionbelt.Items[r].Icon);
|
||||
OUT_str(potionbelt.Items[r].Name);
|
||||
}
|
||||
// Nullify potion belt where server and client indexes diverge, with a client bias
|
||||
for (r = EmuConstants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
eq->potionbelt.Items[r].ID = 0;
|
||||
eq->potionbelt.Items[r].Icon = 0;
|
||||
eq->potionbelt.Items[r].Name[0] = '\0';
|
||||
}
|
||||
|
||||
// OUT(unknown12852[8]);
|
||||
// OUT(unknown12864[76]);
|
||||
|
||||
OUT_str(name);
|
||||
OUT_str(last_name);
|
||||
OUT(guild_id);
|
||||
@@ -1312,8 +1335,8 @@ namespace SoF
|
||||
OUT(copper_bank);
|
||||
OUT(platinum_shared);
|
||||
// OUT(unknown13156[84]);
|
||||
//OUT(expansions);
|
||||
eq->expansions = 16383;
|
||||
OUT(expansions);
|
||||
//eq->expansions = 16383;
|
||||
// OUT(unknown13244[12]);
|
||||
OUT(autosplit);
|
||||
// OUT(unknown13260[16]);
|
||||
@@ -1497,129 +1520,150 @@ namespace SoF
|
||||
|
||||
ENCODE(OP_SendAATable)
|
||||
{
|
||||
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
|
||||
EQApplicationPacket *inapp = *p;
|
||||
*p = nullptr;
|
||||
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
|
||||
|
||||
SETUP_VAR_ENCODE(SendAA_Struct);
|
||||
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability));
|
||||
structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer;
|
||||
|
||||
// Check clientver field to verify this AA should be sent for SoF
|
||||
// clientver 1 is for all clients and 4 is for SoF
|
||||
if (emu->clientver <= 4)
|
||||
{
|
||||
OUT(id);
|
||||
eq->unknown004 = 1;
|
||||
//eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1);
|
||||
//eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1);
|
||||
//eq->title_sid = emu->id - emu->current_level + 1;
|
||||
//eq->desc_sid = emu->id - emu->current_level + 1;
|
||||
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->sof_next_skill);
|
||||
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->sof_next_skill);
|
||||
eq->title_sid = emu->sof_next_skill;
|
||||
eq->desc_sid = emu->sof_next_skill;
|
||||
OUT(class_type);
|
||||
OUT(cost);
|
||||
OUT(seq);
|
||||
OUT(current_level);
|
||||
OUT(prereq_skill);
|
||||
OUT(prereq_minpoints);
|
||||
eq->type = emu->sof_type;
|
||||
OUT(spellid);
|
||||
OUT(spell_type);
|
||||
OUT(spell_refresh);
|
||||
OUT(classes);
|
||||
OUT(berserker);
|
||||
//eq->max_level = emu->sof_max_level;
|
||||
OUT(max_level);
|
||||
OUT(last_id);
|
||||
OUT(next_id);
|
||||
OUT(cost2);
|
||||
eq->aa_expansion = emu->aa_expansion;
|
||||
eq->special_category = emu->special_category;
|
||||
OUT(total_abilities);
|
||||
unsigned int r;
|
||||
for (r = 0; r < emu->total_abilities; r++) {
|
||||
OUT(abilities[r].skill_id);
|
||||
OUT(abilities[r].base1);
|
||||
OUT(abilities[r].base2);
|
||||
OUT(abilities[r].slot);
|
||||
}
|
||||
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
|
||||
outapp->SetWritePosition(sizeof(structs::SendAA_Struct));
|
||||
|
||||
eq->id = emu->id;
|
||||
eq->unknown004 = 1;
|
||||
eq->id = emu->id;
|
||||
eq->hotkey_sid = emu->upper_hotkey_sid;
|
||||
eq->hotkey_sid2 = emu->lower_hotkey_sid;
|
||||
eq->desc_sid = emu->desc_sid;
|
||||
eq->title_sid = emu->title_sid;
|
||||
eq->class_type = emu->level_req;
|
||||
eq->cost = emu->cost;
|
||||
eq->seq = emu->seq;
|
||||
eq->current_level = emu->current_level;
|
||||
eq->type = emu->type;
|
||||
eq->spellid = emu->spell;
|
||||
eq->spell_type = emu->spell_type;
|
||||
eq->spell_refresh = emu->spell_refresh;
|
||||
eq->classes = emu->classes;
|
||||
eq->max_level = emu->max_level;
|
||||
eq->last_id = emu->prev_id;
|
||||
eq->next_id = emu->next_id;
|
||||
eq->cost2 = emu->total_cost;
|
||||
eq->grant_only = emu->grant_only;
|
||||
eq->expendable_charges = emu->charges;
|
||||
eq->aa_expansion = emu->expansion;
|
||||
eq->special_category = emu->category;
|
||||
eq->total_abilities = emu->total_effects;
|
||||
|
||||
for(auto i = 0; i < eq->total_abilities; ++i) {
|
||||
eq->abilities[i].skill_id = inapp->ReadUInt32();
|
||||
eq->abilities[i].base1 = inapp->ReadUInt32();
|
||||
eq->abilities[i].base2 = inapp->ReadUInt32();
|
||||
eq->abilities[i].slot = inapp->ReadUInt32();
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
if(emu->total_prereqs > 0) {
|
||||
eq->prereq_skill = inapp->ReadUInt32();
|
||||
eq->prereq_minpoints = inapp->ReadUInt32();
|
||||
}
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
delete inapp;
|
||||
}
|
||||
|
||||
ENCODE(OP_SendCharInfo)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(CharacterSelect_Struct);
|
||||
ENCODE_LENGTH_ATLEAST(CharacterSelect_Struct);
|
||||
SETUP_VAR_ENCODE(CharacterSelect_Struct);
|
||||
|
||||
//EQApplicationPacket *packet = *p;
|
||||
//const CharacterSelect_Struct *emu = (CharacterSelect_Struct *) packet->pBuffer;
|
||||
// Zero-character count shunt
|
||||
if (emu->CharCount == 0) {
|
||||
ALLOC_VAR_ENCODE(structs::CharacterSelect_Struct, sizeof(structs::CharacterSelect_Struct));
|
||||
eq->CharCount = emu->CharCount;
|
||||
eq->TotalChars = emu->TotalChars;
|
||||
|
||||
int char_count;
|
||||
int namelen = 0;
|
||||
for (char_count = 0; char_count < 10; char_count++) {
|
||||
if (emu->name[char_count][0] == '\0')
|
||||
break;
|
||||
if (strcmp(emu->name[char_count], "<none>") == 0)
|
||||
break;
|
||||
namelen += strlen(emu->name[char_count]);
|
||||
if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT)
|
||||
eq->TotalChars = consts::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
FINISH_ENCODE();
|
||||
return;
|
||||
}
|
||||
|
||||
int total_length = sizeof(structs::CharacterSelect_Struct)
|
||||
+ char_count * sizeof(structs::CharacterSelectEntry_Struct)
|
||||
+ namelen;
|
||||
unsigned char *emu_ptr = __emu_buffer;
|
||||
emu_ptr += sizeof(CharacterSelect_Struct);
|
||||
CharacterSelectEntry_Struct *emu_cse = (CharacterSelectEntry_Struct *)nullptr;
|
||||
|
||||
size_t names_length = 0;
|
||||
size_t character_count = 0;
|
||||
for (; character_count < emu->CharCount && character_count < consts::CHARACTER_CREATION_LIMIT; ++character_count) {
|
||||
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
||||
names_length += strlen(emu_cse->Name);
|
||||
emu_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
size_t total_length = sizeof(structs::CharacterSelect_Struct)
|
||||
+ character_count * sizeof(structs::CharacterSelectEntry_Struct)
|
||||
+ names_length;
|
||||
|
||||
ALLOC_VAR_ENCODE(structs::CharacterSelect_Struct, total_length);
|
||||
structs::CharacterSelectEntry_Struct *eq_cse = (structs::CharacterSelectEntry_Struct *)nullptr;
|
||||
|
||||
//unsigned char *eq_buffer = new unsigned char[total_length];
|
||||
//structs::CharacterSelect_Struct *eq_head = (structs::CharacterSelect_Struct *) eq_buffer;
|
||||
eq->CharCount = character_count;
|
||||
eq->TotalChars = emu->TotalChars;
|
||||
|
||||
eq->char_count = char_count;
|
||||
eq->total_chars = 10;
|
||||
if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT)
|
||||
eq->TotalChars = consts::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
unsigned char *bufptr = (unsigned char *)eq->entries;
|
||||
int r;
|
||||
for (r = 0; r < char_count; r++) {
|
||||
{ //pre-name section...
|
||||
structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr;
|
||||
eq2->level = emu->level[r];
|
||||
eq2->hairstyle = emu->hairstyle[r];
|
||||
eq2->gender = emu->gender[r];
|
||||
memcpy(eq2->name, emu->name[r], strlen(emu->name[r]) + 1);
|
||||
emu_ptr = __emu_buffer;
|
||||
emu_ptr += sizeof(CharacterSelect_Struct);
|
||||
|
||||
unsigned char *eq_ptr = __packet->pBuffer;
|
||||
eq_ptr += sizeof(structs::CharacterSelect_Struct);
|
||||
|
||||
for (int counter = 0; counter < character_count; ++counter) {
|
||||
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
||||
eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // base address
|
||||
|
||||
eq_cse->Level = emu_cse->Level;
|
||||
eq_cse->HairStyle = emu_cse->HairStyle;
|
||||
eq_cse->Gender = emu_cse->Gender;
|
||||
|
||||
strcpy(eq_cse->Name, emu_cse->Name);
|
||||
eq_ptr += strlen(emu_cse->Name);
|
||||
eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // offset address (base + name length offset)
|
||||
eq_cse->Name[0] = '\0'; // (offset)eq_cse->Name[0] = (base)eq_cse->Name[strlen(emu_cse->Name)]
|
||||
|
||||
eq_cse->Beard = emu_cse->Beard;
|
||||
eq_cse->HairColor = emu_cse->HairColor;
|
||||
eq_cse->Face = emu_cse->Face;
|
||||
|
||||
for (int equip_index = 0; equip_index < _MaterialCount; equip_index++) {
|
||||
eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material;
|
||||
eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1;
|
||||
eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial;
|
||||
eq_cse->Equip[equip_index].Color.Color = emu_cse->Equip[equip_index].Color.Color;
|
||||
}
|
||||
//adjust for name.
|
||||
bufptr += strlen(emu->name[r]);
|
||||
{ //post-name section...
|
||||
structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr;
|
||||
eq2->beard = emu->beard[r];
|
||||
eq2->haircolor = emu->haircolor[r];
|
||||
eq2->face = emu->face[r];
|
||||
int k;
|
||||
for (k = 0; k < _MaterialCount; k++) {
|
||||
eq2->equip[k].material = emu->equip[r][k].material;
|
||||
eq2->equip[k].unknown1 = emu->equip[r][k].unknown1;
|
||||
eq2->equip[k].elitematerial = emu->equip[r][k].elitematerial;
|
||||
eq2->equip[k].color.color = emu->equip[r][k].color.color;
|
||||
}
|
||||
eq2->primary = emu->primary[r];
|
||||
eq2->secondary = emu->secondary[r];
|
||||
eq2->tutorial = emu->tutorial[r]; // was u15
|
||||
eq2->u15 = 0xff;
|
||||
eq2->deity = emu->deity[r];
|
||||
eq2->zone = emu->zone[r];
|
||||
eq2->u19 = 0xFF;
|
||||
eq2->race = emu->race[r];
|
||||
eq2->gohome = emu->gohome[r];
|
||||
eq2->class_ = emu->class_[r];
|
||||
eq2->eyecolor1 = emu->eyecolor1[r];
|
||||
eq2->beardcolor = emu->beardcolor[r];
|
||||
eq2->eyecolor2 = emu->eyecolor2[r];
|
||||
eq2->drakkin_heritage = emu->drakkin_heritage[r];
|
||||
eq2->drakkin_tattoo = emu->drakkin_tattoo[r];
|
||||
eq2->drakkin_details = emu->drakkin_details[r];
|
||||
}
|
||||
bufptr += sizeof(structs::CharacterSelectEntry_Struct);
|
||||
|
||||
eq_cse->PrimaryIDFile = emu_cse->PrimaryIDFile;
|
||||
eq_cse->SecondaryIDFile = emu_cse->SecondaryIDFile;
|
||||
eq_cse->Tutorial = emu_cse->Tutorial;
|
||||
eq_cse->Unknown15 = emu_cse->Unknown15;
|
||||
eq_cse->Deity = emu_cse->Deity;
|
||||
eq_cse->Zone = emu_cse->Zone;
|
||||
eq_cse->Unknown19 = emu_cse->Unknown19;
|
||||
eq_cse->Race = emu_cse->Race;
|
||||
eq_cse->GoHome = emu_cse->GoHome;
|
||||
eq_cse->Class = emu_cse->Class;
|
||||
eq_cse->EyeColor1 = emu_cse->EyeColor1;
|
||||
eq_cse->BeardColor = emu_cse->BeardColor;
|
||||
eq_cse->EyeColor2 = emu_cse->EyeColor2;
|
||||
eq_cse->DrakkinHeritage = emu_cse->DrakkinHeritage;
|
||||
eq_cse->DrakkinTattoo = emu_cse->DrakkinTattoo;
|
||||
eq_cse->DrakkinDetails = emu_cse->DrakkinDetails;
|
||||
|
||||
emu_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
eq_ptr += sizeof(structs::CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -1941,7 +1985,7 @@ namespace SoF
|
||||
OUT(material);
|
||||
OUT(unknown06);
|
||||
OUT(elite_material);
|
||||
OUT(color.color);
|
||||
OUT(color.Color);
|
||||
OUT(wear_slot_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -1951,42 +1995,23 @@ namespace SoF
|
||||
|
||||
ENCODE(OP_ZonePlayerToBind)
|
||||
{
|
||||
ENCODE_LENGTH_ATLEAST(ZonePlayerToBind_Struct);
|
||||
SETUP_VAR_ENCODE(ZonePlayerToBind_Struct);
|
||||
ALLOC_LEN_ENCODE(sizeof(structs::ZonePlayerToBind_Struct) + strlen(emu->zone_name));
|
||||
|
||||
ZonePlayerToBind_Struct *zps = (ZonePlayerToBind_Struct*)(*p)->pBuffer;
|
||||
__packet->SetWritePosition(0);
|
||||
__packet->WriteUInt16(emu->bind_zone_id);
|
||||
__packet->WriteUInt16(emu->bind_instance_id);
|
||||
__packet->WriteFloat(emu->x);
|
||||
__packet->WriteFloat(emu->y);
|
||||
__packet->WriteFloat(emu->z);
|
||||
__packet->WriteFloat(emu->heading);
|
||||
__packet->WriteString(emu->zone_name);
|
||||
__packet->WriteUInt8(1); // save items
|
||||
__packet->WriteUInt32(0); // hp
|
||||
__packet->WriteUInt32(0); // mana
|
||||
__packet->WriteUInt32(0); // endurance
|
||||
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
||||
|
||||
unsigned char *buffer1 = new unsigned char[sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)];
|
||||
structs::ZonePlayerToBindHeader_Struct *zph = (structs::ZonePlayerToBindHeader_Struct*)buffer1;
|
||||
unsigned char *buffer2 = new unsigned char[sizeof(structs::ZonePlayerToBindFooter_Struct)];
|
||||
structs::ZonePlayerToBindFooter_Struct *zpf = (structs::ZonePlayerToBindFooter_Struct*)buffer2;
|
||||
|
||||
zph->x = zps->x;
|
||||
zph->y = zps->y;
|
||||
zph->z = zps->z;
|
||||
zph->heading = zps->heading;
|
||||
zph->bind_zone_id = zps->bind_zone_id;
|
||||
zph->bind_instance_id = zps->bind_instance_id;
|
||||
strcpy(zph->zone_name, zps->zone_name);
|
||||
|
||||
zpf->unknown021 = 1;
|
||||
zpf->unknown022 = 0;
|
||||
zpf->unknown023 = 0;
|
||||
zpf->unknown024 = 0;
|
||||
|
||||
ss.write((const char*)buffer1, (sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)));
|
||||
ss.write((const char*)buffer2, sizeof(structs::ZonePlayerToBindFooter_Struct));
|
||||
|
||||
delete[] buffer1;
|
||||
delete[] buffer2;
|
||||
delete[](*p)->pBuffer;
|
||||
|
||||
(*p)->pBuffer = new unsigned char[ss.str().size()];
|
||||
(*p)->size = ss.str().size();
|
||||
|
||||
memcpy((*p)->pBuffer, ss.str().c_str(), ss.str().size());
|
||||
dest->FastQueuePacket(&(*p));
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ZoneServerInfo)
|
||||
@@ -2044,10 +2069,10 @@ namespace SoF
|
||||
eq->drakkin_heritage = emu->drakkin_heritage;
|
||||
eq->gender = emu->gender;
|
||||
for (k = 0; k < 9; k++) {
|
||||
eq->equipment[k].material = emu->equipment[k].material;
|
||||
eq->equipment[k].unknown1 = emu->equipment[k].unknown1;
|
||||
eq->equipment[k].elitematerial = emu->equipment[k].elitematerial;
|
||||
eq->colors[k].color = emu->colors[k].color;
|
||||
eq->equipment[k].Material = emu->equipment[k].Material;
|
||||
eq->equipment[k].Unknown1 = emu->equipment[k].Unknown1;
|
||||
eq->equipment[k].EliteMaterial = emu->equipment[k].EliteMaterial;
|
||||
eq->colors[k].Color = emu->colors[k].Color;
|
||||
}
|
||||
eq->StandState = emu->StandState;
|
||||
eq->guildID = emu->guildID;
|
||||
@@ -2066,6 +2091,7 @@ namespace SoF
|
||||
eq->runspeed = emu->runspeed;
|
||||
eq->light = emu->light;
|
||||
eq->level = emu->level;
|
||||
eq->PlayerState = emu->PlayerState;
|
||||
eq->lfg = emu->lfg;
|
||||
eq->hairstyle = emu->hairstyle;
|
||||
eq->haircolor = emu->haircolor;
|
||||
@@ -2109,7 +2135,7 @@ namespace SoF
|
||||
eq->petOwnerId = emu->petOwnerId;
|
||||
eq->pvp = 0; // 0 = non-pvp colored name, 1 = red pvp name
|
||||
for (k = 0; k < 9; k++) {
|
||||
eq->colors[k].color = emu->colors[k].color;
|
||||
eq->colors[k].Color = emu->colors[k].Color;
|
||||
}
|
||||
eq->anon = emu->anon;
|
||||
eq->face = emu->face;
|
||||
@@ -2667,7 +2693,7 @@ namespace SoF
|
||||
default:
|
||||
emu->command = eq->command;
|
||||
}
|
||||
OUT(unknown);
|
||||
IN(target);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -2808,7 +2834,7 @@ namespace SoF
|
||||
IN(material);
|
||||
IN(unknown06);
|
||||
IN(elite_material);
|
||||
IN(color.color);
|
||||
IN(color.Color);
|
||||
IN(wear_slot_id);
|
||||
emu->hero_forge_model = 0;
|
||||
emu->unknown18 = 0;
|
||||
|
||||
@@ -101,6 +101,8 @@ namespace SoF {
|
||||
}
|
||||
|
||||
namespace consts {
|
||||
static const size_t CHARACTER_CREATION_LIMIT = 12;
|
||||
|
||||
static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount;
|
||||
static const uint16 MAP_BANK_SIZE = 24;
|
||||
static const uint16 MAP_SHARED_BANK_SIZE = 2;
|
||||
@@ -174,9 +176,10 @@ namespace SoF {
|
||||
static const uint16 ITEM_COMMON_SIZE = 5;
|
||||
static const uint16 ITEM_CONTAINER_SIZE = 10;
|
||||
|
||||
static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 5;
|
||||
static const size_t BANDOLIERS_SIZE = 20; // number of bandolier instances
|
||||
static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance
|
||||
|
||||
static const size_t POTION_BELT_ITEM_COUNT = 5;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 50;
|
||||
}
|
||||
|
||||
+134
-115
@@ -103,72 +103,74 @@ struct AdventureInfo {
|
||||
*/
|
||||
struct Color_Struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 blue;
|
||||
uint8 green;
|
||||
uint8 red;
|
||||
uint8 use_tint; // if there's a tint this is FF
|
||||
} rgb;
|
||||
uint32 color;
|
||||
union {
|
||||
struct {
|
||||
uint8 Blue;
|
||||
uint8 Green;
|
||||
uint8 Red;
|
||||
uint8 UseTint; // if there's a tint this is FF
|
||||
} RGB;
|
||||
uint32 Color;
|
||||
};
|
||||
};
|
||||
|
||||
struct CharSelectEquip {
|
||||
uint32 material;
|
||||
uint32 unknown1;
|
||||
uint32 elitematerial;
|
||||
Color_Struct color;
|
||||
struct CharSelectEquip
|
||||
{
|
||||
uint32 Material;
|
||||
uint32 Unknown1;
|
||||
uint32 EliteMaterial;
|
||||
Color_Struct Color;
|
||||
};
|
||||
|
||||
struct CharacterSelectEntry_Struct {
|
||||
/*0000*/ uint8 level; //
|
||||
/*0000*/ uint8 hairstyle; //
|
||||
/*0002*/ uint8 gender; //
|
||||
/*0003*/ char name[1]; //variable length, edi+0
|
||||
/*0000*/ uint8 beard; //
|
||||
/*0001*/ uint8 haircolor; //
|
||||
/*0000*/ uint8 face; //
|
||||
/*0000*/ CharSelectEquip equip[9];
|
||||
/*0000*/ uint32 primary; //
|
||||
/*0000*/ uint32 secondary; //
|
||||
/*0000*/ uint8 u15; // 0xff
|
||||
/*0000*/ uint32 deity; //
|
||||
/*0000*/ uint16 zone; //
|
||||
/*0000*/ uint16 instance;
|
||||
/*0000*/ uint8 gohome; //
|
||||
/*0000*/ uint8 u19; // 0xff
|
||||
/*0000*/ uint32 race; //
|
||||
/*0000*/ uint8 tutorial; //
|
||||
/*0000*/ uint8 class_; //
|
||||
/*0000*/ uint8 eyecolor1; //
|
||||
/*0000*/ uint8 beardcolor; //
|
||||
/*0000*/ uint8 eyecolor2; //
|
||||
/*0000*/ uint32 drakkin_heritage; // Drakkin Heritage
|
||||
/*0000*/ uint32 drakkin_tattoo; // Drakkin Tattoo
|
||||
/*0000*/ uint32 drakkin_details; // Drakkin Details (Facial Spikes)
|
||||
struct CharacterSelectEntry_Struct
|
||||
{
|
||||
/*0000*/ uint8 Level; //
|
||||
/*0000*/ uint8 HairStyle; //
|
||||
/*0002*/ uint8 Gender; //
|
||||
/*0003*/ char Name[1]; // variable length, edi+0
|
||||
/*0000*/ uint8 Beard; //
|
||||
/*0001*/ uint8 HairColor; //
|
||||
/*0000*/ uint8 Face; //
|
||||
/*0000*/ CharSelectEquip Equip[9];
|
||||
/*0000*/ uint32 PrimaryIDFile; //
|
||||
/*0000*/ uint32 SecondaryIDFile; //
|
||||
/*0000*/ uint8 Unknown15; // 0xff
|
||||
/*0000*/ uint32 Deity; //
|
||||
/*0000*/ uint16 Zone; //
|
||||
/*0000*/ uint16 Instance;
|
||||
/*0000*/ uint8 GoHome; //
|
||||
/*0000*/ uint8 Unknown19; // 0xff
|
||||
/*0000*/ uint32 Race; //
|
||||
/*0000*/ uint8 Tutorial; //
|
||||
/*0000*/ uint8 Class; //
|
||||
/*0000*/ uint8 EyeColor1; //
|
||||
/*0000*/ uint8 BeardColor; //
|
||||
/*0000*/ uint8 EyeColor2; //
|
||||
/*0000*/ uint32 DrakkinHeritage; // Drakkin Heritage
|
||||
/*0000*/ uint32 DrakkinTattoo; // Drakkin Tattoo
|
||||
/*0000*/ uint32 DrakkinDetails; // Drakkin Details (Facial Spikes)
|
||||
};
|
||||
|
||||
/*
|
||||
** Character Selection Struct
|
||||
**
|
||||
*/
|
||||
struct CharacterSelect_Struct {
|
||||
/*0000*/ uint32 char_count; //number of chars in this packet
|
||||
/*0004*/ uint32 total_chars; //total number of chars allowed?
|
||||
/*0008*/ CharacterSelectEntry_Struct entries[0];
|
||||
struct CharacterSelect_Struct
|
||||
{
|
||||
/*0000*/ uint32 CharCount; //number of chars in this packet
|
||||
/*0004*/ uint32 TotalChars; //total number of chars allowed?
|
||||
/*0008*/ CharacterSelectEntry_Struct Entries[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* Visible equiptment.
|
||||
* Size: 12 Octets
|
||||
*/
|
||||
struct EquipStruct {
|
||||
/*00*/ uint32 material;
|
||||
/*04*/ uint32 unknown1;
|
||||
/*08*/ uint32 elitematerial;
|
||||
struct EquipStruct
|
||||
{
|
||||
/*00*/ uint32 Material;
|
||||
/*04*/ uint32 Unknown1;
|
||||
/*08*/ uint32 EliteMaterial;
|
||||
/*12*/
|
||||
};
|
||||
|
||||
@@ -239,7 +241,8 @@ struct Spawn_Struct {
|
||||
/*0506*/ uint8 light; // Spawn's lightsource
|
||||
/*0507*/ uint8 unknown0507[4];
|
||||
/*0511*/ uint8 level; // Spawn Level
|
||||
/*0512*/ uint8 unknown0512[16];
|
||||
/*0512*/ uint32 PlayerState;
|
||||
/*0516*/ uint8 unknown0516[12];
|
||||
/*0528*/ uint8 lfg;
|
||||
/*0529*/ uint8 unknown0529[4];
|
||||
/*0533*/ uint8 hairstyle; // Sets the style of hair
|
||||
@@ -523,7 +526,7 @@ struct SpellBuff_Struct
|
||||
/*002*/ uint8 bard_modifier;
|
||||
/*003*/ uint8 effect; //not real
|
||||
/*004*/ uint32 spellid;
|
||||
/*008*/ uint32 duration;
|
||||
/*008*/ int32 duration;
|
||||
/*012*/ uint32 counters;
|
||||
/*016*/ uint32 unknown004; //Might need to be swapped with player_id
|
||||
/*020*/ uint32 player_id; //'global' ID of the caster, for wearoff messages
|
||||
@@ -540,7 +543,7 @@ struct SpellBuffFade_Struct {
|
||||
/*006*/ uint8 effect;
|
||||
/*007*/ uint8 unknown7;
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 unknown016;
|
||||
/*020*/ uint32 unknown020; //prolly global player ID
|
||||
/*024*/ uint32 playerId; // Player id who cast the buff
|
||||
@@ -642,7 +645,7 @@ struct AA_Array
|
||||
{
|
||||
uint32 AA;
|
||||
uint32 value;
|
||||
uint32 unknown08; // Looks like AA_Array is now 12 bytes in Live
|
||||
uint32 charges; // expendable charges
|
||||
};
|
||||
|
||||
|
||||
@@ -653,9 +656,6 @@ struct Disciplines_Struct {
|
||||
};
|
||||
|
||||
static const uint32 MAX_PLAYER_TRIBUTES = 5;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER = 20;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER_ITEMS = 4;
|
||||
static const uint32 MAX_POTIONS_IN_BELT = 5;
|
||||
static const uint32 TRIBUTE_NONE = 0xFFFFFFFF;
|
||||
|
||||
struct Tribute_Struct {
|
||||
@@ -663,26 +663,42 @@ struct Tribute_Struct {
|
||||
uint32 tier;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct {
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
char item_name[64];
|
||||
};
|
||||
|
||||
//len = 320
|
||||
enum { //bandolier item positions
|
||||
bandolierMainHand = 0,
|
||||
bandolierOffHand,
|
||||
// Bandolier item positions
|
||||
enum
|
||||
{
|
||||
bandolierPrimary = 0,
|
||||
bandolierSecondary,
|
||||
bandolierRange,
|
||||
bandolierAmmo
|
||||
};
|
||||
struct Bandolier_Struct {
|
||||
char name[32];
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
struct PotionBelt_Struct {
|
||||
BandolierItem_Struct items[MAX_POTIONS_IN_BELT];
|
||||
|
||||
//len = 320
|
||||
struct Bandolier_Struct
|
||||
{
|
||||
char Name[32];
|
||||
BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct PotionBeltItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
//len = 288
|
||||
struct PotionBelt_Struct
|
||||
{
|
||||
PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
|
||||
@@ -901,7 +917,7 @@ struct PlayerProfile_Struct //23576 Octets
|
||||
/*08288*/ uint32 aapoints_spent; // Number of spent AA points
|
||||
/*08292*/ uint32 aapoints; // Unspent AA points
|
||||
/*08296*/ uint8 unknown06160[4];
|
||||
/*08300*/ Bandolier_Struct bandoliers[MAX_PLAYER_BANDOLIER]; // [6400] bandolier contents
|
||||
/*08300*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // [6400] bandolier contents
|
||||
/*14700*/ PotionBelt_Struct potionbelt; // [360] potion belt 72 extra octets by adding 1 more belt slot
|
||||
/*15060*/ uint8 unknown12852[8];
|
||||
/*15068*/ uint32 available_slots;
|
||||
@@ -1053,7 +1069,7 @@ struct TargetReject_Struct {
|
||||
|
||||
struct PetCommand_Struct {
|
||||
/*000*/ uint32 command;
|
||||
/*004*/ uint32 unknown;
|
||||
/*004*/ uint32 target;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1167,8 +1183,8 @@ struct RequestClientZoneChange_Struct {
|
||||
|
||||
struct Animation_Struct {
|
||||
/*00*/ uint16 spawnid;
|
||||
/*02*/ uint8 action;
|
||||
/*03*/ uint8 value;
|
||||
/*02*/ uint8 speed;
|
||||
/*03*/ uint8 action;
|
||||
/*04*/
|
||||
};
|
||||
|
||||
@@ -1234,9 +1250,10 @@ struct CombatDamage_Struct
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||
/* 05 */ uint16 spellid;
|
||||
/* 07 */ int32 damage;
|
||||
/* 11 */ float unknown11; // cd cc cc 3d
|
||||
/* 15 */ float sequence; // see above notes in Action_Struct
|
||||
/* 19 */ uint8 unknown19[9]; // was [9]
|
||||
/* 11 */ float force; // cd cc cc 3d
|
||||
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 19 */ float meleepush_z;
|
||||
/* 23 */ uint8 unknown23[5]; // was [9] this appears unrelated to the stuff the other clients do here?
|
||||
/* 28 */
|
||||
};
|
||||
|
||||
@@ -2290,7 +2307,7 @@ struct BookRequest_Struct {
|
||||
**
|
||||
*/
|
||||
struct Object_Struct {
|
||||
/*00*/ uint32 linked_list_addr[2];// <Zaphod> They are, get this, prev and next, ala linked list
|
||||
/*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list
|
||||
/*08*/ uint32 unknown008; // Something related to the linked list?
|
||||
/*12*/ uint32 drop_id; // Unique object id for zone
|
||||
/*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in
|
||||
@@ -2310,8 +2327,8 @@ struct Object_Struct {
|
||||
/*100*/ uint32 spawn_id; // Spawn Id of client interacting with object
|
||||
/*104*/
|
||||
};
|
||||
//<Zaphod> 01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] <Zaphod> and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
//01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
|
||||
/*
|
||||
** Click Object Struct
|
||||
@@ -3548,30 +3565,35 @@ struct DynamicWall_Struct {
|
||||
/*80*/
|
||||
};
|
||||
|
||||
enum { //bandolier actions
|
||||
BandolierCreate = 0,
|
||||
BandolierRemove = 1,
|
||||
BandolierSet = 2
|
||||
// Bandolier actions
|
||||
enum
|
||||
{
|
||||
bandolierCreate = 0,
|
||||
bandolierRemove,
|
||||
bandolierSet
|
||||
};
|
||||
|
||||
struct BandolierCreate_Struct {
|
||||
/*00*/ uint32 action; //0 for create
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ char name[32];
|
||||
/*37*/ uint16 unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 unknown39; //0
|
||||
struct BandolierCreate_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; //0 for create
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ char Name[32];
|
||||
/*37*/ uint16 Unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 Unknown39; //0
|
||||
};
|
||||
|
||||
struct BandolierDelete_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierDelete_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct BandolierSet_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierSet_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct Arrow_Struct {
|
||||
@@ -3655,16 +3677,19 @@ struct SendAA_Struct {
|
||||
/*0049*/ uint32 spellid;
|
||||
/*0053*/ uint32 spell_type;
|
||||
/*0057*/ uint32 spell_refresh;
|
||||
/*0061*/ uint16 classes;
|
||||
/*0063*/ uint16 berserker; //seems to be 1 if its a berserker ability
|
||||
/*0061*/ uint32 classes;
|
||||
/*0065*/ uint32 max_level;
|
||||
/*0069*/ uint32 last_id;
|
||||
/*0073*/ uint32 next_id;
|
||||
/*0077*/ uint32 cost2;
|
||||
/*0081*/ uint8 unknown80[7];
|
||||
/*0081*/ uint8 unknown81;
|
||||
/*0082*/ uint8 grant_only; // VetAAs, progression, etc
|
||||
/*0083*/ uint8 unknown83; // 1 for skill cap increase AAs, Mystical Attuning, and RNG attack inc, doesn't seem to matter though
|
||||
/*0084*/ uint32 expendable_charges; // max charges of the AA
|
||||
/*0088*/ uint32 aa_expansion;
|
||||
/*0092*/ uint32 special_category;
|
||||
/*0096*/ uint16 unknown0096;
|
||||
/*0096*/ uint8 shroud;
|
||||
/*0097*/ uint8 unknown97;
|
||||
/*0098*/ uint32 total_abilities;
|
||||
/*0102*/ AA_Ability abilities[0];
|
||||
};
|
||||
@@ -3676,16 +3701,10 @@ struct AA_List {
|
||||
struct AA_Action {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint32 ability;
|
||||
/*08*/ uint32 unknown08;
|
||||
/*08*/ uint32 target_id;
|
||||
/*12*/ uint32 exp_value;
|
||||
};
|
||||
|
||||
struct AA_Skills { //this should be removed and changed to AA_Array
|
||||
/*00*/ uint32 aa_skill; // Total AAs Spent
|
||||
/*04*/ uint32 aa_value;
|
||||
/*08*/ uint32 unknown08;
|
||||
};
|
||||
|
||||
struct AAExpUpdate_Struct {
|
||||
/*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability
|
||||
/*04*/ uint32 aapoints_unspent;
|
||||
@@ -3703,12 +3722,12 @@ struct AltAdvStats_Struct {
|
||||
};
|
||||
|
||||
struct PlayerAA_Struct {
|
||||
AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AATable_Struct {
|
||||
/*00*/ int32 aa_spent; // Total AAs Spent
|
||||
/*04*/ AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
/*04*/ AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct Weather_Struct {
|
||||
@@ -3946,7 +3965,7 @@ struct ClickEffectStruct
|
||||
|
||||
struct ProcEffectStruct
|
||||
{
|
||||
uint32 effect;
|
||||
int32 effect;
|
||||
uint8 level2;
|
||||
uint32 type;
|
||||
uint8 level;
|
||||
@@ -3961,7 +3980,7 @@ struct ProcEffectStruct
|
||||
|
||||
struct WornEffectStruct //worn, focus and scroll effect
|
||||
{
|
||||
uint32 effect;
|
||||
int32 effect;
|
||||
uint8 level2;
|
||||
uint32 type;
|
||||
uint8 level;
|
||||
|
||||
@@ -41,6 +41,11 @@
|
||||
memset(__packet->pBuffer, 0, len); \
|
||||
eq_struct *eq = (eq_struct *) __packet->pBuffer; \
|
||||
|
||||
#define ALLOC_LEN_ENCODE(len) \
|
||||
__packet->pBuffer = new unsigned char[len]; \
|
||||
__packet->size = len; \
|
||||
memset(__packet->pBuffer, 0, len); \
|
||||
|
||||
//a shorter assignment for direct mode
|
||||
#undef OUT
|
||||
#define OUT(x) eq->x = emu->x;
|
||||
@@ -124,14 +129,14 @@
|
||||
//check length of packet before decoding. Call before setup.
|
||||
#define DECODE_LENGTH_EXACT(struct_) \
|
||||
if(__packet->size != sizeof(struct_)) { \
|
||||
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */ \
|
||||
Log.Out(Logs::Detail, Logs::Netcode, "Wrong size on incoming %s (" #struct_ "): Got %d, expected %d", opcodes->EmuToName(__packet->GetOpcode()), __packet->size, sizeof(struct_)); \
|
||||
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */ \
|
||||
return; \
|
||||
}
|
||||
#define DECODE_LENGTH_ATLEAST(struct_) \
|
||||
if(__packet->size < sizeof(struct_)) { \
|
||||
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */ \
|
||||
Log.Out(Logs::Detail, Logs::Netcode, "Wrong size on incoming %s (" #struct_ "): Got %d, expected at least %d", opcodes->EmuToName(__packet->GetOpcode()), __packet->size, sizeof(struct_)); \
|
||||
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */ \
|
||||
return; \
|
||||
}
|
||||
|
||||
|
||||
+200
-100
@@ -122,7 +122,7 @@ namespace Titanium
|
||||
EAT_ENCODE(OP_GuildMemberLevelUpdate); // added ;
|
||||
|
||||
EAT_ENCODE(OP_ZoneServerReady); // added ;
|
||||
|
||||
|
||||
ENCODE(OP_Action)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(Action_Struct);
|
||||
@@ -299,6 +299,23 @@ namespace Titanium
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_Damage)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(CombatDamage_Struct);
|
||||
SETUP_DIRECT_ENCODE(CombatDamage_Struct, structs::CombatDamage_Struct);
|
||||
|
||||
OUT(target);
|
||||
OUT(source);
|
||||
OUT(type);
|
||||
OUT(spellid);
|
||||
OUT(damage);
|
||||
OUT(force);
|
||||
OUT(meleepush_xy);
|
||||
OUT(meleepush_z);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_DeleteCharge) { ENCODE_FORWARD(OP_MoveItem); }
|
||||
|
||||
ENCODE(OP_DeleteItem)
|
||||
@@ -326,7 +343,7 @@ namespace Titanium
|
||||
{
|
||||
SETUP_VAR_ENCODE(ExpeditionCompass_Struct);
|
||||
ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count);
|
||||
|
||||
|
||||
OUT(count);
|
||||
|
||||
for (uint32 i = 0; i < emu->count; ++i)
|
||||
@@ -865,7 +882,7 @@ namespace Titanium
|
||||
// OUT(unknown00178[10]);
|
||||
for (r = 0; r < 9; r++) {
|
||||
OUT(item_material[r]);
|
||||
OUT(item_tint[r].color);
|
||||
OUT(item_tint[r].Color);
|
||||
}
|
||||
// OUT(unknown00224[48]);
|
||||
for (r = 0; r < structs::MAX_PP_AA_ARRAY; r++) {
|
||||
@@ -922,24 +939,46 @@ namespace Titanium
|
||||
OUT(endurance);
|
||||
OUT(aapoints_spent);
|
||||
OUT(aapoints);
|
||||
|
||||
// OUT(unknown06160[4]);
|
||||
for (r = 0; r < structs::MAX_PLAYER_BANDOLIER; r++) {
|
||||
OUT_str(bandoliers[r].name);
|
||||
uint32 k;
|
||||
for (k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) {
|
||||
OUT(bandoliers[r].items[k].item_id);
|
||||
OUT(bandoliers[r].items[k].icon);
|
||||
OUT_str(bandoliers[r].items[k].item_name);
|
||||
|
||||
// Copy bandoliers where server and client indexes converge
|
||||
for (r = 0; r < EmuConstants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
OUT_str(bandoliers[r].Name);
|
||||
for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true
|
||||
OUT(bandoliers[r].Items[k].ID);
|
||||
OUT(bandoliers[r].Items[k].Icon);
|
||||
OUT_str(bandoliers[r].Items[k].Name);
|
||||
}
|
||||
}
|
||||
// OUT(unknown07444[5120]);
|
||||
for (r = 0; r < structs::MAX_PLAYER_BANDOLIER_ITEMS; r++) {
|
||||
OUT(potionbelt.items[r].item_id);
|
||||
OUT(potionbelt.items[r].icon);
|
||||
OUT_str(potionbelt.items[r].item_name);
|
||||
// Nullify bandoliers where server and client indexes diverge, with a client bias
|
||||
for (r = EmuConstants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
eq->bandoliers[r].Name[0] = '\0';
|
||||
for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true
|
||||
eq->bandoliers[r].Items[k].ID = 0;
|
||||
eq->bandoliers[r].Items[k].Icon = 0;
|
||||
eq->bandoliers[r].Items[k].Name[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
// OUT(unknown07444[5120]);
|
||||
|
||||
// Copy potion belt where server and client indexes converge
|
||||
for (r = 0; r < EmuConstants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
OUT(potionbelt.Items[r].ID);
|
||||
OUT(potionbelt.Items[r].Icon);
|
||||
OUT_str(potionbelt.Items[r].Name);
|
||||
}
|
||||
// Nullify potion belt where server and client indexes diverge, with a client bias
|
||||
for (r = EmuConstants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
eq->potionbelt.Items[r].ID = 0;
|
||||
eq->potionbelt.Items[r].Icon = 0;
|
||||
eq->potionbelt.Items[r].Name[0] = '\0';
|
||||
}
|
||||
|
||||
// OUT(unknown12852[8]);
|
||||
// OUT(unknown12864[76]);
|
||||
|
||||
OUT_str(name);
|
||||
OUT_str(last_name);
|
||||
OUT(guild_id);
|
||||
@@ -1048,7 +1087,7 @@ namespace Titanium
|
||||
|
||||
ENCODE(OP_ReadBook)
|
||||
{
|
||||
// no apparent slot translation needed -U
|
||||
// no apparent slot translation needed
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
@@ -1076,8 +1115,8 @@ namespace Titanium
|
||||
|
||||
unsigned int r;
|
||||
for (r = 0; r < structs::MAX_PP_AA_ARRAY; r++) {
|
||||
OUT(aa_list[r].aa_skill);
|
||||
OUT(aa_list[r].aa_value);
|
||||
OUT(aa_list[r].AA);
|
||||
OUT(aa_list[r].value);
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -1085,87 +1124,148 @@ namespace Titanium
|
||||
|
||||
ENCODE(OP_SendAATable)
|
||||
{
|
||||
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
|
||||
EQApplicationPacket *inapp = *p;
|
||||
*p = nullptr;
|
||||
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
|
||||
|
||||
SETUP_VAR_ENCODE(SendAA_Struct);
|
||||
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability));
|
||||
structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer;
|
||||
|
||||
// Check clientver field to verify this AA should be sent for Titanium
|
||||
// clientver 1 is for all clients and 3 is for Titanium
|
||||
if (emu->clientver <= 3)
|
||||
{
|
||||
OUT(id);
|
||||
eq->unknown004 = 1;
|
||||
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->id - emu->current_level + 1);
|
||||
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->id - emu->current_level + 1);
|
||||
eq->title_sid = emu->id - emu->current_level + 1;
|
||||
eq->desc_sid = emu->id - emu->current_level + 1;
|
||||
OUT(class_type);
|
||||
OUT(cost);
|
||||
OUT(seq);
|
||||
OUT(current_level);
|
||||
OUT(prereq_skill);
|
||||
OUT(prereq_minpoints);
|
||||
OUT(type);
|
||||
OUT(spellid);
|
||||
OUT(spell_type);
|
||||
OUT(spell_refresh);
|
||||
OUT(classes);
|
||||
OUT(berserker);
|
||||
OUT(max_level);
|
||||
OUT(last_id);
|
||||
OUT(next_id);
|
||||
OUT(cost2);
|
||||
OUT(unknown80[0]);
|
||||
OUT(unknown80[1]);
|
||||
OUT(total_abilities);
|
||||
unsigned int r;
|
||||
for (r = 0; r < emu->total_abilities; r++) {
|
||||
OUT(abilities[r].skill_id);
|
||||
OUT(abilities[r].base1);
|
||||
OUT(abilities[r].base2);
|
||||
OUT(abilities[r].slot);
|
||||
}
|
||||
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
|
||||
outapp->SetWritePosition(sizeof(structs::SendAA_Struct));
|
||||
|
||||
eq->id = emu->id;
|
||||
eq->unknown004 = 1;
|
||||
eq->id = emu->id;
|
||||
eq->hotkey_sid = emu->upper_hotkey_sid;
|
||||
eq->hotkey_sid2 = emu->lower_hotkey_sid;
|
||||
eq->desc_sid = emu->desc_sid;
|
||||
eq->title_sid = emu->title_sid;
|
||||
eq->class_type = emu->level_req;
|
||||
eq->cost = emu->cost;
|
||||
eq->seq = emu->seq;
|
||||
eq->current_level = emu->current_level;
|
||||
eq->type = emu->type;
|
||||
eq->spellid = emu->spell;
|
||||
eq->spell_type = emu->spell_type;
|
||||
eq->spell_refresh = emu->spell_refresh;
|
||||
eq->classes = emu->classes;
|
||||
eq->max_level = emu->max_level;
|
||||
eq->last_id = emu->prev_id;
|
||||
eq->next_id = emu->next_id;
|
||||
eq->cost2 = emu->total_cost;
|
||||
eq->total_abilities = emu->total_effects;
|
||||
|
||||
for(auto i = 0; i < eq->total_abilities; ++i) {
|
||||
eq->abilities[i].skill_id = inapp->ReadUInt32();
|
||||
eq->abilities[i].base1 = inapp->ReadUInt32();
|
||||
eq->abilities[i].base2 = inapp->ReadUInt32();
|
||||
eq->abilities[i].slot = inapp->ReadUInt32();
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
if(emu->total_prereqs > 0) {
|
||||
eq->prereq_skill = inapp->ReadUInt32();
|
||||
eq->prereq_minpoints = inapp->ReadUInt32();
|
||||
}
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
delete inapp;
|
||||
}
|
||||
|
||||
ENCODE(OP_SendCharInfo)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(CharacterSelect_Struct);
|
||||
ENCODE_LENGTH_ATLEAST(CharacterSelect_Struct);
|
||||
SETUP_DIRECT_ENCODE(CharacterSelect_Struct, structs::CharacterSelect_Struct);
|
||||
|
||||
int r;
|
||||
for (r = 0; r < 10; r++) {
|
||||
OUT(zone[r]);
|
||||
OUT(eyecolor1[r]);
|
||||
OUT(eyecolor2[r]);
|
||||
OUT(hairstyle[r]);
|
||||
OUT(primary[r]);
|
||||
if (emu->race[r] > 473)
|
||||
eq->race[r] = 1;
|
||||
else
|
||||
eq->race[r] = emu->race[r];
|
||||
OUT(class_[r]);
|
||||
OUT_str(name[r]);
|
||||
OUT(gender[r]);
|
||||
OUT(level[r]);
|
||||
OUT(secondary[r]);
|
||||
OUT(face[r]);
|
||||
OUT(beard[r]);
|
||||
int k;
|
||||
for (k = 0; k < 9; k++) {
|
||||
eq->equip[r][k] = emu->equip[r][k].material;
|
||||
eq->cs_colors[r][k].color = emu->equip[r][k].color.color;
|
||||
unsigned char *emu_ptr = __emu_buffer;
|
||||
emu_ptr += sizeof(CharacterSelect_Struct);
|
||||
CharacterSelectEntry_Struct *emu_cse = (CharacterSelectEntry_Struct *)nullptr;
|
||||
|
||||
for (size_t index = 0; index < 10; ++index) {
|
||||
memset(eq->Name[index], 0, 64);
|
||||
}
|
||||
|
||||
// Non character-indexed packet fields
|
||||
eq->Unknown830[0] = 0;
|
||||
eq->Unknown830[1] = 0;
|
||||
eq->Unknown0962[0] = 0;
|
||||
eq->Unknown0962[1] = 0;
|
||||
|
||||
size_t char_index = 0;
|
||||
for (; char_index < emu->CharCount && char_index < 8; ++char_index) {
|
||||
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
||||
|
||||
eq->Race[char_index] = emu_cse->Race;
|
||||
if (eq->Race[char_index] > 473)
|
||||
eq->Race[char_index] = 1;
|
||||
|
||||
for (int index = 0; index < _MaterialCount; ++index) {
|
||||
eq->CS_Colors[char_index][index].Color = emu_cse->Equip[index].Color.Color;
|
||||
}
|
||||
OUT(haircolor[r]);
|
||||
OUT(gohome[r]);
|
||||
OUT(tutorial[r]);
|
||||
OUT(deity[r]);
|
||||
OUT(beardcolor[r]);
|
||||
eq->unknown820[r] = 0xFF;
|
||||
eq->unknown902[r] = 0xFF;
|
||||
|
||||
eq->BeardColor[char_index] = emu_cse->BeardColor;
|
||||
eq->HairStyle[char_index] = emu_cse->HairStyle;
|
||||
|
||||
for (int index = 0; index < _MaterialCount; ++index) {
|
||||
eq->Equip[char_index][index] = emu_cse->Equip[index].Material;
|
||||
}
|
||||
|
||||
eq->SecondaryIDFile[char_index] = emu_cse->SecondaryIDFile;
|
||||
eq->Unknown820[char_index] = (uint8)0xFF;
|
||||
eq->Deity[char_index] = emu_cse->Deity;
|
||||
eq->GoHome[char_index] = emu_cse->GoHome;
|
||||
eq->Tutorial[char_index] = emu_cse->Tutorial;
|
||||
eq->Beard[char_index] = emu_cse->Beard;
|
||||
eq->Unknown902[char_index] = (uint8)0xFF;
|
||||
eq->PrimaryIDFile[char_index] = emu_cse->PrimaryIDFile;
|
||||
eq->HairColor[char_index] = emu_cse->HairColor;
|
||||
eq->Zone[char_index] = emu_cse->Zone;
|
||||
eq->Class[char_index] = emu_cse->Class;
|
||||
eq->Face[char_index] = emu_cse->Face;
|
||||
|
||||
memcpy(eq->Name[char_index], emu_cse->Name, 64);
|
||||
|
||||
eq->Gender[char_index] = emu_cse->Gender;
|
||||
eq->EyeColor1[char_index] = emu_cse->EyeColor1;
|
||||
eq->EyeColor2[char_index] = emu_cse->EyeColor2;
|
||||
eq->Level[char_index] = emu_cse->Level;
|
||||
|
||||
emu_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
for (; char_index < 10; ++char_index) {
|
||||
eq->Race[char_index] = 0;
|
||||
|
||||
for (int index = 0; index < _MaterialCount; ++index) {
|
||||
eq->CS_Colors[char_index][index].Color = 0;
|
||||
}
|
||||
|
||||
eq->BeardColor[char_index] = 0;
|
||||
eq->HairStyle[char_index] = 0;
|
||||
|
||||
for (int index = 0; index < _MaterialCount; ++index) {
|
||||
eq->Equip[char_index][index] = 0;
|
||||
}
|
||||
|
||||
eq->SecondaryIDFile[char_index] = 0;
|
||||
eq->Unknown820[char_index] = (uint8)0xFF;
|
||||
eq->Deity[char_index] = 0;
|
||||
eq->GoHome[char_index] = 0;
|
||||
eq->Tutorial[char_index] = 0;
|
||||
eq->Beard[char_index] = 0;
|
||||
eq->Unknown902[char_index] = (uint8)0xFF;
|
||||
eq->PrimaryIDFile[char_index] = 0;
|
||||
eq->HairColor[char_index] = 0;
|
||||
eq->Zone[char_index] = 0;
|
||||
eq->Class[char_index] = 0;
|
||||
eq->Face[char_index] = 0;
|
||||
|
||||
strncpy(eq->Name[char_index], "<none>", 6);
|
||||
|
||||
eq->Gender[char_index] = 0;
|
||||
eq->EyeColor1[char_index] = 0;
|
||||
eq->EyeColor2[char_index] = 0;
|
||||
eq->Level[char_index] = 0;
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -1227,7 +1327,7 @@ namespace Titanium
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
@@ -1270,7 +1370,7 @@ namespace Titanium
|
||||
InBuffer += strlen(InBuffer) + 1;
|
||||
|
||||
memcpy(OutBuffer, InBuffer, sizeof(TaskDescriptionTrailer_Struct));
|
||||
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
@@ -1383,7 +1483,7 @@ namespace Titanium
|
||||
|
||||
OUT(spawn_id);
|
||||
OUT(material);
|
||||
OUT(color.color);
|
||||
OUT(color.Color);
|
||||
OUT(wear_slot_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -1468,15 +1568,15 @@ namespace Titanium
|
||||
eq->beardcolor = emu->beardcolor;
|
||||
// eq->unknown0147[4] = emu->unknown0147[4];
|
||||
eq->level = emu->level;
|
||||
// eq->unknown0259[4] = emu->unknown0259[4];
|
||||
eq->PlayerState = emu->PlayerState;
|
||||
eq->beard = emu->beard;
|
||||
strcpy(eq->suffix, emu->suffix);
|
||||
eq->petOwnerId = emu->petOwnerId;
|
||||
eq->guildrank = emu->guildrank;
|
||||
// eq->unknown0194[3] = emu->unknown0194[3];
|
||||
for (k = 0; k < 9; k++) {
|
||||
eq->equipment[k] = emu->equipment[k].material;
|
||||
eq->colors[k].color = emu->colors[k].color;
|
||||
eq->equipment[k] = emu->equipment[k].Material;
|
||||
eq->colors[k].Color = emu->colors[k].Color;
|
||||
}
|
||||
for (k = 0; k < 8; k++) {
|
||||
eq->set_to_0xFF[k] = 0xFF;
|
||||
@@ -1540,7 +1640,7 @@ namespace Titanium
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
|
||||
DECODE(OP_ApplyPoison)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct);
|
||||
@@ -1861,14 +1961,14 @@ namespace Titanium
|
||||
default:
|
||||
emu->command = eq->command;
|
||||
}
|
||||
OUT(unknown);
|
||||
IN(target);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_ReadBook)
|
||||
{
|
||||
// no apparent slot translation needed -U
|
||||
// no apparent slot translation needed
|
||||
DECODE_LENGTH_ATLEAST(structs::BookRequest_Struct);
|
||||
SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct);
|
||||
|
||||
@@ -1952,7 +2052,7 @@ namespace Titanium
|
||||
|
||||
IN(spawn_id);
|
||||
IN(material);
|
||||
IN(color.color);
|
||||
IN(color.Color);
|
||||
IN(wear_slot_id);
|
||||
emu->unknown06 = 0;
|
||||
emu->elite_material = 0;
|
||||
@@ -2070,7 +2170,7 @@ namespace Titanium
|
||||
|
||||
return serverSlot; // deprecated
|
||||
}
|
||||
|
||||
|
||||
static inline int16 ServerToTitaniumCorpseSlot(uint32 serverCorpseSlot)
|
||||
{
|
||||
//int16 TitaniumCorpse;
|
||||
@@ -2085,7 +2185,7 @@ namespace Titanium
|
||||
|
||||
return titaniumSlot; // deprecated
|
||||
}
|
||||
|
||||
|
||||
static inline uint32 TitaniumToServerCorpseSlot(int16 titaniumCorpseSlot)
|
||||
{
|
||||
//uint32 ServerCorpse;
|
||||
|
||||
@@ -100,6 +100,8 @@ namespace Titanium {
|
||||
}
|
||||
|
||||
namespace consts {
|
||||
static const size_t CHARACTER_CREATION_LIMIT = 8; // Hard-coded in client - DO NOT ALTER
|
||||
|
||||
static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount;
|
||||
static const uint16 MAP_BANK_SIZE = 16;
|
||||
static const uint16 MAP_SHARED_BANK_SIZE = 2;
|
||||
@@ -173,9 +175,10 @@ namespace Titanium {
|
||||
static const uint16 ITEM_COMMON_SIZE = 5;
|
||||
static const uint16 ITEM_CONTAINER_SIZE = 10;
|
||||
|
||||
static const uint32 BANDOLIERS_COUNT = 4; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 4;
|
||||
static const size_t BANDOLIERS_SIZE = 4; // number of bandolier instances
|
||||
static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance
|
||||
|
||||
static const size_t POTION_BELT_ITEM_COUNT = 4;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 45;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ E(OP_BazaarSearch)
|
||||
E(OP_BecomeTrader)
|
||||
E(OP_ChannelMessage)
|
||||
E(OP_CharInventory)
|
||||
E(OP_Damage)
|
||||
E(OP_DeleteCharge)
|
||||
E(OP_DeleteItem)
|
||||
E(OP_DeleteSpawn)
|
||||
|
||||
@@ -99,16 +99,14 @@ struct AdventureInfo {
|
||||
*/
|
||||
struct Color_Struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 blue;
|
||||
uint8 green;
|
||||
uint8 red;
|
||||
uint8 use_tint; // if there's a tint this is FF
|
||||
} rgb;
|
||||
uint32 color;
|
||||
union {
|
||||
struct {
|
||||
uint8 Blue;
|
||||
uint8 Green;
|
||||
uint8 Red;
|
||||
uint8 UseTint; // if there's a tint this is FF
|
||||
} RGB;
|
||||
uint32 Color;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -117,31 +115,32 @@ struct Color_Struct
|
||||
** Length: 1704 Bytes
|
||||
**
|
||||
*/
|
||||
struct CharacterSelect_Struct {
|
||||
/*0000*/ uint32 race[10]; // Characters Race
|
||||
/*0040*/ Color_Struct cs_colors[10][9]; // Characters Equipment Colors
|
||||
/*0400*/ uint8 beardcolor[10]; // Characters beard Color
|
||||
/*0410*/ uint8 hairstyle[10]; // Characters hair style
|
||||
/*0420*/ uint32 equip[10][9]; // 0=helm, 1=chest, 2=arm, 3=bracer, 4=hand, 5=leg, 6=boot, 7=melee1, 8=melee2 (Might not be)
|
||||
/*0780*/ uint32 secondary[10]; // Characters secondary IDFile number
|
||||
/*0820*/ uint8 unknown820[10]; // 10x ff
|
||||
/*0830*/ uint8 unknown830[2]; // 2x 00
|
||||
/*0832*/ uint32 deity[10]; // Characters Deity
|
||||
/*0872*/ uint8 gohome[10]; // 1=Go Home available, 0=not
|
||||
/*0882*/ uint8 tutorial[10]; // 1=Tutorial available, 0=not
|
||||
/*0892*/ uint8 beard[10]; // Characters Beard Type
|
||||
/*0902*/ uint8 unknown902[10]; // 10x ff
|
||||
/*0912*/ uint32 primary[10]; // Characters primary IDFile number
|
||||
/*0952*/ uint8 haircolor[10]; // Characters Hair Color
|
||||
/*0962*/ uint8 unknown0962[2]; // 2x 00
|
||||
/*0964*/ uint32 zone[10]; // Characters Current Zone
|
||||
/*1004*/ uint8 class_[10]; // Characters Classes
|
||||
/*1014*/ uint8 face[10]; // Characters Face Type
|
||||
/*1024*/ char name[10][64]; // Characters Names
|
||||
/*1664*/ uint8 gender[10]; // Characters Gender
|
||||
/*1674*/ uint8 eyecolor1[10]; // Characters Eye Color
|
||||
/*1684*/ uint8 eyecolor2[10]; // Characters Eye 2 Color
|
||||
/*1694*/ uint8 level[10]; // Characters Levels
|
||||
struct CharacterSelect_Struct
|
||||
{
|
||||
/*0000*/ uint32 Race[10]; // Characters Race
|
||||
/*0040*/ Color_Struct CS_Colors[10][9]; // Characters Equipment Colors
|
||||
/*0400*/ uint8 BeardColor[10]; // Characters beard Color
|
||||
/*0410*/ uint8 HairStyle[10]; // Characters hair style
|
||||
/*0420*/ uint32 Equip[10][9]; // 0=helm, 1=chest, 2=arm, 3=bracer, 4=hand, 5=leg, 6=boot, 7=melee1, 8=melee2 (Might not be)
|
||||
/*0780*/ uint32 SecondaryIDFile[10]; // Characters secondary IDFile number
|
||||
/*0820*/ uint8 Unknown820[10]; // 10x ff
|
||||
/*0830*/ uint8 Unknown830[2]; // 2x 00
|
||||
/*0832*/ uint32 Deity[10]; // Characters Deity
|
||||
/*0872*/ uint8 GoHome[10]; // 1=Go Home available, 0=not
|
||||
/*0882*/ uint8 Tutorial[10]; // 1=Tutorial available, 0=not
|
||||
/*0892*/ uint8 Beard[10]; // Characters Beard Type
|
||||
/*0902*/ uint8 Unknown902[10]; // 10x ff
|
||||
/*0912*/ uint32 PrimaryIDFile[10]; // Characters primary IDFile number
|
||||
/*0952*/ uint8 HairColor[10]; // Characters Hair Color
|
||||
/*0962*/ uint8 Unknown0962[2]; // 2x 00
|
||||
/*0964*/ uint32 Zone[10]; // Characters Current Zone
|
||||
/*1004*/ uint8 Class[10]; // Characters Classes
|
||||
/*1014*/ uint8 Face[10]; // Characters Face Type
|
||||
/*1024*/ char Name[10][64]; // Characters Names
|
||||
/*1664*/ uint8 Gender[10]; // Characters Gender
|
||||
/*1674*/ uint8 EyeColor1[10]; // Characters Eye Color
|
||||
/*1684*/ uint8 EyeColor2[10]; // Characters Eye 2 Color
|
||||
/*1694*/ uint8 Level[10]; // Characters Levels
|
||||
/*1704*/
|
||||
};
|
||||
|
||||
@@ -213,7 +212,7 @@ struct Spawn_Struct {
|
||||
/*0146*/ uint8 beardcolor; // Beard color
|
||||
/*0147*/ uint8 unknown0147[4];
|
||||
/*0151*/ uint8 level; // Spawn Level
|
||||
/*0152*/ uint8 unknown0259[4]; // ***Placeholder
|
||||
/*0152*/ uint32 PlayerState; // PlayerState controls some animation stuff
|
||||
/*0156*/ uint8 beard; // Beard style
|
||||
/*0157*/ char suffix[32]; // Player's suffix (of Veeshan, etc.)
|
||||
/*0189*/ uint32 petOwnerId; // If this is a pet, the spawn id of owner
|
||||
@@ -446,7 +445,7 @@ struct SpellBuff_Struct
|
||||
/*002*/ uint8 bard_modifier;
|
||||
/*003*/ uint8 effect; //not real
|
||||
/*004*/ uint32 spellid;
|
||||
/*008*/ uint32 duration;
|
||||
/*008*/ int32 duration;
|
||||
/*012*/ uint32 counters;
|
||||
/*016*/ uint32 player_id; //'global' ID of the caster, for wearoff messages
|
||||
};
|
||||
@@ -458,7 +457,7 @@ struct SpellBuffFade_Struct {
|
||||
/*006*/ uint8 effect;
|
||||
/*007*/ uint8 unknown7;
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 unknown016;
|
||||
/*020*/ uint32 unknown020; //prolly global player ID
|
||||
/*024*/ uint32 slotid;
|
||||
@@ -586,34 +585,48 @@ struct Disciplines_Struct {
|
||||
};
|
||||
|
||||
static const uint32 MAX_PLAYER_TRIBUTES = 5;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER = 4;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER_ITEMS = 4;
|
||||
static const uint32 TRIBUTE_NONE = 0xFFFFFFFF;
|
||||
struct Tribute_Struct {
|
||||
uint32 tribute;
|
||||
uint32 tier;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct {
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
char item_name[64];
|
||||
};
|
||||
|
||||
//len = 320
|
||||
enum { //bandolier item positions
|
||||
bandolierMainHand = 0,
|
||||
bandolierOffHand,
|
||||
// Bandolier item positions
|
||||
enum
|
||||
{
|
||||
bandolierPrimary = 0,
|
||||
bandolierSecondary,
|
||||
bandolierRange,
|
||||
bandolierAmmo
|
||||
};
|
||||
struct Bandolier_Struct {
|
||||
char name[32];
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
struct PotionBelt_Struct {
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
|
||||
//len = 320
|
||||
struct Bandolier_Struct
|
||||
{
|
||||
char Name[32];
|
||||
BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct PotionBeltItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
//len = 288
|
||||
struct PotionBelt_Struct
|
||||
{
|
||||
PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
|
||||
@@ -817,7 +830,7 @@ struct PlayerProfile_Struct
|
||||
/*06152*/ uint32 aapoints_spent; // Number of spent AA points
|
||||
/*06156*/ uint32 aapoints; // Unspent AA points
|
||||
/*06160*/ uint8 unknown06160[4];
|
||||
/*06164*/ Bandolier_Struct bandoliers[MAX_PLAYER_BANDOLIER]; // bandolier contents
|
||||
/*06164*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // bandolier contents
|
||||
/*07444*/ uint8 unknown07444[5120];
|
||||
/*12564*/ PotionBelt_Struct potionbelt; // potion belt
|
||||
/*12852*/ uint8 unknown12852[8];
|
||||
@@ -937,7 +950,7 @@ struct TargetReject_Struct {
|
||||
|
||||
struct PetCommand_Struct {
|
||||
/*000*/ uint32 command;
|
||||
/*004*/ uint32 unknown;
|
||||
/*004*/ uint32 target;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1049,8 +1062,8 @@ struct RequestClientZoneChange_Struct {
|
||||
|
||||
struct Animation_Struct {
|
||||
/*00*/ uint16 spawnid;
|
||||
/*02*/ uint8 action;
|
||||
/*03*/ uint8 value;
|
||||
/*02*/ uint8 speed;
|
||||
/*03*/ uint8 action;
|
||||
/*04*/
|
||||
};
|
||||
|
||||
@@ -1088,9 +1101,9 @@ struct CombatDamage_Struct
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||
/* 05 */ uint16 spellid;
|
||||
/* 07 */ uint32 damage;
|
||||
/* 11 */ uint32 unknown11;
|
||||
/* 15 */ uint32 sequence; // see above notes in Action_Struct
|
||||
/* 19 */ uint32 unknown19;
|
||||
/* 11 */ float force;
|
||||
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 19 */ float meleepush_z;
|
||||
/* 23 */
|
||||
};
|
||||
|
||||
@@ -1997,7 +2010,7 @@ struct BookRequest_Struct {
|
||||
**
|
||||
*/
|
||||
struct Object_Struct {
|
||||
/*00*/ uint32 linked_list_addr[2];// <Zaphod> They are, get this, prev and next, ala linked list
|
||||
/*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list
|
||||
/*08*/ uint16 unknown008[2]; //
|
||||
/*12*/ uint32 drop_id; // Unique object id for zone
|
||||
/*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in
|
||||
@@ -2016,8 +2029,8 @@ struct Object_Struct {
|
||||
/*88*/ uint32 spawn_id; // Spawn Id of client interacting with object
|
||||
/*92*/
|
||||
};
|
||||
//<Zaphod> 01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] <Zaphod> and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
//01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
|
||||
/*
|
||||
** Click Object Struct
|
||||
@@ -3030,30 +3043,35 @@ struct DynamicWall_Struct {
|
||||
/*80*/
|
||||
};
|
||||
|
||||
enum { //bandolier actions
|
||||
BandolierCreate = 0,
|
||||
BandolierRemove = 1,
|
||||
BandolierSet = 2
|
||||
// Bandolier actions
|
||||
enum
|
||||
{
|
||||
bandolierCreate = 0,
|
||||
bandolierRemove,
|
||||
bandolierSet
|
||||
};
|
||||
|
||||
struct BandolierCreate_Struct {
|
||||
/*00*/ uint32 action; //0 for create
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ char name[32];
|
||||
/*37*/ uint16 unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 unknown39; //0
|
||||
struct BandolierCreate_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; //0 for create
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ char Name[32];
|
||||
/*37*/ uint16 Unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 Unknown39; //0
|
||||
};
|
||||
|
||||
struct BandolierDelete_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierDelete_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct BandolierSet_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierSet_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct Arrow_Struct {
|
||||
@@ -3139,8 +3157,7 @@ struct SendAA_Struct {
|
||||
/*0052*/ uint32 spellid;
|
||||
/*0056*/ uint32 spell_type;
|
||||
/*0060*/ uint32 spell_refresh;
|
||||
/*0064*/ uint16 classes;
|
||||
/*0066*/ uint16 berserker; //seems to be 1 if its a berserker ability
|
||||
/*0064*/ uint32 classes;
|
||||
/*0068*/ uint32 max_level;
|
||||
/*0072*/ uint32 last_id;
|
||||
/*0076*/ uint32 next_id;
|
||||
@@ -3157,15 +3174,10 @@ struct AA_List {
|
||||
struct AA_Action {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint32 ability;
|
||||
/*08*/ uint32 unknown08;
|
||||
/*08*/ uint32 target_id;
|
||||
/*12*/ uint32 exp_value;
|
||||
};
|
||||
|
||||
struct AA_Skills { //this should be removed and changed to AA_Array
|
||||
/*00*/ uint32 aa_skill;
|
||||
/*04*/ uint32 aa_value;
|
||||
};
|
||||
|
||||
struct AAExpUpdate_Struct {
|
||||
/*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability
|
||||
/*04*/ uint32 aapoints_unspent;
|
||||
@@ -3183,11 +3195,11 @@ struct AltAdvStats_Struct {
|
||||
};
|
||||
|
||||
struct PlayerAA_Struct {
|
||||
AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AATable_Struct {
|
||||
AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct Weather_Struct {
|
||||
|
||||
+236
-186
@@ -365,7 +365,7 @@ namespace UF
|
||||
memset(__packet->pBuffer, 0, sz);
|
||||
|
||||
__packet->WriteUInt32(emu->entity_id);
|
||||
__packet->WriteUInt32(0);
|
||||
__packet->WriteUInt32(emu->tic_timer);
|
||||
__packet->WriteUInt8(emu->all_buffs); // 1 = all buffs, 0 = 1 buff
|
||||
__packet->WriteUInt16(emu->count);
|
||||
|
||||
@@ -387,7 +387,7 @@ namespace UF
|
||||
__packet->WriteUInt32(emu->entries[i].num_hits);
|
||||
__packet->WriteString("");
|
||||
}
|
||||
__packet->WriteUInt8(!emu->all_buffs);
|
||||
__packet->WriteUInt8(emu->type);
|
||||
|
||||
FINISH_ENCODE();
|
||||
/*
|
||||
@@ -581,7 +581,10 @@ namespace UF
|
||||
OUT(type);
|
||||
OUT(spellid);
|
||||
OUT(damage);
|
||||
eq->sequence = emu->sequence;
|
||||
OUT(force);
|
||||
OUT(meleepush_xy);
|
||||
OUT(meleepush_z);
|
||||
OUT(special);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@@ -855,8 +858,8 @@ namespace UF
|
||||
// field to be set to (float)255.0 to appear at all, and also the size field below to be 5, to be the correct size. I think SoD has the same
|
||||
// issue.
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown, observed 0
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // This appears to be the size field.
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown, observed 0
|
||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt.
|
||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y);
|
||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x);
|
||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->z);
|
||||
@@ -1791,22 +1794,25 @@ namespace UF
|
||||
OUT(beard);
|
||||
// OUT(unknown00178[10]);
|
||||
for (r = 0; r < 9; r++) {
|
||||
eq->equipment[r].material = emu->item_material[r];
|
||||
eq->equipment[r].unknown1 = 0;
|
||||
eq->equipment[r].elitematerial = 0;
|
||||
eq->equipment[r].Material = emu->item_material[r];
|
||||
eq->equipment[r].Unknown1 = 0;
|
||||
eq->equipment[r].EliteMaterial = 0;
|
||||
//eq->colors[r].color = emu->colors[r].color;
|
||||
}
|
||||
for (r = 0; r < 7; r++) {
|
||||
OUT(item_tint[r].color);
|
||||
OUT(item_tint[r].Color);
|
||||
}
|
||||
// OUT(unknown00224[48]);
|
||||
//NOTE: new client supports 300 AAs, our internal rep/PP
|
||||
//only supports 240..
|
||||
for (r = 0; r < MAX_PP_AA_ARRAY; r++) {
|
||||
OUT(aa_array[r].AA);
|
||||
OUT(aa_array[r].value);
|
||||
eq->aa_array[r].AA = emu->aa_array[r].AA;
|
||||
eq->aa_array[r].value = emu->aa_array[r].value;
|
||||
eq->aa_array[r].charges = emu->aa_array[r].charges;
|
||||
}
|
||||
|
||||
// OUT(unknown02220[4]);
|
||||
|
||||
OUT(mana);
|
||||
OUT(cur_hp);
|
||||
OUT(STR);
|
||||
@@ -1868,26 +1874,46 @@ namespace UF
|
||||
OUT(endurance);
|
||||
OUT(aapoints_spent);
|
||||
OUT(aapoints);
|
||||
|
||||
// OUT(unknown06160[4]);
|
||||
//NOTE: new client supports 20 bandoliers, our internal rep
|
||||
//only supports 4..
|
||||
for (r = 0; r < 4; r++) {
|
||||
OUT_str(bandoliers[r].name);
|
||||
uint32 k;
|
||||
for (k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) {
|
||||
OUT(bandoliers[r].items[k].item_id);
|
||||
OUT(bandoliers[r].items[k].icon);
|
||||
OUT_str(bandoliers[r].items[k].item_name);
|
||||
|
||||
// Copy bandoliers where server and client indexes converge
|
||||
for (r = 0; r < EmuConstants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
OUT_str(bandoliers[r].Name);
|
||||
for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true
|
||||
OUT(bandoliers[r].Items[k].ID);
|
||||
OUT(bandoliers[r].Items[k].Icon);
|
||||
OUT_str(bandoliers[r].Items[k].Name);
|
||||
}
|
||||
}
|
||||
// OUT(unknown07444[5120]);
|
||||
for (r = 0; r < structs::MAX_POTIONS_IN_BELT; r++) {
|
||||
OUT(potionbelt.items[r].item_id);
|
||||
OUT(potionbelt.items[r].icon);
|
||||
OUT_str(potionbelt.items[r].item_name);
|
||||
// Nullify bandoliers where server and client indexes diverge, with a client bias
|
||||
for (r = EmuConstants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
eq->bandoliers[r].Name[0] = '\0';
|
||||
for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true
|
||||
eq->bandoliers[r].Items[k].ID = 0;
|
||||
eq->bandoliers[r].Items[k].Icon = 0;
|
||||
eq->bandoliers[r].Items[k].Name[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
// OUT(unknown07444[5120]);
|
||||
|
||||
// Copy potion belt where server and client indexes converge
|
||||
for (r = 0; r < EmuConstants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
OUT(potionbelt.Items[r].ID);
|
||||
OUT(potionbelt.Items[r].Icon);
|
||||
OUT_str(potionbelt.Items[r].Name);
|
||||
}
|
||||
// Nullify potion belt where server and client indexes diverge, with a client bias
|
||||
for (r = EmuConstants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
eq->potionbelt.Items[r].ID = 0;
|
||||
eq->potionbelt.Items[r].Icon = 0;
|
||||
eq->potionbelt.Items[r].Name[0] = '\0';
|
||||
}
|
||||
|
||||
// OUT(unknown12852[8]);
|
||||
// OUT(unknown12864[76]);
|
||||
|
||||
OUT_str(name);
|
||||
OUT_str(last_name);
|
||||
OUT(guild_id);
|
||||
@@ -1916,8 +1942,8 @@ namespace UF
|
||||
OUT(copper_bank);
|
||||
OUT(platinum_shared);
|
||||
// OUT(unknown13156[84]);
|
||||
//OUT(expansions);
|
||||
eq->expansions = 0xffff;
|
||||
OUT(expansions);
|
||||
//eq->expansions = 0x1ffff;
|
||||
// OUT(unknown13244[12]);
|
||||
OUT(autosplit);
|
||||
// OUT(unknown13260[16]);
|
||||
@@ -2105,16 +2131,16 @@ namespace UF
|
||||
|
||||
eq->aa_spent = emu->aa_spent;
|
||||
eq->aa_assigned = emu->aa_spent;
|
||||
eq->aa_spent3 = emu->aa_spent;
|
||||
eq->aa_spent3 = 0;
|
||||
eq->unknown012 = 0;
|
||||
eq->unknown016 = 0;
|
||||
eq->unknown020 = 0;
|
||||
|
||||
for (uint32 i = 0; i < MAX_PP_AA_ARRAY; ++i)
|
||||
{
|
||||
eq->aa_list[i].aa_skill = emu->aa_list[i].aa_skill;
|
||||
eq->aa_list[i].aa_value = emu->aa_list[i].aa_value;
|
||||
eq->aa_list[i].unknown08 = emu->aa_list[i].unknown08;
|
||||
eq->aa_list[i].AA = emu->aa_list[i].AA;
|
||||
eq->aa_list[i].value = emu->aa_list[i].value;
|
||||
eq->aa_list[i].charges = emu->aa_list[i].charges;
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -2122,129 +2148,158 @@ namespace UF
|
||||
|
||||
ENCODE(OP_SendAATable)
|
||||
{
|
||||
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
|
||||
SETUP_VAR_ENCODE(SendAA_Struct);
|
||||
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
|
||||
EQApplicationPacket *inapp = *p;
|
||||
*p = nullptr;
|
||||
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
|
||||
|
||||
// Check clientver field to verify this AA should be sent for SoF
|
||||
// clientver 1 is for all clients and 6 is for Underfoot
|
||||
if (emu->clientver <= 6)
|
||||
{
|
||||
OUT(id);
|
||||
eq->unknown004 = 1;
|
||||
//eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1);
|
||||
//eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1);
|
||||
//eq->title_sid = emu->id - emu->current_level + 1;
|
||||
//eq->desc_sid = emu->id - emu->current_level + 1;
|
||||
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->sof_next_skill);
|
||||
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->sof_next_skill);
|
||||
eq->title_sid = emu->sof_next_skill;
|
||||
eq->desc_sid = emu->sof_next_skill;
|
||||
OUT(class_type);
|
||||
OUT(cost);
|
||||
OUT(seq);
|
||||
OUT(current_level);
|
||||
OUT(prereq_skill);
|
||||
OUT(prereq_minpoints);
|
||||
eq->type = emu->sof_type;
|
||||
OUT(spellid);
|
||||
OUT(spell_type);
|
||||
OUT(spell_refresh);
|
||||
OUT(classes);
|
||||
OUT(berserker);
|
||||
//eq->max_level = emu->sof_max_level;
|
||||
OUT(max_level);
|
||||
OUT(last_id);
|
||||
OUT(next_id);
|
||||
OUT(cost2);
|
||||
eq->aa_expansion = emu->aa_expansion;
|
||||
eq->special_category = emu->special_category;
|
||||
OUT(total_abilities);
|
||||
unsigned int r;
|
||||
for (r = 0; r < emu->total_abilities; r++) {
|
||||
OUT(abilities[r].skill_id);
|
||||
OUT(abilities[r].base1);
|
||||
OUT(abilities[r].base2);
|
||||
OUT(abilities[r].slot);
|
||||
}
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability));
|
||||
structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer;
|
||||
|
||||
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
|
||||
outapp->SetWritePosition(sizeof(structs::SendAA_Struct));
|
||||
|
||||
eq->id = emu->id;
|
||||
eq->unknown004 = 1;
|
||||
eq->id = emu->id;
|
||||
eq->hotkey_sid = emu->upper_hotkey_sid;
|
||||
eq->hotkey_sid2 = emu->lower_hotkey_sid;
|
||||
eq->desc_sid = emu->desc_sid;
|
||||
eq->title_sid = emu->title_sid;
|
||||
eq->class_type = emu->level_req;
|
||||
eq->cost = emu->cost;
|
||||
eq->seq = emu->seq;
|
||||
eq->current_level = emu->current_level;
|
||||
eq->type = emu->type;
|
||||
eq->spellid = emu->spell;
|
||||
eq->spell_type = emu->spell_type;
|
||||
eq->spell_refresh = emu->spell_refresh;
|
||||
eq->classes = emu->classes;
|
||||
eq->max_level = emu->max_level;
|
||||
eq->last_id = emu->prev_id;
|
||||
eq->next_id = emu->next_id;
|
||||
eq->cost2 = emu->total_cost;
|
||||
eq->grant_only = emu->grant_only;
|
||||
eq->expendable_charges = emu->charges;
|
||||
eq->aa_expansion = emu->expansion;
|
||||
eq->special_category = emu->category;
|
||||
eq->total_abilities = emu->total_effects;
|
||||
|
||||
for(auto i = 0; i < eq->total_abilities; ++i) {
|
||||
eq->abilities[i].skill_id = inapp->ReadUInt32();
|
||||
eq->abilities[i].base1 = inapp->ReadUInt32();
|
||||
eq->abilities[i].base2 = inapp->ReadUInt32();
|
||||
eq->abilities[i].slot = inapp->ReadUInt32();
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
if(emu->total_prereqs > 0) {
|
||||
eq->prereq_skill = inapp->ReadUInt32();
|
||||
eq->prereq_minpoints = inapp->ReadUInt32();
|
||||
}
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
delete inapp;
|
||||
}
|
||||
|
||||
ENCODE(OP_SendCharInfo)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(CharacterSelect_Struct);
|
||||
ENCODE_LENGTH_ATLEAST(CharacterSelect_Struct);
|
||||
SETUP_VAR_ENCODE(CharacterSelect_Struct);
|
||||
|
||||
//EQApplicationPacket *packet = *p;
|
||||
//const CharacterSelect_Struct *emu = (CharacterSelect_Struct *) packet->pBuffer;
|
||||
// Zero-character count shunt
|
||||
if (emu->CharCount == 0) {
|
||||
ALLOC_VAR_ENCODE(structs::CharacterSelect_Struct, sizeof(structs::CharacterSelect_Struct));
|
||||
eq->CharCount = emu->CharCount;
|
||||
eq->TotalChars = emu->TotalChars;
|
||||
|
||||
int char_count;
|
||||
int namelen = 0;
|
||||
for (char_count = 0; char_count < 10; char_count++) {
|
||||
if (emu->name[char_count][0] == '\0')
|
||||
break;
|
||||
if (strcmp(emu->name[char_count], "<none>") == 0)
|
||||
break;
|
||||
namelen += strlen(emu->name[char_count]);
|
||||
if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT)
|
||||
eq->TotalChars = consts::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
// Special Underfoot adjustment - field should really be 'AdditionalChars' or 'BonusChars'
|
||||
uint32 adjusted_total = eq->TotalChars - 8; // Yes, it rolls under for '< 8' - probably an int32 field
|
||||
eq->TotalChars = adjusted_total;
|
||||
|
||||
FINISH_ENCODE();
|
||||
return;
|
||||
}
|
||||
|
||||
int total_length = sizeof(structs::CharacterSelect_Struct)
|
||||
+ char_count * sizeof(structs::CharacterSelectEntry_Struct)
|
||||
+ namelen;
|
||||
unsigned char *emu_ptr = __emu_buffer;
|
||||
emu_ptr += sizeof(CharacterSelect_Struct);
|
||||
CharacterSelectEntry_Struct *emu_cse = (CharacterSelectEntry_Struct *)nullptr;
|
||||
|
||||
size_t names_length = 0;
|
||||
size_t character_count = 0;
|
||||
for (; character_count < emu->CharCount && character_count < consts::CHARACTER_CREATION_LIMIT; ++character_count) {
|
||||
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
||||
names_length += strlen(emu_cse->Name);
|
||||
emu_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
size_t total_length = sizeof(structs::CharacterSelect_Struct)
|
||||
+ character_count * sizeof(structs::CharacterSelectEntry_Struct)
|
||||
+ names_length;
|
||||
|
||||
ALLOC_VAR_ENCODE(structs::CharacterSelect_Struct, total_length);
|
||||
structs::CharacterSelectEntry_Struct *eq_cse = (structs::CharacterSelectEntry_Struct *)nullptr;
|
||||
|
||||
//unsigned char *eq_buffer = new unsigned char[total_length];
|
||||
//structs::CharacterSelect_Struct *eq_head = (structs::CharacterSelect_Struct *) eq_buffer;
|
||||
eq->CharCount = character_count;
|
||||
eq->TotalChars = emu->TotalChars;
|
||||
|
||||
eq->char_count = char_count;
|
||||
eq->total_chars = 10;
|
||||
if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT)
|
||||
eq->TotalChars = consts::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
unsigned char *bufptr = (unsigned char *)eq->entries;
|
||||
int r;
|
||||
for (r = 0; r < char_count; r++) {
|
||||
{ //pre-name section...
|
||||
structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr;
|
||||
eq2->level = emu->level[r];
|
||||
eq2->hairstyle = emu->hairstyle[r];
|
||||
eq2->gender = emu->gender[r];
|
||||
memcpy(eq2->name, emu->name[r], strlen(emu->name[r]) + 1);
|
||||
}
|
||||
//adjust for name.
|
||||
bufptr += strlen(emu->name[r]);
|
||||
{ //post-name section...
|
||||
structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr;
|
||||
eq2->beard = emu->beard[r];
|
||||
eq2->haircolor = emu->haircolor[r];
|
||||
eq2->face = emu->face[r];
|
||||
int k;
|
||||
for (k = 0; k < _MaterialCount; k++) {
|
||||
eq2->equip[k].material = emu->equip[r][k].material;
|
||||
eq2->equip[k].unknown1 = emu->equip[r][k].unknown1;
|
||||
eq2->equip[k].elitematerial = emu->equip[r][k].elitematerial;
|
||||
eq2->equip[k].color.color = emu->equip[r][k].color.color;
|
||||
}
|
||||
eq2->primary = emu->primary[r];
|
||||
eq2->secondary = emu->secondary[r];
|
||||
eq2->tutorial = emu->tutorial[r]; // was u15
|
||||
eq2->u15 = 0xff;
|
||||
eq2->deity = emu->deity[r];
|
||||
eq2->zone = emu->zone[r];
|
||||
eq2->u19 = 0xFF;
|
||||
eq2->race = emu->race[r];
|
||||
eq2->gohome = emu->gohome[r];
|
||||
eq2->class_ = emu->class_[r];
|
||||
eq2->eyecolor1 = emu->eyecolor1[r];
|
||||
eq2->beardcolor = emu->beardcolor[r];
|
||||
eq2->eyecolor2 = emu->eyecolor2[r];
|
||||
eq2->drakkin_heritage = emu->drakkin_heritage[r];
|
||||
eq2->drakkin_tattoo = emu->drakkin_tattoo[r];
|
||||
eq2->drakkin_details = emu->drakkin_details[r];
|
||||
// Special Underfoot adjustment - field should really be 'AdditionalChars' or 'BonusChars' in this client
|
||||
uint32 adjusted_total = eq->TotalChars - 8; // Yes, it rolls under for '< 8' - probably an int32 field
|
||||
eq->TotalChars = adjusted_total;
|
||||
|
||||
emu_ptr = __emu_buffer;
|
||||
emu_ptr += sizeof(CharacterSelect_Struct);
|
||||
|
||||
unsigned char *eq_ptr = __packet->pBuffer;
|
||||
eq_ptr += sizeof(structs::CharacterSelect_Struct);
|
||||
|
||||
for (int counter = 0; counter < character_count; ++counter) {
|
||||
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
||||
eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // base address
|
||||
|
||||
eq_cse->Level = emu_cse->Level;
|
||||
eq_cse->HairStyle = emu_cse->HairStyle;
|
||||
eq_cse->Gender = emu_cse->Gender;
|
||||
|
||||
strcpy(eq_cse->Name, emu_cse->Name);
|
||||
eq_ptr += strlen(emu_cse->Name);
|
||||
eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // offset address (base + name length offset)
|
||||
eq_cse->Name[0] = '\0'; // (offset)eq_cse->Name[0] = (base)eq_cse->Name[strlen(emu_cse->Name)]
|
||||
|
||||
eq_cse->Beard = emu_cse->Beard;
|
||||
eq_cse->HairColor = emu_cse->HairColor;
|
||||
eq_cse->Face = emu_cse->Face;
|
||||
|
||||
for (int equip_index = 0; equip_index < _MaterialCount; equip_index++) {
|
||||
eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material;
|
||||
eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1;
|
||||
eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial;
|
||||
eq_cse->Equip[equip_index].Color.Color = emu_cse->Equip[equip_index].Color.Color;
|
||||
}
|
||||
|
||||
bufptr += sizeof(structs::CharacterSelectEntry_Struct);
|
||||
eq_cse->PrimaryIDFile = emu_cse->PrimaryIDFile;
|
||||
eq_cse->SecondaryIDFile = emu_cse->SecondaryIDFile;
|
||||
eq_cse->Tutorial = emu_cse->Tutorial;
|
||||
eq_cse->Unknown15 = emu_cse->Unknown15;
|
||||
eq_cse->Deity = emu_cse->Deity;
|
||||
eq_cse->Zone = emu_cse->Zone;
|
||||
eq_cse->Unknown19 = emu_cse->Unknown19;
|
||||
eq_cse->Race = emu_cse->Race;
|
||||
eq_cse->GoHome = emu_cse->GoHome;
|
||||
eq_cse->Class = emu_cse->Class;
|
||||
eq_cse->EyeColor1 = emu_cse->EyeColor1;
|
||||
eq_cse->BeardColor = emu_cse->BeardColor;
|
||||
eq_cse->EyeColor2 = emu_cse->EyeColor2;
|
||||
eq_cse->DrakkinHeritage = emu_cse->DrakkinHeritage;
|
||||
eq_cse->DrakkinTattoo = emu_cse->DrakkinTattoo;
|
||||
eq_cse->DrakkinDetails = emu_cse->DrakkinDetails;
|
||||
|
||||
emu_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
eq_ptr += sizeof(structs::CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -2621,7 +2676,7 @@ namespace UF
|
||||
OUT(material);
|
||||
OUT(unknown06);
|
||||
OUT(elite_material);
|
||||
OUT(color.color);
|
||||
OUT(color.Color);
|
||||
OUT(wear_slot_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -2693,42 +2748,23 @@ namespace UF
|
||||
|
||||
ENCODE(OP_ZonePlayerToBind)
|
||||
{
|
||||
ENCODE_LENGTH_ATLEAST(ZonePlayerToBind_Struct);
|
||||
SETUP_VAR_ENCODE(ZonePlayerToBind_Struct);
|
||||
ALLOC_LEN_ENCODE(sizeof(structs::ZonePlayerToBind_Struct) + strlen(emu->zone_name));
|
||||
|
||||
ZonePlayerToBind_Struct *zps = (ZonePlayerToBind_Struct*)(*p)->pBuffer;
|
||||
__packet->SetWritePosition(0);
|
||||
__packet->WriteUInt16(emu->bind_zone_id);
|
||||
__packet->WriteUInt16(emu->bind_instance_id);
|
||||
__packet->WriteFloat(emu->x);
|
||||
__packet->WriteFloat(emu->y);
|
||||
__packet->WriteFloat(emu->z);
|
||||
__packet->WriteFloat(emu->heading);
|
||||
__packet->WriteString(emu->zone_name);
|
||||
__packet->WriteUInt8(1); // save items
|
||||
__packet->WriteUInt32(0); // hp
|
||||
__packet->WriteUInt32(0); // mana
|
||||
__packet->WriteUInt32(0); // endurance
|
||||
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
||||
|
||||
unsigned char *buffer1 = new unsigned char[sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)];
|
||||
structs::ZonePlayerToBindHeader_Struct *zph = (structs::ZonePlayerToBindHeader_Struct*)buffer1;
|
||||
unsigned char *buffer2 = new unsigned char[sizeof(structs::ZonePlayerToBindFooter_Struct)];
|
||||
structs::ZonePlayerToBindFooter_Struct *zpf = (structs::ZonePlayerToBindFooter_Struct*)buffer2;
|
||||
|
||||
zph->x = zps->x;
|
||||
zph->y = zps->y;
|
||||
zph->z = zps->z;
|
||||
zph->heading = zps->heading;
|
||||
zph->bind_zone_id = zps->bind_zone_id;
|
||||
zph->bind_instance_id = zps->bind_instance_id;
|
||||
strcpy(zph->zone_name, zps->zone_name);
|
||||
|
||||
zpf->unknown021 = 1;
|
||||
zpf->unknown022 = 0;
|
||||
zpf->unknown023 = 0;
|
||||
zpf->unknown024 = 0;
|
||||
|
||||
ss.write((const char*)buffer1, (sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)));
|
||||
ss.write((const char*)buffer2, sizeof(structs::ZonePlayerToBindFooter_Struct));
|
||||
|
||||
delete[] buffer1;
|
||||
delete[] buffer2;
|
||||
delete[](*p)->pBuffer;
|
||||
|
||||
(*p)->pBuffer = new unsigned char[ss.str().size()];
|
||||
(*p)->size = ss.str().size();
|
||||
|
||||
memcpy((*p)->pBuffer, ss.str().c_str(), ss.str().size());
|
||||
dest->FastQueuePacket(&(*p));
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ZoneServerInfo)
|
||||
@@ -2976,7 +3012,7 @@ namespace UF
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown12
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petOwnerId);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown13
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown14 - Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->PlayerState);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown15
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown16
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown17
|
||||
@@ -3002,7 +3038,7 @@ namespace UF
|
||||
for (k = 0; k < 9; ++k)
|
||||
{
|
||||
{
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].color);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].Color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3012,11 +3048,21 @@ namespace UF
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].material);
|
||||
if (emu->equipment[MaterialPrimary].Material > 99999) {
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 63);
|
||||
} else {
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].Material);
|
||||
}
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].material);
|
||||
if (emu->equipment[MaterialSecondary].Material > 99999) {
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 63);
|
||||
} else {
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].Material);
|
||||
}
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
}
|
||||
@@ -3026,9 +3072,13 @@ namespace UF
|
||||
structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer;
|
||||
|
||||
for (k = 0; k < 9; k++) {
|
||||
Equipment[k].material = emu->equipment[k].material;
|
||||
Equipment[k].unknown1 = emu->equipment[k].unknown1;
|
||||
Equipment[k].elitematerial = emu->equipment[k].elitematerial;
|
||||
if (emu->equipment[k].Material > 99999) {
|
||||
Equipment[k].Material = 63;
|
||||
} else {
|
||||
Equipment[k].Material = emu->equipment[k].Material;
|
||||
}
|
||||
Equipment[k].Unknown1 = emu->equipment[k].Unknown1;
|
||||
Equipment[k].EliteMaterial = emu->equipment[k].EliteMaterial;
|
||||
}
|
||||
|
||||
Buffer += (sizeof(structs::EquipStruct) * 9);
|
||||
@@ -3329,7 +3379,7 @@ namespace UF
|
||||
IN(type);
|
||||
IN(spellid);
|
||||
IN(damage);
|
||||
emu->sequence = eq->sequence;
|
||||
IN(meleepush_xy);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -3572,7 +3622,7 @@ namespace UF
|
||||
SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct);
|
||||
|
||||
IN(command);
|
||||
IN(unknown);
|
||||
IN(target);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -3728,7 +3778,7 @@ namespace UF
|
||||
IN(material);
|
||||
IN(unknown06);
|
||||
IN(elite_material);
|
||||
IN(color.color);
|
||||
IN(color.Color);
|
||||
IN(wear_slot_id);
|
||||
emu->hero_forge_model = 0;
|
||||
emu->unknown18 = 0;
|
||||
@@ -3799,19 +3849,19 @@ namespace UF
|
||||
hdr.unknown044 = 0;
|
||||
hdr.unknown048 = 0;
|
||||
hdr.unknown052 = 0;
|
||||
hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0;
|
||||
hdr.isEvolving = item->EvolvingItem;
|
||||
ss.write((const char*)&hdr, sizeof(UF::structs::ItemSerializationHeader));
|
||||
|
||||
if (item->EvolvingLevel > 0) {
|
||||
if (item->EvolvingItem > 0) {
|
||||
UF::structs::EvolvingItem evotop;
|
||||
evotop.unknown001 = 0;
|
||||
evotop.unknown002 = 0;
|
||||
evotop.unknown003 = 0;
|
||||
evotop.unknown004 = 0;
|
||||
evotop.evoLevel = item->EvolvingLevel;
|
||||
evotop.progress = 95.512;
|
||||
evotop.progress = 0;
|
||||
evotop.Activated = 1;
|
||||
evotop.evomaxlevel = 7;
|
||||
evotop.evomaxlevel = item->EvolvingMax;
|
||||
ss.write((const char*)&evotop, sizeof(UF::structs::EvolvingItem));
|
||||
}
|
||||
//ORNAMENT IDFILE / ICON -
|
||||
@@ -3834,7 +3884,7 @@ namespace UF
|
||||
|
||||
UF::structs::ItemSerializationHeaderFinish hdrf;
|
||||
hdrf.ornamentIcon = ornaIcon;
|
||||
hdrf.unknown060 = 0; //This is Always 0.. or it breaks shit..
|
||||
hdrf.unknown060 = 0; //This is Always 0.. or it breaks shit..
|
||||
hdrf.unknown061 = 0; //possibly ornament / special ornament
|
||||
hdrf.isCopied = 0; //Flag for item to be 'Copied'
|
||||
hdrf.ItemClass = item->ItemClass;
|
||||
@@ -3911,7 +3961,7 @@ namespace UF
|
||||
ibs.Races = item->Races;
|
||||
ibs.Deity = item->Deity;
|
||||
ibs.SkillModValue = item->SkillModValue;
|
||||
ibs.unknown5 = 0;
|
||||
ibs.SkillModMax = item->SkillModMax;
|
||||
ibs.SkillModType = item->SkillModType;
|
||||
ibs.BaneDmgRace = item->BaneDmgRace;
|
||||
ibs.BaneDmgBody = item->BaneDmgBody;
|
||||
|
||||
@@ -101,6 +101,8 @@ namespace UF {
|
||||
}
|
||||
|
||||
namespace consts {
|
||||
static const size_t CHARACTER_CREATION_LIMIT = 12;
|
||||
|
||||
static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount;
|
||||
static const uint16 MAP_BANK_SIZE = 24;
|
||||
static const uint16 MAP_SHARED_BANK_SIZE = 2;
|
||||
@@ -174,9 +176,10 @@ namespace UF {
|
||||
static const uint16 ITEM_COMMON_SIZE = 5;
|
||||
static const uint16 ITEM_CONTAINER_SIZE = 10;
|
||||
|
||||
static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 5;
|
||||
static const size_t BANDOLIERS_SIZE = 20; // number of bandolier instances
|
||||
static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance
|
||||
|
||||
static const size_t POTION_BELT_ITEM_COUNT = 5;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 50;
|
||||
}
|
||||
|
||||
+140
-118
@@ -103,53 +103,53 @@ struct AdventureInfo {
|
||||
*/
|
||||
struct Color_Struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 blue;
|
||||
uint8 green;
|
||||
uint8 red;
|
||||
uint8 use_tint; // if there's a tint this is FF
|
||||
} rgb;
|
||||
uint32 color;
|
||||
union {
|
||||
struct {
|
||||
uint8 blue;
|
||||
uint8 Green;
|
||||
uint8 Red;
|
||||
uint8 UseTint; // if there's a tint this is FF
|
||||
} RGB;
|
||||
uint32 Color;
|
||||
};
|
||||
};
|
||||
|
||||
struct CharSelectEquip {
|
||||
uint32 material;
|
||||
uint32 unknown1;
|
||||
uint32 elitematerial;
|
||||
Color_Struct color;
|
||||
struct CharSelectEquip
|
||||
{
|
||||
uint32 Material;
|
||||
uint32 Unknown1;
|
||||
uint32 EliteMaterial;
|
||||
Color_Struct Color;
|
||||
};
|
||||
|
||||
struct CharacterSelectEntry_Struct {
|
||||
/*0000*/ uint8 level; //
|
||||
/*0000*/ uint8 hairstyle; //
|
||||
/*0002*/ uint8 gender; //
|
||||
/*0003*/ char name[1]; //variable length, edi+0
|
||||
/*0000*/ uint8 beard; //
|
||||
/*0001*/ uint8 haircolor; //
|
||||
/*0000*/ uint8 face; //
|
||||
/*0000*/ CharSelectEquip equip[9];
|
||||
/*0000*/ uint32 primary; //
|
||||
/*0000*/ uint32 secondary; //
|
||||
/*0000*/ uint8 u15; // 0xff
|
||||
/*0000*/ uint32 deity; //
|
||||
/*0000*/ uint16 zone; //
|
||||
/*0000*/ uint16 instance;
|
||||
/*0000*/ uint8 gohome; //
|
||||
/*0000*/ uint8 u19; // 0xff
|
||||
/*0000*/ uint32 race; //
|
||||
/*0000*/ uint8 tutorial; //
|
||||
/*0000*/ uint8 class_; //
|
||||
/*0000*/ uint8 eyecolor1; //
|
||||
/*0000*/ uint8 beardcolor; //
|
||||
/*0000*/ uint8 eyecolor2; //
|
||||
/*0000*/ uint32 drakkin_heritage; // Drakkin Heritage
|
||||
/*0000*/ uint32 drakkin_tattoo; // Drakkin Tattoo
|
||||
/*0000*/ uint32 drakkin_details; // Drakkin Details (Facial Spikes)
|
||||
/*0000*/ uint8 unknown; // New field to Underfoot
|
||||
struct CharacterSelectEntry_Struct
|
||||
{
|
||||
/*0000*/ uint8 Level; //
|
||||
/*0000*/ uint8 HairStyle; //
|
||||
/*0002*/ uint8 Gender; //
|
||||
/*0003*/ char Name[1]; // variable length, edi+0
|
||||
/*0000*/ uint8 Beard; //
|
||||
/*0001*/ uint8 HairColor; //
|
||||
/*0000*/ uint8 Face; //
|
||||
/*0000*/ CharSelectEquip Equip[9];
|
||||
/*0000*/ uint32 PrimaryIDFile; //
|
||||
/*0000*/ uint32 SecondaryIDFile; //
|
||||
/*0000*/ uint8 Unknown15; // 0xff
|
||||
/*0000*/ uint32 Deity; //
|
||||
/*0000*/ uint16 Zone; //
|
||||
/*0000*/ uint16 Instance;
|
||||
/*0000*/ uint8 GoHome; //
|
||||
/*0000*/ uint8 Unknown19; // 0xff
|
||||
/*0000*/ uint32 Race; //
|
||||
/*0000*/ uint8 Tutorial; //
|
||||
/*0000*/ uint8 Class; //
|
||||
/*0000*/ uint8 EyeColor1; //
|
||||
/*0000*/ uint8 BeardColor; //
|
||||
/*0000*/ uint8 EyeColor2; //
|
||||
/*0000*/ uint32 DrakkinHeritage; // Drakkin Heritage
|
||||
/*0000*/ uint32 DrakkinTattoo; // Drakkin Tattoo
|
||||
/*0000*/ uint32 DrakkinDetails; // Drakkin Details (Facial Spikes)
|
||||
/*0000*/ uint8 Unknown; // New field to Underfoot
|
||||
|
||||
};
|
||||
|
||||
@@ -157,20 +157,22 @@ struct CharacterSelectEntry_Struct {
|
||||
** Character Selection Struct
|
||||
**
|
||||
*/
|
||||
struct CharacterSelect_Struct {
|
||||
/*0000*/ uint32 char_count; //number of chars in this packet
|
||||
/*0004*/ uint32 total_chars; //total number of chars allowed?
|
||||
/*0008*/ CharacterSelectEntry_Struct entries[0];
|
||||
struct CharacterSelect_Struct
|
||||
{
|
||||
/*0000*/ uint32 CharCount; //number of chars in this packet
|
||||
/*0004*/ uint32 TotalChars; //total number of chars allowed?
|
||||
/*0008*/ CharacterSelectEntry_Struct Entries[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* Visible equiptment.
|
||||
* Size: 12 Octets
|
||||
*/
|
||||
struct EquipStruct {
|
||||
/*00*/ uint32 material;
|
||||
/*04*/ uint32 unknown1;
|
||||
/*08*/ uint32 elitematerial;
|
||||
struct EquipStruct
|
||||
{
|
||||
/*00*/ uint32 Material;
|
||||
/*04*/ uint32 Unknown1;
|
||||
/*08*/ uint32 EliteMaterial;
|
||||
/*12*/
|
||||
};
|
||||
|
||||
@@ -284,7 +286,7 @@ struct Spawn_Struct
|
||||
/*0000*/ uint8 unknown12;
|
||||
/*0000*/ uint32 petOwnerId;
|
||||
/*0000*/ uint8 unknown13;
|
||||
/*0000*/ uint32 unknown14; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
/*0000*/ uint32 PlayerState; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
/*0000*/ uint32 unknown15;
|
||||
/*0000*/ uint32 unknown16;
|
||||
/*0000*/ uint32 unknown17;
|
||||
@@ -549,7 +551,7 @@ struct SpellBuff_Struct
|
||||
/*003*/ uint8 effect; // not real
|
||||
/*004*/ uint32 unknown004; // Seen 1 for no buff
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 unknown016;
|
||||
/*020*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages
|
||||
/*024*/ uint32 counters;
|
||||
@@ -566,7 +568,7 @@ struct SpellBuffFade_Struct_Underfoot {
|
||||
/*007*/ uint8 unknown7;
|
||||
/*008*/ float unknown008;
|
||||
/*012*/ uint32 spellid;
|
||||
/*016*/ uint32 duration;
|
||||
/*016*/ int32 duration;
|
||||
/*020*/ uint32 num_hits;
|
||||
/*024*/ uint32 playerId; // Global player ID?
|
||||
/*028*/ uint32 unknown020;
|
||||
@@ -583,7 +585,7 @@ struct SpellBuffFade_Struct {
|
||||
/*006*/ uint8 effect;
|
||||
/*007*/ uint8 unknown7;
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 unknown016;
|
||||
/*020*/ uint32 unknown020; // Global player ID?
|
||||
/*024*/ uint32 playerId; // Player id who cast the buff
|
||||
@@ -711,7 +713,7 @@ struct AA_Array
|
||||
{
|
||||
uint32 AA;
|
||||
uint32 value;
|
||||
uint32 unknown08; // Looks like AA_Array is now 12 bytes in Underfoot
|
||||
uint32 charges; // expendable
|
||||
};
|
||||
|
||||
|
||||
@@ -722,9 +724,6 @@ struct Disciplines_Struct {
|
||||
};
|
||||
|
||||
static const uint32 MAX_PLAYER_TRIBUTES = 5;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER = 20;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER_ITEMS = 4;
|
||||
static const uint32 MAX_POTIONS_IN_BELT = 5;
|
||||
static const uint32 TRIBUTE_NONE = 0xFFFFFFFF;
|
||||
|
||||
struct Tribute_Struct {
|
||||
@@ -732,26 +731,42 @@ struct Tribute_Struct {
|
||||
uint32 tier;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct {
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
char item_name[64];
|
||||
};
|
||||
|
||||
//len = 320
|
||||
enum { //bandolier item positions
|
||||
bandolierMainHand = 0,
|
||||
bandolierOffHand,
|
||||
// Bandolier item positions
|
||||
enum
|
||||
{
|
||||
bandolierPrimary = 0,
|
||||
bandolierSecondary,
|
||||
bandolierRange,
|
||||
bandolierAmmo
|
||||
};
|
||||
struct Bandolier_Struct {
|
||||
char name[32];
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
struct PotionBelt_Struct {
|
||||
BandolierItem_Struct items[MAX_POTIONS_IN_BELT];
|
||||
|
||||
//len = 320
|
||||
struct Bandolier_Struct
|
||||
{
|
||||
char Name[32];
|
||||
BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct PotionBeltItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
//len = 288
|
||||
struct PotionBelt_Struct
|
||||
{
|
||||
PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
|
||||
@@ -974,7 +989,7 @@ struct PlayerProfile_Struct
|
||||
/*11236*/ uint32 aapoints_spent; // Number of spent AA points
|
||||
/*11240*/ uint32 aapoints; // Unspent AA points
|
||||
/*11244*/ uint8 unknown11244[4];
|
||||
/*11248*/ Bandolier_Struct bandoliers[MAX_PLAYER_BANDOLIER]; // [6400] bandolier contents
|
||||
/*11248*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // [6400] bandolier contents
|
||||
/*17648*/ PotionBelt_Struct potionbelt; // [360] potion belt 72 extra octets by adding 1 more belt slot
|
||||
/*18008*/ uint8 unknown18008[8];
|
||||
/*18016*/ uint32 available_slots;
|
||||
@@ -1131,7 +1146,7 @@ struct TargetReject_Struct {
|
||||
|
||||
struct PetCommand_Struct {
|
||||
/*000*/ uint32 command;
|
||||
/*004*/ uint32 unknown;
|
||||
/*004*/ uint32 target;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1245,8 +1260,8 @@ struct RequestClientZoneChange_Struct {
|
||||
|
||||
struct Animation_Struct {
|
||||
/*00*/ uint16 spawnid;
|
||||
/*02*/ uint8 action;
|
||||
/*03*/ uint8 value;
|
||||
/*02*/ uint8 speed;
|
||||
/*03*/ uint8 action;
|
||||
/*04*/
|
||||
};
|
||||
|
||||
@@ -1315,9 +1330,11 @@ struct CombatDamage_Struct
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||
/* 05 */ uint16 spellid;
|
||||
/* 07 */ int32 damage;
|
||||
/* 11 */ float unknown11; // cd cc cc 3d
|
||||
/* 15 */ float sequence; // see above notes in Action_Struct
|
||||
/* 19 */ uint8 unknown19[9]; // was [9]
|
||||
/* 11 */ float force; // cd cc cc 3d
|
||||
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 19 */ float meleepush_z;
|
||||
/* 23 */ uint8 unknown23; // was [9]
|
||||
/* 24 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
|
||||
/* 28 */
|
||||
};
|
||||
|
||||
@@ -2172,7 +2189,7 @@ struct GroupFollow_Struct { // Underfoot Follow Struct
|
||||
struct InspectBuffs_Struct {
|
||||
/*000*/ uint32 spell_id[BUFF_COUNT];
|
||||
/*100*/ uint32 filler100[5]; // BUFF_COUNT is really 30...
|
||||
/*120*/ uint32 tics_remaining[BUFF_COUNT];
|
||||
/*120*/ int32 tics_remaining[BUFF_COUNT];
|
||||
/*220*/ uint32 filler220[5]; // BUFF_COUNT is really 30...
|
||||
};
|
||||
|
||||
@@ -2425,7 +2442,7 @@ struct BookRequest_Struct {
|
||||
**
|
||||
*/
|
||||
struct Object_Struct {
|
||||
/*00*/ uint32 linked_list_addr[2];// <Zaphod> They are, get this, prev and next, ala linked list
|
||||
/*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list
|
||||
/*08*/ uint32 unknown008; // Something related to the linked list?
|
||||
/*12*/ uint32 drop_id; // Unique object id for zone
|
||||
/*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in
|
||||
@@ -2445,8 +2462,8 @@ struct Object_Struct {
|
||||
/*100*/ uint32 spawn_id; // Spawn Id of client interacting with object
|
||||
/*104*/
|
||||
};
|
||||
//<Zaphod> 01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] <Zaphod> and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
//01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
|
||||
/*
|
||||
** Click Object Struct
|
||||
@@ -3758,30 +3775,35 @@ struct DynamicWall_Struct {
|
||||
/*80*/
|
||||
};
|
||||
|
||||
enum { //bandolier actions
|
||||
BandolierCreate = 0,
|
||||
BandolierRemove = 1,
|
||||
BandolierSet = 2
|
||||
// Bandolier actions
|
||||
enum
|
||||
{
|
||||
bandolierCreate = 0,
|
||||
bandolierRemove,
|
||||
bandolierSet
|
||||
};
|
||||
|
||||
struct BandolierCreate_Struct {
|
||||
/*00*/ uint32 action; //0 for create
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ char name[32];
|
||||
/*37*/ uint16 unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 unknown39; //0
|
||||
struct BandolierCreate_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; //0 for create
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ char Name[32];
|
||||
/*37*/ uint16 Unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 Unknown39; //0
|
||||
};
|
||||
|
||||
struct BandolierDelete_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierDelete_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct BandolierSet_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierSet_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
// Not 100% sure on this struct. Live as of 1/1/11 is different than UF. Seems to work 'OK'
|
||||
@@ -3865,16 +3887,21 @@ struct SendAA_Struct {
|
||||
/*0049*/ uint32 spellid;
|
||||
/*0053*/ uint32 spell_type;
|
||||
/*0057*/ uint32 spell_refresh;
|
||||
/*0061*/ uint16 classes;
|
||||
/*0063*/ uint16 berserker; //seems to be 1 if its a berserker ability
|
||||
/*0061*/ uint32 classes;
|
||||
/*0065*/ uint32 max_level;
|
||||
/*0069*/ uint32 last_id;
|
||||
/*0073*/ uint32 next_id;
|
||||
/*0077*/ uint32 cost2;
|
||||
/*0081*/ uint8 unknown80[7];
|
||||
/*0081*/ uint8 unknown81;
|
||||
/*0082*/ uint8 grant_only; // VetAAs, progression, etc
|
||||
/*0083*/ uint8 unknown83; // 1 for skill cap increase AAs, Mystical Attuning, and RNG attack inc, doesn't seem to matter though
|
||||
/*0084*/ uint32 expendable_charges; // max charges of the AA
|
||||
/*0088*/ uint32 aa_expansion;
|
||||
/*0092*/ uint32 special_category;
|
||||
/*0096*/ uint32 unknown0096;
|
||||
/*0096*/ uint8 shroud;
|
||||
/*0097*/ uint8 unknown97;
|
||||
/*0098*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter?
|
||||
/*0099*/ uint8 unknown99;
|
||||
/*0100*/ uint32 total_abilities;
|
||||
/*0104*/ AA_Ability abilities[0];
|
||||
};
|
||||
@@ -3886,15 +3913,10 @@ struct AA_List {
|
||||
struct AA_Action {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint32 ability;
|
||||
/*08*/ uint32 unknown08;
|
||||
/*08*/ uint32 target_id;
|
||||
/*12*/ uint32 exp_value;
|
||||
};
|
||||
|
||||
struct AA_Skills { //this should be removed and changed to AA_Array
|
||||
/*00*/ uint32 aa_skill; // Total AAs Spent
|
||||
/*04*/ uint32 aa_value;
|
||||
/*08*/ uint32 unknown08;
|
||||
};
|
||||
|
||||
struct AAExpUpdate_Struct {
|
||||
/*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability
|
||||
@@ -3913,7 +3935,7 @@ struct AltAdvStats_Struct {
|
||||
};
|
||||
|
||||
struct PlayerAA_Struct { // Is this still used?
|
||||
AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AATable_Struct {
|
||||
@@ -3923,7 +3945,7 @@ struct AATable_Struct {
|
||||
/*12*/ int32 unknown012;
|
||||
/*16*/ int32 unknown016;
|
||||
/*20*/ int32 unknown020;
|
||||
/*24*/ AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
/*24*/ AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct Weather_Struct {
|
||||
@@ -4081,7 +4103,7 @@ struct ItemBodyStruct
|
||||
uint32 Races;
|
||||
uint32 Deity;
|
||||
int32 SkillModValue;
|
||||
uint32 unknown5;
|
||||
uint32 SkillModMax;
|
||||
uint32 SkillModType;
|
||||
uint32 BaneDmgRace;
|
||||
uint32 BaneDmgBody;
|
||||
@@ -4184,7 +4206,7 @@ struct ClickEffectStruct
|
||||
|
||||
struct ProcEffectStruct
|
||||
{
|
||||
uint32 effect;
|
||||
int32 effect;
|
||||
uint8 level2;
|
||||
uint32 type;
|
||||
uint8 level;
|
||||
@@ -4199,7 +4221,7 @@ struct ProcEffectStruct
|
||||
|
||||
struct WornEffectStruct //worn, focus and scroll effect
|
||||
{
|
||||
uint32 effect;
|
||||
int32 effect;
|
||||
uint8 level2;
|
||||
uint32 type;
|
||||
uint8 level;
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
#include "pathfind.h"
|
||||
#include "random.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
|
||||
namespace Pathfind
|
||||
{
|
||||
uint32_t InflateData(const char* buffer, uint32_t len, char* out_buffer, uint32_t out_len_max) {
|
||||
z_stream zstream;
|
||||
int zerror = 0;
|
||||
int i;
|
||||
|
||||
zstream.next_in = const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(buffer));
|
||||
zstream.avail_in = len;
|
||||
zstream.next_out = reinterpret_cast<unsigned char*>(out_buffer);;
|
||||
zstream.avail_out = out_len_max;
|
||||
zstream.zalloc = Z_NULL;
|
||||
zstream.zfree = Z_NULL;
|
||||
zstream.opaque = Z_NULL;
|
||||
|
||||
i = inflateInit2(&zstream, 15);
|
||||
if (i != Z_OK) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
zerror = inflate(&zstream, Z_FINISH);
|
||||
if (zerror == Z_STREAM_END) {
|
||||
inflateEnd(&zstream);
|
||||
return zstream.total_out;
|
||||
}
|
||||
else {
|
||||
if (zerror == -4 && zstream.msg == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
zerror = inflateEnd(&zstream);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t nav_mesh_file_version = 2;
|
||||
const float max_dest_drift = 10.0f;
|
||||
const float at_waypoint_eps = 1.0f;
|
||||
EQEmu::Random path_rng;
|
||||
|
||||
float vec_dist(const glm::vec3 &a, const glm::vec3 &b) {
|
||||
float dist_x = a.x - b.x;
|
||||
float dist_y = a.y - b.y;
|
||||
float dist_z = a.z - b.z;
|
||||
return sqrt((dist_x * dist_x) + (dist_y * dist_y) + (dist_z * dist_z));
|
||||
}
|
||||
|
||||
PathfindingManager::PathfindingManager()
|
||||
{
|
||||
m_nav_mesh = nullptr;
|
||||
m_nav_query = nullptr;
|
||||
m_filter.setIncludeFlags(NavigationPolyFlagAll);
|
||||
m_filter.setAreaCost(NavigationAreaFlagNormal, 1.0f);
|
||||
m_filter.setAreaCost(NavigationAreaFlagWater, 2.5f);
|
||||
m_filter.setAreaCost(NavigationAreaFlagLava, 2.5f);
|
||||
m_filter.setAreaCost(NavigationAreaFlagPvP, 1.0f);
|
||||
m_filter.setAreaCost(NavigationAreaFlagSlime, 1.0f);
|
||||
m_filter.setAreaCost(NavigationAreaFlagIce, 1.0f);
|
||||
m_filter.setAreaCost(NavigationAreaFlagVWater, 2.5f);
|
||||
m_filter.setAreaCost(NavigationAreaFlagGeneralArea, 1.0f);
|
||||
m_filter.setAreaCost(NavigationAreaFlagPortal, 1.0f);
|
||||
}
|
||||
|
||||
PathfindingManager::~PathfindingManager()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void PathfindingManager::Load(const std::string &zone_name)
|
||||
{
|
||||
Clear();
|
||||
|
||||
std::string filename = MAP_DIR + std::string("/") + zone_name + ".nav";
|
||||
FILE *f = fopen(filename.c_str(), "rb");
|
||||
if (f) {
|
||||
char magic[9] = { 0 };
|
||||
if (fread(magic, 9, 1, f) != 1) {
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strncmp(magic, "EQNAVMESH", 9) != 0)
|
||||
{
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t version = 0;
|
||||
if (fread(&version, sizeof(uint32_t), 1, f) != 1) {
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
|
||||
if (version != nav_mesh_file_version) {
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t data_size;
|
||||
if (fread(&data_size, sizeof(data_size), 1, f) != 1) {
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t buffer_size;
|
||||
if (fread(&buffer_size, sizeof(buffer_size), 1, f) != 1) {
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<char> data;
|
||||
data.resize(data_size);
|
||||
if (fread(&data[0], data_size, 1, f) != 1) {
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<char> buffer;
|
||||
buffer.resize(buffer_size);
|
||||
uint32_t v = Pathfind::InflateData(&data[0], data_size, &buffer[0], buffer_size);
|
||||
fclose(f);
|
||||
|
||||
char *buf = &buffer[0];
|
||||
m_nav_mesh = dtAllocNavMesh();
|
||||
|
||||
uint32_t number_of_tiles = *(uint32_t*)buf;
|
||||
buf += sizeof(uint32_t);
|
||||
|
||||
dtNavMeshParams params = *(dtNavMeshParams*)buf;
|
||||
buf += sizeof(dtNavMeshParams);
|
||||
|
||||
dtStatus status = m_nav_mesh->init(¶ms);
|
||||
if (dtStatusFailed(status))
|
||||
{
|
||||
dtFreeNavMesh(m_nav_mesh);
|
||||
m_nav_mesh = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < number_of_tiles; ++i)
|
||||
{
|
||||
uint32_t tile_ref = *(uint32_t*)buf;
|
||||
buf += sizeof(uint32_t);
|
||||
|
||||
int32_t data_size = *(uint32_t*)buf;
|
||||
buf += sizeof(uint32_t);
|
||||
|
||||
if (!tile_ref || !data_size) {
|
||||
dtFreeNavMesh(m_nav_mesh);
|
||||
m_nav_mesh = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char* data = (unsigned char*)dtAlloc(data_size, DT_ALLOC_PERM);
|
||||
memcpy(data, buf, data_size);
|
||||
buf += data_size;
|
||||
|
||||
m_nav_mesh->addTile(data, data_size, DT_TILE_FREE_DATA, tile_ref, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PathfindingManager::Clear()
|
||||
{
|
||||
if (m_nav_mesh) {
|
||||
dtFreeNavMesh(m_nav_mesh);
|
||||
m_nav_mesh = nullptr;
|
||||
}
|
||||
|
||||
if (m_nav_query) {
|
||||
dtFreeNavMeshQuery(m_nav_query);
|
||||
m_nav_query = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PathfindingRoute PathfindingManager::FindRoute(const glm::vec3 &src_loc, const glm::vec3 &dest_loc)
|
||||
{
|
||||
glm::vec3 current_location(src_loc.x, src_loc.z, src_loc.y);
|
||||
glm::vec3 dest_location(dest_loc.x, dest_loc.z, dest_loc.y);
|
||||
|
||||
PathfindingRoute ret;
|
||||
ret.m_status = PathComplete;
|
||||
ret.m_dest = dest_loc;
|
||||
ret.m_current_node = 0;
|
||||
ret.m_active = true;
|
||||
|
||||
if (!m_nav_mesh) {
|
||||
PathfindingNode dest;
|
||||
dest.flag = NavigationPolyFlagNormal;
|
||||
dest.position = dest_loc;
|
||||
ret.m_nodes.push_back(dest);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!m_nav_query) {
|
||||
m_nav_query = dtAllocNavMeshQuery();
|
||||
m_nav_query->init(m_nav_mesh, 4092);
|
||||
}
|
||||
|
||||
dtPolyRef start_ref;
|
||||
dtPolyRef end_ref;
|
||||
glm::vec3 ext(15.0f, 15.0f, 15.0f);
|
||||
|
||||
m_nav_query->findNearestPoly(¤t_location[0], &ext[0], &m_filter, &start_ref, 0);
|
||||
m_nav_query->findNearestPoly(&dest_location[0], &ext[0], &m_filter, &end_ref, 0);
|
||||
|
||||
if (!start_ref || !end_ref) {
|
||||
PathfindingNode dest;
|
||||
dest.flag = NavigationPolyFlagNormal;
|
||||
dest.position = dest_loc;
|
||||
ret.m_nodes.push_back(dest);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int npoly = 0;
|
||||
dtPolyRef path[256] = { 0 };
|
||||
auto status = m_nav_query->findPath(start_ref, end_ref, ¤t_location[0], &dest_location[0], &m_filter, path, &npoly, 256);
|
||||
|
||||
if (status & DT_OUT_OF_NODES || status & DT_BUFFER_TOO_SMALL) {
|
||||
ret.m_status = PathPartial;
|
||||
}
|
||||
else if (status & DT_PARTIAL_RESULT) {
|
||||
ret.m_status = PathBroken;
|
||||
}
|
||||
|
||||
if (npoly) {
|
||||
glm::vec3 epos = dest_location;
|
||||
if (path[npoly - 1] != end_ref)
|
||||
m_nav_query->closestPointOnPoly(path[npoly - 1], &dest_location[0], &epos[0], 0);
|
||||
|
||||
float straight_path[512 * 3];
|
||||
unsigned char straight_path_flags[512];
|
||||
int n_straight_polys;
|
||||
dtPolyRef straight_path_polys[512];
|
||||
status = m_nav_query->findStraightPath(¤t_location[0], &epos[0], path, npoly,
|
||||
straight_path, straight_path_flags,
|
||||
straight_path_polys, &n_straight_polys, 512, DT_STRAIGHTPATH_ALL_CROSSINGS);
|
||||
|
||||
if (ret.m_status == PathComplete && status & DT_OUT_OF_NODES || status & DT_BUFFER_TOO_SMALL) {
|
||||
ret.m_status = PathPartial;
|
||||
}
|
||||
else if (ret.m_status == PathComplete && status & DT_PARTIAL_RESULT) {
|
||||
ret.m_status = PathBroken;
|
||||
}
|
||||
|
||||
if (n_straight_polys) {
|
||||
ret.m_nodes.reserve(n_straight_polys);
|
||||
for (int i = 0; i < n_straight_polys; ++i)
|
||||
{
|
||||
PathfindingNode node;
|
||||
node.position.x = straight_path[i * 3];
|
||||
node.position.z = straight_path[i * 3 + 1];
|
||||
node.position.y = straight_path[i * 3 + 2];
|
||||
if (!dtStatusSucceed(m_nav_mesh->getPolyFlags(straight_path_polys[i], &node.flag))) {
|
||||
node.flag = 0;
|
||||
}
|
||||
|
||||
ret.m_nodes.push_back(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
PathfindingNode dest;
|
||||
dest.flag = NavigationPolyFlagNormal;
|
||||
dest.position = dest_loc;
|
||||
ret.m_nodes.push_back(dest);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool PathfindingManager::GetRandomPoint(const glm::vec3 &start, float radius, glm::vec3 &pos)
|
||||
{
|
||||
if(!m_nav_mesh)
|
||||
return false;
|
||||
|
||||
if (!m_nav_query) {
|
||||
m_nav_query = dtAllocNavMeshQuery();
|
||||
m_nav_query->init(m_nav_mesh, 4092);
|
||||
}
|
||||
|
||||
glm::vec3 ext(10.0f, 10.0f, 10.0f);
|
||||
dtPolyRef start_ref;
|
||||
m_nav_query->findNearestPoly(&start[0], &ext[0], &m_filter, &start_ref, 0);
|
||||
if (!start_ref) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dtPolyRef random_ref;
|
||||
glm::vec3 pt;
|
||||
|
||||
dtStatus status = m_nav_query->findRandomPointAroundCircle(start_ref, &start[0], radius,
|
||||
&m_filter, []() -> float { return (float)path_rng.Real(0.0, 1.0); }, &random_ref, &pt[0]);
|
||||
|
||||
if (dtStatusSucceed(status))
|
||||
{
|
||||
pos.x = pt.x;
|
||||
pos.z = pt.y;
|
||||
pos.y = pt.z;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PathfindingRoute::PathfindingRoute()
|
||||
{
|
||||
m_active = false;
|
||||
}
|
||||
|
||||
PathfindingRoute::~PathfindingRoute()
|
||||
{
|
||||
}
|
||||
|
||||
bool PathfindingRoute::DestinationValid(const glm::vec3 &dest)
|
||||
{
|
||||
if (m_status == PathPartial && m_current_node + 1 == m_nodes.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto dist = vec_dist(dest, m_dest);
|
||||
if (dist <= max_dest_drift) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void PathfindingRoute::CalcCurrentNode(const glm::vec3 ¤t_pos, bool &wp_changed)
|
||||
{
|
||||
wp_changed = false;
|
||||
if (m_active) {
|
||||
//if we're at last node then we dont need to do anything.
|
||||
if (m_nodes.size() - 1 == m_current_node) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto ¤t = GetCurrentNode();
|
||||
auto dist = vec_dist(current.position, current_pos);
|
||||
if (dist < at_waypoint_eps) {
|
||||
m_current_node++;
|
||||
wp_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned short PathfindingRoute::GetPreviousNodeFlag()
|
||||
{
|
||||
if(m_current_node == 0)
|
||||
return 0;
|
||||
|
||||
return m_nodes[m_current_node - 1].flag;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <DetourNavMesh.h>
|
||||
#include <DetourNavMeshQuery.h>
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
enum NavigationAreaFlags
|
||||
{
|
||||
NavigationAreaFlagNormal,
|
||||
NavigationAreaFlagWater,
|
||||
NavigationAreaFlagLava,
|
||||
NavigationAreaFlagZoneLine,
|
||||
NavigationAreaFlagPvP,
|
||||
NavigationAreaFlagSlime,
|
||||
NavigationAreaFlagIce,
|
||||
NavigationAreaFlagVWater,
|
||||
NavigationAreaFlagGeneralArea,
|
||||
NavigationAreaFlagPortal,
|
||||
NavigationAreaFlagDisabled,
|
||||
};
|
||||
|
||||
enum NavigationPolyFlags
|
||||
{
|
||||
NavigationPolyFlagNormal = 1,
|
||||
NavigationPolyFlagWater = 2,
|
||||
NavigationPolyFlagLava = 4,
|
||||
NavigationPolyFlagZoneLine = 8,
|
||||
NavigationPolyFlagPvP = 16,
|
||||
NavigationPolyFlagSlime = 32,
|
||||
NavigationPolyFlagIce = 64,
|
||||
NavigationPolyFlagVWater = 128,
|
||||
NavigationPolyFlagGeneralArea = 256,
|
||||
NavigationPolyFlagPortal = 512,
|
||||
NavigationPolyFlagDisabled = 1024,
|
||||
NavigationPolyFlagAll = 0xFFFF
|
||||
};
|
||||
|
||||
struct PathfindingNode
|
||||
{
|
||||
glm::vec3 position;
|
||||
unsigned short flag;
|
||||
};
|
||||
|
||||
enum PathfindingRouteStatus
|
||||
{
|
||||
PathComplete,
|
||||
PathPartial,
|
||||
PathBroken
|
||||
};
|
||||
|
||||
class PathfindingRoute
|
||||
{
|
||||
public:
|
||||
PathfindingRoute();
|
||||
~PathfindingRoute();
|
||||
|
||||
bool Active() const { return m_active; }
|
||||
bool DestinationValid(const glm::vec3 &dest);
|
||||
void CalcCurrentNode(const glm::vec3 ¤t_pos, bool &wp_changed);
|
||||
const PathfindingNode& GetCurrentNode() { return m_nodes[m_current_node]; }
|
||||
unsigned short GetPreviousNodeFlag();
|
||||
const std::vector<PathfindingNode>& GetNodes() const { return m_nodes; }
|
||||
std::vector<PathfindingNode>& GetNodesEdit() { return m_nodes; }
|
||||
PathfindingRouteStatus GetStatus() { return m_status; }
|
||||
private:
|
||||
glm::vec3 m_dest;
|
||||
std::vector<PathfindingNode> m_nodes;
|
||||
int m_current_node;
|
||||
bool m_active;
|
||||
PathfindingRouteStatus m_status;
|
||||
|
||||
friend class PathfindingManager;
|
||||
};
|
||||
|
||||
class PathfindingManager
|
||||
{
|
||||
public:
|
||||
PathfindingManager();
|
||||
~PathfindingManager();
|
||||
|
||||
void Load(const std::string &filename);
|
||||
void Clear();
|
||||
|
||||
//Expects locations in EQEmu internal format eg what #loc returns not what /loc returns.
|
||||
PathfindingRoute FindRoute(const glm::vec3 ¤t_location, const glm::vec3 &dest_location);
|
||||
bool GetRandomPoint(const glm::vec3 &start, float radius, glm::vec3 &pos);
|
||||
bool Loaded() const { return m_nav_mesh != nullptr; }
|
||||
private:
|
||||
dtNavMesh *m_nav_mesh;
|
||||
dtNavMeshQuery *m_nav_query;
|
||||
dtQueryFilter m_filter;
|
||||
};
|
||||
+2
-5
@@ -39,7 +39,8 @@ enum { //values for pTimerType
|
||||
pTimerDisciplineReuseStart = 14,
|
||||
pTimerDisciplineReuseEnd = 24,
|
||||
pTimerCombatAbility = 25,
|
||||
pTimerBeggingPickPocket = 26,
|
||||
pTimerCombatAbility2 = 26, // RoF2+ Tiger Claw is unlinked from other monk skills, generic in case other classes ever need it
|
||||
pTimerBeggingPickPocket = 27,
|
||||
|
||||
pTimerLayHands = 87, //these IDs are used by client too
|
||||
pTimerHarmTouch = 89, //so dont change them
|
||||
@@ -138,8 +139,4 @@ protected:
|
||||
std::map<pTimerType, PersistentTimer *> _list;
|
||||
};
|
||||
|
||||
//code prettying macros
|
||||
#define AA_Choose3(val, v1, v2, v3) (val==1?v1:(val==2?v2:v3))
|
||||
#define AA_Choose5(val, v1, v2, v3, v4, v5) (val==1?v1:(val==2?v2:(val==3?v3:(val==4?v4:v5))))
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
#define IKSAR 128
|
||||
#define VAHSHIR 130
|
||||
#define CONTROLLED_BOAT 141
|
||||
#define MINOR_ILL_OBJ 142
|
||||
#define TREE 143
|
||||
#define IKSAR_SKELETON 161
|
||||
#define FROGLOK 330
|
||||
#define FROGLOK2 74 // Not sure why /who all reports race as 74 for frogloks
|
||||
|
||||
+149
-172
@@ -17,43 +17,14 @@
|
||||
*/
|
||||
|
||||
#include "rulesys.h"
|
||||
|
||||
#include "database.h"
|
||||
#include "string_util.h"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
/*
|
||||
|
||||
FatherNitwit: Added new rules subsystem to allow game rules to be changed
|
||||
at runtime. more about this will come as time goes on.
|
||||
FatherNitwit: Added #rules command to manage rules data from in game.
|
||||
FatherNitwit: Renamed old #rules to #serverrules
|
||||
FatherNitwit: Moved max level into the rules system (Character:MaxLevel)
|
||||
Requred SQL:
|
||||
|
||||
|
||||
|
||||
CREATE TABLE rule_sets (
|
||||
ruleset_id TINYINT UNSIGNED NOT NULL auto_increment,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
PRIMARY KEY(ruleset_id)
|
||||
);
|
||||
INSERT INTO rule_sets VALUES(0, "default");
|
||||
UPDATE rule_sets SET ruleset_id=0;
|
||||
|
||||
CREATE TABLE rule_values (
|
||||
ruleset_id TINYINT UNSIGNED NOT NULL,
|
||||
rule_name VARCHAR(64) NOT NULL,
|
||||
rule_value VARCHAR(10) NOT NULL,
|
||||
INDEX(ruleset_id),
|
||||
PRIMARY KEY(ruleset_id,rule_name)
|
||||
);
|
||||
|
||||
|
||||
|
||||
Commands:
|
||||
#rules:
|
||||
Commands:
|
||||
#rules:
|
||||
current -> lists current set name
|
||||
switch (set name) -> change set in the DB, but dont reload
|
||||
load (set name) -> load set into this zone without changing the world
|
||||
@@ -94,28 +65,28 @@ RuleManager::RuleManager()
|
||||
}
|
||||
|
||||
RuleManager::CategoryType RuleManager::FindCategory(const char *catname) {
|
||||
int r;
|
||||
for(r = 0; r < _CatCount; r++) {
|
||||
if(strcasecmp(catname, s_categoryNames[r]) == 0)
|
||||
return((CategoryType) r);
|
||||
int i;
|
||||
for (i = 0; i < _CatCount; i++) {
|
||||
if (strcasecmp(catname, s_categoryNames[i]) == 0)
|
||||
return((CategoryType)i);
|
||||
}
|
||||
return(InvalidCategory);
|
||||
}
|
||||
|
||||
bool RuleManager::ListRules(const char *catname, std::vector<const char *> &into) {
|
||||
CategoryType cat = InvalidCategory;
|
||||
if(catname != nullptr) {
|
||||
if (catname != nullptr) {
|
||||
cat = FindCategory(catname);
|
||||
if(cat == InvalidCategory) {
|
||||
if (cat == InvalidCategory) {
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Unable to find category '%s'", catname);
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
int r;
|
||||
int rcount = CountRules();
|
||||
for(r = 0; r < rcount; r++) {
|
||||
const RuleInfo &rule = s_RuleInfo[r];
|
||||
if(catname == nullptr || cat == rule.category) {
|
||||
int i;
|
||||
int rule_count = CountRules();
|
||||
for (i = 0; i < rule_count; i++) {
|
||||
const RuleInfo &rule = s_RuleInfo[i];
|
||||
if (catname == nullptr || cat == rule.category) {
|
||||
into.push_back(rule.name);
|
||||
}
|
||||
}
|
||||
@@ -123,15 +94,14 @@ bool RuleManager::ListRules(const char *catname, std::vector<const char *> &into
|
||||
}
|
||||
|
||||
bool RuleManager::ListCategories(std::vector<const char *> &into) {
|
||||
int r;
|
||||
for(r = 0; r < _CatCount; r++) {
|
||||
into.push_back(s_categoryNames[r]);
|
||||
int i;
|
||||
for (i = 0; i < _CatCount; i++) {
|
||||
into.push_back(s_categoryNames[i]);
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
bool RuleManager::GetRule(const char *rule_name, std::string &ret_val) {
|
||||
bool RuleManager::GetRule(const char *rule_name, std::string &return_value) {
|
||||
RuleType type;
|
||||
uint16 index;
|
||||
if (!_FindRule(rule_name, type, index))
|
||||
@@ -151,12 +121,12 @@ bool RuleManager::GetRule(const char *rule_name, std::string &ret_val) {
|
||||
break;
|
||||
}
|
||||
|
||||
ret_val = tmp;
|
||||
return_value = tmp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Database *db, bool db_save) {
|
||||
bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Database *database, bool db_save) {
|
||||
if(rule_name == nullptr || rule_value == nullptr)
|
||||
return(false);
|
||||
|
||||
@@ -166,25 +136,26 @@ bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Databas
|
||||
return(false);
|
||||
|
||||
switch(type) {
|
||||
case IntRule:
|
||||
m_RuleIntValues [index] = atoi(rule_value);
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %d", rule_name, m_RuleIntValues[index]);
|
||||
break;
|
||||
case RealRule:
|
||||
m_RuleRealValues[index] = atof(rule_value);
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %.13f", rule_name, m_RuleRealValues[index]);
|
||||
break;
|
||||
case BoolRule:
|
||||
uint32 val = 0;
|
||||
if(!strcasecmp(rule_value, "on") || !strcasecmp(rule_value, "true") || !strcasecmp(rule_value, "yes") || !strcasecmp(rule_value, "enabled") || !strcmp(rule_value, "1"))
|
||||
val = 1;
|
||||
m_RuleBoolValues[index] = val;
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %s", rule_name, m_RuleBoolValues[index] == 1 ?"true":"false");
|
||||
break;
|
||||
case IntRule:
|
||||
m_RuleIntValues[index] = atoi(rule_value);
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %d", rule_name, m_RuleIntValues[index]);
|
||||
break;
|
||||
case RealRule:
|
||||
m_RuleRealValues[index] = atof(rule_value);
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %.13f", rule_name, m_RuleRealValues[index]);
|
||||
break;
|
||||
case BoolRule:
|
||||
uint32 val = 0;
|
||||
if (!strcasecmp(rule_value, "on") || !strcasecmp(rule_value, "true") || !strcasecmp(rule_value, "yes") || !strcasecmp(rule_value, "enabled") || !strcmp(rule_value, "1"))
|
||||
val = 1;
|
||||
|
||||
m_RuleBoolValues[index] = val;
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %s", rule_name, m_RuleBoolValues[index] == 1 ? "true" : "false");
|
||||
break;
|
||||
}
|
||||
|
||||
if(db_save)
|
||||
_SaveRule(db, type, index);
|
||||
_SaveRule(database, type, index);
|
||||
|
||||
return(true);
|
||||
}
|
||||
@@ -201,14 +172,14 @@ void RuleManager::ResetRules() {
|
||||
}
|
||||
|
||||
bool RuleManager::_FindRule(const char *rule_name, RuleType &type_into, uint16 &index_into) {
|
||||
if(rule_name == nullptr)
|
||||
if (rule_name == nullptr)
|
||||
return(false);
|
||||
|
||||
int r;
|
||||
int rcount = CountRules();
|
||||
for(r = 0; r < rcount; r++) {
|
||||
const RuleInfo &rule = s_RuleInfo[r];
|
||||
if(strcmp(rule_name, rule.name) == 0) {
|
||||
int i;
|
||||
int rule_count = CountRules();
|
||||
for (i = 0; i < rule_count; i++) {
|
||||
const RuleInfo &rule = s_RuleInfo[i];
|
||||
if (strcmp(rule_name, rule.name) == 0) {
|
||||
type_into = rule.type;
|
||||
index_into = rule.rule_index;
|
||||
return(true);
|
||||
@@ -220,191 +191,197 @@ bool RuleManager::_FindRule(const char *rule_name, RuleType &type_into, uint16 &
|
||||
|
||||
//assumes index is valid!
|
||||
const char *RuleManager::_GetRuleName(RuleType type, uint16 index) {
|
||||
switch(type) {
|
||||
case IntRule:
|
||||
return(s_RuleInfo[index].name);
|
||||
case RealRule:
|
||||
return(s_RuleInfo[index+_IntRuleCount].name);
|
||||
case BoolRule:
|
||||
return(s_RuleInfo[index+_IntRuleCount+_RealRuleCount].name);
|
||||
switch (type) {
|
||||
case IntRule:
|
||||
return(s_RuleInfo[index].name);
|
||||
case RealRule:
|
||||
return(s_RuleInfo[index + _IntRuleCount].name);
|
||||
case BoolRule:
|
||||
return(s_RuleInfo[index + _IntRuleCount + _RealRuleCount].name);
|
||||
}
|
||||
//should never happen
|
||||
return("InvalidRule??");
|
||||
}
|
||||
|
||||
void RuleManager::SaveRules(Database *db, const char *ruleset) {
|
||||
void RuleManager::SaveRules(Database *database, const char *ruleset_name) {
|
||||
|
||||
if(ruleset != nullptr) {
|
||||
if (ruleset_name != nullptr) {
|
||||
//saving to a specific name
|
||||
if(m_activeName != ruleset) {
|
||||
if (m_activeName != ruleset_name) {
|
||||
//a new name...
|
||||
|
||||
m_activeRuleset = _FindOrCreateRuleset(db, ruleset);
|
||||
if(m_activeRuleset == -1) {
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Unable to find or create rule set %s", ruleset);
|
||||
m_activeRuleset = _FindOrCreateRuleset(database, ruleset_name);
|
||||
if (m_activeRuleset == -1) {
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Unable to find or create rule set %s", ruleset_name);
|
||||
return;
|
||||
}
|
||||
m_activeName = ruleset;
|
||||
m_activeName = ruleset_name;
|
||||
}
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Saving running rules into rule set %s (%d)", ruleset, m_activeRuleset);
|
||||
} else {
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Saving running rules into rule set %s (%d)", ruleset_name, m_activeRuleset);
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Saving running rules into running rule set %s", m_activeName.c_str(), m_activeRuleset);
|
||||
}
|
||||
|
||||
int r;
|
||||
for(r = 0; r < _IntRuleCount; r++) {
|
||||
_SaveRule(db, IntRule, r);
|
||||
int i;
|
||||
for (i = 0; i < _IntRuleCount; i++) {
|
||||
_SaveRule(database, IntRule, i);
|
||||
}
|
||||
for(r = 0; r < _RealRuleCount; r++) {
|
||||
_SaveRule(db, RealRule, r);
|
||||
for (i = 0; i < _RealRuleCount; i++) {
|
||||
_SaveRule(database, RealRule, i);
|
||||
}
|
||||
for(r = 0; r < _BoolRuleCount; r++) {
|
||||
_SaveRule(db, BoolRule, r);
|
||||
for (i = 0; i < _BoolRuleCount; i++) {
|
||||
_SaveRule(database, BoolRule, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool RuleManager::LoadRules(Database *db, const char *ruleset) {
|
||||
|
||||
int rsid = GetRulesetID(db, ruleset);
|
||||
if(rsid < 0) {
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Failed to find ruleset '%s' for load operation. Canceling.", ruleset);
|
||||
bool RuleManager::LoadRules(Database *database, const char *ruleset_name) {
|
||||
|
||||
int ruleset_id = GetRulesetID(database, ruleset_name);
|
||||
if (ruleset_id < 0) {
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Failed to find ruleset '%s' for load operation. Canceling.", ruleset_name);
|
||||
return(false);
|
||||
}
|
||||
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", ruleset, rsid);
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", ruleset_name, ruleset_id);
|
||||
|
||||
m_activeRuleset = rsid;
|
||||
m_activeName = ruleset;
|
||||
m_activeRuleset = ruleset_id;
|
||||
m_activeName = ruleset_name;
|
||||
|
||||
std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id=%d", rsid);
|
||||
auto results = db->QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
{
|
||||
return false;
|
||||
/* Load default ruleset values first if we're loading something other than default */
|
||||
if (strcasecmp(ruleset_name, "default") != 0){
|
||||
std::string default_ruleset_name = "default";
|
||||
int default_ruleset_id = GetRulesetID(database, default_ruleset_name.c_str());
|
||||
if (default_ruleset_id < 0) {
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Failed to find default ruleset '%s' for load operation. Canceling.", default_ruleset_name.c_str());
|
||||
return(false);
|
||||
}
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", default_ruleset_name.c_str(), default_ruleset_id);
|
||||
|
||||
std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id = %d", default_ruleset_id);
|
||||
auto results = database->QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
if (!SetRule(row[0], row[1], nullptr, false))
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
|
||||
}
|
||||
|
||||
for(auto row = results.begin(); row != results.end(); ++row)
|
||||
if(!SetRule(row[0], row[1], nullptr, false))
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
|
||||
std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id=%d", ruleset_id);
|
||||
auto results = database->QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
if (!SetRule(row[0], row[1], nullptr, false))
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuleManager::_SaveRule(Database *db, RuleType type, uint16 index) {
|
||||
char vstr[100];
|
||||
void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) {
|
||||
char value_string[100];
|
||||
|
||||
switch(type) {
|
||||
case IntRule:
|
||||
sprintf(vstr, "%d", m_RuleIntValues[index]);
|
||||
break;
|
||||
case RealRule:
|
||||
sprintf(vstr, "%.13f", m_RuleRealValues[index]);
|
||||
break;
|
||||
case BoolRule:
|
||||
sprintf(vstr, "%s", m_RuleBoolValues[index]?"true":"false");
|
||||
break;
|
||||
case IntRule:
|
||||
sprintf(value_string, "%d", m_RuleIntValues[index]);
|
||||
break;
|
||||
case RealRule:
|
||||
sprintf(value_string, "%.13f", m_RuleRealValues[index]);
|
||||
break;
|
||||
case BoolRule:
|
||||
sprintf(value_string, "%s", m_RuleBoolValues[index]?"true":"false");
|
||||
break;
|
||||
}
|
||||
|
||||
std::string query = StringFormat("REPLACE INTO rule_values "
|
||||
"(ruleset_id, rule_name, rule_value) "
|
||||
" VALUES(%d, '%s', '%s')",
|
||||
m_activeRuleset, _GetRuleName(type, index), vstr);
|
||||
auto results = db->QueryDatabase(query);
|
||||
m_activeRuleset, _GetRuleName(type, index), value_string);
|
||||
auto results = database->QueryDatabase(query);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int RuleManager::GetRulesetID(Database *db, const char *rulesetname) {
|
||||
int RuleManager::GetRulesetID(Database *database, const char *ruleset_name) {
|
||||
|
||||
uint32 len = strlen(rulesetname);
|
||||
char* rst = new char[2*len+1];
|
||||
db->DoEscapeString(rst, rulesetname, len);
|
||||
uint32 len = strlen(ruleset_name);
|
||||
char* rst = new char[2 * len + 1];
|
||||
database->DoEscapeString(rst, ruleset_name, len);
|
||||
|
||||
std::string query = StringFormat("SELECT ruleset_id FROM rule_sets WHERE name='%s'", rst);
|
||||
safe_delete_array(rst);
|
||||
auto results = db->QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return -1;
|
||||
}
|
||||
std::string query = StringFormat("SELECT ruleset_id FROM rule_sets WHERE name='%s'", rst);
|
||||
safe_delete_array(rst);
|
||||
auto results = database->QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return -1;
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
return -1;
|
||||
if (results.RowCount() == 0)
|
||||
return -1;
|
||||
|
||||
auto row = results.begin();
|
||||
auto row = results.begin();
|
||||
|
||||
return atoi(row[0]);
|
||||
}
|
||||
|
||||
int RuleManager::_FindOrCreateRuleset(Database *db, const char *ruleset) {
|
||||
int RuleManager::_FindOrCreateRuleset(Database *database, const char *in_ruleset_name) {
|
||||
|
||||
int res = GetRulesetID(db, ruleset);
|
||||
if(res >= 0)
|
||||
return res; //found and existing one...
|
||||
int ruleset_id = GetRulesetID(database, in_ruleset_name);
|
||||
if (ruleset_id >= 0)
|
||||
return ruleset_id; //found and existing one...
|
||||
|
||||
uint32 len = strlen(ruleset);
|
||||
char* rst = new char[2*len+1];
|
||||
db->DoEscapeString(rst, ruleset, len);
|
||||
uint32 len = strlen(in_ruleset_name);
|
||||
char* ruleset_name = new char[2 * len + 1];
|
||||
database->DoEscapeString(ruleset_name, in_ruleset_name, len);
|
||||
|
||||
std::string query = StringFormat("INSERT INTO rule_sets (ruleset_id, name) VALUES(0, '%s')", rst);
|
||||
safe_delete_array(rst);
|
||||
auto results = db->QueryDatabase(query);
|
||||
std::string query = StringFormat("INSERT INTO rule_sets (ruleset_id, name) VALUES(0, '%s')", ruleset_name);
|
||||
safe_delete_array(ruleset_name);
|
||||
auto results = database->QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return results.LastInsertedID();
|
||||
return results.LastInsertedID();
|
||||
}
|
||||
|
||||
std::string RuleManager::GetRulesetName(Database *db, int id) {
|
||||
|
||||
std::string query = StringFormat("SELECT name FROM rule_sets WHERE ruleset_id=%d", id);
|
||||
auto results = db->QueryDatabase(query);
|
||||
std::string RuleManager::GetRulesetName(Database *database, int ruleset_id) {
|
||||
std::string query = StringFormat("SELECT name FROM rule_sets WHERE ruleset_id=%d", ruleset_id);
|
||||
auto results = database->QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return "";
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
return "";
|
||||
return "";
|
||||
|
||||
auto row = results.begin();
|
||||
auto row = results.begin();
|
||||
|
||||
return row[0];
|
||||
}
|
||||
|
||||
bool RuleManager::ListRulesets(Database *db, std::map<int, std::string> &into) {
|
||||
bool RuleManager::ListRulesets(Database *database, std::map<int, std::string> &into) {
|
||||
|
||||
//start out with the default set which is always present.
|
||||
into[0] = "default";
|
||||
|
||||
std::string query = "SELECT ruleset_id, name FROM rule_sets";
|
||||
auto results = db->QueryDatabase(query);
|
||||
std::string query = "SELECT ruleset_id, name FROM rule_sets";
|
||||
auto results = database->QueryDatabase(query);
|
||||
if (results.Success())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
into[ atoi(row[0]) ] = row[1];
|
||||
into[atoi(row[0])] = row[1];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int32 RuleManager::GetIntRule(RuleManager::IntType t) const
|
||||
{
|
||||
int32 RuleManager::GetIntRule(RuleManager::IntType t) const{
|
||||
return(m_RuleIntValues[t]);
|
||||
}
|
||||
|
||||
float RuleManager::GetRealRule(RuleManager::RealType t) const
|
||||
{
|
||||
float RuleManager::GetRealRule(RuleManager::RealType t) const{
|
||||
return(m_RuleRealValues[t]);
|
||||
}
|
||||
|
||||
bool RuleManager::GetBoolRule(RuleManager::BoolType t) const
|
||||
{
|
||||
bool RuleManager::GetBoolRule(RuleManager::BoolType t) const{
|
||||
return (m_RuleBoolValues[t] == 1);
|
||||
}
|
||||
|
||||
|
||||
+542
-496
File diff suppressed because it is too large
Load Diff
+6
-1
@@ -84,6 +84,7 @@
|
||||
#define ServerOP_QGlobalDelete 0x0064
|
||||
#define ServerOP_DepopPlayerCorpse 0x0065
|
||||
#define ServerOP_RequestTellQueue 0x0066 // client asks for it's tell queues
|
||||
#define ServerOP_ChangeSharedMem 0x0067
|
||||
|
||||
#define ServerOP_RaidAdd 0x0100 //in use
|
||||
#define ServerOP_RaidRemove 0x0101 //in use
|
||||
@@ -181,6 +182,7 @@
|
||||
#define ServerOP_CZMessagePlayer 0x4008
|
||||
#define ServerOP_ReloadWorld 0x4009
|
||||
#define ServerOP_ReloadLogs 0x4010
|
||||
#define ServerOP_ReloadPerlExportSettings 0x4011
|
||||
/* Query Server OP Codes */
|
||||
#define ServerOP_QSPlayerLogTrades 0x5010
|
||||
#define ServerOP_QSPlayerLogHandins 0x5011
|
||||
@@ -521,7 +523,7 @@ struct ServerLSPlayerZoneChange_Struct {
|
||||
uint32 from; // 0 = world
|
||||
uint32 to; // 0 = world
|
||||
};
|
||||
struct ServerLSClientAuth {
|
||||
struct ClientAuth_Struct {
|
||||
uint32 lsaccount_id; // ID# in login server's db
|
||||
char name[30]; // username in login server's db
|
||||
char key[30]; // the Key the client will present
|
||||
@@ -545,7 +547,9 @@ struct ServerLSPeerConnect {
|
||||
|
||||
struct ServerConnectInfo {
|
||||
char address[250];
|
||||
char local_address[250];
|
||||
uint16 port;
|
||||
uint32 process_id;
|
||||
};
|
||||
|
||||
struct ServerGMGoto_Struct {
|
||||
@@ -760,6 +764,7 @@ typedef enum {
|
||||
struct LauncherZoneRequest {
|
||||
uint8 command;
|
||||
char short_name[33];
|
||||
uint16 port;
|
||||
};
|
||||
|
||||
struct LauncherZoneStatus {
|
||||
|
||||
+337
-344
@@ -1,6 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1800
|
||||
#include <algorithm>
|
||||
#endif
|
||||
|
||||
#include "classes.h"
|
||||
#include "eq_packet_structs.h"
|
||||
#include "eqemu_exception.h"
|
||||
@@ -16,29 +20,16 @@
|
||||
#include "string_util.h"
|
||||
|
||||
SharedDatabase::SharedDatabase()
|
||||
: Database(), skill_caps_mmf(nullptr), items_mmf(nullptr), items_hash(nullptr), faction_mmf(nullptr), faction_hash(nullptr),
|
||||
loot_table_mmf(nullptr), loot_table_hash(nullptr), loot_drop_mmf(nullptr), loot_drop_hash(nullptr), base_data_mmf(nullptr)
|
||||
: Database()
|
||||
{
|
||||
}
|
||||
|
||||
SharedDatabase::SharedDatabase(const char* host, const char* user, const char* passwd, const char* database, uint32 port)
|
||||
: Database(host, user, passwd, database, port), skill_caps_mmf(nullptr), items_mmf(nullptr), items_hash(nullptr),
|
||||
faction_mmf(nullptr), faction_hash(nullptr), loot_table_mmf(nullptr), loot_table_hash(nullptr), loot_drop_mmf(nullptr),
|
||||
loot_drop_hash(nullptr), base_data_mmf(nullptr)
|
||||
: Database(host, user, passwd, database, port)
|
||||
{
|
||||
}
|
||||
|
||||
SharedDatabase::~SharedDatabase() {
|
||||
safe_delete(skill_caps_mmf);
|
||||
safe_delete(items_mmf);
|
||||
safe_delete(items_hash);
|
||||
safe_delete(faction_mmf);
|
||||
safe_delete(faction_hash);
|
||||
safe_delete(loot_table_mmf);
|
||||
safe_delete(loot_drop_mmf);
|
||||
safe_delete(loot_table_hash);
|
||||
safe_delete(loot_drop_hash);
|
||||
safe_delete(base_data_mmf);
|
||||
}
|
||||
|
||||
bool SharedDatabase::SetHideMe(uint32 account_id, uint8 hideme)
|
||||
@@ -151,28 +142,31 @@ bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const Ite
|
||||
|
||||
bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 slot_id) {
|
||||
|
||||
// If we never save tribute slots..how are we to ever benefit from them!!? The client
|
||||
// object is destroyed upon zoning - including its inventory object..and if tributes
|
||||
// don't exist in the database, then they will never be loaded when the new client
|
||||
// object is created in the new zone object... Something to consider... -U
|
||||
//
|
||||
// (we could add them to the 'NoRent' checks and dispose of after 30 minutes offline)
|
||||
|
||||
//never save tribute slots:
|
||||
if(slot_id >= EmuConstants::TRIBUTE_BEGIN && slot_id <= EmuConstants::TRIBUTE_END)
|
||||
return true;
|
||||
|
||||
if (slot_id >= EmuConstants::SHARED_BANK_BEGIN && slot_id <= EmuConstants::SHARED_BANK_BAGS_END) {
|
||||
// Shared bank inventory
|
||||
if (!inst)
|
||||
return DeleteSharedBankSlot(char_id, slot_id);
|
||||
else
|
||||
return UpdateSharedBankSlot(char_id, inst, slot_id);
|
||||
if (!inst) {
|
||||
return DeleteSharedBankSlot(char_id, slot_id);
|
||||
}
|
||||
else {
|
||||
// Needed to clear out bag slots that 'REPLACE' in UpdateSharedBankSlot does not overwrite..otherwise, duplication occurs
|
||||
// (This requires that parent then child items be sent..which should be how they are currently passed)
|
||||
if (Inventory::SupportsContainers(slot_id))
|
||||
DeleteSharedBankSlot(char_id, slot_id);
|
||||
return UpdateSharedBankSlot(char_id, inst, slot_id);
|
||||
}
|
||||
}
|
||||
else if (!inst) { // All other inventory
|
||||
return DeleteInventorySlot(char_id, slot_id);
|
||||
}
|
||||
|
||||
// Needed to clear out bag slots that 'REPLACE' in UpdateInventorySlot does not overwrite..otherwise, duplication occurs
|
||||
// (This requires that parent then child items be sent..which should be how they are currently passed)
|
||||
if (Inventory::SupportsContainers(slot_id))
|
||||
DeleteInventorySlot(char_id, slot_id);
|
||||
return UpdateInventorySlot(char_id, inst, slot_id);
|
||||
}
|
||||
|
||||
@@ -209,7 +203,9 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, i
|
||||
|
||||
// Save bag contents, if slot supports bag contents
|
||||
if (inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id))
|
||||
for (uint8 idx = SUB_BEGIN; idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) {
|
||||
// Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID'
|
||||
// messages through attrition (and the modded code in SaveInventory)
|
||||
for (uint8 idx = SUB_BEGIN; idx < inst->GetItem()->BagSlots && idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) {
|
||||
const ItemInst* baginst = inst->GetItem(idx);
|
||||
SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx));
|
||||
}
|
||||
@@ -253,7 +249,9 @@ bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst,
|
||||
|
||||
// Save bag contents, if slot supports bag contents
|
||||
if (inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id)) {
|
||||
for (uint8 idx = SUB_BEGIN; idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) {
|
||||
// Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID'
|
||||
// messages through attrition (and the modded code in SaveInventory)
|
||||
for (uint8 idx = SUB_BEGIN; idx < inst->GetItem()->BagSlots && idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) {
|
||||
const ItemInst* baginst = inst->GetItem(idx);
|
||||
SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx));
|
||||
}
|
||||
@@ -790,28 +788,15 @@ void SharedDatabase::GetItemsCount(int32 &item_count, uint32 &max_id)
|
||||
item_count = atoi(row[1]);
|
||||
}
|
||||
|
||||
bool SharedDatabase::LoadItems() {
|
||||
if(items_mmf) {
|
||||
return true;
|
||||
}
|
||||
bool SharedDatabase::LoadItems(const std::string &prefix) {
|
||||
items_mmf.reset(nullptr);
|
||||
|
||||
try {
|
||||
EQEmu::IPCMutex mutex("items");
|
||||
mutex.Lock();
|
||||
items_mmf = new EQEmu::MemoryMappedFile("shared/items");
|
||||
|
||||
int32 items = -1;
|
||||
uint32 max_item = 0;
|
||||
GetItemsCount(items, max_item);
|
||||
if(items == -1) {
|
||||
EQ_EXCEPT("SharedDatabase", "Database returned no result");
|
||||
}
|
||||
uint32 size = static_cast<uint32>(EQEmu::FixedMemoryHashSet<Item_Struct>::estimated_size(items, max_item));
|
||||
if(items_mmf->Size() != size) {
|
||||
EQ_EXCEPT("SharedDatabase", "Couldn't load items because items_mmf->Size() != size");
|
||||
}
|
||||
|
||||
items_hash = new EQEmu::FixedMemoryHashSet<Item_Struct>(reinterpret_cast<uint8*>(items_mmf->Get()), size);
|
||||
std::string file_name = std::string("shared/") + prefix + std::string("items");
|
||||
items_mmf = std::unique_ptr<EQEmu::MemoryMappedFile>(new EQEmu::MemoryMappedFile(file_name));
|
||||
items_hash = std::unique_ptr<EQEmu::FixedMemoryHashSet<Item_Struct>>(new EQEmu::FixedMemoryHashSet<Item_Struct>(reinterpret_cast<uint8*>(items_mmf->Get()), items_mmf->Size()));
|
||||
mutex.Unlock();
|
||||
} catch(std::exception& ex) {
|
||||
Log.Out(Logs::General, Logs::Error, "Error Loading Items: %s", ex.what());
|
||||
@@ -821,36 +806,37 @@ bool SharedDatabase::LoadItems() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id) {
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> hash(reinterpret_cast<uint8*>(data), size, items, max_item_id);
|
||||
void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id)
|
||||
{
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> hash(reinterpret_cast<uint8 *>(data), size, items, max_item_id);
|
||||
|
||||
char ndbuffer[4];
|
||||
bool disableNoRent = false;
|
||||
if(GetVariable("disablenorent", ndbuffer, 4)) {
|
||||
if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') {
|
||||
if (GetVariable("disablenorent", ndbuffer, 4)) {
|
||||
if (ndbuffer[0] == '1' && ndbuffer[1] == '\0') {
|
||||
disableNoRent = true;
|
||||
}
|
||||
}
|
||||
bool disableNoDrop = false;
|
||||
if(GetVariable("disablenodrop", ndbuffer, 4)) {
|
||||
if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') {
|
||||
if (GetVariable("disablenodrop", ndbuffer, 4)) {
|
||||
if (ndbuffer[0] == '1' && ndbuffer[1] == '\0') {
|
||||
disableNoDrop = true;
|
||||
}
|
||||
}
|
||||
bool disableLoreGroup = false;
|
||||
if(GetVariable("disablelore", ndbuffer, 4)) {
|
||||
if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') {
|
||||
if (GetVariable("disablelore", ndbuffer, 4)) {
|
||||
if (ndbuffer[0] == '1' && ndbuffer[1] == '\0') {
|
||||
disableLoreGroup = true;
|
||||
}
|
||||
}
|
||||
bool disableNoTransfer = false;
|
||||
if(GetVariable("disablenotransfer", ndbuffer, 4)) {
|
||||
if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') {
|
||||
if (GetVariable("disablenotransfer", ndbuffer, 4)) {
|
||||
if (ndbuffer[0] == '1' && ndbuffer[1] == '\0') {
|
||||
disableNoTransfer = true;
|
||||
}
|
||||
}
|
||||
|
||||
Item_Struct item;
|
||||
Item_Struct item;
|
||||
|
||||
const std::string query = "SELECT source,"
|
||||
#define F(x) "`"#x"`,"
|
||||
@@ -858,224 +844,226 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
|
||||
#undef F
|
||||
"updated FROM items ORDER BY id";
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return;
|
||||
}
|
||||
if (!results.Success()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(auto row = results.begin(); row != results.end(); ++row) {
|
||||
memset(&item, 0, sizeof(Item_Struct));
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
memset(&item, 0, sizeof(Item_Struct));
|
||||
|
||||
item.ItemClass = (uint8)atoi(row[ItemField::itemclass]);
|
||||
strcpy(item.Name,row[ItemField::name]);
|
||||
strcpy(item.Lore,row[ItemField::lore]);
|
||||
strcpy(item.IDFile,row[ItemField::idfile]);
|
||||
item.ItemClass = (uint8)atoi(row[ItemField::itemclass]);
|
||||
strcpy(item.Name, row[ItemField::name]);
|
||||
strcpy(item.Lore, row[ItemField::lore]);
|
||||
strcpy(item.IDFile, row[ItemField::idfile]);
|
||||
|
||||
item.ID = (uint32)atoul(row[ItemField::id]);
|
||||
item.Weight = (uint8)atoi(row[ItemField::weight]);
|
||||
item.NoRent = disableNoRent ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::norent]);
|
||||
item.NoDrop = disableNoDrop ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::nodrop]);
|
||||
item.Size = (uint8)atoi(row[ItemField::size]);
|
||||
item.Slots = (uint32)atoul(row[ItemField::slots]);
|
||||
item.Price = (uint32)atoul(row[ItemField::price]);
|
||||
item.Icon = (uint32)atoul(row[ItemField::icon]);
|
||||
item.BenefitFlag = (atoul(row[ItemField::benefitflag]) != 0);
|
||||
item.Tradeskills = (atoi(row[ItemField::tradeskills])==0) ? false : true;
|
||||
item.CR = (int8)atoi(row[ItemField::cr]);
|
||||
item.DR = (int8)atoi(row[ItemField::dr]);
|
||||
item.PR = (int8)atoi(row[ItemField::pr]);
|
||||
item.MR = (int8)atoi(row[ItemField::mr]);
|
||||
item.FR = (int8)atoi(row[ItemField::fr]);
|
||||
item.AStr = (int8)atoi(row[ItemField::astr]);
|
||||
item.ASta = (int8)atoi(row[ItemField::asta]);
|
||||
item.AAgi = (int8)atoi(row[ItemField::aagi]);
|
||||
item.ADex = (int8)atoi(row[ItemField::adex]);
|
||||
item.ACha = (int8)atoi(row[ItemField::acha]);
|
||||
item.AInt = (int8)atoi(row[ItemField::aint]);
|
||||
item.AWis = (int8)atoi(row[ItemField::awis]);
|
||||
item.HP = (int32)atoul(row[ItemField::hp]);
|
||||
item.Mana = (int32)atoul(row[ItemField::mana]);
|
||||
item.AC = (int32)atoul(row[ItemField::ac]);
|
||||
item.Deity = (uint32)atoul(row[ItemField::deity]);
|
||||
item.SkillModValue = (int32)atoul(row[ItemField::skillmodvalue]);
|
||||
item.ID = (uint32)atoul(row[ItemField::id]);
|
||||
item.Weight = (uint8)atoi(row[ItemField::weight]);
|
||||
item.NoRent = disableNoRent ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::norent]);
|
||||
item.NoDrop = disableNoDrop ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::nodrop]);
|
||||
item.Size = (uint8)atoi(row[ItemField::size]);
|
||||
item.Slots = (uint32)atoul(row[ItemField::slots]);
|
||||
item.Price = (uint32)atoul(row[ItemField::price]);
|
||||
item.Icon = (uint32)atoul(row[ItemField::icon]);
|
||||
item.BenefitFlag = (atoul(row[ItemField::benefitflag]) != 0);
|
||||
item.Tradeskills = (atoi(row[ItemField::tradeskills]) == 0) ? false : true;
|
||||
item.CR = (int8)atoi(row[ItemField::cr]);
|
||||
item.DR = (int8)atoi(row[ItemField::dr]);
|
||||
item.PR = (int8)atoi(row[ItemField::pr]);
|
||||
item.MR = (int8)atoi(row[ItemField::mr]);
|
||||
item.FR = (int8)atoi(row[ItemField::fr]);
|
||||
item.AStr = (int8)atoi(row[ItemField::astr]);
|
||||
item.ASta = (int8)atoi(row[ItemField::asta]);
|
||||
item.AAgi = (int8)atoi(row[ItemField::aagi]);
|
||||
item.ADex = (int8)atoi(row[ItemField::adex]);
|
||||
item.ACha = (int8)atoi(row[ItemField::acha]);
|
||||
item.AInt = (int8)atoi(row[ItemField::aint]);
|
||||
item.AWis = (int8)atoi(row[ItemField::awis]);
|
||||
item.HP = (int32)atoul(row[ItemField::hp]);
|
||||
item.Mana = (int32)atoul(row[ItemField::mana]);
|
||||
item.AC = (int32)atoul(row[ItemField::ac]);
|
||||
item.Deity = (uint32)atoul(row[ItemField::deity]);
|
||||
item.SkillModValue = (int32)atoul(row[ItemField::skillmodvalue]);
|
||||
item.SkillModMax = (int32)atoul(row[ItemField::skillmodmax]);
|
||||
item.SkillModType = (uint32)atoul(row[ItemField::skillmodtype]);
|
||||
item.BaneDmgRace = (uint32)atoul(row[ItemField::banedmgrace]);
|
||||
item.BaneDmgAmt = (int8)atoi(row[ItemField::banedmgamt]);
|
||||
item.BaneDmgBody = (uint32)atoul(row[ItemField::banedmgbody]);
|
||||
item.Magic = (atoi(row[ItemField::magic]) == 0) ? false : true;
|
||||
item.CastTime_ = (int32)atoul(row[ItemField::casttime_]);
|
||||
item.ReqLevel = (uint8)atoi(row[ItemField::reqlevel]);
|
||||
item.BardType = (uint32)atoul(row[ItemField::bardtype]);
|
||||
item.BardValue = (int32)atoul(row[ItemField::bardvalue]);
|
||||
item.Light = (int8)atoi(row[ItemField::light]);
|
||||
item.Delay = (uint8)atoi(row[ItemField::delay]);
|
||||
item.RecLevel = (uint8)atoi(row[ItemField::reclevel]);
|
||||
item.RecSkill = (uint8)atoi(row[ItemField::recskill]);
|
||||
item.ElemDmgType = (uint8)atoi(row[ItemField::elemdmgtype]);
|
||||
item.ElemDmgAmt = (uint8)atoi(row[ItemField::elemdmgamt]);
|
||||
item.Range = (uint8)atoi(row[ItemField::range]);
|
||||
item.Damage = (uint32)atoi(row[ItemField::damage]);
|
||||
item.Color = (uint32)atoul(row[ItemField::color]);
|
||||
item.Classes = (uint32)atoul(row[ItemField::classes]);
|
||||
item.Races = (uint32)atoul(row[ItemField::races]);
|
||||
|
||||
item.SkillModType = (uint32)atoul(row[ItemField::skillmodtype]);
|
||||
item.BaneDmgRace = (uint32)atoul(row[ItemField::banedmgrace]);
|
||||
item.BaneDmgAmt = (int8)atoi(row[ItemField::banedmgamt]);
|
||||
item.BaneDmgBody = (uint32)atoul(row[ItemField::banedmgbody]);
|
||||
item.Magic = (atoi(row[ItemField::magic])==0) ? false : true;
|
||||
item.CastTime_ = (int32)atoul(row[ItemField::casttime_]);
|
||||
item.ReqLevel = (uint8)atoi(row[ItemField::reqlevel]);
|
||||
item.BardType = (uint32)atoul(row[ItemField::bardtype]);
|
||||
item.BardValue = (int32)atoul(row[ItemField::bardvalue]);
|
||||
item.Light = (int8)atoi(row[ItemField::light]);
|
||||
item.Delay = (uint8)atoi(row[ItemField::delay]);
|
||||
item.RecLevel = (uint8)atoi(row[ItemField::reclevel]);
|
||||
item.RecSkill = (uint8)atoi(row[ItemField::recskill]);
|
||||
item.ElemDmgType = (uint8)atoi(row[ItemField::elemdmgtype]);
|
||||
item.ElemDmgAmt = (uint8)atoi(row[ItemField::elemdmgamt]);
|
||||
item.Range = (uint8)atoi(row[ItemField::range]);
|
||||
item.Damage = (uint32)atoi(row[ItemField::damage]);
|
||||
item.Color = (uint32)atoul(row[ItemField::color]);
|
||||
item.Classes = (uint32)atoul(row[ItemField::classes]);
|
||||
item.Races = (uint32)atoul(row[ItemField::races]);
|
||||
|
||||
item.MaxCharges = (int16)atoi(row[ItemField::maxcharges]);
|
||||
item.ItemType = (uint8)atoi(row[ItemField::itemtype]);
|
||||
item.MaxCharges = (int16)atoi(row[ItemField::maxcharges]);
|
||||
item.ItemType = (uint8)atoi(row[ItemField::itemtype]);
|
||||
item.Material = (uint8)atoi(row[ItemField::material]);
|
||||
item.HerosForgeModel = (uint32)atoi(row[ItemField::herosforgemodel]);
|
||||
item.SellRate = (float)atof(row[ItemField::sellrate]);
|
||||
item.CastTime = (uint32)atoul(row[ItemField::casttime]);
|
||||
item.EliteMaterial = (uint32)atoul(row[ItemField::elitematerial]);
|
||||
item.ProcRate = (int32)atoi(row[ItemField::procrate]);
|
||||
item.CombatEffects = (int8)atoi(row[ItemField::combateffects]);
|
||||
item.Shielding = (int8)atoi(row[ItemField::shielding]);
|
||||
item.StunResist = (int8)atoi(row[ItemField::stunresist]);
|
||||
item.StrikeThrough = (int8)atoi(row[ItemField::strikethrough]);
|
||||
item.ExtraDmgSkill = (uint32)atoul(row[ItemField::extradmgskill]);
|
||||
item.ExtraDmgAmt = (uint32)atoul(row[ItemField::extradmgamt]);
|
||||
item.SpellShield = (int8)atoi(row[ItemField::spellshield]);
|
||||
item.Avoidance = (int8)atoi(row[ItemField::avoidance]);
|
||||
item.Accuracy = (int8)atoi(row[ItemField::accuracy]);
|
||||
item.CharmFileID = (uint32)atoul(row[ItemField::charmfileid]);
|
||||
item.FactionMod1 = (int32)atoul(row[ItemField::factionmod1]);
|
||||
item.FactionMod2 = (int32)atoul(row[ItemField::factionmod2]);
|
||||
item.FactionMod3 = (int32)atoul(row[ItemField::factionmod3]);
|
||||
item.FactionMod4 = (int32)atoul(row[ItemField::factionmod4]);
|
||||
item.FactionAmt1 = (int32)atoul(row[ItemField::factionamt1]);
|
||||
item.FactionAmt2 = (int32)atoul(row[ItemField::factionamt2]);
|
||||
item.FactionAmt3 = (int32)atoul(row[ItemField::factionamt3]);
|
||||
item.FactionAmt4 = (int32)atoul(row[ItemField::factionamt4]);
|
||||
item.SellRate = (float)atof(row[ItemField::sellrate]);
|
||||
item.CastTime = (uint32)atoul(row[ItemField::casttime]);
|
||||
item.EliteMaterial = (uint32)atoul(row[ItemField::elitematerial]);
|
||||
item.ProcRate = (int32)atoi(row[ItemField::procrate]);
|
||||
item.CombatEffects = (int8)atoi(row[ItemField::combateffects]);
|
||||
item.Shielding = (int8)atoi(row[ItemField::shielding]);
|
||||
item.StunResist = (int8)atoi(row[ItemField::stunresist]);
|
||||
item.StrikeThrough = (int8)atoi(row[ItemField::strikethrough]);
|
||||
item.ExtraDmgSkill = (uint32)atoul(row[ItemField::extradmgskill]);
|
||||
item.ExtraDmgAmt = (uint32)atoul(row[ItemField::extradmgamt]);
|
||||
item.SpellShield = (int8)atoi(row[ItemField::spellshield]);
|
||||
item.Avoidance = (int8)atoi(row[ItemField::avoidance]);
|
||||
item.Accuracy = (int8)atoi(row[ItemField::accuracy]);
|
||||
item.CharmFileID = (uint32)atoul(row[ItemField::charmfileid]);
|
||||
item.FactionMod1 = (int32)atoul(row[ItemField::factionmod1]);
|
||||
item.FactionMod2 = (int32)atoul(row[ItemField::factionmod2]);
|
||||
item.FactionMod3 = (int32)atoul(row[ItemField::factionmod3]);
|
||||
item.FactionMod4 = (int32)atoul(row[ItemField::factionmod4]);
|
||||
item.FactionAmt1 = (int32)atoul(row[ItemField::factionamt1]);
|
||||
item.FactionAmt2 = (int32)atoul(row[ItemField::factionamt2]);
|
||||
item.FactionAmt3 = (int32)atoul(row[ItemField::factionamt3]);
|
||||
item.FactionAmt4 = (int32)atoul(row[ItemField::factionamt4]);
|
||||
|
||||
strcpy(item.CharmFile,row[ItemField::charmfile]);
|
||||
strcpy(item.CharmFile, row[ItemField::charmfile]);
|
||||
|
||||
item.AugType = (uint32)atoul(row[ItemField::augtype]);
|
||||
item.AugSlotType[0] = (uint8)atoi(row[ItemField::augslot1type]);
|
||||
item.AugSlotVisible[0] = (uint8)atoi(row[ItemField::augslot1visible]);
|
||||
item.AugSlotUnk2[0] = 0;
|
||||
item.AugSlotType[1] = (uint8)atoi(row[ItemField::augslot2type]);
|
||||
item.AugSlotVisible[1] = (uint8)atoi(row[ItemField::augslot2visible]);
|
||||
item.AugSlotUnk2[1] = 0;
|
||||
item.AugSlotType[2] = (uint8)atoi(row[ItemField::augslot3type]);
|
||||
item.AugSlotVisible[2] = (uint8)atoi(row[ItemField::augslot3visible]);
|
||||
item.AugSlotUnk2[2] = 0;
|
||||
item.AugSlotType[3] = (uint8)atoi(row[ItemField::augslot4type]);
|
||||
item.AugSlotVisible[3] = (uint8)atoi(row[ItemField::augslot4visible]);
|
||||
item.AugSlotUnk2[3] = 0;
|
||||
item.AugSlotType[4] = (uint8)atoi(row[ItemField::augslot5type]);
|
||||
item.AugSlotVisible[4] = (uint8)atoi(row[ItemField::augslot5visible]);
|
||||
item.AugSlotUnk2[4] = 0;
|
||||
item.AugType = (uint32)atoul(row[ItemField::augtype]);
|
||||
item.AugSlotType[0] = (uint8)atoi(row[ItemField::augslot1type]);
|
||||
item.AugSlotVisible[0] = (uint8)atoi(row[ItemField::augslot1visible]);
|
||||
item.AugSlotUnk2[0] = 0;
|
||||
item.AugSlotType[1] = (uint8)atoi(row[ItemField::augslot2type]);
|
||||
item.AugSlotVisible[1] = (uint8)atoi(row[ItemField::augslot2visible]);
|
||||
item.AugSlotUnk2[1] = 0;
|
||||
item.AugSlotType[2] = (uint8)atoi(row[ItemField::augslot3type]);
|
||||
item.AugSlotVisible[2] = (uint8)atoi(row[ItemField::augslot3visible]);
|
||||
item.AugSlotUnk2[2] = 0;
|
||||
item.AugSlotType[3] = (uint8)atoi(row[ItemField::augslot4type]);
|
||||
item.AugSlotVisible[3] = (uint8)atoi(row[ItemField::augslot4visible]);
|
||||
item.AugSlotUnk2[3] = 0;
|
||||
item.AugSlotType[4] = (uint8)atoi(row[ItemField::augslot5type]);
|
||||
item.AugSlotVisible[4] = (uint8)atoi(row[ItemField::augslot5visible]);
|
||||
item.AugSlotUnk2[4] = 0;
|
||||
item.AugSlotType[5] = (uint8)atoi(row[ItemField::augslot6type]);
|
||||
item.AugSlotVisible[5] = (uint8)atoi(row[ItemField::augslot6visible]);
|
||||
item.AugSlotUnk2[5] = 0;
|
||||
|
||||
item.LDoNTheme = (uint32)atoul(row[ItemField::ldontheme]);
|
||||
item.LDoNPrice = (uint32)atoul(row[ItemField::ldonprice]);
|
||||
item.LDoNSold = (uint32)atoul(row[ItemField::ldonsold]);
|
||||
item.BagType = (uint8)atoi(row[ItemField::bagtype]);
|
||||
item.BagSlots = (uint8)atoi(row[ItemField::bagslots]);
|
||||
item.BagSize = (uint8)atoi(row[ItemField::bagsize]);
|
||||
item.BagWR = (uint8)atoi(row[ItemField::bagwr]);
|
||||
item.Book = (uint8)atoi(row[ItemField::book]);
|
||||
item.BookType = (uint32)atoul(row[ItemField::booktype]);
|
||||
item.LDoNTheme = (uint32)atoul(row[ItemField::ldontheme]);
|
||||
item.LDoNPrice = (uint32)atoul(row[ItemField::ldonprice]);
|
||||
item.LDoNSold = (uint32)atoul(row[ItemField::ldonsold]);
|
||||
item.BagType = (uint8)atoi(row[ItemField::bagtype]);
|
||||
item.BagSlots = (uint8)std::min(atoi(row[ItemField::bagslots]), 10); // FIXME: remove when big bags supported
|
||||
item.BagSize = (uint8)atoi(row[ItemField::bagsize]);
|
||||
item.BagWR = (uint8)atoi(row[ItemField::bagwr]);
|
||||
item.Book = (uint8)atoi(row[ItemField::book]);
|
||||
item.BookType = (uint32)atoul(row[ItemField::booktype]);
|
||||
|
||||
strcpy(item.Filename,row[ItemField::filename]);
|
||||
strcpy(item.Filename, row[ItemField::filename]);
|
||||
|
||||
item.BaneDmgRaceAmt = (uint32)atoul(row[ItemField::banedmgraceamt]);
|
||||
item.AugRestrict = (uint32)atoul(row[ItemField::augrestrict]);
|
||||
item.LoreGroup = disableLoreGroup ? (uint8)atoi("0") : atoi(row[ItemField::loregroup]);
|
||||
item.LoreFlag = item.LoreGroup!=0;
|
||||
item.PendingLoreFlag = (atoi(row[ItemField::pendingloreflag])==0) ? false : true;
|
||||
item.ArtifactFlag = (atoi(row[ItemField::artifactflag])==0) ? false : true;
|
||||
item.SummonedFlag = (atoi(row[ItemField::summonedflag])==0) ? false : true;
|
||||
item.Favor = (uint32)atoul(row[ItemField::favor]);
|
||||
item.FVNoDrop = (atoi(row[ItemField::fvnodrop])==0) ? false : true;
|
||||
item.Endur = (uint32)atoul(row[ItemField::endur]);
|
||||
item.DotShielding = (uint32)atoul(row[ItemField::dotshielding]);
|
||||
item.Attack = (uint32)atoul(row[ItemField::attack]);
|
||||
item.Regen = (uint32)atoul(row[ItemField::regen]);
|
||||
item.ManaRegen = (uint32)atoul(row[ItemField::manaregen]);
|
||||
item.EnduranceRegen = (uint32)atoul(row[ItemField::enduranceregen]);
|
||||
item.Haste = (uint32)atoul(row[ItemField::haste]);
|
||||
item.DamageShield = (uint32)atoul(row[ItemField::damageshield]);
|
||||
item.RecastDelay = (uint32)atoul(row[ItemField::recastdelay]);
|
||||
item.RecastType = (uint32)atoul(row[ItemField::recasttype]);
|
||||
item.GuildFavor = (uint32)atoul(row[ItemField::guildfavor]);
|
||||
item.AugDistiller = (uint32)atoul(row[ItemField::augdistiller]);
|
||||
item.Attuneable = (atoi(row[ItemField::attuneable])==0) ? false : true;
|
||||
item.NoPet = (atoi(row[ItemField::nopet])==0) ? false : true;
|
||||
item.PointType = (uint32)atoul(row[ItemField::pointtype]);
|
||||
item.PotionBelt = (atoi(row[ItemField::potionbelt])==0) ? false : true;
|
||||
item.PotionBeltSlots = (atoi(row[ItemField::potionbeltslots])==0) ? false : true;
|
||||
item.StackSize = (uint16)atoi(row[ItemField::stacksize]);
|
||||
item.NoTransfer = disableNoTransfer ? false : (atoi(row[ItemField::notransfer])==0) ? false : true;
|
||||
item.Stackable = (atoi(row[ItemField::stackable])==0) ? false : true;
|
||||
item.Click.Effect = (uint32)atoul(row[ItemField::clickeffect]);
|
||||
item.Click.Type = (uint8)atoul(row[ItemField::clicktype]);
|
||||
item.Click.Level = (uint8)atoul(row[ItemField::clicklevel]);
|
||||
item.Click.Level2 = (uint8)atoul(row[ItemField::clicklevel2]);
|
||||
item.BaneDmgRaceAmt = (uint32)atoul(row[ItemField::banedmgraceamt]);
|
||||
item.AugRestrict = (uint32)atoul(row[ItemField::augrestrict]);
|
||||
item.LoreGroup = disableLoreGroup ? (uint8)atoi("0") : atoi(row[ItemField::loregroup]);
|
||||
item.LoreFlag = item.LoreGroup != 0;
|
||||
item.PendingLoreFlag = (atoi(row[ItemField::pendingloreflag]) == 0) ? false : true;
|
||||
item.ArtifactFlag = (atoi(row[ItemField::artifactflag]) == 0) ? false : true;
|
||||
item.SummonedFlag = (atoi(row[ItemField::summonedflag]) == 0) ? false : true;
|
||||
item.Favor = (uint32)atoul(row[ItemField::favor]);
|
||||
item.FVNoDrop = (atoi(row[ItemField::fvnodrop]) == 0) ? false : true;
|
||||
item.Endur = (uint32)atoul(row[ItemField::endur]);
|
||||
item.DotShielding = (uint32)atoul(row[ItemField::dotshielding]);
|
||||
item.Attack = (uint32)atoul(row[ItemField::attack]);
|
||||
item.Regen = (uint32)atoul(row[ItemField::regen]);
|
||||
item.ManaRegen = (uint32)atoul(row[ItemField::manaregen]);
|
||||
item.EnduranceRegen = (uint32)atoul(row[ItemField::enduranceregen]);
|
||||
item.Haste = (uint32)atoul(row[ItemField::haste]);
|
||||
item.DamageShield = (uint32)atoul(row[ItemField::damageshield]);
|
||||
item.RecastDelay = (uint32)atoul(row[ItemField::recastdelay]);
|
||||
item.RecastType = (uint32)atoul(row[ItemField::recasttype]);
|
||||
item.GuildFavor = (uint32)atoul(row[ItemField::guildfavor]);
|
||||
item.AugDistiller = (uint32)atoul(row[ItemField::augdistiller]);
|
||||
item.Attuneable = (atoi(row[ItemField::attuneable]) == 0) ? false : true;
|
||||
item.NoPet = (atoi(row[ItemField::nopet]) == 0) ? false : true;
|
||||
item.PointType = (uint32)atoul(row[ItemField::pointtype]);
|
||||
item.PotionBelt = (atoi(row[ItemField::potionbelt]) == 0) ? false : true;
|
||||
item.PotionBeltSlots = (atoi(row[ItemField::potionbeltslots]) == 0) ? false : true;
|
||||
item.StackSize = (uint16)atoi(row[ItemField::stacksize]);
|
||||
item.NoTransfer = disableNoTransfer ? false : (atoi(row[ItemField::notransfer]) == 0) ? false : true;
|
||||
item.Stackable = (atoi(row[ItemField::stackable]) == 0) ? false : true;
|
||||
item.Click.Effect = (uint32)atoul(row[ItemField::clickeffect]);
|
||||
item.Click.Type = (uint8)atoul(row[ItemField::clicktype]);
|
||||
item.Click.Level = (uint8)atoul(row[ItemField::clicklevel]);
|
||||
item.Click.Level2 = (uint8)atoul(row[ItemField::clicklevel2]);
|
||||
|
||||
strcpy(item.CharmFile,row[ItemField::charmfile]);
|
||||
strcpy(item.CharmFile, row[ItemField::charmfile]);
|
||||
|
||||
item.Proc.Effect = (uint16)atoul(row[ItemField::proceffect]);
|
||||
item.Proc.Type = (uint8)atoul(row[ItemField::proctype]);
|
||||
item.Proc.Level = (uint8)atoul(row[ItemField::proclevel]);
|
||||
item.Proc.Level2 = (uint8)atoul(row[ItemField::proclevel2]);
|
||||
item.Worn.Effect = (uint16)atoul(row[ItemField::worneffect]);
|
||||
item.Worn.Type = (uint8)atoul(row[ItemField::worntype]);
|
||||
item.Worn.Level = (uint8)atoul(row[ItemField::wornlevel]);
|
||||
item.Worn.Level2 = (uint8)atoul(row[ItemField::wornlevel2]);
|
||||
item.Focus.Effect = (uint16)atoul(row[ItemField::focuseffect]);
|
||||
item.Focus.Type = (uint8)atoul(row[ItemField::focustype]);
|
||||
item.Focus.Level = (uint8)atoul(row[ItemField::focuslevel]);
|
||||
item.Focus.Level2 = (uint8)atoul(row[ItemField::focuslevel2]);
|
||||
item.Scroll.Effect = (uint16)atoul(row[ItemField::scrolleffect]);
|
||||
item.Scroll.Type = (uint8)atoul(row[ItemField::scrolltype]);
|
||||
item.Scroll.Level = (uint8)atoul(row[ItemField::scrolllevel]);
|
||||
item.Scroll.Level2 = (uint8)atoul(row[ItemField::scrolllevel2]);
|
||||
item.Bard.Effect = (uint16)atoul(row[ItemField::bardeffect]);
|
||||
item.Bard.Type = (uint8)atoul(row[ItemField::bardtype]);
|
||||
item.Bard.Level = (uint8)atoul(row[ItemField::bardlevel]);
|
||||
item.Bard.Level2 = (uint8)atoul(row[ItemField::bardlevel2]);
|
||||
item.QuestItemFlag = (atoi(row[ItemField::questitemflag])==0) ? false : true;
|
||||
item.SVCorruption = (int32)atoi(row[ItemField::svcorruption]);
|
||||
item.Purity = (uint32)atoul(row[ItemField::purity]);
|
||||
item.EvolvingLevel = (uint8)atoul(row[ItemField::evolvinglevel]);
|
||||
item.BackstabDmg = (uint32)atoul(row[ItemField::backstabdmg]);
|
||||
item.DSMitigation = (uint32)atoul(row[ItemField::dsmitigation]);
|
||||
item.HeroicStr = (int32)atoi(row[ItemField::heroic_str]);
|
||||
item.HeroicInt = (int32)atoi(row[ItemField::heroic_int]);
|
||||
item.HeroicWis = (int32)atoi(row[ItemField::heroic_wis]);
|
||||
item.HeroicAgi = (int32)atoi(row[ItemField::heroic_agi]);
|
||||
item.HeroicDex = (int32)atoi(row[ItemField::heroic_dex]);
|
||||
item.HeroicSta = (int32)atoi(row[ItemField::heroic_sta]);
|
||||
item.HeroicCha = (int32)atoi(row[ItemField::heroic_cha]);
|
||||
item.HeroicMR = (int32)atoi(row[ItemField::heroic_mr]);
|
||||
item.HeroicFR = (int32)atoi(row[ItemField::heroic_fr]);
|
||||
item.HeroicCR = (int32)atoi(row[ItemField::heroic_cr]);
|
||||
item.HeroicDR = (int32)atoi(row[ItemField::heroic_dr]);
|
||||
item.HeroicPR = (int32)atoi(row[ItemField::heroic_pr]);
|
||||
item.HeroicSVCorrup = (int32)atoi(row[ItemField::heroic_svcorrup]);
|
||||
item.HealAmt = (int32)atoi(row[ItemField::healamt]);
|
||||
item.SpellDmg = (int32)atoi(row[ItemField::spelldmg]);
|
||||
item.LDoNSellBackRate = (uint32)atoul(row[ItemField::ldonsellbackrate]);
|
||||
item.ScriptFileID = (uint32)atoul(row[ItemField::scriptfileid]);
|
||||
item.ExpendableArrow = (uint16)atoul(row[ItemField::expendablearrow]);
|
||||
item.Clairvoyance = (uint32)atoul(row[ItemField::clairvoyance]);
|
||||
item.Proc.Effect = (int32)atoul(row[ItemField::proceffect]);
|
||||
item.Proc.Type = (uint8)atoul(row[ItemField::proctype]);
|
||||
item.Proc.Level = (uint8)atoul(row[ItemField::proclevel]);
|
||||
item.Proc.Level2 = (uint8)atoul(row[ItemField::proclevel2]);
|
||||
item.Worn.Effect = (int32)atoul(row[ItemField::worneffect]);
|
||||
item.Worn.Type = (uint8)atoul(row[ItemField::worntype]);
|
||||
item.Worn.Level = (uint8)atoul(row[ItemField::wornlevel]);
|
||||
item.Worn.Level2 = (uint8)atoul(row[ItemField::wornlevel2]);
|
||||
item.Focus.Effect = (int32)atoul(row[ItemField::focuseffect]);
|
||||
item.Focus.Type = (uint8)atoul(row[ItemField::focustype]);
|
||||
item.Focus.Level = (uint8)atoul(row[ItemField::focuslevel]);
|
||||
item.Focus.Level2 = (uint8)atoul(row[ItemField::focuslevel2]);
|
||||
item.Scroll.Effect = (int32)atoul(row[ItemField::scrolleffect]);
|
||||
item.Scroll.Type = (uint8)atoul(row[ItemField::scrolltype]);
|
||||
item.Scroll.Level = (uint8)atoul(row[ItemField::scrolllevel]);
|
||||
item.Scroll.Level2 = (uint8)atoul(row[ItemField::scrolllevel2]);
|
||||
item.Bard.Effect = (int32)atoul(row[ItemField::bardeffect]);
|
||||
item.Bard.Type = (uint8)atoul(row[ItemField::bardtype]);
|
||||
item.Bard.Level = (uint8)atoul(row[ItemField::bardlevel]);
|
||||
item.Bard.Level2 = (uint8)atoul(row[ItemField::bardlevel2]);
|
||||
item.QuestItemFlag = (atoi(row[ItemField::questitemflag]) == 0) ? false : true;
|
||||
item.SVCorruption = (int32)atoi(row[ItemField::svcorruption]);
|
||||
item.Purity = (uint32)atoul(row[ItemField::purity]);
|
||||
item.EvolvingItem = (uint8)atoul(row[ItemField::evoitem]);
|
||||
item.EvolvingID = (uint8)atoul(row[ItemField::evoid]);
|
||||
item.EvolvingLevel = (uint8)atoul(row[ItemField::evolvinglevel]);
|
||||
item.EvolvingMax = (uint8)atoul(row[ItemField::evomax]);
|
||||
item.BackstabDmg = (uint32)atoul(row[ItemField::backstabdmg]);
|
||||
item.DSMitigation = (uint32)atoul(row[ItemField::dsmitigation]);
|
||||
item.HeroicStr = (int32)atoi(row[ItemField::heroic_str]);
|
||||
item.HeroicInt = (int32)atoi(row[ItemField::heroic_int]);
|
||||
item.HeroicWis = (int32)atoi(row[ItemField::heroic_wis]);
|
||||
item.HeroicAgi = (int32)atoi(row[ItemField::heroic_agi]);
|
||||
item.HeroicDex = (int32)atoi(row[ItemField::heroic_dex]);
|
||||
item.HeroicSta = (int32)atoi(row[ItemField::heroic_sta]);
|
||||
item.HeroicCha = (int32)atoi(row[ItemField::heroic_cha]);
|
||||
item.HeroicMR = (int32)atoi(row[ItemField::heroic_mr]);
|
||||
item.HeroicFR = (int32)atoi(row[ItemField::heroic_fr]);
|
||||
item.HeroicCR = (int32)atoi(row[ItemField::heroic_cr]);
|
||||
item.HeroicDR = (int32)atoi(row[ItemField::heroic_dr]);
|
||||
item.HeroicPR = (int32)atoi(row[ItemField::heroic_pr]);
|
||||
item.HeroicSVCorrup = (int32)atoi(row[ItemField::heroic_svcorrup]);
|
||||
item.HealAmt = (int32)atoi(row[ItemField::healamt]);
|
||||
item.SpellDmg = (int32)atoi(row[ItemField::spelldmg]);
|
||||
item.LDoNSellBackRate = (uint32)atoul(row[ItemField::ldonsellbackrate]);
|
||||
item.ScriptFileID = (uint32)atoul(row[ItemField::scriptfileid]);
|
||||
item.ExpendableArrow = (uint16)atoul(row[ItemField::expendablearrow]);
|
||||
item.Clairvoyance = (uint32)atoul(row[ItemField::clairvoyance]);
|
||||
|
||||
strcpy(item.ClickName,row[ItemField::clickname]);
|
||||
strcpy(item.ProcName,row[ItemField::procname]);
|
||||
strcpy(item.WornName,row[ItemField::wornname]);
|
||||
strcpy(item.FocusName,row[ItemField::focusname]);
|
||||
strcpy(item.ScrollName,row[ItemField::scrollname]);
|
||||
|
||||
try {
|
||||
hash.insert(item.ID, item);
|
||||
} catch(std::exception &ex) {
|
||||
Log.Out(Logs::General, Logs::Error, "Database::LoadItems: %s", ex.what());
|
||||
break;
|
||||
}
|
||||
}
|
||||
strcpy(item.ClickName, row[ItemField::clickname]);
|
||||
strcpy(item.ProcName, row[ItemField::procname]);
|
||||
strcpy(item.WornName, row[ItemField::wornname]);
|
||||
strcpy(item.FocusName, row[ItemField::focusname]);
|
||||
strcpy(item.ScrollName, row[ItemField::scrollname]);
|
||||
|
||||
try {
|
||||
hash.insert(item.ID, item);
|
||||
} catch (std::exception &ex) {
|
||||
Log.Out(Logs::General, Logs::Error, "Database::LoadItems: %s", ex.what());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Item_Struct* SharedDatabase::GetItem(uint32 id) {
|
||||
@@ -1158,7 +1146,7 @@ void SharedDatabase::GetFactionListInfo(uint32 &list_count, uint32 &max_lists) {
|
||||
auto row = results.begin();
|
||||
|
||||
list_count = static_cast<uint32>(atoul(row[0]));
|
||||
max_lists = static_cast<uint32>(atoul(row[1]));
|
||||
max_lists = static_cast<uint32>(atoul(row[1] ? row[1] : "0"));
|
||||
}
|
||||
|
||||
const NPCFactionList* SharedDatabase::GetNPCFactionEntry(uint32 id) {
|
||||
@@ -1222,30 +1210,16 @@ void SharedDatabase::LoadNPCFactionLists(void *data, uint32 size, uint32 list_co
|
||||
|
||||
}
|
||||
|
||||
bool SharedDatabase::LoadNPCFactionLists() {
|
||||
if(faction_hash) {
|
||||
return true;
|
||||
}
|
||||
bool SharedDatabase::LoadNPCFactionLists(const std::string &prefix) {
|
||||
faction_mmf.reset(nullptr);
|
||||
faction_hash.reset(nullptr);
|
||||
|
||||
try {
|
||||
EQEmu::IPCMutex mutex("faction");
|
||||
mutex.Lock();
|
||||
faction_mmf = new EQEmu::MemoryMappedFile("shared/faction");
|
||||
|
||||
uint32 list_count = 0;
|
||||
uint32 max_lists = 0;
|
||||
GetFactionListInfo(list_count, max_lists);
|
||||
if(list_count == 0) {
|
||||
EQ_EXCEPT("SharedDatabase", "Database returned no result");
|
||||
}
|
||||
uint32 size = static_cast<uint32>(EQEmu::FixedMemoryHashSet<NPCFactionList>::estimated_size(
|
||||
list_count, max_lists));
|
||||
|
||||
if(faction_mmf->Size() != size) {
|
||||
EQ_EXCEPT("SharedDatabase", "Couldn't load npc factions because faction_mmf->Size() != size");
|
||||
}
|
||||
|
||||
faction_hash = new EQEmu::FixedMemoryHashSet<NPCFactionList>(reinterpret_cast<uint8*>(faction_mmf->Get()), size);
|
||||
std::string file_name = std::string("shared/") + prefix + std::string("faction");
|
||||
faction_mmf = std::unique_ptr<EQEmu::MemoryMappedFile>(new EQEmu::MemoryMappedFile(file_name));
|
||||
faction_hash = std::unique_ptr<EQEmu::FixedMemoryHashSet<NPCFactionList>>(new EQEmu::FixedMemoryHashSet<NPCFactionList>(reinterpret_cast<uint8*>(faction_mmf->Get()), faction_mmf->Size()));
|
||||
mutex.Unlock();
|
||||
} catch(std::exception& ex) {
|
||||
Log.Out(Logs::General, Logs::Error, "Error Loading npc factions: %s", ex.what());
|
||||
@@ -1358,25 +1332,33 @@ int32 SharedDatabase::DeleteStalePlayerCorpses() {
|
||||
return results.RowsAffected();
|
||||
}
|
||||
|
||||
bool SharedDatabase::GetCommandSettings(std::map<std::string,uint8> &commands) {
|
||||
bool SharedDatabase::GetCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &command_settings)
|
||||
{
|
||||
command_settings.clear();
|
||||
|
||||
const std::string query = "SELECT command, access FROM commands";
|
||||
std::string query = "SELECT `command`, `access`, `aliases` FROM `command_settings`";
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
if (!results.Success())
|
||||
return false;
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
command_settings[row[0]].first = atoi(row[1]);
|
||||
if (row[2][0] == 0)
|
||||
continue;
|
||||
|
||||
std::vector<std::string> aliases = SplitString(row[2], '|');
|
||||
for (std::vector<std::string>::iterator iter = aliases.begin(); iter != aliases.end(); ++iter) {
|
||||
if (iter->empty())
|
||||
continue;
|
||||
command_settings[row[0]].second.push_back(*iter);
|
||||
}
|
||||
}
|
||||
|
||||
commands.clear();
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
commands[row[0]]=atoi(row[1]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharedDatabase::LoadSkillCaps() {
|
||||
if(skill_caps_mmf)
|
||||
return true;
|
||||
bool SharedDatabase::LoadSkillCaps(const std::string &prefix) {
|
||||
skill_caps_mmf.reset(nullptr);
|
||||
|
||||
uint32 class_count = PLAYER_CLASS_COUNT;
|
||||
uint32 skill_count = HIGHEST_SKILL + 1;
|
||||
@@ -1386,11 +1368,8 @@ bool SharedDatabase::LoadSkillCaps() {
|
||||
try {
|
||||
EQEmu::IPCMutex mutex("skill_caps");
|
||||
mutex.Lock();
|
||||
skill_caps_mmf = new EQEmu::MemoryMappedFile("shared/skill_caps");
|
||||
if(skill_caps_mmf->Size() != size) {
|
||||
EQ_EXCEPT("SharedDatabase", "Unable to load skill caps: skill_caps_mmf->Size() != size");
|
||||
}
|
||||
|
||||
std::string file_name = std::string("shared/") + prefix + std::string("skill_caps");
|
||||
skill_caps_mmf = std::unique_ptr<EQEmu::MemoryMappedFile>(new EQEmu::MemoryMappedFile(file_name));
|
||||
mutex.Unlock();
|
||||
} catch(std::exception &ex) {
|
||||
Log.Out(Logs::General, Logs::Error, "Error loading skill caps: %s", ex.what());
|
||||
@@ -1538,8 +1517,29 @@ int SharedDatabase::GetMaxSpellID() {
|
||||
return atoi(row[0]);
|
||||
}
|
||||
|
||||
bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp) {
|
||||
spells_mmf.reset(nullptr);
|
||||
|
||||
try {
|
||||
EQEmu::IPCMutex mutex("spells");
|
||||
mutex.Lock();
|
||||
|
||||
std::string file_name = std::string("shared/") + prefix + std::string("spells");
|
||||
spells_mmf = std::unique_ptr<EQEmu::MemoryMappedFile>(new EQEmu::MemoryMappedFile(file_name));
|
||||
*records = *reinterpret_cast<uint32*>(spells_mmf->Get());
|
||||
*sp = reinterpret_cast<const SPDat_Spell_Struct*>((char*)spells_mmf->Get() + 4);
|
||||
mutex.Unlock();
|
||||
}
|
||||
catch(std::exception& ex) {
|
||||
Log.Out(Logs::General, Logs::Error, "Error Loading Spells: %s", ex.what());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SharedDatabase::LoadSpells(void *data, int max_spells) {
|
||||
SPDat_Spell_Struct *sp = reinterpret_cast<SPDat_Spell_Struct*>(data);
|
||||
*(uint32*)data = max_spells;
|
||||
SPDat_Spell_Struct *sp = reinterpret_cast<SPDat_Spell_Struct*>((char*)data + sizeof(uint32));
|
||||
|
||||
const std::string query = "SELECT * FROM spells_new ORDER BY id ASC";
|
||||
auto results = QueryDatabase(query);
|
||||
@@ -1675,25 +1675,29 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) {
|
||||
sp[tempid].directional_start = static_cast<float>(atoi(row[194]));
|
||||
sp[tempid].directional_end = static_cast<float>(atoi(row[195]));
|
||||
sp[tempid].sneak = atoi(row[196]) != 0;
|
||||
sp[tempid].not_extendable = atoi(row[197]) != 0;
|
||||
sp[tempid].not_focusable = atoi(row[197]) != 0;
|
||||
sp[tempid].no_detrimental_spell_aggro = atoi(row[198]) != 0;
|
||||
sp[tempid].suspendable = atoi(row[200]) != 0;
|
||||
sp[tempid].viral_range = atoi(row[201]);
|
||||
sp[tempid].songcap = atoi(row[202]);
|
||||
sp[tempid].no_block = atoi(row[205]);
|
||||
sp[tempid].spellgroup=atoi(row[207]);
|
||||
sp[tempid].rank = atoi(row[208]);
|
||||
sp[tempid].powerful_flag=atoi(row[209]);
|
||||
sp[tempid].no_resist=atoi(row[209]);
|
||||
sp[tempid].CastRestriction = atoi(row[211]);
|
||||
sp[tempid].AllowRest = atoi(row[212]) != 0;
|
||||
sp[tempid].InCombat = atoi(row[213]) != 0;
|
||||
sp[tempid].OutofCombat = atoi(row[214]) != 0;
|
||||
sp[tempid].override_crit_chance = atoi(row[217]);
|
||||
sp[tempid].aemaxtargets = atoi(row[218]);
|
||||
sp[tempid].maxtargets = atoi(row[219]);
|
||||
sp[tempid].no_heal_damage_item_mod = atoi(row[219]);
|
||||
sp[tempid].persistdeath = atoi(row[224]) != 0;
|
||||
sp[tempid].min_dist = atof(row[227]);
|
||||
sp[tempid].min_dist_mod = atof(row[228]);
|
||||
sp[tempid].max_dist = atof(row[229]);
|
||||
sp[tempid].max_dist_mod = atof(row[230]);
|
||||
sp[tempid].min_range = static_cast<float>(atoi(row[231]));
|
||||
sp[tempid].no_remove = atoi(row[232]) != 0;
|
||||
sp[tempid].DamageShieldType = 0;
|
||||
}
|
||||
|
||||
@@ -1715,25 +1719,15 @@ int SharedDatabase::GetMaxBaseDataLevel() {
|
||||
return atoi(row[0]);
|
||||
}
|
||||
|
||||
bool SharedDatabase::LoadBaseData() {
|
||||
if(base_data_mmf) {
|
||||
return true;
|
||||
}
|
||||
bool SharedDatabase::LoadBaseData(const std::string &prefix) {
|
||||
base_data_mmf.reset(nullptr);
|
||||
|
||||
try {
|
||||
EQEmu::IPCMutex mutex("base_data");
|
||||
mutex.Lock();
|
||||
base_data_mmf = new EQEmu::MemoryMappedFile("shared/base_data");
|
||||
|
||||
int size = 16 * (GetMaxBaseDataLevel() + 1) * sizeof(BaseDataStruct);
|
||||
if(size == 0) {
|
||||
EQ_EXCEPT("SharedDatabase", "Base Data size is zero");
|
||||
}
|
||||
|
||||
if(base_data_mmf->Size() != size) {
|
||||
EQ_EXCEPT("SharedDatabase", "Couldn't load base data because base_data_mmf->Size() != size");
|
||||
}
|
||||
|
||||
std::string file_name = std::string("shared/") + prefix + std::string("base_data");
|
||||
base_data_mmf = std::unique_ptr<EQEmu::MemoryMappedFile>(new EQEmu::MemoryMappedFile(file_name));
|
||||
mutex.Unlock();
|
||||
} catch(std::exception& ex) {
|
||||
Log.Out(Logs::General, Logs::Error, "Error Loading Base Data: %s", ex.what());
|
||||
@@ -1789,7 +1783,6 @@ void SharedDatabase::LoadBaseData(void *data, int max_level) {
|
||||
bd->mana_factor = atof(row[8]);
|
||||
bd->endurance_factor = atof(row[9]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const BaseDataStruct* SharedDatabase::GetBaseData(int lvl, int cl) {
|
||||
@@ -1837,7 +1830,7 @@ void SharedDatabase::GetLootTableInfo(uint32 &loot_table_count, uint32 &max_loot
|
||||
auto row = results.begin();
|
||||
|
||||
loot_table_count = static_cast<uint32>(atoul(row[0]));
|
||||
max_loot_table = static_cast<uint32>(atoul(row[1]));
|
||||
max_loot_table = static_cast<uint32>(atoul(row[1] ? row[1] : "0"));
|
||||
loot_table_entries = static_cast<uint32>(atoul(row[2]));
|
||||
}
|
||||
|
||||
@@ -1858,7 +1851,7 @@ void SharedDatabase::GetLootDropInfo(uint32 &loot_drop_count, uint32 &max_loot_d
|
||||
auto row =results.begin();
|
||||
|
||||
loot_drop_count = static_cast<uint32>(atoul(row[0]));
|
||||
max_loot_drop = static_cast<uint32>(atoul(row[1]));
|
||||
max_loot_drop = static_cast<uint32>(atoul(row[1] ? row[1] : "0"));
|
||||
loot_drop_entries = static_cast<uint32>(atoul(row[2]));
|
||||
}
|
||||
|
||||
@@ -1927,6 +1920,7 @@ void SharedDatabase::LoadLootDrops(void *data, uint32 size) {
|
||||
"ON lootdrop.id = lootdrop_entries.lootdrop_id ORDER BY lootdrop_id";
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 current_id = 0;
|
||||
@@ -1963,21 +1957,23 @@ void SharedDatabase::LoadLootDrops(void *data, uint32 size) {
|
||||
|
||||
}
|
||||
|
||||
bool SharedDatabase::LoadLoot() {
|
||||
if(loot_table_mmf || loot_drop_mmf)
|
||||
return true;
|
||||
bool SharedDatabase::LoadLoot(const std::string &prefix) {
|
||||
loot_table_mmf.reset(nullptr);
|
||||
loot_drop_mmf.reset(nullptr);
|
||||
|
||||
try {
|
||||
EQEmu::IPCMutex mutex("loot");
|
||||
mutex.Lock();
|
||||
loot_table_mmf = new EQEmu::MemoryMappedFile("shared/loot_table");
|
||||
loot_table_hash = new EQEmu::FixedMemoryVariableHashSet<LootTable_Struct>(
|
||||
std::string file_name_lt = std::string("shared/") + prefix + std::string("loot_table");
|
||||
loot_table_mmf = std::unique_ptr<EQEmu::MemoryMappedFile>(new EQEmu::MemoryMappedFile(file_name_lt));
|
||||
loot_table_hash = std::unique_ptr<EQEmu::FixedMemoryVariableHashSet<LootTable_Struct>>(new EQEmu::FixedMemoryVariableHashSet<LootTable_Struct>(
|
||||
reinterpret_cast<uint8*>(loot_table_mmf->Get()),
|
||||
loot_table_mmf->Size());
|
||||
loot_drop_mmf = new EQEmu::MemoryMappedFile("shared/loot_drop");
|
||||
loot_drop_hash = new EQEmu::FixedMemoryVariableHashSet<LootDrop_Struct>(
|
||||
loot_table_mmf->Size()));
|
||||
std::string file_name_ld = std::string("shared/") + prefix + std::string("loot_drop");
|
||||
loot_drop_mmf = std::unique_ptr<EQEmu::MemoryMappedFile>(new EQEmu::MemoryMappedFile(file_name_ld));
|
||||
loot_drop_hash = std::unique_ptr<EQEmu::FixedMemoryVariableHashSet<LootDrop_Struct>>(new EQEmu::FixedMemoryVariableHashSet<LootDrop_Struct>(
|
||||
reinterpret_cast<uint8*>(loot_drop_mmf->Get()),
|
||||
loot_drop_mmf->Size());
|
||||
loot_drop_mmf->Size()));
|
||||
mutex.Unlock();
|
||||
} catch(std::exception &ex) {
|
||||
Log.Out(Logs::General, Logs::Error, "Error loading loot: %s", ex.what());
|
||||
@@ -2017,7 +2013,7 @@ const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) {
|
||||
|
||||
void SharedDatabase::LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message) {
|
||||
std::string query = StringFormat("SELECT `inspect_message` FROM `character_inspect_messages` WHERE `id` = %u LIMIT 1", character_id);
|
||||
auto results = QueryDatabase(query);
|
||||
auto results = QueryDatabase(query);
|
||||
auto row = results.begin();
|
||||
memset(message, '\0', sizeof(InspectMessage_Struct));
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
@@ -2027,27 +2023,24 @@ void SharedDatabase::LoadCharacterInspectMessage(uint32 character_id, InspectMes
|
||||
|
||||
void SharedDatabase::SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message) {
|
||||
std::string query = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message) VALUES (%u, '%s')", character_id, EscapeString(message->text).c_str());
|
||||
auto results = QueryDatabase(query);
|
||||
}
|
||||
|
||||
void SharedDatabase::GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message) {
|
||||
|
||||
std::string query = StringFormat("SELECT BotInspectMessage FROM bots WHERE BotID = %i", botid);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef BOTS
|
||||
void SharedDatabase::GetBotInspectMessage(uint32 bot_id, InspectMessage_Struct* message)
|
||||
{
|
||||
std::string query = StringFormat("SELECT `inspect_message` FROM `bot_inspect_messages` WHERE `bot_id` = %i LIMIT 1", bot_id);
|
||||
auto results = QueryDatabase(query);
|
||||
auto row = results.begin();
|
||||
memset(message, '\0', sizeof(InspectMessage_Struct));
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
memcpy(message, row[0], sizeof(InspectMessage_Struct));
|
||||
}
|
||||
|
||||
if (results.RowCount() != 1)
|
||||
return;
|
||||
|
||||
auto row = results.begin();
|
||||
memcpy(message, row[0], sizeof(InspectMessage_Struct));
|
||||
|
||||
}
|
||||
|
||||
void SharedDatabase::SetBotInspectMessage(uint32 botid, const InspectMessage_Struct* message) {
|
||||
std::string msg = EscapeString(message->text);
|
||||
std::string query = StringFormat("UPDATE bots SET BotInspectMessage = '%s' WHERE BotID = %i", msg.c_str(), botid);
|
||||
QueryDatabase(query);
|
||||
void SharedDatabase::SetBotInspectMessage(uint32 bot_id, const InspectMessage_Struct* message)
|
||||
{
|
||||
std::string query = StringFormat("REPLACE INTO `bot_inspect_messages` (bot_id, inspect_message) VALUES (%u, '%s')", bot_id, EscapeString(message->text).c_str());
|
||||
auto results = QueryDatabase(query);
|
||||
}
|
||||
#endif
|
||||
|
||||
+24
-18
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
class EvolveInfo;
|
||||
class Inventory;
|
||||
@@ -50,9 +51,7 @@ class SharedDatabase : public Database
|
||||
int32 DeleteStalePlayerCorpses();
|
||||
void LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message);
|
||||
void SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message);
|
||||
void GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message);
|
||||
void SetBotInspectMessage(uint32 botid, const InspectMessage_Struct* message);
|
||||
bool GetCommandSettings(std::map<std::string, uint8> &commands);
|
||||
bool GetCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &command_settings);
|
||||
uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID);
|
||||
|
||||
/*
|
||||
@@ -92,7 +91,7 @@ class SharedDatabase : public Database
|
||||
//items
|
||||
void GetItemsCount(int32 &item_count, uint32 &max_id);
|
||||
void LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id);
|
||||
bool LoadItems();
|
||||
bool LoadItems(const std::string &prefix);
|
||||
const Item_Struct* IterateItems(uint32* id);
|
||||
const Item_Struct* GetItem(uint32 id);
|
||||
const EvolveInfo* GetEvolveInfo(uint32 loregroup);
|
||||
@@ -101,43 +100,50 @@ class SharedDatabase : public Database
|
||||
void GetFactionListInfo(uint32 &list_count, uint32 &max_lists);
|
||||
const NPCFactionList* GetNPCFactionEntry(uint32 id);
|
||||
void LoadNPCFactionLists(void *data, uint32 size, uint32 list_count, uint32 max_lists);
|
||||
bool LoadNPCFactionLists();
|
||||
bool LoadNPCFactionLists(const std::string &prefix);
|
||||
|
||||
//loot
|
||||
void GetLootTableInfo(uint32 &loot_table_count, uint32 &max_loot_table, uint32 &loot_table_entries);
|
||||
void GetLootDropInfo(uint32 &loot_drop_count, uint32 &max_loot_drop, uint32 &loot_drop_entries);
|
||||
void LoadLootTables(void *data, uint32 size);
|
||||
void LoadLootDrops(void *data, uint32 size);
|
||||
bool LoadLoot();
|
||||
bool LoadLoot(const std::string &prefix);
|
||||
const LootTable_Struct* GetLootTable(uint32 loottable_id);
|
||||
const LootDrop_Struct* GetLootDrop(uint32 lootdrop_id);
|
||||
|
||||
void LoadSkillCaps(void *data);
|
||||
bool LoadSkillCaps();
|
||||
bool LoadSkillCaps(const std::string &prefix);
|
||||
uint16 GetSkillCap(uint8 Class_, SkillUseTypes Skill, uint8 Level);
|
||||
uint8 GetTrainLevel(uint8 Class_, SkillUseTypes Skill, uint8 Level);
|
||||
|
||||
int GetMaxSpellID();
|
||||
bool LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp);
|
||||
void LoadSpells(void *data, int max_spells);
|
||||
void LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID);
|
||||
|
||||
int GetMaxBaseDataLevel();
|
||||
bool LoadBaseData();
|
||||
bool LoadBaseData(const std::string &prefix);
|
||||
void LoadBaseData(void *data, int max_level);
|
||||
const BaseDataStruct* GetBaseData(int lvl, int cl);
|
||||
|
||||
#ifdef BOTS
|
||||
void GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message);
|
||||
void SetBotInspectMessage(uint32 botid, const InspectMessage_Struct* message);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
EQEmu::MemoryMappedFile *skill_caps_mmf;
|
||||
EQEmu::MemoryMappedFile *items_mmf;
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> *items_hash;
|
||||
EQEmu::MemoryMappedFile *faction_mmf;
|
||||
EQEmu::FixedMemoryHashSet<NPCFactionList> *faction_hash;
|
||||
EQEmu::MemoryMappedFile *loot_table_mmf;
|
||||
EQEmu::FixedMemoryVariableHashSet<LootTable_Struct> *loot_table_hash;
|
||||
EQEmu::MemoryMappedFile *loot_drop_mmf;
|
||||
EQEmu::FixedMemoryVariableHashSet<LootDrop_Struct> *loot_drop_hash;
|
||||
EQEmu::MemoryMappedFile *base_data_mmf;
|
||||
std::unique_ptr<EQEmu::MemoryMappedFile> skill_caps_mmf;
|
||||
std::unique_ptr<EQEmu::MemoryMappedFile> items_mmf;
|
||||
std::unique_ptr<EQEmu::FixedMemoryHashSet<Item_Struct>> items_hash;
|
||||
std::unique_ptr<EQEmu::MemoryMappedFile> faction_mmf;
|
||||
std::unique_ptr<EQEmu::FixedMemoryHashSet<NPCFactionList>> faction_hash;
|
||||
std::unique_ptr<EQEmu::MemoryMappedFile> loot_table_mmf;
|
||||
std::unique_ptr<EQEmu::FixedMemoryVariableHashSet<LootTable_Struct>> loot_table_hash;
|
||||
std::unique_ptr<EQEmu::MemoryMappedFile> loot_drop_mmf;
|
||||
std::unique_ptr<EQEmu::FixedMemoryVariableHashSet<LootDrop_Struct>> loot_drop_hash;
|
||||
std::unique_ptr<EQEmu::MemoryMappedFile> base_data_mmf;
|
||||
std::unique_ptr<EQEmu::MemoryMappedFile> spells_mmf;
|
||||
};
|
||||
|
||||
#endif /*SHAREDDB_H_*/
|
||||
|
||||
@@ -55,3 +55,54 @@ bool EQEmu::IsSpecializedSkill(SkillUseTypes skill)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
float EQEmu::GetSkillMeleePushForce(SkillUseTypes skill)
|
||||
{
|
||||
// This is the force/magnitude of the push from an attack of this skill type
|
||||
// You can find these numbers in the clients skill struct
|
||||
switch (skill) {
|
||||
case Skill1HBlunt:
|
||||
case Skill1HSlashing:
|
||||
case SkillHandtoHand:
|
||||
case SkillThrowing:
|
||||
return 0.1f;
|
||||
case Skill2HBlunt:
|
||||
case Skill2HSlashing:
|
||||
case SkillEagleStrike:
|
||||
case SkillKick:
|
||||
case SkillTigerClaw:
|
||||
//case Skill2HPiercing:
|
||||
return 0.2f;
|
||||
case SkillArchery:
|
||||
return 0.15f;
|
||||
case SkillBackstab:
|
||||
case SkillBash:
|
||||
return 0.3f;
|
||||
case SkillDragonPunch:
|
||||
case SkillRoundKick:
|
||||
return 0.25f;
|
||||
case SkillFlyingKick:
|
||||
return 0.4f;
|
||||
case Skill1HPiercing:
|
||||
case SkillFrenzy:
|
||||
return 0.05f;
|
||||
case SkillIntimidation:
|
||||
return 2.5f;
|
||||
default:
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
bool EQEmu::IsBardInstrumentSkill(SkillUseTypes skill)
|
||||
{
|
||||
switch (skill) {
|
||||
case SkillBrassInstruments:
|
||||
case SkillSinging:
|
||||
case SkillStringedInstruments:
|
||||
case SkillWindInstruments:
|
||||
case SkillPercussionInstruments:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+9
-4
@@ -108,16 +108,17 @@ enum SkillUseTypes
|
||||
/*13869*/ SkillBerserking,
|
||||
/*13902*/ SkillTaunt,
|
||||
/*05837*/ SkillFrenzy, // This appears to be the only listed one not grouped with the others
|
||||
/*00000*/ _EmuSkillCount // move to last position of active enumeration labels
|
||||
|
||||
// SoF+ specific skills
|
||||
// /*03670*/ SkillRemoveTraps,
|
||||
// /*13049*/ SkillTripleAttack,
|
||||
/*03670*/ SkillRemoveTraps,
|
||||
/*13049*/ SkillTripleAttack,
|
||||
|
||||
// RoF2+ specific skills
|
||||
// /*00789*/ Skill2HPiercing,
|
||||
// /*01216*/ SkillNone, // This needs to move down as new skills are added
|
||||
|
||||
/*00000*/ _EmuSkillCount // move to last position of active enumeration labels
|
||||
|
||||
// Skill Counts
|
||||
// /*-----*/ _SkillCount_62 = 75, // use for Ti and earlier max skill checks
|
||||
// /*-----*/ _SkillCount_SoF = 77, // use for SoF thru RoF1 max skill checks
|
||||
@@ -170,7 +171,9 @@ enum SkillUseTypes
|
||||
};
|
||||
|
||||
// temporary until it can be sorted out...
|
||||
#define HIGHEST_SKILL SkillFrenzy
|
||||
#define HIGHEST_SKILL SkillTripleAttack
|
||||
// Spell Effects use this value to determine if an effect applies to all skills.
|
||||
#define ALL_SKILLS -1
|
||||
|
||||
// server profile does not reflect this yet..so, prefixed with 'PACKET_'
|
||||
#define PACKET_SKILL_ARRAY_SIZE 100
|
||||
@@ -268,6 +271,8 @@ typedef enum {
|
||||
namespace EQEmu {
|
||||
bool IsTradeskill(SkillUseTypes skill);
|
||||
bool IsSpecializedSkill(SkillUseTypes skill);
|
||||
float GetSkillMeleePushForce(SkillUseTypes skill);
|
||||
bool IsBardInstrumentSkill(SkillUseTypes skill);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+15
-7
@@ -72,7 +72,7 @@
|
||||
|
||||
|
||||
|
||||
#include "../common/eqemu_logsys.h"
|
||||
#include "../common/eqemu_logsys.h"
|
||||
|
||||
#include "classes.h"
|
||||
#include "spdat.h"
|
||||
@@ -162,7 +162,7 @@ bool IsCureSpell(uint16 spell_id)
|
||||
bool CureEffect = false;
|
||||
|
||||
for(int i = 0; i < EFFECT_COUNT; i++){
|
||||
if (sp.effectid[i] == SE_DiseaseCounter || sp.effectid[i] == SE_PoisonCounter
|
||||
if (sp.effectid[i] == SE_DiseaseCounter || sp.effectid[i] == SE_PoisonCounter
|
||||
|| sp.effectid[i] == SE_CurseCounter || sp.effectid[i] == SE_CorruptionCounter)
|
||||
CureEffect = true;
|
||||
}
|
||||
@@ -405,7 +405,7 @@ bool IsPartialCapableSpell(uint16 spell_id)
|
||||
{
|
||||
if (spells[spell_id].no_partial_resist)
|
||||
return false;
|
||||
|
||||
|
||||
if (IsPureNukeSpell(spell_id))
|
||||
return true;
|
||||
|
||||
@@ -447,7 +447,7 @@ bool IsTGBCompatibleSpell(uint16 spell_id)
|
||||
|
||||
bool IsBardSong(uint16 spell_id)
|
||||
{
|
||||
if (IsValidSpell(spell_id) && spells[spell_id].classes[BARD - 1] < 255)
|
||||
if (IsValidSpell(spell_id) && spells[spell_id].classes[BARD - 1] < 255 && !spells[spell_id].IsDisciplineBuff)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -693,9 +693,9 @@ bool IsCombatSkill(uint16 spell_id)
|
||||
{
|
||||
if (!IsValidSpell(spell_id))
|
||||
return false;
|
||||
|
||||
|
||||
//Check if Discipline
|
||||
if ((spells[spell_id].mana == 0 && (spells[spell_id].EndurCost || spells[spell_id].EndurUpkeep)))
|
||||
if ((spells[spell_id].mana == 0 && (spells[spell_id].EndurCost || spells[spell_id].EndurUpkeep)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -1040,7 +1040,7 @@ bool IsCastonFadeDurationSpell(uint16 spell_id)
|
||||
|
||||
bool IsPowerDistModSpell(uint16 spell_id)
|
||||
{
|
||||
if (IsValidSpell(spell_id) &&
|
||||
if (IsValidSpell(spell_id) &&
|
||||
(spells[spell_id].max_dist_mod || spells[spell_id].min_dist_mod) && spells[spell_id].max_dist > spells[spell_id].min_dist)
|
||||
return true;
|
||||
|
||||
@@ -1092,6 +1092,14 @@ bool DetrimentalSpellAllowsRest(uint16 spell_id)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NoDetrimentalSpellAggro(uint16 spell_id)
|
||||
{
|
||||
if (IsValidSpell(spell_id))
|
||||
return spells[spell_id].no_detrimental_spell_aggro;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 GetNimbusEffect(uint16 spell_id)
|
||||
{
|
||||
if (IsValidSpell(spell_id))
|
||||
|
||||
+67
-48
@@ -38,6 +38,7 @@
|
||||
#define MAX_RESISTABLE_EFFECTS 12 // Number of effects that are typcially checked agianst resists.
|
||||
#define MaxLimitInclude 16 //Number(x 0.5) of focus Limiters that have inclusive checks used when calcing focus effects
|
||||
#define MAX_SKILL_PROCS 4 //Number of spells to check skill procs from. (This is arbitrary) [Single spell can have multiple proc checks]
|
||||
#define MAX_SYMPATHETIC_PROCS 10 // Number of sympathetic procs a client can have (This is arbitrary)
|
||||
|
||||
|
||||
const int Z_AGGRO=10;
|
||||
@@ -132,7 +133,7 @@ typedef enum {
|
||||
/* 42 */ ST_Directional = 0x2a, //ae around this target between two angles
|
||||
/* 43 */ ST_GroupClientAndPet = 0x2b,
|
||||
/* 44 */ ST_Beam = 0x2c,
|
||||
/* 45 */ ST_Ring = 0x2d,
|
||||
/* 45 */ ST_Ring = 0x2d,
|
||||
/* 46 */ ST_TargetsTarget = 0x2e, // uses the target of your target
|
||||
/* 47 */ ST_PetMaster = 0x2f, // uses the master as target
|
||||
/* 48 */ // UNKNOWN
|
||||
@@ -150,10 +151,10 @@ typedef enum {
|
||||
} DmgShieldType;
|
||||
|
||||
//Spell Effect IDs
|
||||
// full listing: https://forums.station.sony.com/eq/index.php?threads/enumerated-spa-list.206288/
|
||||
// https://forums.daybreakgames.com/eq/index.php?threads/enumerated-spa-list.206288/
|
||||
// mirror: http://pastebin.com/MYeQqGwe
|
||||
#define SE_CurrentHP 0 // implemented - Heals and nukes, repeates every tic if in a buff
|
||||
#define SE_ArmorClass 1 // implemented
|
||||
#define SE_ArmorClass 1 // implemented
|
||||
#define SE_ATK 2 // implemented
|
||||
#define SE_MovementSpeed 3 // implemented - SoW, SoC, etc
|
||||
#define SE_STR 4 // implemented
|
||||
@@ -196,7 +197,7 @@ typedef enum {
|
||||
#define SE_Destroy 41 // implemented - Disintegrate, Banishment of Shadows
|
||||
#define SE_ShadowStep 42 // implemented
|
||||
#define SE_Berserk 43 // implemented (*not used in any known live spell) Makes client 'Berserk' giving crip blow chance.
|
||||
#define SE_Lycanthropy 44 // implemented
|
||||
#define SE_Lycanthropy 44 // implemented
|
||||
#define SE_Vampirism 45 // implemented (*not used in any known live spell) Stackable lifetap from melee.
|
||||
#define SE_ResistFire 46 // implemented
|
||||
#define SE_ResistCold 47 // implemented
|
||||
@@ -246,7 +247,7 @@ typedef enum {
|
||||
#define SE_SummonCorpse 91 // implemented
|
||||
#define SE_InstantHate 92 // implemented - add hate
|
||||
#define SE_StopRain 93 // implemented - Wake of Karana
|
||||
#define SE_NegateIfCombat 94 // implemented
|
||||
#define SE_NegateIfCombat 94 // implemented
|
||||
#define SE_Sacrifice 95 // implemented
|
||||
#define SE_Silence 96 // implemented
|
||||
#define SE_ManaPool 97 // implemented
|
||||
@@ -298,7 +299,7 @@ typedef enum {
|
||||
#define SE_LimitCastTimeMin 143 // implemented
|
||||
#define SE_LimitCastTimeMax 144 // implemented (*not used in any known live spell)
|
||||
#define SE_Teleport2 145 // implemented - Banishment of the Pantheon
|
||||
//#define SE_ElectricityResist 146 // *not implemented (Lightning Rod: 23233)
|
||||
//#define SE_ElectricityResist 146 // *not implemented (Lightning Rod: 23233)
|
||||
#define SE_PercentalHeal 147 // implemented
|
||||
#define SE_StackingCommand_Block 148 // implemented?
|
||||
#define SE_StackingCommand_Overwrite 149 // implemented?
|
||||
@@ -380,47 +381,47 @@ typedef enum {
|
||||
#define SE_GiveDoubleAttack 225 // implemented[AA] - Allow any class to double attack with set chance.
|
||||
#define SE_TwoHandBash 226 // *not implemented as bonus
|
||||
#define SE_ReduceSkillTimer 227 // implemented
|
||||
//#define SE_ReduceFallDamage 228 // not implented as bonus - reduce the damage that you take from falling
|
||||
#define SE_ReduceFallDamage 228 // implented - reduce the damage that you take from falling
|
||||
#define SE_PersistantCasting 229 // implemented
|
||||
//#define SE_ExtendedShielding 230 // not used as bonus - increase range of /shield ability
|
||||
#define SE_ExtendedShielding 230 // not used as bonus - increase range of /shield ability
|
||||
#define SE_StunBashChance 231 // implemented - increase chance to stun from bash.
|
||||
#define SE_DivineSave 232 // implemented (base1 == % chance on death to insta-res) (base2 == spell cast on save)
|
||||
#define SE_Metabolism 233 // implemented - Modifies food/drink consumption rates.
|
||||
//#define SE_ReduceApplyPoisonTime 234 // not implemented as bonus - reduces the time to apply poison
|
||||
#define SE_ReduceApplyPoisonTime 234 // not implemented as bonus - reduces the time to apply poison
|
||||
#define SE_ChannelChanceSpells 235 // implemented[AA] - chance to channel from SPELLS *No longer used on live.
|
||||
//#define SE_FreePet 236 // not used
|
||||
#define SE_GivePetGroupTarget 237 // implemented[AA] - (Pet Affinity)
|
||||
#define SE_IllusionPersistence 238 // implemented - lends persistence to your illusionary disguises, causing them to last until you die or the illusion is forcibly removed.
|
||||
//#define SE_FeignedCastOnChance 239 // *not implemented as bonus - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you.
|
||||
#define SE_FeignedCastOnChance 239 // implemented - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you.
|
||||
//#define SE_StringUnbreakable 240 // not used [Likely related to above - you become immune to feign breaking on a resisted spell and have a good chance of feigning through a spell that successfully lands upon you.]
|
||||
#define SE_ImprovedReclaimEnergy 241 // implemented - increase the amount of mana returned to you when reclaiming your pet.
|
||||
#define SE_IncreaseChanceMemwipe 242 // implemented - increases the chance to wipe hate with memory blurr
|
||||
#define SE_CharmBreakChance 243 // implemented - Total Domination
|
||||
#define SE_RootBreakChance 244 // implemented[AA] reduce the chance that your root will break.
|
||||
//#define SE_TrapCircumvention 245 // *not implemented[AA] - decreases the chance that you will set off a trap when opening a chest
|
||||
#define SE_TrapCircumvention 245 // *not implemented[AA] - decreases the chance that you will set off a trap when opening a chest
|
||||
#define SE_SetBreathLevel 246 // *not implemented as bonus
|
||||
#define SE_RaiseSkillCap 247 // *not implemented[AA] - adds skill over the skill cap.
|
||||
//#define SE_SecondaryForte 248 // not implemented as bonus(gives you a 2nd specialize skill that can go past 50 to 100)
|
||||
#define SE_RaiseSkillCap 247 // implemented[AA] - adds skill over the skill cap.
|
||||
#define SE_SecondaryForte 248 // not implemented as bonus(gives you a 2nd specialize skill that can go past 50 to 100)
|
||||
#define SE_SecondaryDmgInc 249 // implemented[AA] Allows off hand weapon to recieve a damage bonus (Sinister Strikes)
|
||||
#define SE_SpellProcChance 250 // implemented - Increase chance to proc from melee proc spells (ie Spirit of Panther)
|
||||
#define SE_ConsumeProjectile 251 // implemented[AA] - chance to not consume an arrow (ConsumeProjectile = 100)
|
||||
#define SE_FrontalBackstabChance 252 // implemented[AA] - chance to perform a full damage backstab from front.
|
||||
#define SE_FrontalBackstabMinDmg 253 // implemented[AA] - allow a frontal backstab for mininum damage.
|
||||
#define SE_Blank 254 // implemented
|
||||
//#define SE_ShieldDuration 255 // not implemented as bonus - increases duration of /shield
|
||||
//#define SE_ShroudofStealth 256 // not implemented as bonus - rogue improved invs
|
||||
//#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold
|
||||
#define SE_ShieldDuration 255 // not implemented as bonus - increases duration of /shield
|
||||
#define SE_ShroudofStealth 256 // implemented
|
||||
#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold
|
||||
#define SE_TripleBackstab 258 // implemented[AA] - chance to perform a triple backstab
|
||||
#define SE_CombatStability 259 // implemented[AA] - damage mitigation
|
||||
#define SE_AddSingingMod 260 // implemented[AA] - Instrument/Singing Mastery, base1 is the mod, base2 is the ItemType
|
||||
#define SE_SongModCap 261 // implemented[AA] - Song Mod cap increase (no longer used on live)
|
||||
#define SE_RaiseStatCap 262 // implemented
|
||||
//#define SE_TradeSkillMastery 263 // not implemented - lets you raise more than one tradeskill above master.
|
||||
//#define SE_HastenedAASkill 264 // not implemented as bonus - Use redux field in aa_actions table for this effect
|
||||
#define SE_TradeSkillMastery 263 // implemented - lets you raise more than one tradeskill above master.
|
||||
#define SE_HastenedAASkill 264 // implemented
|
||||
#define SE_MasteryofPast 265 // implemented[AA] - Spells less than effect values level can not be fizzled
|
||||
#define SE_ExtraAttackChance 266 // implemented - increase chance to score an extra attack with a 2-Handed Weapon.
|
||||
#define SE_PetDiscipline2 267 // *not implemented - /pet focus, /pet no cast
|
||||
//#define SE_ReduceTradeskillFail 268 // *not implemented? - reduces chance to fail with given tradeskill by a percent chance
|
||||
#define SE_ReduceTradeskillFail 268 // implemented - reduces chance to fail with given tradeskill by a percent chance
|
||||
#define SE_MaxBindWound 269 // implemented[AA] - Increase max HP you can bind wound.
|
||||
#define SE_BardSongRange 270 // implemented[AA] - increase range of beneficial bard songs (Sionachie's Crescendo)
|
||||
#define SE_BaseMovementSpeed 271 // implemented[AA] - mods basemove speed, doesn't stack with other move mods
|
||||
@@ -433,14 +434,14 @@ typedef enum {
|
||||
#define SE_FinishingBlow 278 // implemented[AA] - chance to do massive damage under 10% HP (base1 = chance, base2 = damage)
|
||||
#define SE_Flurry 279 // implemented
|
||||
#define SE_PetFlurry 280 // implemented[AA]
|
||||
//#define SE_FeignedMinion 281 // *not implemented[AA] ability allows you to instruct your pet to feign death via the '/pet feign' command. value = succeed chance
|
||||
#define SE_FeignedMinion 281 // *not implemented[AA] ability allows you to instruct your pet to feign death via the '/pet feign' command. value = succeed chance
|
||||
#define SE_ImprovedBindWound 282 // implemented[AA] - increase bind wound amount by percent.
|
||||
#define SE_DoubleSpecialAttack 283 // implemented[AA] - Chance to perform second special attack as monk
|
||||
//#define SE_LoHSetHeal 284 // not used
|
||||
//#define SE_NimbleEvasion 285 // *not implemented - base1 = 100 for max
|
||||
#define SE_NimbleEvasion 285 // *not implemented - base1 = 100 for max
|
||||
#define SE_FcDamageAmt 286 // implemented - adds direct spell damage
|
||||
#define SE_SpellDurationIncByTic 287 // implemented
|
||||
#define SE_SpecialAttackKBProc 288 // implemented[AA] - Chance to to do a knockback from special attacks [AA Dragon Punch].
|
||||
#define SE_SkillAttackProc 288 // implemented[AA] - Chance to proc spell on skill attack usage (ex. Dragon Punch)
|
||||
#define SE_CastOnFadeEffect 289 // implemented - Triggers only if fades after natural duration.
|
||||
#define SE_IncreaseRunSpeedCap 290 // implemented[AA] - increases run speed over the hard cap
|
||||
#define SE_Purify 291 // implemented - Removes determental effects
|
||||
@@ -477,7 +478,7 @@ typedef enum {
|
||||
#define SE_GateToHomeCity 322 // implemented
|
||||
#define SE_DefensiveProc 323 // implemented
|
||||
#define SE_HPToMana 324 // implemented
|
||||
//#define SE_ChanceInvsBreakToAoE 325 // *not implemented[AA] - [AA Nerves of Steel] increasing chance to remain hidden when they are an indirect target of an AoE spell.
|
||||
#define SE_NoBreakAESneak 325 // implemented[AA] - [AA Nerves of Steel] increasing chance to remain hidden when they are an indirect target of an AoE spell.
|
||||
#define SE_SpellSlotIncrease 326 // *not implemented as bonus - increases your spell slot availability
|
||||
#define SE_MysticalAttune 327 // implemented - increases amount of buffs that a player can have
|
||||
#define SE_DelayDeath 328 // implemented - increases how far you can fall below 0 hp before you die
|
||||
@@ -485,7 +486,7 @@ typedef enum {
|
||||
#define SE_CriticalDamageMob 330 // implemented
|
||||
#define SE_Salvage 331 // implemented - chance to recover items that would be destroyed in failed tradeskill combine
|
||||
//#define SE_SummonToCorpse 332 // *not implemented AA - Call of the Wild (Druid/Shaman Res spell with no exp)
|
||||
#define SE_CastOnRuneFadeEffect 333 // implemented
|
||||
#define SE_CastOnRuneFadeEffect 333 // implemented
|
||||
#define SE_BardAEDot 334 // implemented
|
||||
#define SE_BlockNextSpellFocus 335 // implemented - base1 chance to block next spell ie Puratus (8494)
|
||||
//#define SE_IllusionaryTarget 336 // not used
|
||||
@@ -514,8 +515,8 @@ typedef enum {
|
||||
//#define SE_PassiveSenseTrap 359 // *not implemented - Invulnerability (Brell's Blessing)
|
||||
#define SE_ProcOnKillShot 360 // implemented - a buff that has a base1 % to cast spell base2 when you kill a "challenging foe" base3 min level
|
||||
#define SE_SpellOnDeath 361 // implemented - casts spell on death of buffed
|
||||
//#define SE_PotionBeltSlots 362 // *not implemented[AA] 'Quick Draw' expands the potion belt by one additional available item slot per rank.
|
||||
//#define SE_BandolierSlots 363 // *not implemented[AA] 'Battle Ready' expands the bandolier by one additional save slot per rank.
|
||||
#define SE_PotionBeltSlots 362 // *not implemented[AA] 'Quick Draw' expands the potion belt by one additional available item slot per rank.
|
||||
#define SE_BandolierSlots 363 // *not implemented[AA] 'Battle Ready' expands the bandolier by one additional save slot per rank.
|
||||
#define SE_TripleAttackChance 364 // implemented
|
||||
#define SE_ProcOnSpellKillShot 365 // implemented - chance to trigger a spell on kill when the kill is caused by a specific spell with this effect in it (10470 Venin)
|
||||
#define SE_ShieldEquipDmgMod 366 // implemented[AA] Damage modifier to melee if shield equiped. (base1 = dmg mod , base2 = ?) ie Shield Specialist AA
|
||||
@@ -524,11 +525,11 @@ typedef enum {
|
||||
#define SE_CorruptionCounter 369 // implemented
|
||||
#define SE_ResistCorruption 370 // implemented
|
||||
#define SE_AttackSpeed4 371 // implemented - stackable slow effect 'Inhibit Melee'
|
||||
//#define SE_ForageSkill 372 // *not implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not.
|
||||
#define SE_ForageSkill 372 // *not implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not.
|
||||
#define SE_CastOnFadeEffectAlways 373 // implemented - Triggers if fades after natural duration OR from rune/numhits fades.
|
||||
#define SE_ApplyEffect 374 // implemented
|
||||
#define SE_DotCritDmgIncrease 375 // implemented - Increase damage of DoT critical amount
|
||||
//#define SE_Fling 376 // *not implemented - used in 2 test spells (12945 | Movement Test Spell 1)
|
||||
//#define SE_Fling 376 // *not implemented - used in 2 test spells (12945 | Movement Test Spell 1)
|
||||
#define SE_CastOnFadeEffectNPC 377 // implemented - Triggers only if fades after natural duration (On live these are usually players spells that effect an NPC).
|
||||
#define SE_SpellEffectResistChance 378 // implemented - Increase chance to resist specific spell effect (base1=value, base2=spell effect id)
|
||||
#define SE_ShadowStepDirectional 379 // implemented - handled by client
|
||||
@@ -543,7 +544,7 @@ typedef enum {
|
||||
//#define SE_SummonCorpseZone 388 // *not implemented - summons a corpse from any zone(nec AA)
|
||||
#define SE_FcTimerRefresh 389 // implemented - Refresh spell icons
|
||||
//#define SE_FcTimerLockout 390 // *not implemented - Sets recast timers to specific value, focus limited.
|
||||
#define SE_MeleeVulnerability 391 // implemented [Live SPA has this as LimitManaMax however that is clearly not the effect used]
|
||||
#define SE_LimitManaMax 391 // implemented
|
||||
#define SE_FcHealAmt 392 // implemented - Adds or removes healing from spells
|
||||
#define SE_FcHealPctIncoming 393 // implemented - HealRate with focus restrictions.
|
||||
#define SE_FcHealAmtIncoming 394 // implemented - Adds/Removes amount of healing on target by X value with foucs restrictions.
|
||||
@@ -559,7 +560,7 @@ typedef enum {
|
||||
#define SE_LimitSpellSubclass 404 // *not implemented - Limits to specific types of spells (see CheckSpellCategory) [Categories NOT defined yet]
|
||||
#define SE_TwoHandBluntBlock 405 // implemented - chance to block attacks when using two hand blunt weapons (similiar to shield block)
|
||||
#define SE_CastonNumHitFade 406 // implemented - casts a spell when a buff fades due to its numhits being depleted
|
||||
#define SE_CastonFocusEffect 407 // implemented - casts a spell if focus limits are met (ie triggers when a focus effects is applied)
|
||||
#define SE_CastonFocusEffect 407 // implemented - casts a spell if focus limits are met (ie triggers when a focus effects is applied)
|
||||
#define SE_LimitHPPercent 408 // implemented - limited to a certain percent of your hp(ie heals up to 50%)
|
||||
#define SE_LimitManaPercent 409 // implemented - limited to a certain percent of your mana
|
||||
#define SE_LimitEndPercent 410 // implemented - limited to a certain percent of your end
|
||||
@@ -575,10 +576,10 @@ typedef enum {
|
||||
#define SE_FcLimitUse 420 // implemented - increases numhits count by percent (Note: not used in any known live spells)
|
||||
#define SE_FcIncreaseNumHits 421 // implemented[AA] - increases number of hits a buff has till fade. (focus)
|
||||
#define SE_LimitUseMin 422 // implemented - limit a focus to require a min amount of numhits value (used with above)
|
||||
#define SE_LimitUseType 423 // implemented - limit a focus to require a certain numhits type
|
||||
#define SE_LimitUseType 423 // implemented - limit a focus to require a certain numhits type
|
||||
#define SE_GravityEffect 424 // implemented - Pulls/pushes you toward/away the mob at a set pace
|
||||
//#define SE_Display 425 // *not implemented - Illusion: Flying Dragon(21626)
|
||||
//#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window
|
||||
#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window
|
||||
#define SE_SkillProc 427 // implemented - chance to proc when using a skill(ie taunt)
|
||||
#define SE_LimitToSkill 428 // implemented - limits what skills will effect a skill proc
|
||||
#define SE_SkillProcSuccess 429 // implemented - chance to proc when tje skill in use successfully fires.
|
||||
@@ -599,9 +600,9 @@ typedef enum {
|
||||
#define SE_ImprovedTaunt 444 // implemented - Locks Aggro On Caster and Decrease other Players Aggro by X% on NPC targets below level Y
|
||||
//#define SE_AddMercSlot 445 // *not implemented[AA] - [Hero's Barracks] Allows you to conscript additional mercs.
|
||||
#define SE_AStacker 446 // implementet - bufff stacking blocker (26219 | Qirik's Watch)
|
||||
#define SE_BStacker 447 // implemented
|
||||
#define SE_BStacker 447 // implemented
|
||||
#define SE_CStacker 448 // implemented
|
||||
#define SE_DStacker 449 // implemented
|
||||
#define SE_DStacker 449 // implemented
|
||||
#define SE_MitigateDotDamage 450 // implemented DOT spell mitigation rune with max value
|
||||
#define SE_MeleeThresholdGuard 451 // implemented Partial Melee Rune that only is lowered if melee hits are over X amount of damage
|
||||
#define SE_SpellThresholdGuard 452 // implemented Partial Spell Rune that only is lowered if spell hits are over X amount of damage
|
||||
@@ -612,11 +613,25 @@ typedef enum {
|
||||
#define SE_ResourceTap 457 // implemented Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end.
|
||||
#define SE_FactionModPct 458 // implemented Modifies faction gains and losses by percent.
|
||||
#define SE_DamageModifier2 459 // implemented - Modifies melee damage by skill type
|
||||
//#define SE_Ff_Override_NotFocusable 460 //
|
||||
#define SE_ImprovedDamage2 461 // implemented - Increase spell damage by percent (SE_Fc_Damage_%2)
|
||||
#define SE_FcDamageAmt2 462 // implemented - Increase spell damage by flat amount (SE_Fc_Damage_Amt2)
|
||||
//#define SE_Shield_Target 463 //
|
||||
#define SE_PC_Pet_Rampage 464 // implemented - Base1 % chance to do rampage for base2 % of damage each melee round
|
||||
//#define SE_PC_Pet_AE_Rampage 465 // Would assume as above but need to confirm.
|
||||
#define SE_PC_Pet_Flurry_Chance 466 // implemented - Base1 % chance to do flurry from double attack hit.
|
||||
//#define SE_DS_Mitigation_Amount 467 //
|
||||
//#define SE_DS_Mitigation_Percentage 468 //
|
||||
//#define SE_Chance_Best_in_Spell_Grp 469 //
|
||||
//#define SE_Trigger_Best_in_Spell Grp 470 //
|
||||
//#define SE_Double_Melee_Round 471 //
|
||||
|
||||
|
||||
// LAST
|
||||
|
||||
|
||||
#define DF_Permanent 50
|
||||
#define DF_Aura 51
|
||||
|
||||
// note this struct is historical, we don't actually need it to be
|
||||
// aligned to anything, but for maintaining it it is kept in the order that
|
||||
@@ -729,35 +744,38 @@ struct SPDat_Spell_Struct
|
||||
/* 194 */ float directional_start; //Cone Start Angle:
|
||||
/* 195 */ float directional_end; // Cone End Angle:
|
||||
/* 196 */ bool sneak; // effect can only be used if sneaking (rogue 'Daggerfall' ect)
|
||||
/* 197 */ bool not_extendable;
|
||||
/* 198- 199 */
|
||||
/* 197 */ bool not_focusable; //prevents focus effects from being applied to spell
|
||||
/* 198 */ bool no_detrimental_spell_aggro;
|
||||
/* 199 */
|
||||
/* 200 */ bool suspendable; // buff is suspended in suspended buff zones
|
||||
/* 201 */ int viral_range;
|
||||
/* 202 */
|
||||
/* 203 */ //int songcap; // individual song cap (how live currently does it, not implemented)
|
||||
/* 201 */ int viral_range;
|
||||
/* 202 */ int songcap; // individual song cap
|
||||
/* 203 */
|
||||
/* 204 */
|
||||
/* 205 */ bool no_block;
|
||||
/* 206 */
|
||||
/* 206 */
|
||||
/* 207 */ int spellgroup;
|
||||
/* 208 */ int rank; //increments AA effects with same name
|
||||
/* 209 */ int powerful_flag; // Need more investigation to figure out what to call this, for now we know -1 makes charm spells not break before their duration is complete, it does alot more though
|
||||
/* 210 */ // bool DurationFrozen; ???
|
||||
/* 209 */ int no_resist; //makes spells unresistable, which makes charms unbreakable as well.
|
||||
/* 210 */ // bool DurationFrozen; ???
|
||||
/* 211 */ int CastRestriction; //Various restriction categories for spells most seem targetable race related but have also seen others for instance only castable if target hp 20% or lower or only if target out of combat
|
||||
/* 212 */ bool AllowRest;
|
||||
/* 213 */ bool InCombat; //Allow spell if target is in combat
|
||||
/* 214 */ bool OutofCombat; //Allow spell if target is out of combat
|
||||
/* 215 - 217 */
|
||||
/* 218 */ int aemaxtargets; //Is used for various AE effects
|
||||
/* 219 */ int maxtargets; //Is used for beam and ring spells for target # limits (not implemented)
|
||||
/* 220 - 223 */
|
||||
/* 215 - 216 */
|
||||
/* 217 */ int override_crit_chance; //Places a cap on the max chance to critical
|
||||
/* 218 */ int aemaxtargets; //Is used for various AE effects
|
||||
/* 219 */ int no_heal_damage_item_mod;
|
||||
/* 220 - 223 */
|
||||
/* 224 */ bool persistdeath; // buff doesn't get stripped on death
|
||||
/* 225 - 226 */
|
||||
/* 227 */ float min_dist; //spell power modified by distance from caster (Min Distance)
|
||||
/* 228 */ float min_dist_mod; //spell power modified by distance from caster (Modifier at Min Distance)
|
||||
/* 229 */ float max_dist; //spell power modified by distance from caster (Max Distance)
|
||||
/* 230 */ float max_dist_mod; //spell power modified by distance from caster (Modifier at Max Distance)
|
||||
/* 231 */ float min_range; //Min casting range
|
||||
/* 232 - 236 */
|
||||
/* 231 */ float min_range; //Min casting range
|
||||
/* 232 */ bool no_remove; //prevents buff from being removed by click
|
||||
/* 233 - 236 */
|
||||
uint8 DamageShieldType; // This field does not exist in spells_us.txt
|
||||
};
|
||||
|
||||
@@ -863,6 +881,7 @@ uint32 GetPartialMeleeRuneReduction(uint32 spell_id);
|
||||
uint32 GetPartialMagicRuneReduction(uint32 spell_id);
|
||||
uint32 GetPartialMeleeRuneAmount(uint32 spell_id);
|
||||
uint32 GetPartialMagicRuneAmount(uint32 spell_id);
|
||||
bool NoDetrimentalSpellAggro(uint16 spell_id);
|
||||
|
||||
int CalcPetHp(int levelb, int classb, int STA = 75);
|
||||
const char *GetRandPetName();
|
||||
|
||||
@@ -71,7 +71,6 @@ const std::string StringFormat(const char* format, ...)
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
// normal strncpy doesnt put a null term on copied strings, this one does
|
||||
// ref: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcecrt/htm/_wcecrt_strncpy_wcsncpy.asp
|
||||
char* strn0cpy(char* dest, const char* source, uint32 size) {
|
||||
@@ -408,3 +407,11 @@ bool isAlphaNumeric(const char *text)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string) {
|
||||
auto index = string_subject.find_first_of(search_string);
|
||||
while (index != std::string::npos) {
|
||||
string_subject.replace(index, index + 1, replace_string);
|
||||
index = string_subject.find_first_of(search_string);
|
||||
}
|
||||
}
|
||||
|
||||
+18
-21
@@ -23,37 +23,34 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
const std::string vStringFormat(const char* format, va_list args);
|
||||
const std::string StringFormat(const char* format, ...);
|
||||
std::string EscapeString(const std::string &s);
|
||||
std::string EscapeString(const char *src, size_t sz);
|
||||
|
||||
const char *MakeLowerString(const char *source);
|
||||
|
||||
void MakeLowerString(const char *source, char *target);
|
||||
|
||||
int MakeAnyLenString(char** ret, const char* format, ...);
|
||||
uint32 AppendAnyLenString(char** ret, uint32* bufsize, uint32* strlen, const char* format, ...);
|
||||
|
||||
uint32 hextoi(const char* num);
|
||||
uint64 hextoi64(const char* num);
|
||||
bool atobool(const char* iBool);
|
||||
|
||||
char* strn0cpy(char* dest, const char* source, uint32 size);
|
||||
// return value =true if entire string(source) fit, false if it was truncated
|
||||
bool isAlphaNumeric(const char *text);
|
||||
bool strn0cpyt(char* dest, const char* source, uint32 size);
|
||||
|
||||
char *CleanMobName(const char *in, char *out);
|
||||
char *RemoveApostrophes(const char *s);
|
||||
char* strn0cpy(char* dest, const char* source, uint32 size);
|
||||
|
||||
const char *ConvertArray(int input, char *returnchar);
|
||||
const char *ConvertArrayF(float input, char *returnchar);
|
||||
const char *MakeLowerString(const char *source);
|
||||
const std::string StringFormat(const char* format, ...);
|
||||
const std::string vStringFormat(const char* format, va_list args);
|
||||
|
||||
void RemoveApostrophes(std::string &s);
|
||||
char *RemoveApostrophes(const char *s);
|
||||
int MakeAnyLenString(char** ret, const char* format, ...);
|
||||
|
||||
std::string EscapeString(const char *src, size_t sz);
|
||||
std::string EscapeString(const std::string &s);
|
||||
|
||||
std::vector<std::string> SplitString(const std::string &s, char delim);
|
||||
|
||||
bool isAlphaNumeric(const char *text);
|
||||
uint32 AppendAnyLenString(char** ret, uint32* bufsize, uint32* strlen, const char* format, ...);
|
||||
uint32 hextoi(const char* num);
|
||||
|
||||
uint64 hextoi64(const char* num);
|
||||
|
||||
void MakeLowerString(const char *source, char *target);
|
||||
void RemoveApostrophes(std::string &s);
|
||||
void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,7 +23,9 @@
|
||||
*/
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#define snprintf _snprintf
|
||||
#if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900))
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#define strncasecmp _strnicmp
|
||||
#define strcasecmp _stricmp
|
||||
|
||||
|
||||
+19
-1
@@ -43,7 +43,9 @@ typedef unsigned char uchar;
|
||||
typedef const char Const_char; //for perl XS
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#define snprintf _snprintf
|
||||
#if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900))
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#define strncasecmp _strnicmp
|
||||
#define strcasecmp _stricmp
|
||||
typedef void ThreadReturnType;
|
||||
@@ -83,4 +85,20 @@ typedef const char Const_char; //for perl XS
|
||||
#define DLLFUNC extern "C"
|
||||
#endif
|
||||
|
||||
// htonll and ntohll already defined on windows
|
||||
#ifndef WIN32
|
||||
# if defined(__linux__)
|
||||
# include <endian.h>
|
||||
# elif defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
# include <sys/endian.h>
|
||||
# elif defined (__OpenBSD__)
|
||||
# include <sys/types.h>
|
||||
# define be16toh(x) betoh16(x)
|
||||
# define be32toh(x) betoh32(x)
|
||||
# define be64toh(x) betoh64(x)
|
||||
# endif
|
||||
# define htonll(x) htobe64(x)
|
||||
# define ntohll(x) be64toh(x)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+10
-5
@@ -22,15 +22,20 @@
|
||||
#define LOGIN_VERSION "0.8.0"
|
||||
#define EQEMU_PROTOCOL_VERSION "0.3.10"
|
||||
|
||||
#define CURRENT_VERSION "1.0.0"
|
||||
#define CURRENT_VERSION "1.1.3"
|
||||
|
||||
/*
|
||||
Everytime a Database SQL is added to Github,
|
||||
/*
|
||||
Everytime a Database SQL is added to Github,
|
||||
increment CURRENT_BINARY_DATABASE_VERSION number and make sure you update the manifest
|
||||
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9073
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9095
|
||||
#ifdef BOTS
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000
|
||||
#else
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
|
||||
#endif
|
||||
#define COMPILE_DATE __DATE__
|
||||
#define COMPILE_TIME __TIME__
|
||||
#ifndef WIN32
|
||||
|
||||
@@ -102,8 +102,6 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
Log.Out(Logs::Detail, Logs::Launcher, "Starting main loop...");
|
||||
|
||||
// zones["test"] = new ZoneLaunch(&world, "./zone", "dynamic_1");
|
||||
|
||||
ProcLauncher *launch = ProcLauncher::get();
|
||||
RunLoops = true;
|
||||
while(RunLoops) {
|
||||
|
||||
@@ -86,14 +86,13 @@ void WorldServer::Process() {
|
||||
}
|
||||
const LauncherZoneRequest *lzr = (const LauncherZoneRequest *) pack->pBuffer;
|
||||
|
||||
|
||||
switch(ZoneRequestCommands(lzr->command)) {
|
||||
case ZR_Start: {
|
||||
if(m_zones.find(lzr->short_name) != m_zones.end()) {
|
||||
Log.Out(Logs::Detail, Logs::Launcher, "World told us to start zone %s, but it is already running.", lzr->short_name);
|
||||
} else {
|
||||
Log.Out(Logs::Detail, Logs::Launcher, "World told us to start zone %s.", lzr->short_name);
|
||||
ZoneLaunch *l = new ZoneLaunch(this, m_name, lzr->short_name, m_config);
|
||||
ZoneLaunch *l = new ZoneLaunch(this, m_name, lzr->short_name, lzr->port, m_config);
|
||||
m_zones[lzr->short_name] = l;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -34,10 +34,11 @@ void ZoneLaunch::InitStartTimer() {
|
||||
}
|
||||
|
||||
ZoneLaunch::ZoneLaunch(WorldServer *world, const char *launcher_name,
|
||||
const char *zone_name, const EQEmuConfig *config)
|
||||
const char *zone_name, uint16 port, const EQEmuConfig *config)
|
||||
: m_state(StateStartPending),
|
||||
m_world(world),
|
||||
m_zone(zone_name),
|
||||
m_port(port),
|
||||
m_launcherName(launcher_name),
|
||||
m_config(config),
|
||||
m_timer(config->RestartWait),
|
||||
@@ -61,10 +62,14 @@ void ZoneLaunch::SendStatus() const {
|
||||
void ZoneLaunch::Start() {
|
||||
ProcLauncher::Spec *spec = new ProcLauncher::Spec();
|
||||
spec->program = m_config->ZoneExe;
|
||||
// if(m_zone.substr(0,7) == "dynamic")
|
||||
// spec->args.push_back(".");
|
||||
// else
|
||||
spec->args.push_back(m_zone);
|
||||
|
||||
if(m_port) {
|
||||
std::string arg = m_zone + std::string(":") + std::to_string(m_port);
|
||||
spec->args.push_back(arg);
|
||||
} else {
|
||||
spec->args.push_back(m_zone);
|
||||
}
|
||||
|
||||
spec->args.push_back(m_launcherName);
|
||||
spec->handler = this;
|
||||
spec->logFile = m_config->LogPrefix + m_zone + m_config->LogSuffix;
|
||||
|
||||
@@ -28,7 +28,7 @@ class EQEmuConfig;
|
||||
class ZoneLaunch : protected ProcLauncher::EventHandler {
|
||||
public:
|
||||
ZoneLaunch(WorldServer *world, const char *launcher_name,
|
||||
const char *zone_name, const EQEmuConfig *config);
|
||||
const char *zone_name, uint16 port, const EQEmuConfig *config);
|
||||
virtual ~ZoneLaunch();
|
||||
|
||||
void Stop(bool graceful = true);
|
||||
@@ -63,6 +63,7 @@ protected:
|
||||
const std::string m_zone;
|
||||
const char *const m_launcherName;
|
||||
const EQEmuConfig *const m_config;
|
||||
const uint16 m_port;
|
||||
|
||||
Timer m_timer;
|
||||
ProcLauncher::ProcRef m_ref;
|
||||
|
||||
@@ -6,7 +6,6 @@ SET(eqlogin_sources
|
||||
config.cpp
|
||||
database_mysql.cpp
|
||||
database_postgresql.cpp
|
||||
error_log.cpp
|
||||
main.cpp
|
||||
server_manager.cpp
|
||||
world_server.cpp
|
||||
@@ -26,7 +25,6 @@ SET(eqlogin_headers
|
||||
database_postgresql.h
|
||||
encryption.h
|
||||
eq_crypto_api.h
|
||||
error_log.h
|
||||
login_server.h
|
||||
login_structures.h
|
||||
options.h
|
||||
@@ -43,7 +41,7 @@ ADD_EXECUTABLE(loginserver ${eqlogin_sources} ${eqlogin_headers})
|
||||
|
||||
INSTALL(TARGETS loginserver RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
|
||||
TARGET_LINK_LIBRARIES(loginserver common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE})
|
||||
TARGET_LINK_LIBRARIES(loginserver common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY})
|
||||
|
||||
IF(MSVC)
|
||||
SET_TARGET_PROPERTIES(loginserver PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF")
|
||||
|
||||
+107
-102
@@ -16,12 +16,12 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "client.h"
|
||||
#include "error_log.h"
|
||||
#include "login_server.h"
|
||||
#include "login_structures.h"
|
||||
#include "../common/misc_functions.h"
|
||||
#include "../common/eqemu_logsys.h"
|
||||
|
||||
extern ErrorLog *server_log;
|
||||
extern EQEmuLogSys Log;
|
||||
extern LoginServer server;
|
||||
|
||||
Client::Client(std::shared_ptr<EQStream> c, LSClientVersion v)
|
||||
@@ -41,7 +41,7 @@ bool Client::Process()
|
||||
{
|
||||
if(server.options.IsTraceOn())
|
||||
{
|
||||
server_log->Log(log_network, "Application packet received from client (size %u)", app->Size());
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Application packet received from client (size %u)", app->Size());
|
||||
}
|
||||
|
||||
if(server.options.IsDumpInPacketsOn())
|
||||
@@ -55,7 +55,7 @@ bool Client::Process()
|
||||
{
|
||||
if(server.options.IsTraceOn())
|
||||
{
|
||||
server_log->Log(log_network, "Session ready received from client.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Session ready received from client.");
|
||||
}
|
||||
Handle_SessionReady((const char*)app->pBuffer, app->Size());
|
||||
break;
|
||||
@@ -64,13 +64,13 @@ bool Client::Process()
|
||||
{
|
||||
if(app->Size() < 20)
|
||||
{
|
||||
server_log->Log(log_network_error, "Login received but it is too small, discarding.");
|
||||
Log.Out(Logs::General, Logs::Error, "Login received but it is too small, discarding.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(server.options.IsTraceOn())
|
||||
{
|
||||
server_log->Log(log_network, "Login received from client.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Login received from client.");
|
||||
}
|
||||
|
||||
Handle_Login((const char*)app->pBuffer, app->Size());
|
||||
@@ -80,7 +80,7 @@ bool Client::Process()
|
||||
{
|
||||
if(server.options.IsTraceOn())
|
||||
{
|
||||
server_log->Log(log_network, "Server list request received from client.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Server list request received from client.");
|
||||
}
|
||||
|
||||
SendServerListPacket();
|
||||
@@ -90,7 +90,7 @@ bool Client::Process()
|
||||
{
|
||||
if(app->Size() < sizeof(PlayEverquestRequest_Struct))
|
||||
{
|
||||
server_log->Log(log_network_error, "Play received but it is too small, discarding.");
|
||||
Log.Out(Logs::General, Logs::Error, "Play received but it is too small, discarding.");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ bool Client::Process()
|
||||
{
|
||||
char dump[64];
|
||||
app->build_header_dump(dump);
|
||||
server_log->Log(log_network_error, "Recieved unhandled application packet from the client: %s.", dump);
|
||||
Log.Out(Logs::General, Logs::Error, "Recieved unhandled application packet from the client: %s.", dump);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,20 +116,20 @@ void Client::Handle_SessionReady(const char* data, unsigned int size)
|
||||
{
|
||||
if(status != cs_not_sent_session_ready)
|
||||
{
|
||||
server_log->Log(log_network_error, "Session ready received again after already being received.");
|
||||
Log.Out(Logs::General, Logs::Error, "Session ready received again after already being received.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(size < sizeof(unsigned int))
|
||||
{
|
||||
server_log->Log(log_network_error, "Session ready was too small.");
|
||||
Log.Out(Logs::General, Logs::Error, "Session ready was too small.");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int mode = *((unsigned int*)data);
|
||||
if(mode == (unsigned int)lm_from_world)
|
||||
{
|
||||
server_log->Log(log_network, "Session ready indicated logged in from world(unsupported feature), disconnecting.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Session ready indicated logged in from world(unsupported feature), disconnecting.");
|
||||
connection->Close();
|
||||
return;
|
||||
}
|
||||
@@ -175,138 +175,144 @@ void Client::Handle_SessionReady(const char* data, unsigned int size)
|
||||
|
||||
void Client::Handle_Login(const char* data, unsigned int size)
|
||||
{
|
||||
if(status != cs_waiting_for_login)
|
||||
{
|
||||
server_log->Log(log_network_error, "Login received after already having logged in.");
|
||||
if(status != cs_waiting_for_login) {
|
||||
Log.Out(Logs::General, Logs::Error, "Login received after already having logged in.");
|
||||
return;
|
||||
}
|
||||
|
||||
if((size - 12) % 8 != 0)
|
||||
{
|
||||
server_log->Log(log_network_error, "Login received packet of size: %u, this would cause a block corruption, discarding.", size);
|
||||
if((size - 12) % 8 != 0) {
|
||||
Log.Out(Logs::General, Logs::Error, "Login received packet of size: %u, this would cause a block corruption, discarding.", size);
|
||||
return;
|
||||
}
|
||||
|
||||
status = cs_logged_in;
|
||||
|
||||
string e_user;
|
||||
string e_hash;
|
||||
char *e_buffer = nullptr;
|
||||
unsigned int d_account_id = 0;
|
||||
string d_pass_hash;
|
||||
string entered_username;
|
||||
string entered_password_hash_result;
|
||||
|
||||
char *login_packet_buffer = nullptr;
|
||||
|
||||
unsigned int db_account_id = 0;
|
||||
string db_account_password_hash;
|
||||
|
||||
#ifdef WIN32
|
||||
e_buffer = server.eq_crypto->DecryptUsernamePassword(data, size, server.options.GetEncryptionMode());
|
||||
login_packet_buffer = server.eq_crypto->DecryptUsernamePassword(data, size, server.options.GetEncryptionMode());
|
||||
|
||||
int buffer_len = strlen(e_buffer);
|
||||
e_hash.assign(e_buffer, buffer_len);
|
||||
e_user.assign((e_buffer + buffer_len + 1), strlen(e_buffer + buffer_len + 1));
|
||||
int login_packet_buffer_length = strlen(login_packet_buffer);
|
||||
entered_password_hash_result.assign(login_packet_buffer, login_packet_buffer_length);
|
||||
entered_username.assign((login_packet_buffer + login_packet_buffer_length + 1), strlen(login_packet_buffer + login_packet_buffer_length + 1));
|
||||
|
||||
if(server.options.IsTraceOn())
|
||||
{
|
||||
server_log->Log(log_client, "User: %s", e_user.c_str());
|
||||
server_log->Log(log_client, "Hash: %s", e_hash.c_str());
|
||||
if(server.options.IsTraceOn()) {
|
||||
Log.Out(Logs::General, Logs::Debug, "User: %s", entered_username.c_str());
|
||||
Log.Out(Logs::General, Logs::Debug, "Hash: %s", entered_password_hash_result.c_str());
|
||||
}
|
||||
|
||||
server.eq_crypto->DeleteHeap(e_buffer);
|
||||
server.eq_crypto->DeleteHeap(login_packet_buffer);
|
||||
#else
|
||||
e_buffer = DecryptUsernamePassword(data, size, server.options.GetEncryptionMode());
|
||||
login_packet_buffer = DecryptUsernamePassword(data, size, server.options.GetEncryptionMode());
|
||||
|
||||
int buffer_len = strlen(e_buffer);
|
||||
e_hash.assign(e_buffer, buffer_len);
|
||||
e_user.assign((e_buffer + buffer_len + 1), strlen(e_buffer + buffer_len + 1));
|
||||
int login_packet_buffer_length = strlen(login_packet_buffer);
|
||||
entered_password_hash_result.assign(login_packet_buffer, login_packet_buffer_length);
|
||||
entered_username.assign((login_packet_buffer + login_packet_buffer_length + 1), strlen(login_packet_buffer + login_packet_buffer_length + 1));
|
||||
|
||||
if(server.options.IsTraceOn())
|
||||
{
|
||||
server_log->Log(log_client, "User: %s", e_user.c_str());
|
||||
server_log->Log(log_client, "Hash: %s", e_hash.c_str());
|
||||
if(server.options.IsTraceOn()) {
|
||||
Log.Out(Logs::General, Logs::Debug, "User: %s", entered_username.c_str());
|
||||
Log.Out(Logs::General, Logs::Debug, "Hash: %s", entered_password_hash_result.c_str());
|
||||
}
|
||||
|
||||
_HeapDeleteCharBuffer(e_buffer);
|
||||
_HeapDeleteCharBuffer(login_packet_buffer);
|
||||
#endif
|
||||
|
||||
bool result;
|
||||
if(server.db->GetLoginDataFromAccountName(e_user, d_pass_hash, d_account_id) == false)
|
||||
{
|
||||
server_log->Log(log_client_error, "Error logging in, user %s does not exist in the database.", e_user.c_str());
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(d_pass_hash.compare(e_hash) == 0)
|
||||
{
|
||||
if(server.db->GetLoginDataFromAccountName(entered_username, db_account_password_hash, db_account_id) == false) {
|
||||
/* If we have auto_create_accounts enabled in the login.ini, we will process the creation of an account on our own*/
|
||||
if (
|
||||
server.config->GetVariable("options", "auto_create_accounts").compare("TRUE") == 0 &&
|
||||
server.db->CreateLoginData(entered_username, entered_password_hash_result, db_account_id) == true
|
||||
){
|
||||
Log.Out(Logs::General, Logs::Error, "User %s does not exist in the database, so we created it...", entered_username.c_str());
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
else{
|
||||
Log.Out(Logs::General, Logs::Error, "Error logging in, user %s does not exist in the database.", entered_username.c_str());
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(db_account_password_hash.compare(entered_password_hash_result) == 0) {
|
||||
result = true;
|
||||
}
|
||||
else {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(result)
|
||||
{
|
||||
server.CM->RemoveExistingClient(d_account_id);
|
||||
/* Login Accepted */
|
||||
if(result) {
|
||||
|
||||
server.client_manager->RemoveExistingClient(db_account_id);
|
||||
|
||||
in_addr in;
|
||||
in.s_addr = connection->GetRemoteIP();
|
||||
server.db->UpdateLSAccountData(d_account_id, string(inet_ntoa(in)));
|
||||
|
||||
server.db->UpdateLSAccountData(db_account_id, string(inet_ntoa(in)));
|
||||
GenerateKey();
|
||||
account_id = d_account_id;
|
||||
account_name = e_user;
|
||||
|
||||
account_id = db_account_id;
|
||||
account_name = entered_username;
|
||||
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_LoginAccepted, 10 + 80);
|
||||
const LoginLoginRequest_Struct* llrs = (const LoginLoginRequest_Struct *)data;
|
||||
LoginLoginAccepted_Struct* llas = (LoginLoginAccepted_Struct *)outapp->pBuffer;
|
||||
llas->unknown1 = llrs->unknown1;
|
||||
llas->unknown2 = llrs->unknown2;
|
||||
llas->unknown3 = llrs->unknown3;
|
||||
llas->unknown4 = llrs->unknown4;
|
||||
llas->unknown5 = llrs->unknown5;
|
||||
LoginAccepted_Struct* login_accepted = (LoginAccepted_Struct *)outapp->pBuffer;
|
||||
login_accepted->unknown1 = llrs->unknown1;
|
||||
login_accepted->unknown2 = llrs->unknown2;
|
||||
login_accepted->unknown3 = llrs->unknown3;
|
||||
login_accepted->unknown4 = llrs->unknown4;
|
||||
login_accepted->unknown5 = llrs->unknown5;
|
||||
|
||||
Login_ReplyBlock_Struct * lrbs = new Login_ReplyBlock_Struct;
|
||||
memset(lrbs, 0, sizeof(Login_ReplyBlock_Struct));
|
||||
LoginFailedAttempts_Struct * login_failed_attempts = new LoginFailedAttempts_Struct;
|
||||
memset(login_failed_attempts, 0, sizeof(LoginFailedAttempts_Struct));
|
||||
|
||||
lrbs->failed_attempts = 0;
|
||||
lrbs->message = 0x01;
|
||||
lrbs->lsid = d_account_id;
|
||||
lrbs->unknown3[3] = 0x03;
|
||||
lrbs->unknown4[3] = 0x02;
|
||||
lrbs->unknown5[0] = 0xe7;
|
||||
lrbs->unknown5[1] = 0x03;
|
||||
lrbs->unknown6[0] = 0xff;
|
||||
lrbs->unknown6[1] = 0xff;
|
||||
lrbs->unknown6[2] = 0xff;
|
||||
lrbs->unknown6[3] = 0xff;
|
||||
lrbs->unknown7[0] = 0xa0;
|
||||
lrbs->unknown7[1] = 0x05;
|
||||
lrbs->unknown8[3] = 0x02;
|
||||
lrbs->unknown9[0] = 0xff;
|
||||
lrbs->unknown9[1] = 0x03;
|
||||
lrbs->unknown11[0] = 0x63;
|
||||
lrbs->unknown12[0] = 0x01;
|
||||
memcpy(lrbs->key, key.c_str(), key.size());
|
||||
login_failed_attempts->failed_attempts = 0;
|
||||
login_failed_attempts->message = 0x01;
|
||||
login_failed_attempts->lsid = db_account_id;
|
||||
login_failed_attempts->unknown3[3] = 0x03;
|
||||
login_failed_attempts->unknown4[3] = 0x02;
|
||||
login_failed_attempts->unknown5[0] = 0xe7;
|
||||
login_failed_attempts->unknown5[1] = 0x03;
|
||||
login_failed_attempts->unknown6[0] = 0xff;
|
||||
login_failed_attempts->unknown6[1] = 0xff;
|
||||
login_failed_attempts->unknown6[2] = 0xff;
|
||||
login_failed_attempts->unknown6[3] = 0xff;
|
||||
login_failed_attempts->unknown7[0] = 0xa0;
|
||||
login_failed_attempts->unknown7[1] = 0x05;
|
||||
login_failed_attempts->unknown8[3] = 0x02;
|
||||
login_failed_attempts->unknown9[0] = 0xff;
|
||||
login_failed_attempts->unknown9[1] = 0x03;
|
||||
login_failed_attempts->unknown11[0] = 0x63;
|
||||
login_failed_attempts->unknown12[0] = 0x01;
|
||||
memcpy(login_failed_attempts->key, key.c_str(), key.size());
|
||||
|
||||
#ifdef WIN32
|
||||
unsigned int e_size;
|
||||
char *encrypted_buffer = server.eq_crypto->Encrypt((const char*)lrbs, 75, e_size);
|
||||
memcpy(llas->encrypt, encrypted_buffer, 80);
|
||||
char *encrypted_buffer = server.eq_crypto->Encrypt((const char*)login_failed_attempts, 75, e_size);
|
||||
memcpy(login_accepted->encrypt, encrypted_buffer, 80);
|
||||
server.eq_crypto->DeleteHeap(encrypted_buffer);
|
||||
#else
|
||||
unsigned int e_size;
|
||||
char *encrypted_buffer = Encrypt((const char*)lrbs, 75, e_size);
|
||||
memcpy(llas->encrypt, encrypted_buffer, 80);
|
||||
char *encrypted_buffer = Encrypt((const char*)login_failed_attempts, 75, e_size);
|
||||
memcpy(login_accepted->encrypt, encrypted_buffer, 80);
|
||||
_HeapDeleteCharBuffer(encrypted_buffer);
|
||||
#endif
|
||||
|
||||
if(server.options.IsDumpOutPacketsOn())
|
||||
{
|
||||
if(server.options.IsDumpOutPacketsOn()) {
|
||||
DumpPacket(outapp);
|
||||
}
|
||||
|
||||
connection->QueuePacket(outapp);
|
||||
delete outapp;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_LoginAccepted, sizeof(LoginLoginFailed_Struct));
|
||||
const LoginLoginRequest_Struct* llrs = (const LoginLoginRequest_Struct *)data;
|
||||
LoginLoginFailed_Struct* llas = (LoginLoginFailed_Struct *)outapp->pBuffer;
|
||||
@@ -317,8 +323,7 @@ void Client::Handle_Login(const char* data, unsigned int size)
|
||||
llas->unknown5 = llrs->unknown5;
|
||||
memcpy(llas->unknown6, FailedLoginResponseData, sizeof(FailedLoginResponseData));
|
||||
|
||||
if(server.options.IsDumpOutPacketsOn())
|
||||
{
|
||||
if(server.options.IsDumpOutPacketsOn()) {
|
||||
DumpPacket(outapp);
|
||||
}
|
||||
|
||||
@@ -331,7 +336,7 @@ void Client::Handle_Play(const char* data)
|
||||
{
|
||||
if(status != cs_logged_in)
|
||||
{
|
||||
server_log->Log(log_client_error, "Client sent a play request when they either were not logged in, discarding.");
|
||||
Log.Out(Logs::General, Logs::Error, "Client sent a play request when they either were not logged in, discarding.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -341,18 +346,18 @@ void Client::Handle_Play(const char* data)
|
||||
|
||||
if(server.options.IsTraceOn())
|
||||
{
|
||||
server_log->Log(log_network, "Play received from client, server number %u sequence %u.", server_id_in, sequence_in);
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Play received from client, server number %u sequence %u.", server_id_in, sequence_in);
|
||||
}
|
||||
|
||||
this->play_server_id = (unsigned int)play->ServerNumber;
|
||||
play_sequence_id = sequence_in;
|
||||
play_server_id = server_id_in;
|
||||
server.SM->SendUserToWorldRequest(server_id_in, account_id);
|
||||
server.server_manager->SendUserToWorldRequest(server_id_in, account_id);
|
||||
}
|
||||
|
||||
void Client::SendServerListPacket()
|
||||
{
|
||||
EQApplicationPacket *outapp = server.SM->CreateServerListPacket(this);
|
||||
EQApplicationPacket *outapp = server.server_manager->CreateServerListPacket(this);
|
||||
|
||||
if(server.options.IsDumpOutPacketsOn())
|
||||
{
|
||||
@@ -367,8 +372,8 @@ void Client::SendPlayResponse(EQApplicationPacket *outapp)
|
||||
{
|
||||
if(server.options.IsTraceOn())
|
||||
{
|
||||
server_log->Log(log_network_trace, "Sending play response for %s.", GetAccountName().c_str());
|
||||
server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size);
|
||||
Log.Out(Logs::General, Logs::Netcode, "Sending play response for %s.", GetAccountName().c_str());
|
||||
// server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size);
|
||||
}
|
||||
connection->QueuePacket(outapp);
|
||||
status = cs_logged_in;
|
||||
@@ -378,7 +383,7 @@ void Client::GenerateKey()
|
||||
{
|
||||
key.clear();
|
||||
int count = 0;
|
||||
while(count < 10)
|
||||
while (count < 10)
|
||||
{
|
||||
static const char key_selection[] =
|
||||
{
|
||||
|
||||
@@ -16,13 +16,14 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "client_manager.h"
|
||||
#include "error_log.h"
|
||||
#include "login_server.h"
|
||||
|
||||
extern ErrorLog *server_log;
|
||||
extern LoginServer server;
|
||||
extern bool run_server;
|
||||
|
||||
#include "../common/eqemu_logsys.h"
|
||||
extern EQEmuLogSys Log;
|
||||
|
||||
ClientManager::ClientManager()
|
||||
{
|
||||
int titanium_port = atoi(server.config->GetVariable("Titanium", "port").c_str());
|
||||
@@ -30,18 +31,18 @@ ClientManager::ClientManager()
|
||||
titanium_ops = new RegularOpcodeManager;
|
||||
if(!titanium_ops->LoadOpcodes(server.config->GetVariable("Titanium", "opcodes").c_str()))
|
||||
{
|
||||
server_log->Log(log_error, "ClientManager fatal error: couldn't load opcodes for Titanium file %s.",
|
||||
Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't load opcodes for Titanium file %s.",
|
||||
server.config->GetVariable("Titanium", "opcodes").c_str());
|
||||
run_server = false;
|
||||
}
|
||||
|
||||
if(titanium_stream->Open())
|
||||
{
|
||||
server_log->Log(log_network, "ClientManager listening on Titanium stream.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "ClientManager listening on Titanium stream.");
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_error, "ClientManager fatal error: couldn't open Titanium stream.");
|
||||
Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't open Titanium stream.");
|
||||
run_server = false;
|
||||
}
|
||||
|
||||
@@ -50,18 +51,18 @@ ClientManager::ClientManager()
|
||||
sod_ops = new RegularOpcodeManager;
|
||||
if(!sod_ops->LoadOpcodes(server.config->GetVariable("SoD", "opcodes").c_str()))
|
||||
{
|
||||
server_log->Log(log_error, "ClientManager fatal error: couldn't load opcodes for SoD file %s.",
|
||||
Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't load opcodes for SoD file %s.",
|
||||
server.config->GetVariable("SoD", "opcodes").c_str());
|
||||
run_server = false;
|
||||
}
|
||||
|
||||
if(sod_stream->Open())
|
||||
{
|
||||
server_log->Log(log_network, "ClientManager listening on SoD stream.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "ClientManager listening on SoD stream.");
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_error, "ClientManager fatal error: couldn't open SoD stream.");
|
||||
Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't open SoD stream.");
|
||||
run_server = false;
|
||||
}
|
||||
}
|
||||
@@ -99,7 +100,7 @@ void ClientManager::Process()
|
||||
{
|
||||
struct in_addr in;
|
||||
in.s_addr = cur->GetRemoteIP();
|
||||
server_log->Log(log_network, "New Titanium client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort()));
|
||||
Log.Out(Logs::General, Logs::Login_Server, "New Titanium client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort()));
|
||||
|
||||
cur->SetOpcodeManager(&titanium_ops);
|
||||
Client *c = new Client(cur, cv_titanium);
|
||||
@@ -112,7 +113,7 @@ void ClientManager::Process()
|
||||
{
|
||||
struct in_addr in;
|
||||
in.s_addr = cur->GetRemoteIP();
|
||||
server_log->Log(log_network, "New SoD client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort()));
|
||||
Log.Out(Logs::General, Logs::Login_Server, "New SoD client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort()));
|
||||
|
||||
cur->SetOpcodeManager(&sod_ops);
|
||||
Client *c = new Client(cur, cv_sod);
|
||||
@@ -125,7 +126,7 @@ void ClientManager::Process()
|
||||
{
|
||||
if((*iter)->Process() == false)
|
||||
{
|
||||
server_log->Log(log_client, "Client had a fatal error and had to be removed from the login.");
|
||||
Log.Out(Logs::General, Logs::Debug, "Client had a fatal error and had to be removed from the login.");
|
||||
delete (*iter);
|
||||
iter = clients.erase(iter);
|
||||
}
|
||||
@@ -144,7 +145,7 @@ void ClientManager::ProcessDisconnect()
|
||||
std::shared_ptr<EQStream> c = (*iter)->GetConnection();
|
||||
if(c->CheckClosed())
|
||||
{
|
||||
server_log->Log(log_network, "Client disconnected from the server, removing client.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Client disconnected from the server, removing client.");
|
||||
delete (*iter);
|
||||
iter = clients.erase(iter);
|
||||
}
|
||||
@@ -172,7 +173,7 @@ void ClientManager::RemoveExistingClient(unsigned int account_id)
|
||||
{
|
||||
if((*iter)->GetAccountID() == account_id)
|
||||
{
|
||||
server_log->Log(log_network, "Client attempting to log in and existing client already logged in, removing existing client.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Client attempting to log in and existing client already logged in, removing existing client.");
|
||||
delete (*iter);
|
||||
iter = clients.erase(iter);
|
||||
}
|
||||
@@ -200,7 +201,7 @@ Client *ClientManager::GetClient(unsigned int account_id)
|
||||
|
||||
if(count > 1)
|
||||
{
|
||||
server_log->Log(log_client_error, "More than one client with a given account_id existed in the client list.");
|
||||
Log.Out(Logs::General, Logs::Error, "More than one client with a given account_id existed in the client list.");
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "../common/global_define.h"
|
||||
#include "../common/eqemu_logsys.h"
|
||||
#include "config.h"
|
||||
#include "error_log.h"
|
||||
|
||||
extern ErrorLog *server_log;
|
||||
extern EQEmuLogSys Log;
|
||||
/**
|
||||
* Retrieves the variable we want from our title or theme
|
||||
* First gets the map from the title
|
||||
@@ -48,7 +48,7 @@ void Config::Parse(const char *file_name)
|
||||
{
|
||||
if(file_name == nullptr)
|
||||
{
|
||||
server_log->Log(log_error, "Config::Parse(), file_name passed was null.");
|
||||
Log.Out(Logs::General, Logs::Error, "Config::Parse(), file_name passed was null.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ void Config::Parse(const char *file_name)
|
||||
++iter;
|
||||
if(iter == tokens.end())
|
||||
{
|
||||
server_log->Log(log_error, "Config::Parse(), EOF before title done parsing.");
|
||||
Log.Out(Logs::General, Logs::Error, "Config::Parse(), EOF before title done parsing.");
|
||||
fclose(input);
|
||||
vars.clear();
|
||||
return;
|
||||
@@ -104,7 +104,7 @@ void Config::Parse(const char *file_name)
|
||||
mode++;
|
||||
if((*iter).compare("=") != 0)
|
||||
{
|
||||
server_log->Log(log_error, "Config::Parse(), invalid parse token where = should be.");
|
||||
Log.Out(Logs::General, Logs::Error, "Config::Parse(), invalid parse token where = should be.");
|
||||
fclose(input);
|
||||
vars.clear();
|
||||
return;
|
||||
@@ -133,7 +133,7 @@ void Config::Parse(const char *file_name)
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_error, "Config::Parse(), file was unable to be opened for parsing.");
|
||||
Log.Out(Logs::General, Logs::Error, "Config::Parse(), file was unable to be opened for parsing.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,8 @@ public:
|
||||
*/
|
||||
virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id) { return false; }
|
||||
|
||||
virtual bool CreateLoginData(std::string name, std::string &password, unsigned int &id) { return false; }
|
||||
|
||||
/**
|
||||
* Retrieves the world registration from the long and short names provided.
|
||||
* Needed for world login procedure.
|
||||
|
||||
@@ -20,14 +20,12 @@
|
||||
|
||||
#ifdef EQEMU_MYSQL_ENABLED
|
||||
#include "database_mysql.h"
|
||||
#include "error_log.h"
|
||||
#include "login_server.h"
|
||||
#include "../common/eqemu_logsys.h"
|
||||
|
||||
extern ErrorLog *server_log;
|
||||
extern EQEmuLogSys Log;
|
||||
extern LoginServer server;
|
||||
|
||||
#pragma comment(lib, "mysqlclient.lib")
|
||||
|
||||
DatabaseMySQL::DatabaseMySQL(string user, string pass, string host, string port, string name)
|
||||
{
|
||||
this->user = user;
|
||||
@@ -35,35 +33,35 @@ DatabaseMySQL::DatabaseMySQL(string user, string pass, string host, string port,
|
||||
this->host = host;
|
||||
this->name = name;
|
||||
|
||||
db = mysql_init(nullptr);
|
||||
if(db)
|
||||
database = mysql_init(nullptr);
|
||||
if(database)
|
||||
{
|
||||
my_bool r = 1;
|
||||
mysql_options(db, MYSQL_OPT_RECONNECT, &r);
|
||||
if(!mysql_real_connect(db, host.c_str(), user.c_str(), pass.c_str(), name.c_str(), atoi(port.c_str()), nullptr, 0))
|
||||
mysql_options(database, MYSQL_OPT_RECONNECT, &r);
|
||||
if(!mysql_real_connect(database, host.c_str(), user.c_str(), pass.c_str(), name.c_str(), atoi(port.c_str()), nullptr, 0))
|
||||
{
|
||||
mysql_close(db);
|
||||
server_log->Log(log_database, "Failed to connect to MySQL database. Error: %s", mysql_error(db));
|
||||
mysql_close(database);
|
||||
Log.Out(Logs::General, Logs::Error, "Failed to connect to MySQL database. Error: %s", mysql_error(database));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_database, "Failed to create db object in MySQL database.");
|
||||
Log.Out(Logs::General, Logs::Error, "Failed to create db object in MySQL database.");
|
||||
}
|
||||
}
|
||||
|
||||
DatabaseMySQL::~DatabaseMySQL()
|
||||
{
|
||||
if(db)
|
||||
if(database)
|
||||
{
|
||||
mysql_close(db);
|
||||
mysql_close(database);
|
||||
}
|
||||
}
|
||||
|
||||
bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, unsigned int &id)
|
||||
{
|
||||
if(!db)
|
||||
if (!database)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -75,17 +73,17 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u
|
||||
query << name;
|
||||
query << "'";
|
||||
|
||||
if(mysql_query(db, query.str().c_str()) != 0)
|
||||
if (mysql_query(database, query.str().c_str()) != 0)
|
||||
{
|
||||
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
|
||||
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
res = mysql_use_result(db);
|
||||
res = mysql_use_result(database);
|
||||
|
||||
if(res)
|
||||
if (res)
|
||||
{
|
||||
while((row = mysql_fetch_row(res)) != nullptr)
|
||||
while ((row = mysql_fetch_row(res)) != nullptr)
|
||||
{
|
||||
id = atoi(row[0]);
|
||||
password = row[1];
|
||||
@@ -94,14 +92,41 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u
|
||||
}
|
||||
}
|
||||
|
||||
server_log->Log(log_database, "Mysql query returned no result: %s", query.str().c_str());
|
||||
Log.Out(Logs::General, Logs::Error, "Mysql query returned no result: %s", query.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool DatabaseMySQL::CreateLoginData(string name, string &password, unsigned int &id)
|
||||
{
|
||||
if (!database) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
stringstream query(stringstream::in | stringstream::out);
|
||||
|
||||
query << "INSERT INTO " << server.options.GetAccountTable() << " (AccountName, AccountPassword, AccountEmail, LastLoginDate, LastIPAddress) ";
|
||||
query << " VALUES('" << name << "', '" << password << "', 'local_creation', NOW(), '127.0.0.1'); ";
|
||||
|
||||
if (mysql_query(database, query.str().c_str()) != 0) {
|
||||
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
id = mysql_insert_id(database);
|
||||
return true;
|
||||
}
|
||||
|
||||
Log.Out(Logs::General, Logs::Error, "Mysql query returned no result: %s", query.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, unsigned int &id, string &desc, unsigned int &list_id,
|
||||
unsigned int &trusted, string &list_desc, string &account, string &password)
|
||||
unsigned int &trusted, string &list_desc, string &account, string &password)
|
||||
{
|
||||
if(!db)
|
||||
if (!database)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -110,26 +135,26 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
|
||||
MYSQL_ROW row;
|
||||
char escaped_short_name[101];
|
||||
unsigned long length;
|
||||
length = mysql_real_escape_string(db, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
|
||||
escaped_short_name[length+1] = 0;
|
||||
length = mysql_real_escape_string(database, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
|
||||
escaped_short_name[length + 1] = 0;
|
||||
stringstream query(stringstream::in | stringstream::out);
|
||||
query << "SELECT WSR.ServerID, WSR.ServerTagDescription, WSR.ServerTrusted, SLT.ServerListTypeID, ";
|
||||
query << "SLT.ServerListTypeDescription, WSR.ServerAdminID FROM " << server.options.GetWorldRegistrationTable();
|
||||
query << "SELECT ifnull(WSR.ServerID,999999) AS ServerID, WSR.ServerTagDescription, ifnull(WSR.ServerTrusted,0) AS ServerTrusted, ifnull(SLT.ServerListTypeID,3) AS ServerListTypeID, ";
|
||||
query << "SLT.ServerListTypeDescription, ifnull(WSR.ServerAdminID,0) AS ServerAdminID FROM " << server.options.GetWorldRegistrationTable();
|
||||
query << " AS WSR JOIN " << server.options.GetWorldServerTypeTable() << " AS SLT ON WSR.ServerListTypeID = SLT.ServerListTypeID";
|
||||
query << " WHERE WSR.ServerShortName = '";
|
||||
query << escaped_short_name;
|
||||
query << "'";
|
||||
|
||||
if(mysql_query(db, query.str().c_str()) != 0)
|
||||
if (mysql_query(database, query.str().c_str()) != 0)
|
||||
{
|
||||
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
|
||||
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
res = mysql_use_result(db);
|
||||
if(res)
|
||||
res = mysql_use_result(database);
|
||||
if (res)
|
||||
{
|
||||
if((row = mysql_fetch_row(res)) != nullptr)
|
||||
if ((row = mysql_fetch_row(res)) != nullptr)
|
||||
{
|
||||
id = atoi(row[0]);
|
||||
desc = row[1];
|
||||
@@ -139,22 +164,22 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
|
||||
int db_account_id = atoi(row[5]);
|
||||
mysql_free_result(res);
|
||||
|
||||
if(db_account_id > 0)
|
||||
if (db_account_id > 0)
|
||||
{
|
||||
stringstream query(stringstream::in | stringstream::out);
|
||||
query << "SELECT AccountName, AccountPassword FROM " << server.options.GetWorldAdminRegistrationTable();
|
||||
query << " WHERE ServerAdminID = " << db_account_id;
|
||||
|
||||
if(mysql_query(db, query.str().c_str()) != 0)
|
||||
if (mysql_query(database, query.str().c_str()) != 0)
|
||||
{
|
||||
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
|
||||
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
res = mysql_use_result(db);
|
||||
if(res)
|
||||
res = mysql_use_result(database);
|
||||
if (res)
|
||||
{
|
||||
if((row = mysql_fetch_row(res)) != nullptr)
|
||||
if ((row = mysql_fetch_row(res)) != nullptr)
|
||||
{
|
||||
account = row[0];
|
||||
password = row[1];
|
||||
@@ -163,20 +188,20 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
|
||||
}
|
||||
}
|
||||
|
||||
server_log->Log(log_database, "Mysql query returned no result: %s", query.str().c_str());
|
||||
Log.Out(Logs::General, Logs::Error, "Mysql query returned no result: %s", query.str().c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
server_log->Log(log_database, "Mysql query returned no result: %s", query.str().c_str());
|
||||
Log.Out(Logs::General, Logs::Error, "Mysql query returned no result: %s", query.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address)
|
||||
{
|
||||
if(!db)
|
||||
if (!database)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -187,15 +212,15 @@ void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address)
|
||||
query << "', LastLoginDate = now() where LoginServerID = ";
|
||||
query << id;
|
||||
|
||||
if(mysql_query(db, query.str().c_str()) != 0)
|
||||
if (mysql_query(database, query.str().c_str()) != 0)
|
||||
{
|
||||
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
|
||||
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string password, string email)
|
||||
{
|
||||
if(!db)
|
||||
if (!database)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -206,23 +231,23 @@ void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string pas
|
||||
query << password << "'), AccountCreateDate = now(), AccountEmail = '" << email;
|
||||
query << "', LastIPAddress = '0.0.0.0', LastLoginDate = now()";
|
||||
|
||||
if(mysql_query(db, query.str().c_str()) != 0)
|
||||
if (mysql_query(database, query.str().c_str()) != 0)
|
||||
{
|
||||
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
|
||||
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, string ip_address)
|
||||
{
|
||||
if(!db)
|
||||
if (!database)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char escaped_long_name[101];
|
||||
unsigned long length;
|
||||
length = mysql_real_escape_string(db, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length());
|
||||
escaped_long_name[length+1] = 0;
|
||||
length = mysql_real_escape_string(database, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length());
|
||||
escaped_long_name[length + 1] = 0;
|
||||
stringstream query(stringstream::in | stringstream::out);
|
||||
query << "UPDATE " << server.options.GetWorldRegistrationTable() << " SET ServerLastLoginDate = now(), ServerLastIPAddr = '";
|
||||
query << ip_address;
|
||||
@@ -231,15 +256,15 @@ void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, s
|
||||
query << "' WHERE ServerID = ";
|
||||
query << id;
|
||||
|
||||
if(mysql_query(db, query.str().c_str()) != 0)
|
||||
if (mysql_query(database, query.str().c_str()) != 0)
|
||||
{
|
||||
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
|
||||
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name, unsigned int &id)
|
||||
{
|
||||
if(!db)
|
||||
if (!database)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -249,23 +274,23 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name,
|
||||
char escaped_long_name[201];
|
||||
char escaped_short_name[101];
|
||||
unsigned long length;
|
||||
length = mysql_real_escape_string(db, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length());
|
||||
escaped_long_name[length+1] = 0;
|
||||
length = mysql_real_escape_string(db, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
|
||||
escaped_short_name[length+1] = 0;
|
||||
length = mysql_real_escape_string(database, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length());
|
||||
escaped_long_name[length + 1] = 0;
|
||||
length = mysql_real_escape_string(database, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
|
||||
escaped_short_name[length + 1] = 0;
|
||||
stringstream query(stringstream::in | stringstream::out);
|
||||
query << "SELECT max(ServerID) FROM " << server.options.GetWorldRegistrationTable();
|
||||
query << "SELECT ifnull(max(ServerID),0) FROM " << server.options.GetWorldRegistrationTable();
|
||||
|
||||
if(mysql_query(db, query.str().c_str()) != 0)
|
||||
if (mysql_query(database, query.str().c_str()) != 0)
|
||||
{
|
||||
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
|
||||
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
res = mysql_use_result(db);
|
||||
if(res)
|
||||
res = mysql_use_result(database);
|
||||
if (res)
|
||||
{
|
||||
if((row = mysql_fetch_row(res)) != nullptr)
|
||||
if ((row = mysql_fetch_row(res)) != nullptr)
|
||||
{
|
||||
id = atoi(row[0]) + 1;
|
||||
mysql_free_result(res);
|
||||
@@ -275,15 +300,15 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name,
|
||||
query << ", ServerLongName = '" << escaped_long_name << "', ServerShortName = '" << escaped_short_name;
|
||||
query << "', ServerListTypeID = 3, ServerAdminID = 0, ServerTrusted = 0, ServerTagDescription = ''";
|
||||
|
||||
if(mysql_query(db, query.str().c_str()) != 0)
|
||||
if (mysql_query(database, query.str().c_str()) != 0)
|
||||
{
|
||||
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
|
||||
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
server_log->Log(log_database, "World registration did not exist in the database for %s %s", long_name.c_str(), short_name.c_str());
|
||||
Log.Out(Logs::General, Logs::Error, "World registration did not exist in the database for %s %s", long_name.c_str(), short_name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
/**
|
||||
* Constructor, sets our database to null.
|
||||
*/
|
||||
DatabaseMySQL() { db = nullptr; }
|
||||
DatabaseMySQL() { database = nullptr; }
|
||||
|
||||
/**
|
||||
* Constructor, tries to set our database to connect to the supplied options.
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
/**
|
||||
* @return Returns true if the database successfully connected.
|
||||
*/
|
||||
virtual bool IsConnected() { return (db != nullptr); }
|
||||
virtual bool IsConnected() { return (database != nullptr); }
|
||||
|
||||
/**
|
||||
* Retrieves the login data (password hash and account id) from the account name provided
|
||||
@@ -59,6 +59,8 @@ public:
|
||||
*/
|
||||
virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id);
|
||||
|
||||
virtual bool CreateLoginData(std::string name, std::string &password, unsigned int &id);
|
||||
|
||||
/**
|
||||
* Retrieves the world registration from the long and short names provided.
|
||||
* Needed for world login procedure.
|
||||
@@ -88,7 +90,7 @@ public:
|
||||
virtual bool CreateWorldRegistration(std::string long_name, std::string short_name, unsigned int &id);
|
||||
protected:
|
||||
std::string user, pass, host, port, name;
|
||||
MYSQL *db;
|
||||
MYSQL *database;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "error_log.h"
|
||||
#include "login_server.h"
|
||||
|
||||
extern ErrorLog *server_log;
|
||||
|
||||
extern LoginServer server;
|
||||
|
||||
#pragma comment(lib, "libpq.lib")
|
||||
@@ -34,12 +34,12 @@ DatabasePostgreSQL::DatabasePostgreSQL(string user, string pass, string host, st
|
||||
db = PQsetdbLogin(host.c_str(), port.c_str(), nullptr, nullptr, name.c_str(), user.c_str(), pass.c_str());
|
||||
if(!db)
|
||||
{
|
||||
server_log->Log(log_database, "Failed to connect to PostgreSQL Database.");
|
||||
Log.Out(Logs::General, Logs::Error, "Failed to connect to PostgreSQL Database.");
|
||||
}
|
||||
|
||||
if(PQstatus(db) != CONNECTION_OK)
|
||||
{
|
||||
server_log->Log(log_database, "Failed to connect to PostgreSQL Database.");
|
||||
Log.Out(Logs::General, Logs::Error, "Failed to connect to PostgreSQL Database.");
|
||||
PQfinish(db);
|
||||
db = nullptr;
|
||||
}
|
||||
@@ -83,7 +83,7 @@ bool DatabasePostgreSQL::GetLoginDataFromAccountName(string name, string &passwo
|
||||
char *error = PQresultErrorMessage(res);
|
||||
if(strlen(error) > 0)
|
||||
{
|
||||
server_log->Log(log_database, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
|
||||
Log.Out(Logs::General, Logs::Error, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
|
||||
PQclear(res);
|
||||
return false;
|
||||
}
|
||||
@@ -135,7 +135,7 @@ bool DatabasePostgreSQL::GetWorldRegistration(string long_name, string short_nam
|
||||
char *error = PQresultErrorMessage(res);
|
||||
if(strlen(error) > 0)
|
||||
{
|
||||
server_log->Log(log_database, "Database error in DatabasePostgreSQL::GetWorldRegistration(): %s", error);
|
||||
Log.Out(Logs::General, Logs::Error, "Database error in DatabasePostgreSQL::GetWorldRegistration(): %s", error);
|
||||
PQclear(res);
|
||||
return false;
|
||||
}
|
||||
@@ -188,7 +188,7 @@ void DatabasePostgreSQL::UpdateLSAccountData(unsigned int id, string ip_address)
|
||||
char *error = PQresultErrorMessage(res);
|
||||
if(strlen(error) > 0)
|
||||
{
|
||||
server_log->Log(log_database, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
|
||||
Log.Out(Logs::General, Logs::Error, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
|
||||
}
|
||||
PQclear(res);
|
||||
}
|
||||
@@ -225,7 +225,7 @@ void DatabasePostgreSQL::UpdateWorldRegistration(unsigned int id, string long_na
|
||||
char *error = PQresultErrorMessage(res);
|
||||
if(strlen(error) > 0)
|
||||
{
|
||||
server_log->Log(log_database, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
|
||||
Log.Out(Logs::General, Logs::Error, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
|
||||
}
|
||||
PQclear(res);
|
||||
}
|
||||
|
||||
@@ -17,16 +17,16 @@
|
||||
*/
|
||||
#include "../common/global_define.h"
|
||||
#include "encryption.h"
|
||||
#include "error_log.h"
|
||||
#include <string>
|
||||
|
||||
extern ErrorLog *server_log;
|
||||
#include "../common/eqemu_logsys.h"
|
||||
extern EQEmuLogSys Log;
|
||||
|
||||
bool Encryption::LoadCrypto(std::string name)
|
||||
{
|
||||
if(!Load(name.c_str()))
|
||||
{
|
||||
server_log->Log(log_error, "Failed to load %s from the operating system.", name.c_str());
|
||||
Log.Out(Logs::General, Logs::Error, "Failed to load %s from the operating system.", name.c_str());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
@@ -34,21 +34,21 @@ bool Encryption::LoadCrypto(std::string name)
|
||||
encrypt_func = (DLLFUNC_Encrypt)GetSym("Encrypt");
|
||||
if(encrypt_func == NULL)
|
||||
{
|
||||
server_log->Log(log_error, "Failed to attach Encrypt.");
|
||||
Log.Out(Logs::General, Logs::Error, "Failed to attach Encrypt.");
|
||||
Unload();
|
||||
return false;
|
||||
}
|
||||
decrypt_func = (DLLFUNC_DecryptUsernamePassword)GetSym("DecryptUsernamePassword");
|
||||
if(decrypt_func == NULL)
|
||||
{
|
||||
server_log->Log(log_error, "Failed to attach DecryptUsernamePassword.");
|
||||
Log.Out(Logs::General, Logs::Error, "Failed to attach DecryptUsernamePassword.");
|
||||
Unload();
|
||||
return false;
|
||||
}
|
||||
delete_func = (DLLFUNC_HeapDelete)GetSym("_HeapDeleteCharBuffer");
|
||||
if(delete_func == NULL)
|
||||
{
|
||||
server_log->Log(log_error, "Failed to attach _HeapDeleteCharBuffer.");
|
||||
Log.Out(Logs::General, Logs::Error, "Failed to attach _HeapDeleteCharBuffer.");
|
||||
Unload();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2010 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "error_log.h"
|
||||
|
||||
const char *eqLogTypes[_log_largest_type] =
|
||||
{
|
||||
"Debug",
|
||||
"Error",
|
||||
"Database",
|
||||
"Network",
|
||||
"Network Trace",
|
||||
"Network Error",
|
||||
"World",
|
||||
"World Error",
|
||||
"Client",
|
||||
"Client Error"
|
||||
};
|
||||
|
||||
ErrorLog::ErrorLog(const char* file_name)
|
||||
{
|
||||
log_mutex = new Mutex();
|
||||
error_log = fopen(file_name, "w");
|
||||
}
|
||||
|
||||
ErrorLog::~ErrorLog()
|
||||
{
|
||||
log_mutex->lock();
|
||||
if(error_log)
|
||||
{
|
||||
fclose(error_log);
|
||||
}
|
||||
log_mutex->unlock();
|
||||
delete log_mutex;
|
||||
}
|
||||
|
||||
void ErrorLog::Log(eqLogType type, const char *message, ...)
|
||||
{
|
||||
if(type >= _log_largest_type)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
va_list argptr;
|
||||
char *buffer = new char[4096];
|
||||
va_start(argptr, message);
|
||||
vsnprintf(buffer, 4096, message, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
time_t m_clock;
|
||||
struct tm *m_time;
|
||||
time(&m_clock);
|
||||
m_time = localtime(&m_clock);
|
||||
|
||||
log_mutex->lock();
|
||||
printf("[%s] [%02d.%02d.%02d - %02d:%02d:%02d] %s\n",
|
||||
eqLogTypes[type],
|
||||
m_time->tm_mon+1,
|
||||
m_time->tm_mday,
|
||||
m_time->tm_year%100,
|
||||
m_time->tm_hour,
|
||||
m_time->tm_min,
|
||||
m_time->tm_sec,
|
||||
buffer);
|
||||
|
||||
if(error_log)
|
||||
{
|
||||
fprintf(error_log, "[%s] [%02d.%02d.%02d - %02d:%02d:%02d] %s\n",
|
||||
eqLogTypes[type],
|
||||
m_time->tm_mon+1,
|
||||
m_time->tm_mday,
|
||||
m_time->tm_year%100,
|
||||
m_time->tm_hour,
|
||||
m_time->tm_min,
|
||||
m_time->tm_sec,
|
||||
buffer);
|
||||
fflush(error_log);
|
||||
}
|
||||
|
||||
log_mutex->unlock();
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
void ErrorLog::LogPacket(eqLogType type, const char *data, size_t size)
|
||||
{
|
||||
if(type >= _log_largest_type)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
log_mutex->lock();
|
||||
time_t m_clock;
|
||||
struct tm *m_time;
|
||||
time(&m_clock);
|
||||
m_time = localtime(&m_clock);
|
||||
|
||||
log_mutex->lock();
|
||||
printf("[%s] [%02d.%02d.%02d - %02d:%02d:%02d] dumping packet of size %u:\n",
|
||||
eqLogTypes[type],
|
||||
m_time->tm_mon+1,
|
||||
m_time->tm_mday,
|
||||
m_time->tm_year%100,
|
||||
m_time->tm_hour,
|
||||
m_time->tm_min,
|
||||
m_time->tm_sec,
|
||||
(unsigned int)size);
|
||||
|
||||
if(error_log)
|
||||
{
|
||||
fprintf(error_log, "[%s] [%02d.%02d.%02d - %02d:%02d:%02d] dumping packet of size %u\n",
|
||||
eqLogTypes[type],
|
||||
m_time->tm_mon+1,
|
||||
m_time->tm_mday,
|
||||
m_time->tm_year%100,
|
||||
m_time->tm_hour,
|
||||
m_time->tm_min,
|
||||
m_time->tm_sec,
|
||||
(unsigned int)size);
|
||||
}
|
||||
|
||||
char ascii[17]; //16 columns + 1 null term
|
||||
memset(ascii, 0, 17);
|
||||
|
||||
size_t j = 0;
|
||||
size_t i = 0;
|
||||
for(; i < size; ++i)
|
||||
{
|
||||
if(i % 16 == 0)
|
||||
{
|
||||
if(i != 0)
|
||||
{
|
||||
printf(" | %s\n", ascii);
|
||||
if(error_log)
|
||||
{
|
||||
fprintf(error_log, " | %s\n", ascii);
|
||||
}
|
||||
}
|
||||
printf("%.4u: ", (unsigned int)i);
|
||||
memset(ascii, 0, 17);
|
||||
j = 0;
|
||||
}
|
||||
else if(i % 8 == 0)
|
||||
{
|
||||
printf("- ");
|
||||
if(error_log)
|
||||
{
|
||||
fprintf(error_log, "- ");
|
||||
}
|
||||
}
|
||||
|
||||
printf("%02X ", (unsigned int)data[i]);
|
||||
if(error_log)
|
||||
{
|
||||
fprintf(error_log, "%02X ", (unsigned int)data[i]);
|
||||
}
|
||||
|
||||
if(data[i] >= 32 && data[i] < 127)
|
||||
{
|
||||
ascii[j++] = data[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
ascii[j++] = '.';
|
||||
}
|
||||
}
|
||||
|
||||
size_t k = (i - 1) % 16;
|
||||
if(k < 8)
|
||||
{
|
||||
printf(" ");
|
||||
if(error_log)
|
||||
{
|
||||
fprintf(error_log, " ");
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t h = k + 1; h < 16; ++h)
|
||||
{
|
||||
printf(" ");
|
||||
if(error_log)
|
||||
{
|
||||
fprintf(error_log, " ");
|
||||
}
|
||||
}
|
||||
|
||||
printf(" | %s\n", ascii);
|
||||
if(error_log)
|
||||
{
|
||||
fprintf(error_log, " | %s\n", ascii);
|
||||
fflush(error_log);
|
||||
}
|
||||
|
||||
log_mutex->unlock();
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2010 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef EQEMU_ERROR_LOG_H
|
||||
#define EQEMU_ERROR_LOG_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <string>
|
||||
|
||||
#include "../common/mutex.h"
|
||||
|
||||
/**
|
||||
* Dictates the log type specified in ErrorLog for Log(...)
|
||||
*/
|
||||
enum eqLogType
|
||||
{
|
||||
log_debug,
|
||||
log_error,
|
||||
log_database,
|
||||
log_network,
|
||||
log_network_trace,
|
||||
log_network_error,
|
||||
log_world,
|
||||
log_world_error,
|
||||
log_client,
|
||||
log_client_error,
|
||||
_log_largest_type
|
||||
};
|
||||
|
||||
/**
|
||||
* Basic error logging class.
|
||||
* Thread safe logging class that records time and date to both a file and to console(if exists).
|
||||
*/
|
||||
class ErrorLog
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor: opens the log file for writing and creates our mutex for writing to the log.
|
||||
*/
|
||||
ErrorLog(const char* file_name);
|
||||
|
||||
/**
|
||||
* Closes the file and destroys the mutex.
|
||||
*/
|
||||
~ErrorLog();
|
||||
|
||||
/**
|
||||
* Writes to the log system a variable message.
|
||||
*/
|
||||
void Log(eqLogType type, const char *message, ...);
|
||||
|
||||
/**
|
||||
* Writes to the log system a packet.
|
||||
*/
|
||||
void LogPacket(eqLogType type, const char *data, size_t size);
|
||||
|
||||
protected:
|
||||
Mutex *log_mutex;
|
||||
FILE* error_log;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#ifndef EQEMU_LOGINSERVER_H
|
||||
#define EQEMU_LOGINSERVER_H
|
||||
|
||||
#include "error_log.h"
|
||||
#include "config.h"
|
||||
#include "database.h"
|
||||
#include "database_mysql.h"
|
||||
@@ -40,7 +39,7 @@ public:
|
||||
* but it's the most trivial way to do this.
|
||||
*/
|
||||
#ifdef WIN32
|
||||
LoginServer() : config(nullptr), db(nullptr), eq_crypto(nullptr), SM(nullptr) { }
|
||||
LoginServer() : config(nullptr), db(nullptr), eq_crypto(nullptr), server_manager(nullptr) { }
|
||||
#else
|
||||
LoginServer() : config(nullptr), db(nullptr) { }
|
||||
#endif
|
||||
@@ -48,8 +47,8 @@ public:
|
||||
Config *config;
|
||||
Database *db;
|
||||
Options options;
|
||||
ServerManager *SM;
|
||||
ClientManager *CM;
|
||||
ServerManager *server_manager;
|
||||
ClientManager *client_manager;
|
||||
|
||||
#ifdef WIN32
|
||||
Encryption *eq_crypto;
|
||||
|
||||
@@ -38,7 +38,7 @@ struct LoginLoginRequest_Struct {
|
||||
char unknown6[16];
|
||||
};
|
||||
|
||||
struct LoginLoginAccepted_Struct {
|
||||
struct LoginAccepted_Struct {
|
||||
short unknown1;
|
||||
short unknown2;
|
||||
short unknown3;
|
||||
@@ -47,7 +47,7 @@ struct LoginLoginAccepted_Struct {
|
||||
char encrypt[80];
|
||||
};
|
||||
|
||||
struct Login_ReplyBlock_Struct
|
||||
struct LoginFailedAttempts_Struct
|
||||
{
|
||||
char message; //0x01
|
||||
char unknown2[7]; //0x00
|
||||
|
||||
+79
-133
@@ -32,7 +32,6 @@
|
||||
TimeoutManager timeout_manager;
|
||||
LoginServer server;
|
||||
EQEmuLogSys Log;
|
||||
ErrorLog *server_log;
|
||||
bool run_server = true;
|
||||
|
||||
void CatchSignal(int sig_num)
|
||||
@@ -43,106 +42,63 @@ int main()
|
||||
{
|
||||
RegisterExecutablePlatform(ExePlatformLogin);
|
||||
set_exception_handler();
|
||||
Log.LoadLogSettingsDefaults();
|
||||
|
||||
//Create our error log, is of format login_<number>.log
|
||||
time_t current_time = time(nullptr);
|
||||
std::stringstream log_name(std::stringstream::in | std::stringstream::out);
|
||||
#ifdef WIN32
|
||||
log_name << ".\\logs\\login_" << (unsigned int)current_time << ".log";
|
||||
#else
|
||||
log_name << "./logs/login_" << (unsigned int)current_time << ".log";
|
||||
#endif
|
||||
server_log = new ErrorLog(log_name.str().c_str());
|
||||
server_log->Log(log_debug, "Logging System Init.");
|
||||
Log.log_settings[Logs::Error].log_to_console = Logs::General;
|
||||
|
||||
//Create our subsystem and parse the ini file.
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Logging System Init.");
|
||||
|
||||
/* Parse out login.ini */
|
||||
server.config = new Config();
|
||||
server_log->Log(log_debug, "Config System Init.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Config System Init.");
|
||||
server.config->Parse("login.ini");
|
||||
|
||||
//Parse unregistered allowed option.
|
||||
if(server.config->GetVariable("options", "unregistered_allowed").compare("FALSE") == 0)
|
||||
{
|
||||
if (server.config->GetVariable("options", "unregistered_allowed").compare("FALSE") == 0)
|
||||
server.options.AllowUnregistered(false);
|
||||
}
|
||||
|
||||
//Parse trace option.
|
||||
if(server.config->GetVariable("options", "trace").compare("TRUE") == 0)
|
||||
{
|
||||
if (server.config->GetVariable("options", "trace").compare("TRUE") == 0)
|
||||
server.options.Trace(true);
|
||||
}
|
||||
|
||||
//Parse trace option.
|
||||
if(server.config->GetVariable("options", "world_trace").compare("TRUE") == 0)
|
||||
{
|
||||
if (server.config->GetVariable("options", "world_trace").compare("TRUE") == 0)
|
||||
server.options.WorldTrace(true);
|
||||
}
|
||||
|
||||
//Parse packet inc dump option.
|
||||
if(server.config->GetVariable("options", "dump_packets_in").compare("TRUE") == 0)
|
||||
{
|
||||
if (server.config->GetVariable("options", "dump_packets_in").compare("TRUE") == 0)
|
||||
server.options.DumpInPackets(true);
|
||||
}
|
||||
|
||||
//Parse packet out dump option.
|
||||
if(server.config->GetVariable("options", "dump_packets_out").compare("TRUE") == 0)
|
||||
{
|
||||
if (server.config->GetVariable("options", "dump_packets_out").compare("TRUE") == 0)
|
||||
server.options.DumpOutPackets(true);
|
||||
}
|
||||
|
||||
//Parse encryption mode option.
|
||||
std::string mode = server.config->GetVariable("security", "mode");
|
||||
if(mode.size() > 0)
|
||||
{
|
||||
if (mode.size() > 0)
|
||||
server.options.EncryptionMode(atoi(mode.c_str()));
|
||||
}
|
||||
|
||||
//Parse local network option.
|
||||
std::string ln = server.config->GetVariable("options", "local_network");
|
||||
if(ln.size() > 0)
|
||||
{
|
||||
server.options.LocalNetwork(ln);
|
||||
}
|
||||
std::string local_network = server.config->GetVariable("options", "local_network");
|
||||
if (local_network.size() > 0)
|
||||
server.options.LocalNetwork(local_network);
|
||||
|
||||
//Parse reject duplicate servers option.
|
||||
if(server.config->GetVariable("options", "reject_duplicate_servers").compare("TRUE") == 0)
|
||||
{
|
||||
if (server.config->GetVariable("options", "reject_duplicate_servers").compare("TRUE") == 0)
|
||||
server.options.RejectDuplicateServers(true);
|
||||
}
|
||||
|
||||
//Parse account table option.
|
||||
ln = server.config->GetVariable("schema", "account_table");
|
||||
if(ln.size() > 0)
|
||||
{
|
||||
server.options.AccountTable(ln);
|
||||
}
|
||||
local_network = server.config->GetVariable("schema", "account_table");
|
||||
if (local_network.size() > 0)
|
||||
server.options.AccountTable(local_network);
|
||||
|
||||
//Parse world account table option.
|
||||
ln = server.config->GetVariable("schema", "world_registration_table");
|
||||
if(ln.size() > 0)
|
||||
{
|
||||
server.options.WorldRegistrationTable(ln);
|
||||
}
|
||||
local_network = server.config->GetVariable("schema", "world_registration_table");
|
||||
if (local_network.size() > 0)
|
||||
server.options.WorldRegistrationTable(local_network);
|
||||
|
||||
//Parse admin world account table option.
|
||||
ln = server.config->GetVariable("schema", "world_admin_registration_table");
|
||||
if(ln.size() > 0)
|
||||
{
|
||||
server.options.WorldAdminRegistrationTable(ln);
|
||||
}
|
||||
local_network = server.config->GetVariable("schema", "world_admin_registration_table");
|
||||
if (local_network.size() > 0)
|
||||
server.options.WorldAdminRegistrationTable(local_network);
|
||||
|
||||
//Parse world type table option.
|
||||
ln = server.config->GetVariable("schema", "world_server_type_table");
|
||||
if(ln.size() > 0)
|
||||
{
|
||||
server.options.WorldServerTypeTable(ln);
|
||||
}
|
||||
local_network = server.config->GetVariable("schema", "world_server_type_table");
|
||||
if (local_network.size() > 0)
|
||||
server.options.WorldServerTypeTable(local_network);
|
||||
|
||||
//Create our DB from options.
|
||||
if(server.config->GetVariable("database", "subsystem").compare("MySQL") == 0)
|
||||
{
|
||||
/* Create database connection */
|
||||
if (server.config->GetVariable("database", "subsystem").compare("MySQL") == 0) {
|
||||
#ifdef EQEMU_MYSQL_ENABLED
|
||||
server_log->Log(log_debug, "MySQL Database Init.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "MySQL Database Init.");
|
||||
server.db = (Database*)new DatabaseMySQL(
|
||||
server.config->GetVariable("database", "user"),
|
||||
server.config->GetVariable("database", "password"),
|
||||
@@ -151,10 +107,9 @@ int main()
|
||||
server.config->GetVariable("database", "db"));
|
||||
#endif
|
||||
}
|
||||
else if(server.config->GetVariable("database", "subsystem").compare("PostgreSQL") == 0)
|
||||
{
|
||||
else if (server.config->GetVariable("database", "subsystem").compare("PostgreSQL") == 0) {
|
||||
#ifdef EQEMU_POSTGRESQL_ENABLED
|
||||
server_log->Log(log_debug, "PostgreSQL Database Init.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "PostgreSQL Database Init.");
|
||||
server.db = (Database*)new DatabasePostgreSQL(
|
||||
server.config->GetVariable("database", "user"),
|
||||
server.config->GetVariable("database", "password"),
|
||||
@@ -164,78 +119,70 @@ int main()
|
||||
#endif
|
||||
}
|
||||
|
||||
//Make sure our database got created okay, otherwise cleanup and exit.
|
||||
if(!server.db)
|
||||
{
|
||||
server_log->Log(log_error, "Database Initialization Failure.");
|
||||
server_log->Log(log_debug, "Config System Shutdown.");
|
||||
/* Make sure our database got created okay, otherwise cleanup and exit. */
|
||||
if (!server.db) {
|
||||
Log.Out(Logs::General, Logs::Error, "Database Initialization Failure.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown.");
|
||||
delete server.config;
|
||||
server_log->Log(log_debug, "Log System Shutdown.");
|
||||
delete server_log;
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Log System Shutdown.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if WIN32
|
||||
//initialize our encryption.
|
||||
server_log->Log(log_debug, "Encryption Initialize.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Encryption Initialize.");
|
||||
server.eq_crypto = new Encryption();
|
||||
if(server.eq_crypto->LoadCrypto(server.config->GetVariable("security", "plugin")))
|
||||
{
|
||||
server_log->Log(log_debug, "Encryption Loaded Successfully.");
|
||||
if (server.eq_crypto->LoadCrypto(server.config->GetVariable("security", "plugin"))) {
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Encryption Loaded Successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
//We can't run without encryption, cleanup and exit.
|
||||
server_log->Log(log_error, "Encryption Failed to Load.");
|
||||
server_log->Log(log_debug, "Database System Shutdown.");
|
||||
Log.Out(Logs::General, Logs::Error, "Encryption Failed to Load.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Database System Shutdown.");
|
||||
delete server.db;
|
||||
server_log->Log(log_debug, "Config System Shutdown.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown.");
|
||||
delete server.config;
|
||||
server_log->Log(log_debug, "Log System Shutdown.");
|
||||
delete server_log;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
//create our server manager.
|
||||
server_log->Log(log_debug, "Server Manager Initialize.");
|
||||
server.SM = new ServerManager();
|
||||
if(!server.SM)
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Server Manager Initialize.");
|
||||
server.server_manager = new ServerManager();
|
||||
if (!server.server_manager) {
|
||||
//We can't run without a server manager, cleanup and exit.
|
||||
server_log->Log(log_error, "Server Manager Failed to Start.");
|
||||
Log.Out(Logs::General, Logs::Error, "Server Manager Failed to Start.");
|
||||
|
||||
#ifdef WIN32
|
||||
server_log->Log(log_debug, "Encryption System Shutdown.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Encryption System Shutdown.");
|
||||
delete server.eq_crypto;
|
||||
#endif
|
||||
server_log->Log(log_debug, "Database System Shutdown.");
|
||||
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Database System Shutdown.");
|
||||
delete server.db;
|
||||
server_log->Log(log_debug, "Config System Shutdown.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown.");
|
||||
delete server.config;
|
||||
server_log->Log(log_debug, "Log System Shutdown.");
|
||||
delete server_log;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//create our client manager.
|
||||
server_log->Log(log_debug, "Client Manager Initialize.");
|
||||
server.CM = new ClientManager();
|
||||
if(!server.CM)
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Client Manager Initialize.");
|
||||
server.client_manager = new ClientManager();
|
||||
if (!server.client_manager) {
|
||||
//We can't run without a client manager, cleanup and exit.
|
||||
server_log->Log(log_error, "Client Manager Failed to Start.");
|
||||
server_log->Log(log_debug, "Server Manager Shutdown.");
|
||||
delete server.SM;
|
||||
Log.Out(Logs::General, Logs::Error, "Client Manager Failed to Start.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Server Manager Shutdown.");
|
||||
delete server.server_manager;
|
||||
|
||||
#ifdef WIN32
|
||||
server_log->Log(log_debug, "Encryption System Shutdown.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Encryption System Shutdown.");
|
||||
delete server.eq_crypto;
|
||||
#endif
|
||||
server_log->Log(log_debug, "Database System Shutdown.");
|
||||
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Database System Shutdown.");
|
||||
delete server.db;
|
||||
server_log->Log(log_debug, "Config System Shutdown.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown.");
|
||||
delete server.config;
|
||||
server_log->Log(log_debug, "Log System Shutdown.");
|
||||
delete server_log;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -247,30 +194,29 @@ int main()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
server_log->Log(log_debug, "Server Started.");
|
||||
while(run_server)
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Server Started.");
|
||||
while (run_server) {
|
||||
Timer::SetCurrentTime();
|
||||
server.CM->Process();
|
||||
server.SM->Process();
|
||||
server.client_manager->Process();
|
||||
server.server_manager->Process();
|
||||
Sleep(100);
|
||||
}
|
||||
|
||||
server_log->Log(log_debug, "Server Shutdown.");
|
||||
server_log->Log(log_debug, "Client Manager Shutdown.");
|
||||
delete server.CM;
|
||||
server_log->Log(log_debug, "Server Manager Shutdown.");
|
||||
delete server.SM;
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Server Shutdown.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Client Manager Shutdown.");
|
||||
delete server.client_manager;
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Server Manager Shutdown.");
|
||||
delete server.server_manager;
|
||||
|
||||
#ifdef WIN32
|
||||
server_log->Log(log_debug, "Encryption System Shutdown.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Encryption System Shutdown.");
|
||||
delete server.eq_crypto;
|
||||
#endif
|
||||
server_log->Log(log_debug, "Database System Shutdown.");
|
||||
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Database System Shutdown.");
|
||||
delete server.db;
|
||||
server_log->Log(log_debug, "Config System Shutdown.");
|
||||
Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown.");
|
||||
delete server.config;
|
||||
server_log->Log(log_debug, "Log System Shutdown.");
|
||||
delete server_log;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+99
-140
@@ -17,11 +17,12 @@
|
||||
*/
|
||||
#include "server_manager.h"
|
||||
#include "login_server.h"
|
||||
#include "error_log.h"
|
||||
#include "login_structures.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
extern ErrorLog *server_log;
|
||||
#include "../common/eqemu_logsys.h"
|
||||
|
||||
extern EQEmuLogSys Log;
|
||||
extern LoginServer server;
|
||||
extern bool run_server;
|
||||
|
||||
@@ -31,21 +32,18 @@ ServerManager::ServerManager()
|
||||
|
||||
int listen_port = atoi(server.config->GetVariable("options", "listen_port").c_str());
|
||||
tcps = new EmuTCPServer(listen_port, true);
|
||||
if(tcps->Open(listen_port, error_buffer))
|
||||
{
|
||||
server_log->Log(log_network, "ServerManager listening on port %u", listen_port);
|
||||
if(tcps->Open(listen_port, error_buffer)) {
|
||||
Log.Out(Logs::General, Logs::Login_Server, "ServerManager listening on port %u", listen_port);
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_error, "ServerManager fatal error opening port on %u: %s", listen_port, error_buffer);
|
||||
else {
|
||||
Log.Out(Logs::General, Logs::Error, "ServerManager fatal error opening port on %u: %s", listen_port, error_buffer);
|
||||
run_server = false;
|
||||
}
|
||||
}
|
||||
|
||||
ServerManager::~ServerManager()
|
||||
{
|
||||
if(tcps)
|
||||
{
|
||||
if (tcps) {
|
||||
tcps->Close();
|
||||
delete tcps;
|
||||
}
|
||||
@@ -55,38 +53,32 @@ void ServerManager::Process()
|
||||
{
|
||||
ProcessDisconnect();
|
||||
EmuTCPConnection *tcp_c = nullptr;
|
||||
while(tcp_c = tcps->NewQueuePop())
|
||||
{
|
||||
while (tcp_c = tcps->NewQueuePop()) {
|
||||
in_addr tmp;
|
||||
tmp.s_addr = tcp_c->GetrIP();
|
||||
server_log->Log(log_network, "New world server connection from %s:%d", inet_ntoa(tmp), tcp_c->GetrPort());
|
||||
Log.Out(Logs::General, Logs::Login_Server, "New world server connection from %s:%d", inet_ntoa(tmp), tcp_c->GetrPort());
|
||||
|
||||
WorldServer *cur = GetServerByAddress(tcp_c->GetrIP());
|
||||
if(cur)
|
||||
{
|
||||
server_log->Log(log_network, "World server already existed for %s, removing existing connection and updating current.", inet_ntoa(tmp));
|
||||
cur->GetConnection()->Free();
|
||||
cur->SetConnection(tcp_c);
|
||||
cur->Reset();
|
||||
WorldServer *server_entity = GetServerByAddress(tcp_c->GetrIP());
|
||||
if (server_entity) {
|
||||
Log.Out(Logs::General, Logs::Login_Server, "World server already existed for %s, removing existing connection and updating current.", inet_ntoa(tmp));
|
||||
server_entity->GetConnection()->Free();
|
||||
server_entity->SetConnection(tcp_c);
|
||||
server_entity->Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
WorldServer *w = new WorldServer(tcp_c);
|
||||
world_servers.push_back(w);
|
||||
}
|
||||
}
|
||||
|
||||
list<WorldServer*>::iterator iter = world_servers.begin();
|
||||
while(iter != world_servers.end())
|
||||
{
|
||||
if((*iter)->Process() == false)
|
||||
{
|
||||
server_log->Log(log_world, "World server %s had a fatal error and had to be removed from the login.", (*iter)->GetLongName().c_str());
|
||||
while (iter != world_servers.end()) {
|
||||
if ((*iter)->Process() == false) {
|
||||
Log.Out(Logs::General, Logs::World_Server, "World server %s had a fatal error and had to be removed from the login.", (*iter)->GetLongName().c_str());
|
||||
delete (*iter);
|
||||
iter = world_servers.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
@@ -95,20 +87,17 @@ void ServerManager::Process()
|
||||
void ServerManager::ProcessDisconnect()
|
||||
{
|
||||
list<WorldServer*>::iterator iter = world_servers.begin();
|
||||
while(iter != world_servers.end())
|
||||
{
|
||||
EmuTCPConnection *c = (*iter)->GetConnection();
|
||||
if(!c->Connected())
|
||||
{
|
||||
while (iter != world_servers.end()) {
|
||||
EmuTCPConnection *connection = (*iter)->GetConnection();
|
||||
if (!connection->Connected()) {
|
||||
in_addr tmp;
|
||||
tmp.s_addr = c->GetrIP();
|
||||
server_log->Log(log_network, "World server disconnected from the server, removing server and freeing connection.");
|
||||
c->Free();
|
||||
tmp.s_addr = connection->GetrIP();
|
||||
Log.Out(Logs::General, Logs::Login_Server, "World server disconnected from the server, removing server and freeing connection.");
|
||||
connection->Free();
|
||||
delete (*iter);
|
||||
iter = world_servers.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
@@ -117,10 +106,8 @@ void ServerManager::ProcessDisconnect()
|
||||
WorldServer* ServerManager::GetServerByAddress(unsigned int address)
|
||||
{
|
||||
list<WorldServer*>::iterator iter = world_servers.begin();
|
||||
while(iter != world_servers.end())
|
||||
{
|
||||
if((*iter)->GetConnection()->GetrIP() == address)
|
||||
{
|
||||
while (iter != world_servers.end()) {
|
||||
if ((*iter)->GetConnection()->GetrIP() == address) {
|
||||
return (*iter);
|
||||
}
|
||||
++iter;
|
||||
@@ -138,10 +125,8 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c)
|
||||
string client_ip = inet_ntoa(in);
|
||||
|
||||
list<WorldServer*>::iterator iter = world_servers.begin();
|
||||
while(iter != world_servers.end())
|
||||
{
|
||||
if((*iter)->IsAuthorized() == false)
|
||||
{
|
||||
while (iter != world_servers.end()) {
|
||||
if ((*iter)->IsAuthorized() == false) {
|
||||
++iter;
|
||||
continue;
|
||||
}
|
||||
@@ -149,16 +134,13 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c)
|
||||
in.s_addr = (*iter)->GetConnection()->GetrIP();
|
||||
string world_ip = inet_ntoa(in);
|
||||
|
||||
if(world_ip.compare(client_ip) == 0)
|
||||
{
|
||||
if (world_ip.compare(client_ip) == 0) {
|
||||
packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24;
|
||||
}
|
||||
else if(client_ip.find(server.options.GetLocalNetwork()) != string::npos)
|
||||
{
|
||||
else if (client_ip.find(server.options.GetLocalNetwork()) != string::npos) {
|
||||
packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
packet_size += (*iter)->GetLongName().size() + (*iter)->GetRemoteIP().size() + 24;
|
||||
}
|
||||
|
||||
@@ -167,98 +149,87 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c)
|
||||
}
|
||||
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_ServerListResponse, packet_size);
|
||||
ServerListHeader_Struct *sl = (ServerListHeader_Struct*)outapp->pBuffer;
|
||||
sl->Unknown1 = 0x00000004;
|
||||
sl->Unknown2 = 0x00000000;
|
||||
sl->Unknown3 = 0x01650000;
|
||||
/**
|
||||
* Not sure what this is but it should be noted setting it to
|
||||
* 0xFFFFFFFF crashes the client so: don't do that.
|
||||
*/
|
||||
sl->Unknown4 = 0x00000000;
|
||||
sl->NumberOfServers = server_count;
|
||||
ServerListHeader_Struct *server_list = (ServerListHeader_Struct*)outapp->pBuffer;
|
||||
server_list->Unknown1 = 0x00000004;
|
||||
server_list->Unknown2 = 0x00000000;
|
||||
server_list->Unknown3 = 0x01650000;
|
||||
|
||||
unsigned char *data_ptr = outapp->pBuffer;
|
||||
data_ptr += sizeof(ServerListHeader_Struct);
|
||||
/**
|
||||
* Not sure what this is but it should be noted setting it to
|
||||
* 0xFFFFFFFF crashes the client so: don't do that.
|
||||
*/
|
||||
server_list->Unknown4 = 0x00000000;
|
||||
server_list->NumberOfServers = server_count;
|
||||
|
||||
unsigned char *data_pointer = outapp->pBuffer;
|
||||
data_pointer += sizeof(ServerListHeader_Struct);
|
||||
|
||||
iter = world_servers.begin();
|
||||
while(iter != world_servers.end())
|
||||
{
|
||||
if((*iter)->IsAuthorized() == false)
|
||||
{
|
||||
while (iter != world_servers.end()) {
|
||||
if ((*iter)->IsAuthorized() == false) {
|
||||
++iter;
|
||||
continue;
|
||||
}
|
||||
|
||||
in.s_addr = (*iter)->GetConnection()->GetrIP();
|
||||
string world_ip = inet_ntoa(in);
|
||||
if(world_ip.compare(client_ip) == 0)
|
||||
{
|
||||
memcpy(data_ptr, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
|
||||
data_ptr += ((*iter)->GetLocalIP().size() + 1);
|
||||
if (world_ip.compare(client_ip) == 0) {
|
||||
memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
|
||||
data_pointer += ((*iter)->GetLocalIP().size() + 1);
|
||||
}
|
||||
else if(client_ip.find(server.options.GetLocalNetwork()) != string::npos)
|
||||
{
|
||||
memcpy(data_ptr, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
|
||||
data_ptr += ((*iter)->GetLocalIP().size() + 1);
|
||||
else if (client_ip.find(server.options.GetLocalNetwork()) != string::npos) {
|
||||
memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
|
||||
data_pointer += ((*iter)->GetLocalIP().size() + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(data_ptr, (*iter)->GetRemoteIP().c_str(), (*iter)->GetRemoteIP().size());
|
||||
data_ptr += ((*iter)->GetRemoteIP().size() + 1);
|
||||
else {
|
||||
memcpy(data_pointer, (*iter)->GetRemoteIP().c_str(), (*iter)->GetRemoteIP().size());
|
||||
data_pointer += ((*iter)->GetRemoteIP().size() + 1);
|
||||
}
|
||||
|
||||
switch((*iter)->GetServerListID())
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
*(unsigned int*)data_ptr = 0x00000030;
|
||||
switch ((*iter)->GetServerListID()) {
|
||||
case 1: {
|
||||
*(unsigned int*)data_pointer = 0x00000030;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
*(unsigned int*)data_ptr = 0x00000009;
|
||||
case 2: {
|
||||
*(unsigned int*)data_pointer = 0x00000009;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
*(unsigned int*)data_ptr = 0x00000001;
|
||||
default: {
|
||||
*(unsigned int*)data_pointer = 0x00000001;
|
||||
}
|
||||
}
|
||||
data_ptr += 4;
|
||||
|
||||
*(unsigned int*)data_ptr = (*iter)->GetRuntimeID();
|
||||
data_ptr += 4;
|
||||
data_pointer += 4;
|
||||
|
||||
memcpy(data_ptr, (*iter)->GetLongName().c_str(), (*iter)->GetLongName().size());
|
||||
data_ptr += ((*iter)->GetLongName().size() + 1);
|
||||
*(unsigned int*)data_pointer = (*iter)->GetRuntimeID();
|
||||
data_pointer += 4;
|
||||
|
||||
memcpy(data_ptr, "EN", 2);
|
||||
data_ptr += 3;
|
||||
memcpy(data_pointer, (*iter)->GetLongName().c_str(), (*iter)->GetLongName().size());
|
||||
data_pointer += ((*iter)->GetLongName().size() + 1);
|
||||
|
||||
memcpy(data_ptr, "US", 2);
|
||||
data_ptr += 3;
|
||||
memcpy(data_pointer, "EN", 2);
|
||||
data_pointer += 3;
|
||||
|
||||
memcpy(data_pointer, "US", 2);
|
||||
data_pointer += 3;
|
||||
|
||||
// 0 = Up, 1 = Down, 2 = Up, 3 = down, 4 = locked, 5 = locked(down)
|
||||
if((*iter)->GetStatus() < 0)
|
||||
{
|
||||
if((*iter)->GetZonesBooted() == 0)
|
||||
{
|
||||
*(uint32*)data_ptr = 0x01;
|
||||
if ((*iter)->GetStatus() < 0) {
|
||||
if ((*iter)->GetZonesBooted() == 0) {
|
||||
*(uint32*)data_pointer = 0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(uint32*)data_ptr = 0x04;
|
||||
else {
|
||||
*(uint32*)data_pointer = 0x04;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*(uint32*)data_ptr = 0x02;
|
||||
else {
|
||||
*(uint32*)data_pointer = 0x02;
|
||||
}
|
||||
data_ptr += 4;
|
||||
data_pointer += 4;
|
||||
|
||||
*(uint32*)data_ptr = (*iter)->GetPlayersOnline();
|
||||
data_ptr += 4;
|
||||
*(uint32*)data_pointer = (*iter)->GetPlayersOnline();
|
||||
data_pointer += 4;
|
||||
|
||||
++iter;
|
||||
}
|
||||
@@ -270,10 +241,8 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int
|
||||
{
|
||||
list<WorldServer*>::iterator iter = world_servers.begin();
|
||||
bool found = false;
|
||||
while(iter != world_servers.end())
|
||||
{
|
||||
if((*iter)->GetRuntimeID() == server_id)
|
||||
{
|
||||
while (iter != world_servers.end()) {
|
||||
if ((*iter)->GetRuntimeID() == server_id) {
|
||||
ServerPacket *outapp = new ServerPacket(ServerOP_UsertoWorldReq, sizeof(UsertoWorldRequest_Struct));
|
||||
UsertoWorldRequest_Struct *utwr = (UsertoWorldRequest_Struct*)outapp->pBuffer;
|
||||
utwr->worldid = server_id;
|
||||
@@ -281,8 +250,7 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int
|
||||
(*iter)->GetConnection()->SendPacket(outapp);
|
||||
found = true;
|
||||
|
||||
if(server.options.IsDumpInPacketsOn())
|
||||
{
|
||||
if (server.options.IsDumpInPacketsOn()) {
|
||||
DumpPacket(outapp);
|
||||
}
|
||||
delete outapp;
|
||||
@@ -290,25 +258,21 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int
|
||||
++iter;
|
||||
}
|
||||
|
||||
if(!found && server.options.IsTraceOn())
|
||||
{
|
||||
server_log->Log(log_client_error, "Client requested a user to world but supplied an invalid id of %u.", server_id);
|
||||
if (!found && server.options.IsTraceOn()) {
|
||||
Log.Out(Logs::General, Logs::Error, "Client requested a user to world but supplied an invalid id of %u.", server_id);
|
||||
}
|
||||
}
|
||||
|
||||
bool ServerManager::ServerExists(string l_name, string s_name, WorldServer *ignore)
|
||||
{
|
||||
list<WorldServer*>::iterator iter = world_servers.begin();
|
||||
while(iter != world_servers.end())
|
||||
{
|
||||
if((*iter) == ignore)
|
||||
{
|
||||
while (iter != world_servers.end()) {
|
||||
if ((*iter) == ignore) {
|
||||
++iter;
|
||||
continue;
|
||||
}
|
||||
|
||||
if((*iter)->GetLongName().compare(l_name) == 0 && (*iter)->GetShortName().compare(s_name) == 0)
|
||||
{
|
||||
if ((*iter)->GetLongName().compare(l_name) == 0 && (*iter)->GetShortName().compare(s_name) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -320,18 +284,14 @@ bool ServerManager::ServerExists(string l_name, string s_name, WorldServer *igno
|
||||
void ServerManager::DestroyServerByName(string l_name, string s_name, WorldServer *ignore)
|
||||
{
|
||||
list<WorldServer*>::iterator iter = world_servers.begin();
|
||||
while(iter != world_servers.end())
|
||||
{
|
||||
if((*iter) == ignore)
|
||||
{
|
||||
while (iter != world_servers.end()) {
|
||||
if ((*iter) == ignore) {
|
||||
++iter;
|
||||
}
|
||||
|
||||
if((*iter)->GetLongName().compare(l_name) == 0 && (*iter)->GetShortName().compare(s_name) == 0)
|
||||
{
|
||||
if ((*iter)->GetLongName().compare(l_name) == 0 && (*iter)->GetShortName().compare(s_name) == 0) {
|
||||
EmuTCPConnection *c = (*iter)->GetConnection();
|
||||
if(c->Connected())
|
||||
{
|
||||
if (c->Connected()) {
|
||||
c->Disconnect();
|
||||
}
|
||||
c->Free();
|
||||
@@ -341,5 +301,4 @@ void ServerManager::DestroyServerByName(string l_name, string s_name, WorldServe
|
||||
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+128
-129
@@ -16,11 +16,13 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "world_server.h"
|
||||
#include "error_log.h"
|
||||
#include "login_server.h"
|
||||
#include "login_structures.h"
|
||||
#include "config.h"
|
||||
|
||||
extern ErrorLog *server_log;
|
||||
#include "../common/eqemu_logsys.h"
|
||||
|
||||
extern EQEmuLogSys Log;
|
||||
extern LoginServer server;
|
||||
|
||||
WorldServer::WorldServer(EmuTCPConnection *c)
|
||||
@@ -28,19 +30,18 @@ WorldServer::WorldServer(EmuTCPConnection *c)
|
||||
connection = c;
|
||||
zones_booted = 0;
|
||||
players_online = 0;
|
||||
status = 0;
|
||||
server_status = 0;
|
||||
runtime_id = 0;
|
||||
server_list_id = 0;
|
||||
server_type = 0;
|
||||
authorized = false;
|
||||
trusted = false;
|
||||
logged_in = false;
|
||||
is_server_authorized = false;
|
||||
is_server_trusted = false;
|
||||
is_server_logged_in = false;
|
||||
}
|
||||
|
||||
WorldServer::~WorldServer()
|
||||
{
|
||||
if(connection)
|
||||
{
|
||||
if(connection) {
|
||||
connection->Free();
|
||||
}
|
||||
}
|
||||
@@ -49,12 +50,12 @@ void WorldServer::Reset()
|
||||
{
|
||||
zones_booted = 0;
|
||||
players_online = 0;
|
||||
status = 0;
|
||||
server_status = 0;
|
||||
runtime_id;
|
||||
server_list_id = 0;
|
||||
server_type = 0;
|
||||
authorized = false;
|
||||
logged_in = false;
|
||||
is_server_authorized = false;
|
||||
is_server_logged_in = false;
|
||||
}
|
||||
|
||||
bool WorldServer::Process()
|
||||
@@ -64,7 +65,7 @@ bool WorldServer::Process()
|
||||
{
|
||||
if(server.options.IsWorldTraceOn())
|
||||
{
|
||||
server_log->Log(log_network_trace, "Application packet received from server: 0x%.4X, (size %u)", app->opcode, app->size);
|
||||
Log.Out(Logs::General, Logs::Netcode, "Application packet received from server: 0x%.4X, (size %u)", app->opcode, app->size);
|
||||
}
|
||||
|
||||
if(server.options.IsDumpInPacketsOn())
|
||||
@@ -78,14 +79,14 @@ bool WorldServer::Process()
|
||||
{
|
||||
if(app->size < sizeof(ServerNewLSInfo_Struct))
|
||||
{
|
||||
server_log->Log(log_network_error, "Received application packet from server that had opcode ServerOP_NewLSInfo, "
|
||||
Log.Out(Logs::General, Logs::Error, "Received application packet from server that had opcode ServerOP_NewLSInfo, "
|
||||
"but was too small. Discarded to avoid buffer overrun.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(server.options.IsWorldTraceOn())
|
||||
{
|
||||
server_log->Log(log_network_trace, "New Login Info Recieved.");
|
||||
Log.Out(Logs::General, Logs::Netcode, "New Login Info Recieved.");
|
||||
}
|
||||
|
||||
ServerNewLSInfo_Struct *info = (ServerNewLSInfo_Struct*)app->pBuffer;
|
||||
@@ -96,14 +97,14 @@ bool WorldServer::Process()
|
||||
{
|
||||
if(app->size < sizeof(ServerLSStatus_Struct))
|
||||
{
|
||||
server_log->Log(log_network_error, "Recieved application packet from server that had opcode ServerOP_LSStatus, "
|
||||
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerOP_LSStatus, "
|
||||
"but was too small. Discarded to avoid buffer overrun.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(server.options.IsWorldTraceOn())
|
||||
{
|
||||
server_log->Log(log_network_trace, "World Server Status Recieved.");
|
||||
Log.Out(Logs::General, Logs::Netcode, "World Server Status Recieved.");
|
||||
}
|
||||
|
||||
ServerLSStatus_Struct *ls_status = (ServerLSStatus_Struct*)app->pBuffer;
|
||||
@@ -127,7 +128,7 @@ bool WorldServer::Process()
|
||||
{
|
||||
if(app->size < sizeof(UsertoWorldResponse_Struct))
|
||||
{
|
||||
server_log->Log(log_network_error, "Recieved application packet from server that had opcode ServerOP_UsertoWorldResp, "
|
||||
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerOP_UsertoWorldResp, "
|
||||
"but was too small. Discarded to avoid buffer overrun.");
|
||||
break;
|
||||
}
|
||||
@@ -137,21 +138,22 @@ bool WorldServer::Process()
|
||||
//While keeping world server spam with multiple servers connected almost impossible.
|
||||
if(server.options.IsTraceOn())
|
||||
{
|
||||
server_log->Log(log_network_trace, "User-To-World Response received.");
|
||||
Log.Out(Logs::General, Logs::Netcode, "User-To-World Response received.");
|
||||
}
|
||||
|
||||
UsertoWorldResponse_Struct *utwr = (UsertoWorldResponse_Struct*)app->pBuffer;
|
||||
server_log->Log(log_client, "Trying to find client with user id of %u.", utwr->lsaccountid);
|
||||
Client *c = server.CM->GetClient(utwr->lsaccountid);
|
||||
Log.Out(Logs::General, Logs::Debug, "Trying to find client with user id of %u.", utwr->lsaccountid);
|
||||
Client *c = server.client_manager->GetClient(utwr->lsaccountid);
|
||||
if(c)
|
||||
{
|
||||
server_log->Log(log_client, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str());
|
||||
Log.Out(Logs::General, Logs::Debug, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str());
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_PlayEverquestResponse, sizeof(PlayEverquestResponse_Struct));
|
||||
PlayEverquestResponse_Struct *per = (PlayEverquestResponse_Struct*)outapp->pBuffer;
|
||||
per->Sequence = c->GetPlaySequence();
|
||||
per->ServerNumber = c->GetPlayServerID();
|
||||
server_log->Log(log_client, "Found sequence and play of %u %u", c->GetPlaySequence(), c->GetPlayServerID());
|
||||
server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size);
|
||||
Log.Out(Logs::General, Logs::Debug, "Found sequence and play of %u %u", c->GetPlaySequence(), c->GetPlayServerID());
|
||||
|
||||
Log.Out(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str());
|
||||
|
||||
if(utwr->response > 0)
|
||||
{
|
||||
@@ -180,9 +182,9 @@ bool WorldServer::Process()
|
||||
|
||||
if(server.options.IsTraceOn())
|
||||
{
|
||||
server_log->Log(log_network_trace, "Sending play response with following data, allowed %u, sequence %u, server number %u, message %u",
|
||||
Log.Out(Logs::General, Logs::Netcode, "Sending play response with following data, allowed %u, sequence %u, server number %u, message %u",
|
||||
per->Allowed, per->Sequence, per->ServerNumber, per->Message);
|
||||
server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size);
|
||||
Log.Out(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str());
|
||||
}
|
||||
|
||||
if(server.options.IsDumpOutPacketsOn())
|
||||
@@ -195,7 +197,7 @@ bool WorldServer::Process()
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_client_error, "Recieved User-To-World Response for %u but could not find the client referenced!.", utwr->lsaccountid);
|
||||
Log.Out(Logs::General, Logs::Error, "Recieved User-To-World Response for %u but could not find the client referenced!.", utwr->lsaccountid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -203,16 +205,16 @@ bool WorldServer::Process()
|
||||
{
|
||||
if(app->size < sizeof(ServerLSAccountUpdate_Struct))
|
||||
{
|
||||
server_log->Log(log_network_error, "Recieved application packet from server that had opcode ServerLSAccountUpdate_Struct, "
|
||||
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerLSAccountUpdate_Struct, "
|
||||
"but was too small. Discarded to avoid buffer overrun.");
|
||||
break;
|
||||
}
|
||||
|
||||
server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate packet received from: %s", short_name.c_str());
|
||||
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate packet received from: %s", short_name.c_str());
|
||||
ServerLSAccountUpdate_Struct *lsau = (ServerLSAccountUpdate_Struct*)app->pBuffer;
|
||||
if(trusted)
|
||||
if(is_server_trusted)
|
||||
{
|
||||
server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate update processed for: %s", lsau->useraccount);
|
||||
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate update processed for: %s", lsau->useraccount);
|
||||
string name;
|
||||
string password;
|
||||
string email;
|
||||
@@ -225,7 +227,7 @@ bool WorldServer::Process()
|
||||
}
|
||||
default:
|
||||
{
|
||||
server_log->Log(log_network_error, "Recieved application packet from server that had an unknown operation code 0x%.4X.", app->opcode);
|
||||
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had an unknown operation code 0x%.4X.", app->opcode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,9 +239,9 @@ bool WorldServer::Process()
|
||||
|
||||
void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
|
||||
{
|
||||
if(logged_in)
|
||||
if(is_server_logged_in)
|
||||
{
|
||||
server_log->Log(log_network_error, "WorldServer::Handle_NewLSInfo called but the login server was already marked as logged in, aborting.");
|
||||
Log.Out(Logs::General, Logs::Error, "WorldServer::Handle_NewLSInfo called but the login server was already marked as logged in, aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -249,7 +251,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_network_error, "Handle_NewLSInfo error, account name was too long.");
|
||||
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, account name was too long.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -259,7 +261,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_network_error, "Handle_NewLSInfo error, account password was too long.");
|
||||
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, account password was too long.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -269,7 +271,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_network_error, "Handle_NewLSInfo error, long name was too long.");
|
||||
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, long name was too long.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -279,7 +281,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_network_error, "Handle_NewLSInfo error, short name was too long.");
|
||||
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, short name was too long.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -287,7 +289,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
|
||||
{
|
||||
if(strlen(i->local_address) == 0)
|
||||
{
|
||||
server_log->Log(log_network_error, "Handle_NewLSInfo error, local address was null, defaulting to localhost");
|
||||
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, local address was null, defaulting to localhost");
|
||||
local_ip = "127.0.0.1";
|
||||
}
|
||||
else
|
||||
@@ -297,7 +299,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_network_error, "Handle_NewLSInfo error, local address was too long.");
|
||||
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, local address was too long.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -308,7 +310,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
|
||||
in_addr in;
|
||||
in.s_addr = GetConnection()->GetrIP();
|
||||
remote_ip = inet_ntoa(in);
|
||||
server_log->Log(log_network_error, "Handle_NewLSInfo error, remote address was null, defaulting to stream address %s.", remote_ip.c_str());
|
||||
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, remote address was null, defaulting to stream address %s.", remote_ip.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -320,7 +322,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
|
||||
in_addr in;
|
||||
in.s_addr = GetConnection()->GetrIP();
|
||||
remote_ip = inet_ntoa(in);
|
||||
server_log->Log(log_network_error, "Handle_NewLSInfo error, remote address was too long, defaulting to stream address %s.", remote_ip.c_str());
|
||||
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, remote address was too long, defaulting to stream address %s.", remote_ip.c_str());
|
||||
}
|
||||
|
||||
if(strlen(i->serverversion) <= 64)
|
||||
@@ -329,7 +331,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_network_error, "Handle_NewLSInfo error, server version was too long.");
|
||||
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, server version was too long.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -339,27 +341,27 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_network_error, "Handle_NewLSInfo error, protocol version was too long.");
|
||||
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, protocol version was too long.");
|
||||
return;
|
||||
}
|
||||
|
||||
server_type = i->servertype;
|
||||
logged_in = true;
|
||||
is_server_logged_in = true;
|
||||
|
||||
if(server.options.IsRejectingDuplicateServers())
|
||||
{
|
||||
if(server.SM->ServerExists(long_name, short_name, this))
|
||||
if(server.server_manager->ServerExists(long_name, short_name, this))
|
||||
{
|
||||
server_log->Log(log_world_error, "World tried to login but there already exists a server that has that name.");
|
||||
Log.Out(Logs::General, Logs::Error, "World tried to login but there already exists a server that has that name.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(server.SM->ServerExists(long_name, short_name, this))
|
||||
if(server.server_manager->ServerExists(long_name, short_name, this))
|
||||
{
|
||||
server_log->Log(log_world_error, "World tried to login but there already exists a server that has that name.");
|
||||
server.SM->DestroyServerByName(long_name, short_name, this);
|
||||
Log.Out(Logs::General, Logs::Error, "World tried to login but there already exists a server that has that name.");
|
||||
server.server_manager->DestroyServerByName(long_name, short_name, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,112 +380,112 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
|
||||
{
|
||||
if(s_acct_name.size() == 0 || s_acct_pass.size() == 0)
|
||||
{
|
||||
server_log->Log(log_world, "Server %s(%s) successfully logged into account that had no user/password requirement.",
|
||||
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) successfully logged into account that had no user/password requirement.",
|
||||
long_name.c_str(), short_name.c_str());
|
||||
authorized = true;
|
||||
is_server_authorized = true;
|
||||
SetRuntimeID(s_id);
|
||||
server_list_id = s_list_type;
|
||||
desc = s_desc;
|
||||
}
|
||||
else if(s_acct_name.compare(account_name) == 0 && s_acct_pass.compare(account_password) == 0)
|
||||
{
|
||||
server_log->Log(log_world, "Server %s(%s) successfully logged in.",
|
||||
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) successfully logged in.",
|
||||
long_name.c_str(), short_name.c_str());
|
||||
authorized = true;
|
||||
is_server_authorized = true;
|
||||
SetRuntimeID(s_id);
|
||||
server_list_id = s_list_type;
|
||||
desc = s_desc;
|
||||
if(s_trusted)
|
||||
{
|
||||
server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate sent to world");
|
||||
trusted = true;
|
||||
if(s_trusted) {
|
||||
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate sent to world");
|
||||
is_server_trusted = true;
|
||||
ServerPacket *outapp = new ServerPacket(ServerOP_LSAccountUpdate, 0);
|
||||
connection->SendPacket(outapp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_world, "Server %s(%s) attempted to log in but account and password did not match the entry in the database, and only"
|
||||
else {
|
||||
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) attempted to log in but account and password did not match the entry in the database, and only"
|
||||
" registered servers are allowed.", long_name.c_str(), short_name.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_world, "Server %s(%s) attempted to log in but database couldn't find an entry and only registered servers are allowed.",
|
||||
else {
|
||||
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) attempted to log in but database couldn't find an entry and only registered servers are allowed.",
|
||||
long_name.c_str(), short_name.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_world, "Server %s(%s) did not attempt to log in but only registered servers are allowed.",
|
||||
else {
|
||||
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) did not attempt to log in but only registered servers are allowed.",
|
||||
long_name.c_str(), short_name.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int s_id = 0;
|
||||
unsigned int s_list_type = 0;
|
||||
unsigned int s_trusted = 0;
|
||||
string s_desc;
|
||||
string s_list_desc;
|
||||
string s_acct_name;
|
||||
string s_acct_pass;
|
||||
if(server.db->GetWorldRegistration(long_name, short_name, s_id, s_desc, s_list_type, s_trusted, s_list_desc, s_acct_name, s_acct_pass))
|
||||
else {
|
||||
unsigned int server_id = 0;
|
||||
unsigned int server_list_type = 0;
|
||||
unsigned int is_server_trusted = 0;
|
||||
string server_description;
|
||||
string server_list_description;
|
||||
string server_account_name;
|
||||
string server_account_password;
|
||||
|
||||
|
||||
if(server.db->GetWorldRegistration(
|
||||
long_name,
|
||||
short_name,
|
||||
server_id,
|
||||
server_description,
|
||||
server_list_type,
|
||||
is_server_trusted,
|
||||
server_list_description,
|
||||
server_account_name,
|
||||
server_account_password))
|
||||
{
|
||||
if(account_name.size() > 0 && account_password.size() > 0)
|
||||
{
|
||||
if(s_acct_name.compare(account_name) == 0 && s_acct_pass.compare(account_password) == 0)
|
||||
{
|
||||
server_log->Log(log_world, "Server %s(%s) successfully logged in.",
|
||||
|
||||
if(account_name.size() > 0 && account_password.size() > 0) {
|
||||
if(server_account_name.compare(account_name) == 0 && server_account_password.compare(account_password) == 0) {
|
||||
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) successfully logged in.",
|
||||
long_name.c_str(), short_name.c_str());
|
||||
authorized = true;
|
||||
SetRuntimeID(s_id);
|
||||
server_list_id = s_list_type;
|
||||
desc = s_desc;
|
||||
if(s_trusted)
|
||||
{
|
||||
server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate sent to world");
|
||||
trusted = true;
|
||||
is_server_authorized = true;
|
||||
SetRuntimeID(server_id);
|
||||
server_list_id = server_list_type;
|
||||
desc = server_description;
|
||||
|
||||
if(is_server_trusted) {
|
||||
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate sent to world");
|
||||
is_server_trusted = true;
|
||||
ServerPacket *outapp = new ServerPacket(ServerOP_LSAccountUpdate, 0);
|
||||
connection->SendPacket(outapp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// this is the first of two cases where we should deny access even if unregistered is allowed
|
||||
server_log->Log(log_world, "Server %s(%s) attempted to log in but account and password did not match the entry in the database.",
|
||||
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) attempted to log in but account and password did not match the entry in the database.",
|
||||
long_name.c_str(), short_name.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(s_acct_name.size() > 0 || s_acct_pass.size() > 0)
|
||||
{
|
||||
else {
|
||||
if(server_account_name.size() > 0 || server_account_password.size() > 0) {
|
||||
// this is the second of two cases where we should deny access even if unregistered is allowed
|
||||
server_log->Log(log_world, "Server %s(%s) did not attempt to log in but this server requires a password.",
|
||||
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) did not attempt to log in but this server requires a password.",
|
||||
long_name.c_str(), short_name.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_world, "Server %s(%s) did not attempt to log in but unregistered servers are allowed.",
|
||||
else {
|
||||
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) did not attempt to log in but unregistered servers are allowed.",
|
||||
long_name.c_str(), short_name.c_str());
|
||||
authorized = true;
|
||||
SetRuntimeID(s_id);
|
||||
is_server_authorized = true;
|
||||
SetRuntimeID(server_id);
|
||||
server_list_id = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
server_log->Log(log_world, "Server %s(%s) attempted to log in but database couldn't find an entry but unregistered servers are allowed.",
|
||||
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) attempted to log in but database couldn't find an entry but unregistered servers are allowed.",
|
||||
long_name.c_str(), short_name.c_str());
|
||||
if(server.db->CreateWorldRegistration(long_name, short_name, s_id))
|
||||
{
|
||||
authorized = true;
|
||||
SetRuntimeID(s_id);
|
||||
if(server.db->CreateWorldRegistration(long_name, short_name, server_id)) {
|
||||
is_server_authorized = true;
|
||||
SetRuntimeID(server_id);
|
||||
server_list_id = 3;
|
||||
}
|
||||
}
|
||||
@@ -493,9 +495,9 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
|
||||
in.s_addr = connection->GetrIP();
|
||||
server.db->UpdateWorldRegistration(GetRuntimeID(), long_name, string(inet_ntoa(in)));
|
||||
|
||||
if(authorized)
|
||||
if(is_server_authorized)
|
||||
{
|
||||
server.CM->UpdateServerList();
|
||||
server.client_manager->UpdateServerList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,43 +505,40 @@ void WorldServer::Handle_LSStatus(ServerLSStatus_Struct *s)
|
||||
{
|
||||
players_online = s->num_players;
|
||||
zones_booted = s->num_zones;
|
||||
status = s->status;
|
||||
server_status = s->status;
|
||||
}
|
||||
|
||||
void WorldServer::SendClientAuth(unsigned int ip, string account, string key, unsigned int account_id)
|
||||
{
|
||||
ServerPacket *outapp = new ServerPacket(ServerOP_LSClientAuth, sizeof(ServerLSClientAuth));
|
||||
ServerLSClientAuth* slsca = (ServerLSClientAuth*)outapp->pBuffer;
|
||||
ServerPacket *outapp = new ServerPacket(ServerOP_LSClientAuth, sizeof(ClientAuth_Struct));
|
||||
ClientAuth_Struct* client_auth = (ClientAuth_Struct*)outapp->pBuffer;
|
||||
|
||||
slsca->lsaccount_id = account_id;
|
||||
strncpy(slsca->name, account.c_str(), account.size() > 30 ? 30 : account.size());
|
||||
strncpy(slsca->key, key.c_str(), 10);
|
||||
slsca->lsadmin = 0;
|
||||
slsca->worldadmin = 0;
|
||||
slsca->ip = ip;
|
||||
client_auth->lsaccount_id = account_id;
|
||||
strncpy(client_auth->name, account.c_str(), account.size() > 30 ? 30 : account.size());
|
||||
strncpy(client_auth->key, key.c_str(), 10);
|
||||
client_auth->lsadmin = 0;
|
||||
client_auth->worldadmin = 0;
|
||||
client_auth->ip = ip;
|
||||
|
||||
in_addr in;
|
||||
in.s_addr = ip;connection->GetrIP();
|
||||
in.s_addr = ip; connection->GetrIP();
|
||||
string client_address(inet_ntoa(in));
|
||||
in.s_addr = connection->GetrIP();
|
||||
string world_address(inet_ntoa(in));
|
||||
|
||||
if(client_address.compare(world_address) == 0)
|
||||
{
|
||||
slsca->local = 1;
|
||||
if (client_address.compare(world_address) == 0) {
|
||||
client_auth->local = 1;
|
||||
}
|
||||
else if(client_address.find(server.options.GetLocalNetwork()) != string::npos)
|
||||
{
|
||||
slsca->local = 1;
|
||||
else if (client_address.find(server.options.GetLocalNetwork()) != string::npos) {
|
||||
client_auth->local = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
slsca->local = 0;
|
||||
else {
|
||||
client_auth->local = 0;
|
||||
}
|
||||
|
||||
connection->SendPacket(outapp);
|
||||
|
||||
if(server.options.IsDumpInPacketsOn())
|
||||
if (server.options.IsDumpInPacketsOn())
|
||||
{
|
||||
DumpPacket(outapp);
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
/**
|
||||
* Gets whether the server is authorized to show up on the server list or not.
|
||||
*/
|
||||
bool IsAuthorized() const { return authorized; }
|
||||
bool IsAuthorized() const { return is_server_authorized; }
|
||||
|
||||
/**
|
||||
* Gets the local ip of the server.
|
||||
@@ -106,7 +106,7 @@ public:
|
||||
/**
|
||||
* Gets the status of the server.
|
||||
*/
|
||||
int GetStatus() const { return status; }
|
||||
int GetStatus() const { return server_status; }
|
||||
|
||||
/**
|
||||
* Gets the number of zones online on the server.
|
||||
@@ -138,7 +138,7 @@ private:
|
||||
EmuTCPConnection *connection;
|
||||
unsigned int zones_booted;
|
||||
unsigned int players_online;
|
||||
int status;
|
||||
int server_status;
|
||||
unsigned int runtime_id;
|
||||
unsigned int server_list_id;
|
||||
unsigned int server_type;
|
||||
@@ -151,9 +151,9 @@ private:
|
||||
std::string local_ip;
|
||||
std::string protocol;
|
||||
std::string version;
|
||||
bool authorized;
|
||||
bool logged_in;
|
||||
bool trusted;
|
||||
bool is_server_authorized;
|
||||
bool is_server_logged_in;
|
||||
bool is_server_trusted;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+11
-1
@@ -306,7 +306,7 @@ void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 items) {
|
||||
}
|
||||
|
||||
void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 items) {
|
||||
/* Merchant transactions are from the perspective of the merchant, not the player -U */
|
||||
/* Merchant transactions are from the perspective of the merchant, not the player */
|
||||
std::string query = StringFormat("INSERT INTO `qs_merchant_transaction_record` SET `time` = NOW(), "
|
||||
"`zone_id` = '%i', `merchant_id` = '%i', `merchant_pp` = '%i', "
|
||||
"`merchant_gp` = '%i', `merchant_sp` = '%i', `merchant_cp` = '%i', "
|
||||
@@ -386,6 +386,16 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings){
|
||||
log_settings[log_category].log_to_file = atoi(row[3]);
|
||||
log_settings[log_category].log_to_gmsay = atoi(row[4]);
|
||||
|
||||
/* Determine if any output method is enabled for the category
|
||||
and set it to 1 so it can used to check if category is enabled */
|
||||
const bool log_to_console = log_settings[log_category].log_to_console > 0;
|
||||
const bool log_to_file = log_settings[log_category].log_to_file > 0;
|
||||
const bool log_to_gmsay = log_settings[log_category].log_to_gmsay > 0;
|
||||
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay;
|
||||
|
||||
if (is_category_enabled)
|
||||
log_settings[log_category].is_category_enabled = 1;
|
||||
|
||||
/*
|
||||
This determines whether or not the process needs to actually file log anything.
|
||||
If we go through this whole loop and nothing is set to any debug level, there is no point to create a file or keep anything open
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user