mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-22 20:33:01 +00:00
Compare commits
484 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2a91f08845 | |||
| adc64005f1 | |||
| 605480f1c4 | |||
| 3b95601c62 | |||
| a4f2ed28f1 | |||
| e19b969541 | |||
| 4241556f75 | |||
| 961332b40c | |||
| a1a861e0c4 | |||
| 4bbb1aa92f | |||
| 1212ccefef | |||
| c203fec9b4 | |||
| 16ab1839e8 | |||
| f5e4c6a127 | |||
| 166c87c931 | |||
| 345dd442dd | |||
| 565baec675 | |||
| 9884c442e9 | |||
| ad0b5d6a1c | |||
| b82b32e1d2 | |||
| 2fb72e5729 | |||
| 3791bc788f | |||
| 833fa55fdf | |||
| 4fc3c27715 | |||
| cea3ad6a42 | |||
| d8926cd5f3 | |||
| efb03164c7 | |||
| 455eb2e6d9 | |||
| b5b0e53da2 | |||
| 68cb94b39c | |||
| 3d95b6c184 | |||
| 7db7631308 | |||
| f053cd3b56 | |||
| cf27f2bc88 | |||
| 79918ebaba | |||
| 2a648507f2 | |||
| f395ee0508 | |||
| 7166fcc650 | |||
| ae8e58ddc5 | |||
| 26e72c6857 | |||
| df1d740ae6 | |||
| d7e810232a | |||
| 9b992167f0 | |||
| 65d4533568 | |||
| eb545a18a4 | |||
| f2f0228aa4 | |||
| 06337fe762 | |||
| 604c7ad4ab | |||
| bab16771aa | |||
| d3a414a048 | |||
| e85a8db8c4 | |||
| 12cc3c90ea | |||
| 9c656bc498 | |||
| bc337979bb | |||
| a64425ebe6 | |||
| ca933fce45 | |||
| 9c3498b431 | |||
| d7e09a1f3b | |||
| 1652e7a976 | |||
| 37dda9bf41 | |||
| a2b78ff4e6 | |||
| 79a3ce8d7e | |||
| d857fb3c48 | |||
| 2b4cd292e4 | |||
| 3b7cfa6454 | |||
| c5fa7e28c8 | |||
| 5d133a2b47 | |||
| 7122ac33b2 | |||
| c47644ea46 | |||
| a61f951d0e | |||
| 4357b8c731 | |||
| 9cbe25f712 | |||
| c14a17e4de | |||
| ab04a4c6df | |||
| c0cf9bb5aa | |||
| b5d23389ee | |||
| dc35ab5251 | |||
| 9cbfd5c8f0 | |||
| 5631a0711f | |||
| 00e02b61ca | |||
| 108397b138 | |||
| 9a07142a9b | |||
| 919a92bda3 | |||
| 140aba9f69 | |||
| c3d41e08f4 | |||
| 5d6a1aad50 | |||
| af91b2b41c | |||
| 2660aa79ab | |||
| 730738faf9 | |||
| 2bb7bba724 | |||
| e93081dde0 | |||
| 3a46bf7383 | |||
| aa6421afdf | |||
| 6a7eaae122 | |||
| 714b474d2c | |||
| e24d82f0fe | |||
| 33a375677e | |||
| 8fce86c396 | |||
| 68b40f0239 | |||
| 2dc2bac456 | |||
| 00a8a0cf88 | |||
| 5a466da96c | |||
| de4f5ae491 | |||
| fb20d92166 | |||
| 6cff433d23 | |||
| 2da7ddad57 | |||
| 55161e18c8 | |||
| 063d4fbd1a | |||
| c25cb0cc23 | |||
| ddac326239 | |||
| 14fe396510 | |||
| c968a0acdc | |||
| 8c4cd34e01 | |||
| 0dbcf83a11 | |||
| a75648f73f | |||
| 6c2886a71d | |||
| 1d96ddb60d | |||
| c30074be66 | |||
| b5652e6010 | |||
| 202d2ed496 | |||
| 81cee49ea1 | |||
| 2d61cd2b9a | |||
| b06505b80a | |||
| 4c2f9a4423 | |||
| fb3159b657 | |||
| 8ebf5bbb78 | |||
| d2aae4d79c | |||
| f9dc9da42b | |||
| 3f3bbe98b5 | |||
| 59537ae977 | |||
| ee45a28efe | |||
| 70ce81fb0a | |||
| e06d28ad20 | |||
| d57489781c | |||
| 21d65c73b7 | |||
| 8f6d606f53 | |||
| f25e37d0c5 | |||
| e55f9b9d27 | |||
| b01486d767 | |||
| 50ce99ce3e | |||
| 4854201b2a | |||
| c81d05940a | |||
| 47be17e2af | |||
| 809b3b6099 | |||
| f06c7e8834 | |||
| 096448d23c | |||
| e55fb1cafd | |||
| d4962bb2ab | |||
| 98e56bdfe9 | |||
| 5c1be3643e | |||
| c2fa61b3a2 | |||
| 01a1186e63 | |||
| 7427318213 | |||
| d3c3d7b384 | |||
| e9e8143778 | |||
| bc71997518 | |||
| 4a9a9fa197 | |||
| ee14aed8de | |||
| 2717fcc339 | |||
| dc28c8d485 | |||
| a633784f78 | |||
| 5519c3e781 | |||
| 9401323708 | |||
| 251993c61b | |||
| 728ce0c519 | |||
| 6a80bcecc7 | |||
| 6324e3687a | |||
| d16ac99033 | |||
| e12368f002 | |||
| a13fa07e68 | |||
| 7873ad3771 | |||
| dfadc237e5 | |||
| a1f2764978 | |||
| 927d379e75 | |||
| a1f154749c | |||
| 42a2e19e73 | |||
| c56b2e3e03 | |||
| b05f1d3218 | |||
| a004924112 | |||
| 8d986c95cd | |||
| ef7a3cae17 | |||
| 050aba65b6 | |||
| 9154c90418 | |||
| d558f9ece2 | |||
| 327dacdbe1 | |||
| f2ff4245c0 | |||
| 3ceb743195 | |||
| 021f04c17d | |||
| f7e2dbdce6 | |||
| 2a679f1002 | |||
| 8c9849ec73 | |||
| 10086ce97c | |||
| 223ae22f73 | |||
| 4330494f57 | |||
| 64ae7e4529 | |||
| 58c3e267e1 | |||
| 598483a1a4 | |||
| c1122022b9 | |||
| f2c4babd8d | |||
| 5249b065d3 | |||
| 9312261444 | |||
| 85054fedf8 | |||
| 6d7beb1796 | |||
| 66e377fd4a | |||
| 67c4c26f70 | |||
| b1c8e3890a | |||
| d6e06a19a7 | |||
| 4092b3a2cb | |||
| f4f0619618 | |||
| 71ca7f9b39 | |||
| 5fcc83b4b6 | |||
| 1f25639dd3 | |||
| 2a176835b1 | |||
| fff3e77a6e | |||
| 6efb9ec228 | |||
| a663c822e8 | |||
| cf49b2fe49 | |||
| b45e0e80b5 | |||
| 3200145d01 | |||
| 53563b9720 | |||
| 1e22baf267 | |||
| d99c3145ad | |||
| 57243c6799 | |||
| 1100668f21 | |||
| 0cf454dc29 | |||
| 75391d96f4 | |||
| 81b07a5aa0 | |||
| 774aa99b29 | |||
| 756e835144 | |||
| c5c575b028 | |||
| 152e99444c | |||
| 795df5c597 | |||
| 18eff726d0 | |||
| f06a37a009 | |||
| ae53efc52c | |||
| 548eb65e1d | |||
| fede8760d4 | |||
| 6faa202b57 | |||
| c406710623 | |||
| 662c4012db | |||
| 849e7b910d | |||
| 8e33755f02 | |||
| dfaa929778 | |||
| 306b06745f | |||
| 108fc82ee0 | |||
| 577f61b082 | |||
| a01cf0718d | |||
| 90412ba61b | |||
| 5cbc380c62 | |||
| 6c289a7c71 | |||
| 57335b188f | |||
| 056e429100 | |||
| f548aeddb2 | |||
| 4ff9faa4e6 | |||
| 17fc350d46 | |||
| b18bc66b42 | |||
| 324bfd448e | |||
| 75560ee830 | |||
| 50db7637aa | |||
| 67fdc75df3 | |||
| 9993022418 | |||
| bd95ed44fd | |||
| 65fd323eab | |||
| 290c58741e | |||
| 39d0772a01 | |||
| 622fe50479 | |||
| f41a219309 | |||
| 23bc3c7fd6 | |||
| 3144ac1a28 | |||
| a5106420e8 | |||
| 5a42c4f667 | |||
| a3107cc54d | |||
| f0152cef66 | |||
| 21755a9f9e | |||
| b329515a07 | |||
| ff4b117cfa | |||
| e305ba852b | |||
| b8c91cf4f9 | |||
| cd82bd8472 | |||
| 20bed20f47 | |||
| c93054421f | |||
| b7a1fc6644 | |||
| 6bfb8fca2e | |||
| 9d6a7ad743 | |||
| 076b88be9a | |||
| 84a779c4df | |||
| 3fb479e612 | |||
| c1f4ee0e65 | |||
| 32f7dc3d1b | |||
| fa55fd1664 | |||
| c44c0d4efa | |||
| 50c63b95db | |||
| 612029de6e | |||
| dbc6346fe8 | |||
| 93a4153a4b | |||
| 434f270f68 | |||
| 5ba33b88bd | |||
| ce1de9997b | |||
| 8814ab26cd | |||
| 8c23eee42a | |||
| 5475615448 | |||
| 4a5559022f | |||
| 5be2041085 | |||
| 9f4d60ec36 | |||
| c64a2aec94 | |||
| 0e582eda82 | |||
| 7eff6ada87 | |||
| 291997d35b | |||
| ac4572bf79 | |||
| f0a9578b6a | |||
| baa824d8fb | |||
| b19d3ac8a2 | |||
| 6a393bf0c3 | |||
| 09a5551de1 | |||
| 6e2e035d66 | |||
| ac5922bb32 | |||
| ecf2a369cc | |||
| 95b306599f | |||
| 497d20512a | |||
| db916e946e | |||
| 958549b407 | |||
| 71ebf1b2d4 | |||
| e19b8d3056 | |||
| 8b1d64a043 | |||
| 576f99f292 | |||
| e3761cf2a3 | |||
| ad1764b464 | |||
| 1c9ea57a4e | |||
| 03c158b674 | |||
| 39b5374e92 | |||
| 2d3ddcb574 | |||
| ed09281f66 | |||
| 8e51bf8b19 | |||
| 844efa7e20 | |||
| fa3a5c7a72 | |||
| 93db35658a | |||
| d45a57056a | |||
| ff40dbc710 | |||
| 7523c972fa | |||
| 4320c1429e | |||
| dc8bfddd7a | |||
| a8cdfb07e6 | |||
| 011de2692e | |||
| 0cc76ab489 | |||
| c5c9985e0d | |||
| a7e95d7818 | |||
| 933d856b5b | |||
| 285cc3af29 | |||
| de8ae7afa6 | |||
| 1b272cba50 | |||
| e35e38b039 | |||
| 9215ba7a8a | |||
| 3f4334985b | |||
| 21002c2e8a | |||
| 445f967ed6 | |||
| 57a15d473f | |||
| df92c578d2 | |||
| 3af43a8e8d | |||
| 647bcce30b | |||
| 25b527156c | |||
| b3ab7deb80 | |||
| 4a9cb07132 | |||
| 8f1b62d166 | |||
| 7e9994b5d4 | |||
| f2f8fae58b | |||
| 3a1e88f9ed | |||
| 4e101aa6d6 | |||
| ef411ee154 | |||
| 93b3f97f24 | |||
| c1d4cb90b9 | |||
| e939c82717 | |||
| 7d03479f41 | |||
| ff440e16b6 | |||
| c6bb0f6495 | |||
| d142bc552a | |||
| 7dc57c3b05 | |||
| ea9b09cf1f | |||
| 968278d8f8 | |||
| aa910864c8 | |||
| 1499f3338e | |||
| fef2f9fc61 | |||
| 8afbc585da | |||
| 457ce85746 | |||
| 49c093dc62 | |||
| beccd557a8 | |||
| e11610b9fa | |||
| 3e652b98bc | |||
| d43af28de4 | |||
| f5106b6af6 | |||
| 3386d13d2d | |||
| d1b7c675f9 | |||
| a40e1cf893 | |||
| c81ab00764 | |||
| 025ef5e1d6 | |||
| 1f29a40e6d | |||
| 66cadd599b | |||
| aa0345c1f1 | |||
| 73b11c5036 | |||
| efbeb2dbb7 | |||
| 8c97c20727 | |||
| f2d07e5c69 | |||
| 64d5b54e65 | |||
| 89b3a04eb3 | |||
| 1bafe0b6b3 | |||
| 82762c3f5a | |||
| 2742eca119 | |||
| 8fc7f3a732 | |||
| 39ce0178f9 | |||
| 3d2f560436 | |||
| a0768d2d28 | |||
| 9009a7aa23 | |||
| 67b03b4e31 | |||
| b08975aefb | |||
| ea3a7cae0b | |||
| 81314a3315 | |||
| d33cfad567 | |||
| c1698a5bdd | |||
| 2a094e8792 | |||
| 4a0725e278 | |||
| 218ffbb2c5 | |||
| 3e30e78158 | |||
| ff2af0c49e | |||
| cd5697bc81 | |||
| b1571cd062 | |||
| 3e5d0a0601 | |||
| 6a80a061dd | |||
| 509fd0615e | |||
| da5e672a28 | |||
| 7090382074 | |||
| 26eabcd7a4 | |||
| 60091015d3 | |||
| 470392021b | |||
| 90984c3215 | |||
| da2296d416 | |||
| c9221f239c | |||
| f4edc69a87 | |||
| 7d04608c4d | |||
| 32be049d96 | |||
| 26fd52fb06 | |||
| 5dd849ac75 | |||
| f484fe4176 | |||
| 3d20c0d6aa | |||
| 0297045cc5 | |||
| cb90d00832 | |||
| f752b57a55 | |||
| 2bb15271c5 | |||
| 6976e27501 | |||
| c9f27d6f90 | |||
| cb129efcad | |||
| d653989b03 | |||
| ea9b373180 | |||
| a4e006fbfb | |||
| 1ffdd4cb34 | |||
| 7f7ba2e6c2 | |||
| 090086f50c | |||
| 407b003f7d | |||
| b6d315d803 | |||
| 6927177291 | |||
| 31ede355a8 | |||
| 0df84e1ee6 | |||
| 0d509a7f3a | |||
| 4c2271ff69 | |||
| ca2072e7bf | |||
| e1eb1ff738 | |||
| 25f5898bae | |||
| 934ff3dadf | |||
| e4ff76dceb | |||
| 6960a1a682 | |||
| d4174ca236 | |||
| 7854130a93 | |||
| e9c63c7d94 | |||
| 27e0665aae | |||
| ea2f431fce | |||
| 8bdcf7cb94 | |||
| 87cb74b851 | |||
| 26c267db1b | |||
| 99f8e6cef5 | |||
| b6917ec782 | |||
| eb51550109 | |||
| 9d1ace627c | |||
| ec3ef411a1 | |||
| 1394b6a4d2 | |||
| 7f41547963 | |||
| 2e4071cdcf |
+992
@@ -1,3 +1,995 @@
|
||||
## [22.28.1] - 10/20/2023
|
||||
|
||||
### Build
|
||||
|
||||
* Perl Linux build fix
|
||||
|
||||
## [22.28.0] - 10/15/2023
|
||||
|
||||
### Bots
|
||||
|
||||
* Adjust Bot Movement Speed ([#3615](https://github.com/EQEmu/Server/pull/3615)) @Kinglykrab 2023-10-14
|
||||
* Fix bot removal on zone, regression from #3611 ([#3631](https://github.com/EQEmu/Server/pull/3631)) @Akkadius 2023-10-16
|
||||
|
||||
### Crash
|
||||
|
||||
* Fix Crash with #summon ([#3618](https://github.com/EQEmu/Server/pull/3618)) @Kinglykrab 2023-10-14
|
||||
* Fix crash in Mob::ShowBuffs ([#3632](https://github.com/EQEmu/Server/pull/3632)) @Akkadius 2023-10-16
|
||||
* Resolve crash when assigning empty raid note. ([#3628](https://github.com/EQEmu/Server/pull/3628)) @Aeadoin 2023-10-15
|
||||
|
||||
### Feature
|
||||
|
||||
* Add Extra Kick Classes ([#3613](https://github.com/EQEmu/Server/pull/3613)) @Kinglykrab 2023-10-11
|
||||
* Add Immune to Assassinate Special Ability ([#3622](https://github.com/EQEmu/Server/pull/3622)) @Kinglykrab 2023-10-14
|
||||
* Add Immune to Headshot Special Ability ([#3624](https://github.com/EQEmu/Server/pull/3624)) @Kinglykrab 2023-10-14
|
||||
* Update Raid Functions for Titanium and Underfoot ([#3524](https://github.com/EQEmu/Server/pull/3524)) @neckkola 2023-10-14
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix #cast defaulting to cast time ([#3617](https://github.com/EQEmu/Server/pull/3617)) @Kinglykrab 2023-10-14
|
||||
|
||||
### Parser Fix
|
||||
|
||||
* Fix SendIllusion Spire parsing ([#3623](https://github.com/EQEmu/Server/pull/3623)) @Kinglykrab 2023-10-14
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add GrantAllAAPoints() to Perl/Lua and Modify #grantaa ([#3616](https://github.com/EQEmu/Server/pull/3616)) @Kinglykrab 2023-10-14
|
||||
* Add target ID and spell exports to events ([#3620](https://github.com/EQEmu/Server/pull/3620)) @Kinglykrab 2023-10-15
|
||||
|
||||
### Scripts
|
||||
|
||||
* Update 13th Floor importer ([#3630](https://github.com/EQEmu/Server/pull/3630)) @joligario 2023-10-16
|
||||
* Update 13th Floor script for legacy research tome bagtypes ([#3621](https://github.com/EQEmu/Server/pull/3621)) @joligario 2023-10-14
|
||||
|
||||
## [22.27.0] - 10/07/2023
|
||||
|
||||
### Crash
|
||||
|
||||
* Bot member zoned crash fix ([#3607](https://github.com/EQEmu/Server/pull/3607)) @Akkadius 2023-10-07
|
||||
* Fix #summon crash ([#3608](https://github.com/EQEmu/Server/pull/3608)) @Akkadius 2023-10-07
|
||||
* Fix CanUseAlternateAdvancementRank crash ([#3609](https://github.com/EQEmu/Server/pull/3609)) @Akkadius 2023-10-07
|
||||
* Fix crash in #movechar ([#3612](https://github.com/EQEmu/Server/pull/3612)) @Akkadius 2023-10-07
|
||||
* Fix crash in CastSpell Quest API input cast ([#3610](https://github.com/EQEmu/Server/pull/3610)) @Akkadius 2023-10-07
|
||||
* Fix dangling pointer crash observed in SendHPPacketsFrom ([#3611](https://github.com/EQEmu/Server/pull/3611)) @Akkadius 2023-10-07
|
||||
* Fix rarer crash with File::Makedir ([#3606](https://github.com/EQEmu/Server/pull/3606)) @Akkadius 2023-10-07
|
||||
|
||||
### Fixes
|
||||
|
||||
* Add Validation to #find, #set, and #show args ([#3598](https://github.com/EQEmu/Server/pull/3598)) @Kinglykrab 2023-09-18
|
||||
* Ensure Linux builds report failures @Akkadius 2023-10-03
|
||||
* Fix #show group_info Popup ([#3605](https://github.com/EQEmu/Server/pull/3605)) @Kinglykrab 2023-10-04
|
||||
* Fix swarm pet names to use '_' instead of ' ' ([#3601](https://github.com/EQEmu/Server/pull/3601)) @noudess 2023-09-19
|
||||
* Invis vs. Undead/Animal Breaks Charm for Pets ([#3587](https://github.com/EQEmu/Server/pull/3587)) @crdunwel 2023-09-19
|
||||
|
||||
### Logs
|
||||
|
||||
* Change pathing log messages from Error to Pathing. ([#3604](https://github.com/EQEmu/Server/pull/3604)) @joligario 2023-09-29
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add Caster ID Parameter to FindBuff in Perl/Lua ([#3590](https://github.com/EQEmu/Server/pull/3590)) @Kinglykrab 2023-09-29
|
||||
|
||||
## [22.26.2] - 09/18/2023
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix an issue with schema versioning for the AA update
|
||||
|
||||
## [22.26.1] - 09/17/2023
|
||||
|
||||
### Fixes
|
||||
|
||||
* Add Validation to #find, #set, and #show args ([#3598](https://github.com/EQEmu/Server/pull/3598)) @Kinglykrab 2023-09-17
|
||||
|
||||
## [22.26.0] - 09/17/2023
|
||||
|
||||
### Bug
|
||||
|
||||
* Additional Wild Ramp param was causing an overflow it appears at least on local testing. ([#3589](https://github.com/EQEmu/Server/pull/3589)) @fryguy503 2023-09-11
|
||||
|
||||
### Commands
|
||||
|
||||
* npc_edit faction and #setfaction duplicate and incorrect. ([#3577](https://github.com/EQEmu/Server/pull/3577)) @noudess 2023-09-03
|
||||
|
||||
### Feature
|
||||
|
||||
* Add Defensive Proc Rules for Level Gap Penalty ([#3580](https://github.com/EQEmu/Server/pull/3580)) @Kinglykrab 2023-09-17
|
||||
* Add opcodes for Cast and Scribe book buttons ([#3578](https://github.com/EQEmu/Server/pull/3578)) @hgtw 2023-09-17
|
||||
* Cleanup Group Split Money Logic ([#3583](https://github.com/EQEmu/Server/pull/3583)) @crdunwel 2023-09-17
|
||||
|
||||
### Fixes
|
||||
|
||||
* AA System Fixes ([#3572](https://github.com/EQEmu/Server/pull/3572)) @KimLS 2023-09-17
|
||||
* Check for Song Skill Increase on Bard Pulse ([#3586](https://github.com/EQEmu/Server/pull/3586)) @crdunwel 2023-09-17
|
||||
* Fix #set faction/#setfaction Command ([#3575](https://github.com/EQEmu/Server/pull/3575)) @Kinglykrab 2023-09-02
|
||||
* Fix Killed XYZH support in EVENT_DEATH in Perl. ([#3591](https://github.com/EQEmu/Server/pull/3591)) @Kinglykrab 2023-09-17
|
||||
* Fix entity ID on death with #castspell ([#3592](https://github.com/EQEmu/Server/pull/3592)) @Kinglykrab 2023-09-17
|
||||
* Zoning logging edge case safety @Akkadius 2023-08-29
|
||||
|
||||
### Logging
|
||||
|
||||
* Add logging to track down Wild Ramp issue ([#3588](https://github.com/EQEmu/Server/pull/3588)) @fryguy503 2023-09-11
|
||||
|
||||
### Messages
|
||||
|
||||
* Remove duplicate message on tracking begin ([#3574](https://github.com/EQEmu/Server/pull/3574)) @noudess 2023-09-11
|
||||
* Swarm pet normal damage messages were missing ([#3594](https://github.com/EQEmu/Server/pull/3594)) @noudess 2023-09-17
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add ApplySpell() and SetBuffDuration() overloads to Perl/Lua ([#3576](https://github.com/EQEmu/Server/pull/3576)) @Kinglykrab 2023-09-17
|
||||
* Add XYZ/XYZH Overloads to Cross Zone Move Methods ([#3581](https://github.com/EQEmu/Server/pull/3581)) @Kinglykrab 2023-09-17
|
||||
|
||||
## [22.25.0] - 08/28/2023
|
||||
|
||||
### Bots
|
||||
|
||||
* Add Support for Mana Pool AA Bonuses. ([#3571](https://github.com/EQEmu/Server/pull/3571)) @Aeadoin 2023-08-21
|
||||
* Remove In-Game Command References to Bot Groups ([#3545](https://github.com/EQEmu/Server/pull/3545)) @Aeadoin 2023-08-13
|
||||
|
||||
### Bug
|
||||
|
||||
* Escape item name in trader audit. ([#3540](https://github.com/EQEmu/Server/pull/3540)) @fryguy503 2023-08-13
|
||||
|
||||
### CMake
|
||||
|
||||
* Add cmake option to re-enable MSVC warnings ([#3537](https://github.com/EQEmu/Server/pull/3537)) @hgtw 2023-08-13
|
||||
* Define perlbind option for all targets ([#3538](https://github.com/EQEmu/Server/pull/3538)) @hgtw 2023-08-13
|
||||
|
||||
### Charm
|
||||
|
||||
* Fix to update target windows on charm on/off ([#3549](https://github.com/EQEmu/Server/pull/3549)) @noudess 2023-08-20
|
||||
|
||||
### Combat Messages
|
||||
|
||||
* Fix issue where pet proc damage was not showing up ([#3551](https://github.com/EQEmu/Server/pull/3551)) @noudess 2023-08-24
|
||||
|
||||
### Database
|
||||
|
||||
* Change primary key entry to NOT NULL ([#3559](https://github.com/EQEmu/Server/pull/3559)) @joligario 2023-08-20
|
||||
* Extend dumper CLI utility to export static instance data ([#3562](https://github.com/EQEmu/Server/pull/3562)) @Akkadius 2023-08-20
|
||||
|
||||
### Expansions
|
||||
|
||||
* Expansion settings tweaks ([#3556](https://github.com/EQEmu/Server/pull/3556)) @Akkadius 2023-08-20
|
||||
|
||||
### Feature
|
||||
|
||||
* Add adjustability for AERampage Range. ([#3548](https://github.com/EQEmu/Server/pull/3548)) @fryguy503 2023-08-20
|
||||
* Change #reload zone to reload zone headers globally. ([#3557](https://github.com/EQEmu/Server/pull/3557)) @Kinglykrab 2023-08-20
|
||||
* Change money type to all lower case as EQ live money shares and split has it that way. ([#3550](https://github.com/EQEmu/Server/pull/3550)) @regneq 2023-08-18
|
||||
|
||||
### Fixes
|
||||
|
||||
* Add character_stats_record to player tables @Akkadius 2023-08-11
|
||||
* Bots no longer drop group on death, and raid fixes. ([#3542](https://github.com/EQEmu/Server/pull/3542)) @Aeadoin 2023-08-13
|
||||
* Bots will now load AAs properly when spawned. ([#3544](https://github.com/EQEmu/Server/pull/3544)) @Aeadoin 2023-08-13
|
||||
* Clearing target window on CHARM wear off had a side effect ([#3570](https://github.com/EQEmu/Server/pull/3570)) @noudess 2023-08-21
|
||||
* Fix #motd/#set motd Command ([#3558](https://github.com/EQEmu/Server/pull/3558)) @Kinglykrab 2023-08-20
|
||||
* Fix Bot::CheckDataBucket to work with Owner Buckets. ([#3552](https://github.com/EQEmu/Server/pull/3552)) @Aeadoin 2023-08-18
|
||||
* Fix to zoning logging exception @Akkadius 2023-08-29
|
||||
* Instance GetUnusedInstanceID crash fox @Akkadius 2023-08-21
|
||||
* Minor adjustment to formula calc position to fix modifier bug. ([#3565](https://github.com/EQEmu/Server/pull/3565)) @Valorith 2023-08-21
|
||||
|
||||
### Instances
|
||||
|
||||
* Honor reserved instances ([#3563](https://github.com/EQEmu/Server/pull/3563)) @joligario 2023-08-21
|
||||
* Refine id selection ([#3568](https://github.com/EQEmu/Server/pull/3568)) @joligario 2023-08-29
|
||||
|
||||
### Logging
|
||||
|
||||
* Add detailed zoning logging ([#3555](https://github.com/EQEmu/Server/pull/3555)) @Akkadius 2023-08-20
|
||||
|
||||
### Quest API
|
||||
|
||||
* Reload content flags globally when a content flag is set ([#3564](https://github.com/EQEmu/Server/pull/3564)) @Akkadius 2023-08-21
|
||||
|
||||
### Rules
|
||||
|
||||
* Add FinalRaidExpMultiplier Rule ([#3554](https://github.com/EQEmu/Server/pull/3554)) @Valorith 2023-08-20
|
||||
* Add a rule to adjust the randomization range for Wizard\Caster Merc innate critical ratio. ([#3543](https://github.com/EQEmu/Server/pull/3543)) @catapultam-habeo 2023-08-13
|
||||
* Add rule to restrict hand in of quest items to quest flagged NPCs. ([#3536](https://github.com/EQEmu/Server/pull/3536)) @Valorith 2023-08-13
|
||||
* Add rule to toggle pets accepting quest items ([#3533](https://github.com/EQEmu/Server/pull/3533)) @Valorith 2023-08-06
|
||||
* Also reload rules in world when #reload rules invoked ([#3566](https://github.com/EQEmu/Server/pull/3566)) @Akkadius 2023-08-21
|
||||
* Correct explanation of Bots:ManaRegen ([#3569](https://github.com/EQEmu/Server/pull/3569)) @Aeadoin 2023-08-21
|
||||
|
||||
### Spawns
|
||||
|
||||
* Fixes a rarer issue where spawn2 is not being properly content filtered @Akkadius 2023-08-13
|
||||
|
||||
## [22.24.0] - 08/05/2023
|
||||
|
||||
### Character
|
||||
|
||||
* Record character stats to `character_stats_record` table ([#3522](https://github.com/EQEmu/Server/pull/3522)) @Akkadius 2023-08-05
|
||||
|
||||
### Code
|
||||
|
||||
* Cleanup #view zone_loot Command ([#3523](https://github.com/EQEmu/Server/pull/3523)) @Kinglykrab 2023-08-02
|
||||
* Remove Strings::Commify from all identifier values ([#3528](https://github.com/EQEmu/Server/pull/3528)) @Kinglykrab 2023-08-02
|
||||
|
||||
### Feature
|
||||
|
||||
* Add Support for Drakkin Heritage Illusions ([#3521](https://github.com/EQEmu/Server/pull/3521)) @Kinglykrab 2023-08-01
|
||||
|
||||
### Fixes
|
||||
|
||||
* Bug fix for raid mark NPC across zones ([#3525](https://github.com/EQEmu/Server/pull/3525)) @neckkola 2023-08-05
|
||||
* Bugs table should not target content database ([#3535](https://github.com/EQEmu/Server/pull/3535)) @Akkadius 2023-08-05
|
||||
* Fix +/- 0.1 XYZ Door Manipulation ([#3527](https://github.com/EQEmu/Server/pull/3527)) @Kinglykrab 2023-08-02
|
||||
* Fix issue with mob scanning when trying to use EVENT_SPAWN ([#3529](https://github.com/EQEmu/Server/pull/3529)) @Akkadius 2023-08-04
|
||||
|
||||
### Quest API
|
||||
|
||||
* Adjust GetCloseMobList calls internally ([#3530](https://github.com/EQEmu/Server/pull/3530)) @Akkadius 2023-08-04
|
||||
|
||||
## [22.23.0] - 07/31/2023
|
||||
|
||||
### Databuckets
|
||||
|
||||
* Improvements to distributed cache, reload commands ([#3519](https://github.com/EQEmu/Server/pull/3519)) @Akkadius 2023-08-01
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix #gm top level alias for #set gm ([#3517](https://github.com/EQEmu/Server/pull/3517)) @Kinglykrab 2023-07-30
|
||||
* Fix Appearance Issues ([#3520](https://github.com/EQEmu/Server/pull/3520)) @Kinglykrab 2023-08-01
|
||||
* Fix NPC Cast Events not parsing properly. ([#3518](https://github.com/EQEmu/Server/pull/3518)) @Kinglykrab 2023-08-01
|
||||
|
||||
### Scaling/Bug Fix
|
||||
|
||||
* Scaling where min and max damage was bugged ([#3514](https://github.com/EQEmu/Server/pull/3514)) @noudess 2023-08-01
|
||||
|
||||
## [22.22.1] - 07/30/2023
|
||||
|
||||
### Database
|
||||
|
||||
* Hotfix: Add command_subsettings to server tables @Akkadius 2023-07-29
|
||||
|
||||
### Doors
|
||||
|
||||
* Add door blacklist ([#3516](https://github.com/EQEmu/Server/pull/3516)) @Akkadius 2023-07-30
|
||||
|
||||
## [22.22.0] - 07/27/2023
|
||||
|
||||
### Code
|
||||
|
||||
* Fix casing in corpse money and decay time. ([#3511](https://github.com/EQEmu/Server/pull/3511)) @Kinglykrab 2023-07-23
|
||||
|
||||
### Crash Fix
|
||||
|
||||
* Guard against Spells:MaxTotalSlotsPET being set above client allowed maximum. ([#3507](https://github.com/EQEmu/Server/pull/3507)) @Valorith 2023-07-22
|
||||
|
||||
### Data Buckets
|
||||
|
||||
* Distributed Databucket Caching ([#3500](https://github.com/EQEmu/Server/pull/3500)) @Kinglykrab 2023-07-24
|
||||
|
||||
### Database
|
||||
|
||||
* Fix console output in database:dump --dump-output-to-console @Akkadius 2023-07-25
|
||||
|
||||
### Fixes
|
||||
|
||||
* Escape search string in #find item ([#3510](https://github.com/EQEmu/Server/pull/3510)) @Kinglykrab 2023-07-22
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add GetMobTypeIdentifier() to Perl/Lua ([#3512](https://github.com/EQEmu/Server/pull/3512)) @Kinglykrab 2023-07-28
|
||||
|
||||
### Saylink
|
||||
|
||||
* Fix cases where saylinks were not being cached ([#3508](https://github.com/EQEmu/Server/pull/3508)) @Akkadius 2023-07-20
|
||||
|
||||
## [22.21.2] - 07/19/2023
|
||||
|
||||
### Databuckets
|
||||
|
||||
* Fix rarer same bucket name scoping overlap issue ([#3509](https://github.com/EQEmu/Server/pull/3509)) @Akkadius 2023-07-20
|
||||
|
||||
## [22.21.1] - 07/18/2023
|
||||
|
||||
### Bug
|
||||
|
||||
* Show Petition and Show Petition_Info fix ([#3503](https://github.com/EQEmu/Server/pull/3503)) @fryguy503 2023-07-18
|
||||
|
||||
### Code
|
||||
|
||||
* Remove arbitrary teleport blocking in Tutorial and Load zones ([#3506](https://github.com/EQEmu/Server/pull/3506)) @Valorith 2023-07-19
|
||||
|
||||
### Databuckets
|
||||
|
||||
* Fix issue with expired databuckets not being expired and returned properly ([#3504](https://github.com/EQEmu/Server/pull/3504)) @Akkadius 2023-07-18
|
||||
|
||||
### Fixes
|
||||
|
||||
* #set title_suffix Argument Position ([#3505](https://github.com/EQEmu/Server/pull/3505)) @Kinglykrab 2023-07-18
|
||||
|
||||
## [22.21.0] - 07/18/2023
|
||||
|
||||
### Data Buckets
|
||||
|
||||
* Implement scoped data buckets ([#3498](https://github.com/EQEmu/Server/pull/3498)) @Akkadius 2023-07-16
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix rule check and add rule for pickpocket command ([#3492](https://github.com/EQEmu/Server/pull/3492)) @tuday2 2023-07-16
|
||||
|
||||
### Pathing
|
||||
|
||||
* Improvements to roambox logic, pathing ([#3502](https://github.com/EQEmu/Server/pull/3502)) @Akkadius 2023-07-18
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add SetLDoNPoints() to Perl/Lua ([#3496](https://github.com/EQEmu/Server/pull/3496)) @Kinglykrab 2023-07-16
|
||||
|
||||
### Z Clipping
|
||||
|
||||
* Don't issue zclip adjustments when NPC is not moving ([#3499](https://github.com/EQEmu/Server/pull/3499)) @Akkadius 2023-07-16
|
||||
|
||||
## [22.20.1] - 07/15/2023
|
||||
|
||||
### Database
|
||||
|
||||
* Fix database manifest entry for #3443 @neckkola 2023-07-15
|
||||
|
||||
## [22.20.0] - 07/15/2023
|
||||
|
||||
### Bots
|
||||
|
||||
* Remove orphaned commands related to botgroup ([#3489](https://github.com/EQEmu/Server/pull/3489)) @tuday2 2023-07-09
|
||||
|
||||
### Commands
|
||||
|
||||
* Consolidate #set-like commands into a singular #set command ([#3486](https://github.com/EQEmu/Server/pull/3486)) @Kinglykrab 2023-07-15
|
||||
|
||||
### Feature
|
||||
|
||||
* Add Support for item textures higher than 65,535 ([#3494](https://github.com/EQEmu/Server/pull/3494)) @Kinglykrab 2023-07-14
|
||||
* Update raid features ([#3443](https://github.com/EQEmu/Server/pull/3443)) @neckkola 2023-07-13
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix Tradeskill Combines with augmented items ([#3490](https://github.com/EQEmu/Server/pull/3490)) @Kinglykrab 2023-07-15
|
||||
* Fix charmed pets to follow when charmed. ([#3488](https://github.com/EQEmu/Server/pull/3488)) @noudess 2023-07-08
|
||||
* Update bot naming check and add more explanation ([#3491](https://github.com/EQEmu/Server/pull/3491)) @tuday2 2023-07-13
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add Mob/Entity type check methods to Perl/Lua ([#3493](https://github.com/EQEmu/Server/pull/3493)) @Kinglykrab 2023-07-13
|
||||
|
||||
## [22.19.0] - 07/08/2023
|
||||
|
||||
### Bots
|
||||
|
||||
* Add Pickpocket Command ([#3484](https://github.com/EQEmu/Server/pull/3484)) @tuday2 2023-07-08
|
||||
|
||||
### Code
|
||||
|
||||
* Move #find item summon links to front ([#3483](https://github.com/EQEmu/Server/pull/3483)) @Kinglykrab 2023-07-05
|
||||
* Remove LoadItemDBFieldNames() from common/misc.cpp and common/misc.h ([#3473](https://github.com/EQEmu/Server/pull/3473)) @Kinglykrab 2023-07-04
|
||||
|
||||
### Commands
|
||||
|
||||
* Add #itemsearch alias to #find aliases ([#3485](https://github.com/EQEmu/Server/pull/3485)) @Kinglykrab 2023-07-08
|
||||
* Consolidate #show commands into a singular #show command ([#3478](https://github.com/EQEmu/Server/pull/3478)) @Kinglykrab 2023-07-08
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix _PutItem having a slot_id of -1 on mobs with no items ([#3474](https://github.com/EQEmu/Server/pull/3474)) @Kinglykrab 2023-07-04
|
||||
|
||||
### Rules
|
||||
|
||||
* Add Skills:TrivialTradeskillCombinesNoFail Rule ([#3481](https://github.com/EQEmu/Server/pull/3481)) @JasXSL 2023-07-05
|
||||
|
||||
## [22.18.0] - 07/04/2023
|
||||
|
||||
### Commands
|
||||
|
||||
* Add #emotesearch to #find command ([#3480](https://github.com/EQEmu/Server/pull/3480)) @Kinglykrab 2023-07-04
|
||||
* Cleanup #copycharacter Command ([#3479](https://github.com/EQEmu/Server/pull/3479)) @Kinglykrab 2023-07-04
|
||||
|
||||
### Fixes
|
||||
|
||||
* Add chatchannel_reserved_names to a new manifest ([#3482](https://github.com/EQEmu/Server/pull/3482)) @Kinglykrab 2023-07-04
|
||||
* Fix issue in zone store of returning reference to local variable ([#3477](https://github.com/EQEmu/Server/pull/3477)) @Kinglykrab 2023-07-04
|
||||
|
||||
## [22.17.0] - 07/03/2023
|
||||
|
||||
### Cleanup/Feature
|
||||
|
||||
* Add support for bots to #showstats/#mystats ([#3427](https://github.com/EQEmu/Server/pull/3427)) @Kinglykrab 2023-07-01
|
||||
|
||||
### Code
|
||||
|
||||
* Remove LoadItemDBFieldNames() from common/misc.cpp and common/misc.h ([#3473](https://github.com/EQEmu/Server/pull/3473)) @Kinglykrab 2023-07-04
|
||||
* Remove handle_npc_single_npc from zone/lua_parser_events.cpp and zone/lua_parser_events.h ([#3467](https://github.com/EQEmu/Server/pull/3467)) @Kinglykrab 2023-07-03
|
||||
|
||||
### Database
|
||||
|
||||
* Set multi statements off when returning early ([#3462](https://github.com/EQEmu/Server/pull/3462)) @Akkadius 2023-07-01
|
||||
|
||||
### Feature
|
||||
|
||||
* Add Strings::BeginsWith() and Strings::EndsWith() ([#3471](https://github.com/EQEmu/Server/pull/3471)) @Kinglykrab 2023-07-03
|
||||
|
||||
### Fixes
|
||||
|
||||
* Add check for underscores in botcreate command ([#3458](https://github.com/EQEmu/Server/pull/3458)) @tuday2 2023-06-29
|
||||
* EVENT_LANGUAGE_SKILL_UP in Lua was using EVENT_SKILL_UP logic ([#3466](https://github.com/EQEmu/Server/pull/3466)) @Kinglykrab 2023-07-03
|
||||
* Fix _PutItem having a slot_id of -1 on mobs with no items ([#3474](https://github.com/EQEmu/Server/pull/3474)) @Kinglykrab 2023-07-04
|
||||
* Fix data type of GetAggroCount() ([#3470](https://github.com/EQEmu/Server/pull/3470)) @Kinglykrab 2023-07-03
|
||||
|
||||
### Logging
|
||||
|
||||
* Fix logging crash when % are sent through query logs ([#3461](https://github.com/EQEmu/Server/pull/3461)) @Akkadius 2023-07-01
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add ClearAccountFlag() and GetAccountFlags() to Perl/Lua ([#3469](https://github.com/EQEmu/Server/pull/3469)) @Kinglykrab 2023-07-03
|
||||
* Add GetClassAbbreviation() and GetRaceAbbreviation() to Perl/Lua ([#3463](https://github.com/EQEmu/Server/pull/3463)) @Kinglykrab 2023-07-02
|
||||
* Add GetClassPlural() and GetRacePlural() to Perl/Lua ([#3468](https://github.com/EQEmu/Server/pull/3468)) @Kinglykrab 2023-07-03
|
||||
* Add GetCloseMobList() and CalculateDistance() overload to Perl/Lua ([#3455](https://github.com/EQEmu/Server/pull/3455)) @Kinglykrab 2023-07-02
|
||||
* Add Hate Entry Methods to Perl ([#3459](https://github.com/EQEmu/Server/pull/3459)) @Kinglykrab 2023-07-02
|
||||
* Add ItemData Class to Perl ([#3465](https://github.com/EQEmu/Server/pull/3465)) @Kinglykrab 2023-07-02
|
||||
* Add Spawn2 Class to Perl ([#3456](https://github.com/EQEmu/Server/pull/3456)) @Kinglykrab 2023-07-02
|
||||
* Add StatBonuses Class to Perl ([#3460](https://github.com/EQEmu/Server/pull/3460)) @Kinglykrab 2023-07-02
|
||||
* Add missing Item Methods to Perl/Lua. ([#3464](https://github.com/EQEmu/Server/pull/3464)) @Kinglykrab 2023-07-02
|
||||
|
||||
## [22.16.0] - 06/27/2023
|
||||
|
||||
### Code
|
||||
|
||||
* Default skill type to Hand to Hand in #npcedit meleetype ([#3422](https://github.com/EQEmu/Server/pull/3422)) @Kinglykrab 2023-06-19
|
||||
* Delete common/worldconn.cpp ([#3436](https://github.com/EQEmu/Server/pull/3436)) @Kinglykrab 2023-06-24
|
||||
* Remove DatabaseCastAccepted() from zone/npc.cpp and zone/npc.h ([#3449](https://github.com/EQEmu/Server/pull/3449)) @Kinglykrab 2023-06-24
|
||||
* Remove GetACAvoid() from zone/merc.h ([#3447](https://github.com/EQEmu/Server/pull/3447)) @Kinglykrab 2023-06-25
|
||||
* Remove GetACMit() from zone/merc.h ([#3446](https://github.com/EQEmu/Server/pull/3446)) @Kinglykrab 2023-06-24
|
||||
* Remove _ClearWaypints() from zone/npc.h ([#3445](https://github.com/EQEmu/Server/pull/3445)) @Kinglykrab 2023-06-24
|
||||
* Remove acmod() from zone/merc.h ([#3448](https://github.com/EQEmu/Server/pull/3448)) @Kinglykrab 2023-06-24
|
||||
* Remove command_packetprofile from zone/command.h ([#3432](https://github.com/EQEmu/Server/pull/3432)) @Kinglykrab 2023-06-24
|
||||
* Remove command_showpetspell in zone/command.h ([#3430](https://github.com/EQEmu/Server/pull/3430)) @Kinglykrab 2023-06-24
|
||||
* Remove command_unlock from zone/command.h ([#3431](https://github.com/EQEmu/Server/pull/3431)) @Kinglykrab 2023-06-24
|
||||
|
||||
### Commands
|
||||
|
||||
* Add #finddeity Command ([#3435](https://github.com/EQEmu/Server/pull/3435)) @Kinglykrab 2023-06-26
|
||||
* Add #findlanguage Command ([#3434](https://github.com/EQEmu/Server/pull/3434)) @Kinglykrab 2023-06-25
|
||||
* Add #showspells Command ([#3429](https://github.com/EQEmu/Server/pull/3429)) @Kinglykrab 2023-06-24
|
||||
* Add missing subcommands to #npcedit ([#3423](https://github.com/EQEmu/Server/pull/3423)) @Kinglykrab 2023-06-19
|
||||
* Cleanup #showbuffs Command ([#3439](https://github.com/EQEmu/Server/pull/3439)) @Kinglykrab 2023-06-26
|
||||
* Cleanup #shownpcgloballoot and #showzonegloballoot Commands ([#3440](https://github.com/EQEmu/Server/pull/3440)) @Kinglykrab 2023-06-24
|
||||
* Cleanup #viewcurrencies Command ([#3441](https://github.com/EQEmu/Server/pull/3441)) @Kinglykrab 2023-06-25
|
||||
* Consolidate #findX commands to a singular #find Command ([#3452](https://github.com/EQEmu/Server/pull/3452)) @Kinglykrab 2023-06-28
|
||||
* Consolidate #merchant_close_shop and #merchant_open_shop to #merchantshop ([#3433](https://github.com/EQEmu/Server/pull/3433)) @Kinglykrab 2023-06-24
|
||||
* Delete #showbonusstats Command ([#3437](https://github.com/EQEmu/Server/pull/3437)) @Kinglykrab 2023-06-24
|
||||
* Delete #spellinfo Command ([#3438](https://github.com/EQEmu/Server/pull/3438)) @Kinglykrab 2023-06-24
|
||||
|
||||
### Database
|
||||
|
||||
* Fix database version checking edge case issue ([#3428](https://github.com/EQEmu/Server/pull/3428)) @Akkadius 2023-06-22
|
||||
* Fix multi-statement error reporting ([#3425](https://github.com/EQEmu/Server/pull/3425)) @Akkadius 2023-06-19
|
||||
* Implement native database migrations in server ([#2857](https://github.com/EQEmu/Server/pull/2857)) @Akkadius 2023-06-19
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix NPC Item Stat Bonuses ([#3444](https://github.com/EQEmu/Server/pull/3444)) @Kinglykrab 2023-06-26
|
||||
* Fix error in 023_01_21_bots_raid_members.sql ([#3453](https://github.com/EQEmu/Server/pull/3453)) @mibastian 2023-06-28
|
||||
* Fix possible crash with #npcedit weapon ([#3421](https://github.com/EQEmu/Server/pull/3421)) @Kinglykrab 2023-06-19
|
||||
* Merchant Open Flag set only for regular Merchants ([#3454](https://github.com/EQEmu/Server/pull/3454)) @Kinglykrab 2023-06-27
|
||||
|
||||
### Readme
|
||||
|
||||
* Update new location of database updates ([#3424](https://github.com/EQEmu/Server/pull/3424)) @joligario 2023-06-19
|
||||
|
||||
### Rules
|
||||
|
||||
* Add ClientPetsUserOwnerNameInLastName rule ([#3442](https://github.com/EQEmu/Server/pull/3442)) @Kinglykrab 2023-06-25
|
||||
|
||||
## [22.15.3] - 06/19/2023
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix improper condition in Water LOS checks ([#3426](https://github.com/EQEmu/Server/pull/3426)) @Kinglykrab 2023-06-19
|
||||
|
||||
## [22.15.2] - 06/19/2023
|
||||
|
||||
### Database
|
||||
|
||||
* Fix multi-statement error reporting ([#3425](https://github.com/EQEmu/Server/pull/3425)) @Akkadius 2023-06-19
|
||||
|
||||
## [22.15.1] - 06/19/2023
|
||||
|
||||
### Schema
|
||||
|
||||
* Add `chatchannel_reserved_names` table to `database_schema.h`
|
||||
|
||||
## [22.15.0] - 06/19/2023
|
||||
|
||||
### Code
|
||||
|
||||
* Default skill type to Hand to Hand in #npcedit meleetype ([#3422](https://github.com/EQEmu/Server/pull/3422)) @Kinglykrab 2023-06-19
|
||||
|
||||
### Commands
|
||||
|
||||
* Add missing subcommands to #npcedit ([#3423](https://github.com/EQEmu/Server/pull/3423)) @Kinglykrab 2023-06-19
|
||||
|
||||
### Database
|
||||
|
||||
* Implement native database migrations in server ([#2857](https://github.com/EQEmu/Server/pull/2857)) @Akkadius 2023-06-19
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix possible crash with #npcedit weapon ([#3421](https://github.com/EQEmu/Server/pull/3421)) @Kinglykrab 2023-06-19
|
||||
|
||||
## [22.14.1] - 06/18/2023
|
||||
|
||||
### Backups
|
||||
|
||||
* Move world database:dump to use MySQL credentials file ([#3410](https://github.com/EQEmu/Server/pull/3410)) @Akkadius 2023-06-17
|
||||
|
||||
### Binaries
|
||||
|
||||
* Add support for static linking (portable) binaries ([#3417](https://github.com/EQEmu/Server/pull/3417)) @Akkadius 2023-06-18
|
||||
|
||||
### CI
|
||||
|
||||
* Build static linux binaries ([#3419](https://github.com/EQEmu/Server/pull/3419)) @Akkadius 2023-06-18
|
||||
|
||||
### CLI
|
||||
|
||||
* Add `bots:enable` and `bots:disable` commands ([#3415](https://github.com/EQEmu/Server/pull/3415)) @Akkadius 2023-06-17
|
||||
* Add `mercs:enable` and `mercs:disable` commands ([#3416](https://github.com/EQEmu/Server/pull/3416)) @Akkadius 2023-06-18
|
||||
* Console menu validation fixes ([#3413](https://github.com/EQEmu/Server/pull/3413)) @Akkadius 2023-06-17
|
||||
|
||||
### Database
|
||||
|
||||
* Add query multi statement execution support ([#3414](https://github.com/EQEmu/Server/pull/3414)) @Akkadius 2023-06-17
|
||||
|
||||
### Feature
|
||||
|
||||
* Add Water Line of Sight Checks ([#3408](https://github.com/EQEmu/Server/pull/3408)) @nytmyr 2023-06-17
|
||||
|
||||
### Logging
|
||||
|
||||
* Logging improvements, console silencing, terminal coloring ([#3412](https://github.com/EQEmu/Server/pull/3412)) @Akkadius 2023-06-17
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add convert_money_to_string() to Perl/Lua ([#3418](https://github.com/EQEmu/Server/pull/3418)) @Kinglykrab 2023-06-18
|
||||
|
||||
### Strings
|
||||
|
||||
* Add more test cases for string utils ([#3411](https://github.com/EQEmu/Server/pull/3411)) @Akkadius 2023-06-17
|
||||
|
||||
### Targeting
|
||||
|
||||
* Fix bug when using /tar on invalid target ([#3407](https://github.com/EQEmu/Server/pull/3407)) @noudess 2023-06-17
|
||||
|
||||
### Telnet
|
||||
|
||||
* Add cross zone/world wide cast and move functionality to Telnet ([#3409](https://github.com/EQEmu/Server/pull/3409)) @Kinglykrab 2023-06-17
|
||||
|
||||
## [22.13.1] - 06/13/2023
|
||||
|
||||
### Targeting
|
||||
|
||||
* Revert #3383 ([#3405](https://github.com/EQEmu/Server/pull/3405)) @noudess 2023-06-13
|
||||
|
||||
## [22.13.0] - 06/12/2023
|
||||
|
||||
### Code
|
||||
|
||||
* Add GMFind_Struct to packet structures ([#3402](https://github.com/EQEmu/Server/pull/3402)) @Kinglykrab 2023-06-12
|
||||
* Remove CHECK_LOS_STEP from zone/common.h ([#3398](https://github.com/EQEmu/Server/pull/3398)) @Kinglykrab 2023-06-12
|
||||
* Remove CheckCoordLosNoZLeaps() from zone/entity.cpp and zone/entity.h ([#3384](https://github.com/EQEmu/Server/pull/3384)) @Kinglykrab 2023-06-12
|
||||
* Remove CountTempPets() from zone/entity.cpp and zone/entity.h ([#3390](https://github.com/EQEmu/Server/pull/3390)) @Kinglykrab 2023-06-12
|
||||
* Remove Evade() from zone/entity.cpp and zone/entity.h ([#3394](https://github.com/EQEmu/Server/pull/3394)) @Kinglykrab 2023-06-12
|
||||
* Remove GateAllClients() from zone/entity.cpp and zone/entity.h ([#3391](https://github.com/EQEmu/Server/pull/3391)) @Kinglykrab 2023-06-12
|
||||
* Remove GetClient(ip, port) from zone/entity.h ([#3386](https://github.com/EQEmu/Server/pull/3386)) @Kinglykrab 2023-06-12
|
||||
* Remove GetClientCount() from zone/entity.cpp and zone/entity.h ([#3392](https://github.com/EQEmu/Server/pull/3392)) @Kinglykrab 2023-06-12
|
||||
* Remove GetGroupByBot(), GetRaidByMob(), and GetRaidByLeaderName() from zone/entity.cpp and zone/entity.h ([#3387](https://github.com/EQEmu/Server/pull/3387)) @Kinglykrab 2023-06-12
|
||||
* Remove InteractiveChat() and TakenAction() from zone/npc.h ([#3382](https://github.com/EQEmu/Server/pull/3382)) @Kinglykrab 2023-06-12
|
||||
* Remove LimitCheckBoth() from zone/entity.cpp and zone/entity.h ([#3393](https://github.com/EQEmu/Server/pull/3393)) @Kinglykrab 2023-06-12
|
||||
* Remove NPC::AddCash() from npc.cpp/npc.h ([#3380](https://github.com/EQEmu/Server/pull/3380)) @Kinglykrab 2023-06-09
|
||||
* Remove RemoveMob() and RemoveRaid() from zone/entity.cpp and zone/entity.h ([#3389](https://github.com/EQEmu/Server/pull/3389)) @Kinglykrab 2023-06-12
|
||||
* Remove SPECIALIZE_MANA_REDUCE from zone/common.h ([#3400](https://github.com/EQEmu/Server/pull/3400)) @Kinglykrab 2023-06-12
|
||||
* Remove SendAATimer() from zone/entity.h ([#3388](https://github.com/EQEmu/Server/pull/3388)) @Kinglykrab 2023-06-12
|
||||
* Remove WriteEntityIDs() from zone/entity.cpp and zone/entity.h ([#3395](https://github.com/EQEmu/Server/pull/3395)) @Kinglykrab 2023-06-12
|
||||
* Remove _BECOMENPCPET() and _NPCPET() from zone/common.h ([#3399](https://github.com/EQEmu/Server/pull/3399)) @Kinglykrab 2023-06-12
|
||||
* Remove pDBAsyncWorkID from zone/entity.h ([#3385](https://github.com/EQEmu/Server/pull/3385)) @Kinglykrab 2023-06-12
|
||||
* Remove struct DynamicZoneSafeReturn from zone/entity.h ([#3396](https://github.com/EQEmu/Server/pull/3396)) @Kinglykrab 2023-06-12
|
||||
* Remove struct TradeEntity from zone/common.h ([#3397](https://github.com/EQEmu/Server/pull/3397)) @Kinglykrab 2023-06-12
|
||||
|
||||
### Commands
|
||||
|
||||
* Assign #opcode to a #reload alias ([#3401](https://github.com/EQEmu/Server/pull/3401)) @Kinglykrab 2023-06-12
|
||||
|
||||
### Illusions
|
||||
|
||||
* RandomizeFeatures and SetGender were killing db texture ([#3376](https://github.com/EQEmu/Server/pull/3376)) @noudess 2023-06-06
|
||||
|
||||
### Logging
|
||||
|
||||
* Fixed statements that logged incorrect data ([#3381](https://github.com/EQEmu/Server/pull/3381)) @noudess 2023-06-07
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add GetEXPForLevel() to Perl/Lua ([#3403](https://github.com/EQEmu/Server/pull/3403)) @Kinglykrab 2023-06-12
|
||||
* Add SendChannelMessage() to Perl/Lua ([#3378](https://github.com/EQEmu/Server/pull/3378)) @Kinglykrab 2023-06-04
|
||||
* Add several spell methods to Perl/Lua ([#3379](https://github.com/EQEmu/Server/pull/3379)) @Kinglykrab 2023-06-12
|
||||
|
||||
### Targeting
|
||||
|
||||
* /tar <bad target> should not untarget existing target ([#3383](https://github.com/EQEmu/Server/pull/3383)) @noudess 2023-06-12
|
||||
|
||||
## [22.12.0] - 05/29/2023
|
||||
|
||||
### Code
|
||||
|
||||
* Cleanup #setskill and #setskillall Commands ([#3367](https://github.com/EQEmu/Server/pull/3367)) @Kinglykrab 2023-05-25
|
||||
* Delete message.h ([#3348](https://github.com/EQEmu/Server/pull/3348)) @Kinglykrab 2023-05-17
|
||||
* Fix #spawn command NPCs having 0 health ([#3371](https://github.com/EQEmu/Server/pull/3371)) @Kinglykrab 2023-05-21
|
||||
* Remove CalcPetHp from spdat.h ([#3364](https://github.com/EQEmu/Server/pull/3364)) @Kinglykrab 2023-05-25
|
||||
* Remove CountNPC() and QueueManaged() from entity.cpp/entity.h ([#3346](https://github.com/EQEmu/Server/pull/3346)) @Kinglykrab 2023-05-17
|
||||
* Remove DumpMerchantList() from zone.cpp/zone.h ([#3343](https://github.com/EQEmu/Server/pull/3343)) @Kinglykrab 2023-05-17
|
||||
* Remove GetDamageReceived() and GetHealReceived() from combat_record.cpp/combat_record.h ([#3358](https://github.com/EQEmu/Server/pull/3358)) @Kinglykrab 2023-05-17
|
||||
* Remove GetEscapingEntOnHateList() from hate_list.cpp/hate_list.h ([#3353](https://github.com/EQEmu/Server/pull/3353)) @Kinglykrab 2023-05-17
|
||||
* Remove GetMaxRank() from aa_ability.cpp/aa_ability.h ([#3347](https://github.com/EQEmu/Server/pull/3347)) @Kinglykrab 2023-05-25
|
||||
* Remove IsEntityInFrenzyMode() from hate_list.cpp/hate_list.h ([#3352](https://github.com/EQEmu/Server/pull/3352)) @Kinglykrab 2023-05-17
|
||||
* Remove IsRaid() from raids.h ([#3361](https://github.com/EQEmu/Server/pull/3361)) @Kinglykrab 2023-05-25
|
||||
* Remove LoadSpawn2() and PopulateZoneSpawnListClose() from spawn2.cpp/zonedb.h ([#3344](https://github.com/EQEmu/Server/pull/3344)) @Kinglykrab 2023-05-25
|
||||
* Remove SetGraveyard() from zone.cpp/zone.h ([#3354](https://github.com/EQEmu/Server/pull/3354)) @Kinglykrab 2023-05-17
|
||||
* Remove SetTradeCash() from trading.cpp/common.h ([#3356](https://github.com/EQEmu/Server/pull/3356)) @Kinglykrab 2023-05-17
|
||||
* Remove TraderUpdate() from trading.cpp/client.h ([#3357](https://github.com/EQEmu/Server/pull/3357)) @Kinglykrab 2023-05-17
|
||||
* Remove TypeToSkill() from tradeskills.cpp/object.h ([#3355](https://github.com/EQEmu/Server/pull/3355)) @Kinglykrab 2023-05-17
|
||||
* Remove Z_AGGRO from spdat.h ([#3365](https://github.com/EQEmu/Server/pull/3365)) @Kinglykrab 2023-05-25
|
||||
* Remove numMembers from raids.h ([#3362](https://github.com/EQEmu/Server/pull/3362)) @Kinglykrab 2023-05-25
|
||||
* Set GetAugmentType() to int again ([#3335](https://github.com/EQEmu/Server/pull/3335)) @Kinglykrab 2023-05-08
|
||||
|
||||
### Commands
|
||||
|
||||
* Add #findcurrency Command ([#3368](https://github.com/EQEmu/Server/pull/3368)) @Kinglykrab 2023-05-25
|
||||
* Add entity variable command ([#3345](https://github.com/EQEmu/Server/pull/3345)) @Kinglykrab 2023-05-25
|
||||
* Cleanup #setanim ([#3350](https://github.com/EQEmu/Server/pull/3350)) @Kinglykrab 2023-05-25
|
||||
|
||||
### Feature
|
||||
|
||||
* Intoxication setter/getter for source, getter for Perl/Lua ([#3330](https://github.com/EQEmu/Server/pull/3330)) @JasXSL 2023-05-03
|
||||
|
||||
### Fixes
|
||||
|
||||
* #augmentitem bypasses augment restrictions ([#3332](https://github.com/EQEmu/Server/pull/3332)) @Kinglykrab 2023-05-07
|
||||
* Fix Heroic INT/WIS Bonuses ([#3341](https://github.com/EQEmu/Server/pull/3341)) @RekkasGit 2023-05-15
|
||||
* Fix duplicate messages in #npcedit ([#3372](https://github.com/EQEmu/Server/pull/3372)) @Kinglykrab 2023-05-21
|
||||
* Fix issue with Group Pointers/Member roles ([#3374](https://github.com/EQEmu/Server/pull/3374)) @Aeadoin 2023-05-25
|
||||
* Fix mob item bonus calc ([#3334](https://github.com/EQEmu/Server/pull/3334)) @Akkadius 2023-05-07
|
||||
* Fix typos in #zheader ([#3370](https://github.com/EQEmu/Server/pull/3370)) @Kinglykrab 2023-05-21
|
||||
* Mob scaling issue with min dmg set to zero while max dmg is not ([#3351](https://github.com/EQEmu/Server/pull/3351)) @RekkasGit 2023-05-20
|
||||
* NPC Armor Upgrade to a slot not handled correctly ([#3366](https://github.com/EQEmu/Server/pull/3366)) @noudess 2023-05-20
|
||||
* ReloadQuests() on Zone::Init() to avoid cached global quests/plugins ([#3333](https://github.com/EQEmu/Server/pull/3333)) @Kinglykrab 2023-05-07
|
||||
* Revert " ReloadQuests() on Zone::Init() to avoid cached global quests/plugins " ([#3333](https://github.com/EQEmu/Server/pull/3333)) @Akkadius 2023-05-08
|
||||
|
||||
### Memory Leak
|
||||
|
||||
* Fix large memory leak introduced in CalcItemBonuses ([#3331](https://github.com/EQEmu/Server/pull/3331)) @Akkadius 2023-05-07
|
||||
|
||||
### Messages
|
||||
|
||||
* Remove duplicate heal message for healing yourself ([#3329](https://github.com/EQEmu/Server/pull/3329)) @noudess 2023-05-03
|
||||
|
||||
### Performance
|
||||
|
||||
* Character bind is now bulk saved ([#3338](https://github.com/EQEmu/Server/pull/3338)) @Akkadius 2023-05-09
|
||||
* Character buffs now save in bulk ([#3336](https://github.com/EQEmu/Server/pull/3336)) @Akkadius 2023-05-09
|
||||
* Character pet bulk saving ([#3337](https://github.com/EQEmu/Server/pull/3337)) @Akkadius 2023-05-09
|
||||
* Character tribute is now bulk saved ([#3340](https://github.com/EQEmu/Server/pull/3340)) @Kinglykrab 2023-05-25
|
||||
* Mail key is now cached during player load ([#3339](https://github.com/EQEmu/Server/pull/3339)) @Akkadius 2023-05-09
|
||||
|
||||
### Pets
|
||||
|
||||
* Fix saving inconsistencies with pets ([#3375](https://github.com/EQEmu/Server/pull/3375)) @Akkadius 2023-05-25
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add GetHateListClosest(), GetHateListClosestBot(), GetHateListClosestClient(), and GetHateListClosestNPC() methods/overloads to Perl/Lua ([#3359](https://github.com/EQEmu/Server/pull/3359)) @RekkasGit 2023-05-16
|
||||
* Add GetPet() to Perl ([#3309](https://github.com/EQEmu/Server/pull/3309)) @Kinglykrab 2023-05-08
|
||||
* Add Memorize and Scribe Spell Events to Perl/Lua ([#3363](https://github.com/EQEmu/Server/pull/3363)) @Kinglykrab 2023-05-25
|
||||
* Add zone data methods to Perl/Lua ([#3342](https://github.com/EQEmu/Server/pull/3342)) @Kinglykrab 2023-05-24
|
||||
* Cleanup The Darkened Sea Quest Methods Names ([#3369](https://github.com/EQEmu/Server/pull/3369)) @Kinglykrab 2023-05-21
|
||||
|
||||
### Rules
|
||||
|
||||
* Add World:MaximumQuestErrors Rule ([#3349](https://github.com/EQEmu/Server/pull/3349)) @Kinglykrab 2023-05-21
|
||||
* ResurrectionEffectBlock to prevent/allow/move buffs. ([#3288](https://github.com/EQEmu/Server/pull/3288)) @nytmyr 2023-05-08
|
||||
|
||||
## [22.11.0] - 04/29/2023
|
||||
|
||||
### Code
|
||||
|
||||
* Add check for owner in quest::pausetimer() ([#3304](https://github.com/EQEmu/Server/pull/3304)) @Kinglykrab 2023-04-23
|
||||
* Add check for owner in quest::resumetimer() ([#3305](https://github.com/EQEmu/Server/pull/3305)) @Kinglykrab 2023-04-23
|
||||
* Add initiator/owner checks to various methods in questmgr.cpp ([#3306](https://github.com/EQEmu/Server/pull/3306)) @Kinglykrab 2023-04-23
|
||||
* Fix possible nullptr in quest::addloot() ([#3303](https://github.com/EQEmu/Server/pull/3303)) @Kinglykrab 2023-04-23
|
||||
* Remove GetClassHPFactor() from zone/client_mods.cpp and zone/client.h ([#3313](https://github.com/EQEmu/Server/pull/3313)) @Kinglykrab 2023-04-30
|
||||
* Remove GetClassHPFactor() from zone/merc.h ([#3314](https://github.com/EQEmu/Server/pull/3314)) @Kinglykrab 2023-04-30
|
||||
* Remove pDontCastBefore_casting_spell from zone/npc.h ([#3311](https://github.com/EQEmu/Server/pull/3311)) @Kinglykrab 2023-04-30
|
||||
* Remove unused code in zone/pets.cpp ([#3310](https://github.com/EQEmu/Server/pull/3310)) @Kinglykrab 2023-04-30
|
||||
* Remove unused methods in zone/bot.cpp and zone/bot.h ([#3315](https://github.com/EQEmu/Server/pull/3315)) @Kinglykrab 2023-04-30
|
||||
* Remove unused methods in zone/client.cpp and zone/client.h ([#3312](https://github.com/EQEmu/Server/pull/3312)) @Kinglykrab 2023-04-30
|
||||
* Remove unused variable in common/crash.cpp ([#3308](https://github.com/EQEmu/Server/pull/3308)) @Kinglykrab 2023-04-30
|
||||
* Use default ctor/dtor in oriented_bounding_box.h ([#3307](https://github.com/EQEmu/Server/pull/3307)) @Kinglykrab 2023-04-30
|
||||
* quest::createBot() unnecessary check against nullptr ([#3302](https://github.com/EQEmu/Server/pull/3302)) @Kinglykrab 2023-04-23
|
||||
* quest::setallskill() had always true condition. ([#3301](https://github.com/EQEmu/Server/pull/3301)) @Kinglykrab 2023-04-30
|
||||
|
||||
### Crash
|
||||
|
||||
* Fix UCS crash that occurs during log reloading ([#3324](https://github.com/EQEmu/Server/pull/3324)) @Akkadius 2023-04-30
|
||||
* Fix possible dereference of nullptr in Client::CalcHPRegen ([#3316](https://github.com/EQEmu/Server/pull/3316)) @Aeadoin 2023-04-23
|
||||
* Fix possible nullptr in Client::GetCharMaxLevelFromQGlobal() ([#3317](https://github.com/EQEmu/Server/pull/3317)) @Kinglykrab 2023-04-23
|
||||
|
||||
### Discord
|
||||
|
||||
* Add Discord webhook callback processing to world ([#3322](https://github.com/EQEmu/Server/pull/3322)) @Akkadius 2023-04-30
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix issue with NPCs no longer using some armor. ([#3318](https://github.com/EQEmu/Server/pull/3318)) @noudess 2023-04-24
|
||||
* Fix issue with spawning Mercs ([#3327](https://github.com/EQEmu/Server/pull/3327)) @Aeadoin 2023-04-29
|
||||
* Possible issues with SummonItem in Client::QuestReward() methods ([#3325](https://github.com/EQEmu/Server/pull/3325)) @Kinglykrab 2023-04-27
|
||||
|
||||
### Maps
|
||||
|
||||
* Update download with faster releases link ([#3321](https://github.com/EQEmu/Server/pull/3321)) @Akkadius 2023-04-30
|
||||
|
||||
### Messages
|
||||
|
||||
* Remove duplicate you have lost a level message ([#3323](https://github.com/EQEmu/Server/pull/3323)) @noudess 2023-04-25
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add GetDefaultRaceSize() overloads to Perl/Lua ([#3320](https://github.com/EQEmu/Server/pull/3320)) @Kinglykrab 2023-04-30
|
||||
* Add HasSpellEffect() to Perl/Lua ([#3319](https://github.com/EQEmu/Server/pull/3319)) @Kinglykrab 2023-04-30
|
||||
|
||||
## [22.10.0] - 04/22/2023
|
||||
|
||||
### Backups
|
||||
|
||||
* Fix database dump error reporting ([#3175](https://github.com/EQEmu/Server/pull/3175)) @Akkadius 2023-04-04
|
||||
|
||||
### Bots
|
||||
|
||||
* Cleanup GetBotTables() ([#3270](https://github.com/EQEmu/Server/pull/3270)) @Aeadoin 2023-04-06
|
||||
|
||||
### Cleanuo
|
||||
|
||||
* Only define row if we have results in Database::GetCharacterID() ([#3199](https://github.com/EQEmu/Server/pull/3199)) @Kinglykrab 2023-04-05
|
||||
|
||||
### Code
|
||||
|
||||
* Add missing breaks and returns in bonuses.cpp ([#3231](https://github.com/EQEmu/Server/pull/3231)) @Kinglykrab 2023-04-05
|
||||
* Breaks in wrong spot in cases in spell_effects.cpp ([#3297](https://github.com/EQEmu/Server/pull/3297)) @Kinglykrab 2023-04-22
|
||||
* Cleanup always true/false statements in shareddb.cpp ([#3189](https://github.com/EQEmu/Server/pull/3189)) @Kinglykrab 2023-04-05
|
||||
* Cleanup cheap-to-copy reference to use value instead in eq_stream_ident.cpp/eq_stream_ident.h ([#3209](https://github.com/EQEmu/Server/pull/3209)) @Kinglykrab 2023-04-05
|
||||
* Cleanup discord.cpp and discord_manager.cpp ([#3205](https://github.com/EQEmu/Server/pull/3205)) @Kinglykrab 2023-04-05
|
||||
* Cleanup duplicate conditions in negate bonuses in bonuses.cpp ([#3226](https://github.com/EQEmu/Server/pull/3226)) @Kinglykrab 2023-04-05
|
||||
* Cleanup item_instance.cpp always true statements and reassigning of same values ([#3187](https://github.com/EQEmu/Server/pull/3187)) @Kinglykrab 2023-04-05
|
||||
* Cleanup macros in features.h ([#3185](https://github.com/EQEmu/Server/pull/3185)) @Kinglykrab 2023-04-05
|
||||
* Cleanup string -> char* -> string conversions in bot_command.cpp ([#3252](https://github.com/EQEmu/Server/pull/3252)) @Kinglykrab 2023-04-05
|
||||
* Cleanup unnecessary condition in Client::SendAlternateCurrencyValue() ([#3266](https://github.com/EQEmu/Server/pull/3266)) @Kinglykrab 2023-04-05
|
||||
* Cleanup zone/zoning.cpp ([#3289](https://github.com/EQEmu/Server/pull/3289)) @Kinglykrab 2023-04-14
|
||||
* Combine similar cases in Client::InitInnates() ([#3260](https://github.com/EQEmu/Server/pull/3260)) @Kinglykrab 2023-04-05
|
||||
* Convert equipable_slot_list to std::vector from std::list in bot_command.cpp ([#3253](https://github.com/EQEmu/Server/pull/3253)) @Kinglykrab 2023-04-05
|
||||
* Delete embxs.cpp/embxs.h ([#3284](https://github.com/EQEmu/Server/pull/3284)) @Kinglykrab 2023-04-14
|
||||
* Delete unused strings in bot_command.cpp ([#3251](https://github.com/EQEmu/Server/pull/3251)) @Kinglykrab 2023-04-05
|
||||
* Fix GetLastName() length check in Client::SendWindow() ([#3263](https://github.com/EQEmu/Server/pull/3263)) @Kinglykrab 2023-04-05
|
||||
* Fix always false conditions in Client::IncStats() ([#3256](https://github.com/EQEmu/Server/pull/3256)) @Kinglykrab 2023-04-05
|
||||
* Fix check for !this in Client::SendHPUpdateMarquee() ([#3257](https://github.com/EQEmu/Server/pull/3257)) @Kinglykrab 2023-04-05
|
||||
* Fix filter condition in attack.cpp ([#3218](https://github.com/EQEmu/Server/pull/3218)) @Kinglykrab 2023-04-05
|
||||
* Fix ornamentation augment icons in inspect requests ([#3264](https://github.com/EQEmu/Server/pull/3264)) @Kinglykrab 2023-04-05
|
||||
* Fix possible nullptr inst in GetSharedBank() ([#3190](https://github.com/EQEmu/Server/pull/3190)) @Kinglykrab 2023-04-08
|
||||
* Fix possible overflows in Client::AddPlatinum() and Client::TakePlatinum() ([#3255](https://github.com/EQEmu/Server/pull/3255)) @Kinglykrab 2023-04-05
|
||||
* Fix shared_tasks.cpp/shared_tasks.cpp variable named same as class member ([#3192](https://github.com/EQEmu/Server/pull/3192)) @Kinglykrab 2023-04-05
|
||||
* Fix skill_used being used as boolean in Mob::CommonDamage() ([#3220](https://github.com/EQEmu/Server/pull/3220)) @Kinglykrab 2023-04-05
|
||||
* Identical conditions right beside each other in aa.cpp ([#3213](https://github.com/EQEmu/Server/pull/3213)) @Kinglykrab 2023-04-05
|
||||
* Move unreachable code in ApplySpellsBonuses() ([#3229](https://github.com/EQEmu/Server/pull/3229)) @Kinglykrab 2023-04-05
|
||||
* Move variable definition to more relevant scope in DatabaseDumpService::Dump() ([#3200](https://github.com/EQEmu/Server/pull/3200)) @Kinglykrab 2023-04-05
|
||||
* Multiple cases with same outcome in GetDiscordPayloadFromEvent() ([#3184](https://github.com/EQEmu/Server/pull/3184)) @Kinglykrab 2023-04-05
|
||||
* Remove ExportVarComplex() from embparser.cpp/embparser.h ([#3282](https://github.com/EQEmu/Server/pull/3282)) @Kinglykrab 2023-04-14
|
||||
* Remove GetQGlobal() from qglobals.cpp/qglobals.h ([#3285](https://github.com/EQEmu/Server/pull/3285)) @Kinglykrab 2023-04-14
|
||||
* Remove IsFullHP from mob.cpp/mob.h ([#3277](https://github.com/EQEmu/Server/pull/3277)) @Kinglykrab 2023-04-14
|
||||
* Remove IsMeleeDmg() from skills.cpp/skills.h ([#3279](https://github.com/EQEmu/Server/pull/3279)) @Kinglykrab 2023-04-14
|
||||
* Remove _GetMovementSpeed() from mob.h ([#3276](https://github.com/EQEmu/Server/pull/3276)) @Kinglykrab 2023-04-14
|
||||
* Remove always true condition in Strings::Commify() ([#3193](https://github.com/EQEmu/Server/pull/3193)) @Kinglykrab 2023-04-05
|
||||
* Remove always true conditions and unreachable code in Client::SendMercPersonalInfo() ([#3258](https://github.com/EQEmu/Server/pull/3258)) @Kinglykrab 2023-04-05
|
||||
* Remove always true statement in say_link.cpp ([#3188](https://github.com/EQEmu/Server/pull/3188)) @Kinglykrab 2023-04-05
|
||||
* Remove always true statements in task_client_state.cpp ([#3292](https://github.com/EQEmu/Server/pull/3292)) @Kinglykrab 2023-04-14
|
||||
* Remove always true/false conditions from bot.cpp ([#3237](https://github.com/EQEmu/Server/pull/3237)) @Kinglykrab 2023-04-05
|
||||
* Remove bool return from GetSharedPlatinum() ([#3191](https://github.com/EQEmu/Server/pull/3191)) @Kinglykrab 2023-04-05
|
||||
* Remove extra assignment of current_endurance in Client ctor ([#3261](https://github.com/EQEmu/Server/pull/3261)) @Kinglykrab 2023-04-05
|
||||
* Remove extraneous check for NegateAttacks in SE_NegateAttacks ([#3228](https://github.com/EQEmu/Server/pull/3228)) @Kinglykrab 2023-04-05
|
||||
* Remove extraneous parentheses around math in Mob::ApplySpellsBonuses() ([#3227](https://github.com/EQEmu/Server/pull/3227)) @Kinglykrab 2023-04-05
|
||||
* Remove getd(), geti(), InUse(), lasterr(), my_get_sv(), and VarExists() in embperl.cpp/embperl.h ([#3283](https://github.com/EQEmu/Server/pull/3283)) @Kinglykrab 2023-04-15
|
||||
* Remove item_timers from questmgr.cpp/questmgr.h ([#3286](https://github.com/EQEmu/Server/pull/3286)) @Kinglykrab 2023-04-14
|
||||
* Remove pendinggroup from mob.h ([#3278](https://github.com/EQEmu/Server/pull/3278)) @Kinglykrab 2023-04-14
|
||||
* Remove position_same_update_count from client.cpp/client.h ([#3280](https://github.com/EQEmu/Server/pull/3280)) @Kinglykrab 2023-04-14
|
||||
* Remove unnecessary break in while loop in Mob::AddToHateList() ([#3219](https://github.com/EQEmu/Server/pull/3219)) @Kinglykrab 2023-04-05
|
||||
* Remove unnecessary check for IsStackable() in DeleteItem() ([#3186](https://github.com/EQEmu/Server/pull/3186)) @Kinglykrab 2023-04-05
|
||||
* Remove unnecessary condition and cleanup variable name in tasks.cpp ([#3293](https://github.com/EQEmu/Server/pull/3293)) @Kinglykrab 2023-04-14
|
||||
* Remove unnecessary conditions in Client::Consume() ([#3265](https://github.com/EQEmu/Server/pull/3265)) @Kinglykrab 2023-04-05
|
||||
* Remove unnecessary conditions in Client::FilteredMessageCheck() ([#3262](https://github.com/EQEmu/Server/pull/3262)) @Kinglykrab 2023-04-05
|
||||
* Remove unnecessary conditions in Client::SendFactionMessage() ([#3267](https://github.com/EQEmu/Server/pull/3267)) @Kinglykrab 2023-04-05
|
||||
* Remove unnecessary setting of reuse variable in Bot::DoClassAttacks() ([#3233](https://github.com/EQEmu/Server/pull/3233)) @Kinglykrab 2023-04-05
|
||||
* Remove unused SetConfigFile in common/eqemu_config.h ([#3208](https://github.com/EQEmu/Server/pull/3208)) @Kinglykrab 2023-04-05
|
||||
* Remove unused code in eq_packet.cpp/eq_packet.h ([#3183](https://github.com/EQEmu/Server/pull/3183)) @Kinglykrab 2023-04-05
|
||||
* Remove unused ctor and use default dtor in xtargetautohaters.h ([#3290](https://github.com/EQEmu/Server/pull/3290)) @Kinglykrab 2023-04-14
|
||||
* Remove unused macros in common/types.h ([#3194](https://github.com/EQEmu/Server/pull/3194)) @Kinglykrab 2023-04-05
|
||||
* Remove unused variable in Database::CopyCharacter() ([#3197](https://github.com/EQEmu/Server/pull/3197)) @Kinglykrab 2023-04-05
|
||||
* Remove unused variables and use reference in task_manager.cpp ([#3291](https://github.com/EQEmu/Server/pull/3291)) @Kinglykrab 2023-04-14
|
||||
* SE_AttackSpeed3 effect_value is always less than 0 ([#3222](https://github.com/EQEmu/Server/pull/3222)) @Kinglykrab 2023-04-05
|
||||
* SE_StrikeThrough and SE_StrikeThrough2 are the same in bonuses.cpp ([#3223](https://github.com/EQEmu/Server/pull/3223)) @Kinglykrab 2023-04-05
|
||||
* Set bonuses to use spell ID instead of boolean ([#3230](https://github.com/EQEmu/Server/pull/3230)) @Kinglykrab 2023-04-05
|
||||
* Use .clear() and .empty() instead of comparing to empty string or setting to empty string in CheckDatabaseConvertPPBlob() ([#3201](https://github.com/EQEmu/Server/pull/3201)) @Kinglykrab 2023-04-05
|
||||
* Use .clear() instead of setting string to empty in eqemu_command_handler.cpp ([#3195](https://github.com/EQEmu/Server/pull/3195)) @Kinglykrab 2023-04-05
|
||||
* Use .empty() in Client::ScribeSpells() and Client::LearnDisciplines() ([#3259](https://github.com/EQEmu/Server/pull/3259)) @Kinglykrab 2023-04-05
|
||||
* Use constant reference and check for empty string properly in dbcore.cpp ([#3203](https://github.com/EQEmu/Server/pull/3203)) @Kinglykrab 2023-04-05
|
||||
* Use default ctor instead of an empty ctor. ([#3206](https://github.com/EQEmu/Server/pull/3206)) @Kinglykrab 2023-04-05
|
||||
* Use default dtor instead of empty dtor for EQTime in eqtime.cpp/eqtime.h ([#3210](https://github.com/EQEmu/Server/pull/3210)) @Kinglykrab 2023-04-05
|
||||
* Use variable for c->GetTarget() instead of calling multiple times in bot_command.cpp ([#3254](https://github.com/EQEmu/Server/pull/3254)) @Kinglykrab 2023-04-05
|
||||
* Use variable for character instead of a loop ([#3268](https://github.com/EQEmu/Server/pull/3268)) @Kinglykrab 2023-04-05
|
||||
* Utilize .empty() instead of checking for an empty string in Database::ReserveName() ([#3198](https://github.com/EQEmu/Server/pull/3198)) @Kinglykrab 2023-04-05
|
||||
* Utilize IsTaunting(), SetPetPower(), SetPetType(), and SetTaunting() ([#3275](https://github.com/EQEmu/Server/pull/3275)) @Kinglykrab 2023-04-15
|
||||
* Validate for nullptrs in bot.cpp ([#3232](https://github.com/EQEmu/Server/pull/3232)) @Kinglykrab 2023-04-05
|
||||
* other is always defined in these cases in attack.cpp ([#3217](https://github.com/EQEmu/Server/pull/3217)) @Kinglykrab 2023-04-05
|
||||
* results variable is assigned but never used in SaveCharacterCreate() ([#3180](https://github.com/EQEmu/Server/pull/3180)) @Kinglykrab 2023-04-05
|
||||
|
||||
### Crash
|
||||
|
||||
* Add additional raid integrity checks on Bot Spawn. ([#3295](https://github.com/EQEmu/Server/pull/3295)) @Aeadoin 2023-04-16
|
||||
* Fix crash with uninitialized item instance, and Bot timeout ([#3296](https://github.com/EQEmu/Server/pull/3296)) @Aeadoin 2023-04-15
|
||||
* Resolve crash due to uninitialized pointer. ([#3271](https://github.com/EQEmu/Server/pull/3271)) @Aeadoin 2023-04-08
|
||||
|
||||
### Feature
|
||||
|
||||
* Make ornamentations work with any augment type ([#3281](https://github.com/EQEmu/Server/pull/3281)) @Kinglykrab 2023-04-16
|
||||
|
||||
### Fixes
|
||||
|
||||
* Camping was causing player to leave raid, causing unexpected behavior ([#3299](https://github.com/EQEmu/Server/pull/3299)) @Aeadoin 2023-04-22
|
||||
* Resolve loading of inventory ([#3272](https://github.com/EQEmu/Server/pull/3272)) @Aeadoin 2023-04-08
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add ApplySpellRaid() and SetSpellDurationRaid() to Bots in Perl/Lua ([#3274](https://github.com/EQEmu/Server/pull/3274)) @Kinglykrab 2023-04-09
|
||||
* Add GetBuffSpellIDs() to Perl/Lua ([#3273](https://github.com/EQEmu/Server/pull/3273)) @Kinglykrab 2023-04-09
|
||||
* Fix LDoN Methods in Perl/Lua ([#3287](https://github.com/EQEmu/Server/pull/3287)) @Kinglykrab 2023-04-10
|
||||
|
||||
### Rules
|
||||
|
||||
* Optional summoning when already in melee range ([#3204](https://github.com/EQEmu/Server/pull/3204)) @trentdm 2023-04-08
|
||||
|
||||
### Telnet
|
||||
|
||||
* Telnet encoding fix ([#3269](https://github.com/EQEmu/Server/pull/3269)) @Akkadius 2023-04-05
|
||||
|
||||
## [22.9.1] - 04/03/2023
|
||||
|
||||
### Code
|
||||
|
||||
* Add client pointer validation to Zone::GetClosestZonePoint() ([#3173](https://github.com/EQEmu/Server/pull/3173)) @Kinglykrab 2023-04-01
|
||||
* Change level to bot_level in Bot::DoClassAttacks() to not overlap member variable ([#3239](https://github.com/EQEmu/Server/pull/3239)) @Kinglykrab 2023-04-03
|
||||
* Cleanup unnecessary string -> char* -> string conversions in eqemu_config.cpp ([#3207](https://github.com/EQEmu/Server/pull/3207)) @Kinglykrab 2023-04-03
|
||||
* Cleanup uses of insert/push_back when a temp object is used. ([#3170](https://github.com/EQEmu/Server/pull/3170)) @Aeadoin 2023-04-03
|
||||
* Cleanup variable names in Bot::AddSpellToBotList() ([#3248](https://github.com/EQEmu/Server/pull/3248)) @Kinglykrab 2023-04-03
|
||||
* Explicitly cast to float for more precision in Bot::GenerateBastHitPoints() ([#3238](https://github.com/EQEmu/Server/pull/3238)) @Kinglykrab 2023-04-03
|
||||
* Fix SEResist array settings duplicate code ([#3225](https://github.com/EQEmu/Server/pull/3225)) @Kinglykrab 2023-04-03
|
||||
* Fix loop and code duplication for SE_ProcOnKillShot ([#3224](https://github.com/EQEmu/Server/pull/3224)) @Kinglykrab 2023-04-03
|
||||
* Fix possible dereferencing of invalid iterator in constants ([#3181](https://github.com/EQEmu/Server/pull/3181)) @Kinglykrab 2023-04-03
|
||||
* Fix typo where itembonuses should have been used instead of spellbonuses ([#3221](https://github.com/EQEmu/Server/pull/3221)) @Kinglykrab 2023-04-03
|
||||
* Further bot.cpp nullptr checks ([#3240](https://github.com/EQEmu/Server/pull/3240)) @Kinglykrab 2023-04-03
|
||||
* Move cases in Bot::AICastSpell() ([#3247](https://github.com/EQEmu/Server/pull/3247)) @Kinglykrab 2023-04-03
|
||||
* Multiple cases same outcome and set skip variable to same value ([#3216](https://github.com/EQEmu/Server/pull/3216)) @Kinglykrab 2023-04-03
|
||||
* Multiple cases with same outcome in GetGMSayColorFromCategory() ([#3182](https://github.com/EQEmu/Server/pull/3182)) @Kinglykrab 2023-04-03
|
||||
* Remove extraneous loottable_id setting in WakeTheDead in aa.cpp ([#3215](https://github.com/EQEmu/Server/pull/3215)) @Kinglykrab 2023-04-03
|
||||
* Remove possible dereferenced nullptrs in bot.cpp ([#3241](https://github.com/EQEmu/Server/pull/3241)) @Kinglykrab 2023-04-03
|
||||
* Remove unnecessary >= 0 checks for procs in botspellsai.cpp ([#3242](https://github.com/EQEmu/Server/pull/3242)) @Kinglykrab 2023-04-03
|
||||
* Remove unnecessary botCaster check in Bot::GetDebuffBotSpell() ([#3246](https://github.com/EQEmu/Server/pull/3246)) @Kinglykrab 2023-04-03
|
||||
* Remove unnecessary group validation in Bot::Death() ([#3235](https://github.com/EQEmu/Server/pull/3235)) @Kinglykrab 2023-04-03
|
||||
* Remove unnecessary hpr checks in Bot::BotCastHeal() ([#3245](https://github.com/EQEmu/Server/pull/3245)) @Kinglykrab 2023-04-03
|
||||
* Remove unnecessary setting of spell_type_index in Bot::GetChanceToCastBySpellType() ([#3243](https://github.com/EQEmu/Server/pull/3243)) @Kinglykrab 2023-04-03
|
||||
* Remove unnecessary skill_to_use check in Bot::DoClassAttacks() ([#3236](https://github.com/EQEmu/Server/pull/3236)) @Kinglykrab 2023-04-03
|
||||
* Remove unnecessary spell_list validation check in botspellsai.cpp ([#3244](https://github.com/EQEmu/Server/pull/3244)) @Kinglykrab 2023-04-03
|
||||
* Remove unnecessary validation check in Zone::ClearBlockedSpells() ([#3172](https://github.com/EQEmu/Server/pull/3172)) @Kinglykrab 2023-04-01
|
||||
* Remove unused Includes under zone files ([#3162](https://github.com/EQEmu/Server/pull/3162)) @Aeadoin 2023-04-02
|
||||
* Remove unused query variable in Database::DeleteInstance() ([#3202](https://github.com/EQEmu/Server/pull/3202)) @Kinglykrab 2023-04-03
|
||||
* Unconditional return in for loop in GetRaidByCharID() ([#3179](https://github.com/EQEmu/Server/pull/3179)) @Kinglykrab 2023-04-03
|
||||
* Use a constant reference for content_flags in SetContentFlags() ([#3196](https://github.com/EQEmu/Server/pull/3196)) @Kinglykrab 2023-04-03
|
||||
* Wake The Dead argument was named the same as a member variable in Mob ([#3214](https://github.com/EQEmu/Server/pull/3214)) @Kinglykrab 2023-04-03
|
||||
* gid is assigned 2 values simultaneously in bot.cpp ([#3234](https://github.com/EQEmu/Server/pull/3234)) @Kinglykrab 2023-04-03
|
||||
* summon_count > MAX_SWARM_PETS is always false in aa.cpp ([#3212](https://github.com/EQEmu/Server/pull/3212)) @Kinglykrab 2023-04-03
|
||||
|
||||
### Fixes
|
||||
|
||||
* Correct Forward Declaration compilation warning ([#3176](https://github.com/EQEmu/Server/pull/3176)) @Aeadoin 2023-04-02
|
||||
* Fix issue with Bot Raid invites not working. ([#3249](https://github.com/EQEmu/Server/pull/3249)) @Aeadoin 2023-04-03
|
||||
|
||||
### Performance
|
||||
|
||||
* Change to use Pass by reference where valid. ([#3163](https://github.com/EQEmu/Server/pull/3163)) @Aeadoin 2023-04-02
|
||||
|
||||
## [22.9.0] - 04/01/2023
|
||||
|
||||
### Bots
|
||||
|
||||
* Remove Bot Groups Functionality ([#3165](https://github.com/EQEmu/Server/pull/3165)) @Aeadoin 2023-04-01
|
||||
|
||||
### Code
|
||||
|
||||
* Cleanup excessive type casting: string -> char * -> string ([#3169](https://github.com/EQEmu/Server/pull/3169)) @Aeadoin 2023-04-01
|
||||
|
||||
### Crash
|
||||
|
||||
* Add Checks for valid pointers or fix existing. ([#3164](https://github.com/EQEmu/Server/pull/3164)) @Aeadoin 2023-04-01
|
||||
* Fix out of bound arrays, other potential crashes ([#3166](https://github.com/EQEmu/Server/pull/3166)) @Aeadoin 2023-04-01
|
||||
|
||||
### Fixes
|
||||
|
||||
* Correct SE_SlayUndead & SE_HeadShotLevel limit Value when applied. ([#3171](https://github.com/EQEmu/Server/pull/3171)) @Aeadoin 2023-04-01
|
||||
* Prevent VerifyGroup from setting OOZ membername to Null character. ([#3168](https://github.com/EQEmu/Server/pull/3168)) @Aeadoin 2023-04-01
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add missing Luabind definitions to lua_general.cpp ([#3167](https://github.com/EQEmu/Server/pull/3167)) @Kinglykrab 2023-04-01
|
||||
|
||||
## [22.8.2] - 03/30/2023
|
||||
|
||||
### Code
|
||||
|
||||
* "equipped" not "equiped", "dual" not "duel". ([#3149](https://github.com/EQEmu/Server/pull/3149)) @Kinglykrab 2023-03-27
|
||||
|
||||
### Crash
|
||||
|
||||
* Add Checks for out of bounds & dereferencing nullptrs ([#3151](https://github.com/EQEmu/Server/pull/3151)) @Aeadoin 2023-03-28
|
||||
|
||||
### Fixes
|
||||
|
||||
* Check Rule "Bots Enabled" to prevent bot database calls on connect ([#3154](https://github.com/EQEmu/Server/pull/3154)) @Aeadoin 2023-03-29
|
||||
* Correct logic checks for Bot rule AllowOwnerOptionAltCombat ([#3158](https://github.com/EQEmu/Server/pull/3158)) @Aeadoin 2023-03-30
|
||||
* Fix an issue with EVENT_DISCONNECT not firing on regular /camp ([#3153](https://github.com/EQEmu/Server/pull/3153)) @Kinglykrab 2023-03-28
|
||||
* Fix bot_raid_members.sql for MYSQL. ([#3155](https://github.com/EQEmu/Server/pull/3155)) @Aeadoin 2023-03-28
|
||||
* Fix for OOZ Group updates when removing/inviting Bots ([#3159](https://github.com/EQEmu/Server/pull/3159)) @Aeadoin 2023-03-30
|
||||
* Fix issues with Lua tables not starting at index 1 ([#3160](https://github.com/EQEmu/Server/pull/3160)) @Kinglykrab 2023-03-30
|
||||
* Fix strcpy-param-overlap ([#3157](https://github.com/EQEmu/Server/pull/3157)) @Aeadoin 2023-03-29
|
||||
|
||||
### Rules
|
||||
|
||||
* Remove Guild Bank Zone ID Rule ([#3156](https://github.com/EQEmu/Server/pull/3156)) @Kinglykrab 2023-03-29
|
||||
|
||||
## [22.8.1] - 03/27/2023
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix for NPCs having spells interrupted. ([#3150](https://github.com/EQEmu/Server/pull/3150)) @Aeadoin 2023-03-27
|
||||
|
||||
## [22.8.0] - 03/25/2023
|
||||
|
||||
### Code
|
||||
|
||||
* Cleanup Strings::ToInt uses. ([#3142](https://github.com/EQEmu/Server/pull/3142)) @Aeadoin 2023-03-26
|
||||
* Remove extern bool Critical ([#3146](https://github.com/EQEmu/Server/pull/3146)) @Kinglykrab 2023-03-25
|
||||
|
||||
### Crash
|
||||
|
||||
* Fix for crash in Raid::QueuePacket ([#3145](https://github.com/EQEmu/Server/pull/3145)) @Aeadoin 2023-03-25
|
||||
|
||||
### Feature
|
||||
|
||||
* Add support for -1 extradmgskill to allow all skills to be scaled. ([#3136](https://github.com/EQEmu/Server/pull/3136)) @Kinglykrab 2023-03-26
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix for Items looted from corpses. ([#3147](https://github.com/EQEmu/Server/pull/3147)) @Aeadoin 2023-03-26
|
||||
* Fix for SQL Query in npc_scale_global_base ([#3144](https://github.com/EQEmu/Server/pull/3144)) @Aeadoin 2023-03-26
|
||||
|
||||
## [22.7.0] - 03/24/2023
|
||||
|
||||
### Bots
|
||||
|
||||
+19
-1
@@ -16,6 +16,15 @@ SET(CMAKE_CXX_STANDARD 20)
|
||||
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
SET(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
OPTION(EQEMU_BUILD_STATIC "Build with static linking" OFF)
|
||||
|
||||
IF (EQEMU_BUILD_STATIC)
|
||||
SET(BUILD_SHARED_LIBS OFF)
|
||||
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".a")
|
||||
MESSAGE(STATUS "Building with static linking")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")
|
||||
ENDIF(EQEMU_BUILD_STATIC)
|
||||
|
||||
IF(MSVC)
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
|
||||
ADD_DEFINITIONS(-DNOMINMAX)
|
||||
@@ -23,7 +32,11 @@ IF(MSVC)
|
||||
ADD_DEFINITIONS(-D_HAS_AUTO_PTR_ETC) # for Luabind on C++17
|
||||
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
ADD_DEFINITIONS( "/W0 /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /nologo /Os")
|
||||
|
||||
OPTION(EQEMU_DISABLE_MSVC_WARNINGS "Disable MSVC compile warnings." ON)
|
||||
IF(EQEMU_DISABLE_MSVC_WARNINGS)
|
||||
ADD_DEFINITIONS( "/W0 /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /nologo /Os")
|
||||
ENDIF(EQEMU_DISABLE_MSVC_WARNINGS)
|
||||
ELSE(MSVC)
|
||||
ADD_DEFINITIONS(-DHAS_UNION_SEMUN)
|
||||
ENDIF(MSVC)
|
||||
@@ -307,6 +320,10 @@ ELSE()
|
||||
SET(ZLIB_LIBRARY_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
|
||||
ENDIF()
|
||||
|
||||
IF (EQEMU_BUILD_STATIC)
|
||||
SET(ZLIB_LIBRARY_LIBS libz.a)
|
||||
ENDIF(EQEMU_BUILD_STATIC)
|
||||
|
||||
MESSAGE(STATUS "")
|
||||
MESSAGE(STATUS "**************************************************")
|
||||
MESSAGE(STATUS "* Library Usage *")
|
||||
@@ -371,6 +388,7 @@ IF(PERL_LIBRARY_ENABLED)
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${PERL_LIBRARY_INCLUDE}")
|
||||
ADD_DEFINITIONS(-DEMBPERL)
|
||||
ADD_DEFINITIONS(-DEMBPERL_PLUGIN)
|
||||
ADD_DEFINITIONS(-DPERLBIND_NO_STRICT_SCALAR_TYPES)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@ SET(common_sources
|
||||
database.cpp
|
||||
database_conversions.cpp
|
||||
database_instances.cpp
|
||||
database/database_update_manifest.cpp
|
||||
database/database_update_manifest_bots.cpp
|
||||
database/database_update.cpp
|
||||
dbcore.cpp
|
||||
deity.cpp
|
||||
dynamic_zone_base.cpp
|
||||
@@ -506,6 +509,7 @@ SET(common_headers
|
||||
data_verification.h
|
||||
database.h
|
||||
database_schema.h
|
||||
database/database_update.h
|
||||
dbcore.h
|
||||
deity.h
|
||||
discord/discord.h
|
||||
@@ -585,6 +589,7 @@ SET(common_headers
|
||||
ptimer.h
|
||||
queue.h
|
||||
races.h
|
||||
raid.h
|
||||
random.h
|
||||
rdtsc.h
|
||||
rulesys.h
|
||||
@@ -666,7 +671,8 @@ SET(common_headers
|
||||
StackWalker/StackWalker.h
|
||||
util/memory_stream.h
|
||||
util/directory.h
|
||||
util/uuid.h)
|
||||
util/uuid.h
|
||||
)
|
||||
|
||||
SOURCE_GROUP(Event FILES
|
||||
event/event_loop.h
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
#include "../common/global_define.h"
|
||||
#include "../common/classes.h"
|
||||
#include "data_verification.h"
|
||||
|
||||
const char *GetClassIDName(uint8 class_id, uint8 level)
|
||||
{
|
||||
@@ -630,6 +631,20 @@ bool IsINTCasterClass(uint8 class_id)
|
||||
}
|
||||
}
|
||||
|
||||
bool IsHeroicINTCasterClass(uint8 class_id)
|
||||
{
|
||||
switch (class_id) {
|
||||
case NECROMANCER:
|
||||
case WIZARD:
|
||||
case MAGICIAN:
|
||||
case ENCHANTER:
|
||||
case SHADOWKNIGHT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsWISCasterClass(uint8 class_id)
|
||||
{
|
||||
switch (class_id) {
|
||||
@@ -642,6 +657,21 @@ bool IsWISCasterClass(uint8 class_id)
|
||||
}
|
||||
}
|
||||
|
||||
bool IsHeroicWISCasterClass(uint8 class_id)
|
||||
{
|
||||
switch (class_id) {
|
||||
case CLERIC:
|
||||
case DRUID:
|
||||
case SHAMAN:
|
||||
case PALADIN:
|
||||
case BEASTLORD:
|
||||
case RANGER:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsPlateClass(uint8 class_id)
|
||||
{
|
||||
switch (class_id) {
|
||||
@@ -721,3 +751,51 @@ uint8 ClassArmorType(uint8 class_id)
|
||||
return ARMOR_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string GetPlayerClassAbbreviation(uint8 class_id)
|
||||
{
|
||||
if (!EQ::ValueWithin(class_id, WARRIOR, BERSERKER)) {
|
||||
return std::string("UNK");
|
||||
}
|
||||
|
||||
switch (class_id) {
|
||||
case WARRIOR:
|
||||
return "WAR";
|
||||
case CLERIC:
|
||||
return "CLR";
|
||||
case PALADIN:
|
||||
return "PAL";
|
||||
case RANGER:
|
||||
return "RNG";
|
||||
case SHADOWKNIGHT:
|
||||
return "SHD";
|
||||
case DRUID:
|
||||
return "DRU";
|
||||
case MONK:
|
||||
return "MNK";
|
||||
case BARD:
|
||||
return "BRD";
|
||||
case ROGUE:
|
||||
return "ROG";
|
||||
case SHAMAN:
|
||||
return "SHM";
|
||||
case NECROMANCER:
|
||||
return "NEC";
|
||||
case WIZARD:
|
||||
return "WIZ";
|
||||
case MAGICIAN:
|
||||
return "MAG";
|
||||
case ENCHANTER:
|
||||
return "ENC";
|
||||
case BEASTLORD:
|
||||
return "BST";
|
||||
case BERSERKER:
|
||||
return "BER";
|
||||
}
|
||||
|
||||
return std::string("UNK");
|
||||
}
|
||||
|
||||
bool IsPlayerClass(uint8 class_id) {
|
||||
return EQ::ValueWithin(class_id, WARRIOR, BERSERKER);
|
||||
}
|
||||
|
||||
+6
-1
@@ -19,6 +19,7 @@
|
||||
#define CLASSES_CH
|
||||
|
||||
#include "../common/types.h"
|
||||
#include <string>
|
||||
|
||||
#define NO_CLASS 0
|
||||
#define WARRIOR 1
|
||||
@@ -127,6 +128,9 @@
|
||||
const char* GetClassIDName(uint8 class_id, uint8 level = 0);
|
||||
const char* GetPlayerClassName(uint32 player_class_value, uint8 level = 0);
|
||||
|
||||
bool IsPlayerClass(uint8 class_id);
|
||||
const std::string GetPlayerClassAbbreviation(uint8 class_id);
|
||||
|
||||
uint32 GetPlayerClassValue(uint8 class_id);
|
||||
uint32 GetPlayerClassBit(uint8 class_id);
|
||||
|
||||
@@ -140,7 +144,8 @@ bool IsHybridClass(uint8 class_id);
|
||||
bool IsCasterClass(uint8 class_id);
|
||||
bool IsINTCasterClass(uint8 class_id);
|
||||
bool IsWISCasterClass(uint8 class_id);
|
||||
|
||||
bool IsHeroicINTCasterClass(uint8 class_id);
|
||||
bool IsHeroicWISCasterClass(uint8 class_id);
|
||||
bool IsPlateClass(uint8 class_id);
|
||||
bool IsChainClass(uint8 class_id);
|
||||
bool IsLeatherClass(uint8 class_id);
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace EQEmuCommand {
|
||||
index++;
|
||||
}
|
||||
|
||||
if (!arguments_filled || argc == 2 || cmd[{"-h", "--help"}]) {
|
||||
if (!arguments_filled || (argc == 2 && !cmd[{"-h", "--help"}]) || (argc == 3 && cmd[{"-h", "--help"}])) {
|
||||
std::string arguments_string;
|
||||
for (auto &arg : arguments) {
|
||||
arguments_string += " " + arg;
|
||||
@@ -160,7 +160,7 @@ namespace EQEmuCommand {
|
||||
*/
|
||||
std::string command_section;
|
||||
for (auto &it: in_function_map) {
|
||||
description = "";
|
||||
description.clear();
|
||||
|
||||
(it.second)(argc, argv, cmd, description);
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ std::vector<std::string> WorldContentService::GetContentFlagsDisabled()
|
||||
/**
|
||||
* @param content_flags
|
||||
*/
|
||||
void WorldContentService::SetContentFlags(std::vector<ContentFlagsRepository::ContentFlags> content_flags)
|
||||
void WorldContentService::SetContentFlags(const std::vector<ContentFlagsRepository::ContentFlags>& content_flags)
|
||||
{
|
||||
WorldContentService::content_flags = content_flags;
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ public:
|
||||
std::vector<std::string> GetContentFlagsDisabled();
|
||||
bool IsContentFlagEnabled(const std::string& content_flag);
|
||||
bool IsContentFlagDisabled(const std::string& content_flag);
|
||||
void SetContentFlags(std::vector<ContentFlagsRepository::ContentFlags> content_flags);
|
||||
void SetContentFlags(const std::vector<ContentFlagsRepository::ContentFlags>& content_flags);
|
||||
void ReloadContentFlags();
|
||||
WorldContentService * SetExpansionContext();
|
||||
|
||||
|
||||
+1
-4
@@ -41,9 +41,6 @@ void SendCrashReport(const std::string &crash_report)
|
||||
r.set_connection_timeout(1, 0);
|
||||
r.set_read_timeout(1, 0);
|
||||
r.set_write_timeout(1, 0);
|
||||
httplib::Headers headers = {
|
||||
{"Content-Type", "application/json"}
|
||||
};
|
||||
|
||||
// os info
|
||||
auto os = EQ::GetOS();
|
||||
@@ -125,7 +122,7 @@ public:
|
||||
StackWalker::OnOutput(szText);
|
||||
}
|
||||
|
||||
const std::vector<std::string>& const GetLines() { return _lines; }
|
||||
const std::vector<std::string>& GetLines() { return _lines; }
|
||||
private:
|
||||
std::vector<std::string> _lines;
|
||||
};
|
||||
|
||||
+200
-129
@@ -353,7 +353,7 @@ bool Database::ReserveName(uint32 account_id, char* name) {
|
||||
|
||||
query = StringFormat("INSERT INTO `character_data` SET `account_id` = %i, `name` = '%s'", account_id, name);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success() || results.ErrorMessage() != ""){ return false; }
|
||||
if (!results.Success() || !results.ErrorMessage().empty()){ return false; }
|
||||
|
||||
// Put character into the default guild if rule is being used.
|
||||
int guild_id = RuleI(Character, DefaultGuild);
|
||||
@@ -363,7 +363,7 @@ bool Database::ReserveName(uint32 account_id, char* name) {
|
||||
if (character_id > -1) {
|
||||
query = StringFormat("INSERT INTO `guild_members` SET `char_id` = %i, `guild_id` = '%i'", character_id, guild_id);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success() || results.ErrorMessage() != ""){
|
||||
if (!results.Success() || !results.ErrorMessage().empty()){
|
||||
LogInfo("Could not put character [{}] into default Guild", name);
|
||||
}
|
||||
}
|
||||
@@ -449,7 +449,8 @@ bool Database::DeleteCharacter(char *character_name)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp){
|
||||
bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct *pp)
|
||||
{
|
||||
std::string query = StringFormat(
|
||||
"REPLACE INTO `character_data` ("
|
||||
"id,"
|
||||
@@ -634,101 +635,102 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
|
||||
"%u," // guild_auto_consent
|
||||
"%u" // RestTimer
|
||||
")",
|
||||
character_id, // " id, "
|
||||
account_id, // " account_id, "
|
||||
Strings::Escape(pp->name).c_str(), // " `name`, "
|
||||
character_id, // " id, "
|
||||
account_id, // " account_id, "
|
||||
Strings::Escape(pp->name).c_str(), // " `name`, "
|
||||
Strings::Escape(pp->last_name).c_str(), // " last_name, "
|
||||
pp->gender, // " gender, "
|
||||
pp->race, // " race, "
|
||||
pp->class_, // " class, "
|
||||
pp->level, // " `level`, "
|
||||
pp->deity, // " deity, "
|
||||
pp->birthday, // " birthday, "
|
||||
pp->lastlogin, // " last_login, "
|
||||
pp->timePlayedMin, // " time_played, "
|
||||
pp->pvp, // " pvp_status, "
|
||||
pp->level2, // " level2, "
|
||||
pp->anon, // " anon, "
|
||||
pp->gm, // " gm, "
|
||||
pp->intoxication, // " intoxication, "
|
||||
pp->haircolor, // " hair_color, "
|
||||
pp->beardcolor, // " beard_color, "
|
||||
pp->eyecolor1, // " eye_color_1, "
|
||||
pp->eyecolor2, // " eye_color_2, "
|
||||
pp->hairstyle, // " hair_style, "
|
||||
pp->beard, // " beard, "
|
||||
pp->ability_time_seconds, // " ability_time_seconds, "
|
||||
pp->ability_number, // " ability_number, "
|
||||
pp->ability_time_minutes, // " ability_time_minutes, "
|
||||
pp->ability_time_hours, // " ability_time_hours, "
|
||||
pp->gender, // " gender, "
|
||||
pp->race, // " race, "
|
||||
pp->class_, // " class, "
|
||||
pp->level, // " `level`, "
|
||||
pp->deity, // " deity, "
|
||||
pp->birthday, // " birthday, "
|
||||
pp->lastlogin, // " last_login, "
|
||||
pp->timePlayedMin, // " time_played, "
|
||||
pp->pvp, // " pvp_status, "
|
||||
pp->level2, // " level2, "
|
||||
pp->anon, // " anon, "
|
||||
pp->gm, // " gm, "
|
||||
pp->intoxication, // " intoxication, "
|
||||
pp->haircolor, // " hair_color, "
|
||||
pp->beardcolor, // " beard_color, "
|
||||
pp->eyecolor1, // " eye_color_1, "
|
||||
pp->eyecolor2, // " eye_color_2, "
|
||||
pp->hairstyle, // " hair_style, "
|
||||
pp->beard, // " beard, "
|
||||
pp->ability_time_seconds, // " ability_time_seconds, "
|
||||
pp->ability_number, // " ability_number, "
|
||||
pp->ability_time_minutes, // " ability_time_minutes, "
|
||||
pp->ability_time_hours, // " ability_time_hours, "
|
||||
Strings::Escape(pp->title).c_str(), // " title, "
|
||||
Strings::Escape(pp->suffix).c_str(), // " suffix, "
|
||||
pp->exp, // " exp, "
|
||||
pp->points, // " points, "
|
||||
pp->mana, // " mana, "
|
||||
pp->cur_hp, // " cur_hp, "
|
||||
pp->STR, // " str, "
|
||||
pp->STA, // " sta, "
|
||||
pp->CHA, // " cha, "
|
||||
pp->DEX, // " dex, "
|
||||
pp->INT, // " `int`, "
|
||||
pp->AGI, // " agi, "
|
||||
pp->WIS, // " wis, "
|
||||
pp->face, // " face, "
|
||||
pp->y, // " y, "
|
||||
pp->x, // " x, "
|
||||
pp->z, // " z, "
|
||||
pp->heading, // " heading, "
|
||||
pp->pvp2, // " pvp2, "
|
||||
pp->pvptype, // " pvp_type, "
|
||||
pp->autosplit, // " autosplit_enabled, "
|
||||
pp->zone_change_count, // " zone_change_count, "
|
||||
pp->drakkin_heritage, // " drakkin_heritage, "
|
||||
pp->drakkin_tattoo, // " drakkin_tattoo, "
|
||||
pp->drakkin_details, // " drakkin_details, "
|
||||
pp->toxicity, // " toxicity, "
|
||||
pp->hunger_level, // " hunger_level, "
|
||||
pp->thirst_level, // " thirst_level, "
|
||||
pp->ability_up, // " ability_up, "
|
||||
pp->zone_id, // " zone_id, "
|
||||
pp->zoneInstance, // " zone_instance, "
|
||||
pp->leadAAActive, // " leadership_exp_on, "
|
||||
pp->ldon_points_guk, // " ldon_points_guk, "
|
||||
pp->ldon_points_mir, // " ldon_points_mir, "
|
||||
pp->ldon_points_mmc, // " ldon_points_mmc, "
|
||||
pp->ldon_points_ruj, // " ldon_points_ruj, "
|
||||
pp->ldon_points_tak, // " ldon_points_tak, "
|
||||
pp->ldon_points_available, // " ldon_points_available, "
|
||||
pp->tribute_time_remaining, // " tribute_time_remaining, "
|
||||
pp->showhelm, // " show_helm, "
|
||||
pp->career_tribute_points, // " career_tribute_points, "
|
||||
pp->tribute_points, // " tribute_points, "
|
||||
pp->tribute_active, // " tribute_active, "
|
||||
pp->endurance, // " endurance, "
|
||||
pp->group_leadership_exp, // " group_leadership_exp, "
|
||||
pp->raid_leadership_exp, // " raid_leadership_exp, "
|
||||
pp->group_leadership_points, // " group_leadership_points, "
|
||||
pp->raid_leadership_points, // " raid_leadership_points, "
|
||||
pp->air_remaining, // " air_remaining, "
|
||||
pp->PVPKills, // " pvp_kills, "
|
||||
pp->PVPDeaths, // " pvp_deaths, "
|
||||
pp->PVPCurrentPoints, // " pvp_current_points, "
|
||||
pp->PVPCareerPoints, // " pvp_career_points, "
|
||||
pp->PVPBestKillStreak, // " pvp_best_kill_streak, "
|
||||
pp->PVPWorstDeathStreak, // " pvp_worst_death_streak, "
|
||||
pp->PVPCurrentKillStreak, // " pvp_current_kill_streak, "
|
||||
pp->aapoints_spent, // " aa_points_spent, "
|
||||
pp->expAA, // " aa_exp, "
|
||||
pp->aapoints, // " aa_points, "
|
||||
pp->groupAutoconsent, // " group_auto_consent, "
|
||||
pp->raidAutoconsent, // " raid_auto_consent, "
|
||||
pp->guildAutoconsent, // " guild_auto_consent, "
|
||||
pp->RestTimer // " RestTimer) "
|
||||
pp->exp, // " exp, "
|
||||
pp->points, // " points, "
|
||||
pp->mana, // " mana, "
|
||||
pp->cur_hp, // " cur_hp, "
|
||||
pp->STR, // " str, "
|
||||
pp->STA, // " sta, "
|
||||
pp->CHA, // " cha, "
|
||||
pp->DEX, // " dex, "
|
||||
pp->INT, // " `int`, "
|
||||
pp->AGI, // " agi, "
|
||||
pp->WIS, // " wis, "
|
||||
pp->face, // " face, "
|
||||
pp->y, // " y, "
|
||||
pp->x, // " x, "
|
||||
pp->z, // " z, "
|
||||
pp->heading, // " heading, "
|
||||
pp->pvp2, // " pvp2, "
|
||||
pp->pvptype, // " pvp_type, "
|
||||
pp->autosplit, // " autosplit_enabled, "
|
||||
pp->zone_change_count, // " zone_change_count, "
|
||||
pp->drakkin_heritage, // " drakkin_heritage, "
|
||||
pp->drakkin_tattoo, // " drakkin_tattoo, "
|
||||
pp->drakkin_details, // " drakkin_details, "
|
||||
pp->toxicity, // " toxicity, "
|
||||
pp->hunger_level, // " hunger_level, "
|
||||
pp->thirst_level, // " thirst_level, "
|
||||
pp->ability_up, // " ability_up, "
|
||||
pp->zone_id, // " zone_id, "
|
||||
pp->zoneInstance, // " zone_instance, "
|
||||
pp->leadAAActive, // " leadership_exp_on, "
|
||||
pp->ldon_points_guk, // " ldon_points_guk, "
|
||||
pp->ldon_points_mir, // " ldon_points_mir, "
|
||||
pp->ldon_points_mmc, // " ldon_points_mmc, "
|
||||
pp->ldon_points_ruj, // " ldon_points_ruj, "
|
||||
pp->ldon_points_tak, // " ldon_points_tak, "
|
||||
pp->ldon_points_available, // " ldon_points_available, "
|
||||
pp->tribute_time_remaining, // " tribute_time_remaining, "
|
||||
pp->showhelm, // " show_helm, "
|
||||
pp->career_tribute_points, // " career_tribute_points, "
|
||||
pp->tribute_points, // " tribute_points, "
|
||||
pp->tribute_active, // " tribute_active, "
|
||||
pp->endurance, // " endurance, "
|
||||
pp->group_leadership_exp, // " group_leadership_exp, "
|
||||
pp->raid_leadership_exp, // " raid_leadership_exp, "
|
||||
pp->group_leadership_points, // " group_leadership_points, "
|
||||
pp->raid_leadership_points, // " raid_leadership_points, "
|
||||
pp->air_remaining, // " air_remaining, "
|
||||
pp->PVPKills, // " pvp_kills, "
|
||||
pp->PVPDeaths, // " pvp_deaths, "
|
||||
pp->PVPCurrentPoints, // " pvp_current_points, "
|
||||
pp->PVPCareerPoints, // " pvp_career_points, "
|
||||
pp->PVPBestKillStreak, // " pvp_best_kill_streak, "
|
||||
pp->PVPWorstDeathStreak, // " pvp_worst_death_streak, "
|
||||
pp->PVPCurrentKillStreak, // " pvp_current_kill_streak, "
|
||||
pp->aapoints_spent, // " aa_points_spent, "
|
||||
pp->expAA, // " aa_exp, "
|
||||
pp->aapoints, // " aa_points, "
|
||||
pp->groupAutoconsent, // " group_auto_consent, "
|
||||
pp->raidAutoconsent, // " raid_auto_consent, "
|
||||
pp->guildAutoconsent, // " guild_auto_consent, "
|
||||
pp->RestTimer // " RestTimer) "
|
||||
);
|
||||
auto results = QueryDatabase(query);
|
||||
QueryDatabase(query);
|
||||
|
||||
/* Save Bind Points */
|
||||
query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
|
||||
query = StringFormat(
|
||||
"REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
|
||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i), "
|
||||
"(%u, %u, %u, %f, %f, %f, %f, %i), "
|
||||
"(%u, %u, %u, %f, %f, %f, %f, %i), "
|
||||
@@ -739,57 +741,73 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
|
||||
character_id, pp->binds[2].zone_id, 0, pp->binds[2].x, pp->binds[2].y, pp->binds[2].z, pp->binds[2].heading, 2,
|
||||
character_id, pp->binds[3].zone_id, 0, pp->binds[3].x, pp->binds[3].y, pp->binds[3].z, pp->binds[3].heading, 3,
|
||||
character_id, pp->binds[4].zone_id, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading, 4
|
||||
); results = QueryDatabase(query);
|
||||
);
|
||||
QueryDatabase(query);
|
||||
|
||||
/* HoTT Ability */
|
||||
if(RuleB(Character, GrantHoTTOnCreate))
|
||||
{
|
||||
query = StringFormat("INSERT INTO `character_leadership_abilities` (id, slot, `rank`) VALUES (%u, %i, %i)", character_id, 14, 1);
|
||||
results = QueryDatabase(query);
|
||||
}
|
||||
/* HoTT Ability */
|
||||
if (RuleB(Character, GrantHoTTOnCreate)) {
|
||||
query = StringFormat(
|
||||
"INSERT INTO `character_leadership_abilities` (id, slot, `rank`) VALUES (%u, %i, %i)",
|
||||
character_id,
|
||||
14,
|
||||
1
|
||||
);
|
||||
QueryDatabase(query);
|
||||
}
|
||||
|
||||
/* Save Skills */
|
||||
int firstquery = 0;
|
||||
for (int i = 0; i < MAX_PP_SKILL; i++){
|
||||
if (pp->skills[i] > 0){
|
||||
if (firstquery != 1){
|
||||
int firstquery = 0;
|
||||
for (int i = 0; i < MAX_PP_SKILL; i++) {
|
||||
if (pp->skills[i] > 0) {
|
||||
if (firstquery != 1) {
|
||||
firstquery = 1;
|
||||
query = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, i, pp->skills[i]);
|
||||
}
|
||||
else{
|
||||
query = StringFormat(
|
||||
"REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)",
|
||||
character_id,
|
||||
i,
|
||||
pp->skills[i]
|
||||
);
|
||||
} else {
|
||||
query = query + StringFormat(", (%u, %u, %u)", character_id, i, pp->skills[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
results = QueryDatabase(query);
|
||||
QueryDatabase(query);
|
||||
|
||||
/* Save Language */
|
||||
firstquery = 0;
|
||||
for (int i = 0; i < MAX_PP_LANGUAGE; i++){
|
||||
if (pp->languages[i] > 0){
|
||||
if (firstquery != 1){
|
||||
for (int i = 0; i < MAX_PP_LANGUAGE; i++) {
|
||||
if (pp->languages[i] > 0) {
|
||||
if (firstquery != 1) {
|
||||
firstquery = 1;
|
||||
query = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, i, pp->languages[i]);
|
||||
}
|
||||
else{
|
||||
query = StringFormat(
|
||||
"REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)",
|
||||
character_id,
|
||||
i,
|
||||
pp->languages[i]
|
||||
);
|
||||
} else {
|
||||
query = query + StringFormat(", (%u, %u, %u)", character_id, i, pp->languages[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
results = QueryDatabase(query);
|
||||
QueryDatabase(query);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 Database::GetCharacterID(const char *name) {
|
||||
std::string query = StringFormat("SELECT `id` FROM `character_data` WHERE `name` = '%s'", name);
|
||||
const auto query = fmt::format(
|
||||
"SELECT `id` FROM `character_data` WHERE `name` = '{}'",
|
||||
Strings::Escape(name)
|
||||
);
|
||||
auto results = QueryDatabase(query);
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1)
|
||||
{
|
||||
return Strings::ToUnsignedInt(row[0]);
|
||||
if (!results.Success() || !results.RowCount()) {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
auto row = results.begin();
|
||||
return Strings::ToUnsignedInt(row[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -812,7 +830,7 @@ uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) {
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
uint32 accountId = Strings::ToInt(row[0]);
|
||||
uint32 accountId = Strings::ToUnsignedInt(row[0]);
|
||||
|
||||
if (oCharID)
|
||||
*oCharID = Strings::ToUnsignedInt(row[1]);
|
||||
@@ -999,7 +1017,7 @@ bool Database::GetVariable(std::string varname, std::string &varvalue)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Database::SetVariable(const std::string varname, const std::string &varvalue)
|
||||
bool Database::SetVariable(const std::string& varname, const std::string &varvalue)
|
||||
{
|
||||
std::string escaped_name = Strings::Escape(varname);
|
||||
std::string escaped_value = Strings::Escape(varvalue);
|
||||
@@ -2043,10 +2061,12 @@ uint32 Database::GetRaidIDByCharID(uint32 character_id) {
|
||||
character_id
|
||||
);
|
||||
auto results = QueryDatabase(query);
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
return Strings::ToUnsignedInt(row[0]);
|
||||
if (!results.Success() || !results.RowCount()) {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
auto row = results.begin();
|
||||
return Strings::ToUnsignedInt(row[0]);
|
||||
}
|
||||
|
||||
int Database::CountInvSnapshots() {
|
||||
@@ -2272,7 +2292,6 @@ bool Database::CopyCharacter(
|
||||
new_rows.emplace_back(new_values);
|
||||
}
|
||||
|
||||
std::string insert_values;
|
||||
std::vector<std::string> insert_rows;
|
||||
|
||||
for (auto &r: new_rows) {
|
||||
@@ -2328,7 +2347,7 @@ void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string ur
|
||||
);
|
||||
|
||||
if (!DoesTableExist(table_name)) {
|
||||
LogMySQLQuery("Table [{}] does not exist. Downloading from Github and installing...", table_name);
|
||||
LogMySQLQuery("Table [{}] does not exist. Downloading and installing...", table_name);
|
||||
|
||||
// http get request
|
||||
httplib::Client cli(
|
||||
@@ -2336,7 +2355,7 @@ void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string ur
|
||||
"{}://{}",
|
||||
request_uri.get_scheme(),
|
||||
request_uri.get_host()
|
||||
).c_str()
|
||||
)
|
||||
);
|
||||
|
||||
cli.set_connection_timeout(0, 60000000); // 60 sec
|
||||
@@ -2345,7 +2364,7 @@ void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string ur
|
||||
|
||||
int sourced_queries = 0;
|
||||
|
||||
if (auto res = cli.Get(request_uri.get_path().c_str())) {
|
||||
if (auto res = cli.Get(request_uri.get_path())) {
|
||||
if (res->status == 200) {
|
||||
for (auto &s: Strings::Split(res->body, ';')) {
|
||||
if (!Strings::Trim(s).empty()) {
|
||||
@@ -2389,3 +2408,55 @@ uint8 Database::GetMinStatus(uint32 zone_id, uint32 instance_version)
|
||||
|
||||
return !zones.empty() ? zones[0].min_status : 0;
|
||||
}
|
||||
|
||||
void Database::SourceSqlFromUrl(std::string url)
|
||||
{
|
||||
try {
|
||||
uri request_uri(url);
|
||||
|
||||
LogHTTPDetail(
|
||||
"parsing url [{}] path [{}] host [{}] query_string [{}] protocol [{}] port [{}]",
|
||||
url,
|
||||
request_uri.get_path(),
|
||||
request_uri.get_host(),
|
||||
request_uri.get_query(),
|
||||
request_uri.get_scheme(),
|
||||
request_uri.get_port()
|
||||
);
|
||||
|
||||
LogInfo("Downloading and installing from [{}]", url);
|
||||
|
||||
// http get request
|
||||
httplib::Client cli(
|
||||
fmt::format(
|
||||
"{}://{}",
|
||||
request_uri.get_scheme(),
|
||||
request_uri.get_host()
|
||||
)
|
||||
);
|
||||
|
||||
cli.set_connection_timeout(0, 60000000); // 60 sec
|
||||
cli.set_read_timeout(60, 0); // 60 seconds
|
||||
cli.set_write_timeout(60, 0); // 60 seconds
|
||||
|
||||
if (auto res = cli.Get(request_uri.get_path())) {
|
||||
if (res->status == 200) {
|
||||
auto results = QueryDatabaseMulti(res->body);
|
||||
if (!results.ErrorMessage().empty()) {
|
||||
LogError("Error sourcing SQL [{}]", results.ErrorMessage());
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (res->status == 404) {
|
||||
LogError("Error retrieving URL [{}]", url);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LogError("Error retrieving URL [{}]", url);
|
||||
}
|
||||
|
||||
}
|
||||
catch (std::invalid_argument iae) {
|
||||
LogError("URI parser error [{}]", iae.what());
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -235,7 +235,7 @@ public:
|
||||
/* Database Variables */
|
||||
|
||||
bool GetVariable(std::string varname, std::string &varvalue);
|
||||
bool SetVariable(const std::string varname, const std::string &varvalue);
|
||||
bool SetVariable(const std::string& varname, const std::string &varvalue);
|
||||
bool LoadVariables();
|
||||
|
||||
/* General Queries */
|
||||
@@ -263,7 +263,7 @@ public:
|
||||
void ClearInvSnapshots(bool from_now = false);
|
||||
|
||||
void SourceDatabaseTableFromUrl(std::string table_name, std::string url);
|
||||
|
||||
void SourceSqlFromUrl(std::string url);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "../database_schema.h"
|
||||
#include "../file.h"
|
||||
#include "../process/process.h"
|
||||
#include "../termcolor/rang.hpp"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
@@ -36,6 +37,7 @@
|
||||
#else
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <thread>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -91,6 +93,8 @@ std::string DatabaseDumpService::GetMySQLVersion()
|
||||
return Strings::Trim(version_output);
|
||||
}
|
||||
|
||||
const std::string CREDENTIALS_FILE = "login.my.cnf";
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
@@ -99,21 +103,15 @@ std::string DatabaseDumpService::GetBaseMySQLDumpCommand()
|
||||
auto config = EQEmuConfig::get();
|
||||
if (IsDumpContentTables() && !config->ContentDbHost.empty()) {
|
||||
return fmt::format(
|
||||
"mysqldump -u {} -p{} -h {} --port={} {}",
|
||||
config->ContentDbUsername,
|
||||
config->ContentDbPassword,
|
||||
config->ContentDbHost,
|
||||
config->ContentDbPort,
|
||||
"mysqldump --defaults-extra-file={} {}",
|
||||
CREDENTIALS_FILE,
|
||||
config->ContentDbName
|
||||
);
|
||||
};
|
||||
|
||||
return fmt::format(
|
||||
"mysqldump -u {} -p{} -h {} --port={} {}",
|
||||
config->DatabaseUsername,
|
||||
config->DatabasePassword,
|
||||
config->DatabaseHost,
|
||||
config->DatabasePort,
|
||||
"mysqldump --defaults-extra-file={} {}",
|
||||
CREDENTIALS_FILE,
|
||||
config->DatabaseDB
|
||||
);
|
||||
}
|
||||
@@ -145,7 +143,7 @@ std::string DatabaseDumpService::GetQueryServTables()
|
||||
|
||||
std::string DatabaseDumpService::GetSystemTablesList()
|
||||
{
|
||||
auto system_tables = DatabaseSchema::GetServerTables();
|
||||
auto system_tables = DatabaseSchema::GetServerTables();
|
||||
auto version_tables = DatabaseSchema::GetVersionTables();
|
||||
|
||||
system_tables.insert(
|
||||
@@ -199,7 +197,7 @@ std::string DatabaseDumpService::GetDumpFileNameWithPath()
|
||||
return GetSetDumpPath() + GetDumpFileName();
|
||||
}
|
||||
|
||||
void DatabaseDumpService::Dump()
|
||||
void DatabaseDumpService::DatabaseDump()
|
||||
{
|
||||
if (!IsMySQLInstalled()) {
|
||||
LogError("MySQL is not installed; Please check your PATH for a valid MySQL installation");
|
||||
@@ -281,6 +279,11 @@ void DatabaseDumpService::Dump()
|
||||
}
|
||||
}
|
||||
|
||||
if (IsDumpStaticInstanceData()) {
|
||||
tables_to_dump += "instance_list";
|
||||
options += " --no-create-info --where=\"instance_list.is_global > 0 and instance_list.never_expires > 0\"";
|
||||
}
|
||||
|
||||
if (!dump_descriptor.empty()) {
|
||||
SetDumpFileName(GetDumpFileName() + dump_descriptor);
|
||||
}
|
||||
@@ -293,14 +296,6 @@ void DatabaseDumpService::Dump()
|
||||
pipe_file = fmt::format(" > {}.sql", GetDumpFileNameWithPath());
|
||||
}
|
||||
|
||||
std::string execute_command = fmt::format(
|
||||
"{} {} {} {}",
|
||||
GetBaseMySQLDumpCommand(),
|
||||
options,
|
||||
tables_to_dump,
|
||||
pipe_file
|
||||
);
|
||||
|
||||
if (!File::Exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) {
|
||||
File::Makedir(GetSetDumpPath());
|
||||
}
|
||||
@@ -308,30 +303,62 @@ void DatabaseDumpService::Dump()
|
||||
if (IsDumpDropTableSyntaxOnly()) {
|
||||
std::vector<std::string> tables = Strings::Split(tables_to_dump, ' ');
|
||||
|
||||
for (auto &table : tables) {
|
||||
for (auto &table: tables) {
|
||||
std::cout << "DROP TABLE IF EXISTS `" << table << "`;" << std::endl;
|
||||
}
|
||||
|
||||
if (tables_to_dump.empty()) {
|
||||
std::cerr << "No tables were specified" << std::endl;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else {
|
||||
const auto execute_command = fmt::format(
|
||||
"{} {} {} {}",
|
||||
GetBaseMySQLDumpCommand(),
|
||||
options,
|
||||
tables_to_dump,
|
||||
pipe_file
|
||||
);
|
||||
|
||||
BuildCredentialsFile();
|
||||
std::string execution_result = Process::execute(execute_command);
|
||||
if (!execution_result.empty() && IsDumpOutputToConsole()) {
|
||||
std::cout << execution_result;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsDumpOutputToConsole()) {
|
||||
LogSys.LoadLogSettingsDefaults();
|
||||
}
|
||||
|
||||
if (!pipe_file.empty()) {
|
||||
std::string file = fmt::format("{}.sql", GetDumpFileNameWithPath());
|
||||
auto r = File::GetContents(file);
|
||||
if (!r.error.empty()) {
|
||||
LogError("{}", r.error);
|
||||
}
|
||||
|
||||
for (auto &line: Strings::Split(r.contents, "\n")) {
|
||||
if (Strings::Contains(line, "mysqldump:")) {
|
||||
LogError("{}", line);
|
||||
LogError("Database dump failed. Correct the error before continuing or trying again");
|
||||
LogError("This is to prevent data loss on behalf of the server operator");
|
||||
RemoveSqlBackup();
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!tables_to_dump.empty()) {
|
||||
LogInfo("Dumping Tables [{}]", Strings::Trim(tables_to_dump));
|
||||
}
|
||||
|
||||
LogInfo("Database dump created at [{}.sql]", GetDumpFileNameWithPath());
|
||||
|
||||
if (IsDumpWithCompression() && !IsDumpOutputToConsole()) {
|
||||
if (HasCompressionBinary()) {
|
||||
LogInfo("Compression requested... Compressing dump [{}.sql]", GetDumpFileNameWithPath());
|
||||
LogInfo("Compression requested. Compressing dump [{}.sql]", GetDumpFileNameWithPath());
|
||||
|
||||
if (IsTarAvailable()) {
|
||||
Process::execute(
|
||||
@@ -343,6 +370,7 @@ void DatabaseDumpService::Dump()
|
||||
)
|
||||
);
|
||||
LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath());
|
||||
RemoveSqlBackup();
|
||||
}
|
||||
else if (Is7ZipAvailable()) {
|
||||
Process::execute(
|
||||
@@ -353,6 +381,7 @@ void DatabaseDumpService::Dump()
|
||||
)
|
||||
);
|
||||
LogInfo("Compressed dump created at [{}.zip]", GetDumpFileNameWithPath());
|
||||
RemoveSqlBackup();
|
||||
}
|
||||
else {
|
||||
LogInfo("Compression requested, but no available compression binary was found");
|
||||
@@ -363,6 +392,8 @@ void DatabaseDumpService::Dump()
|
||||
}
|
||||
}
|
||||
|
||||
RemoveCredentialsFile();
|
||||
|
||||
// LogDebug("[{}] dump-to-console", IsDumpOutputToConsole());
|
||||
// LogDebug("[{}] dump-path", GetSetDumpPath());
|
||||
// LogDebug("[{}] compression", (IsDumpWithCompression() ? "true" : "false"));
|
||||
@@ -535,3 +566,58 @@ void DatabaseDumpService::SetDumpMercTables(bool dump_merc_tables)
|
||||
{
|
||||
DatabaseDumpService::dump_merc_tables = dump_merc_tables;
|
||||
}
|
||||
|
||||
void DatabaseDumpService::RemoveSqlBackup()
|
||||
{
|
||||
std::string file = fmt::format("{}.sql", GetDumpFileNameWithPath());
|
||||
if (File::Exists(file)) {
|
||||
std::filesystem::remove(file);
|
||||
}
|
||||
|
||||
RemoveCredentialsFile();
|
||||
}
|
||||
|
||||
void DatabaseDumpService::BuildCredentialsFile()
|
||||
{
|
||||
auto config = EQEmuConfig::get();
|
||||
std::ofstream out(CREDENTIALS_FILE);
|
||||
if (out.is_open()) {
|
||||
if (IsDumpContentTables() && !config->ContentDbHost.empty()) {
|
||||
out << "[mysqldump]" << std::endl;
|
||||
out << "user=" << config->ContentDbUsername << std::endl;
|
||||
out << "password=" << config->ContentDbPassword << std::endl;
|
||||
out << "host=" << config->ContentDbHost << std::endl;
|
||||
out << "port=" << config->ContentDbPort << std::endl;
|
||||
out << "default-character-set=utf8" << std::endl;
|
||||
}
|
||||
else {
|
||||
out << "[mysqldump]" << std::endl;
|
||||
out << "user=" << config->DatabaseUsername << std::endl;
|
||||
out << "password=" << config->DatabasePassword << std::endl;
|
||||
out << "host=" << config->DatabaseHost << std::endl;
|
||||
out << "port=" << config->DatabasePort << std::endl;
|
||||
out << "default-character-set=utf8" << std::endl;
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
else {
|
||||
LogError("Failed to open credentials file for writing");
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseDumpService::RemoveCredentialsFile()
|
||||
{
|
||||
if (File::Exists(CREDENTIALS_FILE)) {
|
||||
std::filesystem::remove(CREDENTIALS_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
bool DatabaseDumpService::IsDumpStaticInstanceData()
|
||||
{
|
||||
return dump_static_instance_data;
|
||||
}
|
||||
|
||||
void DatabaseDumpService::SetDumpStaticInstanceData(bool b)
|
||||
{
|
||||
dump_static_instance_data = b;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
class DatabaseDumpService {
|
||||
public:
|
||||
void Dump();
|
||||
void DatabaseDump();
|
||||
bool IsDumpAllTables() const;
|
||||
void SetDumpAllTables(bool dump_all_tables);
|
||||
bool IsDumpWithNoData() const;
|
||||
@@ -58,6 +58,9 @@ public:
|
||||
bool IsDumpMercTables() const;
|
||||
void SetDumpMercTables(bool dump_bot_tables);
|
||||
|
||||
void SetDumpStaticInstanceData(bool b);
|
||||
bool IsDumpStaticInstanceData();
|
||||
|
||||
private:
|
||||
bool dump_all_tables = false;
|
||||
bool dump_state_tables = false;
|
||||
@@ -73,6 +76,8 @@ private:
|
||||
bool dump_drop_table_syntax_only = false;
|
||||
bool dump_bot_tables = false;
|
||||
bool dump_merc_tables = false;
|
||||
bool dump_static_instance_data = false;
|
||||
|
||||
std::string dump_path;
|
||||
std::string dump_file_name;
|
||||
|
||||
@@ -92,6 +97,9 @@ private:
|
||||
std::string GetDumpFileNameWithPath();
|
||||
std::string GetSetDumpPath();
|
||||
std::string GetQueryServTables();
|
||||
void RemoveSqlBackup();
|
||||
void BuildCredentialsFile();
|
||||
void RemoveCredentialsFile();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,300 @@
|
||||
#include <filesystem>
|
||||
#include "database_update.h"
|
||||
#include "../eqemu_logsys.h"
|
||||
#include "../database.h"
|
||||
#include "../strings.h"
|
||||
#include "../rulesys.h"
|
||||
#include "../http/httplib.h"
|
||||
|
||||
#include "database_update_manifest.cpp"
|
||||
#include "database_update_manifest_bots.cpp"
|
||||
#include "database_dump_service.h"
|
||||
|
||||
constexpr int BREAK_LENGTH = 70;
|
||||
|
||||
DatabaseVersion DatabaseUpdate::GetDatabaseVersions()
|
||||
{
|
||||
auto results = m_database->QueryDatabase("SELECT `version`, `bots_version` FROM `db_version` LIMIT 1");
|
||||
if (!results.Success() || !results.RowCount()) {
|
||||
LogError("Failed to read from [db_version] table!");
|
||||
return DatabaseVersion{};
|
||||
}
|
||||
|
||||
auto r = results.begin();
|
||||
|
||||
return DatabaseVersion{
|
||||
.server_database_version = Strings::ToInt(r[0]),
|
||||
.bots_database_version = Strings::ToInt(r[1]),
|
||||
};
|
||||
}
|
||||
|
||||
DatabaseVersion DatabaseUpdate::GetBinaryDatabaseVersions()
|
||||
{
|
||||
return DatabaseVersion{
|
||||
.server_database_version = CURRENT_BINARY_DATABASE_VERSION,
|
||||
.bots_database_version = (RuleB(Bots, Enabled) ? CURRENT_BINARY_BOTS_DATABASE_VERSION : 0),
|
||||
};
|
||||
}
|
||||
|
||||
// the amount of versions we look-back to ensure we have all migrations
|
||||
// we may not want to force these, but just warn about the look-backs
|
||||
constexpr int LOOK_BACK_AMOUNT = 10;
|
||||
|
||||
// this check will take action
|
||||
void DatabaseUpdate::CheckDbUpdates()
|
||||
{
|
||||
InjectBotsVersionColumn();
|
||||
auto v = GetDatabaseVersions();
|
||||
auto b = GetBinaryDatabaseVersions();
|
||||
if (CheckVersionsUpToDate(v, b)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (UpdateManifest(manifest_entries, v.server_database_version, b.server_database_version)) {
|
||||
LogInfo(
|
||||
"Updates ran successfully, setting database version to [{}] from [{}]",
|
||||
b.server_database_version,
|
||||
v.server_database_version
|
||||
);
|
||||
m_database->QueryDatabase(fmt::format("UPDATE `db_version` SET `version` = {}", b.server_database_version));
|
||||
}
|
||||
|
||||
if (b.bots_database_version > 0) {
|
||||
if (UpdateManifest(bot_manifest_entries, v.bots_database_version, b.bots_database_version)) {
|
||||
LogInfo(
|
||||
"Updates ran successfully, setting database version to [{}] from [{}]",
|
||||
b.bots_database_version,
|
||||
v.bots_database_version
|
||||
);
|
||||
m_database->QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE `db_version` SET `bots_version` = {}",
|
||||
b.bots_database_version
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string DatabaseUpdate::GetQueryResult(std::string query)
|
||||
{
|
||||
auto results = m_database->QueryDatabase(query);
|
||||
|
||||
std::vector<std::string> result_lines = {};
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
std::vector<std::string> cols;
|
||||
|
||||
int field_count = results.ColumnCount();
|
||||
cols.reserve(field_count);
|
||||
for (int i = 0; i < field_count; ++i) {
|
||||
if (row[i] != nullptr) {
|
||||
cols.emplace_back(row[i]);
|
||||
}
|
||||
}
|
||||
|
||||
result_lines.emplace_back(Strings::Join(cols, " "));
|
||||
}
|
||||
|
||||
return Strings::Join(result_lines, "\n");
|
||||
}
|
||||
|
||||
bool DatabaseUpdate::ShouldRunMigration(ManifestEntry &e, std::string query_result)
|
||||
{
|
||||
std::string r = Strings::Trim(query_result);
|
||||
if (e.condition == "contains") {
|
||||
return Strings::Contains(r, e.match);
|
||||
}
|
||||
else if (e.condition == "match") {
|
||||
return r == e.match;
|
||||
}
|
||||
else if (e.condition == "missing") {
|
||||
return !Strings::Contains(r, e.match);
|
||||
}
|
||||
else if (e.condition == "empty") {
|
||||
return r.empty();
|
||||
}
|
||||
else if (e.condition == "not_empty") {
|
||||
return !r.empty();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// return true if we ran updates
|
||||
bool DatabaseUpdate::UpdateManifest(
|
||||
std::vector<ManifestEntry> entries,
|
||||
int version_low,
|
||||
int version_high
|
||||
)
|
||||
{
|
||||
std::vector<int> missing_migrations = {};
|
||||
if (version_low != version_high) {
|
||||
|
||||
LogSys.DisableMySQLErrorLogs();
|
||||
for (int version = version_low + 1; version <= version_high; ++version) {
|
||||
for (auto &e: entries) {
|
||||
if (e.version == version) {
|
||||
bool has_migration = true;
|
||||
std::string r = GetQueryResult(e.check);
|
||||
if (ShouldRunMigration(e, r)) {
|
||||
has_migration = false;
|
||||
missing_migrations.emplace_back(e.version);
|
||||
}
|
||||
|
||||
std::string prefix = fmt::format(
|
||||
"[{}]",
|
||||
has_migration ? "ok" : "missing"
|
||||
);
|
||||
|
||||
LogInfo(
|
||||
"[{}] {:>10} | [{}]",
|
||||
e.version,
|
||||
prefix,
|
||||
e.description
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
LogSys.EnableMySQLErrorLogs();
|
||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||
|
||||
if (!missing_migrations.empty()) {
|
||||
LogInfo("Automatically backing up database before applying updates");
|
||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||
auto s = DatabaseDumpService();
|
||||
s.SetDumpAllTables(true);
|
||||
s.SetDumpWithCompression(true);
|
||||
s.DatabaseDump();
|
||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||
}
|
||||
|
||||
if (!missing_migrations.empty()) {
|
||||
LogInfo("Running database migrations. Please wait...");
|
||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||
}
|
||||
|
||||
for (auto &m: missing_migrations) {
|
||||
for (auto &e: entries) {
|
||||
if (e.version == m) {
|
||||
bool errored_migration = false;
|
||||
|
||||
auto r = m_database->QueryDatabaseMulti(e.sql);
|
||||
|
||||
// ignore empty query result "errors"
|
||||
if (r.ErrorNumber() != 1065 && !r.ErrorMessage().empty()) {
|
||||
LogError("(#{}) [{}]", r.ErrorNumber(), r.ErrorMessage());
|
||||
errored_migration = true;
|
||||
|
||||
LogInfo("Required database update failed. This could be a problem");
|
||||
LogInfo("Would you like to skip this update? [y/n] (Timeout 60s)");
|
||||
|
||||
// user input
|
||||
std::string input;
|
||||
bool gave_input = false;
|
||||
time_t start_time = time(nullptr);
|
||||
time_t wait_time_seconds = 60;
|
||||
|
||||
// spawn a concurrent thread that waits for input from std::cin
|
||||
std::thread t1(
|
||||
[&]() {
|
||||
std::cin >> input;
|
||||
gave_input = true;
|
||||
}
|
||||
);
|
||||
t1.detach();
|
||||
|
||||
// check the inputReceived flag once every 50ms for 10 seconds
|
||||
while (time(nullptr) < start_time + wait_time_seconds && !gave_input) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
}
|
||||
|
||||
// prompt for user skip
|
||||
if (Strings::Trim(input) == "y") {
|
||||
errored_migration = false;
|
||||
LogInfo("Skipping update [{}] [{}]", e.version, e.description);
|
||||
}
|
||||
}
|
||||
|
||||
LogInfo(
|
||||
"[{}] [{}] [{}]",
|
||||
e.version,
|
||||
e.description,
|
||||
(errored_migration ? "error" : "ok")
|
||||
);
|
||||
|
||||
if (errored_migration) {
|
||||
LogError("Fatal | Database migration [{}] failed to run", e.description);
|
||||
LogError("Fatal | Shutting down");
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DatabaseUpdate *DatabaseUpdate::SetDatabase(Database *db)
|
||||
{
|
||||
m_database = db;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
|
||||
{
|
||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||
|
||||
LogInfo(
|
||||
"{:>8} | database [{}] binary [{}] {}",
|
||||
"Server",
|
||||
v.server_database_version,
|
||||
b.server_database_version,
|
||||
(v.server_database_version == b.server_database_version) ? "up to date" : "checking updates"
|
||||
);
|
||||
|
||||
if (RuleB(Bots, Enabled) && b.bots_database_version > 0) {
|
||||
LogInfo(
|
||||
"{:>8} | database [{}] binary [{}] {}",
|
||||
"Bots",
|
||||
v.bots_database_version,
|
||||
b.bots_database_version,
|
||||
(v.bots_database_version == b.bots_database_version) ? "up to date" : "checking updates"
|
||||
);
|
||||
}
|
||||
|
||||
LogInfo("{:>8} | [server.auto_database_updates] [<green>true]", "Config");
|
||||
|
||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||
|
||||
// server database version is required
|
||||
bool server_up_to_date = v.server_database_version == b.server_database_version;
|
||||
// bots database version is optional, if not enabled then it is always up-to-date
|
||||
bool bots_up_to_date = RuleB(Bots, Enabled) ? v.bots_database_version == b.bots_database_version : true;
|
||||
|
||||
return server_up_to_date && bots_up_to_date;
|
||||
}
|
||||
|
||||
// checks to see if there are pending updates
|
||||
// used by zone to prevent launch or boot loop until updates are applied
|
||||
bool DatabaseUpdate::HasPendingUpdates()
|
||||
{
|
||||
auto v = GetDatabaseVersions();
|
||||
auto b = GetBinaryDatabaseVersions();
|
||||
|
||||
return !CheckVersionsUpToDate(v, b);
|
||||
}
|
||||
|
||||
void DatabaseUpdate::InjectBotsVersionColumn()
|
||||
{
|
||||
auto r = m_database->QueryDatabase("show columns from db_version where Field like '%bots_version%'");
|
||||
if (r.RowCount() == 0) {
|
||||
m_database->QueryDatabase("ALTER TABLE db_version ADD bots_version int(11) DEFAULT '0' AFTER version");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef EQEMU_DATABASE_UPDATE_H
|
||||
#define EQEMU_DATABASE_UPDATE_H
|
||||
|
||||
#include "../database.h"
|
||||
|
||||
struct ManifestEntry {
|
||||
int version{}; // database version of the migration
|
||||
std::string description{}; // description of the migration ex: "add_new_table" or "add_index_to_table"
|
||||
std::string check{}; // query that checks against the condition
|
||||
std::string condition{}; // condition or "match_type" - Possible values [contains|match|missing|empty|not_empty]
|
||||
std::string match{}; // match field that is not always used, but works in conjunction with "condition" values [missing|match|contains]
|
||||
std::string sql{}; // the SQL DDL that gets ran when the condition is true
|
||||
};
|
||||
|
||||
struct DatabaseVersion {
|
||||
int server_database_version;
|
||||
int bots_database_version;
|
||||
};
|
||||
|
||||
class DatabaseUpdate {
|
||||
public:
|
||||
DatabaseVersion GetDatabaseVersions();
|
||||
DatabaseVersion GetBinaryDatabaseVersions();
|
||||
void CheckDbUpdates();
|
||||
std::string GetQueryResult(std::string query);
|
||||
static bool ShouldRunMigration(ManifestEntry &e, std::string query_result);
|
||||
bool UpdateManifest(std::vector<ManifestEntry> entries, int version_low, int version_high);
|
||||
|
||||
DatabaseUpdate *SetDatabase(Database *db);
|
||||
bool HasPendingUpdates();
|
||||
private:
|
||||
Database *m_database;
|
||||
static bool CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b);
|
||||
void InjectBotsVersionColumn();
|
||||
};
|
||||
|
||||
#endif //EQEMU_DATABASE_UPDATE_H
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,107 @@
|
||||
#include "database_update.h"
|
||||
|
||||
std::vector<ManifestEntry> bot_manifest_entries = {
|
||||
ManifestEntry{
|
||||
.version = 9035,
|
||||
.description = "2022_12_04_bot_archery.sql",
|
||||
.check = "SHOW COLUMNS FROM `bot_data` LIKE 'archery_setting'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `bot_data`
|
||||
ADD COLUMN `archery_setting` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0' AFTER `enforce_spell_settings`;
|
||||
)",
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9036,
|
||||
.description = "2023_01_19_drop_bot_views.sql",
|
||||
.check = "SHOW TABLES LIKE 'vw_groups'",
|
||||
.condition = "not_empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
DROP VIEW vw_bot_groups;
|
||||
DROP VIEW vw_bot_character_mobs;
|
||||
DROP VIEW vw_groups;
|
||||
DROP VIEW vw_guild_members;
|
||||
DROP TABLE bot_guild_members;
|
||||
|
||||
)",
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9037,
|
||||
.description = "2023_01_22_add_name_index.sql",
|
||||
.check = "show index from bot_data WHERE key_name = 'name`",
|
||||
.condition = "",
|
||||
.match = "empty",
|
||||
.sql = R"(
|
||||
create index `name` on bot_data(`name`);
|
||||
)",
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9038,
|
||||
.description = "2023_02_16_add_caster_range.sql",
|
||||
.check = "SHOW COLUMNS FROM `bot_data` LIKE 'caster_range'",
|
||||
.condition = "",
|
||||
.match = "empty",
|
||||
.sql = R"(
|
||||
ALTER TABLE `bot_data`
|
||||
ADD COLUMN `caster_range` INT(11) UNSIGNED NOT NULL DEFAULT '300' AFTER `archery_setting`;
|
||||
)",
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9039,
|
||||
.description = "2023_03_31_remove_bot_groups.sql",
|
||||
.check = "SHOW TABLES LIKE 'bot_groups'",
|
||||
.condition = "",
|
||||
.match = "not_empty",
|
||||
.sql = R"(
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
DROP TABLE IF EXISTS `bot_groups`;
|
||||
DROP TABLE IF EXISTS `bot_group_members`;
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
)",
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9040,
|
||||
.description = "2023_11_16_bot_starting_items.sql",
|
||||
.check = "SHOW TABLES LIKE 'bot_starting_items'",
|
||||
.condition = "",
|
||||
.match = "empty",
|
||||
.sql = R"(
|
||||
CREATE TABLE `bot_starting_items` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`races` int(11) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`classes` int(11) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`item_id` int(11) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`item_charges` tinyint(3) UNSIGNED NOT NULL DEFAULT 1,
|
||||
`min_status` tinyint(3) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`slot_id` mediumint(9) NOT NULL DEFAULT -1,
|
||||
`min_expansion` tinyint(4) NOT NULL DEFAULT -1,
|
||||
`max_expansion` tinyint(4) NOT NULL DEFAULT -1,
|
||||
`content_flags` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
|
||||
`content_flags_disabled` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci;
|
||||
)"
|
||||
}
|
||||
// -- template; copy/paste this when you need to create a new entry
|
||||
// ManifestEntry{
|
||||
// .version = 9228,
|
||||
// .description = "some_new_migration.sql",
|
||||
// .check = "SHOW COLUMNS FROM `table_name` LIKE 'column_name'",
|
||||
// .condition = "empty",
|
||||
// .match = "",
|
||||
// .sql = R"(
|
||||
//
|
||||
//)"
|
||||
};
|
||||
|
||||
// see struct definitions for what each field does
|
||||
// struct ManifestEntry {
|
||||
// int version{}; // database version of the migration
|
||||
// std::string description{}; // description of the migration ex: "add_new_table" or "add_index_to_table"
|
||||
// std::string check{}; // query that checks against the condition
|
||||
// std::string condition{}; // condition or "match_type" - Possible values [contains|match|missing|empty|not_empty]
|
||||
// std::string match{}; // match field that is not always used, but works in conjunction with "condition" values [missing|match|contains]
|
||||
// std::string sql{}; // the SQL DDL that gets ran when the condition is true
|
||||
// };
|
||||
+7
-1799
File diff suppressed because it is too large
Load Diff
@@ -131,85 +131,118 @@ bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version
|
||||
bool Database::GetUnusedInstanceID(uint16 &instance_id)
|
||||
{
|
||||
uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances);
|
||||
uint32 max = 32000;
|
||||
uint32 max_instance_id = 32000;
|
||||
|
||||
// sanity check reserved
|
||||
if (max_reserved_instance_id >= max_instance_id) {
|
||||
instance_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// recycle instances
|
||||
if (RuleB(Instances, RecycleInstanceIds)) {
|
||||
|
||||
//query to get first unused id above reserved
|
||||
auto query = fmt::format(
|
||||
SQL(
|
||||
SELECT id
|
||||
FROM instance_list
|
||||
WHERE id = {};
|
||||
),
|
||||
max_reserved_instance_id + 1
|
||||
);
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
// could not successfully query - bail out
|
||||
if (!results.Success()) {
|
||||
instance_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// first id is available
|
||||
if (results.RowCount() == 0) {
|
||||
instance_id = max_reserved_instance_id + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
// now look for next available above reserved
|
||||
query = fmt::format(
|
||||
SQL(
|
||||
SELECT MIN(i.id + 1) AS next_available
|
||||
FROM instance_list i
|
||||
LEFT JOIN instance_list i2 ON i.id + 1 = i2.id
|
||||
WHERE i.id >= {}
|
||||
AND i2.id IS NULL;
|
||||
),
|
||||
max_reserved_instance_id
|
||||
);
|
||||
|
||||
results = QueryDatabase(query);
|
||||
|
||||
// could not successfully query - bail out
|
||||
if (!results.Success()) {
|
||||
instance_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// did not retrieve any rows - bail out
|
||||
if (results.RowCount() == 0) {
|
||||
instance_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
// check that id is within limits
|
||||
if (row[0] && Strings::ToInt(row[0]) <= max_instance_id) {
|
||||
instance_id = Strings::ToInt(row[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
// no available instance ids
|
||||
instance_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// get max unused id above reserved
|
||||
auto query = fmt::format(
|
||||
"SELECT IFNULL(MAX(id), {}) + 1 FROM instance_list WHERE id > {}",
|
||||
max_reserved_instance_id,
|
||||
max_reserved_instance_id
|
||||
);
|
||||
|
||||
if (RuleB(Instances, RecycleInstanceIds)) {
|
||||
query = (
|
||||
SQL(
|
||||
SELECT i.id + 1 AS next_available
|
||||
FROM instance_list i
|
||||
LEFT JOIN instance_list i2 ON i2.id = i.id + 1
|
||||
WHERE i2.id IS NULL
|
||||
ORDER BY i.id
|
||||
LIMIT 0, 1;
|
||||
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
// could not successfully query - bail out
|
||||
if (!results.Success()) {
|
||||
instance_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// did not retrieve any rows - bail out
|
||||
if (results.RowCount() == 0) {
|
||||
instance_id = max_reserved_instance_id;
|
||||
return true;
|
||||
instance_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
if (Strings::ToInt(row[0]) <= max) {
|
||||
// no instances currently used
|
||||
if (!row[0]) {
|
||||
instance_id = max_reserved_instance_id + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
// check that id is within limits
|
||||
if (Strings::ToInt(row[0]) <= max_instance_id) {
|
||||
instance_id = Strings::ToInt(row[0]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (instance_id < max_reserved_instance_id) {
|
||||
instance_id = max_reserved_instance_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
query = fmt::format("SELECT id FROM instance_list where id > {} ORDER BY id", max_reserved_instance_id);
|
||||
results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success()) {
|
||||
instance_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (results.RowCount() == 0) {
|
||||
instance_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
max_reserved_instance_id++;
|
||||
|
||||
for (auto row : results) {
|
||||
if (max_reserved_instance_id < Strings::ToUnsignedInt(row[0])) {
|
||||
instance_id = max_reserved_instance_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (max_reserved_instance_id > max) {
|
||||
instance_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
max_reserved_instance_id++;
|
||||
}
|
||||
|
||||
instance_id = max_reserved_instance_id;
|
||||
|
||||
return true;
|
||||
// no available instance ids
|
||||
instance_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Database::IsGlobalInstance(uint16 instance_id)
|
||||
@@ -429,8 +462,6 @@ void Database::AssignRaidToInstance(uint32 raid_id, uint32 instance_id)
|
||||
|
||||
void Database::DeleteInstance(uint16 instance_id)
|
||||
{
|
||||
std::string query;
|
||||
|
||||
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id = {}", instance_id));
|
||||
|
||||
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
|
||||
|
||||
@@ -66,9 +66,10 @@ namespace DatabaseSchema {
|
||||
{"character_potionbelt", "id"},
|
||||
{"character_skills", "id"},
|
||||
{"character_spells", "id"},
|
||||
{"character_stats_record", "character_id"},
|
||||
{"character_task_timers", "character_id"},
|
||||
{"character_tasks", "charid"},
|
||||
{"character_tribute", "id"},
|
||||
{"character_tribute", "character_id"},
|
||||
{"completed_tasks", "charid"},
|
||||
{"data_buckets", "id"},
|
||||
{"faction_values", "char_id"},
|
||||
@@ -134,6 +135,7 @@ namespace DatabaseSchema {
|
||||
"character_potionbelt",
|
||||
"character_skills",
|
||||
"character_spells",
|
||||
"character_stats_record",
|
||||
"character_task_timers",
|
||||
"character_tasks",
|
||||
"character_tribute",
|
||||
@@ -256,7 +258,9 @@ namespace DatabaseSchema {
|
||||
{
|
||||
return {
|
||||
"chatchannels",
|
||||
"chatchannel_reserved_names",
|
||||
"command_settings",
|
||||
"command_subsettings",
|
||||
"content_flags",
|
||||
"db_str",
|
||||
"eqtime",
|
||||
@@ -392,9 +396,6 @@ namespace DatabaseSchema {
|
||||
"bot_command_settings",
|
||||
"bot_create_combinations",
|
||||
"bot_data",
|
||||
"bot_group_members",
|
||||
"bot_groups",
|
||||
"bot_guild_members",
|
||||
"bot_heal_rotation_members",
|
||||
"bot_heal_rotation_targets",
|
||||
"bot_heal_rotations",
|
||||
|
||||
+135
-3
@@ -13,6 +13,7 @@
|
||||
#include <iostream>
|
||||
#include <mysqld_error.h>
|
||||
#include <string.h>
|
||||
#include "strings.h"
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#define snprintf _snprintf
|
||||
@@ -74,13 +75,13 @@ void DBcore::ping()
|
||||
m_mutex->unlock();
|
||||
}
|
||||
|
||||
MySQLRequestResult DBcore::QueryDatabase(std::string query, bool retryOnFailureOnce)
|
||||
MySQLRequestResult DBcore::QueryDatabase(const std::string& query, bool retryOnFailureOnce)
|
||||
{
|
||||
auto r = QueryDatabase(query.c_str(), query.length(), retryOnFailureOnce);
|
||||
return r;
|
||||
}
|
||||
|
||||
bool DBcore::DoesTableExist(std::string table_name)
|
||||
bool DBcore::DoesTableExist(const std::string& table_name)
|
||||
{
|
||||
auto results = QueryDatabase(fmt::format("SHOW TABLES LIKE '{}'", table_name));
|
||||
|
||||
@@ -136,7 +137,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
|
||||
/**
|
||||
* Error logging
|
||||
*/
|
||||
if (mysql_errno(mysql) > 0 && strlen(query) > 0) {
|
||||
if (mysql_errno(mysql) > 0 && query[0] != '\0') {
|
||||
LogMySQLError("[{}] [{}]\n[{}]", mysql_errno(mysql), mysql_error(mysql), query);
|
||||
}
|
||||
|
||||
@@ -305,3 +306,134 @@ void DBcore::SetMutex(Mutex *mutex)
|
||||
|
||||
DBcore::m_mutex = mutex;
|
||||
}
|
||||
|
||||
// executes multiple statements in one query
|
||||
// do not use this in application logic
|
||||
// this was built and maintained for database migrations only
|
||||
MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
|
||||
{
|
||||
SetMultiStatementsOn();
|
||||
|
||||
BenchTimer timer;
|
||||
timer.reset();
|
||||
|
||||
LockMutex lock(m_mutex);
|
||||
|
||||
// Reconnect if we are not connected before hand.
|
||||
if (pStatus != Connected) {
|
||||
Open();
|
||||
}
|
||||
auto r = MySQLRequestResult{};
|
||||
|
||||
int status = mysql_real_query(mysql, query.c_str(), query.length());
|
||||
|
||||
// process single result
|
||||
if (status != 0) {
|
||||
unsigned int error_number = mysql_errno(mysql);
|
||||
|
||||
if (error_number == CR_SERVER_GONE_ERROR) {
|
||||
pStatus = Error;
|
||||
}
|
||||
|
||||
// error logging
|
||||
if (mysql_errno(mysql) > 0 && query.length() > 0 && mysql_errno(mysql) != 1065) {
|
||||
std::string error_raw = fmt::format("{}", mysql_error(mysql));
|
||||
std::string mysql_err = Strings::Trim(error_raw);
|
||||
std::string clean_query = Strings::Replace(query, "\n", "");
|
||||
LogMySQLError("[{}] ({}) query [{}]", mysql_err, mysql_errno(mysql), clean_query);
|
||||
|
||||
MYSQL_RES *res = mysql_store_result(mysql);
|
||||
|
||||
uint32 row_count = 0;
|
||||
if (res) {
|
||||
row_count = (uint32) mysql_num_rows(res);
|
||||
}
|
||||
|
||||
r = MySQLRequestResult(
|
||||
res,
|
||||
(uint32) mysql_affected_rows(mysql),
|
||||
row_count,
|
||||
(uint32) mysql_field_count(mysql),
|
||||
(uint32) mysql_insert_id(mysql)
|
||||
);
|
||||
|
||||
std::string error_message = mysql_error(mysql);
|
||||
r.SetErrorMessage(error_message);
|
||||
r.SetErrorNumber(mysql_errno(mysql));
|
||||
|
||||
if (res) {
|
||||
mysql_free_result(res);
|
||||
}
|
||||
|
||||
SetMultiStatementsOff();
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int index = 0;
|
||||
|
||||
// there could be a query with a semicolon in the actual data, this is best effort for
|
||||
// logging / display purposes
|
||||
// rare that we see this when this is only used in DDL statements
|
||||
auto pieces = Strings::Split(query, ";");
|
||||
|
||||
// process each statement result
|
||||
do {
|
||||
uint32 row_count = 0;
|
||||
MYSQL_RES *res = mysql_store_result(mysql);
|
||||
|
||||
r = MySQLRequestResult(
|
||||
res,
|
||||
(uint32) mysql_affected_rows(mysql),
|
||||
row_count,
|
||||
(uint32) mysql_field_count(mysql),
|
||||
(uint32) mysql_insert_id(mysql)
|
||||
);
|
||||
|
||||
if (pieces.size() >= index) {
|
||||
auto piece = pieces[index];
|
||||
LogMySQLQuery(
|
||||
"{} -- ({} row{} affected) ({}s)",
|
||||
piece,
|
||||
r.RowsAffected(),
|
||||
r.RowsAffected() == 1 ? "" : "s",
|
||||
std::to_string(timer.elapsed())
|
||||
);
|
||||
}
|
||||
|
||||
if (res) {
|
||||
row_count = (uint32) mysql_num_rows(res);
|
||||
}
|
||||
|
||||
// more results? -1 = no, >0 = error, 0 = yes (keep looping)
|
||||
if ((status = mysql_next_result(mysql)) > 0) {
|
||||
if (mysql_errno(mysql) > 0) {
|
||||
LogMySQLError("[{}] [{}]", mysql_errno(mysql), mysql_error(mysql));
|
||||
}
|
||||
|
||||
mysql_free_result(res);
|
||||
|
||||
// error logging
|
||||
std::string error_message = mysql_error(mysql);
|
||||
r.SetErrorMessage(error_message);
|
||||
r.SetErrorNumber(mysql_errno(mysql));
|
||||
|
||||
SetMultiStatementsOff();
|
||||
|
||||
// we handle errors elsewhere
|
||||
return r;
|
||||
}
|
||||
|
||||
if (res) {
|
||||
mysql_free_result(res);
|
||||
}
|
||||
|
||||
index++;
|
||||
} while (status == 0);
|
||||
|
||||
SetMultiStatementsOff();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
+16
-3
@@ -24,7 +24,8 @@ public:
|
||||
~DBcore();
|
||||
eStatus GetStatus() { return pStatus; }
|
||||
MySQLRequestResult QueryDatabase(const char *query, uint32 querylen, bool retryOnFailureOnce = true);
|
||||
MySQLRequestResult QueryDatabase(std::string query, bool retryOnFailureOnce = true);
|
||||
MySQLRequestResult QueryDatabase(const std::string& query, bool retryOnFailureOnce = true);
|
||||
MySQLRequestResult QueryDatabaseMulti(const std::string &query);
|
||||
void TransactionBegin();
|
||||
void TransactionCommit();
|
||||
void TransactionRollback();
|
||||
@@ -35,7 +36,7 @@ public:
|
||||
const std::string &GetOriginHost() const;
|
||||
void SetOriginHost(const std::string &origin_host);
|
||||
|
||||
bool DoesTableExist(std::string table_name);
|
||||
bool DoesTableExist(const std::string& table_name);
|
||||
|
||||
void SetMySQL(const DBcore &o)
|
||||
{
|
||||
@@ -77,8 +78,20 @@ private:
|
||||
uint32 pPort;
|
||||
bool pSSL;
|
||||
|
||||
// allows multiple queries to be executed within the same query
|
||||
// do not use this under normal operation
|
||||
// we use this during database migrations only currently
|
||||
void SetMultiStatementsOn()
|
||||
{
|
||||
mysql_set_server_option(mysql, MYSQL_OPTION_MULTI_STATEMENTS_ON);
|
||||
}
|
||||
|
||||
// disables multiple statements to be executed in one query
|
||||
void SetMultiStatementsOff()
|
||||
{
|
||||
mysql_set_server_option(mysql, MYSQL_OPTION_MULTI_STATEMENTS_OFF);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+69
-119
@@ -11,7 +11,7 @@
|
||||
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
|
||||
@@ -19,131 +19,81 @@
|
||||
|
||||
#include "deity.h"
|
||||
|
||||
|
||||
EQ::deity::DeityTypeBit EQ::deity::ConvertDeityTypeToDeityTypeBit(DeityType deity_type)
|
||||
EQ::deity::DeityTypeBit EQ::deity::GetDeityBitmask(DeityType deity_type)
|
||||
{
|
||||
switch (deity_type) {
|
||||
case DeityBertoxxulous:
|
||||
return bit_DeityBertoxxulous;
|
||||
case DeityBrellSirilis:
|
||||
return bit_DeityBrellSirilis;
|
||||
case DeityCazicThule:
|
||||
return bit_DeityCazicThule;
|
||||
case DeityErollisiMarr:
|
||||
return bit_DeityErollisiMarr;
|
||||
case DeityBristlebane:
|
||||
return bit_DeityBristlebane;
|
||||
case DeityInnoruuk:
|
||||
return bit_DeityInnoruuk;
|
||||
case DeityKarana:
|
||||
return bit_DeityKarana;
|
||||
case DeityMithanielMarr:
|
||||
return bit_DeityMithanielMarr;
|
||||
case DeityPrexus:
|
||||
return bit_DeityPrexus;
|
||||
case DeityQuellious:
|
||||
return bit_DeityQuellious;
|
||||
case DeityRallosZek:
|
||||
return bit_DeityRallosZek;
|
||||
case DeityRodcetNife:
|
||||
return bit_DeityRodcetNife;
|
||||
case DeitySolusekRo:
|
||||
return bit_DeitySolusekRo;
|
||||
case DeityTheTribunal:
|
||||
return bit_DeityTheTribunal;
|
||||
case DeityTunare:
|
||||
return bit_DeityTunare;
|
||||
case DeityVeeshan:
|
||||
return bit_DeityVeeshan;
|
||||
case DeityAgnostic_LB:
|
||||
case DeityAgnostic:
|
||||
return bit_DeityAgnostic;
|
||||
default:
|
||||
return bit_DeityAll;
|
||||
};
|
||||
case DeityBertoxxulous:
|
||||
return bit_DeityBertoxxulous;
|
||||
case DeityBrellSirilis:
|
||||
return bit_DeityBrellSirilis;
|
||||
case DeityCazicThule:
|
||||
return bit_DeityCazicThule;
|
||||
case DeityErollisiMarr:
|
||||
return bit_DeityErollisiMarr;
|
||||
case DeityBristlebane:
|
||||
return bit_DeityBristlebane;
|
||||
case DeityInnoruuk:
|
||||
return bit_DeityInnoruuk;
|
||||
case DeityKarana:
|
||||
return bit_DeityKarana;
|
||||
case DeityMithanielMarr:
|
||||
return bit_DeityMithanielMarr;
|
||||
case DeityPrexus:
|
||||
return bit_DeityPrexus;
|
||||
case DeityQuellious:
|
||||
return bit_DeityQuellious;
|
||||
case DeityRallosZek:
|
||||
return bit_DeityRallosZek;
|
||||
case DeityRodcetNife:
|
||||
return bit_DeityRodcetNife;
|
||||
case DeitySolusekRo:
|
||||
return bit_DeitySolusekRo;
|
||||
case DeityTheTribunal:
|
||||
return bit_DeityTheTribunal;
|
||||
case DeityTunare:
|
||||
return bit_DeityTunare;
|
||||
case DeityVeeshan:
|
||||
return bit_DeityVeeshan;
|
||||
case DeityAgnostic_LB:
|
||||
case DeityAgnostic:
|
||||
return bit_DeityAgnostic;
|
||||
default:
|
||||
return bit_DeityAll;
|
||||
}
|
||||
}
|
||||
|
||||
EQ::deity::DeityType EQ::deity::ConvertDeityTypeBitToDeityType(DeityTypeBit deity_type_bit)
|
||||
const std::map<EQ::deity::DeityType, std::string>& EQ::deity::GetDeityMap()
|
||||
{
|
||||
switch (deity_type_bit) {
|
||||
case bit_DeityAgnostic:
|
||||
return DeityAgnostic;
|
||||
case bit_DeityBertoxxulous:
|
||||
return DeityBertoxxulous;
|
||||
case bit_DeityBrellSirilis:
|
||||
return DeityBrellSirilis;
|
||||
case bit_DeityCazicThule:
|
||||
return DeityCazicThule;
|
||||
case bit_DeityErollisiMarr:
|
||||
return DeityErollisiMarr;
|
||||
case bit_DeityBristlebane:
|
||||
return DeityBristlebane;
|
||||
case bit_DeityInnoruuk:
|
||||
return DeityInnoruuk;
|
||||
case bit_DeityKarana:
|
||||
return DeityKarana;
|
||||
case bit_DeityMithanielMarr:
|
||||
return DeityMithanielMarr;
|
||||
case bit_DeityPrexus:
|
||||
return DeityPrexus;
|
||||
case bit_DeityQuellious:
|
||||
return DeityQuellious;
|
||||
case bit_DeityRallosZek:
|
||||
return DeityRallosZek;
|
||||
case bit_DeityRodcetNife:
|
||||
return DeityRodcetNife;
|
||||
case bit_DeitySolusekRo:
|
||||
return DeitySolusekRo;
|
||||
case bit_DeityTheTribunal:
|
||||
return DeityTheTribunal;
|
||||
case bit_DeityTunare:
|
||||
return DeityTunare;
|
||||
case bit_DeityVeeshan:
|
||||
return DeityVeeshan;
|
||||
default:
|
||||
return DeityUnknown;
|
||||
static const std::map<EQ::deity::DeityType, std::string> deity_map = {
|
||||
{ DeityAgnostic, "Agnostic" },
|
||||
{ DeityAgnostic_LB, "Agnostic" },
|
||||
{ DeityBertoxxulous, "Bertoxxulous" },
|
||||
{ DeityBrellSirilis, "Brell Serilis" },
|
||||
{ DeityBristlebane, "Bristlebane" },
|
||||
{ DeityCazicThule, "Cazic-Thule" },
|
||||
{ DeityErollisiMarr, "Erollisi Marr" },
|
||||
{ DeityInnoruuk, "Innoruuk" },
|
||||
{ DeityKarana, "Karana" },
|
||||
{ DeityMithanielMarr, "Mithaniel Marr" },
|
||||
{ DeityPrexus, "Prexus" },
|
||||
{ DeityQuellious, "Quellious" },
|
||||
{ DeityRallosZek, "Rallos Zek" },
|
||||
{ DeityRodcetNife, "Rodcet Nife" },
|
||||
{ DeitySolusekRo, "Solusek Ro" },
|
||||
{ DeityTheTribunal, "The Tribunal" },
|
||||
{ DeityTunare, "Tunare" },
|
||||
{ DeityVeeshan, "Veeshan" }
|
||||
};
|
||||
|
||||
return deity_map;
|
||||
}
|
||||
|
||||
const char* EQ::deity::DeityName(DeityType deity_type)
|
||||
std::string EQ::deity::GetDeityName(DeityType deity_type)
|
||||
{
|
||||
switch (deity_type) {
|
||||
case DeityBertoxxulous:
|
||||
return "Bertoxxulous";
|
||||
case DeityBrellSirilis:
|
||||
return "Brell Serilis";
|
||||
case DeityCazicThule:
|
||||
return "Cazic-Thule";
|
||||
case DeityErollisiMarr:
|
||||
return "Erollisi Marr";
|
||||
case DeityBristlebane:
|
||||
return "Bristlebane";
|
||||
case DeityInnoruuk:
|
||||
return "Innoruuk";
|
||||
case DeityKarana:
|
||||
return "Karana";
|
||||
case DeityMithanielMarr:
|
||||
return "Mithaniel Marr";
|
||||
case DeityPrexus:
|
||||
return "Prexus";
|
||||
case DeityQuellious:
|
||||
return "Quellious";
|
||||
case DeityRallosZek:
|
||||
return "Rallos Zek";
|
||||
case DeityRodcetNife:
|
||||
return "Rodcet Nife";
|
||||
case DeitySolusekRo:
|
||||
return "Solusek Ro";
|
||||
case DeityTheTribunal:
|
||||
return "The Tribunal";
|
||||
case DeityTunare:
|
||||
return "Tunare";
|
||||
case DeityVeeshan:
|
||||
return "Veeshan";
|
||||
case DeityAgnostic_LB:
|
||||
case DeityAgnostic:
|
||||
return "Agnostic";
|
||||
default:
|
||||
return "Unknown";
|
||||
};
|
||||
|
||||
if (EQ::deity::GetDeityMap().find(deity_type) != EQ::deity::GetDeityMap().end()) {
|
||||
return EQ::deity::GetDeityMap().find(deity_type)->second;
|
||||
}
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
+22
-21
@@ -21,6 +21,8 @@
|
||||
#define COMMON_DEITY_H
|
||||
|
||||
#include "types.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace EQ
|
||||
@@ -49,30 +51,29 @@ namespace EQ
|
||||
};
|
||||
|
||||
enum DeityTypeBit : uint32 {
|
||||
bit_DeityNone = 0x00000000,
|
||||
bit_DeityAgnostic = 0x00000001,
|
||||
bit_DeityBertoxxulous = 0x00000002,
|
||||
bit_DeityBrellSirilis = 0x00000004,
|
||||
bit_DeityCazicThule = 0x00000008,
|
||||
bit_DeityErollisiMarr = 0x00000010,
|
||||
bit_DeityBristlebane = 0x00000020,
|
||||
bit_DeityInnoruuk = 0x00000040,
|
||||
bit_DeityKarana = 0x00000080,
|
||||
bit_DeityAgnostic = 0x00000001,
|
||||
bit_DeityBertoxxulous = 0x00000002,
|
||||
bit_DeityBrellSirilis = 0x00000004,
|
||||
bit_DeityCazicThule = 0x00000008,
|
||||
bit_DeityErollisiMarr = 0x00000010,
|
||||
bit_DeityBristlebane = 0x00000020,
|
||||
bit_DeityInnoruuk = 0x00000040,
|
||||
bit_DeityKarana = 0x00000080,
|
||||
bit_DeityMithanielMarr = 0x00000100,
|
||||
bit_DeityPrexus = 0x00000200,
|
||||
bit_DeityQuellious = 0x00000400,
|
||||
bit_DeityRallosZek = 0x00000800,
|
||||
bit_DeityRodcetNife = 0x00001000,
|
||||
bit_DeitySolusekRo = 0x00002000,
|
||||
bit_DeityTheTribunal = 0x00004000,
|
||||
bit_DeityTunare = 0x00008000,
|
||||
bit_DeityVeeshan = 0x00010000,
|
||||
bit_DeityAll = 0xFFFFFFFF
|
||||
bit_DeityPrexus = 0x00000200,
|
||||
bit_DeityQuellious = 0x00000400,
|
||||
bit_DeityRallosZek = 0x00000800,
|
||||
bit_DeityRodcetNife = 0x00001000,
|
||||
bit_DeitySolusekRo = 0x00002000,
|
||||
bit_DeityTheTribunal = 0x00004000,
|
||||
bit_DeityTunare = 0x00008000,
|
||||
bit_DeityVeeshan = 0x00010000,
|
||||
bit_DeityAll = UINT32_MAX
|
||||
};
|
||||
|
||||
extern DeityTypeBit ConvertDeityTypeToDeityTypeBit(DeityType deity_type);
|
||||
extern DeityType ConvertDeityTypeBitToDeityType(DeityTypeBit deity_type_bit);
|
||||
extern const char* DeityName(DeityType deity_type);
|
||||
extern DeityTypeBit GetDeityBitmask(DeityType deity_type);
|
||||
extern std::string GetDeityName(DeityType deity_type);
|
||||
extern const std::map<DeityType, std::string>& GetDeityMap();
|
||||
|
||||
} /*deity*/
|
||||
|
||||
|
||||
@@ -27,9 +27,6 @@ void Discord::SendWebhookMessage(const std::string &message, const std::string &
|
||||
cli.set_connection_timeout(0, 15000000); // 15 sec
|
||||
cli.set_read_timeout(15, 0); // 15 seconds
|
||||
cli.set_write_timeout(15, 0); // 15 seconds
|
||||
httplib::Headers headers = {
|
||||
{"Content-Type", "application/json"}
|
||||
};
|
||||
|
||||
// payload
|
||||
Json::Value p;
|
||||
@@ -96,9 +93,6 @@ void Discord::SendPlayerEventMessage(
|
||||
cli.set_connection_timeout(0, 15000000); // 15 sec
|
||||
cli.set_read_timeout(15, 0); // 15 seconds
|
||||
cli.set_write_timeout(15, 0); // 15 seconds
|
||||
httplib::Headers headers = {
|
||||
{"Content-Type", "application/json"}
|
||||
};
|
||||
|
||||
std::string payload = PlayerEventLogs::GetDiscordPayloadFromEvent(e);
|
||||
if (payload.empty()) {
|
||||
|
||||
@@ -37,7 +37,7 @@ void DiscordManager::ProcessMessageQueue()
|
||||
message,
|
||||
webhook.webhook_url
|
||||
);
|
||||
message = "";
|
||||
message.clear();
|
||||
}
|
||||
|
||||
message += m;
|
||||
@@ -51,7 +51,7 @@ void DiscordManager::ProcessMessageQueue()
|
||||
webhook.webhook_url
|
||||
);
|
||||
}
|
||||
message = "";
|
||||
message.clear();
|
||||
}
|
||||
}
|
||||
// final flush
|
||||
|
||||
+34
-33
@@ -197,11 +197,11 @@ const std::map<int, std::string>& EQ::constants::GetLanguageMap()
|
||||
|
||||
std::string EQ::constants::GetLanguageName(int language_id)
|
||||
{
|
||||
if (EQ::ValueWithin(language_id, LANG_COMMON_TONGUE, LANG_UNKNOWN)) {
|
||||
return EQ::constants::GetLanguageMap().find(language_id)->second;
|
||||
if (!EQ::ValueWithin(language_id, LANG_COMMON_TONGUE, LANG_UNKNOWN)) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return EQ::constants::GetLanguageMap().find(language_id)->second;
|
||||
}
|
||||
|
||||
const std::map<uint32, std::string>& EQ::constants::GetLDoNThemeMap()
|
||||
@@ -220,11 +220,11 @@ const std::map<uint32, std::string>& EQ::constants::GetLDoNThemeMap()
|
||||
|
||||
std::string EQ::constants::GetLDoNThemeName(uint32 theme_id)
|
||||
{
|
||||
if (EQ::ValueWithin(theme_id, LDoNThemes::Unused, LDoNThemes::TAK)) {
|
||||
return EQ::constants::GetLDoNThemeMap().find(theme_id)->second;
|
||||
if (!EQ::ValueWithin(theme_id, LDoNThemes::Unused, LDoNThemes::TAK)) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return EQ::constants::GetLDoNThemeMap().find(theme_id)->second;
|
||||
}
|
||||
|
||||
const std::map<int8, std::string>& EQ::constants::GetFlyModeMap()
|
||||
@@ -243,11 +243,11 @@ const std::map<int8, std::string>& EQ::constants::GetFlyModeMap()
|
||||
|
||||
std::string EQ::constants::GetFlyModeName(int8 flymode_id)
|
||||
{
|
||||
if (EQ::ValueWithin(flymode_id, GravityBehavior::Ground, GravityBehavior::LevitateWhileRunning)) {
|
||||
return EQ::constants::GetFlyModeMap().find(flymode_id)->second;
|
||||
if (!EQ::ValueWithin(flymode_id, GravityBehavior::Ground, GravityBehavior::LevitateWhileRunning)) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return EQ::constants::GetFlyModeMap().find(flymode_id)->second;
|
||||
}
|
||||
|
||||
const std::map<bodyType, std::string>& EQ::constants::GetBodyTypeMap()
|
||||
@@ -365,11 +365,11 @@ const std::map<uint8, std::string>& EQ::constants::GetConsiderLevelMap()
|
||||
|
||||
std::string EQ::constants::GetConsiderLevelName(uint8 faction_consider_level)
|
||||
{
|
||||
if (EQ::constants::GetConsiderLevelMap().find(faction_consider_level) != EQ::constants::GetConsiderLevelMap().end()) {
|
||||
return EQ::constants::GetConsiderLevelMap().find(faction_consider_level)->second;
|
||||
if (!EQ::ValueWithin(faction_consider_level, ConsiderLevel::Ally, ConsiderLevel::Scowls)) {
|
||||
return std::string();;
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return EQ::constants::GetConsiderLevelMap().find(faction_consider_level)->second;
|
||||
}
|
||||
|
||||
const std::map<uint8, std::string>& EQ::constants::GetEnvironmentalDamageMap()
|
||||
@@ -386,11 +386,11 @@ const std::map<uint8, std::string>& EQ::constants::GetEnvironmentalDamageMap()
|
||||
|
||||
std::string EQ::constants::GetEnvironmentalDamageName(uint8 damage_type)
|
||||
{
|
||||
if (EQ::ValueWithin(damage_type, EnvironmentalDamage::Lava, EnvironmentalDamage::Trap)) {
|
||||
return EQ::constants::GetEnvironmentalDamageMap().find(damage_type)->second;
|
||||
if (!EQ::ValueWithin(damage_type, EnvironmentalDamage::Lava, EnvironmentalDamage::Trap)) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return EQ::constants::GetEnvironmentalDamageMap().find(damage_type)->second;
|
||||
}
|
||||
|
||||
const std::map<uint8, std::string>& EQ::constants::GetStuckBehaviorMap()
|
||||
@@ -407,11 +407,11 @@ const std::map<uint8, std::string>& EQ::constants::GetStuckBehaviorMap()
|
||||
|
||||
std::string EQ::constants::GetStuckBehaviorName(uint8 behavior_id)
|
||||
{
|
||||
if (EQ::ValueWithin(behavior_id, StuckBehavior::RunToTarget, StuckBehavior::EvadeCombat)) {
|
||||
return EQ::constants::GetStuckBehaviorMap().find(behavior_id)->second;
|
||||
if (!EQ::ValueWithin(behavior_id, StuckBehavior::RunToTarget, StuckBehavior::EvadeCombat)) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return EQ::constants::GetStuckBehaviorMap().find(behavior_id)->second;
|
||||
}
|
||||
|
||||
const std::map<uint8, std::string>& EQ::constants::GetSpawnAnimationMap()
|
||||
@@ -429,11 +429,11 @@ const std::map<uint8, std::string>& EQ::constants::GetSpawnAnimationMap()
|
||||
|
||||
std::string EQ::constants::GetSpawnAnimationName(uint8 animation_id)
|
||||
{
|
||||
if (EQ::ValueWithin(animation_id, SpawnAnimations::Standing, SpawnAnimations::Looting)) {
|
||||
return EQ::constants::GetSpawnAnimationMap().find(animation_id)->second;
|
||||
if (!EQ::ValueWithin(animation_id, SpawnAnimations::Standing, SpawnAnimations::Looting)) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return EQ::constants::GetSpawnAnimationMap().find(animation_id)->second;
|
||||
}
|
||||
|
||||
const std::map<int, std::string>& EQ::constants::GetObjectTypeMap()
|
||||
@@ -507,11 +507,12 @@ const std::map<int, std::string>& EQ::constants::GetObjectTypeMap()
|
||||
|
||||
std::string EQ::constants::GetObjectTypeName(int object_type)
|
||||
{
|
||||
if (EQ::ValueWithin(object_type, ObjectTypes::SmallBag, ObjectTypes::NoDeposit)) {
|
||||
return EQ::constants::GetObjectTypeMap().find(object_type)->second;
|
||||
if (!EQ::ValueWithin(object_type, ObjectTypes::SmallBag, ObjectTypes::NoDeposit)) {
|
||||
return std::string();
|
||||
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return EQ::constants::GetObjectTypeMap().find(object_type)->second;
|
||||
}
|
||||
|
||||
const std::map<uint8, std::string> &EQ::constants::GetWeatherTypeMap()
|
||||
@@ -527,11 +528,11 @@ const std::map<uint8, std::string> &EQ::constants::GetWeatherTypeMap()
|
||||
|
||||
std::string EQ::constants::GetWeatherTypeName(uint8 weather_type)
|
||||
{
|
||||
if (EQ::ValueWithin(weather_type, WeatherTypes::None, WeatherTypes::Snowing)) {
|
||||
return EQ::constants::GetWeatherTypeMap().find(weather_type)->second;
|
||||
if (!EQ::ValueWithin(weather_type, WeatherTypes::None, WeatherTypes::Snowing)) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return EQ::constants::GetWeatherTypeMap().find(weather_type)->second;
|
||||
}
|
||||
|
||||
const std::map<uint8, std::string> &EQ::constants::GetEmoteEventTypeMap()
|
||||
@@ -553,11 +554,11 @@ const std::map<uint8, std::string> &EQ::constants::GetEmoteEventTypeMap()
|
||||
|
||||
std::string EQ::constants::GetEmoteEventTypeName(uint8 emote_event_type)
|
||||
{
|
||||
if (EQ::ValueWithin(emote_event_type, EmoteEventTypes::LeaveCombat, EmoteEventTypes::OnDespawn)) {
|
||||
return EQ::constants::GetEmoteEventTypeMap().find(emote_event_type)->second;
|
||||
if (!EQ::ValueWithin(emote_event_type, EmoteEventTypes::LeaveCombat, EmoteEventTypes::OnDespawn)) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return EQ::constants::GetEmoteEventTypeMap().find(emote_event_type)->second;
|
||||
}
|
||||
|
||||
const std::map<uint8, std::string> &EQ::constants::GetEmoteTypeMap()
|
||||
@@ -573,9 +574,9 @@ const std::map<uint8, std::string> &EQ::constants::GetEmoteTypeMap()
|
||||
|
||||
std::string EQ::constants::GetEmoteTypeName(uint8 emote_type)
|
||||
{
|
||||
if (EQ::ValueWithin(emote_type, EmoteTypes::Emote, EmoteTypes::Proximity)) {
|
||||
return EQ::constants::GetEmoteTypeMap().find(emote_type)->second;
|
||||
if (!EQ::ValueWithin(emote_type, EmoteTypes::Emote, EmoteTypes::Proximity)) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return EQ::constants::GetEmoteTypeMap().find(emote_type)->second;
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ N(OP_BeginCast),
|
||||
N(OP_Bind_Wound),
|
||||
N(OP_BlockedBuffs),
|
||||
N(OP_BoardBoat),
|
||||
N(OP_BookButton),
|
||||
N(OP_Buff),
|
||||
N(OP_BuffCreate),
|
||||
N(OP_BuffRemoveRequest),
|
||||
@@ -316,6 +317,7 @@ N(OP_LootRequest),
|
||||
N(OP_ManaChange),
|
||||
N(OP_ManaUpdate),
|
||||
N(OP_MarkNPC),
|
||||
N(OP_MarkRaidNPC),
|
||||
N(OP_Marquee),
|
||||
N(OP_MemorizeSpell),
|
||||
N(OP_Mend),
|
||||
@@ -398,6 +400,8 @@ N(OP_PVPLeaderBoardRequest),
|
||||
N(OP_PVPStats),
|
||||
N(OP_QueryResponseThing),
|
||||
N(OP_QueryUCSServerStatus),
|
||||
N(OP_RaidDelegateAbility),
|
||||
N(OP_RaidClearNPCMarks),
|
||||
N(OP_RaidInvite),
|
||||
N(OP_RaidJoin),
|
||||
N(OP_RaidUpdate),
|
||||
|
||||
@@ -1045,4 +1045,11 @@ enum ResurrectionActions
|
||||
Accept
|
||||
};
|
||||
|
||||
enum ScribeSpellActions
|
||||
{
|
||||
Scribe,
|
||||
Memorize,
|
||||
Unmemorize
|
||||
};
|
||||
|
||||
#endif /*COMMON_EQ_CONSTANTS_H*/
|
||||
|
||||
+1
-1
@@ -129,7 +129,7 @@ namespace EQ
|
||||
|
||||
LookupEntry(const LookupEntry *lookup_entry) { }
|
||||
LookupEntry(
|
||||
InventoryTypeSize_Struct InventoryTypeSize,
|
||||
const InventoryTypeSize_Struct& InventoryTypeSize,
|
||||
uint64 EquipmentBitmask,
|
||||
uint64 GeneralBitmask,
|
||||
uint64 CursorBitmask,
|
||||
|
||||
+1
-138
@@ -236,26 +236,6 @@ uint32 EQApplicationPacket::serialize(uint16 opcode, unsigned char *dest) const
|
||||
return size+OpCodeBytes;
|
||||
}
|
||||
|
||||
/*EQProtocolPacket::EQProtocolPacket(uint16 op, const unsigned char *buf, uint32 len)
|
||||
: BasePacket(buf, len),
|
||||
opcode(op)
|
||||
{
|
||||
|
||||
uint32 offset;
|
||||
opcode=ntohs(*(const uint16 *)buf);
|
||||
offset=2;
|
||||
|
||||
if (len-offset) {
|
||||
pBuffer= new unsigned char[len-offset];
|
||||
memcpy(pBuffer,buf+offset,len-offset);
|
||||
size=len-offset;
|
||||
} else {
|
||||
pBuffer=nullptr;
|
||||
size=0;
|
||||
}
|
||||
OpMgr=&RawOpcodeManager;
|
||||
}*/
|
||||
|
||||
bool EQProtocolPacket::combine(const EQProtocolPacket *rhs)
|
||||
{
|
||||
bool result=false;
|
||||
@@ -287,74 +267,6 @@ bool result=false;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
this is the code to do app-layer combining, instead of protocol layer.
|
||||
this was taken out due to complex interactions with the opcode manager,
|
||||
and will require a bit more thinking (likely moving into EQStream) to
|
||||
get running again... but might be a good thing some day.
|
||||
|
||||
bool EQApplicationPacket::combine(const EQApplicationPacket *rhs)
|
||||
{
|
||||
uint32 newsize=0, offset=0;
|
||||
unsigned char *tmpbuffer=nullptr;
|
||||
|
||||
if (opcode!=OP_AppCombined) {
|
||||
newsize=app_opcode_size+size+(size>254?3:1)+app_opcode_size+rhs->size+(rhs->size>254?3:1);
|
||||
tmpbuffer=new unsigned char [newsize];
|
||||
offset=0;
|
||||
if (size>254) {
|
||||
tmpbuffer[offset++]=0xff;
|
||||
*(uint16 *)(tmpbuffer+offset)=htons(size);
|
||||
offset+=1;
|
||||
} else {
|
||||
tmpbuffer[offset++]=size;
|
||||
}
|
||||
offset+=serialize(tmpbuffer+offset);
|
||||
} else {
|
||||
newsize=size+app_opcode_size+rhs->size+(rhs->size>254?3:1);
|
||||
tmpbuffer=new unsigned char [newsize];
|
||||
memcpy(tmpbuffer,pBuffer,size);
|
||||
offset=size;
|
||||
}
|
||||
|
||||
if (rhs->size>254) {
|
||||
tmpbuffer[offset++]=0xff;
|
||||
*(uint16 *)(tmpbuffer+offset)=htons(rhs->size);
|
||||
offset+=1;
|
||||
} else {
|
||||
tmpbuffer[offset++]=rhs->size;
|
||||
}
|
||||
offset+=rhs->serialize(tmpbuffer+offset);
|
||||
|
||||
size=offset;
|
||||
opcode=OP_AppCombined;
|
||||
|
||||
delete[] pBuffer;
|
||||
pBuffer=tmpbuffer;
|
||||
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
bool EQProtocolPacket::ValidateCRC(const unsigned char *buffer, int length, uint32 Key)
|
||||
{
|
||||
bool valid=false;
|
||||
// OP_SessionRequest, OP_SessionResponse, OP_OutOfSession are not CRC'd
|
||||
if (buffer[0]==0x00 && (buffer[1]==OP_SessionRequest || buffer[1]==OP_SessionResponse || buffer[1]==OP_OutOfSession)) {
|
||||
valid=true;
|
||||
} else {
|
||||
uint16 comp_crc=CRC16(buffer,length-2,Key);
|
||||
uint16 packet_crc=ntohs(*(const uint16 *)(buffer+length-2));
|
||||
#ifdef EQN_DEBUG
|
||||
if (packet_crc && comp_crc != packet_crc) {
|
||||
std::cout << "CRC mismatch: comp=" << std::hex << comp_crc << ", packet=" << packet_crc << std::dec << std::endl;
|
||||
}
|
||||
#endif
|
||||
valid = (!packet_crc || comp_crc == packet_crc);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
uint32 EQProtocolPacket::Decompress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize)
|
||||
{
|
||||
uint32 newlen=0;
|
||||
@@ -403,55 +315,6 @@ uint32 flag_offset=1,newlength;
|
||||
return newlength;
|
||||
}
|
||||
|
||||
void EQProtocolPacket::ChatDecode(unsigned char *buffer, int size, int DecodeKey)
|
||||
{
|
||||
if ((size >= 2) && buffer[1]!=0x01 && buffer[0]!=0x02 && buffer[0]!=0x1d) {
|
||||
int Key=DecodeKey;
|
||||
unsigned char *test=(unsigned char *)malloc(size);
|
||||
buffer+=2;
|
||||
size-=2;
|
||||
|
||||
int i;
|
||||
for (i = 0 ; i+4 <= size ; i+=4)
|
||||
{
|
||||
int pt = (*(int*)&buffer[i])^(Key);
|
||||
Key = (*(int*)&buffer[i]);
|
||||
*(int*)&test[i]=pt;
|
||||
}
|
||||
unsigned char KC=Key&0xFF;
|
||||
for ( ; i < size ; i++)
|
||||
{
|
||||
test[i]=buffer[i]^KC;
|
||||
}
|
||||
memcpy(buffer,test,size);
|
||||
free(test);
|
||||
}
|
||||
}
|
||||
|
||||
void EQProtocolPacket::ChatEncode(unsigned char *buffer, int size, int EncodeKey)
|
||||
{
|
||||
if (buffer[1]!=0x01 && buffer[0]!=0x02 && buffer[0]!=0x1d) {
|
||||
int Key=EncodeKey;
|
||||
char *test=(char*)malloc(size);
|
||||
int i;
|
||||
buffer+=2;
|
||||
size-=2;
|
||||
for ( i = 0 ; i+4 <= size ; i+=4)
|
||||
{
|
||||
int pt = (*(int*)&buffer[i])^(Key);
|
||||
Key = pt;
|
||||
*(int*)&test[i]=pt;
|
||||
}
|
||||
unsigned char KC=Key&0xFF;
|
||||
for ( ; i < size ; i++)
|
||||
{
|
||||
test[i]=buffer[i]^KC;
|
||||
}
|
||||
memcpy(buffer,test,size);
|
||||
free(test);
|
||||
}
|
||||
}
|
||||
|
||||
EQApplicationPacket *EQApplicationPacket::Copy() const {
|
||||
return(new EQApplicationPacket(*this));
|
||||
}
|
||||
@@ -515,4 +378,4 @@ std::string DumpPacketToString(const EQApplicationPacket* app){
|
||||
std::ostringstream out;
|
||||
out << DumpPacketHexToString(app->pBuffer, app->size);
|
||||
return out.str();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,11 +80,8 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
static bool ValidateCRC(const unsigned char *buffer, int length, uint32 Key);
|
||||
static uint32 Decompress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize);
|
||||
static uint32 Compress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize);
|
||||
static void ChatDecode(unsigned char *buffer, int size, int DecodeKey);
|
||||
static void ChatEncode(unsigned char *buffer, int size, int EncodeKey);
|
||||
|
||||
uint16 GetRawOpcode() const { return(opcode); }
|
||||
|
||||
|
||||
+40
-11
@@ -1793,6 +1793,17 @@ struct GMSummon_Struct {
|
||||
/*104*/ uint32 unknown2; // E0 E0 56 00
|
||||
};
|
||||
|
||||
struct GMFind_Struct {
|
||||
char charname[64];
|
||||
char gmname[64];
|
||||
uint32 success;
|
||||
uint32 zoneID;
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
uint32 unknown2;
|
||||
};
|
||||
|
||||
struct GMGoto_Struct { // x,y is swapped as compared to summon and makes sense as own packet
|
||||
/* 0*/ char charname[64];
|
||||
|
||||
@@ -2548,7 +2559,10 @@ struct GMEmoteZone_Struct {
|
||||
struct BookText_Struct {
|
||||
uint8 window; // where to display the text (0xFF means new window)
|
||||
uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly others.
|
||||
uint32 invslot; // Only used in SoF and later clients.
|
||||
int16 invslot; // Only used in SoF and later clients.
|
||||
int32 target_id;
|
||||
int8 can_cast;
|
||||
int8 can_scribe;
|
||||
char booktext[1]; // Variable Length
|
||||
};
|
||||
// This is the request to read a book.
|
||||
@@ -2557,11 +2571,18 @@ struct BookText_Struct {
|
||||
struct BookRequest_Struct {
|
||||
uint8 window; // where to display the text (0xFF means new window)
|
||||
uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly others.
|
||||
uint32 invslot; // Only used in Sof and later clients;
|
||||
int16 subslot; // The subslot inside of a bag if it is inside one.
|
||||
int16 invslot; // Only used in Sof and later clients;
|
||||
int32 target_id;
|
||||
char txtfile[20];
|
||||
};
|
||||
|
||||
// used by Scribe and CastSpell book buttons
|
||||
struct BookButton_Struct
|
||||
{
|
||||
int16 invslot; // server slot
|
||||
int32 target_id;
|
||||
};
|
||||
|
||||
/*
|
||||
** Object/Ground Spawn struct
|
||||
** Used for Forges, Ovens, ground spawns, items dropped to ground, etc
|
||||
@@ -4094,7 +4115,9 @@ struct UpdateLeadershipAA_Struct {
|
||||
|
||||
enum
|
||||
{
|
||||
GroupLeadershipAbility_MarkNPC = 0
|
||||
GroupLeadershipAbility_MarkNPC = 0,
|
||||
RaidLeadershipAbility_MarkNPC = 16,
|
||||
RaidLeadershipAbility_MainAssist = 19
|
||||
};
|
||||
|
||||
struct DoGroupLeadershipAbility_Struct
|
||||
@@ -4138,8 +4161,9 @@ struct InspectBuffs_Struct {
|
||||
struct RaidGeneral_Struct {
|
||||
/*00*/ uint32 action; //=10
|
||||
/*04*/ char player_name[64]; //should both be the player's name
|
||||
/*64*/ char leader_name[64];
|
||||
/*132*/ uint32 parameter;
|
||||
/*68*/ uint32 unknown1;
|
||||
/*72*/ char leader_name[64];
|
||||
/*136*/ uint32 parameter;
|
||||
};
|
||||
|
||||
struct RaidAddMember_Struct {
|
||||
@@ -4150,9 +4174,14 @@ struct RaidAddMember_Struct {
|
||||
/*139*/ uint8 flags[5]; //no idea if these are needed...
|
||||
};
|
||||
|
||||
struct RaidNote_Struct {
|
||||
/*000*/ RaidGeneral_Struct general;
|
||||
/*140*/ char note[64];
|
||||
};
|
||||
|
||||
struct RaidMOTD_Struct {
|
||||
/*000*/ RaidGeneral_Struct general; // leader_name and action only used
|
||||
/*136*/ char motd[0]; // max size is 1024, but reply is variable
|
||||
/*000*/ RaidGeneral_Struct general;
|
||||
/*140*/ char motd[1024];
|
||||
};
|
||||
|
||||
struct RaidLeadershipUpdate_Struct {
|
||||
@@ -5524,9 +5553,9 @@ struct ServerLootItem_Struct {
|
||||
uint32 aug_6; // uint32 aug_5;
|
||||
bool attuned;
|
||||
std::string custom_data;
|
||||
uint32 ornamenticon;
|
||||
uint32 ornamentidfile;
|
||||
uint32 ornament_hero_model;
|
||||
uint32 ornamenticon {};
|
||||
uint32 ornamentidfile {};
|
||||
uint32 ornament_hero_model {};
|
||||
uint16 trivial_min_level;
|
||||
uint16 trivial_max_level;
|
||||
uint16 npc_min_level;
|
||||
|
||||
@@ -26,7 +26,7 @@ EQStreamIdentifier::~EQStreamIdentifier() {
|
||||
}
|
||||
}
|
||||
|
||||
void EQStreamIdentifier::RegisterPatch(const EQStreamInterface::Signature &sig, const char *name, OpcodeManager ** opcodes, const StructStrategy *structs) {
|
||||
void EQStreamIdentifier::RegisterPatch(EQStreamInterface::Signature sig, const char *name, OpcodeManager ** opcodes, const StructStrategy *structs) {
|
||||
auto p = new Patch;
|
||||
p->signature = sig;
|
||||
p->name = name;
|
||||
@@ -145,7 +145,7 @@ void EQStreamIdentifier::Process() {
|
||||
}
|
||||
|
||||
void EQStreamIdentifier::AddStream(std::shared_ptr<EQStreamInterface> eqs) {
|
||||
m_streams.push_back(Record(eqs));
|
||||
m_streams.emplace_back(Record(eqs));
|
||||
eqs = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
~EQStreamIdentifier();
|
||||
|
||||
//registration interface.
|
||||
void RegisterPatch(const EQStreamInterface::Signature &sig, const char *name, OpcodeManager ** opcodes, const StructStrategy *structs);
|
||||
void RegisterPatch(EQStreamInterface::Signature sig, const char *name, OpcodeManager ** opcodes, const StructStrategy *structs);
|
||||
|
||||
//main processing interface
|
||||
void Process();
|
||||
|
||||
@@ -23,9 +23,6 @@
|
||||
|
||||
EQDB EQDB::s_EQDB;
|
||||
|
||||
EQDB::EQDB() {
|
||||
}
|
||||
|
||||
unsigned int EQDB::field_count() {
|
||||
return mysql_field_count(mysql_ref);
|
||||
}
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
|
||||
//this is the main object exported to perl.
|
||||
class EQDB {
|
||||
EQDB();
|
||||
EQDB() = default;
|
||||
public:
|
||||
static EQDB *Singleton() { return(&s_EQDB); }
|
||||
|
||||
|
||||
+24
-18
@@ -34,13 +34,13 @@ void EQEmuConfig::parse_config()
|
||||
LongName = _root["server"]["world"].get("longname", "").asString();
|
||||
WorldAddress = _root["server"]["world"].get("address", "").asString();
|
||||
LocalAddress = _root["server"]["world"].get("localaddress", "").asString();
|
||||
MaxClients = Strings::ToInt(_root["server"]["world"].get("maxclients", "-1").asString().c_str());
|
||||
MaxClients = Strings::ToInt(_root["server"]["world"].get("maxclients", "-1").asString());
|
||||
SharedKey = _root["server"]["world"].get("key", "").asString();
|
||||
LoginCount = 0;
|
||||
|
||||
if (_root["server"]["world"]["loginserver"].isObject()) {
|
||||
LoginHost = _root["server"]["world"]["loginserver"].get("host", "login.eqemulator.net").asString();
|
||||
LoginPort = Strings::ToUnsignedInt(_root["server"]["world"]["loginserver"].get("port", "5998").asString().c_str());
|
||||
LoginPort = Strings::ToUnsignedInt(_root["server"]["world"]["loginserver"].get("port", "5998").asString());
|
||||
LoginLegacy = false;
|
||||
if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") { LoginLegacy = true; }
|
||||
LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString();
|
||||
@@ -63,7 +63,7 @@ void EQEmuConfig::parse_config()
|
||||
|
||||
auto loginconfig = new LoginConfig;
|
||||
loginconfig->LoginHost = _root["server"]["world"][str].get("host", "login.eqemulator.net").asString();
|
||||
loginconfig->LoginPort = Strings::ToUnsignedInt(_root["server"]["world"][str].get("port", "5998").asString().c_str());
|
||||
loginconfig->LoginPort = Strings::ToUnsignedInt(_root["server"]["world"][str].get("port", "5998").asString());
|
||||
loginconfig->LoginAccount = _root["server"]["world"][str].get("account", "").asString();
|
||||
loginconfig->LoginPassword = _root["server"]["world"][str].get("password", "").asString();
|
||||
|
||||
@@ -85,16 +85,22 @@ void EQEmuConfig::parse_config()
|
||||
//The only way to enable locked is by switching to true, meaning this value is always false until manually set true
|
||||
Locked = false;
|
||||
if (_root["server"]["world"].get("locked", "false").asString() == "true") { Locked = true; }
|
||||
|
||||
auto_database_updates = false;
|
||||
if (_root["server"].get("auto_database_updates", "true").asString() == "true") {
|
||||
auto_database_updates = true;
|
||||
}
|
||||
|
||||
WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString();
|
||||
WorldTCPPort = Strings::ToUnsignedInt(_root["server"]["world"]["tcp"].get("port", "9000").asString().c_str());
|
||||
WorldTCPPort = Strings::ToUnsignedInt(_root["server"]["world"]["tcp"].get("port", "9000").asString());
|
||||
|
||||
TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString();
|
||||
TelnetTCPPort = Strings::ToUnsignedInt(_root["server"]["world"]["telnet"].get("port", "9001").asString().c_str());
|
||||
TelnetTCPPort = Strings::ToUnsignedInt(_root["server"]["world"]["telnet"].get("port", "9001").asString());
|
||||
TelnetEnabled = false;
|
||||
if (_root["server"]["world"]["telnet"].get("enabled", "false").asString() == "true") { TelnetEnabled = true; }
|
||||
|
||||
WorldHTTPMimeFile = _root["server"]["world"]["http"].get("mimefile", "mime.types").asString();
|
||||
WorldHTTPPort = Strings::ToUnsignedInt(_root["server"]["world"]["http"].get("port", "9080").asString().c_str());
|
||||
WorldHTTPPort = Strings::ToUnsignedInt(_root["server"]["world"]["http"].get("port", "9080").asString());
|
||||
WorldHTTPEnabled = false;
|
||||
|
||||
if (_root["server"]["world"]["http"].get("enabled", "false").asString() == "true") {
|
||||
@@ -109,9 +115,9 @@ void EQEmuConfig::parse_config()
|
||||
* UCS
|
||||
*/
|
||||
ChatHost = _root["server"]["chatserver"].get("host", "eqchat.eqemulator.net").asString();
|
||||
ChatPort = Strings::ToUnsignedInt(_root["server"]["chatserver"].get("port", "7778").asString().c_str());
|
||||
ChatPort = Strings::ToUnsignedInt(_root["server"]["chatserver"].get("port", "7778").asString());
|
||||
MailHost = _root["server"]["mailserver"].get("host", "eqmail.eqemulator.net").asString();
|
||||
MailPort = Strings::ToUnsignedInt(_root["server"]["mailserver"].get("port", "7778").asString().c_str());
|
||||
MailPort = Strings::ToUnsignedInt(_root["server"]["mailserver"].get("port", "7778").asString());
|
||||
|
||||
/**
|
||||
* Database
|
||||
@@ -119,7 +125,7 @@ void EQEmuConfig::parse_config()
|
||||
DatabaseUsername = _root["server"]["database"].get("username", "eq").asString();
|
||||
DatabasePassword = _root["server"]["database"].get("password", "eq").asString();
|
||||
DatabaseHost = _root["server"]["database"].get("host", "localhost").asString();
|
||||
DatabasePort = Strings::ToUnsignedInt(_root["server"]["database"].get("port", "3306").asString().c_str());
|
||||
DatabasePort = Strings::ToUnsignedInt(_root["server"]["database"].get("port", "3306").asString());
|
||||
DatabaseDB = _root["server"]["database"].get("db", "eq").asString();
|
||||
|
||||
/**
|
||||
@@ -128,14 +134,14 @@ void EQEmuConfig::parse_config()
|
||||
ContentDbUsername = _root["server"]["content_database"].get("username", "").asString();
|
||||
ContentDbPassword = _root["server"]["content_database"].get("password", "").asString();
|
||||
ContentDbHost = _root["server"]["content_database"].get("host", "").asString();
|
||||
ContentDbPort = Strings::ToUnsignedInt(_root["server"]["content_database"].get("port", 0).asString().c_str());
|
||||
ContentDbPort = Strings::ToUnsignedInt(_root["server"]["content_database"].get("port", 0).asString());
|
||||
ContentDbName = _root["server"]["content_database"].get("db", "").asString();
|
||||
|
||||
/**
|
||||
* QS
|
||||
*/
|
||||
QSDatabaseHost = _root["server"]["qsdatabase"].get("host", "localhost").asString();
|
||||
QSDatabasePort = Strings::ToUnsignedInt(_root["server"]["qsdatabase"].get("port", "3306").asString().c_str());
|
||||
QSDatabasePort = Strings::ToUnsignedInt(_root["server"]["qsdatabase"].get("port", "3306").asString());
|
||||
QSDatabaseUsername = _root["server"]["qsdatabase"].get("username", "eq").asString();
|
||||
QSDatabasePassword = _root["server"]["qsdatabase"].get("password", "eq").asString();
|
||||
QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString();
|
||||
@@ -143,9 +149,9 @@ void EQEmuConfig::parse_config()
|
||||
/**
|
||||
* Zones
|
||||
*/
|
||||
DefaultStatus = Strings::ToUnsignedInt(_root["server"]["zones"].get("defaultstatus", 0).asString().c_str());
|
||||
ZonePortLow = Strings::ToUnsignedInt(_root["server"]["zones"]["ports"].get("low", "7000").asString().c_str());
|
||||
ZonePortHigh = Strings::ToUnsignedInt(_root["server"]["zones"]["ports"].get("high", "7999").asString().c_str());
|
||||
DefaultStatus = Strings::ToUnsignedInt(_root["server"]["zones"].get("defaultstatus", 0).asString());
|
||||
ZonePortLow = Strings::ToUnsignedInt(_root["server"]["zones"]["ports"].get("low", "7000").asString());
|
||||
ZonePortHigh = Strings::ToUnsignedInt(_root["server"]["zones"]["ports"].get("high", "7999").asString());
|
||||
|
||||
/**
|
||||
* Files
|
||||
@@ -175,10 +181,10 @@ void EQEmuConfig::parse_config()
|
||||
/**
|
||||
* Launcher
|
||||
*/
|
||||
RestartWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("restart", "10000").asString().c_str());
|
||||
TerminateWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString().c_str());
|
||||
InitialBootWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("initial", "20000").asString().c_str());
|
||||
ZoneBootInterval = Strings::ToInt(_root["server"]["launcher"]["timers"].get("interval", "2000").asString().c_str());
|
||||
RestartWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("restart", "10000").asString());
|
||||
TerminateWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString());
|
||||
InitialBootWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("initial", "20000").asString());
|
||||
ZoneBootInterval = Strings::ToInt(_root["server"]["launcher"]["timers"].get("interval", "2000").asString());
|
||||
#ifdef WIN32
|
||||
ZoneExe = _root["server"]["launcher"].get("exe", "zone.exe").asString();
|
||||
#else
|
||||
|
||||
@@ -120,6 +120,8 @@ class EQEmuConfig
|
||||
uint16 ZonePortHigh;
|
||||
uint8 DefaultStatus;
|
||||
|
||||
bool auto_database_updates;
|
||||
|
||||
// uint16 DynamicCount;
|
||||
|
||||
// map<string,uint16> StaticZones;
|
||||
@@ -147,12 +149,6 @@ class EQEmuConfig
|
||||
return (_config);
|
||||
}
|
||||
|
||||
// Allow the use to set the conf file to be used.
|
||||
static void SetConfigFile(std::string file)
|
||||
{
|
||||
EQEmuConfig::ConfigFile = file;
|
||||
}
|
||||
|
||||
// Load the config
|
||||
static bool LoadConfig(const std::string& path = "")
|
||||
{
|
||||
|
||||
+94
-24
@@ -104,9 +104,9 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
|
||||
/**
|
||||
* RFC 5424
|
||||
*/
|
||||
log_settings[Logs::Error].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::Warning].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::Info].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::Error].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::Warning].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::Info].log_to_console = static_cast<uint8>(Logs::General);
|
||||
|
||||
/**
|
||||
* Set Category enabled status on defaults
|
||||
@@ -187,9 +187,10 @@ void EQEmuLogSys::ProcessLogWrite(
|
||||
uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
|
||||
{
|
||||
switch (log_category) {
|
||||
case Logs::Crash:
|
||||
case Logs::Error:
|
||||
case Logs::MySQLError:
|
||||
case Logs::QuestErrors:
|
||||
case Logs::Error:
|
||||
return Chat::Red;
|
||||
case Logs::MySQLQuery:
|
||||
case Logs::Debug:
|
||||
@@ -199,8 +200,6 @@ uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
|
||||
case Logs::Commands:
|
||||
case Logs::Mercenaries:
|
||||
return Chat::Magenta;
|
||||
case Logs::Crash:
|
||||
return Chat::Red;
|
||||
default:
|
||||
return Chat::Yellow;
|
||||
}
|
||||
@@ -220,7 +219,7 @@ void EQEmuLogSys::ProcessConsoleMessage(
|
||||
int line
|
||||
)
|
||||
{
|
||||
bool is_error = (
|
||||
bool is_error = (
|
||||
log_category == Logs::LogCategory::Error ||
|
||||
log_category == Logs::LogCategory::MySQLError ||
|
||||
log_category == Logs::LogCategory::Crash ||
|
||||
@@ -262,7 +261,7 @@ void EQEmuLogSys::ProcessConsoleMessage(
|
||||
}
|
||||
|
||||
if (log_category == Logs::LogCategory::MySQLQuery) {
|
||||
auto s = Strings::Split(message, "--");
|
||||
auto s = Strings::Split(message, "--");
|
||||
if (s.size() > 1) {
|
||||
std::string query = Strings::Trim(s[0]);
|
||||
std::string meta = Strings::Trim(s[1]);
|
||||
@@ -298,19 +297,76 @@ void EQEmuLogSys::ProcessConsoleMessage(
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_upper) {
|
||||
(!is_error ? std::cout : std::cerr)
|
||||
<< rang::fgB::gray
|
||||
<< "["
|
||||
<< rang::style::bold
|
||||
<< rang::fgB::yellow
|
||||
<< e
|
||||
<< rang::fgB::gray
|
||||
<< "] "
|
||||
;
|
||||
// color matching in []
|
||||
// ex: [<red>variable] would produce [variable] with red inside brackets
|
||||
std::map<std::string, rang::fgB> colors = {
|
||||
{"<black>", rang::fgB::black},
|
||||
{"<green>", rang::fgB::green},
|
||||
{"<yellow>", rang::fgB::yellow},
|
||||
{"<blue>", rang::fgB::blue},
|
||||
{"<magenta>", rang::fgB::magenta},
|
||||
{"<cyan>", rang::fgB::cyan},
|
||||
{"<gray>", rang::fgB::gray},
|
||||
{"<red>", rang::fgB::red},
|
||||
};
|
||||
|
||||
bool match_color = false;
|
||||
for (auto &c: colors) {
|
||||
if (Strings::Contains(e, c.first)) {
|
||||
e = Strings::Replace(e, c.first, "");
|
||||
(!is_error ? std::cout : std::cerr)
|
||||
<< rang::fgB::gray
|
||||
<< "["
|
||||
<< rang::style::bold
|
||||
<< c.second
|
||||
<< e
|
||||
<< rang::style::reset
|
||||
<< rang::fgB::gray
|
||||
<< "] ";
|
||||
match_color = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
(!is_error ? std::cout : std::cerr) << rang::fgB::gray << "[" << e << "] ";
|
||||
|
||||
// string match to colors
|
||||
std::map<std::string, rang::fgB> matches = {
|
||||
{"missing", rang::fgB::red},
|
||||
{"error", rang::fgB::red},
|
||||
{"ok", rang::fgB::green},
|
||||
};
|
||||
|
||||
for (auto &c: matches) {
|
||||
if (Strings::Contains(e, c.first)) {
|
||||
(!is_error ? std::cout : std::cerr)
|
||||
<< rang::fgB::gray
|
||||
<< "["
|
||||
<< rang::style::bold
|
||||
<< c.second
|
||||
<< e
|
||||
<< rang::style::reset
|
||||
<< rang::fgB::gray
|
||||
<< "] ";
|
||||
match_color = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if we don't match a color in either the string matching or
|
||||
// the color tag matching, we default to yellow inside brackets
|
||||
// if uppercase, does not get colored
|
||||
if (!match_color) {
|
||||
if (!is_upper) {
|
||||
(!is_error ? std::cout : std::cerr)
|
||||
<< rang::fgB::gray
|
||||
<< "["
|
||||
<< rang::style::bold
|
||||
<< rang::fgB::yellow
|
||||
<< e
|
||||
<< rang::style::reset
|
||||
<< rang::fgB::gray
|
||||
<< "] ";
|
||||
}
|
||||
else {
|
||||
(!is_error ? std::cout : std::cerr) << rang::fgB::gray << "[" << e << "] ";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -390,6 +446,8 @@ void EQEmuLogSys::Out(
|
||||
// remove this when we remove all legacy logs
|
||||
bool ignore_log_legacy_format = (
|
||||
log_category == Logs::Netcode ||
|
||||
log_category == Logs::MySQLQuery ||
|
||||
log_category == Logs::MySQLError ||
|
||||
log_category == Logs::PacketServerClient ||
|
||||
log_category == Logs::PacketClientServer ||
|
||||
log_category == Logs::PacketServerToServer
|
||||
@@ -524,6 +582,8 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name)
|
||||
*/
|
||||
void EQEmuLogSys::SilenceConsoleLogging()
|
||||
{
|
||||
std::copy(std::begin(log_settings), std::end(log_settings), std::begin(pre_silence_settings));
|
||||
|
||||
for (int log_index = Logs::AA; log_index != Logs::MaxCategoryID; log_index++) {
|
||||
log_settings[log_index].log_to_console = 0;
|
||||
log_settings[log_index].is_category_enabled = 0;
|
||||
@@ -537,10 +597,7 @@ void EQEmuLogSys::SilenceConsoleLogging()
|
||||
*/
|
||||
void EQEmuLogSys::EnableConsoleLogging()
|
||||
{
|
||||
for (int log_index = Logs::AA; log_index != Logs::MaxCategoryID; log_index++) {
|
||||
log_settings[log_index].log_to_console = Logs::General;
|
||||
log_settings[log_index].is_category_enabled = 1;
|
||||
}
|
||||
std::copy(std::begin(pre_silence_settings), std::end(pre_silence_settings), std::begin(log_settings));
|
||||
}
|
||||
|
||||
EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
|
||||
@@ -742,3 +799,16 @@ EQEmuLogSys *EQEmuLogSys::SetLogPath(const std::string &log_path)
|
||||
return this;
|
||||
}
|
||||
|
||||
void EQEmuLogSys::DisableMySQLErrorLogs()
|
||||
{
|
||||
log_settings[Logs::MySQLError].log_to_file = 0;
|
||||
log_settings[Logs::MySQLError].log_to_console = 0;
|
||||
log_settings[Logs::MySQLError].log_to_gmsay = 0;
|
||||
}
|
||||
|
||||
void EQEmuLogSys::EnableMySQLErrorLogs()
|
||||
{
|
||||
log_settings[Logs::MySQLError].log_to_file = 1;
|
||||
log_settings[Logs::MySQLError].log_to_console = 1;
|
||||
log_settings[Logs::MySQLError].log_to_gmsay = 1;
|
||||
}
|
||||
|
||||
@@ -137,6 +137,8 @@ namespace Logs {
|
||||
Bugs,
|
||||
QuestErrors,
|
||||
PlayerEvents,
|
||||
DataBuckets,
|
||||
Zoning,
|
||||
MaxCategoryID /* Don't Remove this */
|
||||
};
|
||||
|
||||
@@ -233,6 +235,8 @@ namespace Logs {
|
||||
"Bugs",
|
||||
"QuestErrors",
|
||||
"PlayerEvents",
|
||||
"DataBuckets",
|
||||
"Zoning",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -324,6 +328,9 @@ public:
|
||||
*/
|
||||
LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{};
|
||||
|
||||
// temporary bucket to re-load after silencing
|
||||
LogSettings pre_silence_settings[Logs::LogCategory::MaxCategoryID]{};
|
||||
|
||||
struct LogEnabled {
|
||||
bool log_to_file_enabled;
|
||||
bool log_to_console_enabled;
|
||||
@@ -374,6 +381,9 @@ public:
|
||||
[[nodiscard]] const std::string &GetLogPath() const;
|
||||
EQEmuLogSys * SetLogPath(const std::string &log_path);
|
||||
|
||||
void DisableMySQLErrorLogs();
|
||||
void EnableMySQLErrorLogs();
|
||||
|
||||
private:
|
||||
|
||||
// reference to database
|
||||
|
||||
@@ -794,6 +794,26 @@
|
||||
OutF(LogSys, Logs::Detail, Logs::PlayerEvents, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogDataBuckets(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::DataBuckets))\
|
||||
OutF(LogSys, Logs::General, Logs::DataBuckets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogDataBucketsDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::DataBuckets))\
|
||||
OutF(LogSys, Logs::Detail, Logs::DataBuckets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogZoning(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::Zoning))\
|
||||
OutF(LogSys, Logs::General, Logs::Zoning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogZoningDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::Zoning))\
|
||||
OutF(LogSys, Logs::Detail, Logs::Zoning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define Log(debug_level, log_category, message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(debug_level, log_category))\
|
||||
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
|
||||
+1
-5
@@ -58,10 +58,6 @@ EQTime::EQTime()
|
||||
SetCurrentEQTimeOfDay(start, time(0));
|
||||
}
|
||||
|
||||
EQTime::~EQTime()
|
||||
{
|
||||
}
|
||||
|
||||
//getEQTimeOfDay - Reads timeConvert and writes the result to eqTimeOfDay
|
||||
//This function was written by the ShowEQ Project.
|
||||
//Input: Current Time (as a time_t), a pointer to the TimeOfDay_Struct that will be written to.
|
||||
@@ -203,4 +199,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;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ public:
|
||||
//Constructor/destructor
|
||||
EQTime(TimeOfDay_Struct start_eq, time_t start_real);
|
||||
EQTime();
|
||||
~EQTime();
|
||||
~EQTime() = default;
|
||||
|
||||
//Get functions
|
||||
int GetCurrentEQTimeOfDay( TimeOfDay_Struct *eqTimeOfDay ) { return(GetCurrentEQTimeOfDay(time(nullptr), eqTimeOfDay)); }
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace EQ
|
||||
_running = true;
|
||||
|
||||
for (size_t i = 0; i < threads; ++i) {
|
||||
_threads.push_back(std::thread(std::bind(&TaskScheduler::ProcessWork, this)));
|
||||
_threads.emplace_back(std::thread(std::bind(&TaskScheduler::ProcessWork, this)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -333,7 +333,10 @@ std::string PlayerEventLogs::GetDiscordPayloadFromEvent(const PlayerEvent::Playe
|
||||
payload = PlayerEventDiscordFormatter::FormatDroppedItemEvent(e, n);
|
||||
break;
|
||||
}
|
||||
case PlayerEvent::FISH_FAILURE: {
|
||||
case PlayerEvent::FISH_FAILURE:
|
||||
case PlayerEvent::FORAGE_FAILURE:
|
||||
case PlayerEvent::WENT_ONLINE:
|
||||
case PlayerEvent::WENT_OFFLINE: {
|
||||
payload = PlayerEventDiscordFormatter::FormatWithNodata(e);
|
||||
break;
|
||||
}
|
||||
@@ -348,10 +351,6 @@ std::string PlayerEventLogs::GetDiscordPayloadFromEvent(const PlayerEvent::Playe
|
||||
payload = PlayerEventDiscordFormatter::FormatFishSuccessEvent(e, n);
|
||||
break;
|
||||
}
|
||||
case PlayerEvent::FORAGE_FAILURE: {
|
||||
payload = PlayerEventDiscordFormatter::FormatWithNodata(e);
|
||||
break;
|
||||
}
|
||||
case PlayerEvent::FORAGE_SUCCESS: {
|
||||
PlayerEvent::ForageSuccessEvent n{};
|
||||
std::stringstream ss;
|
||||
@@ -550,11 +549,6 @@ std::string PlayerEventLogs::GetDiscordPayloadFromEvent(const PlayerEvent::Playe
|
||||
payload = PlayerEventDiscordFormatter::FormatResurrectAcceptEvent(e, n);
|
||||
break;
|
||||
}
|
||||
case PlayerEvent::WENT_ONLINE:
|
||||
case PlayerEvent::WENT_OFFLINE: {
|
||||
payload = PlayerEventDiscordFormatter::FormatWithNodata(e);
|
||||
break;
|
||||
}
|
||||
case PlayerEvent::MERCHANT_PURCHASE: {
|
||||
PlayerEvent::MerchantPurchaseEvent n{};
|
||||
std::stringstream ss;
|
||||
|
||||
@@ -384,7 +384,7 @@ namespace PlayerEvent {
|
||||
};
|
||||
|
||||
struct AAPurchasedEvent {
|
||||
int32 aa_id;
|
||||
uint32 aa_id;
|
||||
int32 aa_cost;
|
||||
int32 aa_previous_id;
|
||||
int32 aa_next_id;
|
||||
|
||||
+16
-32
@@ -218,14 +218,14 @@ enum { //some random constants
|
||||
#define HARD_LEVEL_CAP 127
|
||||
|
||||
//the square of the maximum range at whihc you could possibly use NPC services (shop, tribute, etc)
|
||||
#define USE_NPC_RANGE2 200*200 //arbitrary right now
|
||||
#define USE_NPC_RANGE2 40000 //arbitrary right now
|
||||
|
||||
// Squared range for rampage 75.0 * 75.0 for now
|
||||
#define NPC_RAMPAGE_RANGE2 5625.0f
|
||||
|
||||
//the formula for experience for killing a mob.
|
||||
//level is the only valid variable to use
|
||||
#define EXP_FORMULA level*level*75*35/10
|
||||
#define EXP_FORMULA (level * level * 75 * 35 / 10)
|
||||
|
||||
#define HIGHEST_AA_VALUE 35
|
||||
|
||||
@@ -240,36 +240,20 @@ enum { //some random constants
|
||||
|
||||
//Some hard coded statuses from commands and other places:
|
||||
enum {
|
||||
minStatusToBeGM = 40,
|
||||
minStatusToUseGMCommands = 80,
|
||||
minStatusToKick = 150,
|
||||
minStatusToAvoidFalling = 100,
|
||||
minStatusToHaveInvalidSpells = 80,
|
||||
minStatusToHaveInvalidSkills = 80,
|
||||
minStatusToIgnoreZoneFlags = 80,
|
||||
minStatusToBeGM = 40,
|
||||
minStatusToUseGMCommands = 80,
|
||||
minStatusToKick = 150,
|
||||
minStatusToAvoidFalling = 100,
|
||||
minStatusToIgnoreZoneFlags = 80,
|
||||
minStatusToSeeOthersZoneFlags = 80,
|
||||
minStatusToEditOtherGuilds = 80,
|
||||
commandMovecharSelfOnly = 80, //below this == only self move allowed
|
||||
commandMovecharToSpecials = 200, //ability to send people to cshom/load zones
|
||||
commandZoneToSpecials = 80, //zone to cshome, out of load zones
|
||||
commandToggleAI = 250, //can turn NPC AI on and off
|
||||
commandCastSpecials = 100, //can cast special spells
|
||||
commandInstacast = 100, //insta-cast all #casted spells
|
||||
commandLevelAboveCap = 100, //can #level players above level cap
|
||||
commandLevelNPCAboveCap = 100, //can #level NPCs above level cap
|
||||
commandSetSkillsOther = 100, //ability to setskills on others
|
||||
commandRaceOthers = 100, //ability to #race on others
|
||||
commandGenderOthers = 100, //ability to #gender on others
|
||||
commandTextureOthers = 100, //ability to #texture on others
|
||||
commandDoAnimOthers = 100, //can #doanim on others
|
||||
commandLockZones = 101, //can lock or unlock zones
|
||||
commandEditPlayerCorpses = 150, //can Edit Player Corpses
|
||||
commandChangeFlags = 200, //ability to set/refresh flags
|
||||
commandBanPlayers = 100, //can set bans on players
|
||||
commandChangeDatarate = 201, //edit client's data rate
|
||||
commandZoneToCoords = 0, //can #zone with coords
|
||||
commandInterrogateInv = 100, //below this == only log on error state and self-only target dump
|
||||
commandInvSnapshot = 150 //ability to clear/restore snapshots
|
||||
minStatusToEditOtherGuilds = 80,
|
||||
commandMovecharSelfOnly = 80, //below this == only self move allowed
|
||||
commandMovecharToSpecials = 200, //ability to send people to cshom/load zones
|
||||
commandCastSpecials = 100, //can cast special spells
|
||||
commandDoAnimOthers = 100, //can #doanim on others
|
||||
commandEditPlayerCorpses = 150, //can Edit Player Corpses
|
||||
commandInterrogateInv = 100, //below this == only log on error state and self-only target dump
|
||||
commandInvSnapshot = 150 //ability to clear/restore snapshots
|
||||
};
|
||||
|
||||
|
||||
@@ -295,7 +279,7 @@ Developer configuration
|
||||
|
||||
#define COMMON_PROFILE
|
||||
|
||||
#define PROFILE_DUMP_TIME 3*60
|
||||
#define PROFILE_DUMP_TIME 180
|
||||
#endif //EQPROFILE
|
||||
|
||||
|
||||
|
||||
+32
-2
@@ -37,6 +37,7 @@
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@@ -54,8 +55,14 @@ bool File::Exists(const std::string &name)
|
||||
*/
|
||||
void File::Makedir(const std::string &directory_name)
|
||||
{
|
||||
fs::create_directory(directory_name);
|
||||
fs::permissions(directory_name, fs::perms::owner_all);
|
||||
try {
|
||||
fs::create_directory(directory_name);
|
||||
fs::permissions(directory_name, fs::perms::owner_all);
|
||||
}
|
||||
catch (const fs::filesystem_error &ex) {
|
||||
std::cout << "Failed to create directory: " << directory_name << std::endl;
|
||||
std::cout << ex.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::string File::FindEqemuConfigPath()
|
||||
@@ -80,3 +87,26 @@ std::string File::GetCwd()
|
||||
{
|
||||
return fs::current_path().string();
|
||||
}
|
||||
|
||||
FileContentsResult File::GetContents(const std::string &file_name)
|
||||
{
|
||||
std::string error;
|
||||
std::ifstream f;
|
||||
f.open(file_name);
|
||||
std::string line;
|
||||
std::string lines;
|
||||
if (f.is_open()) {
|
||||
while (f) {
|
||||
std::getline(f, line);
|
||||
lines += line + "\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
error = fmt::format("Couldn't open file [{}]", file_name);
|
||||
}
|
||||
|
||||
return FileContentsResult{
|
||||
.contents = lines,
|
||||
.error = error,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -25,10 +25,16 @@
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
struct FileContentsResult {
|
||||
std::string contents;
|
||||
std::string error;
|
||||
};
|
||||
|
||||
class File {
|
||||
public:
|
||||
static bool Exists(const std::string &name);
|
||||
static void Makedir(const std::string& directory_name);
|
||||
static FileContentsResult GetContents(const std::string &file_name);
|
||||
static std::string FindEqemuConfigPath();
|
||||
static std::string GetCwd();
|
||||
};
|
||||
|
||||
@@ -6690,7 +6690,7 @@ static WSInit wsinit_;
|
||||
if (params.empty()) { return Get(path, headers); }
|
||||
|
||||
std::string path_with_query = append_query_params(path, params);
|
||||
return Get(path_with_query.c_str(), headers, progress);
|
||||
return Get(path_with_query, headers, progress);
|
||||
}
|
||||
|
||||
inline Result ClientImpl::Get(const std::string &path, const Params ¶ms,
|
||||
@@ -6710,7 +6710,7 @@ static WSInit wsinit_;
|
||||
}
|
||||
|
||||
std::string path_with_query = append_query_params(path, params);
|
||||
return Get(path_with_query.c_str(), headers, response_handler,
|
||||
return Get(path_with_query, headers, response_handler,
|
||||
content_receiver, progress);
|
||||
}
|
||||
|
||||
@@ -6807,7 +6807,7 @@ static WSInit wsinit_;
|
||||
std::string content_type;
|
||||
const auto &body = detail::serialize_multipart_formdata(
|
||||
items, detail::make_multipart_data_boundary(), content_type);
|
||||
return Post(path, headers, body, content_type.c_str());
|
||||
return Post(path, headers, body, content_type);
|
||||
}
|
||||
|
||||
inline Result ClientImpl::Post(const std::string &path, const Headers &headers,
|
||||
@@ -6820,7 +6820,7 @@ static WSInit wsinit_;
|
||||
std::string content_type;
|
||||
const auto &body =
|
||||
detail::serialize_multipart_formdata(items, boundary, content_type);
|
||||
return Post(path, headers, body, content_type.c_str());
|
||||
return Post(path, headers, body, content_type);
|
||||
}
|
||||
|
||||
inline Result ClientImpl::Put(const std::string &path) {
|
||||
|
||||
@@ -353,7 +353,7 @@ bool EQ::InventoryProfile::SwapItem(
|
||||
fail_state = swapRaceClass;
|
||||
return false;
|
||||
}
|
||||
if (deity_id && source_item->Deity && !(deity::ConvertDeityTypeToDeityTypeBit((deity::DeityType)deity_id) & source_item->Deity)) {
|
||||
if (deity_id && source_item->Deity && !(deity::GetDeityBitmask((deity::DeityType)deity_id) & source_item->Deity)) {
|
||||
fail_state = swapDeity;
|
||||
return false;
|
||||
}
|
||||
@@ -379,7 +379,7 @@ bool EQ::InventoryProfile::SwapItem(
|
||||
fail_state = swapRaceClass;
|
||||
return false;
|
||||
}
|
||||
if (deity_id && destination_item->Deity && !(deity::ConvertDeityTypeToDeityTypeBit((deity::DeityType)deity_id) & destination_item->Deity)) {
|
||||
if (deity_id && destination_item->Deity && !(deity::GetDeityBitmask((deity::DeityType)deity_id) & destination_item->Deity)) {
|
||||
fail_state = swapDeity;
|
||||
return false;
|
||||
}
|
||||
@@ -412,11 +412,12 @@ bool EQ::InventoryProfile::DeleteItem(int16 slot_id, int16 quantity) {
|
||||
// If there are no charges left on the item,
|
||||
if (item_to_delete->GetCharges() <= 0) {
|
||||
// If the item is stackable (e.g arrows), or
|
||||
// the item is not stackable, and is not a charged item, or is expendable, delete it
|
||||
if (item_to_delete->IsStackable() ||
|
||||
(!item_to_delete->IsStackable() &&
|
||||
((item_to_delete->GetItem()->MaxCharges == 0) || item_to_delete->IsExpendable()))
|
||||
) {
|
||||
// the item is not a charged item, or is expendable, delete it
|
||||
if (
|
||||
item_to_delete->IsStackable() ||
|
||||
item_to_delete->GetItem()->MaxCharges == 0 ||
|
||||
item_to_delete->IsExpendable()
|
||||
) {
|
||||
// Item can now be destroyed
|
||||
InventoryProfile::MarkDirty(item_to_delete);
|
||||
return true;
|
||||
@@ -1443,7 +1444,7 @@ int16 EQ::InventoryProfile::_PutItem(int16 slot_id, ItemInstance* inst)
|
||||
}
|
||||
|
||||
if (result == INVALID_INDEX) {
|
||||
LogError("InventoryProfile::_PutItem: Invalid slot_id specified ({}) with parent slot id ({})", slot_id, parentSlot);
|
||||
LogError("Invalid slot_id specified ({}) with parent slot id ({})", slot_id, parentSlot);
|
||||
InventoryProfile::MarkDirty(inst); // Slot not found, clean up
|
||||
}
|
||||
|
||||
|
||||
@@ -230,6 +230,10 @@ bool EQ::ItemData::IsTypeShield() const
|
||||
return (ItemType == item::ItemTypeShield);
|
||||
}
|
||||
|
||||
bool EQ::ItemData::IsQuestItem() const {
|
||||
return QuestItemFlag;
|
||||
}
|
||||
|
||||
bool EQ::ItemData::CheckLoreConflict(const ItemData* l_item, const ItemData* r_item)
|
||||
{
|
||||
if (!l_item || !r_item)
|
||||
|
||||
+166
-160
@@ -131,7 +131,7 @@ namespace EQ
|
||||
Mounts?
|
||||
Ornamentations?
|
||||
GuildBanners?
|
||||
Collectible?
|
||||
Collectible?
|
||||
Placeable?
|
||||
(others?)
|
||||
*/
|
||||
@@ -355,181 +355,186 @@ namespace EQ
|
||||
|
||||
struct ItemData {
|
||||
// Non packet based fields
|
||||
uint8 MinStatus;
|
||||
uint8 MinStatus {};
|
||||
|
||||
// Packet based fields
|
||||
uint8 ItemClass; // Item Type: 0=common, 1=container, 2=book
|
||||
char Name[64]; // Name
|
||||
char Lore[80]; // Lore Name: *=lore, &=summoned, #=artifact, ~=pending lore
|
||||
char IDFile[30]; // Visible model
|
||||
uint32 ID; // Unique ID (also PK for DB)
|
||||
int32 Weight; // Item weight * 10
|
||||
uint8 NoRent; // No Rent: 0=norent, 255=not norent
|
||||
uint8 NoDrop; // No Drop: 0=nodrop, 255=not nodrop
|
||||
uint8 Size; // Size: 0=tiny, 1=small, 2=medium, 3=large, 4=giant
|
||||
uint32 Slots; // Bitfield for which slots this item can be used in
|
||||
uint32 Price; // Item cost (?)
|
||||
uint32 Icon; // Icon Number
|
||||
int32 LoreGroup; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295)
|
||||
bool LoreFlag; // This will be true if LoreGroup is non-zero
|
||||
bool PendingLoreFlag;
|
||||
bool ArtifactFlag;
|
||||
bool SummonedFlag;
|
||||
uint8 FVNoDrop; // Firiona Vie nodrop flag
|
||||
uint32 Favor; // Individual favor
|
||||
uint32 GuildFavor; // Guild favor
|
||||
uint32 PointType;
|
||||
uint8 ItemClass {}; // Item Type: 0=common, 1=container, 2=book
|
||||
char Name[64] {}; // Name
|
||||
char Lore[80] {}; // Lore Name: *=lore, &=summoned, #=artifact, ~=pending lore
|
||||
char IDFile[30] {}; // Visible model
|
||||
uint32 ID {}; // Unique ID (also PK for DB)
|
||||
int32 Weight {}; // Item weight * 10
|
||||
uint8 NoRent{} ; // No Rent: 0=norent, 255=not norent
|
||||
uint8 NoDrop {}; // No Drop: 0=nodrop, 255=not nodrop
|
||||
uint8 Size {}; // Size: 0=tiny, 1=small, 2=medium, 3=large, 4=giant
|
||||
uint32 Slots {}; // Bitfield for which slots this item can be used in
|
||||
uint32 Price {}; // Item cost (?)
|
||||
uint32 Icon {}; // Icon Number
|
||||
int32 LoreGroup {}; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295)
|
||||
bool LoreFlag {}; // This will be true if LoreGroup is non-zero
|
||||
bool PendingLoreFlag {};
|
||||
bool ArtifactFlag {};
|
||||
bool SummonedFlag {};
|
||||
uint8 FVNoDrop {}; // Firiona Vie nodrop flag
|
||||
uint32 Favor {}; // Individual favor
|
||||
uint32 GuildFavor {}; // Guild favor
|
||||
uint32 PointType {};
|
||||
|
||||
//uint32 Unk117;
|
||||
//uint32 Unk118;
|
||||
//uint32 Unk121;
|
||||
//uint32 Unk124;
|
||||
|
||||
uint8 BagType; // 0:Small Bag, 1:Large Bag, 2:Quiver, 3:Belt Pouch ... there are 50 types
|
||||
uint8 BagSlots; // Number of slots: can only be 2, 4, 6, 8, or 10
|
||||
uint8 BagSize; // 0:TINY, 1:SMALL, 2:MEDIUM, 3:LARGE, 4:GIANT
|
||||
uint8 BagWR; // 0->100
|
||||
uint8 BagType {}; // 0:Small Bag, 1:Large Bag, 2:Quiver, 3:Belt Pouch ... there are 50 types
|
||||
uint8 BagSlots {}; // Number of slots: can only be 2, 4, 6, 8, or 10
|
||||
uint8 BagSize {}; // 0:TINY, 1:SMALL, 2:MEDIUM, 3:LARGE, 4:GIANT
|
||||
uint8 BagWR {}; // 0->100
|
||||
|
||||
bool BenefitFlag;
|
||||
bool Tradeskills; // Is this a tradeskill item?
|
||||
int8 CR; // Save vs Cold
|
||||
int8 DR; // Save vs Disease
|
||||
int8 PR; // Save vs Poison
|
||||
int8 MR; // Save vs Magic
|
||||
int8 FR; // Save vs Fire
|
||||
int8 AStr; // Strength
|
||||
int8 ASta; // Stamina
|
||||
int8 AAgi; // Agility
|
||||
int8 ADex; // Dexterity
|
||||
int8 ACha; // Charisma
|
||||
int8 AInt; // Intelligence
|
||||
int8 AWis; // Wisdom
|
||||
int32 HP; // HP
|
||||
int32 Mana; // Mana
|
||||
int32 AC; // AC
|
||||
uint32 Deity; // Bitmask of Deities that can equip this item
|
||||
bool BenefitFlag {};
|
||||
bool Tradeskills {}; // Is this a tradeskill item?
|
||||
int8 CR {}; // Save vs Cold
|
||||
int8 DR {}; // Save vs Disease
|
||||
int8 PR {}; // Save vs Poison
|
||||
int8 MR {}; // Save vs Magic
|
||||
int8 FR {}; // Save vs Fire
|
||||
int8 AStr {}; // Strength
|
||||
int8 ASta {}; // Stamina
|
||||
int8 AAgi {}; // Agility
|
||||
int8 ADex {}; // Dexterity
|
||||
int8 ACha {}; // Charisma
|
||||
int8 AInt {}; // Intelligence
|
||||
int8 AWis {}; // Wisdom
|
||||
int32 HP {}; // HP
|
||||
int32 Mana {}; // Mana
|
||||
int32 AC {}; // AC
|
||||
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
|
||||
int32 BaneDmgAmt; // Bane Damage Body Amount
|
||||
uint32 BaneDmgBody; // Bane Damage Body
|
||||
bool Magic; // True=Magic Item, False=not
|
||||
int32 CastTime_;
|
||||
uint8 ReqLevel; // Required Level to use item
|
||||
uint32 BardType; // Bard Skill Type
|
||||
int32 BardValue; // Bard Skill Amount
|
||||
int8 Light; // Light
|
||||
uint8 Delay; // Delay * 10
|
||||
uint8 RecLevel; // Recommended level to use item
|
||||
uint8 RecSkill; // Recommended skill to use item (refers to primary skill of item)
|
||||
uint8 ElemDmgType; // Elemental Damage Type (1=magic, 2=fire)
|
||||
uint8 ElemDmgAmt; // Elemental Damage
|
||||
uint8 Range; // Range of item
|
||||
uint32 Damage; // Delay between item usage (in 0.1 sec increments)
|
||||
uint32 Color; // RR GG BB 00 <-- as it appears in pc
|
||||
uint32 Classes; // Bitfield of classes that can equip item (1 << class#)
|
||||
uint32 Races; // Bitfield of races that can equip item (1 << race#)
|
||||
//uint32 Unk054;
|
||||
int16 MaxCharges; // Maximum charges items can hold: -1 if not a chargeable item
|
||||
uint8 ItemType; // Item Type/Skill (itemClass* from above)
|
||||
int32 SubType; // Some items have sub types that can be used for other things (unbreakable fishing poles, SE_FFItemClass)
|
||||
uint8 Material; // Item material type
|
||||
uint32 HerosForgeModel;// Hero's Forge Armor Model Type (2-13?)
|
||||
float SellRate; // Sell rate
|
||||
//uint32 Unk059;
|
||||
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
|
||||
int32 BaneDmgAmt {}; // Bane Damage Body Amount
|
||||
uint32 BaneDmgBody {}; // Bane Damage Body
|
||||
bool Magic {}; // True=Magic Item, False=not
|
||||
int32 CastTime_ {};
|
||||
uint8 ReqLevel {}; // Required Level to use item
|
||||
uint32 BardType {}; // Bard Skill Type
|
||||
int32 BardValue {}; // Bard Skill Amount
|
||||
int8 Light {}; // Light
|
||||
uint8 Delay {}; // Delay * 10
|
||||
uint8 RecLevel {}; // Recommended level to use item
|
||||
uint8 RecSkill {}; // Recommended skill to use item (refers to primary skill of item)
|
||||
uint8 ElemDmgType {}; // Elemental Damage Type (1=magic, 2=fire)
|
||||
uint8 ElemDmgAmt {}; // Elemental Damage
|
||||
uint8 Range {}; // Range of item
|
||||
uint32 Damage {}; // Delay between item usage (in 0.1 sec increments)
|
||||
uint32 Color {}; // RR GG BB 00 <-- as it appears in pc
|
||||
uint32 Classes {}; // Bitfield of classes that can equip item (1 << class#)
|
||||
uint32 Races {}; // Bitfield of races that can equip item (1 << race#)
|
||||
//uint32 Unk054 {};
|
||||
int16 MaxCharges {}; // Maximum charges items can hold: -1 if not a chargeable item
|
||||
uint8 ItemType {}; // Item Type/Skill (itemClass* from above)
|
||||
int32 SubType {}; // Some items have sub types that can be used for other things (unbreakable fishing poles, SE_FFItemClass)
|
||||
uint8 Material {}; // Item material type
|
||||
uint32 HerosForgeModel {};// Hero's Forge Armor Model Type (2-13?)
|
||||
float SellRate {}; // Sell rate
|
||||
//uint32 Unk059 {};
|
||||
union {
|
||||
uint32 Fulfilment; // Food fulfilment (How long it lasts)
|
||||
uint32 CastTime; // Cast Time for clicky effects, in milliseconds
|
||||
};
|
||||
uint32 EliteMaterial;
|
||||
int32 ProcRate;
|
||||
int8 CombatEffects; // PoP: Combat Effects +
|
||||
int8 Shielding; // PoP: Shielding %
|
||||
int8 StunResist; // PoP: Stun Resist %
|
||||
int8 StrikeThrough; // PoP: Strike Through %
|
||||
uint32 ExtraDmgSkill;
|
||||
uint32 ExtraDmgAmt;
|
||||
int8 SpellShield; // PoP: Spell Shield %
|
||||
int8 Avoidance; // PoP: Avoidance +
|
||||
int8 Accuracy; // PoP: Accuracy +
|
||||
uint32 CharmFileID;
|
||||
int32 FactionMod1; // Faction Mod 1
|
||||
int32 FactionMod2; // Faction Mod 2
|
||||
int32 FactionMod3; // Faction Mod 3
|
||||
int32 FactionMod4; // Faction Mod 4
|
||||
int32 FactionAmt1; // Faction Amt 1
|
||||
int32 FactionAmt2; // Faction Amt 2
|
||||
int32 FactionAmt3; // Faction Amt 3
|
||||
int32 FactionAmt4; // Faction Amt 4
|
||||
char CharmFile[32]; // ?
|
||||
uint32 AugType;
|
||||
uint8 AugSlotType[invaug::SOCKET_COUNT]; // RoF: Augment Slot 1-6 Type
|
||||
uint8 AugSlotVisible[invaug::SOCKET_COUNT]; // RoF: Augment Slot 1-6 Visible
|
||||
uint8 AugSlotUnk2[invaug::SOCKET_COUNT]; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related
|
||||
uint32 LDoNTheme;
|
||||
uint32 LDoNPrice;
|
||||
uint32 LDoNSold;
|
||||
uint32 BaneDmgRaceAmt;
|
||||
uint32 AugRestrict;
|
||||
int32 Endur;
|
||||
int32 DotShielding;
|
||||
int32 Attack;
|
||||
int32 Regen;
|
||||
int32 ManaRegen;
|
||||
int32 EnduranceRegen;
|
||||
int32 Haste;
|
||||
int32 DamageShield;
|
||||
uint32 RecastDelay;
|
||||
int RecastType;
|
||||
uint32 AugDistiller;
|
||||
bool Attuneable;
|
||||
bool NoPet;
|
||||
bool PotionBelt;
|
||||
bool Stackable;
|
||||
bool NoTransfer;
|
||||
bool QuestItemFlag;
|
||||
int16 StackSize;
|
||||
uint8 PotionBeltSlots;
|
||||
item::ItemEffect_Struct Click, Proc, Worn, Focus, Scroll, Bard;
|
||||
uint32 EliteMaterial {};
|
||||
int32 ProcRate {};
|
||||
int8 CombatEffects {}; // PoP: Combat Effects +
|
||||
int8 Shielding {}; // PoP: Shielding %
|
||||
int8 StunResist {}; // PoP: Stun Resist %
|
||||
int8 StrikeThrough {}; // PoP: Strike Through %
|
||||
int32 ExtraDmgSkill {};
|
||||
int32 ExtraDmgAmt {};
|
||||
int8 SpellShield {}; // PoP: Spell Shield %
|
||||
int8 Avoidance {}; // PoP: Avoidance +
|
||||
int8 Accuracy {}; // PoP: Accuracy +
|
||||
uint32 CharmFileID {};
|
||||
int32 FactionMod1 {}; // Faction Mod 1
|
||||
int32 FactionMod2 {}; // Faction Mod 2
|
||||
int32 FactionMod3 {}; // Faction Mod 3
|
||||
int32 FactionMod4 {}; // Faction Mod 4
|
||||
int32 FactionAmt1 {}; // Faction Amt 1
|
||||
int32 FactionAmt2 {}; // Faction Amt 2
|
||||
int32 FactionAmt3 {}; // Faction Amt 3
|
||||
int32 FactionAmt4 {}; // Faction Amt 4
|
||||
char CharmFile[32] {}; // ?
|
||||
uint32 AugType {};
|
||||
uint8 AugSlotType[invaug::SOCKET_COUNT] {}; // RoF: Augment Slot 1-6 Type
|
||||
uint8 AugSlotVisible[invaug::SOCKET_COUNT] {}; // RoF: Augment Slot 1-6 Visible
|
||||
uint8 AugSlotUnk2[invaug::SOCKET_COUNT] {}; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related
|
||||
uint32 LDoNTheme {};
|
||||
uint32 LDoNPrice {};
|
||||
uint32 LDoNSold {};
|
||||
uint32 BaneDmgRaceAmt {};
|
||||
uint32 AugRestrict {};
|
||||
int32 Endur {};
|
||||
int32 DotShielding {};
|
||||
int32 Attack {};
|
||||
int32 Regen {};
|
||||
int32 ManaRegen {};
|
||||
int32 EnduranceRegen {};
|
||||
int32 Haste {};
|
||||
int32 DamageShield {};
|
||||
uint32 RecastDelay {};
|
||||
int RecastType {};
|
||||
uint32 AugDistiller {};
|
||||
bool Attuneable {};
|
||||
bool NoPet {};
|
||||
bool PotionBelt {};
|
||||
bool Stackable {};
|
||||
bool NoTransfer {};
|
||||
bool QuestItemFlag {};
|
||||
int16 StackSize {};
|
||||
uint8 PotionBeltSlots {};
|
||||
item::ItemEffect_Struct Click {};
|
||||
item::ItemEffect_Struct Proc {};
|
||||
item::ItemEffect_Struct Worn {};
|
||||
item::ItemEffect_Struct Focus {};
|
||||
item::ItemEffect_Struct Scroll {};
|
||||
item::ItemEffect_Struct Bard {};
|
||||
|
||||
uint8 Book; // 0=Not book, 1=Book
|
||||
uint32 BookType;
|
||||
char Filename[33]; // Filename for book data
|
||||
uint8 Book {}; // 0=Not book, 1=Book
|
||||
uint32 BookType {};
|
||||
char Filename[33] {}; // Filename for book data
|
||||
// Begin SoF Fields
|
||||
int32 SVCorruption;
|
||||
uint32 Purity;
|
||||
uint8 EvolvingItem;
|
||||
uint32 EvolvingID;
|
||||
uint8 EvolvingLevel;
|
||||
uint8 EvolvingMax;
|
||||
uint32 BackstabDmg;
|
||||
uint32 DSMitigation;
|
||||
int32 HeroicStr;
|
||||
int32 HeroicInt;
|
||||
int32 HeroicWis;
|
||||
int32 HeroicAgi;
|
||||
int32 HeroicDex;
|
||||
int32 HeroicSta;
|
||||
int32 HeroicCha;
|
||||
int32 HeroicMR;
|
||||
int32 HeroicFR;
|
||||
int32 HeroicCR;
|
||||
int32 HeroicDR;
|
||||
int32 HeroicPR;
|
||||
int32 HeroicSVCorrup;
|
||||
int32 HealAmt;
|
||||
int32 SpellDmg;
|
||||
uint32 LDoNSellBackRate;
|
||||
uint32 ScriptFileID;
|
||||
uint16 ExpendableArrow;
|
||||
uint32 Clairvoyance;
|
||||
char ClickName[65];
|
||||
char ProcName[65];
|
||||
char WornName[65];
|
||||
char FocusName[65];
|
||||
char ScrollName[65];
|
||||
int32 SVCorruption {};
|
||||
uint32 Purity {};
|
||||
uint8 EvolvingItem {};
|
||||
uint32 EvolvingID {};
|
||||
uint8 EvolvingLevel {};
|
||||
uint8 EvolvingMax {};
|
||||
uint32 BackstabDmg {};
|
||||
uint32 DSMitigation {};
|
||||
int32 HeroicStr {};
|
||||
int32 HeroicInt {};
|
||||
int32 HeroicWis {};
|
||||
int32 HeroicAgi {};
|
||||
int32 HeroicDex {};
|
||||
int32 HeroicSta {};
|
||||
int32 HeroicCha {};
|
||||
int32 HeroicMR {};
|
||||
int32 HeroicFR {};
|
||||
int32 HeroicCR {};
|
||||
int32 HeroicDR {};
|
||||
int32 HeroicPR {};
|
||||
int32 HeroicSVCorrup {};
|
||||
int32 HealAmt {};
|
||||
int32 SpellDmg {};
|
||||
uint32 LDoNSellBackRate {};
|
||||
uint32 ScriptFileID {};
|
||||
uint16 ExpendableArrow {};
|
||||
uint32 Clairvoyance {};
|
||||
char ClickName[65] {};
|
||||
char ProcName[65] {};
|
||||
char WornName[65] {};
|
||||
char FocusName[65] {};
|
||||
char ScrollName[65] {};
|
||||
//BardName
|
||||
|
||||
bool IsEquipable(uint16 Race, uint16 Class) const;
|
||||
@@ -541,6 +546,7 @@ namespace EQ
|
||||
bool IsType1HWeapon() const;
|
||||
bool IsType2HWeapon() const;
|
||||
bool IsTypeShield() const;
|
||||
bool IsQuestItem() const;
|
||||
|
||||
static bool CheckLoreConflict(const ItemData* l_item, const ItemData* r_item);
|
||||
bool CheckLoreConflict(const ItemData* item) const { return CheckLoreConflict(this, item); }
|
||||
|
||||
+164
-167
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#include "inventory_profile.h"
|
||||
#include "../common/data_verification.h"
|
||||
//#include "classes.h"
|
||||
//#include "global_define.h"
|
||||
//#include "item_instance.h"
|
||||
@@ -57,108 +58,62 @@ static inline int32 GetNextItemInstSerialNumber() {
|
||||
// class EQ::ItemInstance
|
||||
//
|
||||
EQ::ItemInstance::ItemInstance(const ItemData* item, int16 charges) {
|
||||
m_use_type = ItemInstNormal;
|
||||
if(item) {
|
||||
m_item = new ItemData(*item);
|
||||
} else {
|
||||
m_item = nullptr;
|
||||
}
|
||||
m_charges = charges;
|
||||
m_price = 0;
|
||||
m_attuned = false;
|
||||
m_merchantslot = 0;
|
||||
if (m_item && m_item->IsClassCommon())
|
||||
m_color = m_item->Color;
|
||||
else
|
||||
m_color = 0;
|
||||
m_merchantcount = 1;
|
||||
m_SerialNumber = GetNextItemInstSerialNumber();
|
||||
|
||||
m_exp = 0;
|
||||
m_evolveLvl = 0;
|
||||
m_activated = false;
|
||||
m_scaledItem = nullptr;
|
||||
m_evolveInfo = nullptr;
|
||||
m_scaling = false;
|
||||
m_ornamenticon = 0;
|
||||
m_ornamentidfile = 0;
|
||||
m_ornament_hero_model = 0;
|
||||
m_recast_timestamp = 0;
|
||||
m_new_id_file = 0;
|
||||
if (item) {
|
||||
m_item = new ItemData(*item);
|
||||
}
|
||||
|
||||
m_charges = charges;
|
||||
|
||||
if (m_item && m_item->IsClassCommon()) {
|
||||
m_color = m_item->Color;
|
||||
}
|
||||
|
||||
m_SerialNumber = GetNextItemInstSerialNumber();
|
||||
}
|
||||
|
||||
EQ::ItemInstance::ItemInstance(SharedDatabase *db, uint32 item_id, int16 charges) {
|
||||
m_use_type = ItemInstNormal;
|
||||
m_item = db->GetItem(item_id);
|
||||
if(m_item) {
|
||||
|
||||
m_item = db->GetItem(item_id);
|
||||
|
||||
if (m_item) {
|
||||
m_item = new ItemData(*m_item);
|
||||
}
|
||||
else {
|
||||
m_item = nullptr;
|
||||
}
|
||||
|
||||
m_charges = charges;
|
||||
m_price = 0;
|
||||
m_merchantslot = 0;
|
||||
m_attuned=false;
|
||||
if (m_item && m_item->IsClassCommon())
|
||||
m_color = m_item->Color;
|
||||
else
|
||||
m_color = 0;
|
||||
m_merchantcount = 1;
|
||||
m_SerialNumber = GetNextItemInstSerialNumber();
|
||||
|
||||
m_exp = 0;
|
||||
m_evolveLvl = 0;
|
||||
m_activated = false;
|
||||
m_scaledItem = nullptr;
|
||||
m_evolveInfo = nullptr;
|
||||
m_scaling = false;
|
||||
m_ornamenticon = 0;
|
||||
m_ornamentidfile = 0;
|
||||
m_ornament_hero_model = 0;
|
||||
m_recast_timestamp = 0;
|
||||
m_new_id_file = 0;
|
||||
if (m_item && m_item->IsClassCommon()) {
|
||||
m_color = m_item->Color;
|
||||
} else {
|
||||
m_color = 0;
|
||||
}
|
||||
|
||||
m_SerialNumber = GetNextItemInstSerialNumber();
|
||||
}
|
||||
|
||||
EQ::ItemInstance::ItemInstance(ItemInstTypes use_type) {
|
||||
m_use_type = use_type;
|
||||
m_item = nullptr;
|
||||
m_charges = 0;
|
||||
m_price = 0;
|
||||
m_attuned = false;
|
||||
m_merchantslot = 0;
|
||||
m_color = 0;
|
||||
|
||||
m_exp = 0;
|
||||
m_evolveLvl = 0;
|
||||
m_activated = false;
|
||||
m_scaledItem = nullptr;
|
||||
m_evolveInfo = nullptr;
|
||||
m_scaling = false;
|
||||
m_ornamenticon = 0;
|
||||
m_ornamentidfile = 0;
|
||||
m_ornament_hero_model = 0;
|
||||
m_recast_timestamp = 0;
|
||||
m_new_id_file = 0;
|
||||
m_use_type = use_type;
|
||||
}
|
||||
|
||||
// Make a copy of an EQ::ItemInstance object
|
||||
EQ::ItemInstance::ItemInstance(const ItemInstance& copy)
|
||||
{
|
||||
m_use_type=copy.m_use_type;
|
||||
if(copy.m_item)
|
||||
m_item = new ItemData(*copy.m_item);
|
||||
else
|
||||
m_item = nullptr;
|
||||
m_use_type = copy.m_use_type;
|
||||
|
||||
if (copy.m_item) {
|
||||
m_item = new ItemData(*copy.m_item);
|
||||
} else {
|
||||
m_item = nullptr;
|
||||
}
|
||||
|
||||
m_charges = copy.m_charges;
|
||||
m_price = copy.m_price;
|
||||
m_color = copy.m_color;
|
||||
m_merchantslot = copy.m_merchantslot;
|
||||
m_currentslot = copy.m_currentslot;
|
||||
m_attuned = copy.m_attuned;
|
||||
m_merchantcount = copy.m_merchantcount;
|
||||
|
||||
m_charges=copy.m_charges;
|
||||
m_price=copy.m_price;
|
||||
m_color=copy.m_color;
|
||||
m_merchantslot=copy.m_merchantslot;
|
||||
m_currentslot=copy.m_currentslot;
|
||||
m_attuned=copy.m_attuned;
|
||||
m_merchantcount=copy.m_merchantcount;
|
||||
// Copy container contents
|
||||
for (auto it = copy.m_contents.begin(); it != copy.m_contents.end(); ++it) {
|
||||
ItemInstance* inst_old = it->second;
|
||||
@@ -168,37 +123,42 @@ EQ::ItemInstance::ItemInstance(const ItemInstance& copy)
|
||||
inst_new = inst_old->Clone();
|
||||
}
|
||||
|
||||
if (inst_new != nullptr) {
|
||||
if (inst_new) {
|
||||
m_contents[it->first] = inst_new;
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, std::string>::const_iterator iter;
|
||||
for (iter = copy.m_custom_data.begin(); iter != copy.m_custom_data.end(); ++iter) {
|
||||
m_custom_data[iter->first] = iter->second;
|
||||
}
|
||||
m_SerialNumber = copy.m_SerialNumber;
|
||||
m_custom_data = copy.m_custom_data;
|
||||
m_timers = copy.m_timers;
|
||||
|
||||
m_exp = copy.m_exp;
|
||||
m_SerialNumber = copy.m_SerialNumber;
|
||||
m_custom_data = copy.m_custom_data;
|
||||
m_timers = copy.m_timers;
|
||||
|
||||
m_exp = copy.m_exp;
|
||||
m_evolveLvl = copy.m_evolveLvl;
|
||||
m_activated = copy.m_activated;
|
||||
if (copy.m_scaledItem)
|
||||
|
||||
if (copy.m_scaledItem) {
|
||||
m_scaledItem = new ItemData(*copy.m_scaledItem);
|
||||
else
|
||||
} else {
|
||||
m_scaledItem = nullptr;
|
||||
}
|
||||
|
||||
if(copy.m_evolveInfo)
|
||||
if (copy.m_evolveInfo) {
|
||||
m_evolveInfo = new EvolveInfo(*copy.m_evolveInfo);
|
||||
else
|
||||
} else {
|
||||
m_evolveInfo = nullptr;
|
||||
}
|
||||
|
||||
m_scaling = copy.m_scaling;
|
||||
m_ornamenticon = copy.m_ornamenticon;
|
||||
m_ornamentidfile = copy.m_ornamentidfile;
|
||||
m_scaling = copy.m_scaling;
|
||||
m_ornamenticon = copy.m_ornamenticon;
|
||||
m_ornamentidfile = copy.m_ornamentidfile;
|
||||
m_ornament_hero_model = copy.m_ornament_hero_model;
|
||||
m_recast_timestamp = copy.m_recast_timestamp;
|
||||
m_new_id_file = copy.m_new_id_file;
|
||||
m_recast_timestamp = copy.m_recast_timestamp;
|
||||
m_new_id_file = copy.m_new_id_file;
|
||||
}
|
||||
|
||||
// Clean up container contents
|
||||
@@ -216,11 +176,13 @@ bool EQ::ItemInstance::IsType(item::ItemClass item_class) const
|
||||
// IsType(<ItemClassTypes>) does not protect against 'm_item = nullptr'
|
||||
|
||||
// Check usage type
|
||||
if ((m_use_type == ItemInstWorldContainer) && (item_class == item::ItemClassBag))
|
||||
if (m_use_type == ItemInstWorldContainer && item_class == item::ItemClassBag) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_item)
|
||||
if (!m_item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (m_item->ItemClass == item_class);
|
||||
}
|
||||
@@ -243,21 +205,20 @@ bool EQ::ItemInstance::IsClassBook() const
|
||||
// Is item stackable?
|
||||
bool EQ::ItemInstance::IsStackable() const
|
||||
{
|
||||
if (!m_item)
|
||||
return false;
|
||||
|
||||
return m_item->Stackable;
|
||||
return (m_item && m_item->Stackable);
|
||||
}
|
||||
|
||||
bool EQ::ItemInstance::IsCharged() const
|
||||
{
|
||||
if (!m_item)
|
||||
if (!m_item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_item->MaxCharges > 1)
|
||||
if (m_item->MaxCharges > 1) {
|
||||
return true;
|
||||
else
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Can item be equipped?
|
||||
@@ -306,26 +267,30 @@ bool EQ::ItemInstance::IsEquipable(int16 slot_id) const
|
||||
|
||||
bool EQ::ItemInstance::IsAugmentable() const
|
||||
{
|
||||
if (!m_item)
|
||||
if (!m_item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) {
|
||||
if (m_item->AugSlotType[index] != 0)
|
||||
if (m_item->AugSlotType[index] != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQ::ItemInstance::AvailableWearSlot(uint32 aug_wear_slots) const {
|
||||
if (!m_item || !m_item->IsClassCommon())
|
||||
if (!m_item || !m_item->IsClassCommon()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int index = invslot::EQUIPMENT_BEGIN;
|
||||
for (; index <= invslot::EQUIPMENT_END; ++index) {
|
||||
if (m_item->Slots & (1 << index)) {
|
||||
if (aug_wear_slots & (1 << index))
|
||||
if (aug_wear_slots & (1 << index)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,9 +359,10 @@ EQ::ItemInstance* EQ::ItemInstance::GetItem(uint8 index) const
|
||||
|
||||
uint32 EQ::ItemInstance::GetItemID(uint8 slot) const
|
||||
{
|
||||
ItemInstance *item = GetItem(slot);
|
||||
if (item)
|
||||
const auto item = GetItem(slot);
|
||||
if (item) {
|
||||
return item->GetID();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -520,14 +486,21 @@ uint8 EQ::ItemInstance::FirstOpenSlot() const
|
||||
|
||||
uint8 EQ::ItemInstance::GetTotalItemCount() const
|
||||
{
|
||||
if (!m_item)
|
||||
if (!m_item) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8 item_count = 1;
|
||||
|
||||
if (m_item && !m_item->IsClassBag()) { return item_count; }
|
||||
if (!m_item->IsClassBag()) {
|
||||
return item_count;
|
||||
}
|
||||
|
||||
for (int index = invbag::SLOT_BEGIN; index < m_item->BagSlots; ++index) { if (GetItem(index)) { ++item_count; } }
|
||||
for (int index = invbag::SLOT_BEGIN; index < m_item->BagSlots; ++index) {
|
||||
if (GetItem(index)) {
|
||||
++item_count;
|
||||
}
|
||||
}
|
||||
|
||||
return item_count;
|
||||
}
|
||||
@@ -555,78 +528,99 @@ EQ::ItemInstance* EQ::ItemInstance::GetAugment(uint8 augment_index) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EQ::ItemInstance* EQ::ItemInstance::GetOrnamentationAug(int32 ornamentationAugtype) const
|
||||
bool EQ::ItemInstance::IsOrnamentationAugment(EQ::ItemInstance* augment) const
|
||||
{
|
||||
if (!m_item || !m_item->IsClassCommon()) { return nullptr; }
|
||||
if (ornamentationAugtype == 0) { return nullptr; }
|
||||
if (!m_item || !m_item->IsClassCommon() || !augment) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; i++)
|
||||
{
|
||||
if (GetAugment(i) && m_item->AugSlotType[i] == ornamentationAugtype)
|
||||
{
|
||||
const char *item_IDFile = GetAugment(i)->GetItem()->IDFile;
|
||||
if (
|
||||
(strncmp(item_IDFile, "IT64", strlen(item_IDFile)) == 0
|
||||
|| strncmp(item_IDFile, "IT63", strlen(item_IDFile)) == 0)
|
||||
&& GetAugment(i)->GetItem()->HerosForgeModel == 0
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return GetAugment(i);
|
||||
const auto augment_item = augment->GetItem();
|
||||
if (!augment_item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string& idfile = augment_item->IDFile;
|
||||
|
||||
if (
|
||||
EQ::ValueWithin(
|
||||
augment->GetAugmentType(),
|
||||
OrnamentationAugmentTypes::StandardOrnamentation,
|
||||
OrnamentationAugmentTypes::SpecialOrnamentation
|
||||
) ||
|
||||
(
|
||||
idfile != "IT63" &&
|
||||
idfile != "IT64"
|
||||
) ||
|
||||
augment_item->HerosForgeModel
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
EQ::ItemInstance* EQ::ItemInstance::GetOrnamentationAugment() const
|
||||
{
|
||||
if (!m_item || !m_item->IsClassCommon()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; i++) {
|
||||
const auto augment = GetAugment(i);
|
||||
if (augment && IsOrnamentationAugment(augment)) {
|
||||
return augment;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32 EQ::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const {
|
||||
uint32 EQ::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const
|
||||
{
|
||||
// Not a Hero Forge item.
|
||||
if (m_ornament_hero_model == 0 || material_slot < 0)
|
||||
if (m_ornament_hero_model == 0 || material_slot < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Item is using an explicit Hero Forge ID
|
||||
if (m_ornament_hero_model >= 1000)
|
||||
if (m_ornament_hero_model >= 1000) {
|
||||
return m_ornament_hero_model;
|
||||
}
|
||||
|
||||
// Item is using a shorthand ID
|
||||
return (m_ornament_hero_model * 100) + material_slot;
|
||||
}
|
||||
|
||||
bool EQ::ItemInstance::UpdateOrnamentationInfo() {
|
||||
if (!m_item || !m_item->IsClassCommon())
|
||||
bool EQ::ItemInstance::UpdateOrnamentationInfo()
|
||||
{
|
||||
if (!m_item || !m_item->IsClassCommon()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ornamentSet = false;
|
||||
const auto augment = GetOrnamentationAugment();
|
||||
|
||||
int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType);
|
||||
if (GetOrnamentationAug(ornamentationAugtype))
|
||||
{
|
||||
const ItemData* ornamentItem;
|
||||
ornamentItem = GetOrnamentationAug(ornamentationAugtype)->GetItem();
|
||||
if (ornamentItem != nullptr)
|
||||
{
|
||||
SetOrnamentIcon(ornamentItem->Icon);
|
||||
SetOrnamentHeroModel(ornamentItem->HerosForgeModel);
|
||||
if (strlen(ornamentItem->IDFile) > 2)
|
||||
{
|
||||
SetOrnamentationIDFile(Strings::ToUnsignedInt(&ornamentItem->IDFile[2]));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (augment) {
|
||||
const auto augment_item = GetOrnamentationAugment()->GetItem();
|
||||
|
||||
if (augment_item) {
|
||||
SetOrnamentIcon(augment_item->Icon);
|
||||
SetOrnamentHeroModel(augment_item->HerosForgeModel);
|
||||
|
||||
if (strlen(augment_item->IDFile) > 2) {
|
||||
SetOrnamentationIDFile(Strings::ToUnsignedInt(&augment_item->IDFile[2]));
|
||||
} else {
|
||||
SetOrnamentationIDFile(0);
|
||||
}
|
||||
ornamentSet = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetOrnamentIcon(0);
|
||||
SetOrnamentHeroModel(0);
|
||||
SetOrnamentationIDFile(0);
|
||||
}
|
||||
|
||||
return ornamentSet;
|
||||
SetOrnamentIcon(0);
|
||||
SetOrnamentHeroModel(0);
|
||||
SetOrnamentationIDFile(0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQ::ItemInstance::CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll) {
|
||||
@@ -726,12 +720,14 @@ EQ::ItemInstance* EQ::ItemInstance::RemoveAugment(uint8 index)
|
||||
|
||||
bool EQ::ItemInstance::IsAugmented()
|
||||
{
|
||||
if (!m_item || !m_item->IsClassCommon())
|
||||
if (!m_item || !m_item->IsClassCommon()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) {
|
||||
if (GetAugmentItemID(index))
|
||||
for (uint8 slot_id = invaug::SOCKET_BEGIN; slot_id <= invaug::SOCKET_END; ++slot_id) {
|
||||
if (GetAugmentItemID(slot_id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -940,8 +936,9 @@ bool EQ::ItemInstance::IsDroppable(bool recurse) const
|
||||
|
||||
void EQ::ItemInstance::Initialize(SharedDatabase *db) {
|
||||
// if there's no actual item, don't do anything
|
||||
if (!m_item)
|
||||
if (!m_item) {
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize scaling items
|
||||
if (m_item->CharmFileID != 0) {
|
||||
@@ -950,7 +947,7 @@ void EQ::ItemInstance::Initialize(SharedDatabase *db) {
|
||||
}
|
||||
|
||||
// initialize evolving items
|
||||
else if ((db) && m_item->LoreGroup >= 1000 && m_item->LoreGroup != -1) {
|
||||
else if (db && m_item->LoreGroup >= 1000) {
|
||||
// not complete yet
|
||||
}
|
||||
}
|
||||
|
||||
+35
-29
@@ -51,6 +51,11 @@ typedef enum {
|
||||
byFlagNotSet //apply action if the flag is NOT set
|
||||
} byFlagSetting;
|
||||
|
||||
enum OrnamentationAugmentTypes {
|
||||
StandardOrnamentation = 20,
|
||||
SpecialOrnamentation = 21
|
||||
};
|
||||
|
||||
class SharedDatabase;
|
||||
|
||||
// ########################################
|
||||
@@ -103,7 +108,8 @@ namespace EQ
|
||||
bool AvailableWearSlot(uint32 aug_wear_slots) const;
|
||||
int8 AvailableAugmentSlot(int32 augment_type) const;
|
||||
bool IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const;
|
||||
inline int32 GetAugmentType() const { return ((m_item) ? m_item->AugType : 0); }
|
||||
inline int GetAugmentType() const { return m_item ? m_item->AugType : 0; }
|
||||
inline uint32 GetAugmentRestriction() const { return m_item ? m_item->AugRestrict : 0; }
|
||||
|
||||
inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == item::ItemEffectExpendable) || (m_item->ItemType == item::ItemTypePotion)) : false); }
|
||||
|
||||
@@ -136,7 +142,8 @@ namespace EQ
|
||||
bool IsAugmented();
|
||||
bool ContainsAugmentByID(uint32 item_id);
|
||||
int CountAugmentByID(uint32 item_id);
|
||||
ItemInstance* GetOrnamentationAug(int32 ornamentationAugtype) const;
|
||||
bool IsOrnamentationAugment(EQ::ItemInstance* augment) const;
|
||||
ItemInstance* GetOrnamentationAugment() const;
|
||||
bool UpdateOrnamentationInfo();
|
||||
static bool CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll = false);
|
||||
|
||||
@@ -304,34 +311,33 @@ namespace EQ
|
||||
|
||||
void _PutItem(uint8 index, ItemInstance* inst) { m_contents[index] = inst; }
|
||||
|
||||
ItemInstTypes m_use_type; // Usage type for item
|
||||
const ItemData* m_item; // Ptr to item data
|
||||
int16 m_charges; // # of charges for chargeable items
|
||||
uint32 m_price; // Bazaar /trader price
|
||||
uint32 m_color;
|
||||
uint32 m_merchantslot;
|
||||
int16 m_currentslot;
|
||||
bool m_attuned;
|
||||
int32 m_merchantcount; //number avaliable on the merchant, -1=unlimited
|
||||
int32 m_SerialNumber; // Unique identifier for this instance of an item. Needed for Bazaar.
|
||||
uint32 m_exp;
|
||||
int8 m_evolveLvl;
|
||||
bool m_activated;
|
||||
ItemData* m_scaledItem;
|
||||
::EvolveInfo* m_evolveInfo;
|
||||
bool m_scaling;
|
||||
uint32 m_ornamenticon;
|
||||
uint32 m_ornamentidfile;
|
||||
uint32 m_new_id_file;
|
||||
uint32 m_ornament_hero_model;
|
||||
uint32 m_recast_timestamp;
|
||||
int m_task_delivered_count = 0;
|
||||
ItemInstTypes m_use_type {ItemInstNormal}; // Usage type for item
|
||||
const ItemData* m_item {nullptr}; // Ptr to item data
|
||||
int16 m_charges {0}; // # of charges for chargeable items
|
||||
uint32 m_price {0}; // Bazaar /trader price
|
||||
uint32 m_color {0};
|
||||
uint32 m_merchantslot {0};
|
||||
int16 m_currentslot {0};
|
||||
bool m_attuned {false};
|
||||
int32 m_merchantcount {1}; //number avaliable on the merchant, -1=unlimited
|
||||
int32 m_SerialNumber {0}; // Unique identifier for this instance of an item. Needed for Bazaar.
|
||||
uint32 m_exp {0};
|
||||
int8 m_evolveLvl {0};
|
||||
bool m_activated {false};
|
||||
ItemData* m_scaledItem {nullptr};
|
||||
::EvolveInfo* m_evolveInfo {nullptr};
|
||||
bool m_scaling {false};
|
||||
uint32 m_ornamenticon {0};
|
||||
uint32 m_ornamentidfile {0};
|
||||
uint32 m_new_id_file {0};
|
||||
uint32 m_ornament_hero_model {0};
|
||||
uint32 m_recast_timestamp {0};
|
||||
int m_task_delivered_count {0};
|
||||
|
||||
//
|
||||
// Items inside of this item (augs or contents);
|
||||
std::map<uint8, ItemInstance*> m_contents; // Zero-based index: min=0, max=9
|
||||
std::map<std::string, std::string> m_custom_data;
|
||||
std::map<std::string, ::Timer> m_timers;
|
||||
// Items inside of this item (augs or contents) {};
|
||||
std::map<uint8, ItemInstance*> m_contents {}; // Zero-based index: min=0, max=9
|
||||
std::map<std::string, std::string> m_custom_data {};
|
||||
std::map<std::string, ::Timer> m_timers {};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -48,5 +48,7 @@
|
||||
#define LANG_HADAL 26
|
||||
#define LANG_UNKNOWN 27
|
||||
|
||||
#define MAX_LANGUAGE_SKILL 100
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+1
-118
@@ -151,7 +151,7 @@ static char *temp=nullptr;
|
||||
return false;
|
||||
}
|
||||
ptr++;
|
||||
uint32 id = Strings::ToUnsignedInt(field[id_pos].c_str());
|
||||
uint32 id = Strings::ToUnsignedInt(field[id_pos]);
|
||||
items[id]=field;
|
||||
|
||||
for(i=0;i<10;i++) {
|
||||
@@ -214,123 +214,6 @@ std::string x;
|
||||
return i;
|
||||
}
|
||||
|
||||
void LoadItemDBFieldNames() {
|
||||
DBFieldNames[0]="N/A"; // Charges
|
||||
DBFieldNames[1]="unknown002"; // ?
|
||||
DBFieldNames[2]="N/A"; // Current Equip Slot
|
||||
DBFieldNames[3]="unknown004";
|
||||
DBFieldNames[4]="unknown005"; // ?
|
||||
DBFieldNames[5]="itemclass"; // "Item Type (0=common, 1=container, 2=book)"
|
||||
DBFieldNames[6]="name"; // Name
|
||||
DBFieldNames[7]="lore"; // "Lore Name (*=lore, &=summoned, #=artifact)"
|
||||
DBFieldNames[8]="idfile"; // IDFile
|
||||
DBFieldNames[9]="id"; // ItemNumber
|
||||
DBFieldNames[10]="weight"; // Weight
|
||||
DBFieldNames[11]="norent"; // "NoRent (0=norent, 255=not norent)"
|
||||
DBFieldNames[12]="nodrop"; // "NoDrop (0=nodrop, 255=not nodrop)"
|
||||
DBFieldNames[13]="size"; // "Size (0=tiny, 1=small, 2=medium, 3=large, 4=giant)"
|
||||
DBFieldNames[14]="slots"; // EquipSlots
|
||||
DBFieldNames[15]="cost"; // Cost
|
||||
DBFieldNames[16]="icon"; // IconNumber
|
||||
DBFieldNames[17]="unknown018";
|
||||
DBFieldNames[18]="unknown019";
|
||||
DBFieldNames[19]="unknown020"; // ?
|
||||
DBFieldNames[20]="tradeskills"; // "Tradeskill Item (1=is a tradeskill item, 0=not)"
|
||||
DBFieldNames[21]="cr"; // SvCold
|
||||
DBFieldNames[22]="dr"; // SvDisease
|
||||
DBFieldNames[23]="pr"; // SvPoison
|
||||
DBFieldNames[24]="mr"; // SvMagic
|
||||
DBFieldNames[25]="fr"; // SvFire
|
||||
DBFieldNames[26]="astr"; // STR
|
||||
DBFieldNames[27]="asta"; // STA
|
||||
DBFieldNames[28]="aagi"; // AGI
|
||||
DBFieldNames[29]="adex"; // DEX
|
||||
DBFieldNames[30]="acha"; // CHA
|
||||
DBFieldNames[31]="aint"; // INT
|
||||
DBFieldNames[32]="awis"; // WIS
|
||||
DBFieldNames[33]="hp"; // HP
|
||||
DBFieldNames[34]="mana"; // Mana
|
||||
DBFieldNames[35]="ac"; // AC
|
||||
DBFieldNames[36]="deity"; // Deity
|
||||
DBFieldNames[37]="skillmodvalue"; // Skill Mod Value
|
||||
DBFieldNames[38]="skillmodtype"; // Skill Mod Type
|
||||
DBFieldNames[39]="banedmgrace"; // Bane Dmg Race
|
||||
DBFieldNames[40]="banedmgamt"; // Band Dmg
|
||||
DBFieldNames[41]="banedmgbody"; // Band Dmg Body
|
||||
DBFieldNames[42]="magic"; // "Magic (0=not magic, 1=magic)"
|
||||
DBFieldNames[43]="casttime2"; // Casttime appears twice
|
||||
DBFieldNames[44]="hasteproclvl"; // "Level (Haste value, rather)"
|
||||
DBFieldNames[45]="reqlevel"; // Required Level
|
||||
DBFieldNames[46]="bardtype"; // Bard Type
|
||||
DBFieldNames[47]="bardvalue"; // Bard Type Amount
|
||||
DBFieldNames[48]="light"; // Light
|
||||
DBFieldNames[49]="delay"; // Attack Delay
|
||||
DBFieldNames[50]="reclevel"; // Recommended Level
|
||||
DBFieldNames[51]="recskill"; // Recommended Skill
|
||||
DBFieldNames[52]="elemdmgamt"; // "Elemental Dmg Type (1=magic, 2=fire, 3=cold, 4=poison, 5=disease)"
|
||||
DBFieldNames[53]="elemdmgtype"; // Elemental Dmg
|
||||
DBFieldNames[54]="effecttype"; // "Effect Type (0=combat, 1=clicky, 2=Worn, 3=Expendable charges, 4=Must Equip Clicky, 5=clicky)"
|
||||
DBFieldNames[55]="range"; // Range
|
||||
DBFieldNames[56]="damage"; // Damage
|
||||
DBFieldNames[57]="color"; // Color
|
||||
DBFieldNames[58]="classes"; // Classes
|
||||
DBFieldNames[59]="races"; // Races
|
||||
DBFieldNames[60]="unknown061";
|
||||
DBFieldNames[61]="spellid"; // SpellId
|
||||
DBFieldNames[62]="maxcharges"; // MaxCharges
|
||||
DBFieldNames[63]="itemtype"; // "Skill (ItemType: 1hs, etc)"
|
||||
DBFieldNames[64]="material"; // Material
|
||||
DBFieldNames[65]="sellrate"; // ** Sell Rate
|
||||
DBFieldNames[66]="unknown067";
|
||||
DBFieldNames[67]="casttime"; // CastTime (milliseconds)
|
||||
DBFieldNames[68]="unknown069";
|
||||
DBFieldNames[69]="unknown070"; // ?
|
||||
DBFieldNames[70]="focusid"; // Focus Effect Spell Id
|
||||
DBFieldNames[71]="combateffects"; // CombatEffects
|
||||
DBFieldNames[72]="shielding"; // Shielding
|
||||
DBFieldNames[73]="stunresist"; // StunResist
|
||||
DBFieldNames[74]="strikethrough"; // StrikeThrough
|
||||
DBFieldNames[75]="unknown076";
|
||||
DBFieldNames[76]="unknown077"; // ?
|
||||
DBFieldNames[77]="spellshield"; // Spell Shield
|
||||
DBFieldNames[78]="avoidance"; // Avoidance
|
||||
DBFieldNames[79]="accuracy"; // Accuracy
|
||||
DBFieldNames[80]="factionmod1"; // Faction Mod Index 1
|
||||
DBFieldNames[81]="factionmod2"; // Faction Mod Index 2
|
||||
DBFieldNames[82]="factionmod3"; // Faction Mod Index 3
|
||||
DBFieldNames[83]="factionmod4"; // Faction Mod Index 4
|
||||
DBFieldNames[84]="factionamt1"; // Faction Mod Value 1
|
||||
DBFieldNames[85]="factionamt2"; // Faction Mod Value 2
|
||||
DBFieldNames[86]="factionamt3"; // Faction Mod Value 3
|
||||
DBFieldNames[87]="factionamt4"; // Faction Mod Value 4
|
||||
DBFieldNames[88]="unknown089";
|
||||
DBFieldNames[89]="charmfile"; // ** Charm File
|
||||
DBFieldNames[90]="unknown091";
|
||||
DBFieldNames[91]="augslot1type"; // Slot1Type
|
||||
DBFieldNames[92]="augslot2type"; // Slot2Type
|
||||
DBFieldNames[93]="augslot3type"; // Slot3Type
|
||||
DBFieldNames[94]="augslot4type"; // Slot4Type
|
||||
DBFieldNames[95]="augslot5type"; // Slot5Type
|
||||
DBFieldNames[96]="ldonpointtheme";
|
||||
DBFieldNames[97]="ldonpointcost"; // ?
|
||||
DBFieldNames[98]="unknown099";
|
||||
DBFieldNames[99]="bagtype"; // bag type
|
||||
DBFieldNames[100]="bagslots"; // bag slots
|
||||
DBFieldNames[101]="bagsize"; // bag size capacity
|
||||
DBFieldNames[102]="bagwr"; // bag weight reduction
|
||||
DBFieldNames[103]="booktype"; // "book type (0=rolled up note, 1=book)"
|
||||
DBFieldNames[104]="unknown105";
|
||||
DBFieldNames[105]="filename"; // Book Filename
|
||||
DBFieldNames[106]="unknown107";
|
||||
DBFieldNames[107]="unknown108";
|
||||
DBFieldNames[108]="loreflag";
|
||||
DBFieldNames[109]="unknown111";
|
||||
DBFieldNames[110]="unknown112";
|
||||
DBFieldNames[111]="unknown113";
|
||||
DBFieldNames[112]="unknown114";
|
||||
DBFieldNames[113]="unknown115"; // ? (end quote)
|
||||
}
|
||||
|
||||
void dump_message_column(unsigned char *buffer, unsigned long length, std::string leader, FILE *to)
|
||||
{
|
||||
unsigned long i,j;
|
||||
|
||||
@@ -15,8 +15,6 @@ bool ItemParse(const char *data, int length, std::map<int,std::map<int,std::stri
|
||||
|
||||
int Tokenize(std::string s, std::map<int,std::string> & tokens, char delim='|');
|
||||
|
||||
void LoadItemDBFieldNames();
|
||||
|
||||
#ifndef WIN32
|
||||
int print_stacktrace();
|
||||
#endif
|
||||
|
||||
@@ -51,6 +51,7 @@ void MySQLRequestResult::ZeroOut()
|
||||
m_RowCount = 0;
|
||||
m_RowsAffected = 0;
|
||||
m_LastInsertedID = 0;
|
||||
m_error_message = "";
|
||||
}
|
||||
|
||||
MySQLRequestResult::~MySQLRequestResult()
|
||||
@@ -137,3 +138,23 @@ MySQLRequestResult& MySQLRequestResult::operator=(MySQLRequestResult&& other)
|
||||
other.ZeroOut();
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint32 MySQLRequestResult::GetErrorNumber() const
|
||||
{
|
||||
return m_ErrorNumber;
|
||||
}
|
||||
|
||||
void MySQLRequestResult::SetErrorNumber(uint32 m_error_number)
|
||||
{
|
||||
m_ErrorNumber = m_error_number;
|
||||
}
|
||||
|
||||
const std::string &MySQLRequestResult::GetErrorMessage() const
|
||||
{
|
||||
return m_error_message;
|
||||
}
|
||||
|
||||
void MySQLRequestResult::SetErrorMessage(const std::string &m_error_message)
|
||||
{
|
||||
MySQLRequestResult::m_error_message = m_error_message;
|
||||
}
|
||||
|
||||
@@ -33,30 +33,42 @@ private:
|
||||
uint32 m_LastInsertedID;
|
||||
uint32 m_ErrorNumber;
|
||||
|
||||
std::string m_error_message;
|
||||
|
||||
public:
|
||||
|
||||
MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected = 0, uint32 rowCount = 0, uint32 columnCount = 0, uint32 lastInsertedID = 0, uint32 errorNumber = 0, char *errorBuffer = nullptr);
|
||||
MySQLRequestResult();
|
||||
MySQLRequestResult();
|
||||
MySQLRequestResult(MySQLRequestResult&& moveItem);
|
||||
~MySQLRequestResult();
|
||||
|
||||
MySQLRequestResult& operator=(MySQLRequestResult&& other);
|
||||
|
||||
bool Success() const { return m_Success;}
|
||||
std::string ErrorMessage() const {return m_ErrorBuffer ? std::string(m_ErrorBuffer) : std::string("");}
|
||||
std::string ErrorMessage() const {
|
||||
if (!m_error_message.empty()) {
|
||||
return m_error_message;
|
||||
}
|
||||
|
||||
return m_ErrorBuffer ? std::string(m_ErrorBuffer) : std::string("");
|
||||
}
|
||||
uint32 ErrorNumber() const {return m_ErrorNumber;}
|
||||
uint32 RowsAffected() const {return m_RowsAffected;}
|
||||
uint32 RowCount() const {return m_RowCount;}
|
||||
uint32 ColumnCount() const {return m_ColumnCount;}
|
||||
uint32 LastInsertedID() const {return m_LastInsertedID;}
|
||||
// default to 0 index since we mostly use it that way anyways.
|
||||
uint32 LengthOfColumn(int columnIndex = 0);
|
||||
uint32 LengthOfColumn(int columnIndex = 0);
|
||||
const std::string FieldName(int columnIndex);
|
||||
|
||||
MySQLRequestRow& begin() { return m_CurrentRow; }
|
||||
MySQLRequestRow& end() { return m_OneBeyondRow; }
|
||||
|
||||
uint32 GetErrorNumber() const;
|
||||
void SetErrorNumber(uint32 m_error_number);
|
||||
const std::string &GetErrorMessage() const;
|
||||
void SetErrorMessage(const std::string &m_error_message);
|
||||
|
||||
private:
|
||||
void FreeInternals();
|
||||
void ZeroOut();
|
||||
|
||||
@@ -7,7 +7,7 @@ EQ::Net::ConsoleServer::ConsoleServer(const std::string &addr, int port)
|
||||
m_server = std::make_unique<EQ::Net::TCPServer>();
|
||||
m_server->Listen(addr, port, false, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
|
||||
ConsoleServerConnection *c = new ConsoleServerConnection(this, connection);
|
||||
m_connections.insert(std::make_pair(c->GetUUID(), std::unique_ptr<ConsoleServerConnection>(c)));
|
||||
m_connections.emplace(std::make_pair(c->GetUUID(), std::unique_ptr<ConsoleServerConnection>(c)));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ void EQ::Net::DaybreakConnectionManager::Connect(const std::string &addr, int po
|
||||
m_on_new_connection(connection);
|
||||
}
|
||||
|
||||
m_connections.insert(std::make_pair(std::make_pair(addr, port), connection));
|
||||
m_connections.emplace(std::make_pair(std::make_pair(addr, port), connection));
|
||||
}
|
||||
|
||||
void EQ::Net::DaybreakConnectionManager::Process()
|
||||
@@ -234,7 +234,7 @@ void EQ::Net::DaybreakConnectionManager::ProcessPacket(const std::string &endpoi
|
||||
if (m_on_new_connection) {
|
||||
m_on_new_connection(connection);
|
||||
}
|
||||
m_connections.insert(std::make_pair(std::make_pair(endpoint, port), connection));
|
||||
m_connections.emplace(std::make_pair(std::make_pair(endpoint, port), connection));
|
||||
connection->ProcessPacket(p);
|
||||
}
|
||||
else if (data[1] != OP_OutOfSession) {
|
||||
@@ -527,7 +527,7 @@ void EQ::Net::DaybreakConnection::AddToQueue(int stream, uint16_t seq, const Pac
|
||||
DynamicPacket *out = new DynamicPacket();
|
||||
out->PutPacket(0, p);
|
||||
|
||||
s->packet_queue.insert(std::make_pair(seq, out));
|
||||
s->packet_queue.emplace(std::make_pair(seq, out));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1427,7 +1427,7 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
|
||||
static_cast<size_t>((m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms),
|
||||
m_owner->m_options.resend_delay_min,
|
||||
m_owner->m_options.resend_delay_max);
|
||||
stream->sent_packets.insert(std::make_pair(stream->sequence_out, sent));
|
||||
stream->sent_packets.emplace(std::make_pair(stream->sequence_out, sent));
|
||||
stream->sequence_out++;
|
||||
|
||||
InternalBufferedSend(first_packet);
|
||||
@@ -1459,7 +1459,7 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
|
||||
static_cast<size_t>((m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms),
|
||||
m_owner->m_options.resend_delay_min,
|
||||
m_owner->m_options.resend_delay_max);
|
||||
stream->sent_packets.insert(std::make_pair(stream->sequence_out, sent));
|
||||
stream->sent_packets.emplace(std::make_pair(stream->sequence_out, sent));
|
||||
stream->sequence_out++;
|
||||
|
||||
InternalBufferedSend(packet);
|
||||
@@ -1483,7 +1483,7 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
|
||||
static_cast<size_t>((m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms),
|
||||
m_owner->m_options.resend_delay_min,
|
||||
m_owner->m_options.resend_delay_max);
|
||||
stream->sent_packets.insert(std::make_pair(stream->sequence_out, sent));
|
||||
stream->sent_packets.emplace(std::make_pair(stream->sequence_out, sent));
|
||||
stream->sequence_out++;
|
||||
|
||||
InternalBufferedSend(packet);
|
||||
|
||||
@@ -22,7 +22,7 @@ void EQ::Net::EQStreamManager::SetOptions(const EQStreamManagerInterfaceOptions
|
||||
void EQ::Net::EQStreamManager::DaybreakNewConnection(std::shared_ptr<DaybreakConnection> connection)
|
||||
{
|
||||
std::shared_ptr<EQStream> stream(new EQStream(this, connection));
|
||||
m_streams.insert(std::make_pair(connection, stream));
|
||||
m_streams.emplace(std::make_pair(connection, stream));
|
||||
if (m_on_new_connection) {
|
||||
m_on_new_connection(stream);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ void EQ::Net::ServertalkClient::SendPacket(ServerPacket *p)
|
||||
|
||||
void EQ::Net::ServertalkClient::OnMessage(uint16_t opcode, std::function<void(uint16_t, EQ::Net::Packet&)> cb)
|
||||
{
|
||||
m_message_callbacks.insert(std::make_pair(opcode, cb));
|
||||
m_message_callbacks.emplace(std::make_pair(opcode, cb));
|
||||
}
|
||||
|
||||
void EQ::Net::ServertalkClient::OnMessage(std::function<void(uint16_t, EQ::Net::Packet&)> cb)
|
||||
|
||||
@@ -41,7 +41,7 @@ void EQ::Net::ServertalkLegacyClient::SendPacket(ServerPacket *p)
|
||||
|
||||
void EQ::Net::ServertalkLegacyClient::OnMessage(uint16_t opcode, std::function<void(uint16_t, EQ::Net::Packet&)> cb)
|
||||
{
|
||||
m_message_callbacks.insert(std::make_pair(opcode, cb));
|
||||
m_message_callbacks.emplace(std::make_pair(opcode, cb));
|
||||
}
|
||||
|
||||
void EQ::Net::ServertalkLegacyClient::OnMessage(std::function<void(uint16_t, EQ::Net::Packet&)> cb)
|
||||
|
||||
@@ -19,12 +19,12 @@ void EQ::Net::ServertalkServer::Listen(const ServertalkServerOptions& opts)
|
||||
|
||||
void EQ::Net::ServertalkServer::OnConnectionIdentified(const std::string &type, std::function<void(std::shared_ptr<ServertalkServerConnection>)> cb)
|
||||
{
|
||||
m_on_ident.insert(std::make_pair(type, cb));
|
||||
m_on_ident.emplace(std::make_pair(type, cb));
|
||||
}
|
||||
|
||||
void EQ::Net::ServertalkServer::OnConnectionRemoved(const std::string &type, std::function<void(std::shared_ptr<ServertalkServerConnection>)> cb)
|
||||
{
|
||||
m_on_disc.insert(std::make_pair(type, cb));
|
||||
m_on_disc.emplace(std::make_pair(type, cb));
|
||||
}
|
||||
|
||||
void EQ::Net::ServertalkServer::ConnectionDisconnected(ServertalkServerConnection *conn)
|
||||
@@ -75,7 +75,7 @@ void EQ::Net::ServertalkServer::ConnectionIdentified(ServertalkServerConnection
|
||||
else {
|
||||
std::vector<std::shared_ptr<EQ::Net::ServertalkServerConnection>> vec;
|
||||
vec.push_back(*iter);
|
||||
m_ident_connections.insert(std::make_pair(conn->GetIdentifier(), vec));
|
||||
m_ident_connections.emplace(std::make_pair(conn->GetIdentifier(), vec));
|
||||
}
|
||||
|
||||
m_unident_connections.erase(iter);
|
||||
|
||||
@@ -100,7 +100,7 @@ void EQ::Net::ServertalkServerConnection::SendPacket(ServerPacket *p)
|
||||
|
||||
void EQ::Net::ServertalkServerConnection::OnMessage(uint16_t opcode, std::function<void(uint16_t, EQ::Net::Packet&)> cb)
|
||||
{
|
||||
m_message_callbacks.insert(std::make_pair(opcode, cb));
|
||||
m_message_callbacks.emplace(std::make_pair(opcode, cb));
|
||||
}
|
||||
|
||||
void EQ::Net::ServertalkServerConnection::OnMessage(std::function<void(uint16_t, EQ::Net::Packet&)> cb)
|
||||
|
||||
@@ -142,7 +142,7 @@ void EQ::Net::TCPConnection::Write(const char *data, size_t count)
|
||||
|
||||
WriteBaton *baton = new WriteBaton;
|
||||
baton->connection = this;
|
||||
baton->buffer = new char[count];;
|
||||
baton->buffer = new char[count];
|
||||
|
||||
uv_write_t *write_req = new uv_write_t;
|
||||
memset(write_req, 0, sizeof(uv_write_t));
|
||||
|
||||
+135
-89
@@ -34,6 +34,7 @@
|
||||
#include "../rulesys.h"
|
||||
#include "../path_manager.h"
|
||||
#include "../races.h"
|
||||
#include "../raid.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
@@ -2608,88 +2609,124 @@ namespace RoF
|
||||
|
||||
ENCODE(OP_RaidJoin)
|
||||
{
|
||||
EQApplicationPacket *inapp = *p;
|
||||
unsigned char * __emu_buffer = inapp->pBuffer;
|
||||
RaidCreate_Struct *raid_create = (RaidCreate_Struct*)__emu_buffer;
|
||||
EQApplicationPacket* inapp = *p;
|
||||
*p = nullptr;
|
||||
unsigned char* __emu_buffer = inapp->pBuffer;
|
||||
RaidCreate_Struct* emu = (RaidCreate_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
|
||||
structs::RaidGeneral_Struct *general = (structs::RaidGeneral_Struct*)outapp_create->pBuffer;
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
|
||||
structs::RaidGeneral_Struct* general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
|
||||
|
||||
general->action = 8;
|
||||
general->parameter = 1;
|
||||
strn0cpy(general->leader_name, raid_create->leader_name, 64);
|
||||
strn0cpy(general->player_name, raid_create->leader_name, 64);
|
||||
general->action = raidCreate;
|
||||
general->parameter = RaidCommandAcceptInvite;
|
||||
strn0cpy(general->leader_name, emu->leader_name, sizeof(emu->leader_name));
|
||||
strn0cpy(general->player_name, emu->leader_name, sizeof(emu->leader_name));
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
|
||||
dest->FastQueuePacket(&outapp_create);
|
||||
safe_delete(inapp);
|
||||
|
||||
}
|
||||
|
||||
ENCODE(OP_RaidUpdate)
|
||||
{
|
||||
EQApplicationPacket *inapp = *p;
|
||||
EQApplicationPacket* inapp = *p;
|
||||
*p = nullptr;
|
||||
unsigned char * __emu_buffer = inapp->pBuffer;
|
||||
RaidGeneral_Struct *raid_gen = (RaidGeneral_Struct*)__emu_buffer;
|
||||
unsigned char* __emu_buffer = inapp->pBuffer;
|
||||
RaidGeneral_Struct* raid_gen = (RaidGeneral_Struct*)__emu_buffer;
|
||||
|
||||
if (raid_gen->action == 0) // raid add has longer length than other raid updates
|
||||
switch (raid_gen->action)
|
||||
{
|
||||
RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer;
|
||||
case raidAdd:
|
||||
{
|
||||
RaidAddMember_Struct* emu = (RaidAddMember_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct));
|
||||
structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer;
|
||||
structs::RaidAddMember_Struct* eq = (structs::RaidAddMember_Struct*)outapp->pBuffer;
|
||||
|
||||
add_member->raidGen.action = in_add_member->raidGen.action;
|
||||
add_member->raidGen.parameter = in_add_member->raidGen.parameter;
|
||||
strn0cpy(add_member->raidGen.leader_name, in_add_member->raidGen.leader_name, 64);
|
||||
strn0cpy(add_member->raidGen.player_name, in_add_member->raidGen.player_name, 64);
|
||||
add_member->_class = in_add_member->_class;
|
||||
add_member->level = in_add_member->level;
|
||||
add_member->isGroupLeader = in_add_member->isGroupLeader;
|
||||
add_member->flags[0] = in_add_member->flags[0];
|
||||
add_member->flags[1] = in_add_member->flags[1];
|
||||
add_member->flags[2] = in_add_member->flags[2];
|
||||
add_member->flags[3] = in_add_member->flags[3];
|
||||
add_member->flags[4] = in_add_member->flags[4];
|
||||
dest->FastQueuePacket(&outapp);
|
||||
}
|
||||
else if (raid_gen->action == 35)
|
||||
{
|
||||
RaidMOTD_Struct *inmotd = (RaidMOTD_Struct *)__emu_buffer;
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) +
|
||||
strlen(inmotd->motd) + 1);
|
||||
structs::RaidMOTD_Struct *outmotd = (structs::RaidMOTD_Struct *)outapp->pBuffer;
|
||||
OUT(raidGen.action);
|
||||
OUT(raidGen.parameter);
|
||||
OUT_str(raidGen.leader_name);
|
||||
OUT_str(raidGen.player_name);
|
||||
OUT(_class);
|
||||
OUT(level);
|
||||
OUT(isGroupLeader);
|
||||
OUT(flags[0]);
|
||||
OUT(flags[1]);
|
||||
OUT(flags[2]);
|
||||
OUT(flags[3]);
|
||||
OUT(flags[4]);
|
||||
|
||||
outmotd->general.action = inmotd->general.action;
|
||||
strn0cpy(outmotd->general.player_name, inmotd->general.player_name, 64);
|
||||
strn0cpy(outmotd->motd, inmotd->motd, strlen(inmotd->motd) + 1);
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
else if (raid_gen->action == 14 || raid_gen->action == 30)
|
||||
case raidSetMotd:
|
||||
{
|
||||
RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer;
|
||||
auto outapp =
|
||||
new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
|
||||
structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer;
|
||||
RaidMOTD_Struct* emu = (RaidMOTD_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct));
|
||||
structs::RaidMOTD_Struct* eq = (structs::RaidMOTD_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(general.action);
|
||||
OUT_str(general.player_name);
|
||||
OUT_str(general.leader_name);
|
||||
OUT_str(motd);
|
||||
|
||||
outlaa->action = inlaa->action;
|
||||
strn0cpy(outlaa->player_name, inlaa->player_name, 64);
|
||||
strn0cpy(outlaa->leader_name, inlaa->leader_name, 64);
|
||||
memcpy(&outlaa->raid, &inlaa->raid, sizeof(RaidLeadershipAA_Struct));
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
else
|
||||
case raidSetLeaderAbilities:
|
||||
case raidMakeLeader:
|
||||
{
|
||||
RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer;
|
||||
RaidLeadershipUpdate_Struct* emu = (RaidLeadershipUpdate_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
|
||||
structs::RaidLeadershipUpdate_Struct* eq = (structs::RaidLeadershipUpdate_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(action);
|
||||
OUT_str(player_name);
|
||||
OUT_str(leader_name);
|
||||
memcpy(&eq->raid, &emu->raid, sizeof(RaidLeadershipAA_Struct));
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
case raidSetNote:
|
||||
{
|
||||
auto emu = (RaidNote_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidNote_Struct));
|
||||
auto eq = (structs::RaidNote_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(general.action);
|
||||
OUT_str(general.leader_name);
|
||||
OUT_str(general.player_name);
|
||||
OUT_str(note);
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
case raidNoRaid:
|
||||
{
|
||||
dest->QueuePacket(inapp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
RaidGeneral_Struct* emu = (RaidGeneral_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
|
||||
structs::RaidGeneral_Struct *raid_general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
|
||||
strn0cpy(raid_general->leader_name, in_raid_general->leader_name, 64);
|
||||
strn0cpy(raid_general->player_name, in_raid_general->player_name, 64);
|
||||
raid_general->action = in_raid_general->action;
|
||||
raid_general->parameter = in_raid_general->parameter;
|
||||
dest->FastQueuePacket(&outapp);
|
||||
}
|
||||
structs::RaidGeneral_Struct* eq = (structs::RaidGeneral_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(action);
|
||||
OUT(parameter);
|
||||
OUT_str(leader_name);
|
||||
OUT_str(player_name);
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
safe_delete(inapp);
|
||||
}
|
||||
|
||||
@@ -4861,37 +4898,47 @@ namespace RoF
|
||||
{
|
||||
DECODE_LENGTH_ATLEAST(structs::RaidGeneral_Struct);
|
||||
|
||||
// This is a switch on the RaidGeneral action
|
||||
switch (*(uint32 *)__packet->pBuffer) {
|
||||
case 35: { // raidMOTD
|
||||
// we don't have a nice macro for this
|
||||
structs::RaidMOTD_Struct *__eq_buffer = (structs::RaidMOTD_Struct *)__packet->pBuffer;
|
||||
__eq_buffer->motd[1023] = '\0';
|
||||
size_t motd_size = strlen(__eq_buffer->motd) + 1;
|
||||
__packet->size = sizeof(RaidMOTD_Struct) + motd_size;
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
RaidMOTD_Struct *emu = (RaidMOTD_Struct *)__packet->pBuffer;
|
||||
structs::RaidMOTD_Struct *eq = (structs::RaidMOTD_Struct *)__eq_buffer;
|
||||
strn0cpy(emu->general.player_name, eq->general.player_name, 64);
|
||||
strn0cpy(emu->motd, eq->motd, motd_size);
|
||||
IN(general.action);
|
||||
IN(general.parameter);
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case 36: { // raidPlayerNote unhandled
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
DECODE_LENGTH_EXACT(structs::RaidGeneral_Struct);
|
||||
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
|
||||
strn0cpy(emu->leader_name, eq->leader_name, 64);
|
||||
strn0cpy(emu->player_name, eq->player_name, 64);
|
||||
IN(action);
|
||||
IN(parameter);
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
RaidGeneral_Struct* rgs = (RaidGeneral_Struct*)__packet->pBuffer;
|
||||
|
||||
switch (rgs->action)
|
||||
{
|
||||
case raidSetMotd:
|
||||
{
|
||||
SETUP_VAR_DECODE(RaidMOTD_Struct, structs::RaidMOTD_Struct, motd);
|
||||
|
||||
IN(general.action);
|
||||
IN(general.parameter);
|
||||
IN_str(general.leader_name);
|
||||
IN_str(general.player_name);
|
||||
IN_str(motd);
|
||||
|
||||
FINISH_VAR_DECODE();
|
||||
break;
|
||||
}
|
||||
case raidSetNote:
|
||||
{
|
||||
SETUP_VAR_DECODE(RaidNote_Struct, structs::RaidNote_Struct, note);
|
||||
|
||||
IN(general.action);
|
||||
IN(general.parameter);
|
||||
IN_str(general.leader_name);
|
||||
IN_str(general.player_name);
|
||||
IN_str(note);
|
||||
|
||||
FINISH_VAR_DECODE();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
|
||||
IN(action);
|
||||
IN(parameter);
|
||||
IN_str(leader_name);
|
||||
IN_str(player_name);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5218,7 +5265,6 @@ namespace RoF
|
||||
/**
|
||||
* Ornamentation
|
||||
*/
|
||||
int ornamentation_augment_type = RuleI(Character, OrnamentationAugmentType);
|
||||
uint32 ornamentation_icon = (inst->GetOrnamentationIcon() ? inst->GetOrnamentationIcon() : 0);
|
||||
uint32 hero_model = 0;
|
||||
|
||||
|
||||
+152
-92
@@ -35,6 +35,7 @@
|
||||
#include "../path_manager.h"
|
||||
#include "../classes.h"
|
||||
#include "../races.h"
|
||||
#include "../raid.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
@@ -2677,88 +2678,124 @@ namespace RoF2
|
||||
|
||||
ENCODE(OP_RaidJoin)
|
||||
{
|
||||
EQApplicationPacket *inapp = *p;
|
||||
unsigned char * __emu_buffer = inapp->pBuffer;
|
||||
RaidCreate_Struct *raid_create = (RaidCreate_Struct*)__emu_buffer;
|
||||
EQApplicationPacket* inapp = *p;
|
||||
*p = nullptr;
|
||||
unsigned char* __emu_buffer = inapp->pBuffer;
|
||||
RaidCreate_Struct* emu = (RaidCreate_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
|
||||
structs::RaidGeneral_Struct *general = (structs::RaidGeneral_Struct*)outapp_create->pBuffer;
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
|
||||
structs::RaidGeneral_Struct* general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
|
||||
|
||||
general->action = 8;
|
||||
general->parameter = 1;
|
||||
strn0cpy(general->leader_name, raid_create->leader_name, 64);
|
||||
strn0cpy(general->player_name, raid_create->leader_name, 64);
|
||||
general->action = raidCreate;
|
||||
general->parameter = RaidCommandAcceptInvite;
|
||||
strn0cpy(general->leader_name, emu->leader_name, sizeof(emu->leader_name));
|
||||
strn0cpy(general->player_name, emu->leader_name, sizeof(emu->leader_name));
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
|
||||
dest->FastQueuePacket(&outapp_create);
|
||||
safe_delete(inapp);
|
||||
|
||||
}
|
||||
|
||||
ENCODE(OP_RaidUpdate)
|
||||
{
|
||||
EQApplicationPacket *inapp = *p;
|
||||
EQApplicationPacket* inapp = *p;
|
||||
*p = nullptr;
|
||||
unsigned char * __emu_buffer = inapp->pBuffer;
|
||||
RaidGeneral_Struct *raid_gen = (RaidGeneral_Struct*)__emu_buffer;
|
||||
unsigned char* __emu_buffer = inapp->pBuffer;
|
||||
RaidGeneral_Struct* raid_gen = (RaidGeneral_Struct*)__emu_buffer;
|
||||
|
||||
if (raid_gen->action == 0) // raid add has longer length than other raid updates
|
||||
switch (raid_gen->action)
|
||||
{
|
||||
RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer;
|
||||
case raidAdd:
|
||||
{
|
||||
RaidAddMember_Struct* emu = (RaidAddMember_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct));
|
||||
structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer;
|
||||
structs::RaidAddMember_Struct* eq = (structs::RaidAddMember_Struct*)outapp->pBuffer;
|
||||
|
||||
add_member->raidGen.action = in_add_member->raidGen.action;
|
||||
add_member->raidGen.parameter = in_add_member->raidGen.parameter;
|
||||
strn0cpy(add_member->raidGen.leader_name, in_add_member->raidGen.leader_name, 64);
|
||||
strn0cpy(add_member->raidGen.player_name, in_add_member->raidGen.player_name, 64);
|
||||
add_member->_class = in_add_member->_class;
|
||||
add_member->level = in_add_member->level;
|
||||
add_member->isGroupLeader = in_add_member->isGroupLeader;
|
||||
add_member->flags[0] = in_add_member->flags[0];
|
||||
add_member->flags[1] = in_add_member->flags[1];
|
||||
add_member->flags[2] = in_add_member->flags[2];
|
||||
add_member->flags[3] = in_add_member->flags[3];
|
||||
add_member->flags[4] = in_add_member->flags[4];
|
||||
dest->FastQueuePacket(&outapp);
|
||||
}
|
||||
else if (raid_gen->action == 35)
|
||||
{
|
||||
RaidMOTD_Struct *inmotd = (RaidMOTD_Struct *)__emu_buffer;
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) +
|
||||
strlen(inmotd->motd) + 1);
|
||||
structs::RaidMOTD_Struct *outmotd = (structs::RaidMOTD_Struct *)outapp->pBuffer;
|
||||
OUT(raidGen.action);
|
||||
OUT(raidGen.parameter);
|
||||
OUT_str(raidGen.leader_name);
|
||||
OUT_str(raidGen.player_name);
|
||||
OUT(_class);
|
||||
OUT(level);
|
||||
OUT(isGroupLeader);
|
||||
OUT(flags[0]);
|
||||
OUT(flags[1]);
|
||||
OUT(flags[2]);
|
||||
OUT(flags[3]);
|
||||
OUT(flags[4]);
|
||||
|
||||
outmotd->general.action = inmotd->general.action;
|
||||
strn0cpy(outmotd->general.player_name, inmotd->general.player_name, 64);
|
||||
strn0cpy(outmotd->motd, inmotd->motd, strlen(inmotd->motd) + 1);
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
else if (raid_gen->action == 14 || raid_gen->action == 30)
|
||||
case raidSetMotd:
|
||||
{
|
||||
RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer;
|
||||
auto outapp =
|
||||
new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
|
||||
structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer;
|
||||
RaidMOTD_Struct* emu = (RaidMOTD_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct));
|
||||
structs::RaidMOTD_Struct* eq = (structs::RaidMOTD_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(general.action);
|
||||
OUT_str(general.player_name);
|
||||
OUT_str(general.leader_name);
|
||||
OUT_str(motd);
|
||||
|
||||
outlaa->action = inlaa->action;
|
||||
strn0cpy(outlaa->player_name, inlaa->player_name, 64);
|
||||
strn0cpy(outlaa->leader_name, inlaa->leader_name, 64);
|
||||
memcpy(&outlaa->raid, &inlaa->raid, sizeof(RaidLeadershipAA_Struct));
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
else
|
||||
case raidSetLeaderAbilities:
|
||||
case raidMakeLeader:
|
||||
{
|
||||
RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer;
|
||||
RaidLeadershipUpdate_Struct* emu = (RaidLeadershipUpdate_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
|
||||
structs::RaidLeadershipUpdate_Struct* eq = (structs::RaidLeadershipUpdate_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(action);
|
||||
OUT_str(player_name);
|
||||
OUT_str(leader_name);
|
||||
memcpy(&eq->raid, &emu->raid, sizeof(RaidLeadershipAA_Struct));
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
case raidSetNote:
|
||||
{
|
||||
auto emu = (RaidNote_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidNote_Struct));
|
||||
auto eq = (structs::RaidNote_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(general.action);
|
||||
OUT_str(general.leader_name);
|
||||
OUT_str(general.player_name);
|
||||
OUT_str(note);
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
case raidNoRaid:
|
||||
{
|
||||
dest->QueuePacket(inapp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
RaidGeneral_Struct* emu = (RaidGeneral_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
|
||||
structs::RaidGeneral_Struct *raid_general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
|
||||
strn0cpy(raid_general->leader_name, in_raid_general->leader_name, 64);
|
||||
strn0cpy(raid_general->player_name, in_raid_general->player_name, 64);
|
||||
raid_general->action = in_raid_general->action;
|
||||
raid_general->parameter = in_raid_general->parameter;
|
||||
dest->FastQueuePacket(&outapp);
|
||||
}
|
||||
structs::RaidGeneral_Struct* eq = (structs::RaidGeneral_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(action);
|
||||
OUT(parameter);
|
||||
OUT_str(leader_name);
|
||||
OUT_str(player_name);
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
safe_delete(inapp);
|
||||
}
|
||||
|
||||
@@ -2772,7 +2809,10 @@ namespace RoF2
|
||||
else
|
||||
eq->window = emu->window;
|
||||
OUT(type);
|
||||
OUT(invslot);
|
||||
eq->invslot = ServerToRoF2TypelessSlot(emu->invslot, invtype::typePossessions);
|
||||
OUT(target_id);
|
||||
OUT(can_cast);
|
||||
OUT(can_scribe);
|
||||
strn0cpy(eq->txtfile, emu->booktext, sizeof(eq->txtfile));
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -4398,6 +4438,17 @@ namespace RoF2
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_BookButton)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::BookButton_Struct);
|
||||
SETUP_DIRECT_DECODE(BookButton_Struct, structs::BookButton_Struct);
|
||||
|
||||
emu->invslot = static_cast<int16_t>(RoF2ToServerTypelessSlot(eq->slot, invtype::typePossessions));
|
||||
IN(target_id);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_Buff)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::SpellBuffPacket_Struct);
|
||||
@@ -5064,37 +5115,47 @@ namespace RoF2
|
||||
{
|
||||
DECODE_LENGTH_ATLEAST(structs::RaidGeneral_Struct);
|
||||
|
||||
// This is a switch on the RaidGeneral action
|
||||
switch (*(uint32 *)__packet->pBuffer) {
|
||||
case 35: { // raidMOTD
|
||||
// we don't have a nice macro for this
|
||||
structs::RaidMOTD_Struct *__eq_buffer = (structs::RaidMOTD_Struct *)__packet->pBuffer;
|
||||
__eq_buffer->motd[1023] = '\0';
|
||||
size_t motd_size = strlen(__eq_buffer->motd) + 1;
|
||||
__packet->size = sizeof(RaidMOTD_Struct) + motd_size;
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
RaidMOTD_Struct *emu = (RaidMOTD_Struct *)__packet->pBuffer;
|
||||
structs::RaidMOTD_Struct *eq = (structs::RaidMOTD_Struct *)__eq_buffer;
|
||||
strn0cpy(emu->general.player_name, eq->general.player_name, 64);
|
||||
strn0cpy(emu->motd, eq->motd, motd_size);
|
||||
IN(general.action);
|
||||
IN(general.parameter);
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case 36: { // raidPlayerNote unhandled
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
DECODE_LENGTH_EXACT(structs::RaidGeneral_Struct);
|
||||
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
|
||||
strn0cpy(emu->leader_name, eq->leader_name, 64);
|
||||
strn0cpy(emu->player_name, eq->player_name, 64);
|
||||
IN(action);
|
||||
IN(parameter);
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
RaidGeneral_Struct* rgs = (RaidGeneral_Struct*)__packet->pBuffer;
|
||||
|
||||
switch (rgs->action)
|
||||
{
|
||||
case raidSetMotd:
|
||||
{
|
||||
SETUP_VAR_DECODE(RaidMOTD_Struct, structs::RaidMOTD_Struct, motd);
|
||||
|
||||
IN(general.action);
|
||||
IN(general.parameter);
|
||||
IN_str(general.leader_name);
|
||||
IN_str(general.player_name);
|
||||
IN_str(motd);
|
||||
|
||||
FINISH_VAR_DECODE();
|
||||
break;
|
||||
}
|
||||
case raidSetNote:
|
||||
{
|
||||
SETUP_VAR_DECODE(RaidNote_Struct, structs::RaidNote_Struct, note);
|
||||
|
||||
IN(general.action);
|
||||
IN(general.parameter);
|
||||
IN_str(general.leader_name);
|
||||
IN_str(general.player_name);
|
||||
IN_str(note);
|
||||
|
||||
FINISH_VAR_DECODE();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
|
||||
IN(action);
|
||||
IN(parameter);
|
||||
IN_str(leader_name);
|
||||
IN_str(player_name);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5104,8 +5165,8 @@ namespace RoF2
|
||||
SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct);
|
||||
|
||||
IN(type);
|
||||
IN(invslot);
|
||||
IN(subslot);
|
||||
emu->invslot = static_cast<int16_t>(RoF2ToServerTypelessSlot(eq->invslot, invtype::typePossessions));
|
||||
IN(target_id);
|
||||
emu->window = (uint8)eq->window;
|
||||
strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile));
|
||||
|
||||
@@ -5477,7 +5538,6 @@ namespace RoF2
|
||||
/**
|
||||
* Ornamentation
|
||||
*/
|
||||
int ornamentation_augment_type = RuleI(Character, OrnamentationAugmentType);
|
||||
uint32 ornamentation_icon = (inst->GetOrnamentationIcon() ? inst->GetOrnamentationIcon() : 0);
|
||||
uint32 hero_model = 0;
|
||||
|
||||
|
||||
@@ -150,6 +150,7 @@ D(OP_AugmentInfo)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_BazaarSearch)
|
||||
D(OP_BlockedBuffs)
|
||||
D(OP_BookButton)
|
||||
D(OP_Buff)
|
||||
D(OP_BuffRemoveRequest)
|
||||
D(OP_CastSpell)
|
||||
|
||||
@@ -2868,15 +2868,23 @@ struct BookText_Struct {
|
||||
// This is just a "text file" on the server
|
||||
// or in our case, the 'name' column in our books table.
|
||||
struct BookRequest_Struct {
|
||||
/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window).
|
||||
/*0004*/ uint16 invslot; // Is the slot, but the RoF2 conversion causes it to fail. Turned to 0 since it isnt required anyway.
|
||||
/*0006*/ int16 subslot; // Inventory sub-slot (0-x)
|
||||
/*0008*/ uint16 unknown006; // Seen FFFF
|
||||
/*0010*/ uint16 unknown008; // seen 0000
|
||||
/*0012*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others
|
||||
/*0016*/ uint32 unknown0012;
|
||||
/*0020*/ uint16 unknown0016;
|
||||
/*0022*/ char txtfile[8194];
|
||||
/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window).
|
||||
/*0004*/ TypelessInventorySlot_Struct invslot; // book ItemIndex (with int16_t alignment padding)
|
||||
/*0012*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others
|
||||
/*0016*/ uint32 target_id; // client's target when using the book
|
||||
/*0020*/ uint8 can_cast; // show Cast Spell button in book window
|
||||
/*0021*/ uint8 can_scribe; // show Scribe button in book window
|
||||
/*0022*/ char txtfile[8194];
|
||||
/*8216*/
|
||||
};
|
||||
|
||||
// used by Scribe and CastSpell book buttons
|
||||
struct BookButton_Struct
|
||||
{
|
||||
/*0000*/ TypelessInventorySlot_Struct slot; // book ItemIndex (with int16_t alignment padding)
|
||||
/*0008*/ int32 target_id; // client's target when using the book button
|
||||
/*0012*/ int32 unused; // always 0 from button packets
|
||||
/*0016*/
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -4190,9 +4198,14 @@ struct RaidAddMember_Struct {
|
||||
/*139*/ uint8 flags[5]; //no idea if these are needed...
|
||||
};
|
||||
|
||||
struct RaidNote_Struct {
|
||||
/*000*/ RaidGeneral_Struct general;
|
||||
/*140*/ char note[64];
|
||||
};
|
||||
|
||||
struct RaidMOTD_Struct {
|
||||
/*000*/ RaidGeneral_Struct general; // leader_name and action only used
|
||||
/*140*/ char motd[0]; // max size 1024, but reply is variable
|
||||
/*000*/ RaidGeneral_Struct general;
|
||||
/*140*/ char motd[1024];
|
||||
};
|
||||
|
||||
struct RaidLeadershipUpdate_Struct {
|
||||
|
||||
@@ -4136,9 +4136,14 @@ struct RaidAddMember_Struct {
|
||||
/*139*/ uint8 flags[5]; //no idea if these are needed...
|
||||
};
|
||||
|
||||
struct RaidNote_Struct {
|
||||
/*000*/ RaidGeneral_Struct general;
|
||||
/*140*/ char note[64];
|
||||
};
|
||||
|
||||
struct RaidMOTD_Struct {
|
||||
/*000*/ RaidGeneral_Struct general; // leader_name and action only used
|
||||
/*140*/ char motd[0]; // max size 1024, but reply is variable
|
||||
/*140*/ char motd[1024]; // max size is 1024, but reply is variable
|
||||
};
|
||||
|
||||
struct RaidLeadershipUpdate_Struct {
|
||||
|
||||
+151
-89
@@ -34,6 +34,7 @@
|
||||
#include "../rulesys.h"
|
||||
#include "../path_manager.h"
|
||||
#include "../races.h"
|
||||
#include "../raid.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
@@ -1686,88 +1687,124 @@ namespace SoD
|
||||
|
||||
ENCODE(OP_RaidJoin)
|
||||
{
|
||||
EQApplicationPacket *inapp = *p;
|
||||
unsigned char * __emu_buffer = inapp->pBuffer;
|
||||
RaidCreate_Struct *raid_create = (RaidCreate_Struct*)__emu_buffer;
|
||||
EQApplicationPacket* inapp = *p;
|
||||
*p = nullptr;
|
||||
unsigned char* __emu_buffer = inapp->pBuffer;
|
||||
RaidCreate_Struct* emu = (RaidCreate_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
|
||||
structs::RaidGeneral_Struct *general = (structs::RaidGeneral_Struct*)outapp_create->pBuffer;
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
|
||||
structs::RaidGeneral_Struct* general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
|
||||
|
||||
general->action = 8;
|
||||
general->parameter = 1;
|
||||
strn0cpy(general->leader_name, raid_create->leader_name, 64);
|
||||
strn0cpy(general->player_name, raid_create->leader_name, 64);
|
||||
general->action = raidCreate;
|
||||
general->parameter = RaidCommandAcceptInvite;
|
||||
strn0cpy(general->leader_name, emu->leader_name, sizeof(emu->leader_name));
|
||||
strn0cpy(general->player_name, emu->leader_name, sizeof(emu->leader_name));
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
|
||||
dest->FastQueuePacket(&outapp_create);
|
||||
safe_delete(inapp);
|
||||
|
||||
}
|
||||
|
||||
ENCODE(OP_RaidUpdate)
|
||||
{
|
||||
EQApplicationPacket *inapp = *p;
|
||||
EQApplicationPacket* inapp = *p;
|
||||
*p = nullptr;
|
||||
unsigned char * __emu_buffer = inapp->pBuffer;
|
||||
RaidGeneral_Struct *raid_gen = (RaidGeneral_Struct*)__emu_buffer;
|
||||
unsigned char* __emu_buffer = inapp->pBuffer;
|
||||
RaidGeneral_Struct* raid_gen = (RaidGeneral_Struct*)__emu_buffer;
|
||||
|
||||
if (raid_gen->action == 0) // raid add has longer length than other raid updates
|
||||
switch (raid_gen->action)
|
||||
{
|
||||
RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer;
|
||||
case raidAdd:
|
||||
{
|
||||
RaidAddMember_Struct* emu = (RaidAddMember_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct));
|
||||
structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer;
|
||||
structs::RaidAddMember_Struct* eq = (structs::RaidAddMember_Struct*)outapp->pBuffer;
|
||||
|
||||
add_member->raidGen.action = in_add_member->raidGen.action;
|
||||
add_member->raidGen.parameter = in_add_member->raidGen.parameter;
|
||||
strn0cpy(add_member->raidGen.leader_name, in_add_member->raidGen.leader_name, 64);
|
||||
strn0cpy(add_member->raidGen.player_name, in_add_member->raidGen.player_name, 64);
|
||||
add_member->_class = in_add_member->_class;
|
||||
add_member->level = in_add_member->level;
|
||||
add_member->isGroupLeader = in_add_member->isGroupLeader;
|
||||
add_member->flags[0] = in_add_member->flags[0];
|
||||
add_member->flags[1] = in_add_member->flags[1];
|
||||
add_member->flags[2] = in_add_member->flags[2];
|
||||
add_member->flags[3] = in_add_member->flags[3];
|
||||
add_member->flags[4] = in_add_member->flags[4];
|
||||
dest->FastQueuePacket(&outapp);
|
||||
}
|
||||
else if (raid_gen->action == 35)
|
||||
{
|
||||
RaidMOTD_Struct *inmotd = (RaidMOTD_Struct *)__emu_buffer;
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) +
|
||||
strlen(inmotd->motd) + 1);
|
||||
structs::RaidMOTD_Struct *outmotd = (structs::RaidMOTD_Struct *)outapp->pBuffer;
|
||||
OUT(raidGen.action);
|
||||
OUT(raidGen.parameter);
|
||||
OUT_str(raidGen.leader_name);
|
||||
OUT_str(raidGen.player_name);
|
||||
OUT(_class);
|
||||
OUT(level);
|
||||
OUT(isGroupLeader);
|
||||
OUT(flags[0]);
|
||||
OUT(flags[1]);
|
||||
OUT(flags[2]);
|
||||
OUT(flags[3]);
|
||||
OUT(flags[4]);
|
||||
|
||||
outmotd->general.action = inmotd->general.action;
|
||||
strn0cpy(outmotd->general.player_name, inmotd->general.player_name, 64);
|
||||
strn0cpy(outmotd->motd, inmotd->motd, strlen(inmotd->motd) + 1);
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
else if (raid_gen->action == 14 || raid_gen->action == 30)
|
||||
case raidSetMotd:
|
||||
{
|
||||
RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer;
|
||||
auto outapp =
|
||||
new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
|
||||
structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer;
|
||||
RaidMOTD_Struct* emu = (RaidMOTD_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct));
|
||||
structs::RaidMOTD_Struct* eq = (structs::RaidMOTD_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(general.action);
|
||||
OUT_str(general.player_name);
|
||||
OUT_str(general.leader_name);
|
||||
OUT_str(motd);
|
||||
|
||||
outlaa->action = inlaa->action;
|
||||
strn0cpy(outlaa->player_name, inlaa->player_name, 64);
|
||||
strn0cpy(outlaa->leader_name, inlaa->leader_name, 64);
|
||||
memcpy(&outlaa->raid, &inlaa->raid, sizeof(RaidLeadershipAA_Struct));
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
else
|
||||
case raidSetLeaderAbilities:
|
||||
case raidMakeLeader:
|
||||
{
|
||||
RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer;
|
||||
RaidLeadershipUpdate_Struct* emu = (RaidLeadershipUpdate_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
|
||||
structs::RaidLeadershipUpdate_Struct* eq = (structs::RaidLeadershipUpdate_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(action);
|
||||
OUT_str(player_name);
|
||||
OUT_str(leader_name);
|
||||
memcpy(&eq->raid, &emu->raid, sizeof(RaidLeadershipAA_Struct));
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
case raidSetNote:
|
||||
{
|
||||
auto emu = (RaidNote_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidNote_Struct));
|
||||
auto eq = (structs::RaidNote_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(general.action);
|
||||
OUT_str(general.leader_name);
|
||||
OUT_str(general.player_name);
|
||||
OUT_str(note);
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
case raidNoRaid:
|
||||
{
|
||||
dest->QueuePacket(inapp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
RaidGeneral_Struct* emu = (RaidGeneral_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
|
||||
structs::RaidGeneral_Struct *raid_general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
|
||||
strn0cpy(raid_general->leader_name, in_raid_general->leader_name, 64);
|
||||
strn0cpy(raid_general->player_name, in_raid_general->player_name, 64);
|
||||
raid_general->action = in_raid_general->action;
|
||||
raid_general->parameter = in_raid_general->parameter;
|
||||
dest->FastQueuePacket(&outapp);
|
||||
}
|
||||
structs::RaidGeneral_Struct* eq = (structs::RaidGeneral_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(action);
|
||||
OUT(parameter);
|
||||
OUT_str(leader_name);
|
||||
OUT_str(player_name);
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
safe_delete(inapp);
|
||||
}
|
||||
|
||||
@@ -1782,6 +1819,9 @@ namespace SoD
|
||||
eq->window = emu->window;
|
||||
OUT(type);
|
||||
eq->invslot = ServerToSoDSlot(emu->invslot);
|
||||
OUT(target_id);
|
||||
OUT(can_cast);
|
||||
OUT(can_scribe);
|
||||
strn0cpy(eq->txtfile, emu->booktext, sizeof(eq->txtfile));
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -2817,6 +2857,17 @@ namespace SoD
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_BookButton)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::BookButton_Struct);
|
||||
SETUP_DIRECT_DECODE(BookButton_Struct, structs::BookButton_Struct);
|
||||
|
||||
emu->invslot = static_cast<int16_t>(SoDToServerSlot(eq->invslot));
|
||||
IN(target_id);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_Buff)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::SpellBuffPacket_Struct);
|
||||
@@ -3324,37 +3375,47 @@ namespace SoD
|
||||
{
|
||||
DECODE_LENGTH_ATLEAST(structs::RaidGeneral_Struct);
|
||||
|
||||
// This is a switch on the RaidGeneral action
|
||||
switch (*(uint32 *)__packet->pBuffer) {
|
||||
case 35: { // raidMOTD
|
||||
// we don't have a nice macro for this
|
||||
structs::RaidMOTD_Struct *__eq_buffer = (structs::RaidMOTD_Struct *)__packet->pBuffer;
|
||||
__eq_buffer->motd[1023] = '\0';
|
||||
size_t motd_size = strlen(__eq_buffer->motd) + 1;
|
||||
__packet->size = sizeof(RaidMOTD_Struct) + motd_size;
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
RaidMOTD_Struct *emu = (RaidMOTD_Struct *)__packet->pBuffer;
|
||||
structs::RaidMOTD_Struct *eq = (structs::RaidMOTD_Struct *)__eq_buffer;
|
||||
strn0cpy(emu->general.player_name, eq->general.player_name, 64);
|
||||
strn0cpy(emu->motd, eq->motd, motd_size);
|
||||
IN(general.action);
|
||||
IN(general.parameter);
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case 36: { // raidPlayerNote unhandled
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
DECODE_LENGTH_EXACT(structs::RaidGeneral_Struct);
|
||||
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
|
||||
strn0cpy(emu->leader_name, eq->leader_name, 64);
|
||||
strn0cpy(emu->player_name, eq->player_name, 64);
|
||||
IN(action);
|
||||
IN(parameter);
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
RaidGeneral_Struct* rgs = (RaidGeneral_Struct*)__packet->pBuffer;
|
||||
|
||||
switch (rgs->action)
|
||||
{
|
||||
case raidSetMotd:
|
||||
{
|
||||
SETUP_VAR_DECODE(RaidMOTD_Struct, structs::RaidMOTD_Struct, motd);
|
||||
|
||||
IN(general.action);
|
||||
IN(general.parameter);
|
||||
IN_str(general.leader_name);
|
||||
IN_str(general.player_name);
|
||||
IN_str(motd);
|
||||
|
||||
FINISH_VAR_DECODE();
|
||||
break;
|
||||
}
|
||||
case raidSetNote:
|
||||
{
|
||||
SETUP_VAR_DECODE(RaidNote_Struct, structs::RaidNote_Struct, note);
|
||||
|
||||
IN(general.action);
|
||||
IN(general.parameter);
|
||||
IN_str(general.leader_name);
|
||||
IN_str(general.player_name);
|
||||
IN_str(note);
|
||||
|
||||
FINISH_VAR_DECODE();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
|
||||
IN(action);
|
||||
IN(parameter);
|
||||
IN_str(leader_name);
|
||||
IN_str(player_name);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3364,7 +3425,8 @@ namespace SoD
|
||||
SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct);
|
||||
|
||||
IN(type);
|
||||
emu->invslot = SoDToServerSlot(eq->invslot);
|
||||
emu->invslot = static_cast<int16_t>(SoDToServerSlot(eq->invslot));
|
||||
IN(target_id);
|
||||
emu->window = (uint8)eq->window;
|
||||
strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile));
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ D(OP_ApplyPoison)
|
||||
D(OP_AugmentInfo)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_BazaarSearch)
|
||||
D(OP_BookButton)
|
||||
D(OP_Buff)
|
||||
D(OP_CastSpell)
|
||||
D(OP_ChannelMessage)
|
||||
|
||||
@@ -2351,12 +2351,21 @@ struct BookText_Struct {
|
||||
// This is just a "text file" on the server
|
||||
// or in our case, the 'name' column in our books table.
|
||||
struct BookRequest_Struct {
|
||||
/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window).
|
||||
/*0004*/ uint32 invslot; // The inventory slot the book is in. Not used, but echoed in the response packet.
|
||||
/*0008*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others
|
||||
/*0012*/ uint32 unknown0012;
|
||||
/*0016*/ uint16 unknown0016;
|
||||
/*0018*/ char txtfile[8194];
|
||||
/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window).
|
||||
/*0004*/ uint32 invslot; // The inventory slot the book is in
|
||||
/*0008*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others
|
||||
/*0012*/ uint32 target_id;
|
||||
/*0016*/ uint8 can_cast;
|
||||
/*0017*/ uint8 can_scribe;
|
||||
/*0018*/ char txtfile[8194];
|
||||
};
|
||||
|
||||
// used by Scribe and CastSpell book buttons
|
||||
struct BookButton_Struct
|
||||
{
|
||||
/*0000*/ int32 invslot;
|
||||
/*0004*/ int32 target_id; // client's target when using the book
|
||||
/*0008*/ int32 unused; // always 0 from button packets
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -3583,9 +3592,14 @@ struct RaidAddMember_Struct {
|
||||
/*139*/ uint8 flags[5]; //no idea if these are needed...
|
||||
};
|
||||
|
||||
struct RaidNote_Struct {
|
||||
/*000*/ RaidGeneral_Struct general;
|
||||
/*140*/ char note[64];
|
||||
};
|
||||
|
||||
struct RaidMOTD_Struct {
|
||||
/*000*/ RaidGeneral_Struct general; // leader_name and action only used
|
||||
/*140*/ char motd[0]; // max size 1024, but reply is variable
|
||||
/*140*/ char motd[1024]; // max size is 1024, but reply is variable
|
||||
};
|
||||
|
||||
struct RaidLeadershipUpdate_Struct {
|
||||
|
||||
+151
-89
@@ -33,6 +33,7 @@
|
||||
#include "sof_structs.h"
|
||||
#include "../rulesys.h"
|
||||
#include "../path_manager.h"
|
||||
#include "../raid.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
@@ -1356,88 +1357,124 @@ namespace SoF
|
||||
|
||||
ENCODE(OP_RaidJoin)
|
||||
{
|
||||
EQApplicationPacket *inapp = *p;
|
||||
unsigned char * __emu_buffer = inapp->pBuffer;
|
||||
RaidCreate_Struct *raid_create = (RaidCreate_Struct*)__emu_buffer;
|
||||
EQApplicationPacket* inapp = *p;
|
||||
*p = nullptr;
|
||||
unsigned char* __emu_buffer = inapp->pBuffer;
|
||||
RaidCreate_Struct* emu = (RaidCreate_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
|
||||
structs::RaidGeneral_Struct *general = (structs::RaidGeneral_Struct*)outapp_create->pBuffer;
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
|
||||
structs::RaidGeneral_Struct* general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
|
||||
|
||||
general->action = 8;
|
||||
general->parameter = 1;
|
||||
strn0cpy(general->leader_name, raid_create->leader_name, 64);
|
||||
strn0cpy(general->player_name, raid_create->leader_name, 64);
|
||||
general->action = raidCreate;
|
||||
general->parameter = RaidCommandAcceptInvite;
|
||||
strn0cpy(general->leader_name, emu->leader_name, sizeof(emu->leader_name));
|
||||
strn0cpy(general->player_name, emu->leader_name, sizeof(emu->leader_name));
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
|
||||
dest->FastQueuePacket(&outapp_create);
|
||||
safe_delete(inapp);
|
||||
|
||||
}
|
||||
|
||||
ENCODE(OP_RaidUpdate)
|
||||
{
|
||||
EQApplicationPacket *inapp = *p;
|
||||
EQApplicationPacket* inapp = *p;
|
||||
*p = nullptr;
|
||||
unsigned char * __emu_buffer = inapp->pBuffer;
|
||||
RaidGeneral_Struct *raid_gen = (RaidGeneral_Struct*)__emu_buffer;
|
||||
unsigned char* __emu_buffer = inapp->pBuffer;
|
||||
RaidGeneral_Struct* raid_gen = (RaidGeneral_Struct*)__emu_buffer;
|
||||
|
||||
if (raid_gen->action == 0) // raid add has longer length than other raid updates
|
||||
switch (raid_gen->action)
|
||||
{
|
||||
RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer;
|
||||
case raidAdd:
|
||||
{
|
||||
RaidAddMember_Struct* emu = (RaidAddMember_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct));
|
||||
structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer;
|
||||
structs::RaidAddMember_Struct* eq = (structs::RaidAddMember_Struct*)outapp->pBuffer;
|
||||
|
||||
add_member->raidGen.action = in_add_member->raidGen.action;
|
||||
add_member->raidGen.parameter = in_add_member->raidGen.parameter;
|
||||
strn0cpy(add_member->raidGen.leader_name, in_add_member->raidGen.leader_name, 64);
|
||||
strn0cpy(add_member->raidGen.player_name, in_add_member->raidGen.player_name, 64);
|
||||
add_member->_class = in_add_member->_class;
|
||||
add_member->level = in_add_member->level;
|
||||
add_member->isGroupLeader = in_add_member->isGroupLeader;
|
||||
add_member->flags[0] = in_add_member->flags[0];
|
||||
add_member->flags[1] = in_add_member->flags[1];
|
||||
add_member->flags[2] = in_add_member->flags[2];
|
||||
add_member->flags[3] = in_add_member->flags[3];
|
||||
add_member->flags[4] = in_add_member->flags[4];
|
||||
dest->FastQueuePacket(&outapp);
|
||||
}
|
||||
else if (raid_gen->action == 35)
|
||||
{
|
||||
RaidMOTD_Struct *inmotd = (RaidMOTD_Struct *)__emu_buffer;
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) +
|
||||
strlen(inmotd->motd) + 1);
|
||||
structs::RaidMOTD_Struct *outmotd = (structs::RaidMOTD_Struct *)outapp->pBuffer;
|
||||
OUT(raidGen.action);
|
||||
OUT(raidGen.parameter);
|
||||
OUT_str(raidGen.leader_name);
|
||||
OUT_str(raidGen.player_name);
|
||||
OUT(_class);
|
||||
OUT(level);
|
||||
OUT(isGroupLeader);
|
||||
OUT(flags[0]);
|
||||
OUT(flags[1]);
|
||||
OUT(flags[2]);
|
||||
OUT(flags[3]);
|
||||
OUT(flags[4]);
|
||||
|
||||
outmotd->general.action = inmotd->general.action;
|
||||
strn0cpy(outmotd->general.player_name, inmotd->general.player_name, 64);
|
||||
strn0cpy(outmotd->motd, inmotd->motd, strlen(inmotd->motd) + 1);
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
else if (raid_gen->action == 14 || raid_gen->action == 30)
|
||||
case raidSetMotd:
|
||||
{
|
||||
RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer;
|
||||
auto outapp =
|
||||
new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
|
||||
structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer;
|
||||
RaidMOTD_Struct* emu = (RaidMOTD_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct));
|
||||
structs::RaidMOTD_Struct* eq = (structs::RaidMOTD_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(general.action);
|
||||
OUT_str(general.player_name);
|
||||
OUT_str(general.leader_name);
|
||||
OUT_str(motd);
|
||||
|
||||
outlaa->action = inlaa->action;
|
||||
strn0cpy(outlaa->player_name, inlaa->player_name, 64);
|
||||
strn0cpy(outlaa->leader_name, inlaa->leader_name, 64);
|
||||
memcpy(&outlaa->raid, &inlaa->raid, sizeof(RaidLeadershipAA_Struct));
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
else
|
||||
case raidSetLeaderAbilities:
|
||||
case raidMakeLeader:
|
||||
{
|
||||
RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer;
|
||||
RaidLeadershipUpdate_Struct* emu = (RaidLeadershipUpdate_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
|
||||
structs::RaidLeadershipUpdate_Struct* eq = (structs::RaidLeadershipUpdate_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(action);
|
||||
OUT_str(player_name);
|
||||
OUT_str(leader_name);
|
||||
memcpy(&eq->raid, &emu->raid, sizeof(RaidLeadershipAA_Struct));
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
case raidSetNote:
|
||||
{
|
||||
auto emu = (RaidNote_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidNote_Struct));
|
||||
auto eq = (structs::RaidNote_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(general.action);
|
||||
OUT_str(general.leader_name);
|
||||
OUT_str(general.player_name);
|
||||
OUT_str(note);
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
case raidNoRaid:
|
||||
{
|
||||
dest->QueuePacket(inapp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
RaidGeneral_Struct* emu = (RaidGeneral_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
|
||||
structs::RaidGeneral_Struct *raid_general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
|
||||
strn0cpy(raid_general->leader_name, in_raid_general->leader_name, 64);
|
||||
strn0cpy(raid_general->player_name, in_raid_general->player_name, 64);
|
||||
raid_general->action = in_raid_general->action;
|
||||
raid_general->parameter = in_raid_general->parameter;
|
||||
dest->FastQueuePacket(&outapp);
|
||||
}
|
||||
structs::RaidGeneral_Struct* eq = (structs::RaidGeneral_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(action);
|
||||
OUT(parameter);
|
||||
OUT_str(leader_name);
|
||||
OUT_str(player_name);
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
safe_delete(inapp);
|
||||
}
|
||||
|
||||
@@ -1452,6 +1489,9 @@ namespace SoF
|
||||
eq->window = emu->window;
|
||||
OUT(type);
|
||||
eq->invslot = ServerToSoFSlot(emu->invslot);
|
||||
OUT(target_id);
|
||||
OUT(can_cast);
|
||||
OUT(can_scribe);
|
||||
strn0cpy(eq->txtfile, emu->booktext, sizeof(eq->txtfile));
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -2261,6 +2301,17 @@ namespace SoF
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_BookButton)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::BookButton_Struct);
|
||||
SETUP_DIRECT_DECODE(BookButton_Struct, structs::BookButton_Struct);
|
||||
|
||||
emu->invslot = static_cast<int16_t>(SoFToServerSlot(eq->invslot));
|
||||
IN(target_id);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_Buff)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::SpellBuffPacket_Struct);
|
||||
@@ -2729,37 +2780,47 @@ namespace SoF
|
||||
{
|
||||
DECODE_LENGTH_ATLEAST(structs::RaidGeneral_Struct);
|
||||
|
||||
// This is a switch on the RaidGeneral action
|
||||
switch (*(uint32 *)__packet->pBuffer) {
|
||||
case 35: { // raidMOTD
|
||||
// we don't have a nice macro for this
|
||||
structs::RaidMOTD_Struct *__eq_buffer = (structs::RaidMOTD_Struct *)__packet->pBuffer;
|
||||
__eq_buffer->motd[1023] = '\0';
|
||||
size_t motd_size = strlen(__eq_buffer->motd) + 1;
|
||||
__packet->size = sizeof(RaidMOTD_Struct) + motd_size;
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
RaidMOTD_Struct *emu = (RaidMOTD_Struct *)__packet->pBuffer;
|
||||
structs::RaidMOTD_Struct *eq = (structs::RaidMOTD_Struct *)__eq_buffer;
|
||||
strn0cpy(emu->general.player_name, eq->general.player_name, 64);
|
||||
strn0cpy(emu->motd, eq->motd, motd_size);
|
||||
IN(general.action);
|
||||
IN(general.parameter);
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case 36: { // raidPlayerNote unhandled
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
DECODE_LENGTH_EXACT(structs::RaidGeneral_Struct);
|
||||
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
|
||||
strn0cpy(emu->leader_name, eq->leader_name, 64);
|
||||
strn0cpy(emu->player_name, eq->player_name, 64);
|
||||
IN(action);
|
||||
IN(parameter);
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
RaidGeneral_Struct* rgs = (RaidGeneral_Struct*)__packet->pBuffer;
|
||||
|
||||
switch (rgs->action)
|
||||
{
|
||||
case raidSetMotd:
|
||||
{
|
||||
SETUP_VAR_DECODE(RaidMOTD_Struct, structs::RaidMOTD_Struct, motd);
|
||||
|
||||
IN(general.action);
|
||||
IN(general.parameter);
|
||||
IN_str(general.leader_name);
|
||||
IN_str(general.player_name);
|
||||
IN_str(motd);
|
||||
|
||||
FINISH_VAR_DECODE();
|
||||
break;
|
||||
}
|
||||
case raidSetNote:
|
||||
{
|
||||
SETUP_VAR_DECODE(RaidNote_Struct, structs::RaidNote_Struct, note);
|
||||
|
||||
IN(general.action);
|
||||
IN(general.parameter);
|
||||
IN_str(general.leader_name);
|
||||
IN_str(general.player_name);
|
||||
IN_str(note);
|
||||
|
||||
FINISH_VAR_DECODE();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
|
||||
IN(action);
|
||||
IN(parameter);
|
||||
IN_str(leader_name);
|
||||
IN_str(player_name);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2769,7 +2830,8 @@ namespace SoF
|
||||
SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct);
|
||||
|
||||
IN(type);
|
||||
emu->invslot = SoFToServerSlot(eq->invslot);
|
||||
emu->invslot = static_cast<int16_t>(SoFToServerSlot(eq->invslot));
|
||||
IN(target_id);
|
||||
emu->window = (uint8)eq->window;
|
||||
strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile));
|
||||
|
||||
|
||||
@@ -94,6 +94,7 @@ D(OP_AltCurrencySellSelection)
|
||||
D(OP_ApplyPoison)
|
||||
D(OP_AugmentInfo)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_BookButton)
|
||||
D(OP_Buff)
|
||||
D(OP_Bug)
|
||||
D(OP_CastSpell)
|
||||
|
||||
@@ -2321,12 +2321,21 @@ struct BookText_Struct {
|
||||
// This is just a "text file" on the server
|
||||
// or in our case, the 'name' column in our books table.
|
||||
struct BookRequest_Struct {
|
||||
/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window).
|
||||
/*0004*/ uint32 invslot; // The inventory slot the book is in. Not used, but echoed in the response packet.
|
||||
/*0008*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others
|
||||
/*0012*/ uint32 unknown0012;
|
||||
/*0016*/ uint16 unknown0016;
|
||||
/*0018*/ char txtfile[8194];
|
||||
/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window).
|
||||
/*0004*/ uint32 invslot; // The inventory slot the book is in
|
||||
/*0008*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others
|
||||
/*0012*/ uint32 target_id;
|
||||
/*0016*/ uint8 can_cast;
|
||||
/*0017*/ uint8 can_scribe;
|
||||
/*0018*/ char txtfile[8194];
|
||||
};
|
||||
|
||||
// used by Scribe and CastSpell book buttons
|
||||
struct BookButton_Struct
|
||||
{
|
||||
/*0000*/ int32 invslot;
|
||||
/*0004*/ int32 target_id; // client's target when using the book
|
||||
/*0008*/ int32 unused; // always 0 from button packets
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -3508,9 +3517,14 @@ struct RaidAddMember_Struct {
|
||||
/*139*/ uint8 flags[5]; //no idea if these are needed...
|
||||
};
|
||||
|
||||
struct RaidNote_Struct {
|
||||
/*000*/ RaidGeneral_Struct general;
|
||||
/*140*/ char note[64];
|
||||
};
|
||||
|
||||
struct RaidMOTD_Struct {
|
||||
/*000*/ RaidGeneral_Struct general; // leader_name and action only used
|
||||
/*140*/ char motd[0]; // max size 1024, but reply is variable
|
||||
/*140*/ char motd[1024]; // max size is 1024, but reply is variable
|
||||
};
|
||||
|
||||
struct RaidLeadershipUpdate_Struct {
|
||||
|
||||
@@ -128,6 +128,15 @@
|
||||
emu_struct *emu = (emu_struct *) __packet->pBuffer; \
|
||||
eq_struct *eq = (eq_struct *) __eq_buffer;
|
||||
|
||||
#define SETUP_VAR_DECODE(emu_struct, eq_struct, var_field) \
|
||||
unsigned char *__eq_buffer = __packet->pBuffer; \
|
||||
eq_struct* in = (eq_struct*)__packet->pBuffer; \
|
||||
auto size = strlen(in->var_field); \
|
||||
__packet->size = sizeof(emu_struct) + size + 1; \
|
||||
__packet->pBuffer = new unsigned char[__packet->size]; \
|
||||
emu_struct *emu = (emu_struct *) __packet->pBuffer; \
|
||||
eq_struct *eq = (eq_struct *) __eq_buffer;
|
||||
|
||||
#define MEMSET_IN(emu_struct) \
|
||||
memset(__packet->pBuffer, 0, sizeof(emu_struct));
|
||||
|
||||
@@ -146,6 +155,9 @@
|
||||
delete[] __eq_buffer; \
|
||||
p->SetOpcode(OP_Unknown);
|
||||
|
||||
#define FINISH_VAR_DECODE() \
|
||||
delete[] __eq_buffer;
|
||||
|
||||
//call to finish an encoder using SETUP_DIRECT_DECODE
|
||||
#define FINISH_DIRECT_DECODE() \
|
||||
delete[] __eq_buffer;
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "../item_instance.h"
|
||||
#include "titanium_structs.h"
|
||||
#include "../path_manager.h"
|
||||
#include "../raid.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
@@ -1245,6 +1246,119 @@ namespace Titanium
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_MarkRaidNPC)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(MarkNPC_Struct);
|
||||
SETUP_DIRECT_ENCODE(MarkNPC_Struct, MarkNPC_Struct);
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MarkNPC, sizeof(MarkNPC_Struct));
|
||||
MarkNPC_Struct* mnpcs = (MarkNPC_Struct*)outapp->pBuffer;
|
||||
mnpcs->TargetID = emu->TargetID;
|
||||
mnpcs->Number = emu->Number;
|
||||
dest->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_RaidUpdate)
|
||||
{
|
||||
EQApplicationPacket* inapp = *p;
|
||||
*p = nullptr;
|
||||
unsigned char* __emu_buffer = inapp->pBuffer;
|
||||
RaidGeneral_Struct* raid_gen = (RaidGeneral_Struct*)__emu_buffer;
|
||||
|
||||
switch (raid_gen->action)
|
||||
{
|
||||
case raidAdd:
|
||||
{
|
||||
RaidAddMember_Struct* emu = (RaidAddMember_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct));
|
||||
structs::RaidAddMember_Struct* eq = (structs::RaidAddMember_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(raidGen.action);
|
||||
OUT(raidGen.parameter);
|
||||
OUT_str(raidGen.leader_name);
|
||||
OUT_str(raidGen.player_name);
|
||||
OUT(_class);
|
||||
OUT(level);
|
||||
OUT(isGroupLeader);
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
|
||||
}
|
||||
case raidSetMotd:
|
||||
{
|
||||
RaidMOTD_Struct* emu = (RaidMOTD_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct));
|
||||
structs::RaidMOTD_Struct* eq = (structs::RaidMOTD_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(general.action);
|
||||
OUT_str(general.player_name);
|
||||
OUT_str(general.leader_name);
|
||||
OUT_str(motd);
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
case raidSetLeaderAbilities:
|
||||
case raidMakeLeader:
|
||||
{
|
||||
RaidLeadershipUpdate_Struct* emu = (RaidLeadershipUpdate_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
|
||||
structs::RaidLeadershipUpdate_Struct* eq = (structs::RaidLeadershipUpdate_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(action);
|
||||
OUT_str(player_name);
|
||||
OUT_str(leader_name);
|
||||
memcpy(&eq->raid, &emu->raid, sizeof(RaidLeadershipAA_Struct));
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
case raidSetNote:
|
||||
{
|
||||
auto emu = (RaidNote_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidNote_Struct));
|
||||
auto eq = (structs::RaidNote_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(general.action);
|
||||
OUT_str(general.leader_name);
|
||||
OUT_str(general.player_name);
|
||||
OUT_str(note);
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
case raidNoRaid:
|
||||
{
|
||||
dest->QueuePacket(inapp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
RaidGeneral_Struct* emu = (RaidGeneral_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
|
||||
structs::RaidGeneral_Struct* eq = (structs::RaidGeneral_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(action);
|
||||
OUT(parameter);
|
||||
OUT_str(leader_name);
|
||||
OUT_str(player_name);
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
safe_delete(inapp);
|
||||
}
|
||||
|
||||
ENCODE(OP_ReadBook)
|
||||
{
|
||||
// no apparent slot translation needed
|
||||
@@ -2272,6 +2386,63 @@ namespace Titanium
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_RaidInvite)
|
||||
{
|
||||
DECODE_LENGTH_ATLEAST(structs::RaidGeneral_Struct);
|
||||
RaidGeneral_Struct* rgs = (RaidGeneral_Struct*)__packet->pBuffer;
|
||||
|
||||
switch (rgs->action)
|
||||
{
|
||||
case raidSetMotd:
|
||||
{
|
||||
SETUP_VAR_DECODE(RaidMOTD_Struct, structs::RaidMOTD_Struct, motd);
|
||||
|
||||
IN(general.action);
|
||||
IN(general.parameter);
|
||||
IN_str(general.leader_name);
|
||||
IN_str(general.player_name);
|
||||
|
||||
auto len = 0;
|
||||
if (__packet->size < sizeof(structs::RaidMOTD_Struct)) {
|
||||
len = __packet->size - sizeof(structs::RaidGeneral_Struct);
|
||||
}
|
||||
else {
|
||||
len = sizeof(eq->motd);
|
||||
}
|
||||
|
||||
strn0cpy(emu->motd, eq->motd, len > 1024 ? 1024 : len);
|
||||
emu->motd[len - 1] = '\0';
|
||||
|
||||
FINISH_VAR_DECODE();
|
||||
break;
|
||||
}
|
||||
case raidSetNote:
|
||||
{
|
||||
SETUP_VAR_DECODE(RaidNote_Struct, structs::RaidNote_Struct, note);
|
||||
|
||||
IN(general.action);
|
||||
IN(general.parameter);
|
||||
IN_str(general.leader_name);
|
||||
IN_str(general.player_name);
|
||||
IN_str(note);
|
||||
|
||||
FINISH_VAR_DECODE();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
|
||||
IN(action);
|
||||
IN(parameter);
|
||||
IN_str(leader_name);
|
||||
IN_str(player_name);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DECODE(OP_ReadBook)
|
||||
{
|
||||
// no apparent slot translation needed
|
||||
|
||||
@@ -61,6 +61,8 @@ E(OP_OnLevelMessage)
|
||||
E(OP_PetBuffWindow)
|
||||
E(OP_PlayerProfile)
|
||||
E(OP_NewSpawn)
|
||||
E(OP_MarkRaidNPC)
|
||||
E(OP_RaidUpdate)
|
||||
E(OP_ReadBook)
|
||||
E(OP_RespondAA)
|
||||
E(OP_SendCharInfo)
|
||||
@@ -106,6 +108,7 @@ D(OP_LoadSpellSet)
|
||||
D(OP_LootItem)
|
||||
D(OP_MoveItem)
|
||||
D(OP_PetCommands)
|
||||
D(OP_RaidInvite)
|
||||
D(OP_ReadBook)
|
||||
D(OP_SetServerFilter)
|
||||
D(OP_ShopPlayerSell)
|
||||
|
||||
@@ -3017,23 +3017,39 @@ struct leadExpUpdateStruct {
|
||||
/*0028*/ uint32 unknown0028;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct RaidGeneral_Struct {
|
||||
/*00*/ uint32 action; //=10
|
||||
/*04*/ char player_name[64]; //should both be the player's name
|
||||
/*04*/ char leader_name[64];
|
||||
/*000*/ uint32 action; //=10
|
||||
/*004*/ char player_name[64]; //should both be the player's name
|
||||
/*068*/ char leader_name[64];
|
||||
/*132*/ uint32 parameter;
|
||||
};
|
||||
|
||||
struct RaidAdd_Struct {
|
||||
/*000*/ uint32 action; //=0
|
||||
/*004*/ char player_name[64]; //should both be the player's name
|
||||
/*068*/ char leader_name[64];
|
||||
/*132*/ uint8 _class;
|
||||
/*133*/ uint8 level;
|
||||
/*134*/ uint8 has_group;
|
||||
/*135*/ uint8 unknown135; //seems to be 0x42 or 0
|
||||
struct RaidAddMember_Struct {
|
||||
/*000*/ RaidGeneral_Struct raidGen;
|
||||
/*136*/ uint8 _class;
|
||||
/*137*/ uint8 level;
|
||||
/*138*/ uint8 isGroupLeader;
|
||||
/*139*/ uint8 unknown139; //seems to be 0x42 or 0
|
||||
};
|
||||
|
||||
struct RaidNote_Struct {
|
||||
/*000*/ RaidGeneral_Struct general;
|
||||
/*136*/ char note[64];
|
||||
};
|
||||
|
||||
struct RaidMOTD_Struct {
|
||||
/*000*/ RaidGeneral_Struct general; // leader_name and action only used
|
||||
/*136*/ char motd[1024]; // max size is 1024, but reply is variable
|
||||
};
|
||||
|
||||
struct RaidLeadershipUpdate_Struct {
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ char player_name[64];
|
||||
// /*068*/ uint32 Unknown068;
|
||||
/*072*/ char leader_name[64];
|
||||
/*136*/ GroupLeadershipAA_Struct group; //unneeded
|
||||
/*200*/ RaidLeadershipAA_Struct raid;
|
||||
/*264*/ char Unknown264[128];
|
||||
};
|
||||
|
||||
struct RaidCreate_Struct {
|
||||
|
||||
+160
-99
@@ -35,6 +35,7 @@
|
||||
#include "../path_manager.h"
|
||||
#include "../classes.h"
|
||||
#include "../races.h"
|
||||
#include "../raid.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
@@ -1931,88 +1932,124 @@ namespace UF
|
||||
|
||||
ENCODE(OP_RaidJoin)
|
||||
{
|
||||
EQApplicationPacket *inapp = *p;
|
||||
unsigned char * __emu_buffer = inapp->pBuffer;
|
||||
RaidCreate_Struct *raid_create = (RaidCreate_Struct*)__emu_buffer;
|
||||
EQApplicationPacket* inapp = *p;
|
||||
*p = nullptr;
|
||||
unsigned char* __emu_buffer = inapp->pBuffer;
|
||||
RaidCreate_Struct* emu = (RaidCreate_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
|
||||
structs::RaidGeneral_Struct *general = (structs::RaidGeneral_Struct*)outapp_create->pBuffer;
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
|
||||
structs::RaidGeneral_Struct* general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
|
||||
|
||||
general->action = 8;
|
||||
general->parameter = 1;
|
||||
strn0cpy(general->leader_name, raid_create->leader_name, 64);
|
||||
strn0cpy(general->player_name, raid_create->leader_name, 64);
|
||||
general->action = raidCreate;
|
||||
general->parameter = RaidCommandAcceptInvite;
|
||||
strn0cpy(general->leader_name, emu->leader_name, sizeof(emu->leader_name));
|
||||
strn0cpy(general->player_name, emu->leader_name, sizeof(emu->leader_name));
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
|
||||
dest->FastQueuePacket(&outapp_create);
|
||||
safe_delete(inapp);
|
||||
|
||||
}
|
||||
|
||||
ENCODE(OP_RaidUpdate)
|
||||
{
|
||||
EQApplicationPacket *inapp = *p;
|
||||
EQApplicationPacket* inapp = *p;
|
||||
*p = nullptr;
|
||||
unsigned char * __emu_buffer = inapp->pBuffer;
|
||||
RaidGeneral_Struct *raid_gen = (RaidGeneral_Struct*)__emu_buffer;
|
||||
unsigned char* __emu_buffer = inapp->pBuffer;
|
||||
RaidGeneral_Struct* raid_gen = (RaidGeneral_Struct*)__emu_buffer;
|
||||
|
||||
if (raid_gen->action == 0) // raid add has longer length than other raid updates
|
||||
switch (raid_gen->action)
|
||||
{
|
||||
RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer;
|
||||
case raidAdd:
|
||||
{
|
||||
RaidAddMember_Struct* emu = (RaidAddMember_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct));
|
||||
structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer;
|
||||
structs::RaidAddMember_Struct* eq = (structs::RaidAddMember_Struct*)outapp->pBuffer;
|
||||
|
||||
add_member->raidGen.action = in_add_member->raidGen.action;
|
||||
add_member->raidGen.parameter = in_add_member->raidGen.parameter;
|
||||
strn0cpy(add_member->raidGen.leader_name, in_add_member->raidGen.leader_name, 64);
|
||||
strn0cpy(add_member->raidGen.player_name, in_add_member->raidGen.player_name, 64);
|
||||
add_member->_class = in_add_member->_class;
|
||||
add_member->level = in_add_member->level;
|
||||
add_member->isGroupLeader = in_add_member->isGroupLeader;
|
||||
add_member->flags[0] = in_add_member->flags[0];
|
||||
add_member->flags[1] = in_add_member->flags[1];
|
||||
add_member->flags[2] = in_add_member->flags[2];
|
||||
add_member->flags[3] = in_add_member->flags[3];
|
||||
add_member->flags[4] = in_add_member->flags[4];
|
||||
dest->FastQueuePacket(&outapp);
|
||||
}
|
||||
else if (raid_gen->action == 35)
|
||||
{
|
||||
RaidMOTD_Struct *inmotd = (RaidMOTD_Struct *)__emu_buffer;
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) +
|
||||
strlen(inmotd->motd) + 1);
|
||||
structs::RaidMOTD_Struct *outmotd = (structs::RaidMOTD_Struct *)outapp->pBuffer;
|
||||
OUT(raidGen.action);
|
||||
OUT(raidGen.parameter);
|
||||
OUT_str(raidGen.leader_name);
|
||||
OUT_str(raidGen.player_name);
|
||||
OUT(_class);
|
||||
OUT(level);
|
||||
OUT(isGroupLeader);
|
||||
OUT(flags[0]);
|
||||
OUT(flags[1]);
|
||||
OUT(flags[2]);
|
||||
OUT(flags[3]);
|
||||
OUT(flags[4]);
|
||||
|
||||
outmotd->general.action = inmotd->general.action;
|
||||
strn0cpy(outmotd->general.player_name, inmotd->general.player_name, 64);
|
||||
strn0cpy(outmotd->motd, inmotd->motd, strlen(inmotd->motd) + 1);
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
else if (raid_gen->action == 14 || raid_gen->action == 30)
|
||||
case raidSetMotd:
|
||||
{
|
||||
RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer;
|
||||
auto outapp =
|
||||
new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
|
||||
structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer;
|
||||
RaidMOTD_Struct* emu = (RaidMOTD_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct));
|
||||
structs::RaidMOTD_Struct* eq = (structs::RaidMOTD_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(general.action);
|
||||
OUT_str(general.player_name);
|
||||
OUT_str(general.leader_name);
|
||||
OUT_str(motd);
|
||||
|
||||
outlaa->action = inlaa->action;
|
||||
strn0cpy(outlaa->player_name, inlaa->player_name, 64);
|
||||
strn0cpy(outlaa->leader_name, inlaa->leader_name, 64);
|
||||
memcpy(&outlaa->raid, &inlaa->raid, sizeof(RaidLeadershipAA_Struct));
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
else
|
||||
case raidSetLeaderAbilities:
|
||||
case raidMakeLeader:
|
||||
{
|
||||
RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer;
|
||||
RaidLeadershipUpdate_Struct* emu = (RaidLeadershipUpdate_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
|
||||
structs::RaidLeadershipUpdate_Struct* eq = (structs::RaidLeadershipUpdate_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(action);
|
||||
OUT_str(player_name);
|
||||
OUT_str(leader_name);
|
||||
memcpy(&eq->raid, &emu->raid, sizeof(RaidLeadershipAA_Struct));
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
case raidSetNote:
|
||||
{
|
||||
auto emu = (RaidNote_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidNote_Struct));
|
||||
auto eq = (structs::RaidNote_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(general.action);
|
||||
OUT_str(general.leader_name);
|
||||
OUT_str(general.player_name);
|
||||
OUT_str(note);
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
case raidNoRaid:
|
||||
{
|
||||
dest->QueuePacket(inapp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
RaidGeneral_Struct* emu = (RaidGeneral_Struct*)__emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
|
||||
structs::RaidGeneral_Struct *raid_general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
|
||||
strn0cpy(raid_general->leader_name, in_raid_general->leader_name, 64);
|
||||
strn0cpy(raid_general->player_name, in_raid_general->player_name, 64);
|
||||
raid_general->action = in_raid_general->action;
|
||||
raid_general->parameter = in_raid_general->parameter;
|
||||
dest->FastQueuePacket(&outapp);
|
||||
}
|
||||
structs::RaidGeneral_Struct* eq = (structs::RaidGeneral_Struct*)outapp->pBuffer;
|
||||
|
||||
OUT(action);
|
||||
OUT(parameter);
|
||||
OUT_str(leader_name);
|
||||
OUT_str(player_name);
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
safe_delete(inapp);
|
||||
}
|
||||
|
||||
@@ -2027,6 +2064,9 @@ namespace UF
|
||||
eq->window = emu->window;
|
||||
OUT(type);
|
||||
eq->invslot = ServerToUFSlot(emu->invslot);
|
||||
OUT(target_id);
|
||||
OUT(can_cast);
|
||||
OUT(can_scribe);
|
||||
strn0cpy(eq->txtfile, emu->booktext, sizeof(eq->txtfile));
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -3105,6 +3145,17 @@ namespace UF
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_BookButton)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::BookButton_Struct);
|
||||
SETUP_DIRECT_DECODE(BookButton_Struct, structs::BookButton_Struct);
|
||||
|
||||
emu->invslot = static_cast<int16_t>(UFToServerSlot(eq->invslot));
|
||||
IN(target_id);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_Buff)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::SpellBuffPacket_Struct);
|
||||
@@ -3623,39 +3674,48 @@ namespace UF
|
||||
{
|
||||
DECODE_LENGTH_ATLEAST(structs::RaidGeneral_Struct);
|
||||
|
||||
// This is a switch on the RaidGeneral action
|
||||
switch (*(uint32 *)__packet->pBuffer) {
|
||||
case 35: { // raidMOTD
|
||||
// we don't have a nice macro for this
|
||||
structs::RaidMOTD_Struct *__eq_buffer = (structs::RaidMOTD_Struct *)__packet->pBuffer;
|
||||
__eq_buffer->motd[1023] = '\0';
|
||||
size_t motd_size = strlen(__eq_buffer->motd) + 1;
|
||||
__packet->size = sizeof(RaidMOTD_Struct) + motd_size;
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
RaidMOTD_Struct *emu = (RaidMOTD_Struct *)__packet->pBuffer;
|
||||
structs::RaidMOTD_Struct *eq = (structs::RaidMOTD_Struct *)__eq_buffer;
|
||||
strn0cpy(emu->general.player_name, eq->general.player_name, 64);
|
||||
strn0cpy(emu->motd, eq->motd, motd_size);
|
||||
IN(general.action);
|
||||
IN(general.parameter);
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case 36: { // raidPlayerNote unhandled
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
DECODE_LENGTH_EXACT(structs::RaidGeneral_Struct);
|
||||
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
|
||||
strn0cpy(emu->leader_name, eq->leader_name, 64);
|
||||
strn0cpy(emu->player_name, eq->player_name, 64);
|
||||
IN(action);
|
||||
IN(parameter);
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
RaidGeneral_Struct* rgs = (RaidGeneral_Struct*)__packet->pBuffer;
|
||||
|
||||
switch (rgs->action)
|
||||
{
|
||||
case raidSetMotd:
|
||||
{
|
||||
SETUP_VAR_DECODE(RaidMOTD_Struct, structs::RaidMOTD_Struct, motd);
|
||||
|
||||
IN(general.action);
|
||||
IN(general.parameter);
|
||||
IN_str(general.leader_name);
|
||||
IN_str(general.player_name);
|
||||
IN_str(motd);
|
||||
|
||||
FINISH_VAR_DECODE();
|
||||
break;
|
||||
}
|
||||
case raidSetNote:
|
||||
{
|
||||
SETUP_VAR_DECODE(RaidNote_Struct, structs::RaidNote_Struct, note);
|
||||
|
||||
IN(general.action);
|
||||
IN(general.parameter);
|
||||
IN_str(general.leader_name);
|
||||
IN_str(general.player_name);
|
||||
IN_str(note);
|
||||
|
||||
FINISH_VAR_DECODE();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
|
||||
IN(action);
|
||||
IN(parameter);
|
||||
IN_str(leader_name);
|
||||
IN_str(player_name);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DECODE(OP_ReadBook)
|
||||
@@ -3664,7 +3724,8 @@ namespace UF
|
||||
SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct);
|
||||
|
||||
IN(type);
|
||||
emu->invslot = UFToServerSlot(eq->invslot);
|
||||
emu->invslot = static_cast<int16_t>(UFToServerSlot(eq->invslot));
|
||||
IN(target_id);
|
||||
emu->window = (uint8)eq->window;
|
||||
strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile));
|
||||
|
||||
@@ -3851,17 +3912,17 @@ namespace UF
|
||||
ob.write((const char*)&evotop, sizeof(UF::structs::EvolvingItem));
|
||||
}
|
||||
|
||||
//ORNAMENT IDFILE / ICON -
|
||||
int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType);
|
||||
uint16 ornaIcon = 0;
|
||||
if (inst->GetOrnamentationAug(ornamentationAugtype)) {
|
||||
const EQ::ItemData *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
|
||||
ornaIcon = aug_weap->Icon;
|
||||
uint16 ornament_icon = 0;
|
||||
const auto augment = inst->GetOrnamentationAugment();
|
||||
|
||||
ob.write(aug_weap->IDFile, strlen(aug_weap->IDFile));
|
||||
if (augment) {
|
||||
const auto augment_item = augment->GetItem();
|
||||
ornament_icon = augment_item->Icon;
|
||||
|
||||
ob.write(augment_item->IDFile, strlen(augment_item->IDFile));
|
||||
}
|
||||
else if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) {
|
||||
ornaIcon = inst->GetOrnamentationIcon();
|
||||
ornament_icon = inst->GetOrnamentationIcon();
|
||||
char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile());
|
||||
|
||||
ob.write(tmp, strlen(tmp));
|
||||
@@ -3870,7 +3931,7 @@ namespace UF
|
||||
|
||||
UF::structs::ItemSerializationHeaderFinish hdrf;
|
||||
|
||||
hdrf.ornamentIcon = ornaIcon;
|
||||
hdrf.ornamentIcon = ornament_icon;
|
||||
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'
|
||||
|
||||
@@ -110,6 +110,7 @@ D(OP_ApplyPoison)
|
||||
D(OP_AugmentInfo)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_BazaarSearch)
|
||||
D(OP_BookButton)
|
||||
D(OP_Buff)
|
||||
D(OP_BuffRemoveRequest)
|
||||
D(OP_CastSpell)
|
||||
|
||||
@@ -2400,12 +2400,21 @@ struct BookText_Struct {
|
||||
// This is just a "text file" on the server
|
||||
// or in our case, the 'name' column in our books table.
|
||||
struct BookRequest_Struct {
|
||||
/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window).
|
||||
/*0004*/ uint32 invslot; // The inventory slot the book is in. Not used, but echoed in the response packet.
|
||||
/*0008*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others
|
||||
/*0012*/ uint32 unknown0012;
|
||||
/*0016*/ uint16 unknown0016;
|
||||
/*0018*/ char txtfile[8194];
|
||||
/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window).
|
||||
/*0004*/ uint32 invslot; // The inventory slot the book is in
|
||||
/*0008*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others
|
||||
/*0012*/ uint32 target_id;
|
||||
/*0016*/ uint8 can_cast;
|
||||
/*0017*/ uint8 can_scribe;
|
||||
/*0018*/ char txtfile[8194];
|
||||
};
|
||||
|
||||
// used by Scribe and CastSpell book buttons
|
||||
struct BookButton_Struct
|
||||
{
|
||||
/*0000*/ int32 invslot;
|
||||
/*0004*/ int32 target_id; // client's target when using the book
|
||||
/*0008*/ int32 unused; // always 0 from button packets
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -3638,9 +3647,14 @@ struct RaidAddMember_Struct {
|
||||
/*139*/ uint8 flags[5]; //no idea if these are needed...
|
||||
};
|
||||
|
||||
struct RaidNote_Struct {
|
||||
/*000*/ RaidGeneral_Struct general;
|
||||
/*140*/ char note[64];
|
||||
};
|
||||
|
||||
struct RaidMOTD_Struct {
|
||||
/*000*/ RaidGeneral_Struct general; // leader_name and action only used
|
||||
/*140*/ char motd[0]; // max size 1024, but reply is variable
|
||||
/*000*/ RaidGeneral_Struct general;
|
||||
/*140*/ char motd[1024];
|
||||
};
|
||||
|
||||
struct RaidLeadershipUpdate_Struct {
|
||||
|
||||
@@ -64,7 +64,7 @@ void ProcLauncher::Process() {
|
||||
if(GetExitCodeProcess(cur->second->proc_info.hProcess, &res)) {
|
||||
//got exit code, see if its still running...
|
||||
if(res == STILL_ACTIVE) {
|
||||
cur++;
|
||||
++cur;
|
||||
continue;
|
||||
}
|
||||
//else, it died, handle properly
|
||||
@@ -76,7 +76,7 @@ void ProcLauncher::Process() {
|
||||
|
||||
//if we get here, the current process died.
|
||||
tmp = cur;
|
||||
tmp++;
|
||||
++tmp;
|
||||
ProcessTerminated(cur);
|
||||
cur = tmp;
|
||||
}
|
||||
@@ -174,7 +174,7 @@ ProcLauncher::ProcRef ProcLauncher::Launch(Spec *&to_launch) {
|
||||
std::vector<std::string>::iterator cur, end;
|
||||
cur = it->args.begin();
|
||||
end = it->args.end();
|
||||
for(; cur != end; cur++) {
|
||||
for(; cur != end; ++cur) {
|
||||
args += " ";
|
||||
args += *cur;
|
||||
}
|
||||
@@ -306,7 +306,7 @@ void ProcLauncher::TerminateAll(bool final) {
|
||||
std::map<ProcRef, Spec *>::iterator cur, end;
|
||||
cur = m_running.begin();
|
||||
end = m_running.end();
|
||||
for(; cur != end; cur++) {
|
||||
for(; cur != end; ++cur) {
|
||||
Terminate(cur->first, true);
|
||||
}
|
||||
} else {
|
||||
@@ -317,7 +317,7 @@ void ProcLauncher::TerminateAll(bool final) {
|
||||
std::map<ProcRef, Spec *>::iterator cur, end;
|
||||
cur = running.begin();
|
||||
end = running.end();
|
||||
for(; cur != end; cur++) {
|
||||
for(; cur != end; ++cur) {
|
||||
Terminate(cur->first, true);
|
||||
safe_delete(cur->second);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
|
||||
std::string Process::execute(const std::string &cmd)
|
||||
{
|
||||
std::shared_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);
|
||||
std::string command = fmt::format("{} 2>&1", cmd);
|
||||
std::shared_ptr<FILE> pipe(popen(command.c_str(), "r"), pclose);
|
||||
if (!pipe) { return "ERROR"; }
|
||||
char buffer[128];
|
||||
std::string result;
|
||||
|
||||
@@ -258,7 +258,7 @@ bool EQ::ProfanityManager::clear_database_entries(DBcore *db) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EQ::ProfanityManager::check_for_existing_entry(std::string profanity) {
|
||||
bool EQ::ProfanityManager::check_for_existing_entry(const std::string& profanity) {
|
||||
if (profanity.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace EQ
|
||||
private:
|
||||
static bool load_database_entries(DBcore *db);
|
||||
static bool clear_database_entries(DBcore *db);
|
||||
static bool check_for_existing_entry(std::string profanity);
|
||||
static bool check_for_existing_entry(const std::string& profanity);
|
||||
|
||||
};
|
||||
|
||||
|
||||
+64
-7
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#include "../common/races.h"
|
||||
#include "data_verification.h"
|
||||
|
||||
const char* GetRaceIDName(uint16 race_id)
|
||||
{
|
||||
@@ -67,7 +68,7 @@ const char* GetRaceIDName(uint16 race_id)
|
||||
// return "Froglok";
|
||||
//case DRAKKIN:
|
||||
// return "Drakkin";
|
||||
|
||||
|
||||
// RoF2 Race Labels
|
||||
case RT_ABHORRENT:
|
||||
return "Abhorrent";
|
||||
@@ -1593,11 +1594,13 @@ float GetRaceGenderDefaultHeight(int race, int gender)
|
||||
|
||||
const auto size = sizeof(male_height) / sizeof(male_height[0]);
|
||||
|
||||
if (race >= size)
|
||||
if (race >= size) {
|
||||
return 6.0f;
|
||||
}
|
||||
|
||||
if (gender == 1)
|
||||
if (gender == FEMALE) {
|
||||
return female_height[race];
|
||||
}
|
||||
|
||||
return male_height[race];
|
||||
}
|
||||
@@ -1696,7 +1699,7 @@ bool PlayerAppearance::IsValidBeardColor(uint16 race_id, uint8 gender_id, uint8
|
||||
{
|
||||
if (beard_color_value == 0xFF)
|
||||
return true;
|
||||
|
||||
|
||||
switch (BINDRG(race_id, gender_id)) {
|
||||
case GNOME_MALE:
|
||||
if (beard_color_value <= 24)
|
||||
@@ -1783,7 +1786,7 @@ bool PlayerAppearance::IsValidEyeColor(uint16 race_id, uint8 gender_id, uint8 ey
|
||||
case VAHSHIR_FEMALE:
|
||||
if (eye_color_value <= 9)
|
||||
return true;
|
||||
break;
|
||||
break;
|
||||
case TROLL_MALE:
|
||||
case TROLL_FEMALE:
|
||||
if (eye_color_value <= 10)
|
||||
@@ -2109,7 +2112,7 @@ bool PlayerAppearance::IsValidTexture(uint16 race_id, uint8 gender_id, uint8 tex
|
||||
{
|
||||
if (texture_value == 0xFF)
|
||||
return true;
|
||||
|
||||
|
||||
if (use_luclin) {
|
||||
switch (BINDRG(race_id, gender_id)) {
|
||||
case HUMAN_MALE:
|
||||
@@ -2243,4 +2246,58 @@ const char* GetGenderName(uint32 gender_id) {
|
||||
gender_name = "Neuter";
|
||||
}
|
||||
return gender_name;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string GetPlayerRaceAbbreviation(uint16 race_id)
|
||||
{
|
||||
if (!IsPlayerRace(race_id)) {
|
||||
return std::string("UNK");
|
||||
}
|
||||
|
||||
switch (race_id) {
|
||||
case RACE_HUMAN_1:
|
||||
return "HUM";
|
||||
case RACE_BARBARIAN_2:
|
||||
return "BAR";
|
||||
case RACE_ERUDITE_3:
|
||||
return "ERU";
|
||||
case RACE_WOOD_ELF_4:
|
||||
return "ELF";
|
||||
case RACE_HIGH_ELF_5:
|
||||
return "HIE";
|
||||
case RACE_DARK_ELF_6:
|
||||
return "DEF";
|
||||
case RACE_HALF_ELF_7:
|
||||
return "HEF";
|
||||
case RACE_DWARF_8:
|
||||
return "DWF";
|
||||
case RACE_TROLL_9:
|
||||
return "TRL";
|
||||
case RACE_OGRE_10:
|
||||
return "OGR";
|
||||
case RACE_HALFLING_11:
|
||||
return "HFL";
|
||||
case RACE_GNOME_12:
|
||||
return "GNM";
|
||||
case RACE_IKSAR_128:
|
||||
return "IKS";
|
||||
case RACE_VAH_SHIR_130:
|
||||
return "VAH";
|
||||
case RACE_FROGLOK_330:
|
||||
return "FRG";
|
||||
case RACE_DRAKKIN_522:
|
||||
return "DRK";
|
||||
}
|
||||
|
||||
return std::string("UNK");
|
||||
}
|
||||
|
||||
bool IsPlayerRace(uint16 race_id) {
|
||||
return (
|
||||
EQ::ValueWithin(race_id, RACE_HUMAN_1, RACE_GNOME_12) ||
|
||||
race_id == RACE_IKSAR_128 ||
|
||||
race_id == RACE_VAH_SHIR_130 ||
|
||||
race_id == RACE_FROGLOK_330 ||
|
||||
race_id == RACE_DRAKKIN_522
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#ifndef RACES_H
|
||||
#define RACES_H
|
||||
#include "../common/types.h"
|
||||
#include <string>
|
||||
|
||||
#define MALE 0
|
||||
#define FEMALE 1
|
||||
@@ -853,6 +854,9 @@ const char* GetRaceIDName(uint16 race_id);
|
||||
const char* GetPlayerRaceName(uint32 player_race_value);
|
||||
const char* GetGenderName(uint32 gender_id);
|
||||
|
||||
bool IsPlayerRace(uint16 race_id);
|
||||
const std::string GetPlayerRaceAbbreviation(uint16 race_id);
|
||||
|
||||
uint32 GetPlayerRaceValue(uint16 race_id);
|
||||
uint32 GetPlayerRaceBit(uint16 race_id);
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
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 RAID_H
|
||||
#define RAID_H
|
||||
|
||||
enum { //raid packet types:
|
||||
raidAdd = 0,
|
||||
raidRemove2 = 1, //parameter=0
|
||||
raidMemberNameChange = 2,
|
||||
raidRemove1 = 3, //parameter=0xFFFFFFFF
|
||||
raidNoLongerLeader = 4,
|
||||
raidDisband = 5,
|
||||
raidMembers = 6, //len 395+, details + members list
|
||||
raidNoAssignLeadership = 7,
|
||||
raidCreate = 8, //len 72
|
||||
raidUnknown = 9, // unused?
|
||||
raidNoRaid = 10, //parameter=0
|
||||
raidChangeLootType = 11,
|
||||
raidStringID = 12,
|
||||
raidChangeGroupLeader = 13, //136 raid leader, new group leader, group_id?
|
||||
raidSetLeaderAbilities = 14, //472
|
||||
raidSetLeaderData = 15, // 14,15 SoE names, not sure on difference, 14 packet has 0x100 bytes 15 0x214 in addition to raid general
|
||||
raidChangeGroup = 16, //?? len 136 old leader, new leader, 0 (preceeded with a remove2)
|
||||
raidLock = 17, //len 136 leader?, leader, 0
|
||||
raidUnlock = 18, //len 136 leader?, leader, 0
|
||||
raidRedStringID = 19,
|
||||
raidSetLeader = 20, //len 388, contains 'details' struct without members; also used for "invite to raid"
|
||||
raidMakeLeader = 30,
|
||||
raidSetMotd = 35,
|
||||
raidSetNote = 36,
|
||||
};
|
||||
|
||||
|
||||
enum { //raid command types
|
||||
RaidCommandInviteIntoExisting = 0, //in use
|
||||
RaidCommandAcceptInvite = 1, //in use
|
||||
RaidCommandInvite = 3, //in use
|
||||
RaidCommandDisband = 5, //in use
|
||||
RaidCommandMoveGroup = 6, //in use
|
||||
RaidCommandRemoveGroupLeader = 7,
|
||||
RaidCommandRaidLock = 8, //in use
|
||||
RaidCommandRaidUnlock = 9, //in use
|
||||
RaidCommandLootType = 20, //in use
|
||||
RaidCommandAddLooter = 21, //in use
|
||||
RaidCommandRemoveLooter = 22, //in use
|
||||
RaidCommandMakeLeader = 30,
|
||||
RaidCommandInviteFail = 31, //already in raid, waiting on invite from other raid, etc
|
||||
RaidCommandLootType2 = 32, //in use
|
||||
RaidCommandAddLooter2 = 33, //in use
|
||||
RaidCommandRemoveLooter2 = 34, //in use
|
||||
RaidCommandSetMotd = 35,
|
||||
RaidCommandSetNote = 36,
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -44,7 +44,35 @@ public:
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
static void ClearFlag(
|
||||
Database& db,
|
||||
AccountFlagsRepository::AccountFlags e
|
||||
) {
|
||||
AccountFlagsRepository::DeleteWhere(
|
||||
database,
|
||||
fmt::format(
|
||||
"p_accid = {} AND p_flag = '{}'",
|
||||
e.p_accid,
|
||||
Strings::Escape(e.p_flag)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static void ReplaceFlag(
|
||||
Database& db,
|
||||
AccountFlagsRepository::AccountFlags e
|
||||
) {
|
||||
db.QueryDatabase(
|
||||
fmt::format(
|
||||
"REPLACE INTO {} ({}) VALUES ({}, '{}', '{}')",
|
||||
TableName(),
|
||||
ColumnsRaw(),
|
||||
e.p_accid,
|
||||
Strings::Escape(e.p_flag),
|
||||
Strings::Escape(e.p_value)
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_ACCOUNT_FLAGS_REPOSITORY_H
|
||||
|
||||
@@ -0,0 +1,414 @@
|
||||
/**
|
||||
* DO NOT MODIFY THIS FILE
|
||||
*
|
||||
* This repository was automatically generated and is NOT to be modified directly.
|
||||
* Any repository modifications are meant to be made to the repository extending the base.
|
||||
* Any modifications to base repositories are to be made by the generator only
|
||||
*
|
||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_BASE_BOT_STARTING_ITEMS_REPOSITORY_H
|
||||
#define EQEMU_BASE_BOT_STARTING_ITEMS_REPOSITORY_H
|
||||
|
||||
#include "../../database.h"
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseBotStartingItemsRepository {
|
||||
public:
|
||||
struct BotStartingItems {
|
||||
uint32_t id;
|
||||
uint32_t races;
|
||||
uint32_t classes;
|
||||
uint32_t item_id;
|
||||
uint8_t item_charges;
|
||||
int32_t slot_id;
|
||||
int8_t min_expansion;
|
||||
int8_t max_expansion;
|
||||
std::string content_flags;
|
||||
std::string content_flags_disabled;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
{
|
||||
return std::string("id");
|
||||
}
|
||||
|
||||
static std::vector<std::string> Columns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"races",
|
||||
"classes",
|
||||
"item_id",
|
||||
"item_charges",
|
||||
"slot_id",
|
||||
"min_expansion",
|
||||
"max_expansion",
|
||||
"content_flags",
|
||||
"content_flags_disabled",
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::string> SelectColumns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"races",
|
||||
"classes",
|
||||
"item_id",
|
||||
"item_charges",
|
||||
"slot_id",
|
||||
"min_expansion",
|
||||
"max_expansion",
|
||||
"content_flags",
|
||||
"content_flags_disabled",
|
||||
};
|
||||
}
|
||||
|
||||
static std::string ColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", Columns()));
|
||||
}
|
||||
|
||||
static std::string SelectColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", SelectColumns()));
|
||||
}
|
||||
|
||||
static std::string TableName()
|
||||
{
|
||||
return std::string("bot_starting_items");
|
||||
}
|
||||
|
||||
static std::string BaseSelect()
|
||||
{
|
||||
return fmt::format(
|
||||
"SELECT {} FROM {}",
|
||||
SelectColumnsRaw(),
|
||||
TableName()
|
||||
);
|
||||
}
|
||||
|
||||
static std::string BaseInsert()
|
||||
{
|
||||
return fmt::format(
|
||||
"INSERT INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static BotStartingItems NewEntity()
|
||||
{
|
||||
BotStartingItems e{};
|
||||
|
||||
e.id = 0;
|
||||
e.races = 0;
|
||||
e.classes = 0;
|
||||
e.item_id = 0;
|
||||
e.item_charges = 1;
|
||||
e.slot_id = -1;
|
||||
e.min_expansion = -1;
|
||||
e.max_expansion = -1;
|
||||
e.content_flags = "";
|
||||
e.content_flags_disabled = "";
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static BotStartingItems GetBotStartingItems(
|
||||
const std::vector<BotStartingItems> &bot_starting_itemss,
|
||||
int bot_starting_items_id
|
||||
)
|
||||
{
|
||||
for (auto &bot_starting_items : bot_starting_itemss) {
|
||||
if (bot_starting_items.id == bot_starting_items_id) {
|
||||
return bot_starting_items;
|
||||
}
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static BotStartingItems FindOne(
|
||||
Database& db,
|
||||
int bot_starting_items_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
bot_starting_items_id
|
||||
)
|
||||
);
|
||||
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1) {
|
||||
BotStartingItems e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.races = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.classes = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
|
||||
e.item_id = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.item_charges = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
|
||||
e.slot_id = static_cast<int32_t>(atoi(row[5]));
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[6]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[7]));
|
||||
e.content_flags = row[8] ? row[8] : "";
|
||||
e.content_flags_disabled = row[9] ? row[9] : "";
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static int DeleteOne(
|
||||
Database& db,
|
||||
int bot_starting_items_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {} = {}",
|
||||
TableName(),
|
||||
PrimaryKey(),
|
||||
bot_starting_items_id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int UpdateOne(
|
||||
Database& db,
|
||||
const BotStartingItems &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.races));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.classes));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.item_id));
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.item_charges));
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.slot_id));
|
||||
v.push_back(columns[6] + " = " + std::to_string(e.min_expansion));
|
||||
v.push_back(columns[7] + " = " + std::to_string(e.max_expansion));
|
||||
v.push_back(columns[8] + " = '" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back(columns[9] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE {} SET {} WHERE {} = {}",
|
||||
TableName(),
|
||||
Strings::Implode(", ", v),
|
||||
PrimaryKey(),
|
||||
e.id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static BotStartingItems InsertOne(
|
||||
Database& db,
|
||||
BotStartingItems e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.races));
|
||||
v.push_back(std::to_string(e.classes));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.item_charges));
|
||||
v.push_back(std::to_string(e.slot_id));
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
if (results.Success()) {
|
||||
e.id = results.LastInsertedID();
|
||||
return e;
|
||||
}
|
||||
|
||||
e = NewEntity();
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static int InsertMany(
|
||||
Database& db,
|
||||
const std::vector<BotStartingItems> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.races));
|
||||
v.push_back(std::to_string(e.classes));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.item_charges));
|
||||
v.push_back(std::to_string(e.slot_id));
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static std::vector<BotStartingItems> All(Database& db)
|
||||
{
|
||||
std::vector<BotStartingItems> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{}",
|
||||
BaseSelect()
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
BotStartingItems e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.races = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.classes = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
|
||||
e.item_id = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.item_charges = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
|
||||
e.slot_id = static_cast<int32_t>(atoi(row[5]));
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[6]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[7]));
|
||||
e.content_flags = row[8] ? row[8] : "";
|
||||
e.content_flags_disabled = row[9] ? row[9] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static std::vector<BotStartingItems> GetWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
std::vector<BotStartingItems> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {}",
|
||||
BaseSelect(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
BotStartingItems e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.races = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.classes = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
|
||||
e.item_id = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.item_charges = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
|
||||
e.slot_id = static_cast<int32_t>(atoi(row[5]));
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[6]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[7]));
|
||||
e.content_flags = row[8] ? row[8] : "";
|
||||
e.content_flags_disabled = row[9] ? row[9] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static int DeleteWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {}",
|
||||
TableName(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int Truncate(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"TRUNCATE TABLE {}",
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int64 GetMaxId(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COALESCE(MAX({}), 0) FROM {}",
|
||||
PrimaryKey(),
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
static int64 Count(Database& db, const std::string &where_filter = "")
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COUNT(*) FROM {} {}",
|
||||
TableName(),
|
||||
(where_filter.empty() ? "" : "WHERE " + where_filter)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_BASE_BOT_STARTING_ITEMS_REPOSITORY_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,354 @@
|
||||
/**
|
||||
* DO NOT MODIFY THIS FILE
|
||||
*
|
||||
* This repository was automatically generated and is NOT to be modified directly.
|
||||
* Any repository modifications are meant to be made to the repository extending the base.
|
||||
* Any modifications to base repositories are to be made by the generator only
|
||||
*
|
||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_BASE_CHARACTER_TRIBUTE_REPOSITORY_H
|
||||
#define EQEMU_BASE_CHARACTER_TRIBUTE_REPOSITORY_H
|
||||
|
||||
#include "../../database.h"
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseCharacterTributeRepository {
|
||||
public:
|
||||
struct CharacterTribute {
|
||||
int32_t id;
|
||||
uint32_t character_id;
|
||||
uint8_t tier;
|
||||
uint32_t tribute;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
{
|
||||
return std::string("id");
|
||||
}
|
||||
|
||||
static std::vector<std::string> Columns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"character_id",
|
||||
"tier",
|
||||
"tribute",
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::string> SelectColumns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"character_id",
|
||||
"tier",
|
||||
"tribute",
|
||||
};
|
||||
}
|
||||
|
||||
static std::string ColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", Columns()));
|
||||
}
|
||||
|
||||
static std::string SelectColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", SelectColumns()));
|
||||
}
|
||||
|
||||
static std::string TableName()
|
||||
{
|
||||
return std::string("character_tribute");
|
||||
}
|
||||
|
||||
static std::string BaseSelect()
|
||||
{
|
||||
return fmt::format(
|
||||
"SELECT {} FROM {}",
|
||||
SelectColumnsRaw(),
|
||||
TableName()
|
||||
);
|
||||
}
|
||||
|
||||
static std::string BaseInsert()
|
||||
{
|
||||
return fmt::format(
|
||||
"INSERT INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static CharacterTribute NewEntity()
|
||||
{
|
||||
CharacterTribute e{};
|
||||
|
||||
e.id = 0;
|
||||
e.character_id = 0;
|
||||
e.tier = 0;
|
||||
e.tribute = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static CharacterTribute GetCharacterTribute(
|
||||
const std::vector<CharacterTribute> &character_tributes,
|
||||
int character_tribute_id
|
||||
)
|
||||
{
|
||||
for (auto &character_tribute : character_tributes) {
|
||||
if (character_tribute.id == character_tribute_id) {
|
||||
return character_tribute;
|
||||
}
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static CharacterTribute FindOne(
|
||||
Database& db,
|
||||
int character_tribute_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
character_tribute_id
|
||||
)
|
||||
);
|
||||
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1) {
|
||||
CharacterTribute e{};
|
||||
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.character_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.tier = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
|
||||
e.tribute = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static int DeleteOne(
|
||||
Database& db,
|
||||
int character_tribute_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {} = {}",
|
||||
TableName(),
|
||||
PrimaryKey(),
|
||||
character_tribute_id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int UpdateOne(
|
||||
Database& db,
|
||||
const CharacterTribute &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.character_id));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.tier));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.tribute));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE {} SET {} WHERE {} = {}",
|
||||
TableName(),
|
||||
Strings::Implode(", ", v),
|
||||
PrimaryKey(),
|
||||
e.id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static CharacterTribute InsertOne(
|
||||
Database& db,
|
||||
CharacterTribute e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.character_id));
|
||||
v.push_back(std::to_string(e.tier));
|
||||
v.push_back(std::to_string(e.tribute));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
if (results.Success()) {
|
||||
e.id = results.LastInsertedID();
|
||||
return e;
|
||||
}
|
||||
|
||||
e = NewEntity();
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static int InsertMany(
|
||||
Database& db,
|
||||
const std::vector<CharacterTribute> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.character_id));
|
||||
v.push_back(std::to_string(e.tier));
|
||||
v.push_back(std::to_string(e.tribute));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static std::vector<CharacterTribute> All(Database& db)
|
||||
{
|
||||
std::vector<CharacterTribute> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{}",
|
||||
BaseSelect()
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
CharacterTribute e{};
|
||||
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.character_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.tier = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
|
||||
e.tribute = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static std::vector<CharacterTribute> GetWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
std::vector<CharacterTribute> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {}",
|
||||
BaseSelect(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
CharacterTribute e{};
|
||||
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.character_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.tier = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
|
||||
e.tribute = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static int DeleteWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {}",
|
||||
TableName(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int Truncate(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"TRUNCATE TABLE {}",
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int64 GetMaxId(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COALESCE(MAX({}), 0) FROM {}",
|
||||
PrimaryKey(),
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
static int64 Count(Database& db, const std::string &where_filter = "")
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COUNT(*) FROM {} {}",
|
||||
TableName(),
|
||||
(where_filter.empty() ? "" : "WHERE " + where_filter)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_BASE_CHARACTER_TRIBUTE_REPOSITORY_H
|
||||
@@ -0,0 +1,364 @@
|
||||
/**
|
||||
* DO NOT MODIFY THIS FILE
|
||||
*
|
||||
* This repository was automatically generated and is NOT to be modified directly.
|
||||
* Any repository modifications are meant to be made to the repository extending the base.
|
||||
* Any modifications to base repositories are to be made by the generator only
|
||||
*
|
||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_BASE_COMMAND_SUBSETTINGS_REPOSITORY_H
|
||||
#define EQEMU_BASE_COMMAND_SUBSETTINGS_REPOSITORY_H
|
||||
|
||||
#include "../../database.h"
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseCommandSubsettingsRepository {
|
||||
public:
|
||||
struct CommandSubsettings {
|
||||
uint32_t id;
|
||||
std::string parent_command;
|
||||
std::string sub_command;
|
||||
uint32_t access_level;
|
||||
std::string top_level_aliases;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
{
|
||||
return std::string("id");
|
||||
}
|
||||
|
||||
static std::vector<std::string> Columns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"parent_command",
|
||||
"sub_command",
|
||||
"access_level",
|
||||
"top_level_aliases",
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::string> SelectColumns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"parent_command",
|
||||
"sub_command",
|
||||
"access_level",
|
||||
"top_level_aliases",
|
||||
};
|
||||
}
|
||||
|
||||
static std::string ColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", Columns()));
|
||||
}
|
||||
|
||||
static std::string SelectColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", SelectColumns()));
|
||||
}
|
||||
|
||||
static std::string TableName()
|
||||
{
|
||||
return std::string("command_subsettings");
|
||||
}
|
||||
|
||||
static std::string BaseSelect()
|
||||
{
|
||||
return fmt::format(
|
||||
"SELECT {} FROM {}",
|
||||
SelectColumnsRaw(),
|
||||
TableName()
|
||||
);
|
||||
}
|
||||
|
||||
static std::string BaseInsert()
|
||||
{
|
||||
return fmt::format(
|
||||
"INSERT INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static CommandSubsettings NewEntity()
|
||||
{
|
||||
CommandSubsettings e{};
|
||||
|
||||
e.id = 0;
|
||||
e.parent_command = "";
|
||||
e.sub_command = "";
|
||||
e.access_level = 0;
|
||||
e.top_level_aliases = "";
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static CommandSubsettings GetCommandSubsettings(
|
||||
const std::vector<CommandSubsettings> &command_subsettingss,
|
||||
int command_subsettings_id
|
||||
)
|
||||
{
|
||||
for (auto &command_subsettings : command_subsettingss) {
|
||||
if (command_subsettings.id == command_subsettings_id) {
|
||||
return command_subsettings;
|
||||
}
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static CommandSubsettings FindOne(
|
||||
Database& db,
|
||||
int command_subsettings_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
command_subsettings_id
|
||||
)
|
||||
);
|
||||
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1) {
|
||||
CommandSubsettings e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.parent_command = row[1] ? row[1] : "";
|
||||
e.sub_command = row[2] ? row[2] : "";
|
||||
e.access_level = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.top_level_aliases = row[4] ? row[4] : "";
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static int DeleteOne(
|
||||
Database& db,
|
||||
int command_subsettings_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {} = {}",
|
||||
TableName(),
|
||||
PrimaryKey(),
|
||||
command_subsettings_id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int UpdateOne(
|
||||
Database& db,
|
||||
const CommandSubsettings &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = '" + Strings::Escape(e.parent_command) + "'");
|
||||
v.push_back(columns[2] + " = '" + Strings::Escape(e.sub_command) + "'");
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.access_level));
|
||||
v.push_back(columns[4] + " = '" + Strings::Escape(e.top_level_aliases) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE {} SET {} WHERE {} = {}",
|
||||
TableName(),
|
||||
Strings::Implode(", ", v),
|
||||
PrimaryKey(),
|
||||
e.id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static CommandSubsettings InsertOne(
|
||||
Database& db,
|
||||
CommandSubsettings e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back("'" + Strings::Escape(e.parent_command) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.sub_command) + "'");
|
||||
v.push_back(std::to_string(e.access_level));
|
||||
v.push_back("'" + Strings::Escape(e.top_level_aliases) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
if (results.Success()) {
|
||||
e.id = results.LastInsertedID();
|
||||
return e;
|
||||
}
|
||||
|
||||
e = NewEntity();
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static int InsertMany(
|
||||
Database& db,
|
||||
const std::vector<CommandSubsettings> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back("'" + Strings::Escape(e.parent_command) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.sub_command) + "'");
|
||||
v.push_back(std::to_string(e.access_level));
|
||||
v.push_back("'" + Strings::Escape(e.top_level_aliases) + "'");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static std::vector<CommandSubsettings> All(Database& db)
|
||||
{
|
||||
std::vector<CommandSubsettings> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{}",
|
||||
BaseSelect()
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
CommandSubsettings e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.parent_command = row[1] ? row[1] : "";
|
||||
e.sub_command = row[2] ? row[2] : "";
|
||||
e.access_level = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.top_level_aliases = row[4] ? row[4] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static std::vector<CommandSubsettings> GetWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
std::vector<CommandSubsettings> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {}",
|
||||
BaseSelect(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
CommandSubsettings e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.parent_command = row[1] ? row[1] : "";
|
||||
e.sub_command = row[2] ? row[2] : "";
|
||||
e.access_level = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.top_level_aliases = row[4] ? row[4] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static int DeleteWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {}",
|
||||
TableName(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int Truncate(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"TRUNCATE TABLE {}",
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int64 GetMaxId(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COALESCE(MAX({}), 0) FROM {}",
|
||||
PrimaryKey(),
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
static int64 Count(Database& db, const std::string &where_filter = "")
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COUNT(*) FROM {} {}",
|
||||
TableName(),
|
||||
(where_filter.empty() ? "" : "WHERE " + where_filter)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_BASE_COMMAND_SUBSETTINGS_REPOSITORY_H
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "../../database.h"
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
|
||||
class BaseDataBucketsRepository {
|
||||
public:
|
||||
@@ -24,6 +24,24 @@ public:
|
||||
std::string key_;
|
||||
std::string value;
|
||||
uint32_t expires;
|
||||
int64_t character_id;
|
||||
int64_t npc_id;
|
||||
int64_t bot_id;
|
||||
|
||||
// cereal
|
||||
template<class Archive>
|
||||
void serialize(Archive &ar)
|
||||
{
|
||||
ar(
|
||||
CEREAL_NVP(id),
|
||||
CEREAL_NVP(key_),
|
||||
CEREAL_NVP(value),
|
||||
CEREAL_NVP(expires),
|
||||
CEREAL_NVP(character_id),
|
||||
CEREAL_NVP(npc_id),
|
||||
CEREAL_NVP(bot_id)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -38,6 +56,9 @@ public:
|
||||
"`key`",
|
||||
"value",
|
||||
"expires",
|
||||
"character_id",
|
||||
"npc_id",
|
||||
"bot_id",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -48,6 +69,9 @@ public:
|
||||
"`key`",
|
||||
"value",
|
||||
"expires",
|
||||
"character_id",
|
||||
"npc_id",
|
||||
"bot_id",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -88,10 +112,13 @@ public:
|
||||
{
|
||||
DataBuckets e{};
|
||||
|
||||
e.id = 0;
|
||||
e.key_ = "";
|
||||
e.value = "";
|
||||
e.expires = 0;
|
||||
e.id = 0;
|
||||
e.key_ = "";
|
||||
e.value = "";
|
||||
e.expires = 0;
|
||||
e.character_id = 0;
|
||||
e.npc_id = 0;
|
||||
e.bot_id = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -128,10 +155,13 @@ public:
|
||||
if (results.RowCount() == 1) {
|
||||
DataBuckets e{};
|
||||
|
||||
e.id = strtoull(row[0], nullptr, 10);
|
||||
e.key_ = row[1] ? row[1] : "";
|
||||
e.value = row[2] ? row[2] : "";
|
||||
e.expires = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.id = strtoull(row[0], nullptr, 10);
|
||||
e.key_ = row[1] ? row[1] : "";
|
||||
e.value = row[2] ? row[2] : "";
|
||||
e.expires = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.character_id = strtoll(row[4], nullptr, 10);
|
||||
e.npc_id = strtoll(row[5], nullptr, 10);
|
||||
e.bot_id = strtoll(row[6], nullptr, 10);
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -168,6 +198,9 @@ public:
|
||||
v.push_back(columns[1] + " = '" + Strings::Escape(e.key_) + "'");
|
||||
v.push_back(columns[2] + " = '" + Strings::Escape(e.value) + "'");
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.expires));
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.character_id));
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.npc_id));
|
||||
v.push_back(columns[6] + " = " + std::to_string(e.bot_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -193,6 +226,9 @@ public:
|
||||
v.push_back("'" + Strings::Escape(e.key_) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.value) + "'");
|
||||
v.push_back(std::to_string(e.expires));
|
||||
v.push_back(std::to_string(e.character_id));
|
||||
v.push_back(std::to_string(e.npc_id));
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -226,6 +262,9 @@ public:
|
||||
v.push_back("'" + Strings::Escape(e.key_) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.value) + "'");
|
||||
v.push_back(std::to_string(e.expires));
|
||||
v.push_back(std::to_string(e.character_id));
|
||||
v.push_back(std::to_string(e.npc_id));
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -259,10 +298,13 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
DataBuckets e{};
|
||||
|
||||
e.id = strtoull(row[0], nullptr, 10);
|
||||
e.key_ = row[1] ? row[1] : "";
|
||||
e.value = row[2] ? row[2] : "";
|
||||
e.expires = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.id = strtoull(row[0], nullptr, 10);
|
||||
e.key_ = row[1] ? row[1] : "";
|
||||
e.value = row[2] ? row[2] : "";
|
||||
e.expires = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.character_id = strtoll(row[4], nullptr, 10);
|
||||
e.npc_id = strtoll(row[5], nullptr, 10);
|
||||
e.bot_id = strtoll(row[6], nullptr, 10);
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -287,10 +329,13 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
DataBuckets e{};
|
||||
|
||||
e.id = strtoull(row[0], nullptr, 10);
|
||||
e.key_ = row[1] ? row[1] : "";
|
||||
e.value = row[2] ? row[2] : "";
|
||||
e.expires = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.id = strtoull(row[0], nullptr, 10);
|
||||
e.key_ = row[1] ? row[1] : "";
|
||||
e.value = row[2] ? row[2] : "";
|
||||
e.expires = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.character_id = strtoll(row[4], nullptr, 10);
|
||||
e.npc_id = strtoll(row[5], nullptr, 10);
|
||||
e.bot_id = strtoll(row[6], nullptr, 10);
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user