mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-26 12:02:28 +00:00
Compare commits
162 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 |
+415
@@ -1,3 +1,418 @@
|
||||
## [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
|
||||
|
||||
+6
-1
@@ -32,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)
|
||||
@@ -384,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()
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
@@ -750,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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -279,6 +279,11 @@ void DatabaseDumpService::DatabaseDump()
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -324,7 +329,9 @@ void DatabaseDumpService::DatabaseDump()
|
||||
}
|
||||
}
|
||||
|
||||
LogSys.LoadLogSettingsDefaults();
|
||||
if (!IsDumpOutputToConsole()) {
|
||||
LogSys.LoadLogSettingsDefaults();
|
||||
}
|
||||
|
||||
if (!pipe_file.empty()) {
|
||||
std::string file = fmt::format("{}.sql", GetDumpFileNameWithPath());
|
||||
@@ -604,3 +611,13 @@ void DatabaseDumpService::RemoveCredentialsFile()
|
||||
std::filesystem::remove(CREDENTIALS_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
bool DatabaseDumpService::IsDumpStaticInstanceData()
|
||||
{
|
||||
return dump_static_instance_data;
|
||||
}
|
||||
|
||||
void DatabaseDumpService::SetDumpStaticInstanceData(bool b)
|
||||
{
|
||||
dump_static_instance_data = b;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ void DatabaseUpdate::CheckDbUpdates()
|
||||
InjectBotsVersionColumn();
|
||||
auto v = GetDatabaseVersions();
|
||||
auto b = GetBinaryDatabaseVersions();
|
||||
if (CheckVersions(v, b)) {
|
||||
if (CheckVersionsUpToDate(v, b)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ DatabaseUpdate *DatabaseUpdate::SetDatabase(Database *db)
|
||||
return this;
|
||||
}
|
||||
|
||||
bool DatabaseUpdate::CheckVersions(DatabaseVersion v, DatabaseVersion b)
|
||||
bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
|
||||
{
|
||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||
|
||||
@@ -259,7 +259,7 @@ bool DatabaseUpdate::CheckVersions(DatabaseVersion v, DatabaseVersion b)
|
||||
(v.server_database_version == b.server_database_version) ? "up to date" : "checking updates"
|
||||
);
|
||||
|
||||
if (b.bots_database_version > 0) {
|
||||
if (RuleB(Bots, Enabled) && b.bots_database_version > 0) {
|
||||
LogInfo(
|
||||
"{:>8} | database [{}] binary [{}] {}",
|
||||
"Bots",
|
||||
@@ -273,8 +273,12 @@ bool DatabaseUpdate::CheckVersions(DatabaseVersion v, DatabaseVersion b)
|
||||
|
||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||
|
||||
return (v.server_database_version == b.server_database_version) &&
|
||||
(v.bots_database_version == b.bots_database_version);
|
||||
// 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
|
||||
@@ -284,7 +288,7 @@ bool DatabaseUpdate::HasPendingUpdates()
|
||||
auto v = GetDatabaseVersions();
|
||||
auto b = GetBinaryDatabaseVersions();
|
||||
|
||||
return !CheckVersions(v, b);
|
||||
return !CheckVersionsUpToDate(v, b);
|
||||
}
|
||||
|
||||
void DatabaseUpdate::InjectBotsVersionColumn()
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
bool HasPendingUpdates();
|
||||
private:
|
||||
Database *m_database;
|
||||
static bool CheckVersions(DatabaseVersion v, DatabaseVersion b);
|
||||
static bool CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b);
|
||||
void InjectBotsVersionColumn();
|
||||
};
|
||||
|
||||
|
||||
@@ -4642,11 +4642,10 @@ ADD COLUMN `avoidance` int(11) unsigned NOT NULL DEFAULT 0 AFTER `heal_scale`;
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `npc_scale_global_base`
|
||||
MODIFY COLUMN `hp` bigint(20) NOT NULL DEFAULT 0 AFTER `ac`,
|
||||
MODIFY COLUMN `hp_regen_rate` bigint(20) NOT NULL DEFAULT 0 AFTER `max_dmg`,
|
||||
ADD COLUMN `hp_regen_per_second` bigint(20) NOT NULL DEFAULT 0 AFTER `hp_regen_rate`,
|
||||
ADD COLUMN `avoidance` int(11) unsigned NOT NULL DEFAULT 0 AFTER `heal_scale`;
|
||||
DROP INDEX `PRIMARY` ON `raid_members`;
|
||||
CREATE UNIQUE INDEX `UNIQUE` ON `raid_members`(`name`);
|
||||
ALTER TABLE `raid_members` ADD COLUMN `bot_id` int(4) NOT NULL DEFAULT 0 AFTER `charid`;
|
||||
ALTER TABLE `raid_members` ADD COLUMN `id` BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT FIRST;
|
||||
|
||||
)"
|
||||
},
|
||||
@@ -4745,6 +4744,205 @@ ADD COLUMN `id` int(11) NOT NULL AUTO_INCREMENT FIRST,
|
||||
ADD PRIMARY KEY (`id`);
|
||||
)",
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9229,
|
||||
.description = "2023_07_04_chatchannel_reserved_names_fix.sql",
|
||||
.check = "SHOW TABLES LIKE 'chatchannel_reserved_names'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
CREATE TABLE `chatchannel_reserved_names`
|
||||
(
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(64) NOT NULL,
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE KEY `name` (`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9230,
|
||||
.description = "2023_06_23_raid_feature_updates",
|
||||
.check = "SHOW COLUMNS FROM `raid_members` LIKE 'is_assister'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `raid_members`
|
||||
ADD COLUMN `is_marker` TINYINT UNSIGNED DEFAULT 0 NOT NULL AFTER `islooter`,
|
||||
ADD COLUMN `is_assister` TINYINT UNSIGNED DEFAULT 0 NOT NULL AFTER `is_marker`,
|
||||
ADD COLUMN `note` VARCHAR(64) DEFAULT '' NOT NULL AFTER `is_assister`;
|
||||
|
||||
ALTER TABLE `raid_details`
|
||||
ADD COLUMN `marked_npc_1` SMALLINT UNSIGNED DEFAULT 0 NOT NULL AFTER `motd`,
|
||||
ADD COLUMN `marked_npc_2` SMALLINT UNSIGNED DEFAULT 0 NOT NULL AFTER `marked_npc_1`,
|
||||
ADD COLUMN `marked_npc_3` SMALLINT UNSIGNED DEFAULT 0 NOT NULL AFTER `marked_npc_2`;
|
||||
)",
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9231,
|
||||
.description = "2023_07_14_npc_unsigned_melee_texture.sql",
|
||||
.check = "SHOW COLUMNS FROM `npc_types` LIKE 'd_melee_texture1'",
|
||||
.condition = "contains",
|
||||
.match = "int(11) signed",
|
||||
.sql = R"(ALTER TABLE `npc_types`
|
||||
MODIFY COLUMN `d_melee_texture1` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `armortint_blue`,
|
||||
MODIFY COLUMN `d_melee_texture2` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `d_melee_texture1`;
|
||||
)",
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9232,
|
||||
.description = "2023_07_11_command_subsettings.sql",
|
||||
.check = "SHOW TABLES LIKE 'command_subsettings'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(CREATE TABLE `command_subsettings` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`parent_command` varchar(32) NOT NULL,
|
||||
`sub_command` varchar(32) NOT NULL,
|
||||
`access_level` int(11) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`top_level_aliases` varchar(255) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `command`(`parent_command`, `sub_command`)
|
||||
)
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9233,
|
||||
.description = "2023_07_16_scoped_data_buckets.sql",
|
||||
.check = "SHOW COLUMNS FROM `data_buckets` LIKE 'character_id'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
|
||||
ALTER TABLE `data_buckets`
|
||||
ADD COLUMN `character_id` bigint(11) NOT NULL DEFAULT 0 AFTER `expires`,
|
||||
ADD COLUMN `npc_id` bigint(11) NOT NULL DEFAULT 0 AFTER `character_id`,
|
||||
ADD COLUMN `bot_id` bigint(11) NOT NULL DEFAULT 0 AFTER `npc_id`,
|
||||
DROP INDEX `key_index`,
|
||||
ADD UNIQUE INDEX `keys`(`key`,`character_id`,`npc_id`,`bot_id`);
|
||||
|
||||
UPDATE data_buckets SET character_id = SUBSTRING_INDEX(SUBSTRING_INDEX( `key`, '-', 2 ), '-', -1), `key` = SUBSTR(SUBSTRING_INDEX(`key`, SUBSTRING_INDEX( `key`, '-', 2 ), -1), 2) WHERE `key` LIKE 'character-%';
|
||||
UPDATE data_buckets SET npc_id = SUBSTRING_INDEX(SUBSTRING_INDEX( `key`, '-', 2 ), '-', -1), `key` = SUBSTR(SUBSTRING_INDEX(`key`, SUBSTRING_INDEX( `key`, '-', 2 ), -1), 2) WHERE `key` LIKE 'npc-%';
|
||||
UPDATE data_buckets SET bot_id = SUBSTRING_INDEX(SUBSTRING_INDEX( `key`, '-', 2 ), '-', -1), `key` = SUBSTR(SUBSTRING_INDEX(`key`, SUBSTRING_INDEX( `key`, '-', 2 ), -1), 2) WHERE `key` LIKE 'bot-%';
|
||||
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9234,
|
||||
.description = "2023_07_27_update_raid_details.sql",
|
||||
.check = "SHOW COLUMNS FROM `raid_details` LIKE 'marked_npc_1_entity_id';",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(ALTER TABLE `raid_details`
|
||||
CHANGE COLUMN `marked_npc_1` `marked_npc_1_entity_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `motd`,
|
||||
ADD COLUMN `marked_npc_1_zone_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_1_entity_id`,
|
||||
ADD COLUMN `marked_npc_1_instance_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_1_zone_id`,
|
||||
CHANGE COLUMN `marked_npc_2` `marked_npc_2_entity_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_1_instance_id`,
|
||||
ADD COLUMN `marked_npc_2_zone_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_2_entity_id`,
|
||||
ADD COLUMN `marked_npc_2_instance_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_2_zone_id`,
|
||||
CHANGE COLUMN `marked_npc_3` `marked_npc_3_entity_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_2_instance_id`,
|
||||
ADD COLUMN `marked_npc_3_zone_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_3_entity_id`,
|
||||
ADD COLUMN `marked_npc_3_instance_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_3_zone_id`;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9235,
|
||||
.description = "2023_07_31_character_stats_record.sql",
|
||||
.check = "SHOW TABLES LIKE 'character_stats_record'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
|
||||
CREATE TABLE `character_stats_record` (
|
||||
`character_id` int NOT NULL,
|
||||
`name` varchar(100) NULL,
|
||||
`status` int NULL DEFAULT 0,
|
||||
`level` int NULL DEFAULT 0,
|
||||
`class` int NULL DEFAULT 0,
|
||||
`race` int NULL DEFAULT 0,
|
||||
`aa_points` int NULL DEFAULT 0,
|
||||
`hp` bigint NULL DEFAULT 0,
|
||||
`mana` bigint NULL DEFAULT 0,
|
||||
`endurance` bigint NULL DEFAULT 0,
|
||||
`ac` int NULL DEFAULT 0,
|
||||
`strength` int NULL DEFAULT 0,
|
||||
`stamina` int NULL DEFAULT 0,
|
||||
`dexterity` int NULL DEFAULT 0,
|
||||
`agility` int NULL DEFAULT 0,
|
||||
`intelligence` int NULL DEFAULT 0,
|
||||
`wisdom` int NULL DEFAULT 0,
|
||||
`charisma` int NULL DEFAULT 0,
|
||||
`magic_resist` int NULL DEFAULT 0,
|
||||
`fire_resist` int NULL DEFAULT 0,
|
||||
`cold_resist` int NULL DEFAULT 0,
|
||||
`poison_resist` int NULL DEFAULT 0,
|
||||
`disease_resist` int NULL DEFAULT 0,
|
||||
`corruption_resist` int NULL DEFAULT 0,
|
||||
`heroic_strength` int NULL DEFAULT 0,
|
||||
`heroic_stamina` int NULL DEFAULT 0,
|
||||
`heroic_dexterity` int NULL DEFAULT 0,
|
||||
`heroic_agility` int NULL DEFAULT 0,
|
||||
`heroic_intelligence` int NULL DEFAULT 0,
|
||||
`heroic_wisdom` int NULL DEFAULT 0,
|
||||
`heroic_charisma` int NULL DEFAULT 0,
|
||||
`heroic_magic_resist` int NULL DEFAULT 0,
|
||||
`heroic_fire_resist` int NULL DEFAULT 0,
|
||||
`heroic_cold_resist` int NULL DEFAULT 0,
|
||||
`heroic_poison_resist` int NULL DEFAULT 0,
|
||||
`heroic_disease_resist` int NULL DEFAULT 0,
|
||||
`heroic_corruption_resist` int NULL DEFAULT 0,
|
||||
`haste` int NULL DEFAULT 0,
|
||||
`accuracy` int NULL DEFAULT 0,
|
||||
`attack` int NULL DEFAULT 0,
|
||||
`avoidance` int NULL DEFAULT 0,
|
||||
`clairvoyance` int NULL DEFAULT 0,
|
||||
`combat_effects` int NULL DEFAULT 0,
|
||||
`damage_shield_mitigation` int NULL DEFAULT 0,
|
||||
`damage_shield` int NULL DEFAULT 0,
|
||||
`dot_shielding` int NULL DEFAULT 0,
|
||||
`hp_regen` int NULL DEFAULT 0,
|
||||
`mana_regen` int NULL DEFAULT 0,
|
||||
`endurance_regen` int NULL DEFAULT 0,
|
||||
`shielding` int NULL DEFAULT 0,
|
||||
`spell_damage` int NULL DEFAULT 0,
|
||||
`spell_shielding` int NULL DEFAULT 0,
|
||||
`strikethrough` int NULL DEFAULT 0,
|
||||
`stun_resist` int NULL DEFAULT 0,
|
||||
`backstab` int NULL DEFAULT 0,
|
||||
`wind` int NULL DEFAULT 0,
|
||||
`brass` int NULL DEFAULT 0,
|
||||
`string` int NULL DEFAULT 0,
|
||||
`percussion` int NULL DEFAULT 0,
|
||||
`singing` int NULL DEFAULT 0,
|
||||
`baking` int NULL DEFAULT 0,
|
||||
`alchemy` int NULL DEFAULT 0,
|
||||
`tailoring` int NULL DEFAULT 0,
|
||||
`blacksmithing` int NULL DEFAULT 0,
|
||||
`fletching` int NULL DEFAULT 0,
|
||||
`brewing` int NULL DEFAULT 0,
|
||||
`jewelry` int NULL DEFAULT 0,
|
||||
`pottery` int NULL DEFAULT 0,
|
||||
`research` int NULL DEFAULT 0,
|
||||
`alcohol` int NULL DEFAULT 0,
|
||||
`fishing` int NULL DEFAULT 0,
|
||||
`tinkering` int NULL DEFAULT 0,
|
||||
`created_at` datetime DEFAULT NULL,
|
||||
`updated_at` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`character_id`)
|
||||
);
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9236,
|
||||
.description = "2023_08_24_aa_ability_auto_grant.sql",
|
||||
.check = "SHOW COLUMNS FROM `aa_ability` LIKE 'auto_grant_enabled';",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `aa_ability` ADD COLUMN `auto_grant_enabled` TINYINT(4) NOT NULL DEFAULT '0' AFTER `reset_on_death`;
|
||||
UPDATE `aa_ability` SET `auto_grant_enabled` = 1 WHERE `grant_only` = 0 AND `charges` = 0 AND `category` = -1;
|
||||
)"
|
||||
},
|
||||
|
||||
// -- template; copy/paste this when you need to create a new entry
|
||||
// ManifestEntry{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -66,6 +66,7 @@ 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", "character_id"},
|
||||
@@ -134,6 +135,7 @@ namespace DatabaseSchema {
|
||||
"character_potionbelt",
|
||||
"character_skills",
|
||||
"character_spells",
|
||||
"character_stats_record",
|
||||
"character_task_timers",
|
||||
"character_tasks",
|
||||
"character_tribute",
|
||||
@@ -258,6 +260,7 @@ namespace DatabaseSchema {
|
||||
"chatchannels",
|
||||
"chatchannel_reserved_names",
|
||||
"command_settings",
|
||||
"command_subsettings",
|
||||
"content_flags",
|
||||
"db_str",
|
||||
"eqtime",
|
||||
|
||||
@@ -365,6 +365,8 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
|
||||
mysql_free_result(res);
|
||||
}
|
||||
|
||||
SetMultiStatementsOff();
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
@@ -418,6 +420,8 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
|
||||
r.SetErrorMessage(error_message);
|
||||
r.SetErrorNumber(mysql_errno(mysql));
|
||||
|
||||
SetMultiStatementsOff();
|
||||
|
||||
// we handle errors elsewhere
|
||||
return r;
|
||||
}
|
||||
|
||||
+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*/
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -2559,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.
|
||||
@@ -2568,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
|
||||
@@ -4105,7 +4115,9 @@ struct UpdateLeadershipAA_Struct {
|
||||
|
||||
enum
|
||||
{
|
||||
GroupLeadershipAbility_MarkNPC = 0
|
||||
GroupLeadershipAbility_MarkNPC = 0,
|
||||
RaidLeadershipAbility_MarkNPC = 16,
|
||||
RaidLeadershipAbility_MainAssist = 19
|
||||
};
|
||||
|
||||
struct DoGroupLeadershipAbility_Struct
|
||||
@@ -4149,8 +4161,10 @@ 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;
|
||||
/*200*/ char note[64];
|
||||
};
|
||||
|
||||
struct RaidAddMember_Struct {
|
||||
|
||||
@@ -446,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
|
||||
|
||||
@@ -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",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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__);\
|
||||
|
||||
+15
-29
@@ -240,36 +240,22 @@ 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
|
||||
commandInstacast = 100, //insta-cast all #casted spells
|
||||
commandDoAnimOthers = 100, //can #doanim on others
|
||||
commandLockZones = 101, //can lock or unlock zones
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1444,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)
|
||||
|
||||
@@ -546,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); }
|
||||
|
||||
@@ -720,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;
|
||||
|
||||
@@ -48,5 +48,7 @@
|
||||
#define LANG_HADAL 26
|
||||
#define LANG_UNKNOWN 27
|
||||
|
||||
#define MAX_LANGUAGE_SKILL 100
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
-117
@@ -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
|
||||
|
||||
+31
-4
@@ -35,6 +35,7 @@
|
||||
#include "../path_manager.h"
|
||||
#include "../classes.h"
|
||||
#include "../races.h"
|
||||
#include "../../zone/raids.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
@@ -2737,7 +2738,7 @@ namespace RoF2
|
||||
{
|
||||
RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer;
|
||||
auto outapp =
|
||||
new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
|
||||
new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
|
||||
structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer;
|
||||
|
||||
outlaa->action = inlaa->action;
|
||||
@@ -2746,6 +2747,18 @@ namespace RoF2
|
||||
memcpy(&outlaa->raid, &inlaa->raid, sizeof(RaidLeadershipAA_Struct));
|
||||
dest->FastQueuePacket(&outapp);
|
||||
}
|
||||
else if (raid_gen->action == raidSetNote)
|
||||
{
|
||||
auto in_note = (RaidGeneral_Struct*)__emu_buffer;
|
||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct));
|
||||
auto note = (RaidGeneral_Struct*)outapp->pBuffer;
|
||||
note->action = raidSetNote;
|
||||
strn0cpy(note->leader_name, in_note->leader_name, sizeof(note->leader_name));
|
||||
strn0cpy(note->player_name, in_note->player_name, sizeof(note->leader_name));
|
||||
strn0cpy(note->note, in_note->note, sizeof(note->note));
|
||||
dest->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
else
|
||||
{
|
||||
RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer;
|
||||
@@ -2772,7 +2785,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 +4414,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);
|
||||
@@ -5104,8 +5131,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));
|
||||
|
||||
|
||||
@@ -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*/
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+16
-1
@@ -1782,6 +1782,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 +2820,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);
|
||||
@@ -3364,7 +3378,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
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+16
-1
@@ -1452,6 +1452,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 +2264,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);
|
||||
@@ -2769,7 +2783,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
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+16
-1
@@ -2027,6 +2027,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 +3108,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);
|
||||
@@ -3664,7 +3678,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));
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseItemsRepository {
|
||||
public:
|
||||
struct Items {
|
||||
@@ -122,7 +123,7 @@ public:
|
||||
int32_t pr;
|
||||
int32_t procrate;
|
||||
int32_t races;
|
||||
int32_t range;
|
||||
int32_t range_;
|
||||
int32_t reclevel;
|
||||
int32_t recskill;
|
||||
int32_t reqlevel;
|
||||
@@ -417,7 +418,7 @@ public:
|
||||
"pr",
|
||||
"procrate",
|
||||
"races",
|
||||
"range",
|
||||
"`range`",
|
||||
"reclevel",
|
||||
"recskill",
|
||||
"reqlevel",
|
||||
@@ -708,7 +709,7 @@ public:
|
||||
"pr",
|
||||
"procrate",
|
||||
"races",
|
||||
"range",
|
||||
"`range`",
|
||||
"reclevel",
|
||||
"recskill",
|
||||
"reqlevel",
|
||||
@@ -1033,7 +1034,7 @@ public:
|
||||
e.pr = 0;
|
||||
e.procrate = 0;
|
||||
e.races = 0;
|
||||
e.range = 0;
|
||||
e.range_ = 0;
|
||||
e.reclevel = 0;
|
||||
e.recskill = 0;
|
||||
e.reqlevel = 0;
|
||||
@@ -1240,8 +1241,9 @@ public:
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE id = {} LIMIT 1",
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
items_id
|
||||
)
|
||||
);
|
||||
@@ -1353,7 +1355,7 @@ public:
|
||||
e.pr = static_cast<int32_t>(atoi(row[100]));
|
||||
e.procrate = static_cast<int32_t>(atoi(row[101]));
|
||||
e.races = static_cast<int32_t>(atoi(row[102]));
|
||||
e.range = static_cast<int32_t>(atoi(row[103]));
|
||||
e.range_ = static_cast<int32_t>(atoi(row[103]));
|
||||
e.reclevel = static_cast<int32_t>(atoi(row[104]));
|
||||
e.recskill = static_cast<int32_t>(atoi(row[105]));
|
||||
e.reqlevel = static_cast<int32_t>(atoi(row[106]));
|
||||
@@ -1671,7 +1673,7 @@ public:
|
||||
v.push_back(columns[100] + " = " + std::to_string(e.pr));
|
||||
v.push_back(columns[101] + " = " + std::to_string(e.procrate));
|
||||
v.push_back(columns[102] + " = " + std::to_string(e.races));
|
||||
v.push_back(columns[103] + " = " + std::to_string(e.range));
|
||||
v.push_back(columns[103] + " = " + std::to_string(e.range_));
|
||||
v.push_back(columns[104] + " = " + std::to_string(e.reclevel));
|
||||
v.push_back(columns[105] + " = " + std::to_string(e.recskill));
|
||||
v.push_back(columns[106] + " = " + std::to_string(e.reqlevel));
|
||||
@@ -1977,7 +1979,7 @@ public:
|
||||
v.push_back(std::to_string(e.pr));
|
||||
v.push_back(std::to_string(e.procrate));
|
||||
v.push_back(std::to_string(e.races));
|
||||
v.push_back(std::to_string(e.range));
|
||||
v.push_back(std::to_string(e.range_));
|
||||
v.push_back(std::to_string(e.reclevel));
|
||||
v.push_back(std::to_string(e.recskill));
|
||||
v.push_back(std::to_string(e.reqlevel));
|
||||
@@ -2291,7 +2293,7 @@ public:
|
||||
v.push_back(std::to_string(e.pr));
|
||||
v.push_back(std::to_string(e.procrate));
|
||||
v.push_back(std::to_string(e.races));
|
||||
v.push_back(std::to_string(e.range));
|
||||
v.push_back(std::to_string(e.range_));
|
||||
v.push_back(std::to_string(e.reclevel));
|
||||
v.push_back(std::to_string(e.recskill));
|
||||
v.push_back(std::to_string(e.reqlevel));
|
||||
@@ -2609,7 +2611,7 @@ public:
|
||||
e.pr = static_cast<int32_t>(atoi(row[100]));
|
||||
e.procrate = static_cast<int32_t>(atoi(row[101]));
|
||||
e.races = static_cast<int32_t>(atoi(row[102]));
|
||||
e.range = static_cast<int32_t>(atoi(row[103]));
|
||||
e.range_ = static_cast<int32_t>(atoi(row[103]));
|
||||
e.reclevel = static_cast<int32_t>(atoi(row[104]));
|
||||
e.recskill = static_cast<int32_t>(atoi(row[105]));
|
||||
e.reqlevel = static_cast<int32_t>(atoi(row[106]));
|
||||
@@ -2918,7 +2920,7 @@ public:
|
||||
e.pr = static_cast<int32_t>(atoi(row[100]));
|
||||
e.procrate = static_cast<int32_t>(atoi(row[101]));
|
||||
e.races = static_cast<int32_t>(atoi(row[102]));
|
||||
e.range = static_cast<int32_t>(atoi(row[103]));
|
||||
e.range_ = static_cast<int32_t>(atoi(row[103]));
|
||||
e.reclevel = static_cast<int32_t>(atoi(row[104]));
|
||||
e.recskill = static_cast<int32_t>(atoi(row[105]));
|
||||
e.reqlevel = static_cast<int32_t>(atoi(row[106]));
|
||||
|
||||
@@ -66,8 +66,8 @@ public:
|
||||
uint8_t armortint_red;
|
||||
uint8_t armortint_green;
|
||||
uint8_t armortint_blue;
|
||||
int32_t d_melee_texture1;
|
||||
int32_t d_melee_texture2;
|
||||
uint32_t d_melee_texture1;
|
||||
uint32_t d_melee_texture2;
|
||||
std::string ammo_idfile;
|
||||
uint8_t prim_melee_type;
|
||||
uint8_t sec_melee_type;
|
||||
@@ -583,7 +583,7 @@ public:
|
||||
e.exp_mod = 100;
|
||||
e.heroic_strikethrough = 0;
|
||||
e.faction_amount = 0;
|
||||
e.keeps_sold_items = 0;
|
||||
e.keeps_sold_items = 1;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -666,8 +666,8 @@ public:
|
||||
e.armortint_red = static_cast<uint8_t>(strtoul(row[43], nullptr, 10));
|
||||
e.armortint_green = static_cast<uint8_t>(strtoul(row[44], nullptr, 10));
|
||||
e.armortint_blue = static_cast<uint8_t>(strtoul(row[45], nullptr, 10));
|
||||
e.d_melee_texture1 = static_cast<int32_t>(atoi(row[46]));
|
||||
e.d_melee_texture2 = static_cast<int32_t>(atoi(row[47]));
|
||||
e.d_melee_texture1 = static_cast<uint32_t>(strtoul(row[46], nullptr, 10));
|
||||
e.d_melee_texture2 = static_cast<uint32_t>(strtoul(row[47], nullptr, 10));
|
||||
e.ammo_idfile = row[48] ? row[48] : "";
|
||||
e.prim_melee_type = static_cast<uint8_t>(strtoul(row[49], nullptr, 10));
|
||||
e.sec_melee_type = static_cast<uint8_t>(strtoul(row[50], nullptr, 10));
|
||||
@@ -1289,8 +1289,8 @@ public:
|
||||
e.armortint_red = static_cast<uint8_t>(strtoul(row[43], nullptr, 10));
|
||||
e.armortint_green = static_cast<uint8_t>(strtoul(row[44], nullptr, 10));
|
||||
e.armortint_blue = static_cast<uint8_t>(strtoul(row[45], nullptr, 10));
|
||||
e.d_melee_texture1 = static_cast<int32_t>(atoi(row[46]));
|
||||
e.d_melee_texture2 = static_cast<int32_t>(atoi(row[47]));
|
||||
e.d_melee_texture1 = static_cast<uint32_t>(strtoul(row[46], nullptr, 10));
|
||||
e.d_melee_texture2 = static_cast<uint32_t>(strtoul(row[47], nullptr, 10));
|
||||
e.ammo_idfile = row[48] ? row[48] : "";
|
||||
e.prim_melee_type = static_cast<uint8_t>(strtoul(row[49], nullptr, 10));
|
||||
e.sec_melee_type = static_cast<uint8_t>(strtoul(row[50], nullptr, 10));
|
||||
@@ -1440,8 +1440,8 @@ public:
|
||||
e.armortint_red = static_cast<uint8_t>(strtoul(row[43], nullptr, 10));
|
||||
e.armortint_green = static_cast<uint8_t>(strtoul(row[44], nullptr, 10));
|
||||
e.armortint_blue = static_cast<uint8_t>(strtoul(row[45], nullptr, 10));
|
||||
e.d_melee_texture1 = static_cast<int32_t>(atoi(row[46]));
|
||||
e.d_melee_texture2 = static_cast<int32_t>(atoi(row[47]));
|
||||
e.d_melee_texture1 = static_cast<uint32_t>(strtoul(row[46], nullptr, 10));
|
||||
e.d_melee_texture2 = static_cast<uint32_t>(strtoul(row[47], nullptr, 10));
|
||||
e.ammo_idfile = row[48] ? row[48] : "";
|
||||
e.prim_melee_type = static_cast<uint8_t>(strtoul(row[49], nullptr, 10));
|
||||
e.sec_melee_type = static_cast<uint8_t>(strtoul(row[50], nullptr, 10));
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseRaidDetailsRepository {
|
||||
public:
|
||||
struct RaidDetails {
|
||||
@@ -23,6 +24,15 @@ public:
|
||||
int32_t loottype;
|
||||
int8_t locked;
|
||||
std::string motd;
|
||||
uint32_t marked_npc_1_entity_id;
|
||||
uint32_t marked_npc_1_zone_id;
|
||||
uint32_t marked_npc_1_instance_id;
|
||||
uint32_t marked_npc_2_entity_id;
|
||||
uint32_t marked_npc_2_zone_id;
|
||||
uint32_t marked_npc_2_instance_id;
|
||||
uint32_t marked_npc_3_entity_id;
|
||||
uint32_t marked_npc_3_zone_id;
|
||||
uint32_t marked_npc_3_instance_id;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -37,6 +47,15 @@ public:
|
||||
"loottype",
|
||||
"locked",
|
||||
"motd",
|
||||
"marked_npc_1_entity_id",
|
||||
"marked_npc_1_zone_id",
|
||||
"marked_npc_1_instance_id",
|
||||
"marked_npc_2_entity_id",
|
||||
"marked_npc_2_zone_id",
|
||||
"marked_npc_2_instance_id",
|
||||
"marked_npc_3_entity_id",
|
||||
"marked_npc_3_zone_id",
|
||||
"marked_npc_3_instance_id",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -47,6 +66,15 @@ public:
|
||||
"loottype",
|
||||
"locked",
|
||||
"motd",
|
||||
"marked_npc_1_entity_id",
|
||||
"marked_npc_1_zone_id",
|
||||
"marked_npc_1_instance_id",
|
||||
"marked_npc_2_entity_id",
|
||||
"marked_npc_2_zone_id",
|
||||
"marked_npc_2_instance_id",
|
||||
"marked_npc_3_entity_id",
|
||||
"marked_npc_3_zone_id",
|
||||
"marked_npc_3_instance_id",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -87,10 +115,19 @@ public:
|
||||
{
|
||||
RaidDetails e{};
|
||||
|
||||
e.raidid = 0;
|
||||
e.loottype = 0;
|
||||
e.locked = 0;
|
||||
e.motd = "";
|
||||
e.raidid = 0;
|
||||
e.loottype = 0;
|
||||
e.locked = 0;
|
||||
e.motd = "";
|
||||
e.marked_npc_1_entity_id = 0;
|
||||
e.marked_npc_1_zone_id = 0;
|
||||
e.marked_npc_1_instance_id = 0;
|
||||
e.marked_npc_2_entity_id = 0;
|
||||
e.marked_npc_2_zone_id = 0;
|
||||
e.marked_npc_2_instance_id = 0;
|
||||
e.marked_npc_3_entity_id = 0;
|
||||
e.marked_npc_3_zone_id = 0;
|
||||
e.marked_npc_3_instance_id = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -116,8 +153,9 @@ public:
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE id = {} LIMIT 1",
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
raid_details_id
|
||||
)
|
||||
);
|
||||
@@ -126,10 +164,19 @@ public:
|
||||
if (results.RowCount() == 1) {
|
||||
RaidDetails e{};
|
||||
|
||||
e.raidid = static_cast<int32_t>(atoi(row[0]));
|
||||
e.loottype = static_cast<int32_t>(atoi(row[1]));
|
||||
e.locked = static_cast<int8_t>(atoi(row[2]));
|
||||
e.motd = row[3] ? row[3] : "";
|
||||
e.raidid = static_cast<int32_t>(atoi(row[0]));
|
||||
e.loottype = static_cast<int32_t>(atoi(row[1]));
|
||||
e.locked = static_cast<int8_t>(atoi(row[2]));
|
||||
e.motd = row[3] ? row[3] : "";
|
||||
e.marked_npc_1_entity_id = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
|
||||
e.marked_npc_1_zone_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
|
||||
e.marked_npc_1_instance_id = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
|
||||
e.marked_npc_2_entity_id = static_cast<uint32_t>(strtoul(row[7], nullptr, 10));
|
||||
e.marked_npc_2_zone_id = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
|
||||
e.marked_npc_2_instance_id = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
|
||||
e.marked_npc_3_entity_id = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
|
||||
e.marked_npc_3_zone_id = static_cast<uint32_t>(strtoul(row[11], nullptr, 10));
|
||||
e.marked_npc_3_instance_id = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -167,6 +214,15 @@ public:
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.loottype));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.locked));
|
||||
v.push_back(columns[3] + " = '" + Strings::Escape(e.motd) + "'");
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.marked_npc_1_entity_id));
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.marked_npc_1_zone_id));
|
||||
v.push_back(columns[6] + " = " + std::to_string(e.marked_npc_1_instance_id));
|
||||
v.push_back(columns[7] + " = " + std::to_string(e.marked_npc_2_entity_id));
|
||||
v.push_back(columns[8] + " = " + std::to_string(e.marked_npc_2_zone_id));
|
||||
v.push_back(columns[9] + " = " + std::to_string(e.marked_npc_2_instance_id));
|
||||
v.push_back(columns[10] + " = " + std::to_string(e.marked_npc_3_entity_id));
|
||||
v.push_back(columns[11] + " = " + std::to_string(e.marked_npc_3_zone_id));
|
||||
v.push_back(columns[12] + " = " + std::to_string(e.marked_npc_3_instance_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -192,6 +248,15 @@ public:
|
||||
v.push_back(std::to_string(e.loottype));
|
||||
v.push_back(std::to_string(e.locked));
|
||||
v.push_back("'" + Strings::Escape(e.motd) + "'");
|
||||
v.push_back(std::to_string(e.marked_npc_1_entity_id));
|
||||
v.push_back(std::to_string(e.marked_npc_1_zone_id));
|
||||
v.push_back(std::to_string(e.marked_npc_1_instance_id));
|
||||
v.push_back(std::to_string(e.marked_npc_2_entity_id));
|
||||
v.push_back(std::to_string(e.marked_npc_2_zone_id));
|
||||
v.push_back(std::to_string(e.marked_npc_2_instance_id));
|
||||
v.push_back(std::to_string(e.marked_npc_3_entity_id));
|
||||
v.push_back(std::to_string(e.marked_npc_3_zone_id));
|
||||
v.push_back(std::to_string(e.marked_npc_3_instance_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -225,6 +290,15 @@ public:
|
||||
v.push_back(std::to_string(e.loottype));
|
||||
v.push_back(std::to_string(e.locked));
|
||||
v.push_back("'" + Strings::Escape(e.motd) + "'");
|
||||
v.push_back(std::to_string(e.marked_npc_1_entity_id));
|
||||
v.push_back(std::to_string(e.marked_npc_1_zone_id));
|
||||
v.push_back(std::to_string(e.marked_npc_1_instance_id));
|
||||
v.push_back(std::to_string(e.marked_npc_2_entity_id));
|
||||
v.push_back(std::to_string(e.marked_npc_2_zone_id));
|
||||
v.push_back(std::to_string(e.marked_npc_2_instance_id));
|
||||
v.push_back(std::to_string(e.marked_npc_3_entity_id));
|
||||
v.push_back(std::to_string(e.marked_npc_3_zone_id));
|
||||
v.push_back(std::to_string(e.marked_npc_3_instance_id));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -258,10 +332,19 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
RaidDetails e{};
|
||||
|
||||
e.raidid = static_cast<int32_t>(atoi(row[0]));
|
||||
e.loottype = static_cast<int32_t>(atoi(row[1]));
|
||||
e.locked = static_cast<int8_t>(atoi(row[2]));
|
||||
e.motd = row[3] ? row[3] : "";
|
||||
e.raidid = static_cast<int32_t>(atoi(row[0]));
|
||||
e.loottype = static_cast<int32_t>(atoi(row[1]));
|
||||
e.locked = static_cast<int8_t>(atoi(row[2]));
|
||||
e.motd = row[3] ? row[3] : "";
|
||||
e.marked_npc_1_entity_id = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
|
||||
e.marked_npc_1_zone_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
|
||||
e.marked_npc_1_instance_id = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
|
||||
e.marked_npc_2_entity_id = static_cast<uint32_t>(strtoul(row[7], nullptr, 10));
|
||||
e.marked_npc_2_zone_id = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
|
||||
e.marked_npc_2_instance_id = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
|
||||
e.marked_npc_3_entity_id = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
|
||||
e.marked_npc_3_zone_id = static_cast<uint32_t>(strtoul(row[11], nullptr, 10));
|
||||
e.marked_npc_3_instance_id = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -286,10 +369,19 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
RaidDetails e{};
|
||||
|
||||
e.raidid = static_cast<int32_t>(atoi(row[0]));
|
||||
e.loottype = static_cast<int32_t>(atoi(row[1]));
|
||||
e.locked = static_cast<int8_t>(atoi(row[2]));
|
||||
e.motd = row[3] ? row[3] : "";
|
||||
e.raidid = static_cast<int32_t>(atoi(row[0]));
|
||||
e.loottype = static_cast<int32_t>(atoi(row[1]));
|
||||
e.locked = static_cast<int8_t>(atoi(row[2]));
|
||||
e.motd = row[3] ? row[3] : "";
|
||||
e.marked_npc_1_entity_id = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
|
||||
e.marked_npc_1_zone_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
|
||||
e.marked_npc_1_instance_id = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
|
||||
e.marked_npc_2_entity_id = static_cast<uint32_t>(strtoul(row[7], nullptr, 10));
|
||||
e.marked_npc_2_zone_id = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
|
||||
e.marked_npc_2_instance_id = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
|
||||
e.marked_npc_3_entity_id = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
|
||||
e.marked_npc_3_zone_id = static_cast<uint32_t>(strtoul(row[11], nullptr, 10));
|
||||
e.marked_npc_3_instance_id = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,9 @@ public:
|
||||
int8_t isgroupleader;
|
||||
int8_t israidleader;
|
||||
int8_t islooter;
|
||||
uint8_t is_marker;
|
||||
uint8_t is_assister;
|
||||
std::string note;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -52,6 +55,9 @@ public:
|
||||
"isgroupleader",
|
||||
"israidleader",
|
||||
"islooter",
|
||||
"is_marker",
|
||||
"is_assister",
|
||||
"note",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -69,6 +75,9 @@ public:
|
||||
"isgroupleader",
|
||||
"israidleader",
|
||||
"islooter",
|
||||
"is_marker",
|
||||
"is_assister",
|
||||
"note",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -120,6 +129,9 @@ public:
|
||||
e.isgroupleader = 0;
|
||||
e.israidleader = 0;
|
||||
e.islooter = 0;
|
||||
e.is_marker = 0;
|
||||
e.is_assister = 0;
|
||||
e.note = "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -167,6 +179,9 @@ public:
|
||||
e.isgroupleader = static_cast<int8_t>(atoi(row[8]));
|
||||
e.israidleader = static_cast<int8_t>(atoi(row[9]));
|
||||
e.islooter = static_cast<int8_t>(atoi(row[10]));
|
||||
e.is_marker = static_cast<uint8_t>(strtoul(row[11], nullptr, 10));
|
||||
e.is_assister = static_cast<uint8_t>(strtoul(row[12], nullptr, 10));
|
||||
e.note = row[13] ? row[13] : "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -210,6 +225,9 @@ public:
|
||||
v.push_back(columns[8] + " = " + std::to_string(e.isgroupleader));
|
||||
v.push_back(columns[9] + " = " + std::to_string(e.israidleader));
|
||||
v.push_back(columns[10] + " = " + std::to_string(e.islooter));
|
||||
v.push_back(columns[11] + " = " + std::to_string(e.is_marker));
|
||||
v.push_back(columns[12] + " = " + std::to_string(e.is_assister));
|
||||
v.push_back(columns[13] + " = '" + Strings::Escape(e.note) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -242,6 +260,9 @@ public:
|
||||
v.push_back(std::to_string(e.isgroupleader));
|
||||
v.push_back(std::to_string(e.israidleader));
|
||||
v.push_back(std::to_string(e.islooter));
|
||||
v.push_back(std::to_string(e.is_marker));
|
||||
v.push_back(std::to_string(e.is_assister));
|
||||
v.push_back("'" + Strings::Escape(e.note) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -282,6 +303,9 @@ public:
|
||||
v.push_back(std::to_string(e.isgroupleader));
|
||||
v.push_back(std::to_string(e.israidleader));
|
||||
v.push_back(std::to_string(e.islooter));
|
||||
v.push_back(std::to_string(e.is_marker));
|
||||
v.push_back(std::to_string(e.is_assister));
|
||||
v.push_back("'" + Strings::Escape(e.note) + "'");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -326,6 +350,9 @@ public:
|
||||
e.isgroupleader = static_cast<int8_t>(atoi(row[8]));
|
||||
e.israidleader = static_cast<int8_t>(atoi(row[9]));
|
||||
e.islooter = static_cast<int8_t>(atoi(row[10]));
|
||||
e.is_marker = static_cast<uint8_t>(strtoul(row[11], nullptr, 10));
|
||||
e.is_assister = static_cast<uint8_t>(strtoul(row[12], nullptr, 10));
|
||||
e.note = row[13] ? row[13] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -361,6 +388,9 @@ public:
|
||||
e.isgroupleader = static_cast<int8_t>(atoi(row[8]));
|
||||
e.israidleader = static_cast<int8_t>(atoi(row[9]));
|
||||
e.islooter = static_cast<int8_t>(atoi(row[10]));
|
||||
e.is_marker = static_cast<uint8_t>(strtoul(row[11], nullptr, 10));
|
||||
e.is_assister = static_cast<uint8_t>(strtoul(row[12], nullptr, 10));
|
||||
e.note = row[13] ? row[13] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef EQEMU_CHARACTER_STATS_RECORD_REPOSITORY_H
|
||||
#define EQEMU_CHARACTER_STATS_RECORD_REPOSITORY_H
|
||||
|
||||
#include "../database.h"
|
||||
#include "../strings.h"
|
||||
#include "base/base_character_stats_record_repository.h"
|
||||
|
||||
class CharacterStatsRecordRepository: public BaseCharacterStatsRecordRepository {
|
||||
public:
|
||||
|
||||
/**
|
||||
* This file was auto generated and can be modified and extended upon
|
||||
*
|
||||
* Base repository methods are automatically
|
||||
* generated in the "base" version of this repository. The base repository
|
||||
* is immutable and to be left untouched, while methods in this class
|
||||
* are used as extension methods for more specific persistence-layer
|
||||
* accessors or mutators.
|
||||
*
|
||||
* Base Methods (Subject to be expanded upon in time)
|
||||
*
|
||||
* Note: Not all tables are designed appropriately to fit functionality with all base methods
|
||||
*
|
||||
* InsertOne
|
||||
* UpdateOne
|
||||
* DeleteOne
|
||||
* FindOne
|
||||
* GetWhere(std::string where_filter)
|
||||
* DeleteWhere(std::string where_filter)
|
||||
* InsertMany
|
||||
* All
|
||||
*
|
||||
* Example custom methods in a repository
|
||||
*
|
||||
* CharacterStatsRecordRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||
* CharacterStatsRecordRepository::GetWhereNeverExpires()
|
||||
* CharacterStatsRecordRepository::GetWhereXAndY()
|
||||
* CharacterStatsRecordRepository::DeleteWhereXAndY()
|
||||
*
|
||||
* Most of the above could be covered by base methods, but if you as a developer
|
||||
* find yourself re-using logic for other parts of the code, its best to just make a
|
||||
* method that can be re-used easily elsewhere especially if it can use a base repository
|
||||
* method and encapsulate filters there
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_CHARACTER_STATS_RECORD_REPOSITORY_H
|
||||
@@ -0,0 +1,221 @@
|
||||
#ifndef EQEMU_COMMAND_SUBSETTINGS_REPOSITORY_H
|
||||
#define EQEMU_COMMAND_SUBSETTINGS_REPOSITORY_H
|
||||
|
||||
#include "../database.h"
|
||||
#include "../strings.h"
|
||||
#include "base/base_command_subsettings_repository.h"
|
||||
|
||||
class CommandSubsettingsRepository: public BaseCommandSubsettingsRepository {
|
||||
public:
|
||||
|
||||
/**
|
||||
* This file was auto generated and can be modified and extended upon
|
||||
*
|
||||
* Base repository methods are automatically
|
||||
* generated in the "base" version of this repository. The base repository
|
||||
* is immutable and to be left untouched, while methods in this class
|
||||
* are used as extension methods for more specific persistence-layer
|
||||
* accessors or mutators.
|
||||
*
|
||||
* Base Methods (Subject to be expanded upon in time)
|
||||
*
|
||||
* Note: Not all tables are designed appropriately to fit functionality with all base methods
|
||||
*
|
||||
* InsertOne
|
||||
* UpdateOne
|
||||
* DeleteOne
|
||||
* FindOne
|
||||
* GetWhere(std::string where_filter)
|
||||
* DeleteWhere(std::string where_filter)
|
||||
* InsertMany
|
||||
* All
|
||||
*
|
||||
* Example custom methods in a repository
|
||||
*
|
||||
* CommandSubsettingsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||
* CommandSubsettingsRepository::GetWhereNeverExpires()
|
||||
* CommandSubsettingsRepository::GetWhereXAndY()
|
||||
* CommandSubsettingsRepository::DeleteWhereXAndY()
|
||||
*
|
||||
* Most of the above could be covered by base methods, but if you as a developer
|
||||
* find yourself re-using logic for other parts of the code, its best to just make a
|
||||
* method that can be re-used easily elsewhere especially if it can use a base repository
|
||||
* method and encapsulate filters there
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
static std::vector<CommandSubsettingsRepository::CommandSubsettings> GetAll(Database& db)
|
||||
{
|
||||
// these are the base definitions for command_subsettings and can be over-ridden by the database
|
||||
std::vector<CommandSubsettingsRepository::CommandSubsettings> static_records = {
|
||||
{.parent_command = "find", .sub_command = "aa", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findaa"},
|
||||
{.parent_command = "find", .sub_command = "character", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findcharacter"},
|
||||
{.parent_command = "find", .sub_command = "class", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findclass"},
|
||||
{.parent_command = "find", .sub_command = "currency", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findcurrency"},
|
||||
{.parent_command = "find", .sub_command = "deity", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "finddeity"},
|
||||
{.parent_command = "find", .sub_command = "emote", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findemote"},
|
||||
{.parent_command = "find", .sub_command = "faction", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findfaction"},
|
||||
{.parent_command = "find", .sub_command = "item", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fi|finditem|itemsearch"},
|
||||
{.parent_command = "find", .sub_command = "language", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findlanguage"},
|
||||
{.parent_command = "find", .sub_command = "npc_type", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fn|findnpc|findnpctype"},
|
||||
{.parent_command = "find", .sub_command = "race", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findrace"},
|
||||
{.parent_command = "find", .sub_command = "recipe", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findrecipe"},
|
||||
{.parent_command = "find", .sub_command = "skill", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findskill"},
|
||||
{.parent_command = "find", .sub_command = "spell", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fs|findspell"},
|
||||
{.parent_command = "find", .sub_command = "task", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findtask"},
|
||||
{.parent_command = "find", .sub_command = "zone", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fz|findzone"},
|
||||
{.parent_command = "set", .sub_command = "aa_exp", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setaaxp|setaaexp"},
|
||||
{.parent_command = "set", .sub_command = "aa_points", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setaapts|setaapoints"},
|
||||
{.parent_command = "set", .sub_command = "adventure_points", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setadventurepoints"},
|
||||
{.parent_command = "set", .sub_command = "alternate_currency", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setaltcurrency"},
|
||||
{.parent_command = "set", .sub_command = "animation", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setanim"},
|
||||
{.parent_command = "set", .sub_command = "anon", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setanon"},
|
||||
{.parent_command = "set", .sub_command = "bind", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "bind"},
|
||||
{.parent_command = "set", .sub_command = "checksum", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "updatechecksum"},
|
||||
{.parent_command = "set", .sub_command = "class_permanent", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "permaclass"},
|
||||
{.parent_command = "set", .sub_command = "crystals", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setcrystals"},
|
||||
{.parent_command = "set", .sub_command = "date", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "date"},
|
||||
{.parent_command = "set", .sub_command = "endurance", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setendurance"},
|
||||
{.parent_command = "set", .sub_command = "endurance_full", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "endurance"},
|
||||
{.parent_command = "set", .sub_command = "exp", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setxp|setexp"},
|
||||
{.parent_command = "set", .sub_command = "faction", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setfaction"},
|
||||
{.parent_command = "set", .sub_command = "flymode", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "flymode"},
|
||||
{.parent_command = "set", .sub_command = "freeze", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "freeze|unfreeze"},
|
||||
{.parent_command = "set", .sub_command = "gender", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "gender"},
|
||||
{.parent_command = "set", .sub_command = "gender_permanent", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "permagender"},
|
||||
{.parent_command = "set", .sub_command = "gm", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "gm"},
|
||||
{.parent_command = "set", .sub_command = "gm_speed", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "gmspeed"},
|
||||
{.parent_command = "set", .sub_command = "gm_status", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "flag"},
|
||||
{.parent_command = "set", .sub_command = "god_mode", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "godmode"},
|
||||
{.parent_command = "set", .sub_command = "haste", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "haste"},
|
||||
{.parent_command = "set", .sub_command = "hero_model", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "heromodel"},
|
||||
{.parent_command = "set", .sub_command = "hide_me", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "hideme"},
|
||||
{.parent_command = "set", .sub_command = "hp", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "sethp"},
|
||||
{.parent_command = "set", .sub_command = "hp_full", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "heal"},
|
||||
{.parent_command = "set", .sub_command = "invulnerable", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "invul|invulnerable"},
|
||||
{.parent_command = "set", .sub_command = "language", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setlanguage"},
|
||||
{.parent_command = "set", .sub_command = "last_name", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "lastname"},
|
||||
{.parent_command = "set", .sub_command = "level", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "level"},
|
||||
{.parent_command = "set", .sub_command = "loginserver_info", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setlsinfo"},
|
||||
{.parent_command = "set", .sub_command = "mana", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setmana"},
|
||||
{.parent_command = "set", .sub_command = "mana_full", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "mana"},
|
||||
{.parent_command = "set", .sub_command = "motd", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "motd"},
|
||||
{.parent_command = "set", .sub_command = "name", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "name"},
|
||||
{.parent_command = "set", .sub_command = "ooc_mute", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "oocmute"},
|
||||
{.parent_command = "set", .sub_command = "password", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setpass"},
|
||||
{.parent_command = "set", .sub_command = "pvp", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "pvp"},
|
||||
{.parent_command = "set", .sub_command = "pvp_points", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setpvppoints"},
|
||||
{.parent_command = "set", .sub_command = "race", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "race"},
|
||||
{.parent_command = "set", .sub_command = "race_permanent", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "permarace"},
|
||||
{.parent_command = "set", .sub_command = "server_locked", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "lock|serverlock|serverunlock|unlock"},
|
||||
{.parent_command = "set", .sub_command = "skill", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setskill"},
|
||||
{.parent_command = "set", .sub_command = "skill_all", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setallskill|setallskills|setskillall"},
|
||||
{.parent_command = "set", .sub_command = "skill_all_max", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "maxskills"},
|
||||
{.parent_command = "set", .sub_command = "start_zone", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setstartzone"},
|
||||
{.parent_command = "set", .sub_command = "temporary_name", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "tempname"},
|
||||
{.parent_command = "set", .sub_command = "texture", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "texture"},
|
||||
{.parent_command = "set", .sub_command = "time", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "time"},
|
||||
{.parent_command = "set", .sub_command = "time_zone", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "timezone"},
|
||||
{.parent_command = "set", .sub_command = "title", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "title"},
|
||||
{.parent_command = "set", .sub_command = "title_suffix", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "titlesuffix"},
|
||||
{.parent_command = "set", .sub_command = "weather", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "weather"},
|
||||
{.parent_command = "set", .sub_command = "zone", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "zclip|zcolor|zheader|zonelock|zsafecoords|zsky|zunderworld"},
|
||||
{.parent_command = "show", .sub_command = "aggro", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "aggro"},
|
||||
{.parent_command = "show", .sub_command = "buffs", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showbuffs"},
|
||||
{.parent_command = "show", .sub_command = "buried_corpse_count", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "getplayerburiedcorpsecount"},
|
||||
{.parent_command = "show", .sub_command = "client_version_summary", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "cvs"},
|
||||
{.parent_command = "show", .sub_command = "currencies", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "viewcurrencies"},
|
||||
{.parent_command = "show", .sub_command = "distance", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "distance"},
|
||||
{.parent_command = "show", .sub_command = "emote", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "emoteview"},
|
||||
{.parent_command = "show", .sub_command = "field_of_view", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fov"},
|
||||
{.parent_command = "show", .sub_command = "flags", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "flags"},
|
||||
{.parent_command = "show", .sub_command = "group_info", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "ginfo"},
|
||||
{.parent_command = "show", .sub_command = "hatelist", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "hatelist"},
|
||||
{.parent_command = "show", .sub_command = "inventory", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "peekinv"},
|
||||
{.parent_command = "show", .sub_command = "ip_lookup", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "iplookup"},
|
||||
{.parent_command = "show", .sub_command = "line_of_sight", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "checklos"},
|
||||
{.parent_command = "show", .sub_command = "network", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "network"},
|
||||
{.parent_command = "show", .sub_command = "network_stats", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "netstats"},
|
||||
{.parent_command = "show", .sub_command = "npc_global_loot", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "shownpcgloballoot"},
|
||||
{.parent_command = "show", .sub_command = "npc_stats", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "npcstats"},
|
||||
{.parent_command = "show", .sub_command = "npc_type", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "viewnpctype"},
|
||||
{.parent_command = "show", .sub_command = "peqzone_flags", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "peqzone_flags"},
|
||||
{.parent_command = "show", .sub_command = "petition", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "listpetition|viewpetition"},
|
||||
{.parent_command = "show", .sub_command = "petition_info", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "petitioninfo"},
|
||||
{.parent_command = "show", .sub_command = "proximity", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "proximity"},
|
||||
{.parent_command = "show", .sub_command = "quest_errors", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "questerrors"},
|
||||
{.parent_command = "show", .sub_command = "quest_globals", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "globalview"},
|
||||
{.parent_command = "show", .sub_command = "recipe", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "viewrecipe"},
|
||||
{.parent_command = "show", .sub_command = "server_info", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "serverinfo"},
|
||||
{.parent_command = "show", .sub_command = "skills", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showskills"},
|
||||
{.parent_command = "show", .sub_command = "spawn_status", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "spawnstatus"},
|
||||
{.parent_command = "show", .sub_command = "spells", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showspells"},
|
||||
{.parent_command = "show", .sub_command = "spells_list", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showspellslist"},
|
||||
{.parent_command = "show", .sub_command = "stats", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showstats"},
|
||||
{.parent_command = "show", .sub_command = "timers", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "timers"},
|
||||
{.parent_command = "show", .sub_command = "traps", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "trapinfo"},
|
||||
{.parent_command = "show", .sub_command = "uptime", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "uptime"},
|
||||
{.parent_command = "show", .sub_command = "variable", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "getvariable"},
|
||||
{.parent_command = "show", .sub_command = "version", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "version"},
|
||||
{.parent_command = "show", .sub_command = "waypoints", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "wpinfo"},
|
||||
{.parent_command = "show", .sub_command = "who", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "who"},
|
||||
{.parent_command = "show", .sub_command = "xtargets", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "xtargets"},
|
||||
{.parent_command = "show", .sub_command = "zone_global_loot", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showzonegloballoot"},
|
||||
{.parent_command = "show", .sub_command = "zone_loot", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "viewzoneloot"},
|
||||
{.parent_command = "show", .sub_command = "zone_points", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showzonepoints"},
|
||||
{.parent_command = "show", .sub_command = "zone_stats", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "zstats"},
|
||||
{.parent_command = "show", .sub_command = "zone_status", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "zonestatus"},
|
||||
};
|
||||
|
||||
auto db_sub_settings = All(db);
|
||||
|
||||
// inject commands in the database that are not already there
|
||||
std::vector<CommandSubsettingsRepository::CommandSubsettings> new_records = {};
|
||||
for (const auto &r: static_records) {
|
||||
bool found = false;
|
||||
for (const auto &db_r: db_sub_settings) {
|
||||
if (r.parent_command == db_r.parent_command && r.sub_command == db_r.sub_command) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
LogInfo("New command [{}] sub-command [{}] added to database table [{}] !", r.parent_command, r.sub_command, TableName());
|
||||
new_records.emplace_back(r);
|
||||
}
|
||||
}
|
||||
|
||||
if (!new_records.empty()) {
|
||||
InsertMany(db, new_records);
|
||||
// if any were added, we need to reload the list
|
||||
db_sub_settings = All(db);
|
||||
}
|
||||
|
||||
// remove commands from the database that are not in the static list
|
||||
bool any_deleted = false;
|
||||
for (const auto &db_r: db_sub_settings) {
|
||||
bool found = false;
|
||||
for (const auto &r: static_records) {
|
||||
if (r.parent_command == db_r.parent_command && r.sub_command == db_r.sub_command) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
LogInfo("Command [{}] sub-command [{}] removed from database table [{}] !", db_r.parent_command, db_r.sub_command, TableName());
|
||||
DeleteWhere(db, fmt::format("parent_command = '{}' AND sub_command = '{}'", db_r.parent_command, db_r.sub_command));
|
||||
any_deleted = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if any were deleted, re-read the database
|
||||
if (any_deleted) {
|
||||
db_sub_settings = All(db);
|
||||
}
|
||||
|
||||
// return the final list of what's in the database
|
||||
return db_sub_settings;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_COMMAND_SUBSETTINGS_REPOSITORY_H
|
||||
@@ -44,7 +44,35 @@ public:
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
static std::vector<int32> GetItemIDsBySearchCriteria(
|
||||
Database& db,
|
||||
std::string search_string,
|
||||
int query_limit = 0
|
||||
)
|
||||
{
|
||||
auto query = fmt::format(
|
||||
"SELECT `id` FROM {} WHERE LOWER(`name`) LIKE '%%{}%%' ORDER BY id ASC",
|
||||
TableName(),
|
||||
Strings::Escape(search_string)
|
||||
);
|
||||
|
||||
if (query_limit >= 1) {
|
||||
query += fmt::format(" LIMIT {}", query_limit);
|
||||
}
|
||||
|
||||
std::vector<int32> item_id_list;
|
||||
|
||||
auto results = db.QueryDatabase(query);
|
||||
if (!results.Success() || !results.RowCount()) {
|
||||
return item_id_list;
|
||||
}
|
||||
|
||||
for (auto row : results) {
|
||||
item_id_list.emplace_back(Strings::ToInt(row[0]));
|
||||
}
|
||||
|
||||
return item_id_list;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_ITEMS_REPOSITORY_H
|
||||
|
||||
@@ -44,7 +44,28 @@ public:
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
static int UpdateRaidMarkedNPC(
|
||||
Database& db,
|
||||
int32_t raid_id,
|
||||
uint32_t marked_npc_entity_id,
|
||||
uint32_t marked_npc_zone_id,
|
||||
uint32_t marked_npc_instance_id,
|
||||
uint32_t slot_number
|
||||
) {
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE `{0}` SET `marked_npc_{4}_entity_id` = '{1}',`marked_npc_{4}_zone_id` = '{2}',`marked_npc_{4}_instance_id` = '{3}' WHERE raidid = '{5}';",
|
||||
TableName(),
|
||||
marked_npc_entity_id,
|
||||
marked_npc_zone_id,
|
||||
marked_npc_instance_id,
|
||||
slot_number,
|
||||
raid_id
|
||||
)
|
||||
);
|
||||
|
||||
return results.Success() ? results.RowsAffected() : 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_RAID_DETAILS_REPOSITORY_H
|
||||
|
||||
@@ -44,7 +44,59 @@ public:
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
static int UpdateRaidNote(
|
||||
Database& db,
|
||||
int32_t raid_id,
|
||||
const std::string& note,
|
||||
const std::string& character_name
|
||||
) {
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format("UPDATE `{}` SET `note` = '{}' WHERE raidid = '{}' AND name = '{}';",
|
||||
TableName(),
|
||||
Strings::Escape(note),
|
||||
raid_id,
|
||||
Strings::Escape(character_name)
|
||||
)
|
||||
);
|
||||
return results.Success() ? results.RowsAffected() : 0;
|
||||
}
|
||||
|
||||
static int UpdateRaidAssister(
|
||||
Database& db,
|
||||
int32_t raid_id,
|
||||
const std::string& character_name,
|
||||
uint8_t value
|
||||
) {
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE `{}` SET `is_assister` = '{}' WHERE raidid = '{}' AND `name` = '{}';",
|
||||
TableName(),
|
||||
value,
|
||||
raid_id,
|
||||
Strings::Escape(character_name)
|
||||
)
|
||||
);
|
||||
|
||||
return results.Success() ? results.RowsAffected() : 0;
|
||||
}
|
||||
|
||||
static int UpdateRaidMarker(
|
||||
Database& db,
|
||||
int32_t raid_id,
|
||||
const std::string& character_name,
|
||||
uint8_t value
|
||||
) {
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE `{}` SET `is_marker` = '{}' WHERE raidid = '{}' AND `name` = '{}';",
|
||||
TableName(),
|
||||
value,
|
||||
raid_id,
|
||||
Strings::Escape(character_name)
|
||||
)
|
||||
);
|
||||
|
||||
return results.Success() ? results.RowsAffected() : 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_RAID_MEMBERS_REPOSITORY_H
|
||||
|
||||
+15
-3
@@ -58,6 +58,7 @@ RULE_REAL(Character, ExpMultiplier, 0.5, "If greater than 0, the experience gain
|
||||
RULE_REAL(Character, AAExpMultiplier, 0.5, "If greater than 0, the AA experience gained is multiplied by this value. ")
|
||||
RULE_REAL(Character, GroupExpMultiplier, 0.5, "The experience in a group is multiplied by this value in addition to the group multiplier. The group multiplier is: 2 members=x 1.2, 3=x1.4, 4=x1.6, 5=x1.8, 6=x2.16")
|
||||
RULE_REAL(Character, RaidExpMultiplier, 0.2, "The experience gained in raids is multiplied by (1-RaidExpMultiplier) ")
|
||||
RULE_REAL(Character, FinalRaidExpMultiplier, 1.0, "Multiplies all raid experience by this value. Default: 1.0")
|
||||
RULE_BOOL(Character, UseXPConScaling, true, "When activated, the experience is modified depending on the difference between player level and NPC level. The values from the rules GreenModifier to RedModifier are used")
|
||||
RULE_INT(Character, ShowExpValues, 0, "Show experience values. 0=normal, 1=show raw experience values, 2=show raw experience values and percent")
|
||||
RULE_INT(Character, GreenModifier, 20, "The experience obtained for green con mobs is multiplied by value/100")
|
||||
@@ -241,6 +242,7 @@ RULE_CATEGORY_END()
|
||||
RULE_CATEGORY(Skills)
|
||||
RULE_INT(Skills, MaxTrainTradeskills, 21, "Highest level for trading skills that can be learnt by the trainer")
|
||||
RULE_BOOL(Skills, UseLimitTradeskillSearchSkillDiff, true, "Enables the limit for the maximum difference between trivial and skill for recipe searches and favorites")
|
||||
RULE_BOOL(Skills, TrivialTradeskillCombinesNoFail, false, "Enable to make all trivial tradeskill combines unable to fail")
|
||||
RULE_INT(Skills, MaxTradeskillSearchSkillDiff, 50, "The maximum difference in skill between the trivial of an item and the skill of the player if the trivial is higher than the skill. Recipes that have not been learnt or made at least once via the Experiment mode will be removed from searches based on this criteria.")
|
||||
RULE_INT(Skills, MaxTrainSpecializations, 50, "Maximum level a GM trainer will train casting specializations")
|
||||
RULE_INT(Skills, SwimmingStartValue, 100, "Start value of swimming skill")
|
||||
@@ -255,7 +257,9 @@ RULE_REAL(Pets, AttackCommandRange, 150, "Range at which a pet will respond to a
|
||||
RULE_BOOL(Pets, UnTargetableSwarmPet, false, "Setting whether swarm pets should be targetable")
|
||||
RULE_REAL(Pets, PetPowerLevelCap, 10, "Maximum number of levels a player pet can go up with pet power")
|
||||
RULE_BOOL(Pets, CanTakeNoDrop, false, "Setting whether anyone can give no-drop items to pets")
|
||||
RULE_BOOL(Pets, CanTakeQuestItems, true, "Setting whether anyone can give quest items to pets")
|
||||
RULE_BOOL(Pets, LivelikeBreakCharmOnInvis, true, "Default: true will break charm on any type of invis (hide/ivu/iva/etc) false will only break if the pet can not see you (ex. you have an undead pet and cast IVU")
|
||||
RULE_BOOL(Pets, ClientPetsUseOwnerNameInLastName, true, "Disable this to keep client pet's last names from being owner_name's pet")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(GM)
|
||||
@@ -285,7 +289,8 @@ RULE_BOOL(World, GMAccountIPList, false, "Check IP list against GM accounts. Thi
|
||||
RULE_INT(World, MinGMAntiHackStatus, 1, "Minimum status to check against AntiHack list")
|
||||
RULE_INT(World, SoFStartZoneID, -1, "Sets the Starting Zone for SoF Clients separate from Titanium Clients (-1 is disabled)")
|
||||
RULE_INT(World, TitaniumStartZoneID, -1, "Sets the Starting Zone for Titanium Clients (-1 is disabled). Replaces the old method")
|
||||
RULE_INT(World, ExpansionSettings, 16383, "Sets the expansion settings for the server, This is sent on login to world and affects client expansion settings. Defaults to all expansions enabled up to TSS, value is bitmask")
|
||||
RULE_INT(World, ExpansionSettings, 16383, "Sets the expansion settings bitmask for the server, This is sent on login to world and affects client expansion settings. Defaults to all expansions enabled up to TSS, value is bitmask")
|
||||
RULE_INT(World, CharacterSelectExpansionSettings, -1, "Sets the expansion settings bitmask for character select if you wish to override. -1 is off")
|
||||
RULE_BOOL(World, UseClientBasedExpansionSettings, true, "If true it will overrule World, ExpansionSettings and set someone's expansion based on the client they're using")
|
||||
RULE_INT(World, PVPSettings, 0, "Sets the PVP settings for the server. 1=Rallos Zek RuleSet, 2=Tallon/Vallon Zek Ruleset, 4=Sullon Zek Ruleset, 6=Discord Ruleset, anything above 6 is the Discord Ruleset without the no-drop restrictions removed. NOTE: edit IsAttackAllowed in Zone-table to accomodate for these rules")
|
||||
RULE_INT(World, PVPMinLevel, 0, "Minimum level to pvp")
|
||||
@@ -447,10 +452,14 @@ RULE_BOOL(Spells, TargetsTargetRequiresCombatRange, true, "Disable to remove com
|
||||
RULE_BOOL(Spells, NPCBuffLevelRestrictions, false, "Impose BuffLevelRestrictions on NPCs if true")
|
||||
RULE_INT(Spells, ResurrectionEffectBlock, 2, "0 = allow overwrites/rule disabled. If set to 1 = Block all buffs that would overwrite Resurrection Effects. If set to 2 = Will not overwrite Resurrection Effects, instead moves new buff to an empty slot if available. Default is 2.")
|
||||
RULE_BOOL(Spells, WaterMatchRequiredForLoS, true, "Enable/Disable the requirement of both the attacker/victim being both in or out of water for spells LoS to pass.")
|
||||
RULE_INT(Spells, WizardCritMinimumRandomRatio, 20, "The minimum value for the random range which Wizards and Caster DPS Mercs innately have for spell crit ratio. Set to 20 for vanilla values.")
|
||||
RULE_INT(Spells, WizardCritMaximumRandomRatio, 70, "The maximum value for the random range which Wizards and Caster DPS Mercs innately have for spell crit ratio. Set to 70 for vanilla values.")
|
||||
RULE_INT(Spells, DefensiveProcPenaltyLevelGap, 6, "Defensive Proc Penalty Level Gap where procs start losing their proc rate at RuleR(Spells, DefensiveProcPenaltyModifier)% per level difference")
|
||||
RULE_REAL(Spells, DefensiveProcPenaltyLevelGapModifier, 10.0f, "Defensive Proc Penalty Level Gap Modifier where procs start losing their proc rate at defined % after RuleI(Spells, DefensiveProcLevelGap) level difference")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Combat)
|
||||
RULE_REAL(Combat, AERampageSafeZone, 0.018, "max hit ae ramp reduction range")
|
||||
RULE_REAL(Combat, AERampageMaxDistance, 70, "Max AERampage range (% of max combat distance)")
|
||||
RULE_INT(Combat, PetBaseCritChance, 0, "Pet base crit chance")
|
||||
RULE_INT(Combat, NPCBashKickLevel, 6, "The level that NPCcan KICK/BASH")
|
||||
RULE_INT(Combat, MeleeCritDifficulty, 8900, "Value against which is rolled to check if a melee crit is triggered. Lower is easier")
|
||||
@@ -538,6 +547,7 @@ RULE_INT(NPC, LastFightingDelayMovingMin, 10000, "Minimum time before mob goes h
|
||||
RULE_INT(NPC, LastFightingDelayMovingMax, 20000, "Maximum time before mob goes home after all aggro loss (milliseconds)")
|
||||
RULE_BOOL(NPC, SmartLastFightingDelayMoving, true, "When true, mobs that started going home previously will do so again immediately if still on FD hate list")
|
||||
RULE_BOOL(NPC, ReturnNonQuestNoDropItems, false, "Returns NO DROP items on NPC that don't have an EVENT_TRADE sub in their script")
|
||||
RULE_BOOL(NPC, ReturnQuestItemsFromNonQuestNPCs, false, "Returns Quest items traded to NPCs that are not flagged as a Quest NPC")
|
||||
RULE_INT(NPC, StartEnrageValue, 9, " Percentage HP that an NPC will begin to enrage")
|
||||
RULE_BOOL(NPC, LiveLikeEnrage, false, "If set to true then only player controlled pets will enrage")
|
||||
RULE_BOOL(NPC, EnableMeritBasedFaction, false, "If set to true, faction will be given in the same way as experience (solo/group/raid)")
|
||||
@@ -617,7 +627,7 @@ RULE_BOOL(Bots, FinishBuffing, false, "Allow for buffs to complete even if the b
|
||||
RULE_BOOL(Bots, GroupBuffing, false, "Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB")
|
||||
RULE_INT(Bots, HealRotationMaxMembers, 24, "Maximum number of heal rotation members")
|
||||
RULE_INT(Bots, HealRotationMaxTargets, 12, "Maximum number of heal rotation targets")
|
||||
RULE_REAL(Bots, ManaRegen, 2.0, "Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players")
|
||||
RULE_REAL(Bots, ManaRegen, 2.0, "Adjust mana regen. Acts as a final multiplier, stacks with Rule Character:ManaRegenMultiplier.")
|
||||
RULE_BOOL(Bots, PreferNoManaCommandSpells, true, "Give sorting priority to newer no-mana spells (i.e., 'Bind Affinity')")
|
||||
RULE_BOOL(Bots, QuestableSpawnLimit, false, "Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl")
|
||||
RULE_INT(Bots, SpawnLimit, 71, "Number of bots a character can have spawned at one time, You + 71 bots is a 12 group pseudo-raid")
|
||||
@@ -635,6 +645,7 @@ RULE_BOOL(Bots, OldRaceRezEffects, false, "Older clients had ID 757 for races wi
|
||||
RULE_BOOL(Bots, ResurrectionSickness, true, "Use Resurrection Sickness based on Resurrection spell cast, set to false to disable Resurrection Sickness.")
|
||||
RULE_INT(Bots, OldResurrectionSicknessSpell, 757, "757 is Default Old Resurrection Sickness Spell")
|
||||
RULE_INT(Bots, ResurrectionSicknessSpell, 756, "756 is Default Resurrection Sickness Spell")
|
||||
RULE_BOOL(Bots, AllowPickpocketCommand, true, "Allows the use of the bot command 'pickpocket'")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Chat)
|
||||
@@ -811,6 +822,7 @@ RULE_CATEGORY_END()
|
||||
RULE_CATEGORY(Expansion)
|
||||
RULE_INT(Expansion, CurrentExpansion, -1, "The current expansion enabled for the server [-1 = ALL, 0 = Classic, 1 = Kunark etc.]")
|
||||
RULE_BOOL(Expansion, UseCurrentExpansionAAOnly, false, "When true will only load AA ranks that match CurrentExpansion rule")
|
||||
RULE_INT(Expansion, AutoGrantAAExpansion, -1, "Expansion to auto grant AAs up to, [-1 = Disabled, 0 = Classic, 1 = Kunark etc.]")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Instances)
|
||||
|
||||
+2
-1
@@ -376,7 +376,7 @@ std::string EQ::SayLinkEngine::InjectSaylinksIfNotExist(const char *message)
|
||||
|
||||
void EQ::SayLinkEngine::LoadCachedSaylinks()
|
||||
{
|
||||
auto saylinks = SaylinkRepository::GetWhere(database, "phrase not like '%#%'");
|
||||
auto saylinks = SaylinkRepository::GetWhere(database, "phrase not REGEXP BINARY '[A-Z]' and phrase not REGEXP '[0-9]'");
|
||||
LogSaylink("Loaded [{}] saylinks into cache", saylinks.size());
|
||||
g_cached_saylinks = saylinks;
|
||||
}
|
||||
@@ -399,6 +399,7 @@ SaylinkRepository::Saylink EQ::SayLinkEngine::GetOrSaveSaylink(std::string sayli
|
||||
|
||||
// return if found from the database
|
||||
if (!saylinks.empty()) {
|
||||
g_cached_saylinks.emplace_back(saylinks[0]);
|
||||
return saylinks[0];
|
||||
}
|
||||
|
||||
|
||||
+88
-67
@@ -10,6 +10,7 @@
|
||||
#include <cereal/types/chrono.hpp>
|
||||
#include <cereal/types/string.hpp>
|
||||
#include <cereal/types/vector.hpp>
|
||||
#include <glm/vec4.hpp>
|
||||
|
||||
#define SERVER_TIMEOUT 45000 // how often keepalive gets sent
|
||||
#define INTERSERVER_TIMER 10000
|
||||
@@ -113,6 +114,7 @@
|
||||
#define ServerOP_GroupFollowAck 0x0111
|
||||
#define ServerOP_GroupCancelInvite 0x0112
|
||||
#define ServerOP_RaidMOTD 0x0113
|
||||
#define ServerOP_RaidNote 0x0114
|
||||
|
||||
#define ServerOP_InstanceUpdateTime 0x014F
|
||||
#define ServerOP_AdventureRequest 0x0150
|
||||
@@ -248,6 +250,7 @@
|
||||
#define ServerOP_ReloadZonePoints 0x4122
|
||||
#define ServerOP_ReloadDzTemplates 0x4123
|
||||
#define ServerOP_ReloadZoneData 0x4124
|
||||
#define ServerOP_ReloadDataBucketsCache 0x4125
|
||||
|
||||
#define ServerOP_CZDialogueWindow 0x4500
|
||||
#define ServerOP_CZLDoNUpdate 0x4501
|
||||
@@ -285,6 +288,8 @@
|
||||
// player events
|
||||
#define ServerOP_PlayerEvent 0x5100
|
||||
|
||||
#define ServerOP_DataBucketCacheUpdate 0x5200
|
||||
|
||||
enum {
|
||||
CZUpdateType_Character,
|
||||
CZUpdateType_Group,
|
||||
@@ -1075,6 +1080,10 @@ struct ServerRaidMOTD_Struct {
|
||||
char motd[0];
|
||||
};
|
||||
|
||||
struct ServerRaidNote_Struct {
|
||||
uint32 rid;
|
||||
};
|
||||
|
||||
struct ServerLFGMatchesRequest_Struct {
|
||||
uint32 FromID;
|
||||
uint8 QuerierLevel;
|
||||
@@ -1478,95 +1487,96 @@ struct CZClientMessageString_Struct {
|
||||
|
||||
struct CZDialogueWindow_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
char message[4096];
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
char message[4096];
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
};
|
||||
|
||||
struct CZLDoNUpdate_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
uint8 update_subtype; // 0 - Loss, 1 - Points, 2 - Win
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
uint8 update_subtype; // 0 - Loss, 1 - Points, 2 - Win
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint32 theme_id;
|
||||
int points; // Only used in Points Subtype, else 1
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
int points; // Only used in Points Subtype, else 1
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
};
|
||||
|
||||
struct CZMarquee_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint32 type;
|
||||
uint32 priority;
|
||||
uint32 fade_in;
|
||||
uint32 fade_out;
|
||||
uint32 duration;
|
||||
char message[512];
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
char message[512];
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
};
|
||||
|
||||
struct CZMessage_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
int update_identifier; // Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
int update_identifier; // Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint32 type;
|
||||
char message[512];
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
char message[512];
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
};
|
||||
|
||||
struct CZMove_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
uint8 update_subtype; // 0 - Move Zone, 1 - Move Zone Instance
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint16 instance_id; // Only used by Move Zone Instance, else 0
|
||||
char zone_short_name[32]; // Only by with Move Zone, else empty
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
std::string client_name = std::string(); // Only used by Character Name Type, else empty
|
||||
glm::vec4 coordinates = glm::vec4(0.f); // XYZ or XYZH, heading is optional, defaults to 0.
|
||||
uint16 instance_id = 0; // Only used by Move Zone Instance, else 0
|
||||
uint32 update_identifier = 0; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
uint8 update_subtype; // 0 - Move Zone, 1 - Move Zone Instance
|
||||
std::string zone_short_name = std::string(); // Only used by Move Zone, else empty
|
||||
};
|
||||
|
||||
struct CZSetEntityVariable_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name, 6 - NPC
|
||||
int update_identifier; // Group ID, Raid ID, Guild ID, Expedition ID, or NPC ID based on update type, 0 for Character Name
|
||||
char variable_name[256];
|
||||
char variable_value[256];
|
||||
char client_name[64]; // Only used by Character Type, else empty
|
||||
int update_identifier; // Group ID, Raid ID, Guild ID, Expedition ID, or NPC ID based on update type, 0 for Character Name
|
||||
char variable_name[256];
|
||||
char variable_value[256];
|
||||
char client_name[64]; // Only used by Character Type, else empty
|
||||
};
|
||||
|
||||
struct CZSignal_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name, 6 - NPC
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, Expedition ID, or NPC ID based on update type, 0 for Character Name
|
||||
int signal_id;
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, Expedition ID, or NPC ID based on update type, 0 for Character Name
|
||||
int signal_id;
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
};
|
||||
|
||||
struct CZSpell_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
uint8 update_subtype; // 0 - Cast Spell, 1 - Remove Spell
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
uint8 update_subtype; // 0 - Cast Spell, 1 - Remove Spell
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint32 spell_id;
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
};
|
||||
|
||||
struct CZTaskUpdate_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
uint8 update_subtype; // 0 - Activity Reset, 1 - Activity Update, 2 - Assign Task, 3 - Disable Task, 4 - Enable Task, 5 - Fail Task, 6 - Remove Task
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
uint8 update_subtype; // 0 - Activity Reset, 1 - Activity Update, 2 - Assign Task, 3 - Disable Task, 4 - Enable Task, 5 - Fail Task, 6 - Remove Task
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint32 task_identifier;
|
||||
int task_subidentifier; // Activity ID for Activity Reset and Activity Update, NPC Entity ID for Assign Task, else -1
|
||||
int update_count; // Only used by Activity Update, else 1
|
||||
bool enforce_level_requirement; // Only used by Assign Task
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
int task_subidentifier; // Activity ID for Activity Reset and Activity Update, NPC Entity ID for Assign Task, else -1
|
||||
int update_count; // Only used by Activity Update, else 1
|
||||
bool enforce_level_requirement; // Only used by Assign Task
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
};
|
||||
|
||||
struct WWDialogueWindow_Struct {
|
||||
char message[4096];
|
||||
char message[4096];
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct WWLDoNUpdate_Struct {
|
||||
uint8 update_type; // 0 - Loss, 1 - Points, 2 - Win
|
||||
uint8 update_type; // 0 - Loss, 1 - Points, 2 - Win
|
||||
uint32 theme_id;
|
||||
int points; // Only used in Points Subtype, else 1
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
int points; // Only used in Points Subtype, else 1
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct WWMarquee_Struct {
|
||||
@@ -1575,56 +1585,57 @@ struct WWMarquee_Struct {
|
||||
uint32 fade_in;
|
||||
uint32 fade_out;
|
||||
uint32 duration;
|
||||
char message[512];
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
char message[512];
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct WWMessage_Struct {
|
||||
uint32 type;
|
||||
char message[512];
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
char message[512];
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct WWMove_Struct {
|
||||
uint8 update_type; // 0 - Move Zone, 1 - Move Zone Instance
|
||||
char zone_short_name[32]; // Used with Move Zone
|
||||
uint8 update_type; // 0 - Move Zone, 1 - Move Zone Instance
|
||||
char zone_short_name[32]; // Used with Move Zone
|
||||
uint16 instance_id; // Used with Move Zone Instance
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
|
||||
struct WWSetEntityVariable_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - NPC
|
||||
char variable_name[256];
|
||||
char variable_value[256];
|
||||
char variable_name[256];
|
||||
char variable_value[256];
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct WWSignal_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - NPC
|
||||
int signal_id;
|
||||
int signal_id;
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct WWSpell_Struct {
|
||||
uint8 update_type; // 0 - Cast Spell, 1 - Remove Spell
|
||||
uint8 update_type; // 0 - Cast Spell, 1 - Remove Spell
|
||||
uint32 spell_id;
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct WWTaskUpdate_Struct {
|
||||
uint8 update_type; // 0 - Activity Reset, 1 - Activity Update, 2 - Assign Task, 3 - Disable Task, 4 - Enable Task, 5 - Fail Task, 6 - Remove Task
|
||||
uint8 update_type; // 0 - Activity Reset, 1 - Activity Update, 2 - Assign Task, 3 - Disable Task, 4 - Enable Task, 5 - Fail Task, 6 - Remove Task
|
||||
uint32 task_identifier;
|
||||
int task_subidentifier; // Activity ID for Activity Reset and Activity Update, NPC Entity ID for Assign Task, else -1
|
||||
int update_count; // Update Count for Activity Update, else 1
|
||||
bool enforce_level_requirement; // Only used by Assign Task, else false
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
int task_subidentifier; // Activity ID for Activity Reset and Activity Update, NPC Entity ID for Assign Task, else -1
|
||||
int update_count; // Update Count for Activity Update, else 1
|
||||
bool enforce_level_requirement; // Only used by Assign Task, else false
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct ReloadWorld_Struct {
|
||||
@@ -1815,6 +1826,11 @@ struct ServerSendPlayerEvent_Struct {
|
||||
char cereal_data[0];
|
||||
};
|
||||
|
||||
struct ServerDataBucketCacheUpdate_Struct {
|
||||
uint32_t cereal_size;
|
||||
char cereal_data[0];
|
||||
};
|
||||
|
||||
struct ServerFlagUpdate_Struct {
|
||||
uint32 account_id;
|
||||
int16 admin;
|
||||
@@ -1824,6 +1840,11 @@ struct ServerOOCMute_Struct {
|
||||
bool is_muted;
|
||||
};
|
||||
|
||||
struct ServerZoneStatus_Struct {
|
||||
char name[64];
|
||||
int16 admin;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#endif
|
||||
|
||||
+54
-15
@@ -1635,25 +1635,29 @@ bool SharedDatabase::GetCommandSettings(std::map<std::string, std::pair<uint8, s
|
||||
{
|
||||
command_settings.clear();
|
||||
|
||||
const std::string query = "SELECT `command`, `access`, `aliases` FROM `command_settings`";
|
||||
const std::string& query = "SELECT `command`, `access`, `aliases` FROM `command_settings`";
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
if (!results.Success() || !results.RowCount()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto& row = results.begin(); row != results.end(); ++row) {
|
||||
for (auto row : results) {
|
||||
command_settings[row[0]].first = Strings::ToUnsignedInt(row[1]);
|
||||
if (row[2][0] == 0)
|
||||
if (row[2][0] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<std::string> aliases = Strings::Split(row[2], '|');
|
||||
for (auto iter = aliases.begin(); iter != aliases.end(); ++iter) {
|
||||
if (iter->empty())
|
||||
for (const auto& e : aliases) {
|
||||
if (e.empty()) {
|
||||
continue;
|
||||
command_settings[row[0]].second.push_back(*iter);
|
||||
}
|
||||
|
||||
command_settings[row[0]].second.push_back(e);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharedDatabase::UpdateInjectedCommandSettings(const std::vector<std::pair<std::string, uint8>> &injected)
|
||||
@@ -1668,13 +1672,15 @@ bool SharedDatabase::UpdateInjectedCommandSettings(const std::vector<std::pair<s
|
||||
)
|
||||
);
|
||||
|
||||
if (!QueryDatabase(query).Success()) {
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LogInfo(
|
||||
"[{0}] New Command(s) Added",
|
||||
injected.size()
|
||||
"[{}] New Command{} Added",
|
||||
injected.size(),
|
||||
injected.size() != 1 ? "s" : ""
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1684,25 +1690,58 @@ bool SharedDatabase::UpdateInjectedCommandSettings(const std::vector<std::pair<s
|
||||
bool SharedDatabase::UpdateOrphanedCommandSettings(const std::vector<std::string> &orphaned)
|
||||
{
|
||||
if (orphaned.size()) {
|
||||
const std::string query = fmt::format(
|
||||
std::string query = fmt::format(
|
||||
"DELETE FROM `command_settings` WHERE `command` IN ({})",
|
||||
Strings::ImplodePair(",", std::pair<char, char>('\'', '\''), orphaned)
|
||||
);
|
||||
|
||||
if (!QueryDatabase(query).Success()) {
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
query = fmt::format(
|
||||
"DELETE FROM `command_subsettings` WHERE `parent_command` IN ({})",
|
||||
Strings::ImplodePair(",", std::pair<char, char>('\'', '\''), orphaned)
|
||||
);
|
||||
|
||||
auto results_two = QueryDatabase(query);
|
||||
if (!results_two.Success()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LogInfo(
|
||||
"{} Orphaned Command{} Deleted",
|
||||
"{} Orphaned Command{} Deleted | {} Orphaned Subcommand{} Deleted",
|
||||
orphaned.size(),
|
||||
(orphaned.size() == 1 ? "" : "s")
|
||||
orphaned.size() != 1 ? "s" : "",
|
||||
results_two.RowsAffected(),
|
||||
results_two.RowsAffected() != 1 ? "s" : ""
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharedDatabase::GetCommandSubSettings(std::vector<CommandSubsettingsRepository::CommandSubsettings> &command_subsettings)
|
||||
{
|
||||
command_subsettings.clear();
|
||||
|
||||
const auto& l = CommandSubsettingsRepository::GetAll(*this);
|
||||
|
||||
if (l.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
command_subsettings.reserve(l.size());
|
||||
|
||||
for (const auto& e : l) {
|
||||
command_subsettings.emplace_back(e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SharedDatabase::LoadSkillCaps(const std::string &prefix) {
|
||||
skill_caps_mmf.reset(nullptr);
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "fixed_memory_hash_set.h"
|
||||
#include "fixed_memory_variable_hash_set.h"
|
||||
#include "say_link.h"
|
||||
#include "repositories/command_subsettings_repository.h"
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
@@ -77,6 +78,7 @@ public:
|
||||
bool GetCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &command_settings);
|
||||
bool UpdateInjectedCommandSettings(const std::vector<std::pair<std::string, uint8>> &injected);
|
||||
bool UpdateOrphanedCommandSettings(const std::vector<std::string> &orphaned);
|
||||
bool GetCommandSubSettings(std::vector<CommandSubsettingsRepository::CommandSubsettings> &command_subsettings);
|
||||
uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID);
|
||||
bool SetGMInvul(uint32 account_id, bool gminvul);
|
||||
bool SetGMFlymode(uint32 account_id, uint8 flymode);
|
||||
|
||||
+52
-15
@@ -376,7 +376,7 @@ std::string Strings::Money(uint64 platinum, uint64 gold, uint64 silver, uint64 c
|
||||
std::string money_string = "Unknown";
|
||||
if (copper && silver && gold && platinum) { // CSGP
|
||||
money_string = fmt::format(
|
||||
"{} Platinum, {} Gold, {} Silver, and {} Copper",
|
||||
"{} platinum, {} gold, {} silver, and {} copper",
|
||||
Strings::Commify(std::to_string(platinum)),
|
||||
Strings::Commify(std::to_string(gold)),
|
||||
Strings::Commify(std::to_string(silver)),
|
||||
@@ -385,7 +385,7 @@ std::string Strings::Money(uint64 platinum, uint64 gold, uint64 silver, uint64 c
|
||||
}
|
||||
else if (copper && silver && !gold && platinum) { // CSP
|
||||
money_string = fmt::format(
|
||||
"{} Platinum, {} Silver, and {} Copper",
|
||||
"{} platinum, {} silver, and {} copper",
|
||||
Strings::Commify(std::to_string(platinum)),
|
||||
Strings::Commify(std::to_string(silver)),
|
||||
Strings::Commify(std::to_string(copper))
|
||||
@@ -393,7 +393,7 @@ std::string Strings::Money(uint64 platinum, uint64 gold, uint64 silver, uint64 c
|
||||
}
|
||||
else if (copper && silver && gold && !platinum) { // CSG
|
||||
money_string = fmt::format(
|
||||
"{} Gold, {} Silver, and {} Copper",
|
||||
"{} gold, {} silver, and {} copper",
|
||||
Strings::Commify(std::to_string(gold)),
|
||||
Strings::Commify(std::to_string(silver)),
|
||||
Strings::Commify(std::to_string(copper))
|
||||
@@ -401,21 +401,21 @@ std::string Strings::Money(uint64 platinum, uint64 gold, uint64 silver, uint64 c
|
||||
}
|
||||
else if (copper && !silver && !gold && platinum) { // CP
|
||||
money_string = fmt::format(
|
||||
"{} Platinum and {} Copper",
|
||||
"{} platinum and {} copper",
|
||||
Strings::Commify(std::to_string(platinum)),
|
||||
Strings::Commify(std::to_string(copper))
|
||||
);
|
||||
}
|
||||
else if (copper && silver && !gold && !platinum) { // CS
|
||||
money_string = fmt::format(
|
||||
"{} Silver and {} Copper",
|
||||
"{} silver and {} copper",
|
||||
Strings::Commify(std::to_string(silver)),
|
||||
Strings::Commify(std::to_string(copper))
|
||||
);
|
||||
}
|
||||
else if (!copper && silver && gold && platinum) { // SGP
|
||||
money_string = fmt::format(
|
||||
"{} Platinum, {} Gold, and {} Silver",
|
||||
"{} platinum, {} gold, and {} silver",
|
||||
Strings::Commify(std::to_string(platinum)),
|
||||
Strings::Commify(std::to_string(gold)),
|
||||
Strings::Commify(std::to_string(silver))
|
||||
@@ -423,21 +423,21 @@ std::string Strings::Money(uint64 platinum, uint64 gold, uint64 silver, uint64 c
|
||||
}
|
||||
else if (!copper && silver && !gold && platinum) { // SP
|
||||
money_string = fmt::format(
|
||||
"{} Platinum and {} Silver",
|
||||
"{} platinum and {} silver",
|
||||
Strings::Commify(std::to_string(platinum)),
|
||||
Strings::Commify(std::to_string(silver))
|
||||
);
|
||||
}
|
||||
else if (!copper && silver && gold && !platinum) { // SG
|
||||
money_string = fmt::format(
|
||||
"{} Gold and {} Silver",
|
||||
"{} gold and {} silver",
|
||||
Strings::Commify(std::to_string(gold)),
|
||||
Strings::Commify(std::to_string(silver))
|
||||
);
|
||||
}
|
||||
else if (copper && !silver && gold && platinum) { // CGP
|
||||
money_string = fmt::format(
|
||||
"{} Platinum, {} Gold, and {} Copper",
|
||||
"{} platinum, {} gold, and {} copper",
|
||||
Strings::Commify(std::to_string(platinum)),
|
||||
Strings::Commify(std::to_string(gold)),
|
||||
Strings::Commify(std::to_string(copper))
|
||||
@@ -445,39 +445,39 @@ std::string Strings::Money(uint64 platinum, uint64 gold, uint64 silver, uint64 c
|
||||
}
|
||||
else if (copper && !silver && gold && !platinum) { // CG
|
||||
money_string = fmt::format(
|
||||
"{} Gold and {} Copper",
|
||||
"{} gold and {} copper",
|
||||
Strings::Commify(std::to_string(gold)),
|
||||
Strings::Commify(std::to_string(copper))
|
||||
);
|
||||
}
|
||||
else if (!copper && !silver && gold && platinum) { // GP
|
||||
money_string = fmt::format(
|
||||
"{} Platinum and {} Gold",
|
||||
"{} platinum and {} gold",
|
||||
Strings::Commify(std::to_string(platinum)),
|
||||
Strings::Commify(std::to_string(gold))
|
||||
);
|
||||
}
|
||||
else if (!copper && !silver && !gold && platinum) { // P
|
||||
money_string = fmt::format(
|
||||
"{} Platinum",
|
||||
"{} platinum",
|
||||
Strings::Commify(std::to_string(platinum))
|
||||
);
|
||||
}
|
||||
else if (!copper && !silver && gold && !platinum) { // G
|
||||
money_string = fmt::format(
|
||||
"{} Gold",
|
||||
"{} gold",
|
||||
Strings::Commify(std::to_string(gold))
|
||||
);
|
||||
}
|
||||
else if (!copper && silver && !gold && !platinum) { // S
|
||||
money_string = fmt::format(
|
||||
"{} Silver",
|
||||
"{} silver",
|
||||
Strings::Commify(std::to_string(silver))
|
||||
);
|
||||
}
|
||||
else if (copper && !silver && !gold && !platinum) { // C
|
||||
money_string = fmt::format(
|
||||
"{} Copper",
|
||||
"{} copper",
|
||||
Strings::Commify(std::to_string(copper))
|
||||
);
|
||||
}
|
||||
@@ -695,8 +695,31 @@ std::string Strings::ConvertToDigit(int n, const std::string& suffix)
|
||||
return NUM_TO_ENGLISH_X[n] + suffix;
|
||||
}
|
||||
}
|
||||
|
||||
bool Strings::BeginsWith(const std::string& subject, const std::string& search)
|
||||
{
|
||||
if (subject.length() < search.length()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return subject.starts_with(search);
|
||||
}
|
||||
|
||||
bool Strings::EndsWith(const std::string& subject, const std::string& search)
|
||||
{
|
||||
if (subject.length() < search.length()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return subject.ends_with(search);
|
||||
}
|
||||
|
||||
bool Strings::Contains(const std::string& subject, const std::string& search)
|
||||
{
|
||||
if (subject.length() < search.length()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return subject.find(search) != std::string::npos;
|
||||
}
|
||||
|
||||
@@ -859,3 +882,17 @@ std::string Strings::RemoveNumbers(std::string s)
|
||||
|
||||
return s.substr(0, current);
|
||||
}
|
||||
|
||||
std::string Strings::ZoneTime(const uint8 hours, const uint8 minutes)
|
||||
{
|
||||
return fmt::format(
|
||||
"{:02}:{:02} {}",
|
||||
(
|
||||
(hours % 12) == 0 ?
|
||||
12 :
|
||||
(hours % 12)
|
||||
),
|
||||
minutes,
|
||||
hours >= 13 ? "PM" : "AM"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -128,6 +128,9 @@ public:
|
||||
static bool ToBool(const std::string& bool_string);
|
||||
static inline bool EqualFold(const std::string &string_one, const std::string &string_two) { return strcasecmp(string_one.c_str(), string_two.c_str()) == 0; }
|
||||
static std::string Random(size_t length);
|
||||
static bool BeginsWith(const std::string& subject, const std::string& search);
|
||||
static bool EndsWith(const std::string& subject, const std::string& search);
|
||||
static std::string ZoneTime(const uint8 hours, const uint8 minutes);
|
||||
|
||||
template<typename T>
|
||||
static std::string
|
||||
|
||||
+2
-2
@@ -25,7 +25,7 @@
|
||||
|
||||
// Build variables
|
||||
// these get injected during the build pipeline
|
||||
#define CURRENT_VERSION "22.15.3-dev" // always append -dev to the current version for custom-builds
|
||||
#define CURRENT_VERSION "22.26.2-dev" // always append -dev to the current version for custom-builds
|
||||
#define LOGIN_VERSION "0.8.0"
|
||||
#define COMPILE_DATE __DATE__
|
||||
#define COMPILE_TIME __TIME__
|
||||
@@ -42,7 +42,7 @@
|
||||
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9228
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9236
|
||||
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9039
|
||||
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "../common/global_define.h"
|
||||
#include "../common/eqemu_logsys.h"
|
||||
#include <iomanip>
|
||||
|
||||
#include "worldconn.h"
|
||||
#include "eqemu_config.h"
|
||||
#include "md5.h"
|
||||
#include "servertalk.h"
|
||||
|
||||
WorldConnection::WorldConnection(EmuTCPConnection::ePacketMode mode, const char *password)
|
||||
: m_password(password)
|
||||
{
|
||||
tcpc.SetPacketMode(mode);
|
||||
pTryReconnect = true;
|
||||
pConnected = false;
|
||||
}
|
||||
|
||||
WorldConnection::~WorldConnection() {
|
||||
}
|
||||
|
||||
bool WorldConnection::SendPacket(ServerPacket* pack) {
|
||||
if (!Connected())
|
||||
return false;
|
||||
return tcpc.SendPacket(pack);
|
||||
}
|
||||
|
||||
void WorldConnection::OnConnected() {
|
||||
const EQEmuConfig *Config=EQEmuConfig::get();
|
||||
LogNetcode("[WORLD] Connected to World: [{}]:[{}]", Config->WorldIP.c_str(), Config->WorldTCPPort);
|
||||
|
||||
auto pack = new ServerPacket(ServerOP_ZAAuth, 16);
|
||||
MD5::Generate((const uchar*) m_password.c_str(), m_password.length(), pack->pBuffer);
|
||||
SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
|
||||
void WorldConnection::Process() {
|
||||
//persistent connection....
|
||||
if (!Connected()) {
|
||||
pConnected = tcpc.Connected();
|
||||
if (pConnected) {
|
||||
OnConnected();
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void WorldConnection::AsyncConnect() {
|
||||
const EQEmuConfig *Config=EQEmuConfig::get();
|
||||
tcpc.AsyncConnect(Config->WorldIP.c_str(), Config->WorldTCPPort);
|
||||
}
|
||||
|
||||
bool WorldConnection::Connect() {
|
||||
const EQEmuConfig *Config=EQEmuConfig::get();
|
||||
char errbuf[TCPConnection_ErrorBufferSize];
|
||||
if (tcpc.Connect(Config->WorldIP.c_str(), Config->WorldTCPPort, errbuf)) {
|
||||
return true;
|
||||
} else {
|
||||
LogNetcode("[WORLD] WorldConnection connect: Connecting to the server [{}]:[{}] failed: [{}]", Config->WorldIP.c_str(), Config->WorldTCPPort, errbuf);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void WorldConnection::Disconnect() {
|
||||
tcpc.Disconnect();
|
||||
}
|
||||
|
||||
+9
-13
@@ -370,7 +370,7 @@ uint32 ZoneStore::GetZoneRuleSet(uint32 zone_id, int version)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const std::string& ZoneStore::GetZoneNote(uint32 zone_id, int version)
|
||||
const std::string ZoneStore::GetZoneNote(uint32 zone_id, int version)
|
||||
{
|
||||
for (auto &z: m_zones) {
|
||||
if (z.zoneidnumber == zone_id && z.version == version) {
|
||||
@@ -384,8 +384,7 @@ const std::string& ZoneStore::GetZoneNote(uint32 zone_id, int version)
|
||||
}
|
||||
}
|
||||
|
||||
const auto& note = std::string();
|
||||
return note;
|
||||
return "";
|
||||
}
|
||||
|
||||
float ZoneStore::GetZoneUnderworld(uint32 zone_id, int version)
|
||||
@@ -736,7 +735,7 @@ float ZoneStore::GetZoneFogDensity(uint32 zone_id, int version)
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
const std::string& ZoneStore::GetZoneFlagNeeded(uint32 zone_id, int version)
|
||||
const std::string ZoneStore::GetZoneFlagNeeded(uint32 zone_id, int version)
|
||||
{
|
||||
for (auto &z: m_zones) {
|
||||
if (z.zoneidnumber == zone_id && z.version == version) {
|
||||
@@ -750,8 +749,7 @@ const std::string& ZoneStore::GetZoneFlagNeeded(uint32 zone_id, int version)
|
||||
}
|
||||
}
|
||||
|
||||
const auto& flag_needed = std::string();
|
||||
return flag_needed;
|
||||
return "";
|
||||
}
|
||||
|
||||
int8 ZoneStore::GetZoneCanBind(uint32 zone_id, int version)
|
||||
@@ -1259,7 +1257,7 @@ int8 ZoneStore::GetZoneMaximumExpansion(uint32 zone_id, int version)
|
||||
return DEFAULT_ZONE_MIN_MAX_EXPANSION;
|
||||
}
|
||||
|
||||
const std::string& ZoneStore::GetZoneContentFlags(uint32 zone_id, int version)
|
||||
const std::string ZoneStore::GetZoneContentFlags(uint32 zone_id, int version)
|
||||
{
|
||||
for (auto &z: m_zones) {
|
||||
if (z.zoneidnumber == zone_id && z.version == version) {
|
||||
@@ -1271,13 +1269,12 @@ const std::string& ZoneStore::GetZoneContentFlags(uint32 zone_id, int version)
|
||||
if (z.zoneidnumber == zone_id && z.version == 0) {
|
||||
return z.content_flags;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const auto& content_flags = std::string();
|
||||
return content_flags;
|
||||
return "";
|
||||
}
|
||||
|
||||
const std::string& ZoneStore::GetZoneContentFlagsDisabled(uint32 zone_id, int version)
|
||||
const std::string ZoneStore::GetZoneContentFlagsDisabled(uint32 zone_id, int version)
|
||||
{
|
||||
for (auto &z: m_zones) {
|
||||
if (z.zoneidnumber == zone_id && z.version == version) {
|
||||
@@ -1291,8 +1288,7 @@ const std::string& ZoneStore::GetZoneContentFlagsDisabled(uint32 zone_id, int ve
|
||||
}
|
||||
}
|
||||
|
||||
const auto& content_flags_disabled = std::string();
|
||||
return content_flags_disabled;
|
||||
return "";
|
||||
}
|
||||
|
||||
int ZoneStore::GetZoneUnderworldTeleportIndex(uint32 zone_id, int version)
|
||||
|
||||
+4
-4
@@ -54,7 +54,7 @@ public:
|
||||
int GetZoneTimeZone(uint32 zone_id, int version = 0);
|
||||
int GetZoneMaximumPlayers(uint32 zone_id, int version = 0);
|
||||
uint32 GetZoneRuleSet(uint32 zone_id, int version = 0);
|
||||
const std::string& GetZoneNote(uint32 zone_id, int version = 0);
|
||||
const std::string GetZoneNote(uint32 zone_id, int version = 0);
|
||||
float GetZoneUnderworld(uint32 zone_id, int version = 0);
|
||||
float GetZoneMinimumClip(uint32 zone_id, int version = 0);
|
||||
float GetZoneMaximumClip(uint32 zone_id, int version = 0);
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
float GetZoneWalkSpeed(uint32 zone_id, int version = 0);
|
||||
uint8 GetZoneTimeType(uint32 zone_id, int version = 0);
|
||||
float GetZoneFogDensity(uint32 zone_id, int version = 0);
|
||||
const std::string& GetZoneFlagNeeded(uint32 zone_id, int version = 0);
|
||||
const std::string GetZoneFlagNeeded(uint32 zone_id, int version = 0);
|
||||
int8 GetZoneCanBind(uint32 zone_id, int version = 0);
|
||||
int8 GetZoneCanCombat(uint32 zone_id, int version = 0);
|
||||
int8 GetZoneCanLevitate(uint32 zone_id, int version = 0);
|
||||
@@ -95,8 +95,8 @@ public:
|
||||
uint32 GetZoneMaximumMovementUpdateRange(uint32 zone_id, int version = 0);
|
||||
int8 GetZoneMinimumExpansion(uint32 zone_id, int version = 0);
|
||||
int8 GetZoneMaximumExpansion(uint32 zone_id, int version = 0);
|
||||
const std::string& GetZoneContentFlags(uint32 zone_id, int version = 0);
|
||||
const std::string& GetZoneContentFlagsDisabled(uint32 zone_id, int version = 0);
|
||||
const std::string GetZoneContentFlags(uint32 zone_id, int version = 0);
|
||||
const std::string GetZoneContentFlagsDisabled(uint32 zone_id, int version = 0);
|
||||
int GetZoneUnderworldTeleportIndex(uint32 zone_id, int version = 0);
|
||||
int GetZoneLavaDamage(uint32 zone_id, int version = 0);
|
||||
int GetZoneMinimumLavaDamage(uint32 zone_id, int version = 0);
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eqemu-server",
|
||||
"version": "22.15.3",
|
||||
"version": "22.26.2",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/EQEmu/Server.git"
|
||||
|
||||
@@ -301,9 +301,7 @@ OP_LeadershipExpUpdate=0x2797
|
||||
OP_PurchaseLeadershipAA=0x6c55
|
||||
OP_UpdateLeadershipAA=0x0026
|
||||
OP_MarkNPC=0x1fb5
|
||||
OP_MarkRaidNPC=0x5a58 #unimplemented
|
||||
OP_ClearNPCMarks=0x2003
|
||||
OP_ClearRaidNPCMarks=0x20d3 #unimplemented
|
||||
OP_DelegateAbility=0x76b8
|
||||
OP_SetGroupTarget=0x2814
|
||||
OP_Charm=0x5d92
|
||||
@@ -372,6 +370,7 @@ OP_AggroMeterTargetInfo=0x16bc
|
||||
OP_AggroMeterUpdate=0x1781
|
||||
OP_UnderWorld=0x2eb3 # clients sends up when they detect an underworld issue, might be useful for cheat detection
|
||||
OP_KickPlayers=0x6770
|
||||
OP_BookButton=0x6146
|
||||
|
||||
# Expeditions
|
||||
OP_DzQuit=0xb2e3
|
||||
@@ -544,6 +543,9 @@ OP_LFGResponse=0x0000
|
||||
OP_RaidInvite=0x55ac
|
||||
OP_RaidUpdate=0x3973
|
||||
OP_RaidJoin=0x0000
|
||||
OP_RaidDelegateAbility=0x2b33
|
||||
OP_MarkRaidNPC=0x5a58
|
||||
OP_RaidClearNPCMarks=0x20d3
|
||||
|
||||
# Button-push commands
|
||||
OP_Taunt=0x2703
|
||||
|
||||
@@ -360,6 +360,7 @@ OP_Marquee=0x7dc9
|
||||
OP_Fling=0x2b88
|
||||
OP_CancelSneakHide=0x7705
|
||||
OP_UnderWorld=0x51ae # clients sends up when they detect an underworld issue, might be useful for cheat detection
|
||||
OP_BookButton=0x4348
|
||||
|
||||
# Expedition
|
||||
OP_DzQuit=0x054e
|
||||
|
||||
@@ -341,6 +341,7 @@ OP_Marquee=0x2f75
|
||||
OP_Untargetable=0x3e36
|
||||
OP_CancelSneakHide=0x5335
|
||||
OP_UnderWorld=0x7580 # clients sends up when they detect an underworld issue, might be useful for cheat detection
|
||||
OP_BookButton=0x4eee
|
||||
|
||||
#expedition
|
||||
OP_DzQuit=0x20d6
|
||||
|
||||
@@ -371,6 +371,7 @@ OP_Marquee=0x3675
|
||||
OP_Fling=0x51b1
|
||||
OP_CancelSneakHide=0x7686
|
||||
OP_UnderWorld=0x2d9d # clients sends up when they detect an underworld issue, might be useful for cheat detection
|
||||
OP_BookButton=0x018e
|
||||
|
||||
OP_DzQuit=0x1539
|
||||
OP_DzListTimers=0x21e9
|
||||
|
||||
@@ -112,6 +112,7 @@ if ($requested_table_to_generate ne "all") {
|
||||
}
|
||||
|
||||
my @cereal_enabled_tables = (
|
||||
"data_buckets",
|
||||
"player_event_logs"
|
||||
);
|
||||
|
||||
@@ -586,7 +587,8 @@ sub get_reserved_cpp_variable_names {
|
||||
return (
|
||||
"class",
|
||||
"int",
|
||||
"key"
|
||||
"key",
|
||||
"range"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ echo "Generating [create_*] table exports..."
|
||||
bash -c "${world_bin} database:dump --login-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_login.sql"
|
||||
bash -c "${world_bin} database:dump --player-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_player.sql"
|
||||
bash -c "${world_bin} database:dump --state-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_state.sql"
|
||||
echo 'REPLACE INTO `instance_list` VALUES (1,25,1,1,0,0,1),(2,25,2,1,0,0,1),(3,151,1,1,0,0,1),(4,114,1,1,0,0,1),(5,344,1,1,0,0,1),(6,202,0,1,0,0,1);' >> "${dump_path}create_tables_state.sql"
|
||||
bash -c "${world_bin} database:dump --static-instance-data --dump-output-to-console >> ${dump_path}create_tables_state.sql"
|
||||
bash -c "${world_bin} database:dump --query-serv-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_queryserv.sql"
|
||||
|
||||
# with content
|
||||
|
||||
@@ -15,6 +15,7 @@ void WorldserverCLI::DatabaseDump(int argc, char **argv, argh::parser &cmd, std:
|
||||
"--state-tables",
|
||||
"--system-tables",
|
||||
"--query-serv-tables",
|
||||
"--static-instance-data",
|
||||
"--table-structure-only",
|
||||
"--table-lock",
|
||||
"--dump-path=",
|
||||
@@ -51,6 +52,7 @@ void WorldserverCLI::DatabaseDump(int argc, char **argv, argh::parser &cmd, std:
|
||||
s->SetDumpWithCompression(cmd[{"--compress"}]);
|
||||
s->SetDumpOutputToConsole(cmd[{"--dump-output-to-console"}]);
|
||||
s->SetDumpDropTableSyntaxOnly(cmd[{"--drop-table-syntax-only"}]);
|
||||
s->SetDumpStaticInstanceData(cmd[{"--static-instance-data"}]);
|
||||
|
||||
s->DatabaseDump();
|
||||
}
|
||||
|
||||
+5
-2
@@ -208,11 +208,14 @@ void Client::SendExpansionInfo() {
|
||||
auto outapp = new EQApplicationPacket(OP_ExpansionInfo, sizeof(ExpansionInfo_Struct));
|
||||
ExpansionInfo_Struct *eis = (ExpansionInfo_Struct*)outapp->pBuffer;
|
||||
|
||||
if (RuleB(World, UseClientBasedExpansionSettings)) {
|
||||
if (RuleI(World, CharacterSelectExpansionSettings) != -1) {
|
||||
eis->Expansions = RuleI(World, CharacterSelectExpansionSettings);
|
||||
}
|
||||
else if (RuleB(World, UseClientBasedExpansionSettings)) {
|
||||
eis->Expansions = EQ::expansions::ConvertClientVersionToExpansionsMask(eqs->ClientVersion());
|
||||
}
|
||||
else {
|
||||
eis->Expansions = (RuleI(World, ExpansionSettings) & EQ::expansions::ConvertClientVersionToExpansionsMask(eqs->ClientVersion()));
|
||||
eis->Expansions = RuleI(World, ExpansionSettings);
|
||||
}
|
||||
|
||||
QueuePacket(outapp);
|
||||
|
||||
+12
-7
@@ -1226,15 +1226,20 @@ void ConsoleCrossZoneMove(
|
||||
}
|
||||
|
||||
auto pack = new ServerPacket(ServerOP_CZMove, sizeof(CZMove_Struct));
|
||||
auto* CZM = (CZMove_Struct*) pack->pBuffer;
|
||||
auto m = (CZMove_Struct*) pack->pBuffer;
|
||||
|
||||
CZM->update_type = update_type;
|
||||
CZM->update_subtype = !instance_id ? CZMoveUpdateSubtype_MoveZone : CZMoveUpdateSubtype_MoveZoneInstance;
|
||||
CZM->update_identifier = update_identifier;
|
||||
CZM->instance_id = instance_id;
|
||||
if (!name.empty()) {
|
||||
m->client_name = name;
|
||||
}
|
||||
|
||||
strn0cpy(CZM->zone_short_name, zone_short_name.c_str(), sizeof(CZM->zone_short_name));
|
||||
strn0cpy(CZM->client_name, name.c_str(), sizeof(CZM->client_name));
|
||||
m->instance_id = instance_id;
|
||||
m->update_identifier = update_identifier;
|
||||
m->update_type = update_type;
|
||||
m->update_subtype = !instance_id ? CZMoveUpdateSubtype_MoveZone : CZMoveUpdateSubtype_MoveZoneInstance;
|
||||
|
||||
if (!zone_short_name.empty()) {
|
||||
m->zone_short_name = zone_short_name;
|
||||
}
|
||||
|
||||
zoneserver_list.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
|
||||
@@ -138,6 +138,7 @@ std::vector<Reload> reload_types = {
|
||||
Reload{.command = "alternate_currencies", .opcode = ServerOP_ReloadAlternateCurrencies, .desc = "Alternate Currencies"},
|
||||
Reload{.command = "blocked_spells", .opcode = ServerOP_ReloadBlockedSpells, .desc = "Blocked Spells"},
|
||||
Reload{.command = "commands", .opcode = ServerOP_ReloadCommands, .desc = "Commands"},
|
||||
Reload{.command = "data_buckets_cache", .opcode = ServerOP_ReloadDataBucketsCache, .desc = "Data Buckets Cache"},
|
||||
Reload{.command = "doors", .opcode = ServerOP_ReloadDoors, .desc = "Doors"},
|
||||
Reload{.command = "dztemplates", .opcode = ServerOP_ReloadDzTemplates, .desc = "Dynamic Zone Templates"},
|
||||
Reload{.command = "ground_spawns", .opcode = ServerOP_ReloadGroundSpawns, .desc = "Ground Spawns"},
|
||||
|
||||
+74
-9
@@ -46,6 +46,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../common/repositories/player_event_logs_repository.h"
|
||||
#include "../common/events/player_event_logs.h"
|
||||
#include "../common/patches/patches.h"
|
||||
#include "../zone/data_bucket.h"
|
||||
|
||||
extern ClientList client_list;
|
||||
extern GroupLFPList LFPGroupList;
|
||||
@@ -397,6 +398,14 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_RaidNote: {
|
||||
if (pack->size < sizeof(ServerRaidNote_Struct)) {
|
||||
break;
|
||||
}
|
||||
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_SpawnCondition: {
|
||||
if (pack->size != sizeof(ServerSpawnCondition_Struct)) {
|
||||
break;
|
||||
@@ -748,7 +757,8 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
}
|
||||
case ServerOP_ZoneStatus: {
|
||||
if (pack->size >= 1) {
|
||||
zoneserver_list.SendZoneStatus((char *)&pack->pBuffer[1], (uint8)pack->pBuffer[0], this);
|
||||
auto z = (ServerZoneStatus_Struct*) pack->pBuffer;
|
||||
zoneserver_list.SendZoneStatus(z->name, z->admin, this);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -785,11 +795,29 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
client = client_list.FindCharacter(ztz->name);
|
||||
}
|
||||
|
||||
LogInfo("ZoneToZone request for [{}] current zone [{}] req zone [{}]", ztz->name, ztz->current_zone_id, ztz->requested_zone_id);
|
||||
LogZoning(
|
||||
"ZoneToZone request for client [{}] guild_id [{}] requested_zone [{}] requested_zone_id [{}] requested_instance_id [{}] current_zone [{}] current_zone_id [{}] current_instance_id [{}] response [{}] admin [{}] ignorerestrictions [{}]",
|
||||
ztz->name,
|
||||
ztz->guild_id,
|
||||
ZoneName(ztz->requested_zone_id),
|
||||
ztz->requested_zone_id,
|
||||
ztz->requested_instance_id,
|
||||
ZoneName(ztz->current_zone_id),
|
||||
ztz->current_zone_id,
|
||||
ztz->current_instance_id,
|
||||
ztz->response,
|
||||
ztz->admin,
|
||||
ztz->ignorerestrictions
|
||||
);
|
||||
|
||||
/* This is a request from the egress zone */
|
||||
if (GetZoneID() == ztz->current_zone_id && GetInstanceID() == ztz->current_instance_id) {
|
||||
LogInfo("Processing ZTZ for egress from zone for client [{}]", ztz->name);
|
||||
LogZoning(
|
||||
"ZoneToZone request for client [{}] for egress from zone [{}]",
|
||||
ztz->name,
|
||||
ZoneName(ztz->current_zone_id),
|
||||
ztz->current_zone_id
|
||||
);
|
||||
|
||||
if (
|
||||
ztz->admin < AccountStatus::QuestTroupe &&
|
||||
@@ -797,6 +825,14 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
zoneserver_list.IsZoneLocked(ztz->requested_zone_id)
|
||||
) {
|
||||
ztz->response = 0;
|
||||
|
||||
LogZoning(
|
||||
"ZoneToZone request for client [{}] for egress from zone [{}] denied, zone is locked",
|
||||
ztz->name,
|
||||
ZoneName(ztz->current_zone_id),
|
||||
ztz->current_zone_id
|
||||
);
|
||||
|
||||
SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
@@ -808,12 +844,25 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
);
|
||||
|
||||
if (ingress_server) {
|
||||
LogInfo("Found a zone already booted for [{}]", ztz->name);
|
||||
LogZoning(
|
||||
"Found a zone already booted for ZoneToZone for client [{}] for ingress_server from zone [{}] found booted zone",
|
||||
ztz->name,
|
||||
ZoneName(ztz->current_zone_id),
|
||||
ztz->current_zone_id
|
||||
);
|
||||
|
||||
ztz->response = 1;
|
||||
} else {
|
||||
int server_id;
|
||||
if ((server_id = zoneserver_list.TriggerBootup(ztz->requested_zone_id, ztz->requested_instance_id))) {
|
||||
LogInfo("Successfully booted a zone for [{}]", ztz->name);
|
||||
LogZoning(
|
||||
"ZoneToZone successfully booted a zone for character [{}] zone [{}] ({}) instance [{}] ({})",
|
||||
ztz->name,
|
||||
ZoneName(ztz->requested_zone_id),
|
||||
ztz->requested_zone_id,
|
||||
ztz->requested_instance_id,
|
||||
server_id
|
||||
);
|
||||
ztz->response = 1;
|
||||
ingress_server = zoneserver_list.FindByID(server_id);
|
||||
} else {
|
||||
@@ -831,8 +880,8 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
ingress_server->SendPacket(pack); // inform target server
|
||||
}
|
||||
} else {
|
||||
LogInfo(
|
||||
"Processing ZTZ for ingress to zone for client [{}] instance_id [{}] zone_id [{}]",
|
||||
LogZoning(
|
||||
"Processing ZTZ for egress to zone for client [{}] instance_id [{}] zone_id [{}]",
|
||||
ztz->name,
|
||||
ztz->current_instance_id,
|
||||
ztz->current_zone_id
|
||||
@@ -844,7 +893,13 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
);
|
||||
|
||||
if (egress_server) {
|
||||
LogInfo("Found egress server, forwarding client");
|
||||
LogZoning(
|
||||
"Found egress server_id [{}] zone_id [{}] zone_name [{}] instance_id [{}], forwarding client",
|
||||
egress_server->GetID(),
|
||||
egress_server->GetZoneID(),
|
||||
egress_server->GetZoneName(),
|
||||
egress_server->GetInstanceID()
|
||||
);
|
||||
egress_server->SendPacket(pack);
|
||||
}
|
||||
}
|
||||
@@ -1333,13 +1388,13 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
case ServerOP_ReloadBlockedSpells:
|
||||
case ServerOP_ReloadCommands:
|
||||
case ServerOP_ReloadDoors:
|
||||
case ServerOP_ReloadDataBucketsCache:
|
||||
case ServerOP_ReloadGroundSpawns:
|
||||
case ServerOP_ReloadLevelEXPMods:
|
||||
case ServerOP_ReloadMerchants:
|
||||
case ServerOP_ReloadNPCEmotes:
|
||||
case ServerOP_ReloadObjects:
|
||||
case ServerOP_ReloadPerlExportSettings:
|
||||
case ServerOP_ReloadRules:
|
||||
case ServerOP_ReloadStaticZoneData:
|
||||
case ServerOP_ReloadTitles:
|
||||
case ServerOP_ReloadTraps:
|
||||
@@ -1364,6 +1419,11 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadRules: {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
RuleManager::Instance()->LoadRules(&database, "default", true);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadContentFlags: {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
content_service.SetExpansionContext()->ReloadContentFlags();
|
||||
@@ -1459,6 +1519,11 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
DynamicZone::HandleZoneMessage(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DataBucketCacheUpdate: {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogInfo("Unknown ServerOPcode from zone {:#04x}, size [{}]", pack->opcode, pack->size);
|
||||
DumpPacket(pack->pBuffer, pack->size);
|
||||
|
||||
@@ -118,8 +118,11 @@ SET(zone_sources
|
||||
perl_perlpacket.cpp
|
||||
perl_player_corpse.cpp
|
||||
perl_questitem.cpp
|
||||
perl_questitem_data.cpp
|
||||
perl_raids.cpp
|
||||
perl_spawn.cpp
|
||||
perl_spell.cpp
|
||||
perl_stat_bonuses.cpp
|
||||
perlpacket.cpp
|
||||
petitions.cpp
|
||||
pets.cpp
|
||||
|
||||
+171
-36
@@ -1111,7 +1111,7 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
FinishAlternateAdvancementPurchase(rank, false);
|
||||
FinishAlternateAdvancementPurchase(rank, false, true);
|
||||
}
|
||||
|
||||
bool Client::GrantAlternateAdvancementAbility(int aa_id, int points, bool ignore_cost) {
|
||||
@@ -1134,13 +1134,13 @@ bool Client::GrantAlternateAdvancementAbility(int aa_id, int points, bool ignore
|
||||
}
|
||||
|
||||
ret = true;
|
||||
FinishAlternateAdvancementPurchase(rank, ignore_cost);
|
||||
FinishAlternateAdvancementPurchase(rank, ignore_cost, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost) {
|
||||
void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost, bool send_message_and_save) {
|
||||
auto rank_id = rank->base_ability->first_rank_id;
|
||||
|
||||
if (rank->base_ability->charges) {
|
||||
@@ -1156,7 +1156,7 @@ void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost
|
||||
SetAA(rank_id, rank->current_value, 0);
|
||||
|
||||
//if not max then send next aa
|
||||
if (rank->next) {
|
||||
if (rank->next && send_message_and_save) {
|
||||
SendAlternateAdvancementRank(rank->base_ability->id, rank->next->current_value);
|
||||
}
|
||||
}
|
||||
@@ -1164,10 +1164,12 @@ void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost
|
||||
auto cost = !ignore_cost ? rank->cost : 0;
|
||||
|
||||
m_pp.aapoints -= static_cast<uint32>(cost);
|
||||
SaveAA();
|
||||
|
||||
SendAlternateAdvancementPoints();
|
||||
SendAlternateAdvancementStats();
|
||||
if (send_message_and_save) {
|
||||
SaveAA();
|
||||
SendAlternateAdvancementPoints();
|
||||
SendAlternateAdvancementStats();
|
||||
}
|
||||
|
||||
if (player_event_logs.IsEventEnabled(PlayerEvent::AA_PURCHASE)) {
|
||||
auto e = PlayerEvent::AAPurchasedEvent{
|
||||
@@ -1181,14 +1183,16 @@ void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost
|
||||
}
|
||||
|
||||
if (rank->prev) {
|
||||
MessageString(
|
||||
Chat::Yellow,
|
||||
AA_IMPROVE,
|
||||
std::to_string(rank->title_sid).c_str(),
|
||||
std::to_string(rank->prev->current_value).c_str(),
|
||||
std::to_string(cost).c_str(),
|
||||
cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str()
|
||||
);
|
||||
if (send_message_and_save) {
|
||||
MessageString(
|
||||
Chat::Yellow,
|
||||
AA_IMPROVE,
|
||||
std::to_string(rank->title_sid).c_str(),
|
||||
std::to_string(rank->prev->current_value).c_str(),
|
||||
std::to_string(cost).c_str(),
|
||||
cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
/* QS: Player_Log_AA_Purchases */
|
||||
if (RuleB(QueryServ, PlayerLogAAPurchases)) {
|
||||
@@ -1203,13 +1207,15 @@ void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost
|
||||
QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc);
|
||||
}
|
||||
} else {
|
||||
MessageString(
|
||||
Chat::Yellow,
|
||||
AA_GAIN_ABILITY,
|
||||
std::to_string(rank->title_sid).c_str(),
|
||||
std::to_string(cost).c_str(),
|
||||
cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str()
|
||||
);
|
||||
if (send_message_and_save) {
|
||||
MessageString(
|
||||
Chat::Yellow,
|
||||
AA_GAIN_ABILITY,
|
||||
std::to_string(rank->title_sid).c_str(),
|
||||
std::to_string(cost).c_str(),
|
||||
cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
/* QS: Player_Log_AA_Purchases */
|
||||
if (RuleB(QueryServ, PlayerLogAAPurchases)) {
|
||||
@@ -1594,6 +1600,15 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) {
|
||||
}
|
||||
}
|
||||
|
||||
int expansion = RuleI(Expansion, CurrentExpansion);
|
||||
bool use_expansion_aa = RuleB(Expansion, UseCurrentExpansionAAOnly);
|
||||
if (use_expansion_aa && expansion >= 0) {
|
||||
if (rank->expansion > expansion) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (IsClient()) {
|
||||
if (rank->expansion && !(CastToClient()->GetPP().expansions & (1 << (rank->expansion - 1)))) {
|
||||
return false;
|
||||
@@ -1645,6 +1660,10 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsClient() && CastToClient()->HasAlreadyPurchasedRank(rank)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//You can't purchase grant only AAs they can only be assigned
|
||||
if(check_grant && ability->grant_only) {
|
||||
return false;
|
||||
@@ -1701,9 +1720,7 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price,
|
||||
}
|
||||
|
||||
void Zone::LoadAlternateAdvancement() {
|
||||
if(!content_db.LoadAlternateAdvancementAbilities(aa_abilities,
|
||||
aa_ranks))
|
||||
{
|
||||
if (!content_db.LoadAlternateAdvancementAbilities(aa_abilities, aa_ranks)) {
|
||||
aa_abilities.clear();
|
||||
aa_ranks.clear();
|
||||
LogInfo("Failed to load Alternate Advancement Data");
|
||||
@@ -1766,7 +1783,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map<int, std
|
||||
{
|
||||
abilities.clear();
|
||||
std::string query = "SELECT id, name, category, classes, races, deities, drakkin_heritage, status, type, charges, "
|
||||
"grant_only, reset_on_death, first_rank_id FROM aa_ability WHERE enabled = 1";
|
||||
"grant_only, reset_on_death, auto_grant_enabled, first_rank_id FROM aa_ability WHERE enabled = 1";
|
||||
auto results = QueryDatabase(query);
|
||||
if(results.Success()) {
|
||||
for(auto row = results.begin(); row != results.end(); ++row) {
|
||||
@@ -1784,7 +1801,8 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map<int, std
|
||||
ability->charges = Strings::ToInt(row[9]);
|
||||
ability->grant_only = Strings::ToBool(row[10]);
|
||||
ability->reset_on_death = Strings::ToBool(row[11]);
|
||||
ability->first_rank_id = Strings::ToInt(row[12]);
|
||||
ability->auto_grant_enabled = Strings::ToBool(row[12]);
|
||||
ability->first_rank_id = Strings::ToInt(row[13]);
|
||||
ability->first = nullptr;
|
||||
|
||||
abilities[ability->id] = std::unique_ptr<AA::Ability>(ability);
|
||||
@@ -1795,17 +1813,11 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map<int, std
|
||||
}
|
||||
|
||||
LogInfo("Loaded [{}] Alternate Advancement Abilities", Strings::Commify((int)abilities.size()));
|
||||
int expansion = RuleI(Expansion, CurrentExpansion);
|
||||
bool use_expansion_aa = RuleB(Expansion, UseCurrentExpansionAAOnly);
|
||||
|
||||
ranks.clear();
|
||||
if (use_expansion_aa && expansion >= 0) {
|
||||
query = fmt::format("SELECT id, upper_hotkey_sid, lower_hotkey_sid, title_sid, desc_sid, cost, level_req, spell, spell_type, recast_time, "
|
||||
"next_id, expansion FROM aa_ranks WHERE expansion <= {}", expansion);
|
||||
} else {
|
||||
query = "SELECT id, upper_hotkey_sid, lower_hotkey_sid, title_sid, desc_sid, cost, level_req, spell, spell_type, recast_time, "
|
||||
|
||||
query = "SELECT id, upper_hotkey_sid, lower_hotkey_sid, title_sid, desc_sid, cost, level_req, spell, spell_type, recast_time, "
|
||||
"next_id, expansion FROM aa_ranks";
|
||||
}
|
||||
|
||||
results = QueryDatabase(query);
|
||||
if(results.Success()) {
|
||||
for(auto row = results.begin(); row != results.end(); ++row) {
|
||||
@@ -2070,3 +2082,126 @@ void Client::TogglePurchaseAlternativeAdvancementRank(int rank_id){
|
||||
CalcBonuses();
|
||||
}
|
||||
|
||||
void Client::AutoGrantAAPoints() {
|
||||
int auto_grant_expansion = RuleI(Expansion, AutoGrantAAExpansion);
|
||||
|
||||
if (auto_grant_expansion == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
//iterate through every AA
|
||||
for (auto& iter : zone->aa_abilities) {
|
||||
auto ability = iter.second.get();
|
||||
|
||||
if (ability->grant_only) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ability->charges > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ability->auto_grant_enabled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto level = GetLevel();
|
||||
auto p = 1;
|
||||
auto rank = ability->first;
|
||||
while (rank != nullptr) {
|
||||
if (CanUseAlternateAdvancementRank(rank)) {
|
||||
if (rank->expansion <= auto_grant_expansion && rank->level_req <= level && !HasAlreadyPurchasedRank(rank)) {
|
||||
FinishAlternateAdvancementPurchase(rank, true, false);
|
||||
|
||||
if (rank->prev) {
|
||||
MessageString(
|
||||
Chat::Yellow,
|
||||
AA_IMPROVE,
|
||||
std::to_string(rank->title_sid).c_str(),
|
||||
std::to_string(rank->prev->current_value).c_str(),
|
||||
"0",
|
||||
std::to_string(AA_POINTS).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
MessageString(
|
||||
Chat::Yellow,
|
||||
AA_GAIN_ABILITY,
|
||||
std::to_string(rank->title_sid).c_str(),
|
||||
"0",
|
||||
std::to_string(AA_POINTS).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
p++;
|
||||
rank = rank->next;
|
||||
}
|
||||
}
|
||||
|
||||
SendClearAA();
|
||||
SendAlternateAdvancementTable();
|
||||
SendAlternateAdvancementPoints();
|
||||
SendAlternateAdvancementStats();
|
||||
}
|
||||
|
||||
void Client::GrantAllAAPoints()
|
||||
{
|
||||
//iterate through every AA
|
||||
for (auto& iter : zone->aa_abilities) {
|
||||
auto ability = iter.second.get();
|
||||
|
||||
if (ability->charges > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto level = GetLevel();
|
||||
auto p = 1;
|
||||
auto rank = ability->first;
|
||||
while (rank != nullptr) {
|
||||
if (CanUseAlternateAdvancementRank(rank)) {
|
||||
if (rank->level_req <= level && !HasAlreadyPurchasedRank(rank)) {
|
||||
FinishAlternateAdvancementPurchase(rank, true, false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
p++;
|
||||
rank = rank->next;
|
||||
}
|
||||
}
|
||||
|
||||
SaveAA();
|
||||
SendClearAA();
|
||||
SendAlternateAdvancementTable();
|
||||
SendAlternateAdvancementPoints();
|
||||
SendAlternateAdvancementStats();
|
||||
}
|
||||
|
||||
bool Client::HasAlreadyPurchasedRank(AA::Rank *rank) {
|
||||
auto iter = aa_ranks.find(rank->base_ability->id);
|
||||
|
||||
if (iter == aa_ranks.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(iter->first, iter->second.first);
|
||||
auto ability = ability_rank.first;
|
||||
auto current = ability_rank.second;
|
||||
|
||||
while (current != nullptr) {
|
||||
if (current == rank) {
|
||||
return true;
|
||||
}
|
||||
|
||||
current = current->prev;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
int status;
|
||||
bool grant_only;
|
||||
bool reset_on_death;
|
||||
bool auto_grant_enabled;
|
||||
int type;
|
||||
int charges;
|
||||
int first_rank_id;
|
||||
|
||||
+27
-6
@@ -975,8 +975,7 @@ bool Mob::IsBeneficialAllowed(Mob *target)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Mob::CombatRange(Mob* other, float fixed_size_mod, bool aeRampage)
|
||||
{
|
||||
bool Mob::CombatRange(Mob* other, float fixed_size_mod, bool aeRampage, ExtraAttackOptions *opts) {
|
||||
if (!other) {
|
||||
return(false);
|
||||
}
|
||||
@@ -1071,18 +1070,40 @@ bool Mob::CombatRange(Mob* other, float fixed_size_mod, bool aeRampage)
|
||||
SetPseudoRoot(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (aeRampage) {
|
||||
float multiplyer = GetSize() * RuleR(Combat, AERampageSafeZone);
|
||||
float ramp_range = (size_mod * multiplyer);
|
||||
float aeramp_size = RuleR(Combat, AERampageMaxDistance);
|
||||
|
||||
LogCombatDetail("AERampage: Default - aeramp_size = [{}] ", aeramp_size);
|
||||
|
||||
if (opts) {
|
||||
if (opts->range_percent > 0) {
|
||||
aeramp_size = opts->range_percent;
|
||||
LogCombatDetail("AE Rampage: range_percent = [{}] -- aeramp_size [{}]", opts->range_percent, aeramp_size);
|
||||
}
|
||||
}
|
||||
|
||||
if (aeramp_size <= 0) {
|
||||
aeramp_size = 0.90;
|
||||
} else {
|
||||
aeramp_size /= 100;
|
||||
}
|
||||
|
||||
float ramp_range = size_mod * aeramp_size;
|
||||
|
||||
LogCombatDetail("AE Rampage: ramp_range = [{}] -- (size_mod [{}] * aeramp_size [{}])", ramp_range, size_mod, aeramp_size);
|
||||
LogCombatDetail("AE Rampage: _DistNoRoot [{}] <= ramp_range [{}]", _DistNoRoot, ramp_range);
|
||||
|
||||
if (_DistNoRoot <= ramp_range) {
|
||||
LogCombatDetail("AE Rampage: Combat Distance returned [true]");
|
||||
return true;
|
||||
} else {
|
||||
LogCombatDetail("AE Rampage: Combat Distance returned [false]");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_DistNoRoot <= size_mod)
|
||||
{
|
||||
if (_DistNoRoot <= size_mod) {
|
||||
//A hack to kill an exploit till we get something better.
|
||||
if (flymode != GravityBehavior::Flying && _zDist > 500 && !CheckLastLosState()) {
|
||||
return false;
|
||||
|
||||
+58
-33
@@ -1741,7 +1741,8 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill
|
||||
static_cast<int>(attack_skill)
|
||||
);
|
||||
|
||||
if (parse->EventPlayer(EVENT_DEATH, this, export_string, 0) != 0) {
|
||||
std::vector<std::any> args = { CastToMob() };
|
||||
if (parse->EventPlayer(EVENT_DEATH, this, export_string, 0, &args) != 0) {
|
||||
if (GetHP() < 0) {
|
||||
SetHP(0);
|
||||
}
|
||||
@@ -2388,7 +2389,8 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
||||
static_cast<int>(attack_skill)
|
||||
);
|
||||
|
||||
if (parse->EventNPC(EVENT_DEATH, this, oos, export_string, 0) != 0) {
|
||||
std::vector<std::any> args = { CastToMob() };
|
||||
if (parse->EventNPC(EVENT_DEATH, this, oos, export_string, 0, &args) != 0) {
|
||||
if (GetHP() < 0) {
|
||||
SetHP(0);
|
||||
}
|
||||
@@ -2405,7 +2407,9 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
||||
spell,
|
||||
static_cast<int>(attack_skill)
|
||||
);
|
||||
if (parse->EventBot(EVENT_DEATH, CastToBot(), oos, export_string, 0) != 0) {
|
||||
|
||||
std::vector<std::any> args = { CastToMob() };
|
||||
if (parse->EventBot(EVENT_DEATH, CastToBot(), oos, export_string, 0, &args) != 0) {
|
||||
if (GetHP() < 0) {
|
||||
SetHP(0);
|
||||
}
|
||||
@@ -4226,11 +4230,11 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
||||
//this was done to simplify the code here (since we can only effectively skip one mob on queue)
|
||||
eqFilterType filter;
|
||||
Mob* skip = attacker;
|
||||
if (attacker && attacker->GetOwnerID()) {
|
||||
if (attacker && attacker->GetOwner()) {
|
||||
//attacker is a pet, let pet owners see their pet's damage
|
||||
Mob* owner = attacker->GetOwner();
|
||||
if (owner && owner->IsClient()) {
|
||||
if ((IsValidSpell(spell_id) || (FromDamageShield)) && damage > 0) {
|
||||
if (FromDamageShield && damage > 0) {
|
||||
//special crap for spell damage, looks hackish to me
|
||||
char val1[20] = { 0 };
|
||||
owner->MessageString(Chat::NonMelee, OTHER_HIT_NONMELEE, GetCleanName(), ConvertArray(damage, val1));
|
||||
@@ -4249,7 +4253,15 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
||||
filter = FilterPetMisses;
|
||||
|
||||
if (!FromDamageShield)
|
||||
owner->CastToClient()->QueuePacket(outapp, true, CLIENT_CONNECTED, filter);
|
||||
entity_list.QueueCloseClients(
|
||||
this, /* Sender */
|
||||
outapp, /* packet */
|
||||
false, /* Skip Sender */
|
||||
((IsValidSpell(spell_id)) ? RuleI(Range, SpellMessages) : RuleI(Range, DamageMessages)),
|
||||
0, /* don't skip anyone on spell */
|
||||
true, /* Packet ACK */
|
||||
filter /* eqFilterType filter */
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4351,16 +4363,21 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
||||
CastToClient()->QueuePacket(outapp);
|
||||
}
|
||||
|
||||
// Otherwise, send normal spell or melee message to observers.
|
||||
entity_list.QueueCloseClients(
|
||||
this, /* Sender */
|
||||
outapp, /* packet */
|
||||
true, /* Skip Sender */
|
||||
range, /* distance packet travels at the speed of sound */
|
||||
(IsValidSpell(spell_id) && skill_used != EQ::skills::SkillTigerClaw) ? 0 : skip,
|
||||
true, /* Packet ACK */
|
||||
filter /* eqFilterType filter */
|
||||
);
|
||||
// Send normal message to observers
|
||||
// Exclude damage done by client pets as that's handled
|
||||
// elsewhere using proper "my pet damage filter"
|
||||
Mob *owner = attacker->GetOwner();
|
||||
if (!owner || (owner && !owner->IsClient())) {
|
||||
entity_list.QueueCloseClients(
|
||||
this, /* Sender */
|
||||
outapp, /* packet */
|
||||
true, /* Skip Sender */
|
||||
range, /* distance packet travels at the speed of sound */
|
||||
(IsValidSpell(spell_id) && skill_used != EQ::skills::SkillTigerClaw) ? 0 : skip,
|
||||
true, /* Packet ACK */
|
||||
filter /* eqFilterType filter */
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4526,8 +4543,8 @@ float Mob::GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 h
|
||||
}
|
||||
|
||||
// argument 'weapon' not used
|
||||
void Mob::TryDefensiveProc(Mob *on, uint16 hand) {
|
||||
|
||||
void Mob::TryDefensiveProc(Mob *on, uint16 hand)
|
||||
{
|
||||
if (!on) {
|
||||
SetTarget(nullptr);
|
||||
LogError("A null Mob object was passed to Mob::TryDefensiveProc for evaluation!");
|
||||
@@ -4539,23 +4556,26 @@ void Mob::TryDefensiveProc(Mob *on, uint16 hand) {
|
||||
}
|
||||
|
||||
if (!on->HasDied() && on->GetHP() > 0) {
|
||||
|
||||
float ProcChance, ProcBonus;
|
||||
on->GetDefensiveProcChances(ProcBonus, ProcChance, hand, this);
|
||||
float proc_chance, proc_bonus;
|
||||
on->GetDefensiveProcChances(proc_bonus, proc_chance, hand, this);
|
||||
|
||||
if (hand == EQ::invslot::slotSecondary) {
|
||||
ProcChance /= 2;
|
||||
proc_chance /= 2;
|
||||
}
|
||||
|
||||
int level_penalty = 0;
|
||||
int level_diff = GetLevel() - on->GetLevel();
|
||||
if (level_diff > 6) {//10% penalty per level if > 6 levels over target.
|
||||
level_penalty = (level_diff - 6) * 10;
|
||||
int level_penalty = 0;
|
||||
int level_diff = GetLevel() - on->GetLevel();
|
||||
int penalty_level_gap = RuleI(Spells, DefensiveProcPenaltyLevelGap);
|
||||
if (
|
||||
penalty_level_gap >= 0 &&
|
||||
level_diff > penalty_level_gap
|
||||
) {//10% penalty per level if > penalty_level_gap levels over target.
|
||||
level_penalty = (level_diff - penalty_level_gap) * RuleR(Spells, DefensiveProcPenaltyLevelGapModifier);
|
||||
}
|
||||
|
||||
ProcChance -= ProcChance*level_penalty / 100;
|
||||
proc_chance -= proc_chance * level_penalty / 100;
|
||||
|
||||
if (ProcChance < 0) {
|
||||
if (proc_chance < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4563,7 +4583,7 @@ void Mob::TryDefensiveProc(Mob *on, uint16 hand) {
|
||||
for (int i = 0; i < MAX_PROCS; i++) {
|
||||
if (IsValidSpell(DefensiveProcs[i].spellID)) {
|
||||
if (!IsProcLimitTimerActive(DefensiveProcs[i].base_spellID, DefensiveProcs[i].proc_reuse_time, ProcType::DEFENSIVE_PROC)) {
|
||||
float chance = ProcChance * (static_cast<float>(DefensiveProcs[i].chance) / 100.0f);
|
||||
float chance = proc_chance * (static_cast<float>(DefensiveProcs[i].chance) / 100.0f);
|
||||
if (zone->random.Roll(chance)) {
|
||||
ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on);
|
||||
CheckNumHitsRemaining(NumHit::DefensiveSpellProcs, 0, DefensiveProcs[i].base_spellID);
|
||||
@@ -4576,14 +4596,14 @@ void Mob::TryDefensiveProc(Mob *on, uint16 hand) {
|
||||
//AA Procs
|
||||
if (IsOfClientBot()) {
|
||||
for (int i = 0; i < MAX_AA_PROCS; i += 4) {
|
||||
int32 aa_rank_id = aabonuses.DefensiveProc[i + +SBIndex::COMBAT_PROC_ORIGIN_ID];
|
||||
int32 aa_spell_id = aabonuses.DefensiveProc[i + SBIndex::COMBAT_PROC_SPELL_ID];
|
||||
int32 aa_proc_chance = 100 + aabonuses.DefensiveProc[i + SBIndex::COMBAT_PROC_RATE_MOD];
|
||||
int32 aa_rank_id = aabonuses.DefensiveProc[i + +SBIndex::COMBAT_PROC_ORIGIN_ID];
|
||||
int32 aa_spell_id = aabonuses.DefensiveProc[i + SBIndex::COMBAT_PROC_SPELL_ID];
|
||||
int32 aa_proc_chance = 100 + aabonuses.DefensiveProc[i + SBIndex::COMBAT_PROC_RATE_MOD];
|
||||
uint32 aa_proc_reuse_timer = aabonuses.DefensiveProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER];
|
||||
|
||||
if (aa_rank_id) {
|
||||
if (!IsProcLimitTimerActive(-aa_rank_id, aa_proc_reuse_timer, ProcType::DEFENSIVE_PROC)) {
|
||||
float chance = ProcChance * (static_cast<float>(aa_proc_chance) / 100.0f);
|
||||
float chance = proc_chance * (static_cast<float>(aa_proc_chance) / 100.0f);
|
||||
if (zone->random.Roll(chance) && IsValidSpell(aa_spell_id)) {
|
||||
ExecWeaponProc(nullptr, aa_spell_id, on);
|
||||
SetProcLimitTimer(-aa_rank_id, aa_proc_reuse_timer, ProcType::DEFENSIVE_PROC);
|
||||
@@ -6458,3 +6478,8 @@ int64 Mob::GetManaRegen() const
|
||||
{
|
||||
return mana_regen;
|
||||
}
|
||||
|
||||
int64 Mob::GetEnduranceRegen() const
|
||||
{
|
||||
return 0; // not implemented
|
||||
}
|
||||
|
||||
+5
-8
@@ -146,7 +146,8 @@ void Mob::CalcItemBonuses(StatBonuses* b) {
|
||||
int16 i;
|
||||
|
||||
for (i = EQ::invslot::BONUS_BEGIN; i <= EQ::invslot::BONUS_SKILL_END; i++) {
|
||||
const EQ::ItemInstance* inst = GetInv().GetItem(i);
|
||||
const auto* inst = GetInv().GetItem(i);
|
||||
|
||||
if (!inst) {
|
||||
continue;
|
||||
}
|
||||
@@ -6032,14 +6033,10 @@ float Mob::CheckHeroicBonusesDataBuckets(std::string bucket_name)
|
||||
{
|
||||
std::string bucket_value;
|
||||
if (!bucket_name.empty()) {
|
||||
const auto full_name = fmt::format(
|
||||
"{}-{}",
|
||||
GetBucketKey(),
|
||||
bucket_name
|
||||
);
|
||||
|
||||
DataBucketKey k = GetScopedBucketKeys();
|
||||
k.key = bucket_name;
|
||||
if (IsOfClientBot()) {
|
||||
bucket_value = DataBucket::CheckBucketKey(this, full_name);
|
||||
bucket_value = DataBucket::GetData(k).value;
|
||||
}
|
||||
|
||||
if (bucket_value.empty() || !Strings::IsNumber(bucket_value)) {
|
||||
|
||||
+85
-115
@@ -119,7 +119,15 @@ Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm
|
||||
}
|
||||
|
||||
// This constructor is used when the bot is loaded out of the database
|
||||
Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType *npcTypeData)
|
||||
Bot::Bot(
|
||||
uint32 botID,
|
||||
uint32 botOwnerCharacterID,
|
||||
uint32 botSpellsID,
|
||||
double totalPlayTime,
|
||||
uint32 lastZoneId,
|
||||
NPCType *npcTypeData,
|
||||
int32 expansion_bitmask
|
||||
)
|
||||
: NPC(npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1), ping_timer(1)
|
||||
{
|
||||
GiveNPCTypeData(npcTypeData);
|
||||
@@ -161,6 +169,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
|
||||
RestRegenHP = 0;
|
||||
RestRegenMana = 0;
|
||||
RestRegenEndurance = 0;
|
||||
m_expansion_bitmask = expansion_bitmask;
|
||||
SetBotID(botID);
|
||||
SetBotSpellID(botSpellsID);
|
||||
SetSpawnStatus(false);
|
||||
@@ -268,26 +277,48 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
|
||||
case SE_IllusionCopy:
|
||||
case SE_Illusion: {
|
||||
if (spell.base_value[x1] == -1) {
|
||||
if (gender == 1)
|
||||
gender = 0;
|
||||
else if (gender == 0)
|
||||
gender = 1;
|
||||
SendIllusionPacket(GetRace(), gender, 0xFF, 0xFF);
|
||||
}
|
||||
else if (spell.base_value[x1] == -2) // WTF IS THIS
|
||||
if (gender == FEMALE) {
|
||||
gender = MALE;
|
||||
} else if (gender == MALE) {
|
||||
gender = FEMALE;
|
||||
}
|
||||
|
||||
SendIllusionPacket(
|
||||
AppearanceStruct{
|
||||
.gender_id = gender,
|
||||
.race_id = GetRace(),
|
||||
}
|
||||
);
|
||||
} else if (spell.base_value[x1] == -2) // WTF IS THIS
|
||||
{
|
||||
if (GetRace() == IKSAR || GetRace() == VAHSHIR || GetRace() <= GNOME) {
|
||||
SendIllusionPacket(GetRace(), GetGender(), spell.limit_value[x1], spell.max_value[x1]);
|
||||
SendIllusionPacket(
|
||||
AppearanceStruct{
|
||||
.gender_id = GetGender(),
|
||||
.helmet_texture = static_cast<uint8>(spell.max_value[x1]),
|
||||
.race_id = GetRace(),
|
||||
.texture = static_cast<uint8>(spell.limit_value[x1]),
|
||||
}
|
||||
);
|
||||
}
|
||||
} else if (spell.max_value[x1] > 0) {
|
||||
SendIllusionPacket(
|
||||
AppearanceStruct{
|
||||
.helmet_texture = static_cast<uint8>(spell.max_value[x1]),
|
||||
.race_id = static_cast<uint16>(spell.base_value[x1]),
|
||||
.texture = static_cast<uint8>(spell.limit_value[x1]),
|
||||
}
|
||||
);
|
||||
} else {
|
||||
SendIllusionPacket(
|
||||
AppearanceStruct{
|
||||
.helmet_texture = static_cast<uint8>(spell.max_value[x1]),
|
||||
.race_id = static_cast<uint16>(spell.base_value[x1]),
|
||||
.texture = static_cast<uint8>(spell.limit_value[x1]),
|
||||
}
|
||||
);
|
||||
}
|
||||
else if (spell.max_value[x1] > 0)
|
||||
{
|
||||
SendIllusionPacket(spell.base_value[x1], 0xFF, spell.limit_value[x1], spell.max_value[x1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendIllusionPacket(spell.base_value[x1], 0xFF, 0xFF, 0xFF);
|
||||
}
|
||||
|
||||
switch (spell.base_value[x1]) {
|
||||
case OGRE:
|
||||
SendAppearancePacket(AT_Size, 9);
|
||||
@@ -427,6 +458,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
|
||||
Bot::~Bot() {
|
||||
AI_Stop();
|
||||
LeaveHealRotationMemberPool();
|
||||
DataBucket::DeleteCachedBuckets(DataBucketLoadType::Bot, GetBotID());
|
||||
|
||||
if (HasPet()) {
|
||||
GetPet()->Depop();
|
||||
@@ -1273,8 +1305,11 @@ bool Bot::IsValidName(std::string& name)
|
||||
if (!isupper(name[0]))
|
||||
return false;
|
||||
|
||||
for (int i = 1; i < name.length(); ++i) {
|
||||
if ((!RuleB(Bots, AllowCamelCaseNames) && !islower(name[i])) && name[i] != '_') {
|
||||
for (char c : name.substr(1)) {
|
||||
if (!RuleB(Bots, AllowCamelCaseNames) && !islower(c)) {
|
||||
return false;
|
||||
}
|
||||
if (isdigit(c) || ispunct(c)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3302,16 +3337,23 @@ bool Bot::Spawn(Client* botCharacterOwner) {
|
||||
|
||||
if (auto raid = entity_list.GetRaidByBotName(GetName())) {
|
||||
// Safety Check to confirm we have a valid raid
|
||||
if (raid->IsRaidMember(GetBotOwner()->CastToClient())) {
|
||||
if (!raid->IsRaidMember(GetBotOwner()->GetName())) {
|
||||
Bot::RemoveBotFromRaid(this);
|
||||
} else {
|
||||
raid->LearnMembers();
|
||||
SetRaidGrouped(true);
|
||||
raid->LearnMembers();
|
||||
raid->VerifyRaid();
|
||||
}
|
||||
}
|
||||
else if (auto group = entity_list.GetGroupByMobName(GetName())) {
|
||||
group->LearnMembers();
|
||||
SetGrouped(true);
|
||||
// Safety Check to confirm we have a valid group
|
||||
if (!group->IsGroupMember(GetBotOwner()->GetName())) {
|
||||
Bot::RemoveBotFromGroup(this, group);
|
||||
} else {
|
||||
SetGrouped(true);
|
||||
group->LearnMembers();
|
||||
group->VerifyGroup();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -4508,10 +4550,9 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client*
|
||||
}
|
||||
|
||||
bool Bot::Death(Mob *killerMob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill) {
|
||||
if (!NPC::Death(killerMob, damage, spell_id, attack_skill))
|
||||
if (!NPC::Death(killerMob, damage, spell_id, attack_skill)) {
|
||||
return false;
|
||||
|
||||
Save();
|
||||
}
|
||||
|
||||
Mob *my_owner = GetBotOwner();
|
||||
if (my_owner && my_owner->IsClient() && my_owner->CastToClient()->GetBotOption(Client::booDeathMarquee)) {
|
||||
@@ -4521,81 +4562,11 @@ bool Bot::Death(Mob *killerMob, int64 damage, uint16 spell_id, EQ::skills::Skill
|
||||
my_owner->CastToClient()->SendMarqueeMessage(Chat::White, 510, 0, 1000, 3000, StringFormat("%s has been slain", GetCleanName()));
|
||||
}
|
||||
|
||||
Mob *give_exp = hate_list.GetDamageTopOnHateList(this);
|
||||
Client *give_exp_client = nullptr;
|
||||
if (give_exp && give_exp->IsClient())
|
||||
give_exp_client = give_exp->CastToClient();
|
||||
|
||||
bool IsLdonTreasure = (GetClass() == LDON_TREASURE);
|
||||
const auto c = entity_list.GetCorpseByID(GetID());
|
||||
if (c) {
|
||||
c->Depop();
|
||||
}
|
||||
|
||||
if (HasRaid()) {
|
||||
if (auto raid = entity_list.GetRaidByBotName(GetName()); raid) {
|
||||
for (auto& m: raid->members) {
|
||||
if (strcmp(m.member_name, GetName()) == 0) {
|
||||
m.member = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (HasGroup()) {
|
||||
if (auto g = GetGroup()) {
|
||||
for (int i = 0; i < MAX_GROUP_MEMBERS; i++) {
|
||||
if (g->members[i]) {
|
||||
if (g->members[i] == this) {
|
||||
// If the leader dies, make the next bot the leader
|
||||
// and reset all bots followid
|
||||
if (g->IsLeader(g->members[i])) {
|
||||
if (g->members[i + 1]) {
|
||||
g->SetLeader(g->members[i + 1]);
|
||||
g->members[i + 1]->SetFollowID(g->members[i]->GetFollowID());
|
||||
for (int j = 0; j < MAX_GROUP_MEMBERS; j++) {
|
||||
if (g->members[j] && (g->members[j] != g->members[i + 1]))
|
||||
g->members[j]->SetFollowID(g->members[i + 1]->GetID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// delete from group data
|
||||
RemoveBotFromGroup(this, g);
|
||||
//Make sure group still exists if it doesnt they were already updated in RemoveBotFromGroup
|
||||
g = GetGroup();
|
||||
if (!g)
|
||||
break;
|
||||
|
||||
// if group members exist below this one, move
|
||||
// them all up one slot in the group list
|
||||
int j = (i + 1);
|
||||
for (; j < MAX_GROUP_MEMBERS; j++) {
|
||||
if (g->members[j]) {
|
||||
g->members[j - 1] = g->members[j];
|
||||
strcpy(g->membername[j - 1], g->members[j]->GetCleanName());
|
||||
g->membername[j][0] = '\0';
|
||||
memset(g->membername[j], 0, 64);
|
||||
g->members[j] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// update the client group
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct));
|
||||
GroupJoin_Struct* gu = (GroupJoin_Struct*) outapp->pBuffer;
|
||||
gu->action = groupActLeave;
|
||||
strcpy(gu->membername, GetCleanName());
|
||||
for (int k = 0; k < MAX_GROUP_MEMBERS; k++) {
|
||||
if (g->members[k] && g->members[k]->IsClient()) {
|
||||
g->members[k]->CastToClient()->QueuePacket(outapp);
|
||||
}
|
||||
}
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LeaveHealRotationMemberPool();
|
||||
|
||||
if ((GetPullingFlag() || GetReturningFlag()) && my_owner && my_owner->IsClient()) {
|
||||
@@ -4614,6 +4585,7 @@ bool Bot::Death(Mob *killerMob, int64 damage, uint16 spell_id, EQ::skills::Skill
|
||||
parse->EventBot(EVENT_DEATH_COMPLETE, this, killerMob, export_string, 0);
|
||||
}
|
||||
|
||||
Zone();
|
||||
entity_list.RemoveBot(GetID());
|
||||
|
||||
return true;
|
||||
@@ -5428,10 +5400,10 @@ void Bot::ProcessBotOwnerRefDelete(Mob* botOwner) {
|
||||
int64 Bot::CalcMaxMana() {
|
||||
switch(GetCasterClass()) {
|
||||
case 'I':
|
||||
max_mana = (GenerateBaseManaPoints() + itembonuses.Mana + spellbonuses.Mana + GroupLeadershipAAManaEnhancement());
|
||||
max_mana = (GenerateBaseManaPoints() + itembonuses.Mana + spellbonuses.Mana + aabonuses.Mana + GroupLeadershipAAManaEnhancement());
|
||||
max_mana += itembonuses.heroic_max_mana;
|
||||
case 'W': {
|
||||
max_mana = (GenerateBaseManaPoints() + itembonuses.Mana + spellbonuses.Mana + GroupLeadershipAAManaEnhancement());
|
||||
max_mana = (GenerateBaseManaPoints() + itembonuses.Mana + spellbonuses.Mana + aabonuses.Mana + GroupLeadershipAAManaEnhancement());
|
||||
max_mana += itembonuses.heroic_max_mana;
|
||||
break;
|
||||
}
|
||||
@@ -8190,27 +8162,23 @@ void Bot::OwnerMessage(const std::string& message)
|
||||
bool Bot::CheckDataBucket(std::string bucket_name, const std::string& bucket_value, uint8 bucket_comparison)
|
||||
{
|
||||
if (!bucket_name.empty() && !bucket_value.empty()) {
|
||||
auto full_name = fmt::format(
|
||||
"{}-{}",
|
||||
GetBucketKey(),
|
||||
bucket_name
|
||||
);
|
||||
// try to fetch from bot first
|
||||
DataBucketKey k = GetScopedBucketKeys();
|
||||
k.key = bucket_name;
|
||||
|
||||
auto player_value = DataBucket::CheckBucketKey(this, full_name);
|
||||
if (player_value.empty() && GetBotOwner()) {
|
||||
full_name = fmt::format(
|
||||
"{}-{}",
|
||||
GetBotOwner()->GetBucketKey(),
|
||||
bucket_name
|
||||
);
|
||||
auto b = DataBucket::GetData(k);
|
||||
if (b.value.empty() && GetBotOwner()) {
|
||||
// fetch from owner
|
||||
k = GetBotOwner()->GetScopedBucketKeys();
|
||||
k.key = bucket_name;
|
||||
|
||||
player_value = DataBucket::CheckBucketKey(GetBotOwner(), full_name);
|
||||
if (player_value.empty()) {
|
||||
b = DataBucket::GetData(k);
|
||||
if (b.value.empty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (zone->CompareDataBucket(bucket_comparison, bucket_value, player_value)) {
|
||||
if (zone->CompareDataBucket(bucket_comparison, bucket_value, b.value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -8600,6 +8568,7 @@ std::vector<Mob*> Bot::GetApplySpellList(
|
||||
void Bot::ApplySpell(
|
||||
int spell_id,
|
||||
int duration,
|
||||
int level,
|
||||
ApplySpellType apply_type,
|
||||
bool allow_pets,
|
||||
bool is_raid_group_only
|
||||
@@ -8607,13 +8576,14 @@ void Bot::ApplySpell(
|
||||
const auto& l = GetApplySpellList(apply_type, allow_pets, is_raid_group_only);
|
||||
|
||||
for (const auto& m : l) {
|
||||
m->ApplySpellBuff(spell_id, duration);
|
||||
m->ApplySpellBuff(spell_id, duration, level);
|
||||
}
|
||||
}
|
||||
|
||||
void Bot::SetSpellDuration(
|
||||
int spell_id,
|
||||
int duration,
|
||||
int level,
|
||||
ApplySpellType apply_type,
|
||||
bool allow_pets,
|
||||
bool is_raid_group_only
|
||||
@@ -8621,7 +8591,7 @@ void Bot::SetSpellDuration(
|
||||
const auto& l = GetApplySpellList(apply_type, allow_pets, is_raid_group_only);
|
||||
|
||||
for (const auto& m : l) {
|
||||
m->SetBuffDuration(spell_id, duration);
|
||||
m->SetBuffDuration(spell_id, duration, level);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -130,7 +130,7 @@ public:
|
||||
|
||||
// Class Constructors
|
||||
Bot(NPCType *npcTypeData, Client* botOwner);
|
||||
Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType *npcTypeData);
|
||||
Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType *npcTypeData, int32 expansion_bitmask);
|
||||
|
||||
//abstract virtual override function implementations requird by base abstract class
|
||||
bool Death(Mob* killerMob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill) override;
|
||||
@@ -584,7 +584,7 @@ public:
|
||||
|
||||
// "Quest API" Methods
|
||||
bool HasBotSpellEntry(uint16 spellid);
|
||||
void ApplySpell(int spell_id, int duration = 0, ApplySpellType apply_type = ApplySpellType::Solo, bool allow_pets = false, bool is_raid_group_only = true);
|
||||
void ApplySpell(int spell_id, int duration = 0, int level = -1, ApplySpellType apply_type = ApplySpellType::Solo, bool allow_pets = false, bool is_raid_group_only = true);
|
||||
void BreakInvis();
|
||||
void Escape();
|
||||
void Fling(float value, float target_x, float target_y, float target_z, bool ignore_los = false, bool clip_through_walls = false, bool calculate_speed = false);
|
||||
@@ -593,7 +593,7 @@ public:
|
||||
int32 GetAugmentIDAt(int16 slot_id, uint8 augslot);
|
||||
int32 GetRawItemAC();
|
||||
void SendSpellAnim(uint16 targetid, uint16 spell_id);
|
||||
void SetSpellDuration(int spell_id, int duration = 0, ApplySpellType apply_type = ApplySpellType::Solo, bool allow_pets = false, bool is_raid_group_only = true);
|
||||
void SetSpellDuration(int spell_id, int duration = 0, int level = -1, ApplySpellType apply_type = ApplySpellType::Solo, bool allow_pets = false, bool is_raid_group_only = true);
|
||||
|
||||
// "SET" Class Methods
|
||||
void SetBotSpellID(uint32 newSpellID);
|
||||
|
||||
+240
-53
@@ -63,6 +63,7 @@
|
||||
#include "water_map.h"
|
||||
#include "worldserver.h"
|
||||
#include "dialogue_window.h"
|
||||
#include "mob.h"
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
@@ -1423,6 +1424,7 @@ int bot_command_init(void)
|
||||
bot_command_add("petremove", "Orders a bot to remove its charmed pet", AccountStatus::Player, bot_subcommand_pet_remove) ||
|
||||
bot_command_add("petsettype", "Orders a Magician bot to use a specified pet type", AccountStatus::Player, bot_subcommand_pet_set_type) ||
|
||||
bot_command_add("picklock", "Orders a capable bot to pick the lock of the closest door", AccountStatus::Player, bot_command_pick_lock) ||
|
||||
bot_command_add("pickpocket", "Orders a capable bot to pickpocket a NPC", AccountStatus::Player, bot_command_pickpocket) ||
|
||||
bot_command_add("precombat", "Sets flag used to determine pre-combat behavior", AccountStatus::Player, bot_command_precombat) ||
|
||||
bot_command_add("portal", "Orders a Wizard bot to open a magical doorway to a specified destination", AccountStatus::Player, bot_subcommand_portal) ||
|
||||
bot_command_add("pull", "Orders a designated bot to 'pull' an enemy", AccountStatus::Player, bot_command_pull) ||
|
||||
@@ -2097,7 +2099,6 @@ namespace ActionableBots
|
||||
ABT_Target,
|
||||
ABT_ByName,
|
||||
ABT_OwnerGroup,
|
||||
ABT_BotGroup,
|
||||
ABT_TargetGroup,
|
||||
ABT_NamesGroup,
|
||||
ABT_HealRotation,
|
||||
@@ -2438,7 +2439,6 @@ void bot_command_actionable(Client *c, const Seperator *sep)
|
||||
c->Message(Chat::White, "target - selects target as single bot .. use ^command [target] or imply by empty actionable argument");
|
||||
c->Message(Chat::White, "byname [name] - selects single bot by name");
|
||||
c->Message(Chat::White, "ownergroup - selects all bots in the owner's group");
|
||||
c->Message(Chat::White, "botgroup [name] - selects members of a bot-group by its name");
|
||||
c->Message(Chat::White, "targetgroup - selects all bots in target's group");
|
||||
c->Message(Chat::White, "namesgroup [name] - selects all bots in name's group");
|
||||
c->Message(Chat::White, "healrotation [name] - selects all member and target bots of a heal rotation where name is a member");
|
||||
@@ -2456,7 +2456,7 @@ void bot_command_aggressive(Client *c, const Seperator *sep)
|
||||
if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Stance) || helper_command_alias_fail(c, "bot_command_aggressive", sep->arg[0], "aggressive"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotationtargets | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotationtargets | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
helper_send_usage_required_bots(c, BCEnum::SpT_Stance);
|
||||
return;
|
||||
}
|
||||
@@ -2686,7 +2686,7 @@ void bot_command_attack(Client *c, const Seperator *sep)
|
||||
}
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
|
||||
c->Message(Chat::White, "usage: <enemy_target> %s [actionable: byname | ownergroup | botgroup | namesgroup | healrotation | default: spawned] ([actionable_name])", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: <enemy_target> %s [actionable: byname | ownergroup | namesgroup | healrotation | default: spawned] ([actionable_name])", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = ActionableBots::ABM_Type2;
|
||||
@@ -2814,19 +2814,6 @@ void bot_command_bot(Client *c, const Seperator *sep)
|
||||
helper_send_available_subcommands(c, "bot", subcommand_list);
|
||||
}
|
||||
|
||||
void bot_command_botgroup(Client *c, const Seperator *sep)
|
||||
{
|
||||
const std::list<const char*> subcommand_list = {
|
||||
"botgroupaddmember", "botgroupcreate", "botgroupdelete", "botgrouplist", "botgroupload", "botgroupremovemember"
|
||||
};
|
||||
|
||||
if (helper_command_alias_fail(c, "bot_command_botgroup", sep->arg[0], "botgroup")) {
|
||||
return;
|
||||
}
|
||||
|
||||
helper_send_available_subcommands(c, "bot-group", subcommand_list);
|
||||
}
|
||||
|
||||
void bot_command_charm(Client *c, const Seperator *sep)
|
||||
{
|
||||
auto local_list = &bot_command_spells[BCEnum::SpT_Charm];
|
||||
@@ -2956,7 +2943,7 @@ void bot_command_defensive(Client *c, const Seperator *sep)
|
||||
if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Stance) || helper_command_alias_fail(c, "bot_command_defensive", sep->arg[0], "defensive"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotationtargets | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotationtargets | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
helper_send_usage_required_bots(c, BCEnum::SpT_Stance);
|
||||
return;
|
||||
}
|
||||
@@ -3158,7 +3145,7 @@ void bot_command_follow(Client *c, const Seperator *sep)
|
||||
if (helper_command_alias_fail(c, "bot_command_follow", sep->arg[0], "follow"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: (<friendly_target>) %s ([option: reset]) [actionable: byname | ownergroup | botgroup | namesgroup | healrotation | spawned] ([actionable_name])", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: (<friendly_target>) %s ([option: reset]) [actionable: byname | ownergroup | namesgroup | healrotation | spawned] ([actionable_name])", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s chain", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
@@ -3265,7 +3252,7 @@ void bot_command_guard(Client *c, const Seperator *sep)
|
||||
}
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
|
||||
c->Message(Chat::White, "usage: %s ([option: clear]) [actionable: target | byname | ownergroup | botgroup | namesgroup | healrotation | spawned] ([actionable_name])", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([option: clear]) [actionable: target | byname | ownergroup | namesgroup | healrotation | spawned] ([actionable_name])", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_Type2);
|
||||
@@ -3399,7 +3386,7 @@ void bot_command_hold(Client *c, const Seperator *sep)
|
||||
}
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
|
||||
c->Message(Chat::White, "usage: %s ([option: clear]) [actionable: target | byname | ownergroup | botgroup | namesgroup | healrotation | spawned] ([actionable_name])", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([option: clear]) [actionable: target | byname | ownergroup | namesgroup | healrotation | spawned] ([actionable_name])", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_Type2);
|
||||
@@ -4739,7 +4726,7 @@ void bot_command_taunt(Client *c, const Seperator *sep)
|
||||
if (helper_command_alias_fail(c, "bot_command_taunt", sep->arg[0], "taunt"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotationtargets | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotationtargets | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
@@ -5056,7 +5043,7 @@ void bot_subcommand_bot_camp(Client *c, const Seperator *sep)
|
||||
if (helper_command_alias_fail(c, "bot_subcommand_bot_camp", sep->arg[0], "botcamp"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = ActionableBots::ABM_NoFilter;
|
||||
@@ -5316,7 +5303,7 @@ void bot_command_view_combos(Client *c, const Seperator *sep)
|
||||
const uint16 bot_race = static_cast<uint16>(Strings::ToUnsignedInt(sep->arg[1]));
|
||||
const std::string race_name = GetRaceIDName(bot_race);
|
||||
|
||||
if (!Mob::IsPlayerRace(bot_race)) {
|
||||
if (!IsPlayerRace(bot_race)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
@@ -5512,6 +5499,7 @@ void bot_subcommand_bot_create(Client *c, const Seperator *sep)
|
||||
|
||||
std::string bot_name = sep->arg[1];
|
||||
bot_name = Strings::UcFirst(bot_name);
|
||||
|
||||
if (arguments < 2 || !sep->IsNumber(2)) {
|
||||
c->Message(Chat::White, "Invalid class!");
|
||||
return;
|
||||
@@ -5639,7 +5627,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep)
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Usage: {} [Material Slot] [Red: 0-255] [Green: 0-255] [Blue: 0-255] ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))",
|
||||
"Usage: {} [Material Slot] [Red: 0-255] [Green: 0-255] [Blue: 0-255] ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))",
|
||||
sep->arg[0]
|
||||
).c_str()
|
||||
);
|
||||
@@ -5846,8 +5834,8 @@ void bot_subcommand_bot_follow_distance(Client *c, const Seperator *sep)
|
||||
if (helper_command_alias_fail(c, "bot_subcommand_bot_follow_distance", sep->arg[0], "botfollowdistance"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s [set] [distance] ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s [clear] ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s [set] [distance] ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s [clear] ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = ActionableBots::ABM_NoFilter;
|
||||
@@ -6021,7 +6009,7 @@ void bot_subcommand_bot_inspect_message(Client *c, const Seperator *sep)
|
||||
if (helper_command_alias_fail(c, "bot_subcommand_bot_inspect_message", sep->arg[0], "botinspectmessage"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s [set | clear] ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s [set | clear] ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "Notes:");
|
||||
if (c->ClientVersion() >= EQ::versions::ClientVersion::SoF) {
|
||||
c->Message(Chat::White, "- Self-inspect and type your bot's inspect message");
|
||||
@@ -6403,7 +6391,7 @@ void bot_subcommand_bot_report(Client *c, const Seperator *sep)
|
||||
if (helper_command_alias_fail(c, "bot_subcommand_bot_report", sep->arg[0], "botreport"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = ActionableBots::ABM_NoFilter;
|
||||
@@ -6762,7 +6750,7 @@ void bot_subcommand_bot_summon(Client *c, const Seperator *sep)
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Usage: {} ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))",
|
||||
"Usage: {} ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))",
|
||||
sep->arg[0]
|
||||
).c_str()
|
||||
);
|
||||
@@ -6907,7 +6895,7 @@ void bot_subcommand_bot_toggle_helm(Client *c, const Seperator *sep)
|
||||
if (helper_command_alias_fail(c, "bot_subcommand_bot_toggle_helm", sep->arg[0], "bottogglehelm"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = ActionableBots::ABM_NoFilter;
|
||||
@@ -8587,7 +8575,7 @@ void bot_subcommand_pet_get_lost(Client *c, const Seperator *sep)
|
||||
if (helper_command_alias_fail(c, "bot_subcommand_pet_get_lost", sep->arg[0], "petgetlost"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
int ab_mask = ActionableBots::ABM_NoFilter;
|
||||
@@ -8830,26 +8818,28 @@ void helper_bot_appearance_form_final(Client *bot_owner, Bot *my_bot)
|
||||
|
||||
void helper_bot_appearance_form_update(Bot *my_bot)
|
||||
{
|
||||
if (!my_bot)
|
||||
if (!my_bot) {
|
||||
return;
|
||||
}
|
||||
|
||||
my_bot->SendIllusionPacket(
|
||||
my_bot->GetRace(),
|
||||
my_bot->GetGender(),
|
||||
0xFF, //my_bot->GetTexture(), // 0xFF - change back if issues arise
|
||||
0xFF, //my_bot->GetHelmTexture(), // 0xFF - change back if issues arise
|
||||
my_bot->GetHairColor(),
|
||||
my_bot->GetBeardColor(),
|
||||
my_bot->GetEyeColor1(),
|
||||
my_bot->GetEyeColor2(),
|
||||
my_bot->GetHairStyle(),
|
||||
my_bot->GetLuclinFace(),
|
||||
my_bot->GetBeard(),
|
||||
0xFF, // aa_title (0xFF)
|
||||
my_bot->GetDrakkinHeritage(),
|
||||
my_bot->GetDrakkinTattoo(),
|
||||
my_bot->GetDrakkinDetails(),
|
||||
my_bot->GetSize()
|
||||
AppearanceStruct{
|
||||
.beard = my_bot->GetBeard(),
|
||||
.beard_color = my_bot->GetBeardColor(),
|
||||
.drakkin_details = my_bot->GetDrakkinDetails(),
|
||||
.drakkin_heritage = my_bot->GetDrakkinHeritage(),
|
||||
.drakkin_tattoo = my_bot->GetDrakkinTattoo(),
|
||||
.eye_color_one = my_bot->GetEyeColor1(),
|
||||
.eye_color_two = my_bot->GetEyeColor2(),
|
||||
.face = my_bot->GetLuclinFace(),
|
||||
.gender_id = my_bot->GetGender(),
|
||||
.hair = my_bot->GetHairStyle(),
|
||||
.hair_color = my_bot->GetHairColor(),
|
||||
.helmet_texture = my_bot->GetHelmTexture(),
|
||||
.race_id = my_bot->GetRace(),
|
||||
.size = my_bot->GetSize(),
|
||||
.texture = my_bot->GetTexture(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8864,8 +8854,8 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas
|
||||
bot_owner->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"'{}' is an invalid name. You may only use characters 'A-Z', 'a-z' and '_'.",
|
||||
bot_name
|
||||
"'{}' is an invalid name. You may only use characters 'A-Z' or 'a-z'. Mixed case {} allowed.",
|
||||
bot_name, RuleB(Bots, AllowCamelCaseNames) ? "is" : "is not"
|
||||
).c_str()
|
||||
);
|
||||
return bot_id;
|
||||
@@ -8894,7 +8884,7 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas
|
||||
return bot_id;
|
||||
}
|
||||
|
||||
if (!Bot::IsValidRaceClassCombo(bot_race, bot_class) && bot_owner->IsPlayerRace(bot_race)) {
|
||||
if (!Bot::IsValidRaceClassCombo(bot_race, bot_class) && IsPlayerRace(bot_race)) {
|
||||
const std::string bot_race_name = GetRaceIDName(bot_race);
|
||||
const std::string bot_class_name = GetClassIDName(bot_class);
|
||||
const auto view_saylink = Saylink::Silent(
|
||||
@@ -9181,7 +9171,7 @@ bool helper_cast_standard_spell(Bot* casting_bot, Mob* target_mob, int spell_id,
|
||||
|
||||
bool helper_command_disabled(Client* bot_owner, bool rule_value, const char* command)
|
||||
{
|
||||
if (rule_value) {
|
||||
if (!rule_value) {
|
||||
bot_owner->Message(Chat::White, "Bot command %s is not enabled on this server.", command);
|
||||
return true;
|
||||
}
|
||||
@@ -10007,3 +9997,200 @@ void bot_command_caster_range(Client* c, const Seperator* sep)
|
||||
c->Message(Chat::White, "Incorrect argument, use help for a list of options.");
|
||||
}
|
||||
}
|
||||
|
||||
void bot_command_pickpocket(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (helper_command_disabled(c, RuleB(Bots, AllowPickpocketCommand), "pickpocket")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_command_alias_fail(c, "bot_command_pickpocket", sep->arg[0], "pickpocket")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: <enemy_target>", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<Bot *> sbl;
|
||||
MyBots::PopulateSBL_BySpawnedBots(c, sbl);
|
||||
|
||||
// Check for capable rogue
|
||||
ActionableBots::Filter_ByClasses(c, sbl, PLAYER_CLASS_ROGUE_BIT);
|
||||
Bot *my_bot = ActionableBots::AsSpawned_ByMinLevelAndClass(c, sbl, 7, ROGUE);
|
||||
if (!my_bot) {
|
||||
c->Message(Chat::White, "No bots are capable of performing this action");
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure a mob is targetted and a valid NPC
|
||||
Mob *target_mob = ActionableTarget::AsSingle_ByAttackable(c);
|
||||
if (!target_mob || !target_mob->IsNPC()) {
|
||||
c->Message(Chat::White, "You must <target> an enemy to use this command");
|
||||
return;
|
||||
}
|
||||
|
||||
NPC *target_npc = ActionableTarget::AsSingle_ByAttackable(c)->CastToNPC();
|
||||
|
||||
// Check if mob is close enough
|
||||
glm::vec4 mob_distance = (c->GetPosition() - target_mob->GetPosition());
|
||||
float mob_xy_distance = ((mob_distance.x * mob_distance.x) + (mob_distance.y * mob_distance.y));
|
||||
float mob_z_distance = (mob_distance.z * mob_distance.z);
|
||||
float z_offset_diff = target_mob->GetZOffset() - c->GetZOffset();
|
||||
|
||||
if (mob_z_distance >= (35-z_offset_diff) || mob_xy_distance > 250) {
|
||||
c->Message(Chat::White, "You must be closer to an enemy to use this command");
|
||||
return;
|
||||
}
|
||||
|
||||
// Adapted from pickpock skill in npc.cpp
|
||||
// Make sure we are allowed to target them
|
||||
uint8 over_level = target_mob->GetLevel();
|
||||
if (over_level > (my_bot->GetLevel() + THIEF_PICKPOCKET_OVER)) {
|
||||
c->Message(Chat::Red, "You are too inexperienced to pick pocket this target");
|
||||
return;
|
||||
}
|
||||
|
||||
// Random fail roll
|
||||
if (zone->random.Roll(5)) {
|
||||
if (zone->CanDoCombat()) {
|
||||
target_mob->AddToHateList(c, 50);
|
||||
}
|
||||
target_mob->Say("Stop thief!");
|
||||
c->Message(Chat::Red, "You are noticed trying to steal!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup variables for calcs
|
||||
bool steal_skill = my_bot->GetSkill(EQ::skills::SkillPickPockets);
|
||||
bool steal_chance = steal_skill * 100 / (5 * over_level + 5);
|
||||
|
||||
// Determine whether to steal money or an item.
|
||||
uint32 money[6] = {
|
||||
0,
|
||||
((steal_skill >= 125) ? (target_npc->GetPlatinum()) : (0)),
|
||||
((steal_skill >= 60) ? (target_npc->GetGold()) : (0)),
|
||||
target_npc->GetSilver(),
|
||||
target_npc->GetCopper(),
|
||||
0
|
||||
};
|
||||
|
||||
bool has_coin = ((money[PickPocketPlatinum] | money[PickPocketGold] | money[PickPocketSilver] | money[PickPocketCopper]) != 0);
|
||||
bool steal_item = (steal_skill >= steal_chance && (zone->random.Roll(50) || !has_coin));
|
||||
|
||||
// Steal item
|
||||
while (steal_item) {
|
||||
std::vector<std::pair<const EQ::ItemData *, uint16>> loot_selection; // <const ItemData*, charges>
|
||||
for (auto item_iter: target_npc->itemlist) {
|
||||
if (!item_iter || !item_iter->item_id) {
|
||||
continue;
|
||||
}
|
||||
auto item_test = database.GetItem(item_iter->item_id);
|
||||
if (item_test->Magic || !item_test->NoDrop || item_test->IsClassBag() || c->CheckLoreConflict(item_test) ||
|
||||
item_iter->equip_slot != EQ::invslot::SLOT_INVALID) {
|
||||
continue;
|
||||
}
|
||||
loot_selection.emplace_back(
|
||||
std::make_pair(
|
||||
item_test,
|
||||
((item_test->Stackable) ? (1) : (item_iter->charges))
|
||||
)
|
||||
);
|
||||
}
|
||||
if (loot_selection.empty()) {
|
||||
steal_item = false;
|
||||
break;
|
||||
}
|
||||
|
||||
int random = zone->random.Int(0, (loot_selection.size() - 1));
|
||||
|
||||
int16 slot_id = c->GetInv().FindFreeSlot(
|
||||
false,
|
||||
true,
|
||||
(loot_selection[random].first->Size),
|
||||
(loot_selection[random].first->ItemType == EQ::item::ItemTypeArrow)
|
||||
);
|
||||
if (slot_id == INVALID_INDEX) {
|
||||
steal_item = false;
|
||||
break;
|
||||
}
|
||||
|
||||
auto item_inst = database.CreateItem(loot_selection[random].first, loot_selection[random].second);
|
||||
if (item_inst == nullptr) {
|
||||
steal_item = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Successful item pickpocket
|
||||
if (item_inst->IsStackable() && RuleB(Character, UseStackablePickPocketing)) {
|
||||
if (!c->TryStacking(item_inst, ItemPacketTrade, false, false)) {
|
||||
c->PutItemInInventory(slot_id, *item_inst);
|
||||
c->SendItemPacket(slot_id, item_inst, ItemPacketTrade);
|
||||
}
|
||||
}
|
||||
else {
|
||||
c->PutItemInInventory(slot_id, *item_inst);
|
||||
c->SendItemPacket(slot_id, item_inst, ItemPacketTrade);
|
||||
}
|
||||
target_npc->RemoveItem(item_inst->GetID());
|
||||
c->Message(Chat::White, "You stole an item.");
|
||||
safe_delete(item_inst);
|
||||
return;
|
||||
}
|
||||
|
||||
// no items, try money
|
||||
while (!steal_item && has_coin) {
|
||||
uint32 coin_amount = zone->random.Int(1, (steal_skill / 25) + 1);
|
||||
|
||||
int coin_type = PickPocketPlatinum;
|
||||
while (coin_type <= PickPocketCopper) {
|
||||
if (money[coin_type]) {
|
||||
if (coin_amount > money[coin_type]) {
|
||||
coin_amount = money[coin_type];
|
||||
}
|
||||
break;
|
||||
}
|
||||
++coin_type;
|
||||
}
|
||||
if (coin_type > PickPocketCopper) {
|
||||
break;
|
||||
}
|
||||
|
||||
memset(money, 0, (sizeof(int) * 6));
|
||||
money[coin_type] = coin_amount;
|
||||
|
||||
if (zone->random.Roll(steal_chance)) { // Successful coin pickpocket
|
||||
switch (coin_type) {
|
||||
case PickPocketPlatinum:
|
||||
target_npc->SetPlatinum(target_npc->GetPlatinum() - coin_amount);
|
||||
break;
|
||||
case PickPocketGold:
|
||||
target_npc->SetGold(target_npc->GetGold() - coin_amount);
|
||||
break;
|
||||
case PickPocketSilver:
|
||||
target_npc->SetSilver(target_npc->GetSilver() - coin_amount);
|
||||
break;
|
||||
case PickPocketCopper:
|
||||
target_npc->SetCopper(target_npc->GetCopper() - coin_amount);
|
||||
break;
|
||||
default: // has_coin..but, doesn't have coin?
|
||||
c->Message(Chat::Red, "You failed to pickpocket.");
|
||||
return;
|
||||
}
|
||||
c->Message(Chat::White, "You stole money.");
|
||||
c->AddMoneyToPP(
|
||||
money[PickPocketCopper],
|
||||
money[PickPocketSilver],
|
||||
money[PickPocketGold],
|
||||
money[PickPocketPlatinum],
|
||||
true
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
c->Message(Chat::Red, "You failed to pickpocket.");
|
||||
return;
|
||||
}
|
||||
c->Message(Chat::White, "This target's pockets are empty");
|
||||
}
|
||||
|
||||
+1
-1
@@ -552,7 +552,6 @@ void bot_command_apply_potion(Client* c, const Seperator* sep);
|
||||
void bot_command_attack(Client *c, const Seperator *sep);
|
||||
void bot_command_bind_affinity(Client *c, const Seperator *sep);
|
||||
void bot_command_bot(Client *c, const Seperator *sep);
|
||||
void bot_command_botgroup(Client *c, const Seperator *sep);
|
||||
void bot_command_caster_range(Client* c, const Seperator* sep);
|
||||
void bot_command_charm(Client *c, const Seperator *sep);
|
||||
void bot_command_cure(Client *c, const Seperator *sep);
|
||||
@@ -576,6 +575,7 @@ void bot_command_movement_speed(Client *c, const Seperator *sep);
|
||||
void bot_command_owner_option(Client *c, const Seperator *sep);
|
||||
void bot_command_pet(Client *c, const Seperator *sep);
|
||||
void bot_command_pick_lock(Client *c, const Seperator *sep);
|
||||
void bot_command_pickpocket(Client* c, const Seperator* sep);
|
||||
void bot_command_precombat(Client* c, const Seperator* sep);
|
||||
void bot_command_pull(Client *c, const Seperator *sep);
|
||||
void bot_command_release(Client *c, const Seperator *sep);
|
||||
|
||||
@@ -464,7 +464,8 @@ bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot)
|
||||
l.spells_id,
|
||||
l.time_spawned,
|
||||
l.zone_id,
|
||||
t
|
||||
t,
|
||||
l.expansion_bitmask
|
||||
);
|
||||
|
||||
if (loaded_bot) {
|
||||
@@ -479,8 +480,6 @@ bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot)
|
||||
|
||||
loaded_bot->SetStopMeleeLevel(l.stop_melee_level);
|
||||
|
||||
loaded_bot->SetExpansionBitmask(l.expansion_bitmask, false);
|
||||
|
||||
loaded_bot->SetBotEnforceSpellSetting((l.enforce_spell_settings ? true : false));
|
||||
|
||||
loaded_bot->SetBotArcherySetting((l.archery_setting ? true : false));
|
||||
|
||||
+323
-781
File diff suppressed because it is too large
Load Diff
+30
-14
@@ -123,6 +123,9 @@ typedef enum {
|
||||
EvacToSafeCoords
|
||||
} ZoneMode;
|
||||
|
||||
// translate above enum to a string
|
||||
std::string GetZoneModeString(ZoneMode mode);
|
||||
|
||||
enum {
|
||||
HideCorpseNone = 0,
|
||||
HideCorpseAll = 1,
|
||||
@@ -131,6 +134,12 @@ enum {
|
||||
HideCorpseNPC = 5
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
Disciplines,
|
||||
Spells
|
||||
} ShowSpellType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
Empty = 0,
|
||||
@@ -227,6 +236,7 @@ public:
|
||||
~Client();
|
||||
|
||||
void ReconnectUCS();
|
||||
void RecordStats();
|
||||
|
||||
void SetDisplayMobInfoWindow(bool display_mob_info_window);
|
||||
bool GetDisplayMobInfoWindow() const;
|
||||
@@ -375,6 +385,7 @@ public:
|
||||
inline PetInfo* GetPetInfo(uint16 pet) { return (pet==1)?&m_suspendedminion:&m_petinfo; }
|
||||
inline InspectMessage_Struct& GetInspectMessage() { return m_inspect_message; }
|
||||
inline const InspectMessage_Struct& GetInspectMessage() const { return m_inspect_message; }
|
||||
void ReloadExpansionProfileSetting();
|
||||
|
||||
void SetPetCommandState(int button, int state);
|
||||
|
||||
@@ -596,6 +607,7 @@ public:
|
||||
inline void SetEXPModifier(uint32 zone_id, double exp_modifier, int16 instance_version = -1) { database.SetEXPModifier(CharacterID(), zone_id, exp_modifier, instance_version); };
|
||||
|
||||
bool UpdateLDoNPoints(uint32 theme_id, int points);
|
||||
void SetLDoNPoints(uint32 theme_id, uint32 points);
|
||||
void SetPVPPoints(uint32 Points) { m_pp.PVPCurrentPoints = Points; }
|
||||
uint32 GetPVPPoints() { return m_pp.PVPCurrentPoints; }
|
||||
void AddPVPPoints(uint32 Points);
|
||||
@@ -669,6 +681,8 @@ public:
|
||||
inline const int32 GetInstanceID() const { return zone->GetInstanceID(); }
|
||||
void SetZoning(bool in) { bZoning = in; }
|
||||
|
||||
void ShowSpells(Client* c, ShowSpellType show_spell_type);
|
||||
|
||||
FACTION_VALUE GetReverseFactionCon(Mob* iOther);
|
||||
FACTION_VALUE GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 p_race, uint32 p_class, uint32 p_deity, int32 pFaction, Mob* tnpc);
|
||||
bool ReloadCharacterFaction(Client *c, uint32 facid, uint32 charid);
|
||||
@@ -764,7 +778,6 @@ public:
|
||||
void SetLanguageSkill(int langid, int value);
|
||||
void SetHoTT(uint32 mobid);
|
||||
void ShowSkillsWindow();
|
||||
void SendStatsWindow(Client* client, bool use_window);
|
||||
|
||||
uint16 MaxSkill(EQ::skills::SkillType skillid, uint16 class_, uint16 level) const;
|
||||
inline uint16 MaxSkill(EQ::skills::SkillType skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); }
|
||||
@@ -892,6 +905,9 @@ public:
|
||||
int GetAAPoints() { return m_pp.aapoints; }
|
||||
int GetSpentAA() { return m_pp.aapoints_spent; }
|
||||
uint32 GetRequiredAAExperience();
|
||||
void AutoGrantAAPoints();
|
||||
void GrantAllAAPoints();
|
||||
bool HasAlreadyPurchasedRank(AA::Rank* rank);
|
||||
|
||||
bool SendGMCommand(std::string message, bool ignore_status = false);
|
||||
|
||||
@@ -907,6 +923,7 @@ public:
|
||||
void ApplySpell(
|
||||
int spell_id,
|
||||
int duration = 0,
|
||||
int level = -1,
|
||||
ApplySpellType apply_type = ApplySpellType::Solo,
|
||||
bool allow_pets = false,
|
||||
bool is_raid_group_only = true,
|
||||
@@ -916,6 +933,7 @@ public:
|
||||
void SetSpellDuration(
|
||||
int spell_id,
|
||||
int duration = 0,
|
||||
int level = -1,
|
||||
ApplySpellType apply_type = ApplySpellType::Solo,
|
||||
bool allow_pets = false,
|
||||
bool is_raid_group_only = true,
|
||||
@@ -1087,7 +1105,7 @@ public:
|
||||
uint16 GetMaxSkillAfterSpecializationRules(EQ::skills::SkillType skillid, uint16 maxSkill);
|
||||
void SendPopupToClient(const char *Title, const char *Text, uint32 PopupID = 0, uint32 Buttons = 0, uint32 Duration = 0);
|
||||
void SendFullPopup(const char *Title, const char *Text, uint32 PopupID = 0, uint32 NegativeID = 0, uint32 Buttons = 0, uint32 Duration = 0, const char *ButtonName0 = 0, const char *ButtonName1 = 0, uint32 SoundControls = 0);
|
||||
void SendWindow(uint32 PopupID, uint32 NegativeID, uint32 Buttons, const char *ButtonName0, const char *ButtonName1, uint32 Duration, int title_type, Client* target, const char *Title, const char *Text, ...);
|
||||
void SendWindow(uint32 button_one_id, uint32 button_two_id, uint32 button_type, const char* button_one_text, const char* button_two_text, uint32 duration, int title_type, Mob* target, const char* title, const char* text, ...);
|
||||
bool PendingTranslocate;
|
||||
time_t TranslocateTime;
|
||||
bool PendingSacrifice;
|
||||
@@ -1340,7 +1358,7 @@ public:
|
||||
|
||||
bool CanEnterZone(const std::string& zone_short_name = "", int16 instance_version = -1);
|
||||
|
||||
int GetAggroCount();
|
||||
uint32 GetAggroCount();
|
||||
void IncrementAggroCount(bool raid_target = false);
|
||||
void DecrementAggroCount();
|
||||
void SendPVPStats();
|
||||
@@ -1353,8 +1371,8 @@ public:
|
||||
uint32 GetLDoNLossesTheme(uint32 t);
|
||||
uint32 GetLDoNPointsTheme(uint32 t);
|
||||
void UpdateLDoNWinLoss(uint32 theme_id, bool win = false, bool remove = false);
|
||||
void CheckLDoNHail(Mob *target);
|
||||
void CheckEmoteHail(Mob *target, const char* message);
|
||||
void CheckLDoNHail(NPC* n);
|
||||
void CheckEmoteHail(NPC* n, const char* message);
|
||||
|
||||
void HandleLDoNOpen(NPC *target);
|
||||
void HandleLDoNSenseTraps(NPC *target, uint16 skill, uint8 type);
|
||||
@@ -1552,8 +1570,6 @@ public:
|
||||
Timer* GetMercTimer() { return &merc_timer; };
|
||||
Timer* GetPickLockTimer() { return &pick_lock_timer; };
|
||||
|
||||
const char* GetRacePlural(Client* client);
|
||||
const char* GetClassPlural(Client* client);
|
||||
void SendWebLink(const char* website);
|
||||
void SendMarqueeMessage(uint32 type, std::string message, uint32 duration = 3000);
|
||||
void SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message);
|
||||
@@ -1576,8 +1592,10 @@ public:
|
||||
int32 GetActWIS() { return( std::min(GetMaxWIS(), GetWIS()) ); }
|
||||
int32 GetActCHA() { return( std::min(GetMaxCHA(), GetCHA()) ); }
|
||||
void LoadAccountFlags();
|
||||
void SetAccountFlag(std::string flag, std::string val);
|
||||
std::string GetAccountFlag(std::string flag);
|
||||
void ClearAccountFlag(const std::string& flag);
|
||||
void SetAccountFlag(const std::string& flag, const std::string& value);
|
||||
std::string GetAccountFlag(const std::string& flag);
|
||||
std::vector<std::string> GetAccountFlags();
|
||||
void SetGMStatus(int16 new_status);
|
||||
void Consume(const EQ::ItemData *item, uint8 type, int16 slot, bool auto_consume);
|
||||
void PlayMP3(const char* fname);
|
||||
@@ -1589,8 +1607,6 @@ public:
|
||||
void SetInvulnerableEnvironmentDamage(bool val) { invulnerable_environment_damage = val; }
|
||||
void SetIntoxication(int32 in_intoxication);
|
||||
|
||||
void ShowNumHits(); // work around function for numhits not showing on buffs
|
||||
|
||||
void ApplyWeaponsStance();
|
||||
void TogglePassiveAlternativeAdvancement(const AA::Rank &rank, uint32 ability_id);
|
||||
bool UseTogglePassiveHotkey(const AA::Rank &rank);
|
||||
@@ -1651,7 +1667,7 @@ protected:
|
||||
bool client_data_loaded;
|
||||
|
||||
|
||||
void FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost);
|
||||
void FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost, bool send_message_and_save);
|
||||
|
||||
Mob* bind_sight_target;
|
||||
|
||||
@@ -1900,7 +1916,7 @@ private:
|
||||
int8 last_reported_mana_percent;
|
||||
int8 last_reported_endurance_percent;
|
||||
|
||||
unsigned int AggroCount; // How many mobs are aggro on us.
|
||||
uint32 AggroCount; // How many mobs are aggro on us.
|
||||
|
||||
bool ooc_regen;
|
||||
float AreaHPRegen;
|
||||
@@ -1919,6 +1935,7 @@ private:
|
||||
public:
|
||||
void SetSharedTaskId(int64 shared_task_id);
|
||||
int64 GetSharedTaskId() const;
|
||||
struct XTarget_Struct XTargets[XTARGET_HARDCAP];
|
||||
private:
|
||||
|
||||
bool m_exp_enabled;
|
||||
@@ -1971,7 +1988,6 @@ private:
|
||||
bool XTargetAutoAddHaters;
|
||||
bool m_dirtyautohaters;
|
||||
|
||||
struct XTarget_Struct XTargets[XTARGET_HARDCAP];
|
||||
XTargetAutoHaters m_autohatermgr;
|
||||
XTargetAutoHaters *m_activeautohatermgr;
|
||||
|
||||
|
||||
@@ -649,7 +649,7 @@ int64 Client::CalcBaseMana()
|
||||
int64 Client::CalcBaseManaRegen()
|
||||
{
|
||||
uint8 clevel = GetLevel();
|
||||
int32 regen = 0;
|
||||
int64 regen = 0;
|
||||
if (IsSitting() || (GetHorseId() != 0)) {
|
||||
if (HasSkill(EQ::skills::SkillMeditate)) {
|
||||
regen = (((GetSkill(EQ::skills::SkillMeditate) / 10) + (clevel - (clevel / 4))) / 4) + 4;
|
||||
@@ -666,7 +666,7 @@ int64 Client::CalcBaseManaRegen()
|
||||
|
||||
int64 Client::CalcManaRegen(bool bCombat)
|
||||
{
|
||||
int regen = 0;
|
||||
int64 regen = 0;
|
||||
auto level = GetLevel();
|
||||
// so the new formulas break down with older skill caps where you don't have the skill until 4 or 8
|
||||
// so for servers that want to use the old skill progression they can set this rule so they
|
||||
@@ -688,9 +688,9 @@ int64 Client::CalcManaRegen(bool bCombat)
|
||||
}
|
||||
}
|
||||
if (old)
|
||||
regen = std::max(regen, 2);
|
||||
regen = std::max(regen, static_cast<int64>(2));
|
||||
} else if (old) {
|
||||
regen = std::max(regen, 1);
|
||||
regen = std::max(regen, static_cast<int64>(1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+371
-41
@@ -62,6 +62,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../common/repositories/account_repository.h"
|
||||
|
||||
#include "../common/events/player_event_logs.h"
|
||||
#include "../common/repositories/character_stats_record_repository.h"
|
||||
|
||||
extern QueryServ* QServ;
|
||||
extern Zone* zone;
|
||||
@@ -144,6 +145,7 @@ void MapOpcodes()
|
||||
ConnectedOpcodes[OP_Bind_Wound] = &Client::Handle_OP_Bind_Wound;
|
||||
ConnectedOpcodes[OP_BlockedBuffs] = &Client::Handle_OP_BlockedBuffs;
|
||||
ConnectedOpcodes[OP_BoardBoat] = &Client::Handle_OP_BoardBoat;
|
||||
ConnectedOpcodes[OP_BookButton] = &Client::Handle_OP_BookButton;
|
||||
ConnectedOpcodes[OP_Buff] = &Client::Handle_OP_Buff;
|
||||
ConnectedOpcodes[OP_BuffRemoveRequest] = &Client::Handle_OP_BuffRemoveRequest;
|
||||
ConnectedOpcodes[OP_Bug] = &Client::Handle_OP_Bug;
|
||||
@@ -328,6 +330,8 @@ void MapOpcodes()
|
||||
ConnectedOpcodes[OP_PVPLeaderBoardRequest] = &Client::Handle_OP_PVPLeaderBoardRequest;
|
||||
ConnectedOpcodes[OP_QueryUCSServerStatus] = &Client::Handle_OP_QueryUCSServerStatus;
|
||||
ConnectedOpcodes[OP_RaidInvite] = &Client::Handle_OP_RaidCommand;
|
||||
ConnectedOpcodes[OP_RaidDelegateAbility] = &Client::Handle_OP_RaidDelegateAbility;
|
||||
ConnectedOpcodes[OP_RaidClearNPCMarks] = &Client::Handle_OP_RaidClearNPCMarks;
|
||||
ConnectedOpcodes[OP_RandomReq] = &Client::Handle_OP_RandomReq;
|
||||
ConnectedOpcodes[OP_ReadBook] = &Client::Handle_OP_ReadBook;
|
||||
ConnectedOpcodes[OP_RecipeAutoCombine] = &Client::Handle_OP_RecipeAutoCombine;
|
||||
@@ -607,7 +611,6 @@ void Client::CompleteConnect()
|
||||
but not important for now.
|
||||
*/
|
||||
raid->SendRaidCreate(this);
|
||||
raid->SendMakeLeaderPacketTo(raid->leadername, this);
|
||||
raid->SendRaidAdd(GetName(), this);
|
||||
raid->SendBulkRaid(this);
|
||||
raid->SendGroupUpdate(this);
|
||||
@@ -616,6 +619,7 @@ void Client::CompleteConnect()
|
||||
raid->UpdateRaidAAs();
|
||||
raid->SendAllRaidLeadershipAA();
|
||||
}
|
||||
raid->SendMakeLeaderPacketTo(raid->leadername, this);
|
||||
uint32 grpID = raid->GetGroup(GetName());
|
||||
if (grpID < 12) {
|
||||
raid->SendRaidGroupRemove(GetName(), grpID);
|
||||
@@ -636,6 +640,8 @@ void Client::CompleteConnect()
|
||||
raid->SendRaidLockTo(this);
|
||||
|
||||
raid->SendHPManaEndPacketsTo(this);
|
||||
raid->SendAssistTarget(this);
|
||||
raid->SendMarkTargets(this);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -911,6 +917,10 @@ void Client::CompleteConnect()
|
||||
|
||||
heroforge_wearchange_timer.Start(250);
|
||||
|
||||
RecordStats();
|
||||
|
||||
AutoGrantAAPoints();
|
||||
|
||||
// enforce some rules..
|
||||
if (!CanEnterZone()) {
|
||||
LogInfo("Kicking character [{}] from zone, not allowed here (missing requirements)", GetCleanName());
|
||||
@@ -1438,12 +1448,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
if (m_pp.ldon_points_tak < 0 || m_pp.ldon_points_tak > 2000000000) { m_pp.ldon_points_tak = 0; }
|
||||
if (m_pp.ldon_points_available < 0 || m_pp.ldon_points_available > 2000000000) { m_pp.ldon_points_available = 0; }
|
||||
|
||||
if (RuleB(World, UseClientBasedExpansionSettings)) {
|
||||
m_pp.expansions = EQ::expansions::ConvertClientVersionToExpansionsMask(ClientVersion());
|
||||
}
|
||||
else {
|
||||
m_pp.expansions = (RuleI(World, ExpansionSettings) & EQ::expansions::ConvertClientVersionToExpansionsMask(ClientVersion()));
|
||||
}
|
||||
ReloadExpansionProfileSetting();
|
||||
|
||||
if (!database.LoadAlternateAdvancement(this)) {
|
||||
LogError("Error loading AA points for [{}]", GetName());
|
||||
@@ -2120,6 +2125,11 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app)
|
||||
(tmp->GetClass() != DISCORD_MERCHANT) && (tmp->GetClass() != NORRATHS_KEEPERS_MERCHANT) && (tmp->GetClass() != DARK_REIGN_MERCHANT)))
|
||||
return;
|
||||
|
||||
if (!tmp->CastToNPC()->IsMerchantOpen()) {
|
||||
tmp->SayString(zone->random.Int(MERCHANT_CLOSED_ONE, MERCHANT_CLOSED_THREE));
|
||||
return;
|
||||
}
|
||||
|
||||
//you have to be somewhat close to them to be properly using them
|
||||
if (DistanceSquared(m_Position, tmp->GetPosition()) > USE_NPC_RANGE2)
|
||||
return;
|
||||
@@ -2129,7 +2139,7 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app)
|
||||
const EQ::ItemData *item = nullptr;
|
||||
std::list<MerchantList> merlist = zone->merchanttable[merchantid];
|
||||
std::list<MerchantList>::const_iterator itr;
|
||||
for (itr = merlist.begin(); itr != merlist.end() && count<255; ++itr) {
|
||||
for (itr = merlist.begin(); itr != merlist.end(); ++itr) {
|
||||
const MerchantList &ml = *itr;
|
||||
if (GetLevel() < ml.level_required) {
|
||||
continue;
|
||||
@@ -3038,8 +3048,22 @@ void Client::Handle_OP_AssistGroup(const EQApplicationPacket *app)
|
||||
LogDebug("Size mismatch in OP_AssistGroup expected [{}] got [{}]", sizeof(EntityId_Struct), app->size);
|
||||
return;
|
||||
}
|
||||
QueuePacket(app);
|
||||
return;
|
||||
|
||||
EntityId_Struct* eid = (EntityId_Struct*)app->pBuffer;
|
||||
Entity* entity = entity_list.GetID(eid->entity_id);
|
||||
|
||||
if (entity && entity->IsMob()) {
|
||||
Mob* new_target = entity->CastToMob();
|
||||
if (new_target && (GetGM() ||
|
||||
Distance(m_Position, new_target->GetPosition()) <= TARGETING_RANGE)) {
|
||||
cheat_manager.SetExemptStatus(Assist, true);
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Assist, sizeof(EntityId_Struct));
|
||||
eid = (EntityId_Struct*)outapp->pBuffer;
|
||||
eid->entity_id = new_target->GetID();
|
||||
FastQueuePacket(&outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Client::Handle_OP_AugmentInfo(const EQApplicationPacket *app)
|
||||
@@ -4107,6 +4131,28 @@ void Client::Handle_OP_BoardBoat(const EQApplicationPacket *app)
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_BookButton(const EQApplicationPacket* app)
|
||||
{
|
||||
if (app->size != sizeof(BookButton_Struct))
|
||||
{
|
||||
LogError("Size mismatch in OP_BookButton. expected [{}] got [{}]", sizeof(BookButton_Struct), app->size);
|
||||
DumpPacket(app);
|
||||
return;
|
||||
}
|
||||
|
||||
BookButton_Struct* book = reinterpret_cast<BookButton_Struct*>(app->pBuffer);
|
||||
|
||||
const EQ::ItemInstance* const inst = GetInv().GetItem(book->invslot);
|
||||
if (inst && inst->GetItem()->Book)
|
||||
{
|
||||
// todo: if scribe book learn recipes and delete book from inventory
|
||||
// todo: if cast book use its spell on target and delete book from inventory (unless reusable?)
|
||||
}
|
||||
|
||||
EQApplicationPacket outapp(OP_FinishWindow, 0);
|
||||
QueuePacket(&outapp);
|
||||
}
|
||||
|
||||
void Client::Handle_OP_Buff(const EQApplicationPacket *app)
|
||||
{
|
||||
/*
|
||||
@@ -5201,12 +5247,12 @@ void Client::Handle_OP_ConsiderCorpse(const EQApplicationPacket *app)
|
||||
|
||||
uint32 decay_time = t->GetDecayTime();
|
||||
if (decay_time) {
|
||||
auto time_string = Strings::SecondsToTime(decay_time, true);
|
||||
const std::string& time_string = Strings::SecondsToTime(decay_time, true);
|
||||
Message(
|
||||
Chat::NPCQuestSay,
|
||||
fmt::format(
|
||||
"This corpse will decay in {}.",
|
||||
time_string
|
||||
Strings::ToLower(time_string)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
@@ -5845,6 +5891,31 @@ void Client::Handle_OP_DoGroupLeadershipAbility(const EQApplicationPacket *app)
|
||||
break;
|
||||
}
|
||||
|
||||
case RaidLeadershipAbility_MainAssist:
|
||||
{
|
||||
//This is not needed as it executes from opcode 0x2b33 which is sent
|
||||
//with this opcode.
|
||||
//if (GetTarget())
|
||||
//{
|
||||
// Raid* r = GetRaid();
|
||||
// if (r)
|
||||
// {
|
||||
// r->DelegateAbility(GetTarget()->CastToClient()->GetName());
|
||||
// }
|
||||
//}
|
||||
break;
|
||||
}
|
||||
case RaidLeadershipAbility_MarkNPC:
|
||||
{
|
||||
if (GetTarget() && GetTarget()->IsMob()) {
|
||||
Raid* r = GetRaid();
|
||||
if (r) {
|
||||
r->RaidMarkNPC(this, dglas->Parameter);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
default:
|
||||
LogDebug("Got unhandled OP_DoGroupLeadershipAbility Ability: [{}] Parameter: [{}]", dglas->Ability, dglas->Parameter);
|
||||
break;
|
||||
@@ -6774,16 +6845,14 @@ void Client::Handle_OP_GMSearchCorpse(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_GMServers(const EQApplicationPacket *app)
|
||||
{
|
||||
if (!worldserver.Connected())
|
||||
Message(Chat::Red, "Error: World server disconnected");
|
||||
else {
|
||||
auto pack = new ServerPacket(ServerOP_ZoneStatus, strlen(GetName()) + 2);
|
||||
memset(pack->pBuffer, (uint8)admin, 1);
|
||||
strcpy((char *)&pack->pBuffer[1], GetName());
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
return;
|
||||
auto pack = new ServerPacket(ServerOP_ZoneStatus, sizeof(ServerZoneStatus_Struct));
|
||||
|
||||
auto z = (ServerZoneStatus_Struct *) pack->pBuffer;
|
||||
z->admin = Admin();
|
||||
strn0cpy(z->name, GetName(), sizeof(z->name));
|
||||
|
||||
worldserver.SendPacket(pack);
|
||||
delete pack;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_GMSummon(const EQApplicationPacket *app)
|
||||
@@ -9142,8 +9211,14 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
|
||||
}
|
||||
else if (inst->IsClassCommon())
|
||||
{
|
||||
if (!RuleB(Skills, RequireTomeHandin) && item->ItemType == EQ::item::ItemTypeSpell && (strstr((const char*)item->Name, "Tome of ") || strstr((const char*)item->Name, "Skill: ")))
|
||||
{
|
||||
if (
|
||||
!RuleB(Skills, RequireTomeHandin) &&
|
||||
item->ItemType == EQ::item::ItemTypeSpell &&
|
||||
(
|
||||
Strings::BeginsWith(item->Name, "Tome of ") ||
|
||||
Strings::BeginsWith(item->Name, "Skill: ")
|
||||
)
|
||||
) {
|
||||
DeleteItemInInventory(slot_id, 1, true);
|
||||
TrainDiscipline(item->ID);
|
||||
}
|
||||
@@ -10707,7 +10782,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
case PET_HEALTHREPORT: {
|
||||
if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) {
|
||||
MessageString(Chat::PetResponse, PET_REPORT_HP, ConvertArrayF(mypet->GetHPRatio(), val1));
|
||||
mypet->ShowBuffList(this);
|
||||
mypet->ShowBuffs(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -11457,10 +11532,9 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app)
|
||||
break;
|
||||
|
||||
case POPUPID_UPDATE_SHOWSTATSWINDOW:
|
||||
if (GetTarget() && GetTarget()->IsClient()) {
|
||||
GetTarget()->CastToClient()->SendStatsWindow(this, true);
|
||||
}
|
||||
else {
|
||||
if (GetTarget() && GetTarget()->IsOfClientBot()) {
|
||||
GetTarget()->SendStatsWindow(this, true);
|
||||
} else {
|
||||
SendStatsWindow(this, true);
|
||||
}
|
||||
return;
|
||||
@@ -11926,6 +12000,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
||||
if (raid->IsLocked()) {
|
||||
raid->SendRaidLockTo(c);
|
||||
}
|
||||
raid->SendAssistTarget(c);
|
||||
raid->SendMarkTargets(c);
|
||||
}
|
||||
}
|
||||
group->JoinRaidXTarget(raid);
|
||||
@@ -11940,6 +12016,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
||||
if (raid->IsLocked()) {
|
||||
raid->SendRaidLockTo(this);
|
||||
}
|
||||
raid->SendAssistTarget(this);
|
||||
raid->SendMarkTargets(this);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -11980,6 +12058,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
||||
if (raid->IsLocked()) {
|
||||
raid->SendRaidLockTo(c);
|
||||
}
|
||||
raid->SendAssistTarget(c);
|
||||
raid->SendMarkTargets(c);
|
||||
}
|
||||
else {
|
||||
Client* c = nullptr;
|
||||
@@ -11996,6 +12076,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
||||
if (raid->IsLocked()) {
|
||||
raid->SendRaidLockTo(c);
|
||||
}
|
||||
raid->SendAssistTarget(c);
|
||||
raid->SendMarkTargets(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12035,6 +12117,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
||||
if (raid->IsLocked()) {
|
||||
raid->SendRaidLockTo(c);
|
||||
}
|
||||
raid->SendAssistTarget(c);
|
||||
raid->SendMarkTargets(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -12052,6 +12136,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
||||
if (raid->IsLocked()) {
|
||||
raid->SendRaidLockTo(c);
|
||||
}
|
||||
raid->SendAssistTarget(c);
|
||||
raid->SendMarkTargets(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12092,6 +12178,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
||||
if (raid->IsLocked()) {
|
||||
raid->SendRaidLockTo(c);
|
||||
}
|
||||
raid->SendAssistTarget(c);
|
||||
raid->SendMarkTargets(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -12108,6 +12196,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
||||
if (raid->IsLocked()) {
|
||||
raid->SendRaidLockTo(c);
|
||||
}
|
||||
raid->SendAssistTarget(c);
|
||||
raid->SendMarkTargets(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12121,6 +12211,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
||||
if (raid->IsLocked()) {
|
||||
raid->SendRaidLockTo(this);
|
||||
}
|
||||
raid->SendAssistTarget(this);
|
||||
raid->SendMarkTargets(this);
|
||||
}
|
||||
else { // neither has a group
|
||||
raid = new Raid(player_sending_invite);
|
||||
@@ -12135,6 +12227,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
||||
if (raid->IsLocked()) {
|
||||
raid->SendRaidLockTo(this);
|
||||
}
|
||||
raid->SendAssistTarget(this);
|
||||
raid->SendMarkTargets(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12157,6 +12251,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
||||
//Does not camp the Bots, just removes from the raid
|
||||
if (c_to_disband) {
|
||||
uint32 i = raid->GetPlayerIndex(raid_command_packet->leader_name);
|
||||
raid->RemoveRaidDelegates(raid_command_packet->leader_name);
|
||||
raid->SendRemoveAllRaidXTargets(raid_command_packet->leader_name);
|
||||
raid->SetNewRaidLeader(i);
|
||||
raid->HandleBotGroupDisband(c_to_disband->CharacterID());
|
||||
raid->HandleOfflineBots(c_to_disband->CharacterID());
|
||||
@@ -12172,11 +12268,13 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
||||
|
||||
if (gid < 12 && (raid->IsGroupLeader(b_to_disband->GetName()) || raid->GroupCount(gid) < 2)) {
|
||||
uint32 owner_id = b_to_disband->CastToBot()->GetOwner()->CastToClient()->CharacterID();
|
||||
raid->RemoveRaidDelegates(raid_command_packet->leader_name);
|
||||
raid->UpdateRaidXTargets();
|
||||
raid->HandleBotGroupDisband(owner_id, gid);
|
||||
|
||||
} else if (b_to_disband && raid->IsRaidMember(b_to_disband->GetName())) {
|
||||
raid->RemoveRaidDelegates(raid_command_packet->leader_name);
|
||||
raid->UpdateRaidXTargets();
|
||||
Bot::RemoveBotFromRaid(b_to_disband);
|
||||
|
||||
} else if (gid < 12 && raid->GetGroupLeader(gid) && raid->GetGroupLeader(gid)->IsBot()) {
|
||||
c_doing_disband->Message(
|
||||
Chat::Yellow,
|
||||
@@ -12207,6 +12305,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
||||
}
|
||||
}
|
||||
raid->SetNewRaidLeader(i);
|
||||
raid->RemoveRaidDelegates(raid_command_packet->leader_name);
|
||||
raid->UpdateRaidXTargets();
|
||||
raid->RemoveMember(raid_command_packet->leader_name);
|
||||
Client* c = entity_list.GetClientByName(raid_command_packet->leader_name);
|
||||
if (c) {
|
||||
@@ -12260,9 +12360,9 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
||||
if (client_to_update) {
|
||||
raid->SendRaidRemove(raid->members[x].member_name, client_to_update);
|
||||
raid->SendRaidCreate(client_to_update);
|
||||
raid->SendMakeLeaderPacketTo(raid->leadername, client_to_update);
|
||||
raid->SendRaidAdd(raid->members[x].member_name, client_to_update);
|
||||
raid->SendBulkRaid(client_to_update);
|
||||
raid->SendMakeLeaderPacketTo(raid->leadername, client_to_update);
|
||||
if (raid->IsLocked()) {
|
||||
raid->SendRaidLockTo(client_to_update);
|
||||
}
|
||||
@@ -12310,9 +12410,9 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
||||
raid->GroupUpdate(raid_command_packet->parameter);
|
||||
|
||||
/* If our old was a group send update there too */
|
||||
if (old_group < 12)
|
||||
if (old_group < 12) {
|
||||
raid->GroupUpdate(old_group);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Move player to ungrouped bank */
|
||||
@@ -12373,7 +12473,7 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
||||
}
|
||||
|
||||
raid->GroupUpdate(oldgrp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Client* client_moved = entity_list.GetClientByName(raid_command_packet->leader_name);
|
||||
@@ -12471,7 +12571,18 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
||||
raid->SendRaidMOTDToWorld();
|
||||
break;
|
||||
}
|
||||
case RaidCommandSetNote:
|
||||
{
|
||||
|
||||
Raid* raid = entity_list.GetRaidByClient(this);
|
||||
if (!raid) {
|
||||
break;
|
||||
}
|
||||
|
||||
raid->SaveRaidNote(raid_command_packet->leader_name, raid_command_packet->note);
|
||||
raid->SendRaidNotesToWorld();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
Message(Chat::Red, "Raid command (%d) NYI", raid_command_packet->action);
|
||||
break;
|
||||
@@ -14021,9 +14132,8 @@ void Client::Handle_OP_ShopRequest(const EQApplicationPacket *app)
|
||||
if (tmp->Charmed())
|
||||
action = 0;
|
||||
|
||||
// 1199 I don't have time for that now. etc
|
||||
if (!tmp->CastToNPC()->IsMerchantOpen()) {
|
||||
tmp->SayString(zone->random.Int(1199, 1202));
|
||||
tmp->SayString(zone->random.Int(MERCHANT_CLOSED_ONE, MERCHANT_CLOSED_THREE));
|
||||
action = 0;
|
||||
}
|
||||
|
||||
@@ -14313,7 +14423,7 @@ void Client::Handle_OP_Split(const EQApplicationPacket *app)
|
||||
if (raid)
|
||||
raid->SplitMoney(raid->GetGroup(this), split->copper, split->silver, split->gold, split->platinum);
|
||||
else if (group)
|
||||
group->SplitMoney(split->copper, split->silver, split->gold, split->platinum);
|
||||
group->SplitMoney(split->copper, split->silver, split->gold, split->platinum, this);
|
||||
|
||||
return;
|
||||
|
||||
@@ -14428,8 +14538,8 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app)
|
||||
|
||||
if (nt) {
|
||||
if (GetGM() || (!nt->IsInvisible(this) && (DistanceSquared(m_Position, nt->GetPosition()) <= TARGETING_RANGE*TARGETING_RANGE))) {
|
||||
if (nt->GetBodyType() == BT_NoTarget2 ||
|
||||
nt->GetBodyType() == BT_Special ||
|
||||
if (nt->GetBodyType() == BT_NoTarget2 ||
|
||||
nt->GetBodyType() == BT_Special ||
|
||||
nt->GetBodyType() == BT_NoTarget) {
|
||||
can_target = false;
|
||||
}
|
||||
@@ -15792,14 +15902,87 @@ void Client::Handle_OP_XTargetRequest(const EQApplicationPacket *app)
|
||||
case RaidAssist1:
|
||||
case RaidAssist2:
|
||||
case RaidAssist3:
|
||||
{
|
||||
struct AssistType {
|
||||
XTargetType type;
|
||||
int32 assist_slot;
|
||||
};
|
||||
|
||||
std::vector<AssistType> assist_types = {
|
||||
{ RaidAssist1, MAIN_ASSIST_1_SLOT },
|
||||
{ RaidAssist2, MAIN_ASSIST_2_SLOT },
|
||||
{ RaidAssist3, MAIN_ASSIST_3_SLOT }
|
||||
};
|
||||
|
||||
for (auto& t : assist_types) {
|
||||
if (t.type == Type) {
|
||||
Raid* r = GetRaid();
|
||||
if (r) {
|
||||
Client* ma = entity_list.GetClientByName(r->main_assister_pcs[t.assist_slot]);
|
||||
if (ma) {
|
||||
UpdateXTargetType(t.type, ma, ma->GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RaidAssist1Target:
|
||||
case RaidAssist2Target:
|
||||
case RaidAssist3Target:
|
||||
{
|
||||
struct AssistType {
|
||||
XTargetType type;
|
||||
int32 assist_slot;
|
||||
};
|
||||
|
||||
std::vector<AssistType> assist_types = {
|
||||
{ RaidAssist1Target, MAIN_ASSIST_1_SLOT },
|
||||
{ RaidAssist2Target, MAIN_ASSIST_2_SLOT },
|
||||
{ RaidAssist3Target, MAIN_ASSIST_3_SLOT }
|
||||
};
|
||||
|
||||
for (auto& t : assist_types) {
|
||||
if (t.type == Type) {
|
||||
Raid* r = GetRaid();
|
||||
if (r) {
|
||||
Client* ma = entity_list.GetClientByName(r->main_assister_pcs[t.assist_slot]);
|
||||
if (ma && ma->GetTarget()) {
|
||||
UpdateXTargetType(t.type, ma->GetTarget(), ma->GetTarget()->GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RaidMarkTarget1:
|
||||
case RaidMarkTarget2:
|
||||
case RaidMarkTarget3:
|
||||
{
|
||||
// Not implemented yet.
|
||||
struct AssistType {
|
||||
XTargetType type;
|
||||
int32 assist_slot;
|
||||
};
|
||||
|
||||
std::vector<AssistType> assist_types = {
|
||||
{ RaidMarkTarget1, MAIN_MARKER_1_SLOT },
|
||||
{ RaidMarkTarget2, MAIN_MARKER_2_SLOT },
|
||||
{ RaidMarkTarget3, MAIN_MARKER_3_SLOT }
|
||||
};
|
||||
|
||||
for (auto& t : assist_types) {
|
||||
if (t.type == Type) {
|
||||
Raid* r = GetRaid();
|
||||
if (r) {
|
||||
auto mm = entity_list.GetNPCByID(r->marked_npcs[t.assist_slot].entity_id);
|
||||
if (mm) {
|
||||
UpdateXTargetType(t.type, mm->CastToMob(), mm->CastToMob()->GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -16183,3 +16366,150 @@ void Client::RecordKilledNPCEvent(NPC *n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Client::Handle_OP_RaidDelegateAbility(const EQApplicationPacket *app)
|
||||
{
|
||||
if (app->size != sizeof(DelegateAbility_Struct)) {
|
||||
LogDebug(
|
||||
"Size mismatch in OP_RaidDelegateAbility expected [{}] got [{}]",
|
||||
sizeof(DelegateAbility_Struct),
|
||||
app->size
|
||||
);
|
||||
DumpPacket(app);
|
||||
return;
|
||||
}
|
||||
|
||||
DelegateAbility_Struct *das = (DelegateAbility_Struct *) app->pBuffer;
|
||||
|
||||
switch (das->DelegateAbility) {
|
||||
case RaidDelegateMainAssist: {
|
||||
auto r = GetRaid();
|
||||
if (r) {
|
||||
r->DelegateAbilityAssist(this, das->Name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RaidDelegateMainMarker: {
|
||||
auto r = GetRaid();
|
||||
if (r) {
|
||||
r->DelegateAbilityMark(this, das->Name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LogDebug("RaidDelegateAbility default case");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Client::Handle_OP_RaidClearNPCMarks(const EQApplicationPacket* app)
|
||||
{
|
||||
if (app->size != 0) {
|
||||
LogDebug("Size mismatch in OP_RaidClearNPCMark expected [{}] got [{}]", 0, app->size);
|
||||
DumpPacket(app);
|
||||
return;
|
||||
}
|
||||
|
||||
auto r = GetRaid();
|
||||
if (r) {
|
||||
r->RaidClearNPCMarks(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::RecordStats()
|
||||
{
|
||||
auto r = CharacterStatsRecordRepository::FindOne(
|
||||
database,
|
||||
CharacterID()
|
||||
);
|
||||
|
||||
r.status = Admin();
|
||||
r.name = GetCleanName();
|
||||
r.aa_points = GetAAPoints() + GetSpentAA();
|
||||
r.level = GetLevel();
|
||||
r.class_ = GetBaseClass();
|
||||
r.race = GetBaseRace();
|
||||
r.hp = GetMaxHP() - GetSpellBonuses().HP;
|
||||
r.mana = GetMaxMana() - GetSpellBonuses().Mana;
|
||||
r.endurance = GetMaxEndurance() - GetSpellBonuses().Endurance;
|
||||
r.ac = GetDisplayAC() - GetSpellBonuses().AC;
|
||||
r.strength = GetSTR() - GetSpellBonuses().STR;
|
||||
r.stamina = GetSTA() - GetSpellBonuses().STA;
|
||||
r.dexterity = GetDEX() - GetSpellBonuses().DEX;
|
||||
r.agility = GetAGI() - GetSpellBonuses().AGI;
|
||||
r.intelligence = GetINT() - GetSpellBonuses().INT;
|
||||
r.wisdom = GetWIS() - GetSpellBonuses().WIS;
|
||||
r.charisma = GetCHA() - GetSpellBonuses().CHA;
|
||||
r.magic_resist = GetMR() - GetSpellBonuses().MR;
|
||||
r.fire_resist = GetFR() - GetSpellBonuses().FR;
|
||||
r.cold_resist = GetCR() - GetSpellBonuses().CR;
|
||||
r.poison_resist = GetPR() - GetSpellBonuses().PR;
|
||||
r.disease_resist = GetDR() - GetSpellBonuses().DR;
|
||||
r.corruption_resist = GetCorrup() - GetSpellBonuses().Corrup;
|
||||
r.heroic_strength = GetHeroicSTR() - GetSpellBonuses().HeroicSTR;
|
||||
r.heroic_stamina = GetHeroicSTA() - GetSpellBonuses().HeroicSTA;
|
||||
r.heroic_dexterity = GetHeroicDEX() - GetSpellBonuses().HeroicDEX;
|
||||
r.heroic_agility = GetHeroicAGI() - GetSpellBonuses().HeroicAGI;
|
||||
r.heroic_intelligence = GetHeroicINT() - GetSpellBonuses().HeroicINT;
|
||||
r.heroic_wisdom = GetHeroicWIS() - GetSpellBonuses().HeroicWIS;
|
||||
r.heroic_charisma = GetHeroicCHA() - GetSpellBonuses().HeroicCHA;
|
||||
r.heroic_magic_resist = GetHeroicMR() - GetSpellBonuses().HeroicMR;
|
||||
r.heroic_fire_resist = GetHeroicFR() - GetSpellBonuses().HeroicFR;
|
||||
r.heroic_cold_resist = GetHeroicCR() - GetSpellBonuses().HeroicCR;
|
||||
r.heroic_poison_resist = GetHeroicPR() - GetSpellBonuses().HeroicPR;
|
||||
r.heroic_disease_resist = GetHeroicDR() - GetSpellBonuses().HeroicDR;
|
||||
r.heroic_corruption_resist = GetHeroicCorrup() - GetSpellBonuses().HeroicCorrup;
|
||||
r.haste = GetHaste();
|
||||
r.accuracy = GetAccuracy() - GetSpellBonuses().Accuracy[EQ::skills::HIGHEST_SKILL + 1];
|
||||
r.attack = GetTotalATK() - GetSpellBonuses().ATK;
|
||||
r.avoidance = GetAvoidance() - GetSpellBonuses().AvoidMeleeChance;
|
||||
r.clairvoyance = GetClair() - GetSpellBonuses().Clairvoyance;
|
||||
r.combat_effects = GetCombatEffects() - GetSpellBonuses().ProcChance;
|
||||
r.damage_shield_mitigation = GetDSMit() - GetSpellBonuses().DSMitigation;
|
||||
r.damage_shield = GetDS() - GetSpellBonuses().DamageShield;
|
||||
r.dot_shielding = GetDoTShield() - GetSpellBonuses().DoTShielding;
|
||||
r.hp_regen = GetHPRegen() - GetSpellBonuses().HPRegen;
|
||||
r.mana_regen = GetManaRegen() - GetSpellBonuses().ManaRegen;
|
||||
r.endurance_regen = GetEnduranceRegen() - GetSpellBonuses().EnduranceRegen;
|
||||
r.shielding = GetShielding() - GetSpellBonuses().MeleeMitigation;
|
||||
r.spell_damage = GetSpellDmg() - GetSpellBonuses().SpellDmg;
|
||||
r.spell_shielding = GetSpellShield() - GetSpellBonuses().SpellShield;
|
||||
r.strikethrough = GetStrikeThrough() - GetSpellBonuses().StrikeThrough;
|
||||
r.stun_resist = GetStunResist() - GetSpellBonuses().StunResist;
|
||||
r.backstab = 0;
|
||||
r.wind = GetWindMod();
|
||||
r.brass = GetBrassMod();
|
||||
r.string = GetStringMod();
|
||||
r.percussion = GetPercMod();
|
||||
r.singing = GetSingMod();
|
||||
r.baking = GetSkill(EQ::skills::SkillType::SkillBaking);
|
||||
r.alchemy = GetSkill(EQ::skills::SkillType::SkillAlchemy);
|
||||
r.jewelry = GetSkill(EQ::skills::SkillType::SkillJewelryMaking);
|
||||
r.tailoring = GetSkill(EQ::skills::SkillType::SkillTailoring);
|
||||
r.blacksmithing = GetSkill(EQ::skills::SkillType::SkillBlacksmithing);
|
||||
r.fletching = GetSkill(EQ::skills::SkillType::SkillFletching);
|
||||
r.brewing = GetSkill(EQ::skills::SkillType::SkillBrewing);
|
||||
r.fishing = GetSkill(EQ::skills::SkillType::SkillFishing);
|
||||
r.pottery = GetSkill(EQ::skills::SkillType::SkillPottery);
|
||||
r.alcohol = GetSkill(EQ::skills::SkillType::SkillAlcoholTolerance);
|
||||
r.tinkering = GetSkill(EQ::skills::SkillType::SkillTinkering);
|
||||
r.updated_at = std::time(nullptr);
|
||||
|
||||
if (r.character_id > 0) {
|
||||
CharacterStatsRecordRepository::UpdateOne(database, r);
|
||||
} else {
|
||||
r.character_id = CharacterID();
|
||||
r.created_at = std::time(nullptr);
|
||||
CharacterStatsRecordRepository::InsertOne(database, r);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::ReloadExpansionProfileSetting()
|
||||
{
|
||||
if (RuleB(World, UseClientBasedExpansionSettings)) {
|
||||
m_pp.expansions = EQ::expansions::ConvertClientVersionToExpansionsMask(ClientVersion());
|
||||
}
|
||||
else {
|
||||
m_pp.expansions = RuleI(World, ExpansionSettings);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
void Handle_OP_Bind_Wound(const EQApplicationPacket *app);
|
||||
void Handle_OP_BlockedBuffs(const EQApplicationPacket *app);
|
||||
void Handle_OP_BoardBoat(const EQApplicationPacket *app);
|
||||
void Handle_OP_BookButton(const EQApplicationPacket *app);
|
||||
void Handle_OP_Buff(const EQApplicationPacket *app);
|
||||
void Handle_OP_BuffRemoveRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_Bug(const EQApplicationPacket *app);
|
||||
@@ -241,7 +242,9 @@
|
||||
void Handle_OP_PVPLeaderBoardRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_QueryUCSServerStatus(const EQApplicationPacket *app);
|
||||
void Handle_OP_RaidCommand(const EQApplicationPacket *app);
|
||||
void Handle_OP_RandomReq(const EQApplicationPacket *app);
|
||||
void Handle_OP_RaidDelegateAbility(const EQApplicationPacket* app);
|
||||
void Handle_OP_RaidClearNPCMarks(const EQApplicationPacket* app);
|
||||
void Handle_OP_RandomReq(const EQApplicationPacket* app);
|
||||
void Handle_OP_ReadBook(const EQApplicationPacket *app);
|
||||
void Handle_OP_RecipeAutoCombine(const EQApplicationPacket *app);
|
||||
void Handle_OP_RecipeDetails(const EQApplicationPacket *app);
|
||||
|
||||
@@ -741,6 +741,8 @@ void Client::OnDisconnect(bool hard_disconnect) {
|
||||
parse->EventPlayer(EVENT_DISCONNECT, this, "", 0);
|
||||
}
|
||||
|
||||
RecordStats();
|
||||
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
@@ -853,18 +855,16 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
|
||||
auto bucket_name = ml.bucket_name;
|
||||
auto const& bucket_value = ml.bucket_value;
|
||||
if (!bucket_name.empty() && !bucket_value.empty()) {
|
||||
auto full_name = fmt::format(
|
||||
"{}-{}",
|
||||
GetBucketKey(),
|
||||
bucket_name
|
||||
);
|
||||
|
||||
auto const& player_value = DataBucket::CheckBucketKey(this, full_name);
|
||||
if (player_value.empty()) {
|
||||
DataBucketKey k = GetScopedBucketKeys();
|
||||
k.key = bucket_name;
|
||||
|
||||
auto b = DataBucket::GetData(k);
|
||||
if (b.value.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!zone->CompareDataBucket(ml.bucket_comparison, bucket_value, player_value)) {
|
||||
if (!zone->CompareDataBucket(ml.bucket_comparison, bucket_value, b.value)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
+96
-377
@@ -1,8 +1,8 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
#include <fmt/format.h>
|
||||
#include "../common/repositories/command_subsettings_repository.h"
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#define strcasecmp _stricmp
|
||||
@@ -40,16 +40,17 @@ extern FastMath g_Math;
|
||||
void CatchSignal(int sig_num);
|
||||
|
||||
|
||||
int command_count; // how many commands we have
|
||||
int command_count; // how many commands we have
|
||||
|
||||
// this is the pointer to the dispatch function, updated once
|
||||
// init has been performed to point at the real function
|
||||
int (*command_dispatch)(Client *, std::string, bool) = command_notavail;
|
||||
|
||||
std::map<std::string, CommandRecord *> commandlist;
|
||||
std::map<std::string, std::string> commandaliases;
|
||||
std::vector<CommandRecord *> command_delete_list;
|
||||
std::map<std::string, uint8> commands_map;
|
||||
std::map<std::string, CommandRecord *> commandlist;
|
||||
std::map<std::string, std::string> commandaliases;
|
||||
std::vector<CommandRecord *> command_delete_list;
|
||||
std::map<std::string, uint8> commands_map;
|
||||
std::vector<CommandSubsettingsRepository::CommandSubsettings> command_subsettings;
|
||||
|
||||
/*
|
||||
* command_notavail
|
||||
@@ -86,7 +87,6 @@ int command_init(void)
|
||||
if (
|
||||
command_add("acceptrules", "[acceptrules] - Accept the EQEmu Agreement", AccountStatus::Player, command_acceptrules) ||
|
||||
command_add("advnpcspawn", "[maketype|makegroup|addgroupentry|addgroupspawn][removegroupspawn|movespawn|editgroupbox|cleargroupbox]", AccountStatus::GMLeadAdmin, command_advnpcspawn) ||
|
||||
command_add("aggro", "[Distance] [-v] - Display aggro information for all mobs 'Distance' distance from your target. (-v is verbose Faction Information)", AccountStatus::QuestTroupe, command_aggro) ||
|
||||
command_add("aggrozone", "[aggro] - Aggro every mob in the zone with X aggro. Default is 0. Not recommend if you're not invulnerable.", AccountStatus::GMAdmin, command_aggrozone) ||
|
||||
command_add("ai", "[factionid/spellslist/con/guard/roambox/stop/start] - Modify AI on NPC target", AccountStatus::GMAdmin, command_ai) ||
|
||||
command_add("appearance", "[type] [value] - Send an appearance packet for you or your target", AccountStatus::GMLeadAdmin, command_appearance) ||
|
||||
@@ -95,21 +95,17 @@ int command_init(void)
|
||||
command_add("attack", "[Entity Name] - Make your NPC target attack an entity by name", AccountStatus::GMLeadAdmin, command_attack) ||
|
||||
command_add("augmentitem", "Force augments an item. Must have the augment item window open.", AccountStatus::GMImpossible, command_augmentitem) ||
|
||||
command_add("ban", "[Character Name] [Reason] - Ban by character name", AccountStatus::GMLeadAdmin, command_ban) ||
|
||||
command_add("bind", "Sets your targets bind spot to their current location", AccountStatus::GMMgmt, command_bind) ||
|
||||
command_add("bugs", "[Close|Delete|Review|Search|View] - Handles player bug reports", AccountStatus::QuestTroupe, command_bugs) ||
|
||||
command_add("bot", "Type \"#bot help\" or \"^help\" to the see the list of available commands for bots.", AccountStatus::Player, command_bot) ||
|
||||
command_add("camerashake", "[Duration (Milliseconds)] [Intensity (1-10)] - Shakes the camera on everyone's screen globally.", AccountStatus::QuestTroupe, command_camerashake) ||
|
||||
command_add("castspell", "[Spell ID] [Instant (0 = False, 1 = True, Default is 1 if Unused)] - Cast a spell", AccountStatus::Guide, command_castspell) ||
|
||||
command_add("chat", "[Channel ID] [Message] - Send a channel message to all zones", AccountStatus::GMMgmt, command_chat) ||
|
||||
command_add("checklos", "Check for line of sight to your target", AccountStatus::Guide, command_checklos) ||
|
||||
command_add("copycharacter", "[source_char_name] [dest_char_name] [dest_account_name] - Copies character to destination account", AccountStatus::GMImpossible, command_copycharacter) ||
|
||||
command_add("corpse", "Manipulate corpses, use with no arguments for help", AccountStatus::Guide, command_corpse) ||
|
||||
command_add("corpsefix", "Attempts to bring corpses from underneath the ground within close proximity of the player", AccountStatus::Player, command_corpsefix) ||
|
||||
command_add("countitem", "[Item ID] - Counts the specified Item ID in your or your target's inventory", AccountStatus::GMLeadAdmin, command_countitem) ||
|
||||
command_add("cvs", "Summary of client versions currently online.", AccountStatus::GMMgmt, command_cvs) ||
|
||||
command_add("damage", "[Amount] - Damage yourself or your target", AccountStatus::GMAdmin, command_damage) ||
|
||||
command_add("databuckets", "View|Delete [key] [limit]- View data buckets, limit 50 default or Delete databucket by key", AccountStatus::QuestTroupe, command_databuckets) ||
|
||||
command_add("date", "[Year] [Month] [Day] [Hour] [Minute] - Set EQ time (Hour and Minute are optional)", AccountStatus::EQSupport, command_date) ||
|
||||
command_add("dbspawn2", "[Spawngroup ID] [Respawn] [Variance] [Condition ID] [Condition Minimum] - Spawn an NPC from a predefined row in the spawn2 table, Respawn and Variance are in Seconds (condition is optional)", AccountStatus::GMAdmin, command_dbspawn2) ||
|
||||
command_add("delacct", "[Account ID|Account Name] - Delete an account by ID or Name", AccountStatus::GMLeadAdmin, command_delacct) ||
|
||||
command_add("delpetition", "[petition number] - Delete a petition", AccountStatus::ApprenticeGuide, command_delpetition) ||
|
||||
@@ -118,7 +114,6 @@ int command_init(void)
|
||||
command_add("devtools", "[Enable|Disable] - Manages Developer Tools (send no parameter for menu)", AccountStatus::GMMgmt, command_devtools) ||
|
||||
command_add("disablerecipe", "[Recipe ID] - Disables a Recipe", AccountStatus::QuestTroupe, command_disablerecipe) ||
|
||||
command_add("disarmtrap", "Analog for ldon disarm trap for the newer clients since we still don't have it working.", AccountStatus::QuestTroupe, command_disarmtrap) ||
|
||||
command_add("distance", "Reports the distance between you and your target.", AccountStatus::QuestTroupe, command_distance) ||
|
||||
command_add("door", "Door editing command", AccountStatus::QuestTroupe, command_door) ||
|
||||
command_add("doanim", "[Animation ID|Animation Name] [Speed] - Send an animation by ID or name at the specified speed to you or your target (Speed is optional)", AccountStatus::Guide, command_doanim) ||
|
||||
command_add("dye", "[slot|'help'] [red] [green] [blue] [use_tint] - Dyes the specified armor slot to Red, Green, and Blue provided, allows you to bypass darkness limits.", AccountStatus::ApprenticeGuide, command_dye) ||
|
||||
@@ -126,97 +121,50 @@ int command_init(void)
|
||||
command_add("dzkickplayers", "Removes all players from current expedition. (/kickplayers alternative for pre-RoF clients)", AccountStatus::Player, command_dzkickplayers) ||
|
||||
command_add("editmassrespawn", "[name-search] [second-value] - Mass (Zone wide) NPC respawn timer editing command", AccountStatus::GMAdmin, command_editmassrespawn) ||
|
||||
command_add("emote", "[Name|World|Zone] [type] [message] - Send an emote message by name, to the world, or to your zone (^ separator allows multiple messages to be sent at once)", AccountStatus::QuestTroupe, command_emote) ||
|
||||
command_add("emotesearch", "[Search Criteria] - Search for NPC Emotes", AccountStatus::QuestTroupe, command_emotesearch) ||
|
||||
command_add("emoteview", "Lists all NPC Emotes", AccountStatus::QuestTroupe, command_emoteview) ||
|
||||
command_add("emptyinventory", "Clears your or your target's entire inventory (Equipment, General, Bank, and Shared Bank)", AccountStatus::GMImpossible, command_emptyinventory) ||
|
||||
command_add("enablerecipe", "[Recipe ID] - Enables a Recipe", AccountStatus::QuestTroupe, command_enablerecipe) ||
|
||||
command_add("endurance", "Restores your or your target's endurance.", AccountStatus::Guide, command_endurance) ||
|
||||
command_add("entityvariable", "[clear|delete|set|view] - Modify entity variables for yourself or your target", AccountStatus::GMAdmin, command_entityvariable) ||
|
||||
command_add("exptoggle", "[Toggle] - Toggle your or your target's experience gain.", AccountStatus::QuestTroupe, command_exptoggle) ||
|
||||
command_add("faction", "[Find (criteria | all ) | Review (criteria | all) | Reset (id)] - Resets Player's Faction", AccountStatus::QuestTroupe, command_faction) ||
|
||||
command_add("factionassociation", "[factionid] [amount] - triggers a faction hits via association", AccountStatus::GMLeadAdmin, command_faction_association) ||
|
||||
command_add("feature", "Change your or your target's feature's temporarily", AccountStatus::QuestTroupe, command_feature) ||
|
||||
command_add("size", "Change your targets size (alias of #feature size)", AccountStatus::QuestTroupe, command_feature) ||
|
||||
command_add("findaa", "[Search Criteria] - Search for an AA", AccountStatus::Guide, command_findaa) ||
|
||||
command_add("findaliases", "[Search Criteria]- Searches for available command aliases, by alias or command", AccountStatus::Player, command_findaliases) ||
|
||||
command_add("findcharacter", "[Search Criteria] - Search for a character", AccountStatus::Guide, command_findcharacter) ||
|
||||
command_add("findclass", "[Search Criteria] - Search for a class", AccountStatus::Guide, command_findclass) ||
|
||||
command_add("findcurrency", "[Search Criteria] - Search for an alternate currency", AccountStatus::Guide, command_findcurrency) ||
|
||||
command_add("findfaction", "[Search Criteria] - Search for a faction", AccountStatus::Guide, command_findfaction) ||
|
||||
command_add("findnpctype", "[Search Criteria] - Search database NPC types", AccountStatus::GMAdmin, command_findnpctype) ||
|
||||
command_add("findrace", "[Search Criteria] - Search for a race", AccountStatus::Guide, command_findrace) ||
|
||||
command_add("findrecipe", "[Search Criteria] - Search for a recipe", AccountStatus::Guide, command_findrecipe) ||
|
||||
command_add("findskill", "[Search Criteria] - Search for a skill", AccountStatus::Guide, command_findskill) ||
|
||||
command_add("findspell", "[Search Criteria] - Search for a spell", AccountStatus::Guide, command_findspell) ||
|
||||
command_add("findtask", "[Search Criteria] - Search for a task", AccountStatus::Guide, command_findtask) ||
|
||||
command_add("findzone", "[Search Criteria] - Search database zones", AccountStatus::GMAdmin, command_findzone) ||
|
||||
command_add("find", "Search command used to find various things", AccountStatus::Guide, command_find) ||
|
||||
command_add("fixmob", "[race|gender|texture|helm|face|hair|haircolor|beard|beardcolor|heritage|tattoo|detail] [next|prev] - Manipulate appearance of your target", AccountStatus::QuestTroupe, command_fixmob) ||
|
||||
command_add("flag", "[Status] [Account Name] - Refresh your admin status, or set an account's Admin status if arguments provided", AccountStatus::Player, command_flag) ||
|
||||
command_add("flagedit", "Edit zone flags on your target. Use #flagedit help for more info.", AccountStatus::GMAdmin, command_flagedit) ||
|
||||
command_add("flags", "displays the Zone Flags of you or your target", AccountStatus::Player, command_flags) ||
|
||||
command_add("flymode", "[0/1/2/3/4/5] - Set your or your player target's flymode to ground/flying/levitate/water/floating/levitate_running", AccountStatus::Guide, command_flymode) ||
|
||||
command_add("fov", "Check wether you're behind or in your target's field of view", AccountStatus::QuestTroupe, command_fov) ||
|
||||
command_add("freeze", "Freeze your target", AccountStatus::QuestTroupe, command_freeze) ||
|
||||
command_add("gassign", "[Grid ID] - Assign targetted NPC to predefined wandering grid id", AccountStatus::GMAdmin, command_gassign) ||
|
||||
command_add("gearup", "Developer tool to quickly equip yourself or your target", AccountStatus::GMMgmt, command_gearup) ||
|
||||
command_add("gender", "[0/1/2] - Change your or your target's gender to male/female/neuter", AccountStatus::Guide, command_gender) ||
|
||||
command_add("getplayerburiedcorpsecount", "Get your or your target's total number of buried player corpses.", AccountStatus::GMAdmin, command_getplayerburiedcorpsecount) ||
|
||||
command_add("getvariable", "[Variable Name] - Get the value of a variable from the database", AccountStatus::GMMgmt, command_getvariable) ||
|
||||
command_add("ginfo", "get group info on target.", AccountStatus::ApprenticeGuide, command_ginfo) ||
|
||||
command_add("giveitem", "[itemid] [charges] - Summon an item onto your target's cursor. Charges are optional.", AccountStatus::GMMgmt, command_giveitem) ||
|
||||
command_add("givemoney", "[Platinum] [Gold] [Silver] [Copper] - Gives specified amount of money to you or your player target", AccountStatus::GMMgmt, command_givemoney) ||
|
||||
command_add("globalview", "Lists all qglobals in cache if you were to do a quest with this target.", AccountStatus::QuestTroupe, command_globalview) ||
|
||||
command_add("gm", "[On|Off] - Modify your or your target's GM Flag", AccountStatus::QuestTroupe, command_gm) ||
|
||||
command_add("gmspeed", "[On|Off] - Turn GM Speed On or Off for you or your player target", AccountStatus::GMAdmin, command_gmspeed) ||
|
||||
command_add("gmzone", "[Zone ID|Zone Short Name] [Version] [Instance Identifier] - Zones to a private GM instance (Version defaults to 0 and Instance Identifier defaults to 'gmzone' if not used)", AccountStatus::GMAdmin, command_gmzone) ||
|
||||
command_add("godmode", "[on/off] - Turns on/off hideme, gmspeed, invul, and flymode.", AccountStatus::GMMgmt, command_godmode) ||
|
||||
command_add("goto", "[playername] or [x y z] [h] - Teleport to the provided coordinates or to your target", AccountStatus::Steward, command_goto) ||
|
||||
command_add("grantaa", "Grants a player all available AA points for their level.", AccountStatus::GMMgmt, command_grantaa) ||
|
||||
command_add("grid", "[add/delete] [grid_num] [wandertype] [pausetype] - Create/delete a wandering grid", AccountStatus::GMAreas, command_grid) ||
|
||||
command_add("guild", "Guild manipulation commands. Use argument help for more info.", AccountStatus::Steward, command_guild) ||
|
||||
command_add("haste", "[Percentage] - Set your or your target's GM Bonus Haste (100 is 100% more Attack Speed)", AccountStatus::GMAdmin, command_haste) ||
|
||||
command_add("hatelist", "Display hate list for NPC.", AccountStatus::QuestTroupe, command_hatelist) ||
|
||||
command_add("heal", "Completely heal your target", AccountStatus::Steward, command_heal) ||
|
||||
command_add("help", "[Search Criteria] - List available commands and their description, specify partial command as argument to search", AccountStatus::Player, command_help) ||
|
||||
command_add("heromodel", "[Hero Model] [Slot] - Set your or your target's appearance to a full set of Hero's Forge Armor, if slot is set, sends exact model just to slot.", AccountStatus::GMMgmt, command_heromodel) ||
|
||||
command_add("hideme", "[On|Off] or [0|1] - Hide yourself from players below your status level.", AccountStatus::QuestTroupe, command_hideme) ||
|
||||
command_add("hotfix", "[hotfix_name] - Reloads shared memory into a hotfix, equiv to load_shared_memory followed by apply_shared_memory", AccountStatus::GMImpossible, command_hotfix) ||
|
||||
command_add("hp", "Refresh your HP bar from the server.", AccountStatus::Player, command_hp) ||
|
||||
command_add("incstat", "Increases or Decreases a client's stats permanently.", AccountStatus::GMMgmt, command_incstat) ||
|
||||
command_add("instance", "Modify Instances", AccountStatus::GMMgmt, command_instance) ||
|
||||
command_add("interrogateinv", "use [help] argument for available options", AccountStatus::Player, command_interrogateinv) ||
|
||||
command_add("interrupt", "[Message ID] [Color] - Interrupt your casting. Arguments are optional.", AccountStatus::Guide, command_interrupt) ||
|
||||
command_add("invsnapshot", "Manipulates inventory snapshots for your current target", AccountStatus::QuestTroupe, command_invsnapshot) ||
|
||||
command_add("invul", "[On|Off]] - Turn player target's or your invulnerable flag on or off", AccountStatus::QuestTroupe, command_invul) ||
|
||||
command_add("ipban", "[IP] - Ban IP", AccountStatus::GMMgmt, command_ipban) ||
|
||||
command_add("iplookup", "[charname] - Look up IP address of charname", AccountStatus::GMMgmt, command_iplookup) ||
|
||||
command_add("itemsearch", "[Search Criteria] - Search for an item", AccountStatus::Steward, command_itemsearch) ||
|
||||
command_add("kick", "[Character Name] - Disconnect a player by name", AccountStatus::GMLeadAdmin, command_kick) ||
|
||||
command_add("kill", "Kill your target", AccountStatus::GMAdmin, command_kill) ||
|
||||
command_add("killallnpcs", "[npc_name] - Kills all npcs by search name, leave blank for all attackable NPC's", AccountStatus::GMMgmt, command_killallnpcs) ||
|
||||
command_add("lastname", "[Last Name] - Set your or your player target's last name (use \"-1\" to remove last name)", AccountStatus::Guide, command_lastname) ||
|
||||
command_add("level", "[Level] - Set your or your target's level", AccountStatus::Steward, command_level) ||
|
||||
command_add("list", "[npcs|players|corpses|doors|objects] [search] - Search entities", AccountStatus::ApprenticeGuide, command_list) ||
|
||||
command_add("listpetition", "List petitions", AccountStatus::Guide, command_listpetition) ||
|
||||
command_add("lootsim", "[npc_type_id] [loottable_id] [iterations] - Runs benchmark simulations using real loot logic to report numbers and data", AccountStatus::GMImpossible, command_lootsim) ||
|
||||
command_add("load_shared_memory", "[shared_memory_name] - Reloads shared memory and uses the input as output", AccountStatus::GMImpossible, command_load_shared_memory) ||
|
||||
command_add("loc", "Print out your or your target's current location and heading", AccountStatus::Player, command_loc) ||
|
||||
command_add("logs", "Manage anything to do with logs", AccountStatus::GMImpossible, command_logs) ||
|
||||
command_add("makepet", "[Pet Name] - Make a pet", AccountStatus::Guide, command_makepet) ||
|
||||
command_add("mana", "Fill your or your target's mana", AccountStatus::Guide, command_mana) ||
|
||||
command_add("maxskills", "Maxes skills for you or your player target.", AccountStatus::GMMgmt, command_max_all_skills) ||
|
||||
command_add("memspell", "[Spell ID] [Spell Gem] - Memorize a Spell by ID to the specified Spell Gem for you or your target", AccountStatus::Guide, command_memspell) ||
|
||||
command_add("merchant_close_shop", "Closes a merchant shop", AccountStatus::GMAdmin, command_merchantcloseshop) ||
|
||||
command_add("merchant_open_shop", "Opens a merchants shop", AccountStatus::GMAdmin, command_merchantopenshop) ||
|
||||
command_add("merchantshop", "Closes or opens your target merchant's shop", AccountStatus::GMAdmin, command_merchantshop) ||
|
||||
command_add("modifynpcstat", "[Stat] [Value] - Modifies an NPC's stats temporarily.", AccountStatus::GMLeadAdmin, command_modifynpcstat) ||
|
||||
command_add("motd", "[Message of the Day] - Set Message of the Day (leave empty to have no Message of the Day)", AccountStatus::GMLeadAdmin, command_motd) ||
|
||||
command_add("movechar", "[Character ID|Character Name] [Zone ID|Zone Short Name] - Move an offline character to the specified zone", AccountStatus::Guide, command_movechar) ||
|
||||
command_add("movement", "Various movement commands", AccountStatus::GMMgmt, command_movement) ||
|
||||
command_add("myskills", "Show details about your current skill levels", AccountStatus::Player, command_myskills) ||
|
||||
command_add("mysql", "[Help|Query] [SQL Query] - Mysql CLI, see 'Help' for options.", AccountStatus::GMImpossible, command_mysql) ||
|
||||
command_add("mystats", "Show details about you or your pet", AccountStatus::Guide, command_mystats) ||
|
||||
command_add("name", "[New Name] - Rename your player target", AccountStatus::GMLeadAdmin, command_name) ||
|
||||
command_add("netstats", "Gets the network stats for a stream.", AccountStatus::GMMgmt, command_netstats) ||
|
||||
command_add("network", "Admin commands for the udp network interface.", AccountStatus::GMImpossible, command_network) ||
|
||||
command_add("npccast", "[targetname/entityid] [spellid] - Causes NPC target to cast spellid on targetname/entityid", AccountStatus::QuestTroupe, command_npccast) ||
|
||||
command_add("npcedit", "[column] [value] - Mega NPC editing command", AccountStatus::GMAdmin, command_npcedit) ||
|
||||
command_add("npceditmass", "[name-search] [column] [value] - Mass (Zone wide) NPC data editing command", AccountStatus::GMAdmin, command_npceditmass) ||
|
||||
@@ -225,31 +173,18 @@ int command_init(void)
|
||||
command_add("npcsay", "[Message] - Make your NPC target say a message.", AccountStatus::GMLeadAdmin, command_npcsay) ||
|
||||
command_add("npcshout", "[Message] - Make your NPC target shout a message.", AccountStatus::GMLeadAdmin, command_npcshout) ||
|
||||
command_add("npcspawn", "[create/add/update/remove/delete] - Manipulate spawn DB", AccountStatus::GMAreas, command_npcspawn) ||
|
||||
command_add("npcstats", "Show stats about target NPC", AccountStatus::QuestTroupe, command_npcstats) ||
|
||||
command_add("npctypespawn", "[NPC ID] [Faction ID] - Spawn an NPC by ID from the database with an option of setting its Faction ID", AccountStatus::Steward, command_npctypespawn) ||
|
||||
command_add("nudge", "Nudge your target's current position by specific values", AccountStatus::QuestTroupe, command_nudge) ||
|
||||
command_add("nukebuffs", "[Beneficial|Detrimental|Help] - Strip all buffs by type on you or your target (no argument to remove all buffs)", AccountStatus::Guide, command_nukebuffs) ||
|
||||
command_add("nukeitem", "[Item ID] - Removes the specified Item ID from you or your player target's inventory", AccountStatus::GMLeadAdmin, command_nukeitem) ||
|
||||
command_add("object", "List|Add|Edit|Move|Rotate|Copy|Save|Undo|Delete - Manipulate static and tradeskill objects within the zone", AccountStatus::GMAdmin, command_object) ||
|
||||
command_add("oocmute", "[0|1] - Enable or Disable Server OOC", AccountStatus::GMMgmt, command_oocmute) ||
|
||||
command_add("opcode", "Reloads all opcodes from server patch files", AccountStatus::GMMgmt, command_reload) ||
|
||||
command_add("path", "view and edit pathing", AccountStatus::GMMgmt, command_path) ||
|
||||
command_add("peekinv", "[equip/gen/cursor/poss/limbo/curlim/trib/bank/shbank/allbank/trade/world/all] - Print out contents of your player target's inventory", AccountStatus::GMAdmin, command_peekinv) ||
|
||||
command_add("peqzone", "[Zone ID|Zone Short Name] - Teleports you to the specified zone if you meet the requirements.", AccountStatus::Player, command_peqzone) ||
|
||||
command_add("peqzone_flags", "displays the PEQZone Flags of you or your target", AccountStatus::Player, command_peqzone_flags) ||
|
||||
command_add("permaclass", "[Class ID] - Change your or your player target's class, changed client is disconnected", AccountStatus::QuestTroupe, command_permaclass) ||
|
||||
command_add("permagender", "[Gender ID] - Change your or your player target's gender", AccountStatus::QuestTroupe, command_permagender) ||
|
||||
command_add("permarace", "[Race ID] - Change your or your player target's race", AccountStatus::QuestTroupe, command_permarace) ||
|
||||
command_add("petitems", "View your pet's items if you have one", AccountStatus::ApprenticeGuide, command_petitems) ||
|
||||
command_add("petitioninfo", "[petition number] - Get info about a petition", AccountStatus::ApprenticeGuide, command_petitioninfo) ||
|
||||
command_add("picklock", "Analog for ldon pick lock for the newer clients since we still don't have it working.", AccountStatus::Player, command_picklock) ||
|
||||
command_add("profanity", "Manage censored language.", AccountStatus::GMLeadAdmin, command_profanity) ||
|
||||
command_add("push", "[Back Push] [Up Push] - Lets you do spell push on an NPC", AccountStatus::GMLeadAdmin, command_push) ||
|
||||
command_add("proximity", "Shows NPC proximity", AccountStatus::GMLeadAdmin, command_proximity) ||
|
||||
command_add("pvp", "[On|Off] - Set you or your player target's PVP status", AccountStatus::GMAdmin, command_pvp) ||
|
||||
command_add("qglobal", "[On|Off|View] - Toggles quest global functionality for your NPC target", AccountStatus::GMAdmin, command_qglobal) ||
|
||||
command_add("questerrors", "Shows quest errors.", AccountStatus::GMAdmin, command_questerrors) ||
|
||||
command_add("race", "[racenum] - Change your or your target's race. Use racenum 0 to return to normal", AccountStatus::Guide, command_race) ||
|
||||
command_add("raidloot", "[All|GroupLeader|RaidLeader|Selected] - Sets your Raid Loot Type if you have permission to do so.", AccountStatus::Player, command_raidloot) ||
|
||||
command_add("randomfeatures", "Temporarily randomizes the Facial Features of your target", AccountStatus::QuestTroupe, command_randomfeatures) ||
|
||||
command_add("refreshgroup", "Refreshes Group for you or your player target.", AccountStatus::Player, command_refreshgroup) ||
|
||||
@@ -270,44 +205,12 @@ int command_init(void)
|
||||
command_add("scribespells", "[Max level] [Min level] - Scribe all spells for you or your player target that are usable by them, up to level specified. (may freeze client for a few seconds)", AccountStatus::GMLeadAdmin, command_scribespells) ||
|
||||
command_add("sendzonespawns", "Refresh spawn list for all clients in zone", AccountStatus::GMLeadAdmin, command_sendzonespawns) ||
|
||||
command_add("sensetrap", "Analog for ldon sense trap for the newer clients since we still don't have it working.", AccountStatus::Player, command_sensetrap) ||
|
||||
command_add("serverinfo", "Get CPU, Operating System, and Process Information about the server", AccountStatus::GMMgmt, command_serverinfo) ||
|
||||
command_add("serverlock", "[0|1] - Lock or Unlock the World Server (0 = Unlocked, 1 = Locked)", AccountStatus::GMLeadAdmin, command_serverlock) ||
|
||||
command_add("serverrules", "Read this server's rules", AccountStatus::Player, command_serverrules) ||
|
||||
command_add("setaapts", "[AA|Group|Raid] [AA Amount] - Set your or your player target's Available AA Points by Type", AccountStatus::GMAdmin, command_setaapts) ||
|
||||
command_add("setaaxp", "[AA|Group|Raid] [AA Experience] - Set your or your player target's AA Experience by Type", AccountStatus::GMAdmin, command_setaaxp) ||
|
||||
command_add("setadventurepoints", "[Theme] [Points] - Set your or your player target's available Adventure Points by Theme", AccountStatus::GMLeadAdmin, command_set_adventure_points) ||
|
||||
command_add("setaltcurrency", "[Currency ID] [Amount] - Set your or your target's available Alternate Currency by Currency ID", AccountStatus::GMAdmin, command_setaltcurrency) ||
|
||||
command_add("setanim", "[Animation ID (IDs are 0 to 4)] - Set target's appearance to Animation ID", AccountStatus::GMMgmt, command_setanim) ||
|
||||
command_add("setanon", "[Anonymous Flag] - Set you or your target's Anonymous Flag (0 = Not Anonymous, 1 = Anonymous, 2 = Roleplaying)", AccountStatus::QuestTroupe, command_setanon) ||
|
||||
command_add("setcrystals", "[value] - Set your or your player target's available radiant or ebon crystals", AccountStatus::GMAdmin, command_setcrystals) ||
|
||||
command_add("setendurance", "[Endurance] - Set your or your target's Endurance", AccountStatus::GMAdmin, command_setendurance) ||
|
||||
command_add("setfaction", "[Faction ID] - Sets targeted NPC's faction in the database", AccountStatus::GMAreas, command_setfaction) ||
|
||||
command_add("sethp", "[Health] - Set your or your target's Health", AccountStatus::GMAdmin, command_sethp) ||
|
||||
command_add("setlanguage", "[Language ID] [Value] - Set your or your target's Language by ID to Value", AccountStatus::Guide, command_setlanguage) ||
|
||||
command_add("setlsinfo", "[Email] [Password] - Set loginserver email address and password (if supported by loginserver)", AccountStatus::Steward, command_setlsinfo) ||
|
||||
command_add("setmana", "[Mana] - Set your or your target's Mana", AccountStatus::GMAdmin, command_setmana) ||
|
||||
command_add("setpass", "[Account Name] [Password] - Set local password by account name", AccountStatus::GMLeadAdmin, command_setpass) ||
|
||||
command_add("setpvppoints", "[Amount] - Set your or your player target's PVP points", AccountStatus::GMAdmin, command_setpvppoints) ||
|
||||
command_add("setskill", "[skillnum] [value] - Set your target's skill skillnum to value", AccountStatus::Guide, command_setskill) ||
|
||||
command_add("setskillall", "[Skill Level] - Set all of your or your target's skills to the specified skill level", AccountStatus::Guide, command_setskillall) ||
|
||||
command_add("setstartzone", "[Zone ID|Zone Short Name] - Sets your or your target's starting zone (Use '0' or 'Reset' to allow the player use of /setstartcity)", AccountStatus::QuestTroupe, command_setstartzone) ||
|
||||
command_add("setstat", "Sets the stats to a specific value.", AccountStatus::Max, command_setstat) ||
|
||||
command_add("setxp", "[value] - Set your or your player target's experience", AccountStatus::GMAdmin, command_setxp) ||
|
||||
command_add("showbonusstats", "[item|spell|all] Shows bonus stats for target from items or spells. Shows both by default.", AccountStatus::Guide, command_showbonusstats) ||
|
||||
command_add("showbuffs", "List buffs active on your target or you if no target", AccountStatus::Guide, command_showbuffs) ||
|
||||
command_add("shownumhits", "Shows buffs numhits for yourself.", AccountStatus::Player, command_shownumhits) ||
|
||||
command_add("shownpcgloballoot", "Show global loot entries for your target NPC", AccountStatus::Guide, command_shownpcgloballoot) ||
|
||||
command_add("showskills", "[Start Skill ID] [All] - Show the values of your or your player target's skills in a popup 50 at a time, use 'all' as second argument to show non-usable skill's values", AccountStatus::Guide, command_showskills) ||
|
||||
command_add("showspellslist", "Shows spell list of targeted NPC", AccountStatus::GMAdmin, command_showspellslist) ||
|
||||
command_add("showstats", "Show details about you or your target", AccountStatus::Guide, command_showstats) ||
|
||||
command_add("showzonegloballoot", "Show global loot entries for your current zone", AccountStatus::Guide, command_showzonegloballoot) ||
|
||||
command_add("showzonepoints", "Show zone points for current zone", AccountStatus::Guide, command_showzonepoints) ||
|
||||
command_add("set", "Set command used to set various things", AccountStatus::Guide, command_set) ||
|
||||
command_add("show", "Show command used to show various things", AccountStatus::Guide, command_show) ||
|
||||
command_add("shutdown", "Shut this zone process down", AccountStatus::GMLeadAdmin, command_shutdown) ||
|
||||
command_add("spawn", "[name] [race] [level] [material] [hp] [gender] [class] [priweapon] [secweapon] [merchantid] - Spawn an NPC", AccountStatus::Steward, command_spawn) ||
|
||||
command_add("spawneditmass", "[Search Criteria] [Edit Option] [Edit Value] [Apply] Mass editing spawn command (Apply is optional, 0 = False, 1 = True, default is False)", AccountStatus::GMLeadAdmin, command_spawneditmass) ||
|
||||
command_add("spawnfix", "Find targeted NPC in database based on its X/Y/heading and update the database to make it spawn at your current location/heading.", AccountStatus::GMAreas, command_spawnfix) ||
|
||||
command_add("spawnstatus", "[All|Disabled|Enabled|Spawn ID] - Show respawn timer status", AccountStatus::GMAdmin, command_spawnstatus) ||
|
||||
command_add("spellinfo", "[spellid] - Get detailed info about a spell", AccountStatus::Steward, command_spellinfo) ||
|
||||
command_add("stun", "[duration] - Stuns you or your target for duration", AccountStatus::GMAdmin, command_stun) ||
|
||||
command_add("summon", "[Character Name] - Summons your corpse, NPC, or player target, or by character name if specified", AccountStatus::QuestTroupe, command_summon) ||
|
||||
command_add("summonburiedplayercorpse", "Summons the target's oldest buried corpse, if any exist.", AccountStatus::GMAdmin, command_summonburiedplayercorpse) ||
|
||||
@@ -315,57 +218,27 @@ int command_init(void)
|
||||
command_add("suspend", "[name] [days] [reason] - Suspend by character name and for specificed number of days", AccountStatus::GMLeadAdmin, command_suspend) ||
|
||||
command_add("suspendmulti", "[Character Name One|Character Name Two|etc] [Days] [Reason] - Suspend multiple characters by name for specified number of days", AccountStatus::GMLeadAdmin, command_suspendmulti) ||
|
||||
command_add("task", "(subcommand) - Task system commands", AccountStatus::GMLeadAdmin, command_task) ||
|
||||
command_add("tempname", "[newname] - Temporarily renames your target. Leave name blank to restore the original name.", AccountStatus::GMAdmin, command_tempname) ||
|
||||
command_add("petname", "[newname] - Temporarily renames your pet. Leave name blank to restore the original name.", AccountStatus::GMAdmin, command_petname) ||
|
||||
command_add("texture", "[Texture] [Helmet Texture] - Change your or your target's texture (Helmet Texture defaults to 0 if not used)", AccountStatus::Steward, command_texture) ||
|
||||
command_add("time", "[Hour] [Minute] - Set world time to specified time", AccountStatus::EQSupport, command_time) ||
|
||||
command_add("timers", "Display persistent timers for target", AccountStatus::GMMgmt, command_timers) ||
|
||||
command_add("timezone", "[Hour] [Minutes] - Set timezone (Minutes are optional)", AccountStatus::EQSupport, command_timezone) ||
|
||||
command_add("title", "[Title] - Set your or your player target's title (use \"-1\" to remove title)", AccountStatus::Guide, command_title) ||
|
||||
command_add("titlesuffix", "[Title Suffix] - Set your or your player target's title suffix (use \"-1\" to remove title suffix)", AccountStatus::Guide, command_titlesuffix) ||
|
||||
command_add("traindisc", "[level] - Trains all the disciplines usable by the target, up to level specified. (may freeze client for a few seconds)", AccountStatus::GMLeadAdmin, command_traindisc) ||
|
||||
command_add("trapinfo", "Gets infomation about the traps currently spawned in the zone.", AccountStatus::QuestTroupe, command_trapinfo) ||
|
||||
command_add("tune", "Calculate statistical values related to combat.", AccountStatus::GMAdmin, command_tune) ||
|
||||
command_add("undye", "Remove dye from all of your or your target's armor slots", AccountStatus::GMAdmin, command_undye) ||
|
||||
command_add("unfreeze", "Unfreeze your target", AccountStatus::QuestTroupe, command_unfreeze) ||
|
||||
command_add("unmemspell", "[Spell ID] - Unmemorize a Spell by ID for you or your target", AccountStatus::Guide, command_unmemspell) ||
|
||||
command_add("unmemspells", " Unmemorize all spells for you or your target", AccountStatus::Guide, command_unmemspells) ||
|
||||
command_add("unscribespell", "[Spell ID] - Unscribe a spell from your or your target's spell book by Spell ID", AccountStatus::GMCoder, command_unscribespell) ||
|
||||
command_add("unscribespells", "Clear out your or your player target's spell book.", AccountStatus::GMCoder, command_unscribespells) ||
|
||||
command_add("untraindisc", "[Spell ID] - Untrain your or your target's discipline by Spell ID", AccountStatus::GMCoder, command_untraindisc) ||
|
||||
command_add("untraindiscs", "Untrains all disciplines from your target.", AccountStatus::GMCoder, command_untraindiscs) ||
|
||||
command_add("updatechecksum", "update client checksum", AccountStatus::GMImpossible, command_updatechecksum) ||
|
||||
command_add("uptime", "[zone server id] - Get uptime of worldserver, or zone server if argument provided", AccountStatus::Steward, command_uptime) ||
|
||||
command_add("version", "Display current version of EQEmu server", AccountStatus::Player, command_version) ||
|
||||
command_add("viewcurrencies", "View your or your target's currencies", AccountStatus::GMAdmin, command_viewcurrencies) ||
|
||||
command_add("viewnpctype", "[NPC ID] - Show stats for an NPC by NPC ID", AccountStatus::GMAdmin, command_viewnpctype) ||
|
||||
command_add("viewpetition", "[petition number] - View a petition", AccountStatus::ApprenticeGuide, command_viewpetition) ||
|
||||
command_add("viewrecipe", "[Recipe ID] - Show a recipe's entries", AccountStatus::GMAdmin, command_viewrecipe) ||
|
||||
command_add("viewzoneloot", "[item id] - Allows you to search a zone's loot for a specific item ID. (0 shows all loot in the zone)", AccountStatus::QuestTroupe, command_viewzoneloot) ||
|
||||
command_add("wc", "[Slot ID] [Material] [Hero Forge Model] [Elite Material] - Sets the specified slot for you or your target to a material, Hero Forge Model and Elite Material are optional", AccountStatus::GMMgmt, command_wc) ||
|
||||
command_add("weather", "[0/1/2/3] (Off/Rain/Snow/Manual) - Change the weather", AccountStatus::QuestTroupe, command_weather) ||
|
||||
command_add("who", "[search]", AccountStatus::ApprenticeGuide, command_who) ||
|
||||
command_add("worldshutdown", "Shut down world and all zones", AccountStatus::GMMgmt, command_worldshutdown) ||
|
||||
command_add("wp", "[add|delete] [grid_id] [pause] [waypoint_id] [-h] - Add or delete a waypoint by grid ID. (-h to use current heading)", AccountStatus::GMAreas, command_wp) ||
|
||||
command_add("wpadd", "[pause] [-h] - Add your current location as a waypoint to your NPC target's AI path. (-h to use current heading)", AccountStatus::GMAreas, command_wpadd) ||
|
||||
command_add("wpinfo", "Show waypoint info about your NPC target", AccountStatus::GMAreas, command_wpinfo) ||
|
||||
command_add("worldwide", "Performs world-wide GM functions such as cast (can be extended for other commands). Use caution", AccountStatus::GMImpossible, command_worldwide) ||
|
||||
command_add("xtargets", "[New Max XTargets] - Show your or your target's XTargets and optionally set max XTargets.", AccountStatus::GMImpossible, command_xtargets) ||
|
||||
command_add("zclip", "[Minimum Clip] [Maximum Clip] [Fog Minimum Clip] [Fog Maximum Clip] [Permanent (0 = False, 1 = True)] - Change zone clipping", AccountStatus::QuestTroupe, command_zclip) ||
|
||||
command_add("zcolor", "[Red] [Green] [Blue] [Permanent (0 = False, 1 = True)] - Change sky color", AccountStatus::QuestTroupe, command_zcolor) ||
|
||||
command_add("zheader", "[Zone ID|Zone Short Name] [Version] - Load a zone header from the database", AccountStatus::QuestTroupe, command_zheader) ||
|
||||
command_add("zone", "[Zone ID|Zone Short Name] [X] [Y] [Z] - Teleport to specified Zone by ID or Short Name (coordinates are optional)", AccountStatus::Guide, command_zone) ||
|
||||
command_add("zonebootup", "[ZoneServerID] [shortname] - Make a zone server boot a specific zone", AccountStatus::GMLeadAdmin, command_zonebootup) ||
|
||||
command_add("zoneinstance", "[Instance ID] [X] [Y] [Z] - Teleport to specified Instance by ID (coordinates are optional)", AccountStatus::Guide, command_zone_instance) ||
|
||||
command_add("zonelock", "[List|Lock|Unlock] [Zone ID|Zone Short Name] - Set or get lock status of a Zone by ID or Short Name", AccountStatus::GMAdmin, command_zonelock) ||
|
||||
command_add("zoneshutdown", "[shortname] - Shut down a zone server", AccountStatus::GMLeadAdmin, command_zoneshutdown) ||
|
||||
command_add("zonestatus", "Show connected zoneservers, synonymous with /servers", AccountStatus::GMLeadAdmin, command_zonestatus) ||
|
||||
command_add("zopp", "Troubleshooting command - Sends a fake item packet to you. No server reference is created.", AccountStatus::GMImpossible, command_zopp) ||
|
||||
command_add("zsafecoords", "[X] [Y] [Z] [Heading] [Permanent (0 = False, 1 = True)] - Set the current zone's safe coordinates", AccountStatus::QuestTroupe, command_zsafecoords) ||
|
||||
command_add("zsave", " Saves zheader to the database", AccountStatus::QuestTroupe, command_zsave) ||
|
||||
command_add("zsky", "[Sky Type] [Permanent (0 = False, 1 = True)] - Change zone sky type", AccountStatus::QuestTroupe, command_zsky) ||
|
||||
command_add("zstats", "Show info about zone header", AccountStatus::QuestTroupe, command_zstats) ||
|
||||
command_add("zunderworld", "[Z] [Permanent (0 = False, 1 = True)] - Change zone underworld Z", AccountStatus::QuestTroupe, command_zunderworld)
|
||||
command_add("zsave", " Saves zheader to the database", AccountStatus::QuestTroupe, command_zsave)
|
||||
) {
|
||||
command_deinit();
|
||||
return -1;
|
||||
@@ -373,22 +246,35 @@ int command_init(void)
|
||||
|
||||
std::map<std::string, std::pair<uint8, std::vector<std::string>>> command_settings;
|
||||
database.GetCommandSettings(command_settings);
|
||||
database.GetCommandSubSettings(command_subsettings);
|
||||
|
||||
std::vector<std::pair<std::string, uint8>> injected_command_settings;
|
||||
std::vector<std::string> orphaned_command_settings;
|
||||
|
||||
// inject static sub command aliases
|
||||
// .e.g old #fi routes to #find item or #itemsearch routes to #find item
|
||||
for (auto& cs : command_settings) {
|
||||
for (const auto& e : command_subsettings) {
|
||||
if (cs.first == e.parent_command) {
|
||||
for (const auto& alias : Strings::Split(e.top_level_aliases, "|")) {
|
||||
cs.second.second.emplace_back(alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& cs : command_settings) {
|
||||
auto cl = commandlist.find(cs.first);
|
||||
if (cl == commandlist.end()) {
|
||||
orphaned_command_settings.push_back(cs.first);
|
||||
LogInfo(
|
||||
"Command [{}] no longer exists... Deleting orphaned entry from `command_settings` table...",
|
||||
"Command [{}] no longer exists. Deleting orphaned entry from `command_settings` table.",
|
||||
cs.first
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (orphaned_command_settings.size()) {
|
||||
if (!orphaned_command_settings.empty()) {
|
||||
if (!database.UpdateOrphanedCommandSettings(orphaned_command_settings)) {
|
||||
LogInfo("Failed to process 'Orphaned Commands' update operation.");
|
||||
}
|
||||
@@ -398,16 +284,16 @@ int command_init(void)
|
||||
for (const auto& w : working_cl) {
|
||||
auto cs = command_settings.find(w.first);
|
||||
if (cs == command_settings.end()) {
|
||||
injected_command_settings.emplace_back(std::pair<std::string, uint8>(w.first, w.second->admin));
|
||||
injected_command_settings.emplace_back(w.first, w.second->admin);
|
||||
LogInfo(
|
||||
"New Command [{}] found... Adding to `command_settings` table with admin [{}]...",
|
||||
"New Command [{}] found. Adding to `command_settings` table with admin status [{}]",
|
||||
w.first,
|
||||
w.second->admin
|
||||
);
|
||||
|
||||
if (w.second->admin == AccountStatus::Player) {
|
||||
LogCommands(
|
||||
"command_init(): Warning: Command [{}] defaulting to admin level 0!",
|
||||
"Warning: Command [{}] defaulting to admin level 0!",
|
||||
w.first
|
||||
);
|
||||
}
|
||||
@@ -416,8 +302,9 @@ int command_init(void)
|
||||
}
|
||||
|
||||
w.second->admin = cs->second.first;
|
||||
|
||||
LogCommands(
|
||||
"command_init(): - Command [{}] set to admin level [{}]",
|
||||
"Command [{}] set to admin level [{}]",
|
||||
w.first,
|
||||
cs->second.first
|
||||
);
|
||||
@@ -440,7 +327,7 @@ int command_init(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
commandlist[a] = w.second;
|
||||
commandlist[a] = w.second;
|
||||
commandaliases[a] = w.first;
|
||||
|
||||
LogCommands(
|
||||
@@ -451,7 +338,7 @@ int command_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (injected_command_settings.size()) {
|
||||
if (!injected_command_settings.empty()) {
|
||||
if (!database.UpdateInjectedCommandSettings(injected_command_settings)) {
|
||||
LogInfo("Failed to process 'Injected Commands' update operation.");
|
||||
}
|
||||
@@ -462,6 +349,7 @@ int command_init(void)
|
||||
return command_count;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* command_deinit
|
||||
* clears the command list, freeing resources
|
||||
@@ -513,23 +401,24 @@ int command_add(std::string command_name, std::string description, uint8 admin,
|
||||
}
|
||||
|
||||
auto c = new CommandRecord;
|
||||
c->admin = admin;
|
||||
|
||||
c->admin = admin;
|
||||
c->description = description;
|
||||
c->function = function;
|
||||
c->function = function;
|
||||
|
||||
commands_map[command_name] = admin;
|
||||
|
||||
commandlist[command_name] = c;
|
||||
commands_map[command_name] = admin;
|
||||
commandlist[command_name] = c;
|
||||
commandaliases[command_name] = command_name;
|
||||
|
||||
command_delete_list.push_back(c);
|
||||
command_count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8 GetCommandStatus(Client *c, std::string command_name) {
|
||||
auto command_status = commands_map[command_name];
|
||||
return command_status;
|
||||
uint8 GetCommandStatus(std::string command_name)
|
||||
{
|
||||
return commands_map[command_name];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -555,9 +444,46 @@ int command_realdispatch(Client *c, std::string message, bool ignore_status)
|
||||
}
|
||||
|
||||
auto cur = commandlist[cstr];
|
||||
if (!ignore_status && c->Admin() < cur->admin) {
|
||||
c->Message(Chat::White, "Your status is not high enough to use this command.");
|
||||
return -1;
|
||||
|
||||
bool is_subcommand = false;
|
||||
bool can_use_subcommand = false;
|
||||
bool found_subcommand_setting = false;
|
||||
|
||||
const auto arguments = sep.argnum;
|
||||
|
||||
if (arguments >= 2) {
|
||||
const std::string& sub_command = sep.arg[1];
|
||||
|
||||
for (const auto &e : command_subsettings) {
|
||||
if (e.sub_command == sub_command) {
|
||||
can_use_subcommand = c->Admin() >= static_cast<int16>(e.access_level);
|
||||
is_subcommand = true;
|
||||
found_subcommand_setting = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_subcommand_setting) {
|
||||
for (const auto &e: command_subsettings) {
|
||||
if (e.sub_command == sub_command) {
|
||||
can_use_subcommand = c->Admin() >= static_cast<int16>(e.access_level);
|
||||
is_subcommand = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ignore_status) {
|
||||
if (!is_subcommand && c->Admin() < cur->admin) {
|
||||
c->Message(Chat::White, "Your status is not high enough to use this command.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (is_subcommand && !can_use_subcommand) {
|
||||
c->Message(Chat::White, "Your status is not high enough to use this subcommand.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* QS: Player_Log_Issued_Commands */
|
||||
@@ -612,7 +538,10 @@ void command_help(Client *c, const Seperator *sep)
|
||||
|
||||
for (const auto& cur : commandlist) {
|
||||
if (!search_criteria.empty()) {
|
||||
if (!Strings::Contains(cur.first, search_criteria) && !Strings::Contains(cur.second->description, search_criteria)) {
|
||||
if (
|
||||
!Strings::Contains(cur.first, search_criteria) &&
|
||||
!Strings::Contains(cur.second->description, search_criteria)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -632,10 +561,9 @@ void command_help(Client *c, const Seperator *sep)
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} | Status: {} | {}",
|
||||
"{} | {}",
|
||||
command_link,
|
||||
cur.second->admin,
|
||||
!cur.second->description.empty() ? cur.second->description : ""
|
||||
cur.second->description
|
||||
).c_str()
|
||||
);
|
||||
|
||||
@@ -667,88 +595,6 @@ void command_help(Client *c, const Seperator *sep)
|
||||
);
|
||||
}
|
||||
|
||||
void command_findaliases(Client *c, const Seperator *sep)
|
||||
{
|
||||
int arguments = sep->argnum;
|
||||
if (!arguments) {
|
||||
c->Message(Chat::White, "Usage: #findaliases [Search Critera]");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string search_criteria = Strings::ToLower(sep->argplus[1]);
|
||||
|
||||
auto find_iter = commandaliases.find(search_criteria);
|
||||
if (find_iter == commandaliases.end()) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"No commands or aliases found matching '{}'.",
|
||||
search_criteria
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
auto command_iter = commandlist.find(find_iter->second);
|
||||
if (
|
||||
find_iter->second.empty() ||
|
||||
command_iter == commandlist.end()
|
||||
) {
|
||||
c->Message(Chat::White, "An unknown condition occurred.");
|
||||
return;
|
||||
}
|
||||
|
||||
auto current_commmand_link = Saylink::Silent(
|
||||
fmt::format(
|
||||
"{}{}",
|
||||
COMMAND_CHAR,
|
||||
command_iter->first
|
||||
)
|
||||
);
|
||||
|
||||
int alias_count = 0;
|
||||
int alias_number = 1;
|
||||
std::string alias_link;
|
||||
for (const auto& a : commandaliases) {
|
||||
if (
|
||||
find_iter->second != a.second ||
|
||||
c->Admin() < command_iter->second->admin
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
alias_link = Saylink::Silent(
|
||||
fmt::format(
|
||||
"{}{}",
|
||||
COMMAND_CHAR,
|
||||
a.first
|
||||
)
|
||||
);
|
||||
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Alias {} | {}",
|
||||
alias_number,
|
||||
alias_link
|
||||
).c_str()
|
||||
);
|
||||
|
||||
alias_count++;
|
||||
alias_number++;
|
||||
}
|
||||
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} Alias{} listed for {}.",
|
||||
alias_count,
|
||||
alias_count != 1 ? "es" : "",
|
||||
current_commmand_link
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
void command_hotfix(Client *c, const Seperator *sep)
|
||||
{
|
||||
auto items_count = database.GetItemsCount();
|
||||
@@ -934,7 +780,6 @@ void command_bot(Client *c, const Seperator *sep)
|
||||
|
||||
#include "gm_commands/acceptrules.cpp"
|
||||
#include "gm_commands/advnpcspawn.cpp"
|
||||
#include "gm_commands/aggro.cpp"
|
||||
#include "gm_commands/aggrozone.cpp"
|
||||
#include "gm_commands/ai.cpp"
|
||||
#include "gm_commands/appearance.cpp"
|
||||
@@ -942,20 +787,16 @@ void command_bot(Client *c, const Seperator *sep)
|
||||
#include "gm_commands/attack.cpp"
|
||||
#include "gm_commands/augmentitem.cpp"
|
||||
#include "gm_commands/ban.cpp"
|
||||
#include "gm_commands/bind.cpp"
|
||||
#include "gm_commands/bugs.cpp"
|
||||
#include "gm_commands/camerashake.cpp"
|
||||
#include "gm_commands/castspell.cpp"
|
||||
#include "gm_commands/chat.cpp"
|
||||
#include "gm_commands/checklos.cpp"
|
||||
#include "gm_commands/copycharacter.cpp"
|
||||
#include "gm_commands/corpse.cpp"
|
||||
#include "gm_commands/corpsefix.cpp"
|
||||
#include "gm_commands/countitem.cpp"
|
||||
#include "gm_commands/cvs.cpp"
|
||||
#include "gm_commands/damage.cpp"
|
||||
#include "gm_commands/databuckets.cpp"
|
||||
#include "gm_commands/date.cpp"
|
||||
#include "gm_commands/dbspawn2.cpp"
|
||||
#include "gm_commands/delacct.cpp"
|
||||
#include "gm_commands/delpetition.cpp"
|
||||
@@ -964,7 +805,6 @@ void command_bot(Client *c, const Seperator *sep)
|
||||
#include "gm_commands/devtools.cpp"
|
||||
#include "gm_commands/disablerecipe.cpp"
|
||||
#include "gm_commands/disarmtrap.cpp"
|
||||
#include "gm_commands/distance.cpp"
|
||||
#include "gm_commands/doanim.cpp"
|
||||
#include "gm_commands/door.cpp"
|
||||
#include "gm_commands/door_manipulation.cpp"
|
||||
@@ -973,91 +813,45 @@ void command_bot(Client *c, const Seperator *sep)
|
||||
#include "gm_commands/dzkickplayers.cpp"
|
||||
#include "gm_commands/editmassrespawn.cpp"
|
||||
#include "gm_commands/emote.cpp"
|
||||
#include "gm_commands/emotesearch.cpp"
|
||||
#include "gm_commands/emoteview.cpp"
|
||||
#include "gm_commands/emptyinventory.cpp"
|
||||
#include "gm_commands/enablerecipe.cpp"
|
||||
#include "gm_commands/endurance.cpp"
|
||||
#include "gm_commands/entityvariable.cpp"
|
||||
#include "gm_commands/exptoggle.cpp"
|
||||
#include "gm_commands/faction.cpp"
|
||||
#include "gm_commands/feature.cpp"
|
||||
#include "gm_commands/findaa.cpp"
|
||||
#include "gm_commands/findcharacter.cpp"
|
||||
#include "gm_commands/findclass.cpp"
|
||||
#include "gm_commands/findcurrency.cpp"
|
||||
#include "gm_commands/findfaction.cpp"
|
||||
#include "gm_commands/findnpctype.cpp"
|
||||
#include "gm_commands/findrace.cpp"
|
||||
#include "gm_commands/findrecipe.cpp"
|
||||
#include "gm_commands/findskill.cpp"
|
||||
#include "gm_commands/findspell.cpp"
|
||||
#include "gm_commands/findtask.cpp"
|
||||
#include "gm_commands/findzone.cpp"
|
||||
#include "gm_commands/find.cpp"
|
||||
#include "gm_commands/fixmob.cpp"
|
||||
#include "gm_commands/flag.cpp"
|
||||
#include "gm_commands/flagedit.cpp"
|
||||
#include "gm_commands/flags.cpp"
|
||||
#include "gm_commands/flymode.cpp"
|
||||
#include "gm_commands/fov.cpp"
|
||||
#include "gm_commands/freeze.cpp"
|
||||
#include "gm_commands/gassign.cpp"
|
||||
#include "gm_commands/gearup.cpp"
|
||||
#include "gm_commands/gender.cpp"
|
||||
#include "gm_commands/getplayerburiedcorpsecount.cpp"
|
||||
#include "gm_commands/getvariable.cpp"
|
||||
#include "gm_commands/ginfo.cpp"
|
||||
#include "gm_commands/giveitem.cpp"
|
||||
#include "gm_commands/givemoney.cpp"
|
||||
#include "gm_commands/globalview.cpp"
|
||||
#include "gm_commands/gm.cpp"
|
||||
#include "gm_commands/gmspeed.cpp"
|
||||
#include "gm_commands/gmzone.cpp"
|
||||
#include "gm_commands/godmode.cpp"
|
||||
#include "gm_commands/goto.cpp"
|
||||
#include "gm_commands/grantaa.cpp"
|
||||
#include "gm_commands/grid.cpp"
|
||||
#include "gm_commands/guild.cpp"
|
||||
#include "gm_commands/haste.cpp"
|
||||
#include "gm_commands/hatelist.cpp"
|
||||
#include "gm_commands/heal.cpp"
|
||||
#include "gm_commands/heromodel.cpp"
|
||||
#include "gm_commands/hideme.cpp"
|
||||
#include "gm_commands/hp.cpp"
|
||||
#include "gm_commands/incstat.cpp"
|
||||
#include "gm_commands/instance.cpp"
|
||||
#include "gm_commands/interrogateinv.cpp"
|
||||
#include "gm_commands/interrupt.cpp"
|
||||
#include "gm_commands/invsnapshot.cpp"
|
||||
#include "gm_commands/invul.cpp"
|
||||
#include "gm_commands/ipban.cpp"
|
||||
#include "gm_commands/iplookup.cpp"
|
||||
#include "gm_commands/itemsearch.cpp"
|
||||
#include "gm_commands/kick.cpp"
|
||||
#include "gm_commands/kill.cpp"
|
||||
#include "gm_commands/killallnpcs.cpp"
|
||||
#include "gm_commands/lastname.cpp"
|
||||
#include "gm_commands/level.cpp"
|
||||
#include "gm_commands/list.cpp"
|
||||
#include "gm_commands/listpetition.cpp"
|
||||
#include "gm_commands/lootsim.cpp"
|
||||
#include "gm_commands/loc.cpp"
|
||||
#include "gm_commands/logs.cpp"
|
||||
#include "gm_commands/makepet.cpp"
|
||||
#include "gm_commands/mana.cpp"
|
||||
#include "gm_commands/max_all_skills.cpp"
|
||||
#include "gm_commands/memspell.cpp"
|
||||
#include "gm_commands/merchantcloseshop.cpp"
|
||||
#include "gm_commands/merchantopenshop.cpp"
|
||||
#include "gm_commands/merchantshop.cpp"
|
||||
#include "gm_commands/modifynpcstat.cpp"
|
||||
#include "gm_commands/motd.cpp"
|
||||
#include "gm_commands/movechar.cpp"
|
||||
#include "gm_commands/movement.cpp"
|
||||
#include "gm_commands/myskills.cpp"
|
||||
#include "gm_commands/mysql.cpp"
|
||||
#include "gm_commands/mystats.cpp"
|
||||
#include "gm_commands/name.cpp"
|
||||
#include "gm_commands/netstats.cpp"
|
||||
#include "gm_commands/network.cpp"
|
||||
#include "gm_commands/npccast.cpp"
|
||||
#include "gm_commands/npcedit.cpp"
|
||||
#include "gm_commands/npceditmass.cpp"
|
||||
@@ -1066,31 +860,18 @@ void command_bot(Client *c, const Seperator *sep)
|
||||
#include "gm_commands/npcsay.cpp"
|
||||
#include "gm_commands/npcshout.cpp"
|
||||
#include "gm_commands/npcspawn.cpp"
|
||||
#include "gm_commands/npcstats.cpp"
|
||||
#include "gm_commands/npctypespawn.cpp"
|
||||
#include "gm_commands/nudge.cpp"
|
||||
#include "gm_commands/nukebuffs.cpp"
|
||||
#include "gm_commands/nukeitem.cpp"
|
||||
#include "gm_commands/object.cpp"
|
||||
#include "gm_commands/oocmute.cpp"
|
||||
#include "gm_commands/path.cpp"
|
||||
#include "gm_commands/peekinv.cpp"
|
||||
#include "gm_commands/peqzone.cpp"
|
||||
#include "gm_commands/peqzone_flags.cpp"
|
||||
#include "gm_commands/permaclass.cpp"
|
||||
#include "gm_commands/permagender.cpp"
|
||||
#include "gm_commands/permarace.cpp"
|
||||
#include "gm_commands/petitems.cpp"
|
||||
#include "gm_commands/petitioninfo.cpp"
|
||||
#include "gm_commands/petname.cpp"
|
||||
#include "gm_commands/picklock.cpp"
|
||||
#include "gm_commands/profanity.cpp"
|
||||
#include "gm_commands/proximity.cpp"
|
||||
#include "gm_commands/push.cpp"
|
||||
#include "gm_commands/pvp.cpp"
|
||||
#include "gm_commands/qglobal.cpp"
|
||||
#include "gm_commands/questerrors.cpp"
|
||||
#include "gm_commands/race.cpp"
|
||||
#include "gm_commands/raidloot.cpp"
|
||||
#include "gm_commands/randomfeatures.cpp"
|
||||
#include "gm_commands/refreshgroup.cpp"
|
||||
@@ -1109,44 +890,12 @@ void command_bot(Client *c, const Seperator *sep)
|
||||
#include "gm_commands/scribespells.cpp"
|
||||
#include "gm_commands/sendzonespawns.cpp"
|
||||
#include "gm_commands/sensetrap.cpp"
|
||||
#include "gm_commands/serverinfo.cpp"
|
||||
#include "gm_commands/serverlock.cpp"
|
||||
#include "gm_commands/serverrules.cpp"
|
||||
#include "gm_commands/set_adventure_points.cpp"
|
||||
#include "gm_commands/setaapts.cpp"
|
||||
#include "gm_commands/setaaxp.cpp"
|
||||
#include "gm_commands/setaltcurrency.cpp"
|
||||
#include "gm_commands/setanim.cpp"
|
||||
#include "gm_commands/setanon.cpp"
|
||||
#include "gm_commands/setcrystals.cpp"
|
||||
#include "gm_commands/setendurance.cpp"
|
||||
#include "gm_commands/setfaction.cpp"
|
||||
#include "gm_commands/sethp.cpp"
|
||||
#include "gm_commands/setlanguage.cpp"
|
||||
#include "gm_commands/setlsinfo.cpp"
|
||||
#include "gm_commands/setmana.cpp"
|
||||
#include "gm_commands/setpass.cpp"
|
||||
#include "gm_commands/setpvppoints.cpp"
|
||||
#include "gm_commands/setskill.cpp"
|
||||
#include "gm_commands/setskillall.cpp"
|
||||
#include "gm_commands/setstartzone.cpp"
|
||||
#include "gm_commands/setstat.cpp"
|
||||
#include "gm_commands/setxp.cpp"
|
||||
#include "gm_commands/showbonusstats.cpp"
|
||||
#include "gm_commands/showbuffs.cpp"
|
||||
#include "gm_commands/shownpcgloballoot.cpp"
|
||||
#include "gm_commands/shownumhits.cpp"
|
||||
#include "gm_commands/showskills.cpp"
|
||||
#include "gm_commands/showspellslist.cpp"
|
||||
#include "gm_commands/showstats.cpp"
|
||||
#include "gm_commands/showzonegloballoot.cpp"
|
||||
#include "gm_commands/showzonepoints.cpp"
|
||||
#include "gm_commands/set.cpp"
|
||||
#include "gm_commands/show.cpp"
|
||||
#include "gm_commands/shutdown.cpp"
|
||||
#include "gm_commands/spawn.cpp"
|
||||
#include "gm_commands/spawneditmass.cpp"
|
||||
#include "gm_commands/spawnfix.cpp"
|
||||
#include "gm_commands/spawnstatus.cpp"
|
||||
#include "gm_commands/spellinfo.cpp"
|
||||
#include "gm_commands/faction_association.cpp"
|
||||
#include "gm_commands/stun.cpp"
|
||||
#include "gm_commands/summon.cpp"
|
||||
@@ -1155,53 +904,23 @@ void command_bot(Client *c, const Seperator *sep)
|
||||
#include "gm_commands/suspend.cpp"
|
||||
#include "gm_commands/suspendmulti.cpp"
|
||||
#include "gm_commands/task.cpp"
|
||||
#include "gm_commands/tempname.cpp"
|
||||
#include "gm_commands/texture.cpp"
|
||||
#include "gm_commands/time.cpp"
|
||||
#include "gm_commands/timers.cpp"
|
||||
#include "gm_commands/timezone.cpp"
|
||||
#include "gm_commands/title.cpp"
|
||||
#include "gm_commands/titlesuffix.cpp"
|
||||
#include "gm_commands/traindisc.cpp"
|
||||
#include "gm_commands/trapinfo.cpp"
|
||||
#include "gm_commands/tune.cpp"
|
||||
#include "gm_commands/undye.cpp"
|
||||
#include "gm_commands/unfreeze.cpp"
|
||||
#include "gm_commands/unmemspell.cpp"
|
||||
#include "gm_commands/unmemspells.cpp"
|
||||
#include "gm_commands/unscribespell.cpp"
|
||||
#include "gm_commands/unscribespells.cpp"
|
||||
#include "gm_commands/updatechecksum.cpp"
|
||||
#include "gm_commands/untraindisc.cpp"
|
||||
#include "gm_commands/untraindiscs.cpp"
|
||||
#include "gm_commands/uptime.cpp"
|
||||
#include "gm_commands/version.cpp"
|
||||
#include "gm_commands/viewcurrencies.cpp"
|
||||
#include "gm_commands/viewnpctype.cpp"
|
||||
#include "gm_commands/viewpetition.cpp"
|
||||
#include "gm_commands/viewrecipe.cpp"
|
||||
#include "gm_commands/viewzoneloot.cpp"
|
||||
#include "gm_commands/wc.cpp"
|
||||
#include "gm_commands/weather.cpp"
|
||||
#include "gm_commands/who.cpp"
|
||||
#include "gm_commands/worldshutdown.cpp"
|
||||
#include "gm_commands/worldwide.cpp"
|
||||
#include "gm_commands/wp.cpp"
|
||||
#include "gm_commands/wpadd.cpp"
|
||||
#include "gm_commands/wpinfo.cpp"
|
||||
#include "gm_commands/xtargets.cpp"
|
||||
#include "gm_commands/zclip.cpp"
|
||||
#include "gm_commands/zcolor.cpp"
|
||||
#include "gm_commands/zheader.cpp"
|
||||
#include "gm_commands/zone.cpp"
|
||||
#include "gm_commands/zonebootup.cpp"
|
||||
#include "gm_commands/zonelock.cpp"
|
||||
#include "gm_commands/zoneshutdown.cpp"
|
||||
#include "gm_commands/zonestatus.cpp"
|
||||
#include "gm_commands/zone_instance.cpp"
|
||||
#include "gm_commands/zopp.cpp"
|
||||
#include "gm_commands/zsafecoords.cpp"
|
||||
#include "gm_commands/zsave.cpp"
|
||||
#include "gm_commands/zsky.cpp"
|
||||
#include "gm_commands/zstats.cpp"
|
||||
#include "gm_commands/zunderworld.cpp"
|
||||
|
||||
+8
-138
@@ -26,19 +26,19 @@ void command_deinit(void);
|
||||
int command_add(std::string command_name, std::string description, uint8 admin, CmdFuncPtr function);
|
||||
int command_notavail(Client *c, std::string message, bool ignore_status);
|
||||
int command_realdispatch(Client *c, std::string message, bool ignore_status);
|
||||
uint8 GetCommandStatus(Client *c, std::string command_name);
|
||||
uint8 GetCommandStatus(std::string command_name);
|
||||
void ListModifyNPCStatMap(Client *c);
|
||||
std::map<std::string, std::string> GetModifyNPCStatMap();
|
||||
std::string GetModifyNPCStatDescription(std::string stat);
|
||||
void SendFeatureSubCommands(Client *c);
|
||||
void SendNPCEditSubCommands(Client *c);
|
||||
void SendRuleSubCommands(Client *c);
|
||||
void SendGuildSubCommands(Client *c);
|
||||
void SendPeekInvSubCommands(Client *c);
|
||||
void SendShowInventorySubCommands(Client *c);
|
||||
|
||||
// Commands
|
||||
void command_acceptrules(Client *c, const Seperator *sep);
|
||||
void command_advnpcspawn(Client *c, const Seperator *sep);
|
||||
void command_aggro(Client *c, const Seperator *sep);
|
||||
void command_aggrozone(Client *c, const Seperator *sep);
|
||||
void command_ai(Client *c, const Seperator *sep);
|
||||
void command_appearance(Client *c, const Seperator *sep);
|
||||
@@ -47,20 +47,16 @@ void command_apply_shared_memory(Client *c, const Seperator *sep);
|
||||
void command_attack(Client *c, const Seperator *sep);
|
||||
void command_augmentitem(Client *c, const Seperator *sep);
|
||||
void command_ban(Client *c, const Seperator *sep);
|
||||
void command_bind(Client *c, const Seperator *sep);
|
||||
void command_bugs(Client *c, const Seperator *sep);
|
||||
void command_camerashake(Client *c, const Seperator *sep);
|
||||
void command_castspell(Client *c, const Seperator *sep);
|
||||
void command_chat(Client *c, const Seperator *sep);
|
||||
void command_checklos(Client *c, const Seperator *sep);
|
||||
void command_copycharacter(Client *c, const Seperator *sep);
|
||||
void command_corpse(Client *c, const Seperator *sep);
|
||||
void command_corpsefix(Client *c, const Seperator *sep);
|
||||
void command_countitem(Client *c, const Seperator *sep);
|
||||
void command_cvs(Client *c, const Seperator *sep);
|
||||
void command_damage(Client *c, const Seperator *sep);
|
||||
void command_databuckets(Client *c, const Seperator *sep);
|
||||
void command_date(Client *c, const Seperator *sep);
|
||||
void command_dbspawn2(Client *c, const Seperator *sep);
|
||||
void command_delacct(Client *c, const Seperator *sep);
|
||||
void command_delpetition(Client *c, const Seperator *sep);
|
||||
@@ -70,103 +66,56 @@ void command_devtools(Client *c, const Seperator *sep);
|
||||
void command_disablerecipe(Client *c, const Seperator *sep);
|
||||
void command_disarmtrap(Client *c, const Seperator *sep);
|
||||
void command_door(Client *c, const Seperator *sep);
|
||||
void command_distance(Client *c, const Seperator *sep);
|
||||
void command_doanim(Client *c, const Seperator *sep);
|
||||
void command_dye(Client *c, const Seperator *sep);
|
||||
void command_dz(Client *c, const Seperator *sep);
|
||||
void command_dzkickplayers(Client *c, const Seperator *sep);
|
||||
void command_editmassrespawn(Client *c, const Seperator *sep);
|
||||
void command_emote(Client *c, const Seperator *sep);
|
||||
void command_emotesearch(Client *c, const Seperator *sep);
|
||||
void command_emoteview(Client *c, const Seperator *sep);
|
||||
void command_emptyinventory(Client *c, const Seperator *sep);
|
||||
void command_enablerecipe(Client *c, const Seperator *sep);
|
||||
void command_endurance(Client *c, const Seperator *sep);
|
||||
void command_entityvariable(Client *c, const Seperator *sep);
|
||||
void command_exptoggle(Client *c, const Seperator *sep);
|
||||
void command_faction(Client *c, const Seperator *sep);
|
||||
void command_faction_association(Client *c, const Seperator *sep);
|
||||
void command_feature(Client *c, const Seperator *sep);
|
||||
void command_findaa(Client *c, const Seperator *sep);
|
||||
void command_findaliases(Client *c, const Seperator *sep);
|
||||
void command_findcharacter(Client *c, const Seperator *sep);
|
||||
void command_findclass(Client *c, const Seperator *sep);
|
||||
void command_findcurrency(Client *c, const Seperator *sep);
|
||||
void command_findfaction(Client *c, const Seperator *sep);
|
||||
void command_findnpctype(Client *c, const Seperator *sep);
|
||||
void command_findrace(Client *c, const Seperator *sep);
|
||||
void command_findrecipe(Client *c, const Seperator *sep);
|
||||
void command_findskill(Client *c, const Seperator *sep);
|
||||
void command_findspell(Client *c, const Seperator *sep);
|
||||
void command_findtask(Client *c, const Seperator *sep);
|
||||
void command_findzone(Client *c, const Seperator *sep);
|
||||
void command_find(Client *c, const Seperator *sep);
|
||||
void command_fixmob(Client *c, const Seperator *sep);
|
||||
void command_flag(Client *c, const Seperator *sep);
|
||||
void command_flagedit(Client *c, const Seperator *sep);
|
||||
void command_flags(Client *c, const Seperator *sep);
|
||||
void command_flymode(Client *c, const Seperator *sep);
|
||||
void command_fov(Client *c, const Seperator *sep);
|
||||
void command_freeze(Client *c, const Seperator *sep);
|
||||
void command_gassign(Client *c, const Seperator *sep);
|
||||
void command_gearup(Client *c, const Seperator *sep);
|
||||
void command_gender(Client *c, const Seperator *sep);
|
||||
void command_getplayerburiedcorpsecount(Client *c, const Seperator *sep);
|
||||
void command_getvariable(Client *c, const Seperator *sep);
|
||||
void command_ginfo(Client *c, const Seperator *sep);
|
||||
void command_giveitem(Client *c, const Seperator *sep);
|
||||
void command_givemoney(Client *c, const Seperator *sep);
|
||||
void command_globalview(Client *c, const Seperator *sep);
|
||||
void command_gm(Client *c, const Seperator *sep);
|
||||
void command_gmspeed(Client *c, const Seperator *sep);
|
||||
void command_gmzone(Client *c, const Seperator *sep);
|
||||
void command_godmode(Client* c, const Seperator *sep);
|
||||
void command_goto(Client *c, const Seperator *sep);
|
||||
void command_grantaa(Client* c, const Seperator* sep);
|
||||
void command_grid(Client *c, const Seperator *sep);
|
||||
void command_guild(Client *c, const Seperator *sep);
|
||||
void command_haste(Client *c, const Seperator *sep);
|
||||
void command_hatelist(Client *c, const Seperator *sep);
|
||||
void command_heal(Client *c, const Seperator *sep);
|
||||
void command_help(Client *c, const Seperator *sep);
|
||||
void command_heromodel(Client *c, const Seperator *sep);
|
||||
void command_hideme(Client *c, const Seperator *sep);
|
||||
void command_hotfix(Client *c, const Seperator *sep);
|
||||
void command_hp(Client *c, const Seperator *sep);
|
||||
void command_incstat(Client *c, const Seperator *sep);
|
||||
void command_instance(Client *c, const Seperator *sep);
|
||||
void command_interrogateinv(Client *c, const Seperator *sep);
|
||||
void command_interrupt(Client *c, const Seperator *sep);
|
||||
void command_invsnapshot(Client *c, const Seperator *sep);
|
||||
void command_invul(Client *c, const Seperator *sep);
|
||||
void command_ipban(Client *c, const Seperator *sep);
|
||||
void command_iplookup(Client *c, const Seperator *sep);
|
||||
void command_itemsearch(Client *c, const Seperator *sep);
|
||||
void command_kick(Client *c, const Seperator *sep);
|
||||
void command_killallnpcs(Client *c, const Seperator *sep);
|
||||
void command_kill(Client *c, const Seperator *sep);
|
||||
void command_lastname(Client *c, const Seperator *sep);
|
||||
void command_level(Client *c, const Seperator *sep);
|
||||
void command_list(Client *c, const Seperator *sep);
|
||||
void command_listpetition(Client *c, const Seperator *sep);
|
||||
void command_lootsim(Client *c, const Seperator *sep);
|
||||
void command_load_shared_memory(Client *c, const Seperator *sep);
|
||||
void command_loc(Client *c, const Seperator *sep);
|
||||
void command_logs(Client *c, const Seperator *sep);
|
||||
void command_makepet(Client *c, const Seperator *sep);
|
||||
void command_mana(Client *c, const Seperator *sep);
|
||||
void command_max_all_skills(Client *c, const Seperator *sep);
|
||||
void command_memspell(Client *c, const Seperator *sep);
|
||||
void command_merchantcloseshop(Client *c, const Seperator *sep);
|
||||
void command_merchantopenshop(Client *c, const Seperator *sep);
|
||||
void command_merchantshop(Client *c, const Seperator *sep);
|
||||
void command_modifynpcstat(Client *c, const Seperator *sep);
|
||||
void command_motd(Client *c, const Seperator *sep);
|
||||
void command_movechar(Client *c, const Seperator *sep);
|
||||
void command_movement(Client *c, const Seperator *sep);
|
||||
void command_myskills(Client *c, const Seperator *sep);
|
||||
void command_mysql(Client *c, const Seperator *sep);
|
||||
void command_mystats(Client *c, const Seperator *sep);
|
||||
void command_name(Client *c, const Seperator *sep);
|
||||
void command_netstats(Client *c, const Seperator *sep);
|
||||
void command_network(Client *c, const Seperator *sep);
|
||||
void command_npccast(Client *c, const Seperator *sep);
|
||||
void command_npcedit(Client *c, const Seperator *sep);
|
||||
void command_npceditmass(Client *c, const Seperator *sep);
|
||||
@@ -175,36 +124,19 @@ void command_npcloot(Client *c, const Seperator *sep);
|
||||
void command_npcsay(Client *c, const Seperator *sep);
|
||||
void command_npcshout(Client *c, const Seperator *sep);
|
||||
void command_npcspawn(Client *c, const Seperator *sep);
|
||||
void command_npcstats(Client *c, const Seperator *sep);
|
||||
void command_npctypespawn(Client *c, const Seperator *sep);
|
||||
void command_nudge(Client *c, const Seperator *sep);
|
||||
void command_nukebuffs(Client *c, const Seperator *sep);
|
||||
void command_nukeitem(Client *c, const Seperator *sep);
|
||||
void command_object(Client *c, const Seperator *sep);
|
||||
void command_oocmute(Client *c, const Seperator *sep);
|
||||
|
||||
#ifdef PACKET_PROFILER
|
||||
void command_packetprofile(Client *c, const Seperator *sep);
|
||||
#endif
|
||||
|
||||
void command_path(Client *c, const Seperator *sep);
|
||||
void command_peekinv(Client *c, const Seperator *sep);
|
||||
void command_peqzone(Client *c, const Seperator *sep);
|
||||
void command_peqzone_flags(Client *c, const Seperator *sep);
|
||||
void command_permaclass(Client *c, const Seperator *sep);
|
||||
void command_permagender(Client *c, const Seperator *sep);
|
||||
void command_permarace(Client *c, const Seperator *sep);
|
||||
void command_petitems(Client *c, const Seperator *sep);
|
||||
void command_petitioninfo(Client *c, const Seperator *sep);
|
||||
void command_picklock(Client *c, const Seperator *sep);
|
||||
void command_profanity(Client *c, const Seperator *sep);
|
||||
|
||||
void command_proximity(Client *c, const Seperator *sep);
|
||||
void command_push(Client *c, const Seperator *sep);
|
||||
void command_pvp(Client *c, const Seperator *sep);
|
||||
void command_qglobal(Client *c, const Seperator *sep);
|
||||
void command_questerrors(Client *c, const Seperator *sep);
|
||||
void command_race(Client *c, const Seperator *sep);
|
||||
void command_raidloot(Client* c, const Seperator* sep);
|
||||
void command_randomfeatures(Client *c, const Seperator *sep);
|
||||
void command_refreshgroup(Client *c, const Seperator *sep);
|
||||
@@ -218,50 +150,18 @@ void command_revoke(Client *c, const Seperator *sep);
|
||||
void command_roambox(Client *c, const Seperator *sep);
|
||||
void command_rules(Client *c, const Seperator *sep);
|
||||
void command_save(Client *c, const Seperator *sep);
|
||||
void command_serverlock(Client *c, const Seperator *sep);
|
||||
void command_scale(Client *c, const Seperator *sep);
|
||||
void command_scribespell(Client *c, const Seperator *sep);
|
||||
void command_scribespells(Client *c, const Seperator *sep);
|
||||
void command_sendzonespawns(Client *c, const Seperator *sep);
|
||||
void command_sensetrap(Client *c, const Seperator *sep);
|
||||
void command_serverinfo(Client *c, const Seperator *sep);
|
||||
void command_serverrules(Client *c, const Seperator *sep);
|
||||
void command_set_adventure_points(Client *c, const Seperator *sep);
|
||||
void command_setaapts(Client *c, const Seperator *sep);
|
||||
void command_setaaxp(Client *c, const Seperator *sep);
|
||||
void command_setaltcurrency(Client *c, const Seperator *sep);
|
||||
void command_setanim(Client *c, const Seperator *sep);
|
||||
void command_setanon(Client *c, const Seperator *sep);
|
||||
void command_setcrystals(Client *c, const Seperator *sep);
|
||||
void command_setendurance(Client *c, const Seperator *sep);
|
||||
void command_setfaction(Client *c, const Seperator *sep);
|
||||
void command_sethp(Client *c, const Seperator *sep);
|
||||
void command_setlanguage(Client *c, const Seperator *sep);
|
||||
void command_setlsinfo(Client *c, const Seperator *sep);
|
||||
void command_setmana(Client *c, const Seperator *sep);
|
||||
void command_setpass(Client *c, const Seperator *sep);
|
||||
void command_setpvppoints(Client *c, const Seperator *sep);
|
||||
void command_setskill(Client *c, const Seperator *sep);
|
||||
void command_setskillall(Client *c, const Seperator *sep);
|
||||
void command_setstartzone(Client *c, const Seperator *sep);
|
||||
void command_setstat(Client *c, const Seperator *sep);
|
||||
void command_setxp(Client *c, const Seperator *sep);
|
||||
void command_showbonusstats(Client *c, const Seperator *sep);
|
||||
void command_showbuffs(Client *c, const Seperator *sep);
|
||||
void command_shownumhits(Client *c, const Seperator *sep);
|
||||
void command_shownpcgloballoot(Client *c, const Seperator *sep);
|
||||
void command_showpetspell(Client *c, const Seperator *sep);
|
||||
void command_showskills(Client *c, const Seperator *sep);
|
||||
void command_showspellslist(Client *c, const Seperator *sep);
|
||||
void command_showstats(Client *c, const Seperator *sep);
|
||||
void command_showzonegloballoot(Client *c, const Seperator *sep);
|
||||
void command_showzonepoints(Client *c, const Seperator *sep);
|
||||
void command_set(Client *c, const Seperator *sep);
|
||||
void command_show(Client *c, const Seperator *sep);
|
||||
void command_shutdown(Client *c, const Seperator *sep);
|
||||
void command_spawn(Client *c, const Seperator *sep);
|
||||
void command_spawneditmass(Client *c, const Seperator *sep);
|
||||
void command_spawnfix(Client *c, const Seperator *sep);
|
||||
void command_spawnstatus(Client *c, const Seperator *sep);
|
||||
void command_spellinfo(Client *c, const Seperator *sep);
|
||||
void command_stun(Client *c, const Seperator *sep);
|
||||
void command_summon(Client *c, const Seperator *sep);
|
||||
void command_summonburiedplayercorpse(Client *c, const Seperator *sep);
|
||||
@@ -269,58 +169,28 @@ void command_summonitem(Client *c, const Seperator *sep);
|
||||
void command_suspend(Client *c, const Seperator *sep);
|
||||
void command_suspendmulti(Client *c, const Seperator *sep);
|
||||
void command_task(Client *c, const Seperator *sep);
|
||||
void command_tempname(Client *c, const Seperator *sep);
|
||||
void command_petname(Client *c, const Seperator *sep);
|
||||
void command_texture(Client *c, const Seperator *sep);
|
||||
void command_time(Client *c, const Seperator *sep);
|
||||
void command_timers(Client *c, const Seperator *sep);
|
||||
void command_timezone(Client *c, const Seperator *sep);
|
||||
void command_title(Client *c, const Seperator *sep);
|
||||
void command_titlesuffix(Client *c, const Seperator *sep);
|
||||
void command_traindisc(Client *c, const Seperator *sep);
|
||||
void command_trapinfo(Client *c, const Seperator *sep);
|
||||
void command_tune(Client *c, const Seperator *sep);
|
||||
void command_undye(Client *c, const Seperator *sep);
|
||||
void command_unfreeze(Client *c, const Seperator *sep);
|
||||
void command_unlock(Client *c, const Seperator *sep);
|
||||
void command_unmemspell(Client *c, const Seperator *sep);
|
||||
void command_unmemspells(Client *c, const Seperator *sep);
|
||||
void command_unscribespell(Client *c, const Seperator *sep);
|
||||
void command_unscribespells(Client *c, const Seperator *sep);
|
||||
void command_untraindisc(Client *c, const Seperator *sep);
|
||||
void command_untraindiscs(Client *c, const Seperator *sep);
|
||||
void command_updatechecksum(Client* c, const Seperator* sep);
|
||||
void command_uptime(Client *c, const Seperator *sep);
|
||||
void command_version(Client *c, const Seperator *sep);
|
||||
void command_viewcurrencies(Client *c, const Seperator *sep);
|
||||
void command_viewnpctype(Client *c, const Seperator *sep);
|
||||
void command_viewpetition(Client *c, const Seperator *sep);
|
||||
void command_viewrecipe(Client *c, const Seperator *sep);
|
||||
void command_viewzoneloot(Client *c, const Seperator *sep);
|
||||
void command_wc(Client *c, const Seperator *sep);
|
||||
void command_weather(Client *c, const Seperator *sep);
|
||||
void command_who(Client *c, const Seperator *sep);
|
||||
void command_worldshutdown(Client *c, const Seperator *sep);
|
||||
void command_wp(Client *c, const Seperator *sep);
|
||||
void command_wpadd(Client *c, const Seperator *sep);
|
||||
void command_wpinfo(Client *c, const Seperator *sep);
|
||||
void command_worldwide(Client *c, const Seperator *sep);
|
||||
void command_xtargets(Client *c, const Seperator *sep);
|
||||
void command_zclip(Client *c, const Seperator *sep);
|
||||
void command_zcolor(Client *c, const Seperator *sep);
|
||||
void command_zheader(Client *c, const Seperator *sep);
|
||||
void command_zone(Client *c, const Seperator *sep);
|
||||
void command_zone_instance(Client *c, const Seperator *sep);
|
||||
void command_zonebootup(Client *c, const Seperator *sep);
|
||||
void command_zonelock(Client *c, const Seperator *sep);
|
||||
void command_zoneshutdown(Client *c, const Seperator *sep);
|
||||
void command_zonestatus(Client *c, const Seperator *sep);
|
||||
void command_zopp(Client *c, const Seperator *sep);
|
||||
void command_zsafecoords(Client *c, const Seperator *sep);
|
||||
void command_zsave(Client *c, const Seperator *sep);
|
||||
void command_zsky(Client *c, const Seperator *sep);
|
||||
void command_zstats(Client *c, const Seperator *sep);
|
||||
void command_zunderworld(Client *c, const Seperator *sep);
|
||||
|
||||
#include "bot.h"
|
||||
void command_bot(Client*c, const Seperator *sep);
|
||||
|
||||
+1
-1
@@ -891,7 +891,7 @@ struct ExtraAttackOptions {
|
||||
int hit_chance;
|
||||
int melee_damage_bonus_flat;
|
||||
int skilldmgtaken_bonus_flat;
|
||||
|
||||
int range_percent;
|
||||
};
|
||||
|
||||
struct DamageTable {
|
||||
|
||||
+2
-2
@@ -1207,7 +1207,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
|
||||
client->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"This corpse Contains {}.",
|
||||
"This corpse contains {}.",
|
||||
Strings::Money(
|
||||
GetPlatinum(),
|
||||
GetGold(),
|
||||
@@ -1217,7 +1217,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
client->Message(Chat::Yellow, "This corpse Contains no money.");
|
||||
client->Message(Chat::Yellow, "This corpse contains no money.");
|
||||
}
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_MoneyOnCorpse, sizeof(moneyOnCorpseStruct));
|
||||
|
||||
+636
-168
@@ -1,205 +1,673 @@
|
||||
#include "data_bucket.h"
|
||||
#include "entity.h"
|
||||
#include "zonedb.h"
|
||||
#include "mob.h"
|
||||
#include "worldserver.h"
|
||||
#include <ctime>
|
||||
#include <cctype>
|
||||
|
||||
/**
|
||||
* Persists data via bucket_name as key
|
||||
* @param bucket_key
|
||||
* @param bucket_value
|
||||
* @param expires_time
|
||||
*/
|
||||
void DataBucket::SetData(const std::string& bucket_key, const std::string& bucket_value, std::string expires_time) {
|
||||
uint64 bucket_id = DataBucket::DoesBucketExist(bucket_key);
|
||||
extern WorldServer worldserver;
|
||||
|
||||
std::string query;
|
||||
long long expires_time_unix = 0;
|
||||
std::vector<DataBucketCacheEntry> g_data_bucket_cache = {};
|
||||
|
||||
if (!expires_time.empty()) {
|
||||
if (isalpha(expires_time[0]) || isalpha(expires_time[expires_time.length() - 1])) {
|
||||
expires_time_unix = (long long) std::time(nullptr) + Strings::TimeToSeconds(expires_time);
|
||||
} else {
|
||||
expires_time_unix = (long long) std::time(nullptr) + Strings::ToInt(expires_time);
|
||||
void DataBucket::SetData(const std::string &bucket_key, const std::string &bucket_value, std::string expires_time)
|
||||
{
|
||||
auto k = DataBucketKey{
|
||||
.key = bucket_key,
|
||||
.value = bucket_value,
|
||||
.expires = expires_time,
|
||||
.character_id = 0,
|
||||
.npc_id = 0,
|
||||
.bot_id = 0
|
||||
};
|
||||
|
||||
DataBucket::SetData(k);
|
||||
}
|
||||
|
||||
void DataBucket::SetData(const DataBucketKey &k)
|
||||
{
|
||||
auto b = DataBucketsRepository::NewEntity();
|
||||
auto r = GetData(k, true);
|
||||
// if we have an entry, use it
|
||||
if (r.id > 0) {
|
||||
b = r;
|
||||
}
|
||||
|
||||
// add scoping to bucket
|
||||
if (k.character_id > 0) {
|
||||
b.character_id = k.character_id;
|
||||
}
|
||||
else if (k.npc_id > 0) {
|
||||
b.npc_id = k.npc_id;
|
||||
}
|
||||
else if (k.bot_id > 0) {
|
||||
b.bot_id = k.bot_id;
|
||||
}
|
||||
|
||||
const uint64 bucket_id = b.id;
|
||||
int64 expires_time_unix = 0;
|
||||
|
||||
if (!k.expires.empty()) {
|
||||
expires_time_unix = static_cast<int64>(std::time(nullptr)) + Strings::ToInt(k.expires);
|
||||
if (isalpha(k.expires[0]) || isalpha(k.expires[k.expires.length() - 1])) {
|
||||
expires_time_unix = static_cast<int64>(std::time(nullptr)) + Strings::TimeToSeconds(k.expires);
|
||||
}
|
||||
}
|
||||
|
||||
if (bucket_id > 0) {
|
||||
std::string update_expired_time;
|
||||
if (expires_time_unix > 0) {
|
||||
update_expired_time = StringFormat(", `expires` = %lld ", expires_time_unix);
|
||||
b.expires = expires_time_unix;
|
||||
b.value = k.value;
|
||||
|
||||
if (bucket_id) {
|
||||
// loop cache and update cache value and timestamp
|
||||
for (auto &ce: g_data_bucket_cache) {
|
||||
if (CheckBucketMatch(ce.e, k)) {
|
||||
ce.e = b;
|
||||
ce.updated_time = GetCurrentTimeUNIX();
|
||||
ce.update_action = DataBucketCacheUpdateAction::Upsert;
|
||||
SendDataBucketCacheUpdate(ce);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
query = StringFormat(
|
||||
"UPDATE `data_buckets` SET `value` = '%s' %s WHERE `id` = %i",
|
||||
Strings::Escape(bucket_value).c_str(),
|
||||
Strings::Escape(update_expired_time).c_str(),
|
||||
bucket_id
|
||||
);
|
||||
DataBucketsRepository::UpdateOne(database, b);
|
||||
}
|
||||
else {
|
||||
query = StringFormat(
|
||||
"INSERT INTO `data_buckets` (`key`, `value`, `expires`) VALUES ('%s', '%s', '%lld')",
|
||||
Strings::Escape(bucket_key).c_str(),
|
||||
Strings::Escape(bucket_value).c_str(),
|
||||
expires_time_unix
|
||||
);
|
||||
}
|
||||
b.key_ = k.key;
|
||||
b = DataBucketsRepository::InsertOne(database, b);
|
||||
if (!ExistsInCache(b)) {
|
||||
// add data bucket and timestamp to cache
|
||||
auto ce = DataBucketCacheEntry{
|
||||
.e = b,
|
||||
.updated_time = DataBucket::GetCurrentTimeUNIX(),
|
||||
.update_action = DataBucketCacheUpdateAction::Upsert
|
||||
};
|
||||
|
||||
database.QueryDatabase(query);
|
||||
g_data_bucket_cache.emplace_back(ce);
|
||||
|
||||
SendDataBucketCacheUpdate(ce);
|
||||
|
||||
DeleteFromMissesCache(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves data via bucket_name as key
|
||||
* @param bucket_key
|
||||
* @return
|
||||
*/
|
||||
std::string DataBucket::GetData(const std::string& bucket_key) {
|
||||
std::string query = StringFormat(
|
||||
"SELECT `value` from `data_buckets` WHERE `key` = '%s' AND (`expires` > %lld OR `expires` = 0) LIMIT 1",
|
||||
bucket_key.c_str(),
|
||||
(long long) std::time(nullptr)
|
||||
);
|
||||
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
if (results.RowCount() != 1)
|
||||
return std::string();
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
return std::string(row[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves data expires time via bucket_name as key
|
||||
* @param bucket_key
|
||||
* @return
|
||||
*/
|
||||
std::string DataBucket::GetDataExpires(const std::string& bucket_key) {
|
||||
std::string query = StringFormat(
|
||||
"SELECT `expires` from `data_buckets` WHERE `key` = '%s' AND (`expires` > %lld OR `expires` = 0) LIMIT 1",
|
||||
bucket_key.c_str(),
|
||||
(long long) std::time(nullptr)
|
||||
);
|
||||
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
if (results.RowCount() != 1)
|
||||
return std::string();
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
return std::string(row[0]);
|
||||
}
|
||||
|
||||
std::string DataBucket::GetDataRemaining(const std::string& bucket_key) {
|
||||
if (DataBucket::GetDataExpires(bucket_key).empty()) {
|
||||
return "0";
|
||||
}
|
||||
std::string query = fmt::format(
|
||||
"SELECT (`expires` - UNIX_TIMESTAMP()) AS `remaining` from `data_buckets` WHERE `key` = '{}' AND (`expires` > {} OR `expires` = 0) LIMIT 1",
|
||||
bucket_key.c_str(),
|
||||
(long long) std::time(nullptr)
|
||||
);
|
||||
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
if (results.RowCount() != 1)
|
||||
return std::string();
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
return std::string(row[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for bucket existence by bucket_name key
|
||||
* @param bucket_key
|
||||
* @return
|
||||
*/
|
||||
uint64 DataBucket::DoesBucketExist(const std::string& bucket_key) {
|
||||
std::string query = StringFormat(
|
||||
"SELECT `id` from `data_buckets` WHERE `key` = '%s' AND (`expires` > %lld OR `expires` = 0) LIMIT 1",
|
||||
Strings::Escape(bucket_key).c_str(),
|
||||
(long long) std::time(nullptr)
|
||||
);
|
||||
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() != 1)
|
||||
return 0;
|
||||
|
||||
return Strings::ToUnsignedBigInt(row[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes data bucket by key
|
||||
* @param bucket_key
|
||||
* @return
|
||||
*/
|
||||
bool DataBucket::DeleteData(const std::string& bucket_key) {
|
||||
std::string query = StringFormat(
|
||||
"DELETE FROM `data_buckets` WHERE `key` = '%s'",
|
||||
Strings::Escape(bucket_key).c_str()
|
||||
);
|
||||
|
||||
auto results = database.QueryDatabase(query);
|
||||
|
||||
return results.Success();
|
||||
}
|
||||
|
||||
bool DataBucket::GetDataBuckets(Mob* mob)
|
||||
std::string DataBucket::GetData(const std::string &bucket_key)
|
||||
{
|
||||
auto l = BaseDataBucketsRepository::GetWhere(
|
||||
DataBucketKey k = {};
|
||||
k.key = bucket_key;
|
||||
return GetData(k).value;
|
||||
}
|
||||
|
||||
// GetData fetches bucket data from the database or cache if it exists
|
||||
// if the bucket doesn't exist, it will be added to the cache as a miss
|
||||
// if ignore_misses_cache is true, the bucket will not be added to the cache as a miss
|
||||
// the only place we should be ignoring the misses cache is on the initial read during SetData
|
||||
DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k, bool ignore_misses_cache)
|
||||
{
|
||||
LogDataBuckets(
|
||||
"Getting bucket key [{}] bot_id [{}] character_id [{}] npc_id [{}]",
|
||||
k.key,
|
||||
k.bot_id,
|
||||
k.character_id,
|
||||
k.npc_id
|
||||
);
|
||||
|
||||
for (const auto &ce: g_data_bucket_cache) {
|
||||
if (CheckBucketMatch(ce.e, k)) {
|
||||
if (ce.e.expires > 0 && ce.e.expires < std::time(nullptr)) {
|
||||
LogDataBuckets("Attempted to read expired key [{}] removing from cache", ce.e.key_);
|
||||
DeleteData(k);
|
||||
return DataBucketsRepository::NewEntity();
|
||||
}
|
||||
|
||||
// this is a bucket miss, return empty entity
|
||||
// we still cache bucket misses, so we don't have to hit the database
|
||||
if (ce.e.id == 0) {
|
||||
return DataBucketsRepository::NewEntity();
|
||||
}
|
||||
|
||||
LogDataBuckets("Returning key [{}] value [{}] from cache", ce.e.key_, ce.e.value);
|
||||
return ce.e;
|
||||
}
|
||||
}
|
||||
|
||||
auto r = DataBucketsRepository::GetWhere(
|
||||
database,
|
||||
fmt::format(
|
||||
"`key` LIKE '{}-%'",
|
||||
Strings::Escape(mob->GetBucketKey())
|
||||
"{} `key` = '{}' LIMIT 1",
|
||||
DataBucket::GetScopedDbFilters(k),
|
||||
k.key
|
||||
)
|
||||
);
|
||||
|
||||
if (l.empty()) {
|
||||
if (r.empty()) {
|
||||
|
||||
// if we're ignoring the misses cache, don't add to the cache
|
||||
// the only place this is ignored is during the initial read of SetData
|
||||
if (!ignore_misses_cache) {
|
||||
size_t size_before = g_data_bucket_cache.size();
|
||||
|
||||
// cache bucket misses, so we don't have to hit the database
|
||||
// when scripts try to read a bucket that doesn't exist
|
||||
g_data_bucket_cache.emplace_back(
|
||||
DataBucketCacheEntry{
|
||||
.e = DataBucketsRepository::DataBuckets{
|
||||
.id = 0,
|
||||
.key_ = k.key,
|
||||
.value = "",
|
||||
.expires = 0,
|
||||
.character_id = k.character_id,
|
||||
.npc_id = k.npc_id,
|
||||
.bot_id = k.bot_id
|
||||
},
|
||||
.updated_time = DataBucket::GetCurrentTimeUNIX()
|
||||
}
|
||||
);
|
||||
|
||||
LogDataBuckets(
|
||||
"Key [{}] not found in database, adding to cache as a miss character_id [{}] npc_id [{}] bot_id [{}] cache size before [{}] after [{}]",
|
||||
k.key,
|
||||
k.character_id,
|
||||
k.npc_id,
|
||||
k.bot_id,
|
||||
size_before,
|
||||
g_data_bucket_cache.size()
|
||||
);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// if the entry has expired, delete it
|
||||
if (r[0].expires > 0 && r[0].expires < (long long) std::time(nullptr)) {
|
||||
DeleteData(k);
|
||||
return {};
|
||||
}
|
||||
|
||||
bool has_cache = false;
|
||||
for (auto &ce: g_data_bucket_cache) {
|
||||
if (ce.e.id == r[0].id) {
|
||||
has_cache = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_cache) {
|
||||
// add data bucket and timestamp to cache
|
||||
g_data_bucket_cache.emplace_back(
|
||||
DataBucketCacheEntry{
|
||||
.e = r[0],
|
||||
.updated_time = DataBucket::GetCurrentTimeUNIX()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return r[0];
|
||||
}
|
||||
|
||||
std::string DataBucket::GetDataExpires(const std::string &bucket_key)
|
||||
{
|
||||
DataBucketKey k = {};
|
||||
k.key = bucket_key;
|
||||
|
||||
return GetDataExpires(k);
|
||||
}
|
||||
|
||||
std::string DataBucket::GetDataRemaining(const std::string &bucket_key)
|
||||
{
|
||||
DataBucketKey k = {};
|
||||
k.key = bucket_key;
|
||||
return GetDataRemaining(k);
|
||||
}
|
||||
|
||||
bool DataBucket::DeleteData(const std::string &bucket_key)
|
||||
{
|
||||
DataBucketKey k = {};
|
||||
k.key = bucket_key;
|
||||
return DeleteData(k);
|
||||
}
|
||||
|
||||
// GetDataBuckets bulk loads all data buckets for a mob
|
||||
bool DataBucket::GetDataBuckets(Mob *mob)
|
||||
{
|
||||
DataBucketLoadType::Type t;
|
||||
const uint32 id = mob->GetMobTypeIdentifier();
|
||||
|
||||
if (!id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mob->m_data_bucket_cache.clear();
|
||||
|
||||
DataBucketCache d;
|
||||
|
||||
for (const auto& e : l) {
|
||||
d.bucket_id = e.id;
|
||||
d.bucket_key = e.key_;
|
||||
d.bucket_value = e.value;
|
||||
d.bucket_expires = e.expires;
|
||||
|
||||
mob->m_data_bucket_cache.emplace_back(d);
|
||||
if (mob->IsBot()) {
|
||||
t = DataBucketLoadType::Bot;
|
||||
}
|
||||
else if (mob->IsClient()) {
|
||||
t = DataBucketLoadType::Client;
|
||||
}
|
||||
else if (mob->IsNPC()) {
|
||||
t = DataBucketLoadType::NPC;
|
||||
}
|
||||
|
||||
BulkLoadEntities(t, {id});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string DataBucket::CheckBucketKey(const Mob* mob, std::string_view full_name)
|
||||
bool DataBucket::DeleteData(const DataBucketKey &k)
|
||||
{
|
||||
std::string bucket_value;
|
||||
for (const auto &d : mob->m_data_bucket_cache) {
|
||||
if (d.bucket_key == full_name) {
|
||||
bucket_value = d.bucket_value;
|
||||
size_t size_before = g_data_bucket_cache.size();
|
||||
|
||||
// delete from cache where contents match
|
||||
g_data_bucket_cache.erase(
|
||||
std::remove_if(
|
||||
g_data_bucket_cache.begin(),
|
||||
g_data_bucket_cache.end(),
|
||||
[&](DataBucketCacheEntry &ce) {
|
||||
bool match = CheckBucketMatch(ce.e, k);
|
||||
if (match) {
|
||||
ce.update_action = DataBucketCacheUpdateAction::Delete;
|
||||
SendDataBucketCacheUpdate(ce);
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
),
|
||||
g_data_bucket_cache.end()
|
||||
);
|
||||
|
||||
LogDataBuckets(
|
||||
"Deleting bucket key [{}] bot_id [{}] character_id [{}] npc_id [{}] cache size before [{}] after [{}]",
|
||||
k.key,
|
||||
k.bot_id,
|
||||
k.character_id,
|
||||
k.npc_id,
|
||||
size_before,
|
||||
g_data_bucket_cache.size()
|
||||
);
|
||||
|
||||
return DataBucketsRepository::DeleteWhere(
|
||||
database,
|
||||
fmt::format(
|
||||
"{} `key` = '{}'",
|
||||
DataBucket::GetScopedDbFilters(k),
|
||||
k.key
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
std::string DataBucket::GetDataExpires(const DataBucketKey &k)
|
||||
{
|
||||
LogDataBuckets(
|
||||
"Getting bucket expiration key [{}] bot_id [{}] character_id [{}] npc_id [{}]",
|
||||
k.key,
|
||||
k.bot_id,
|
||||
k.character_id,
|
||||
k.npc_id
|
||||
);
|
||||
|
||||
auto r = GetData(k);
|
||||
if (r.id == 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return std::to_string(r.expires);
|
||||
}
|
||||
|
||||
std::string DataBucket::GetDataRemaining(const DataBucketKey &k)
|
||||
{
|
||||
LogDataBuckets(
|
||||
"Getting bucket remaining key [{}] bot_id [{}] character_id [{}] npc_id [{}]",
|
||||
k.key,
|
||||
k.bot_id,
|
||||
k.character_id,
|
||||
k.npc_id
|
||||
);
|
||||
|
||||
auto r = GetData(k);
|
||||
if (r.id == 0) {
|
||||
return "0";
|
||||
}
|
||||
|
||||
return fmt::format("{}", r.expires - (long long) std::time(nullptr));
|
||||
}
|
||||
|
||||
std::string DataBucket::GetScopedDbFilters(const DataBucketKey &k)
|
||||
{
|
||||
std::vector<std::string> query = {};
|
||||
if (k.character_id > 0) {
|
||||
query.emplace_back(fmt::format("character_id = {}", k.character_id));
|
||||
}
|
||||
else {
|
||||
query.emplace_back("character_id = 0");
|
||||
}
|
||||
|
||||
if (k.npc_id > 0) {
|
||||
query.emplace_back(fmt::format("npc_id = {}", k.npc_id));
|
||||
}
|
||||
else {
|
||||
query.emplace_back("npc_id = 0");
|
||||
}
|
||||
|
||||
if (k.bot_id > 0) {
|
||||
query.emplace_back(fmt::format("bot_id = {}", k.bot_id));
|
||||
}
|
||||
else {
|
||||
query.emplace_back("bot_id = 0");
|
||||
}
|
||||
|
||||
return fmt::format(
|
||||
"{} {}",
|
||||
Strings::Join(query, " AND "),
|
||||
!query.empty() ? "AND" : ""
|
||||
);
|
||||
}
|
||||
|
||||
bool DataBucket::CheckBucketMatch(const DataBucketsRepository::DataBuckets &dbe, const DataBucketKey &k)
|
||||
{
|
||||
return (
|
||||
dbe.key_ == k.key &&
|
||||
dbe.bot_id == k.bot_id &&
|
||||
dbe.character_id == k.character_id &&
|
||||
dbe.npc_id == k.npc_id
|
||||
);
|
||||
}
|
||||
|
||||
void DataBucket::BulkLoadEntities(DataBucketLoadType::Type t, std::vector<uint32> ids)
|
||||
{
|
||||
if (ids.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ids.size() == 1) {
|
||||
bool has_cache = false;
|
||||
for (const auto &ce: g_data_bucket_cache) {
|
||||
if (t == DataBucketLoadType::Bot) {
|
||||
has_cache = ce.e.bot_id == ids[0];
|
||||
}
|
||||
else if (t == DataBucketLoadType::Client) {
|
||||
has_cache = ce.e.character_id == ids[0];
|
||||
}
|
||||
else if (t == DataBucketLoadType::NPC) {
|
||||
has_cache = ce.e.npc_id == ids[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (has_cache) {
|
||||
LogDataBucketsDetail("LoadType [{}] ID [{}] has cache", DataBucketLoadType::Name[t], ids[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::string column;
|
||||
|
||||
switch (t) {
|
||||
case DataBucketLoadType::Bot:
|
||||
column = "bot_id";
|
||||
break;
|
||||
case DataBucketLoadType::Client:
|
||||
column = "character_id";
|
||||
break;
|
||||
case DataBucketLoadType::NPC:
|
||||
column = "npc_id";
|
||||
break;
|
||||
default:
|
||||
LogError("Incorrect LoadType [{}]", t);
|
||||
break;
|
||||
}
|
||||
|
||||
const auto &l = DataBucketsRepository::GetWhere(
|
||||
database,
|
||||
fmt::format(
|
||||
"{} IN ({}) AND (`expires` > {} OR `expires` = 0)",
|
||||
column,
|
||||
Strings::Join(ids, ", "),
|
||||
(long long) std::time(nullptr)
|
||||
)
|
||||
);
|
||||
|
||||
if (l.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t size_before = g_data_bucket_cache.size();
|
||||
|
||||
LogDataBucketsDetail("cache size before [{}] l size [{}]", g_data_bucket_cache.size(), l.size());
|
||||
|
||||
uint32 added_count = 0;
|
||||
|
||||
for (const auto &e: l) {
|
||||
if (!ExistsInCache(e)) {
|
||||
added_count++;
|
||||
}
|
||||
}
|
||||
|
||||
g_data_bucket_cache.reserve(g_data_bucket_cache.size() + added_count);
|
||||
|
||||
for (const auto &e: l) {
|
||||
if (!ExistsInCache(e)) {
|
||||
LogDataBucketsDetail("bucket id [{}] bucket key [{}] bucket value [{}]", e.id, e.key_, e.value);
|
||||
|
||||
g_data_bucket_cache.emplace_back(
|
||||
DataBucketCacheEntry{
|
||||
.e = e,
|
||||
.updated_time = GetCurrentTimeUNIX()
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
LogDataBucketsDetail("cache size after [{}]", g_data_bucket_cache.size());
|
||||
|
||||
LogDataBuckets(
|
||||
"Bulk Loaded ids [{}] column [{}] new cache size is [{}]",
|
||||
ids.size(),
|
||||
column,
|
||||
g_data_bucket_cache.size()
|
||||
);
|
||||
}
|
||||
|
||||
void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type t, uint32 id)
|
||||
{
|
||||
size_t size_before = g_data_bucket_cache.size();
|
||||
|
||||
g_data_bucket_cache.erase(
|
||||
std::remove_if(
|
||||
g_data_bucket_cache.begin(),
|
||||
g_data_bucket_cache.end(),
|
||||
[&](DataBucketCacheEntry &ce) {
|
||||
return (
|
||||
(t == DataBucketLoadType::Bot && ce.e.bot_id == id) ||
|
||||
(t == DataBucketLoadType::Client && ce.e.character_id == id) ||
|
||||
(t == DataBucketLoadType::NPC && ce.e.npc_id == id)
|
||||
);
|
||||
}
|
||||
),
|
||||
g_data_bucket_cache.end()
|
||||
);
|
||||
|
||||
LogDataBuckets(
|
||||
"LoadType [{}] id [{}] cache size before [{}] after [{}]",
|
||||
DataBucketLoadType::Name[t],
|
||||
id,
|
||||
size_before,
|
||||
g_data_bucket_cache.size()
|
||||
);
|
||||
}
|
||||
|
||||
int64_t DataBucket::GetCurrentTimeUNIX()
|
||||
{
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch()
|
||||
).count();
|
||||
}
|
||||
|
||||
bool DataBucket::ExistsInCache(const DataBucketsRepository::DataBuckets &e)
|
||||
{
|
||||
for (const auto &ce: g_data_bucket_cache) {
|
||||
if (ce.e.id == e.id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DataBucket::SendDataBucketCacheUpdate(const DataBucketCacheEntry &e)
|
||||
{
|
||||
if (!e.e.id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EQ::Net::DynamicPacket p;
|
||||
p.PutSerialize(0, e);
|
||||
|
||||
auto pack_size = sizeof(ServerDataBucketCacheUpdate_Struct) + p.Length();
|
||||
auto pack = new ServerPacket(ServerOP_DataBucketCacheUpdate, static_cast<uint32_t>(pack_size));
|
||||
auto buf = reinterpret_cast<ServerDataBucketCacheUpdate_Struct *>(pack->pBuffer);
|
||||
|
||||
buf->cereal_size = static_cast<uint32_t>(p.Length());
|
||||
|
||||
memcpy(buf->cereal_data, p.Data(), p.Length());
|
||||
|
||||
worldserver.SendPacket(pack);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DataBucket::HandleWorldMessage(ServerPacket *p)
|
||||
{
|
||||
DataBucketCacheEntry n;
|
||||
auto s = (ServerDataBucketCacheUpdate_Struct *) p->pBuffer;
|
||||
EQ::Util::MemoryStreamReader ss(s->cereal_data, s->cereal_size);
|
||||
cereal::BinaryInputArchive archive(ss);
|
||||
archive(n);
|
||||
|
||||
LogDataBucketsDetail(
|
||||
"Received cache packet for id [{}] key [{}] value [{}] action [{}]",
|
||||
n.e.id,
|
||||
n.e.key_,
|
||||
n.e.value,
|
||||
n.update_action
|
||||
);
|
||||
|
||||
// delete
|
||||
if (n.update_action == DataBucketCacheUpdateAction::Delete) {
|
||||
DeleteFromMissesCache(n.e);
|
||||
|
||||
g_data_bucket_cache.erase(
|
||||
std::remove_if(
|
||||
g_data_bucket_cache.begin(),
|
||||
g_data_bucket_cache.end(),
|
||||
[&](DataBucketCacheEntry &ce) {
|
||||
bool match = n.e.id > 0 && ce.e.id == n.e.id;
|
||||
if (match) {
|
||||
LogDataBuckets(
|
||||
"[delete] cache key [{}] id [{}] cache_size before [{}] after [{}]",
|
||||
ce.e.key_,
|
||||
ce.e.id,
|
||||
g_data_bucket_cache.size(),
|
||||
g_data_bucket_cache.size() - 1
|
||||
);
|
||||
}
|
||||
return match;
|
||||
}
|
||||
),
|
||||
g_data_bucket_cache.end()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// update
|
||||
bool has_key = false;
|
||||
for (auto &ce: g_data_bucket_cache) {
|
||||
// update cache
|
||||
if (ce.e.id == n.e.id) {
|
||||
// reject old updates
|
||||
int64 time_delta = ce.updated_time - n.updated_time;
|
||||
if (ce.updated_time >= n.updated_time) {
|
||||
LogDataBuckets(
|
||||
"Attempted to update older cache key [{}] rejecting old time [{}] new time [{}] delta [{}] cache_size [{}]",
|
||||
ce.e.key_,
|
||||
ce.updated_time,
|
||||
n.updated_time,
|
||||
time_delta,
|
||||
g_data_bucket_cache.size()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
DeleteFromMissesCache(n.e);
|
||||
|
||||
LogDataBuckets(
|
||||
"[update] cache id [{}] key [{}] value [{}] old time [{}] new time [{}] delta [{}] cache_size [{}]",
|
||||
ce.e.id,
|
||||
ce.e.key_,
|
||||
n.e.value,
|
||||
ce.updated_time,
|
||||
n.updated_time,
|
||||
time_delta,
|
||||
g_data_bucket_cache.size()
|
||||
);
|
||||
ce.e = n.e;
|
||||
ce.updated_time = n.updated_time;
|
||||
has_key = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bucket_value;
|
||||
|
||||
// create
|
||||
if (!has_key) {
|
||||
DeleteFromMissesCache(n.e);
|
||||
|
||||
size_t size_before = g_data_bucket_cache.size();
|
||||
|
||||
g_data_bucket_cache.emplace_back(
|
||||
DataBucketCacheEntry{
|
||||
.e = n.e,
|
||||
.updated_time = GetCurrentTimeUNIX()
|
||||
}
|
||||
);
|
||||
|
||||
LogDataBuckets(
|
||||
"[create] Adding new cache id [{}] key [{}] value [{}] cache size before [{}] after [{}]",
|
||||
n.e.id,
|
||||
n.e.key_,
|
||||
n.e.value,
|
||||
size_before,
|
||||
g_data_bucket_cache.size()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void DataBucket::DeleteFromMissesCache(DataBucketsRepository::DataBuckets e)
|
||||
{
|
||||
// delete from cache where there might have been a written bucket miss to the cache
|
||||
// this is to prevent the cache from growing too large
|
||||
size_t size_before = g_data_bucket_cache.size();
|
||||
|
||||
g_data_bucket_cache.erase(
|
||||
std::remove_if(
|
||||
g_data_bucket_cache.begin(),
|
||||
g_data_bucket_cache.end(),
|
||||
[&](DataBucketCacheEntry &ce) {
|
||||
return ce.e.id == 0 && ce.e.key_ == e.key_ &&
|
||||
ce.e.character_id == e.character_id &&
|
||||
ce.e.npc_id == e.npc_id &&
|
||||
ce.e.bot_id == e.bot_id;
|
||||
}
|
||||
),
|
||||
g_data_bucket_cache.end()
|
||||
);
|
||||
LogDataBucketsDetail(
|
||||
"Deleted bucket misses from cache where key [{}] size before [{}] after [{}]",
|
||||
e.key_,
|
||||
size_before,
|
||||
g_data_bucket_cache.size()
|
||||
);
|
||||
}
|
||||
|
||||
void DataBucket::ClearCache()
|
||||
{
|
||||
g_data_bucket_cache.clear();
|
||||
LogInfo("Cleared data buckets cache");
|
||||
}
|
||||
|
||||
+76
-9
@@ -9,19 +9,86 @@
|
||||
#include "../common/types.h"
|
||||
#include "../common/repositories/data_buckets_repository.h"
|
||||
#include "mob.h"
|
||||
#include "../common/json/json_archive_single_line.h"
|
||||
#include "../common/servertalk.h"
|
||||
|
||||
enum DataBucketCacheUpdateAction : uint8 {
|
||||
Upsert,
|
||||
Delete
|
||||
};
|
||||
|
||||
struct DataBucketCacheEntry {
|
||||
DataBucketsRepository::DataBuckets e;
|
||||
int64_t updated_time{};
|
||||
DataBucketCacheUpdateAction update_action{};
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive &ar)
|
||||
{
|
||||
ar(
|
||||
CEREAL_NVP(e),
|
||||
CEREAL_NVP(updated_time),
|
||||
CEREAL_NVP(update_action)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
struct DataBucketKey {
|
||||
std::string key;
|
||||
std::string value;
|
||||
std::string expires;
|
||||
int64_t character_id;
|
||||
int64_t npc_id;
|
||||
int64_t bot_id;
|
||||
};
|
||||
|
||||
namespace DataBucketLoadType {
|
||||
enum Type : uint8 {
|
||||
Bot,
|
||||
Client,
|
||||
NPC,
|
||||
MaxType
|
||||
};
|
||||
|
||||
static const std::string Name[Type::MaxType] = {
|
||||
"Bot",
|
||||
"Client",
|
||||
"NPC",
|
||||
};
|
||||
}
|
||||
|
||||
class DataBucket {
|
||||
public:
|
||||
static void SetData(const std::string& bucket_key, const std::string& bucket_value, std::string expires_time = "");
|
||||
static bool DeleteData(const std::string& bucket_key);
|
||||
static std::string GetData(const std::string& bucket_key);
|
||||
static std::string GetDataExpires(const std::string& bucket_key);
|
||||
static std::string GetDataRemaining(const std::string& bucket_key);
|
||||
static bool GetDataBuckets(Mob* mob);
|
||||
static std::string CheckBucketKey(const Mob* mob, std::string_view full_name);
|
||||
// non-scoped bucket methods (for global buckets)
|
||||
static void SetData(const std::string &bucket_key, const std::string &bucket_value, std::string expires_time = "");
|
||||
static bool DeleteData(const std::string &bucket_key);
|
||||
static std::string GetData(const std::string &bucket_key);
|
||||
static std::string GetDataExpires(const std::string &bucket_key);
|
||||
static std::string GetDataRemaining(const std::string &bucket_key);
|
||||
|
||||
private:
|
||||
static uint64 DoesBucketExist(const std::string& bucket_key);
|
||||
static bool GetDataBuckets(Mob *mob);
|
||||
|
||||
static int64_t GetCurrentTimeUNIX();
|
||||
|
||||
// scoped bucket methods
|
||||
static void SetData(const DataBucketKey &k);
|
||||
static bool DeleteData(const DataBucketKey &k);
|
||||
static DataBucketsRepository::DataBuckets GetData(const DataBucketKey &k, bool ignore_misses_cache = false);
|
||||
static std::string GetDataExpires(const DataBucketKey &k);
|
||||
static std::string GetDataRemaining(const DataBucketKey &k);
|
||||
static std::string GetScopedDbFilters(const DataBucketKey &k);
|
||||
|
||||
// bucket repository versus key matching
|
||||
static bool CheckBucketMatch(const DataBucketsRepository::DataBuckets &dbe, const DataBucketKey &k);
|
||||
static bool ExistsInCache(const DataBucketsRepository::DataBuckets &e);
|
||||
|
||||
static void BulkLoadEntities(DataBucketLoadType::Type t, std::vector<uint32> ids);
|
||||
static void DeleteCachedBuckets(DataBucketLoadType::Type t, uint32 id);
|
||||
|
||||
static bool SendDataBucketCacheUpdate(const DataBucketCacheEntry &e);
|
||||
static void HandleWorldMessage(ServerPacket *p);
|
||||
static void DeleteFromMissesCache(DataBucketsRepository::DataBuckets e);
|
||||
static void ClearCache();
|
||||
};
|
||||
|
||||
#endif //EQEMU_DATABUCKET_H
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user