mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-31 13:16:39 +00:00
Compare commits
168 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fa91559a85 | |||
| ce728c4d0d | |||
| d29937cba6 | |||
| 799593c394 | |||
| b7c93e12de | |||
| c1651b7dca | |||
| 4093b505d3 | |||
| dbb0288a13 | |||
| 0a9a941b6b | |||
| 702024fe04 | |||
| acdd65b55c | |||
| 6db7c624e9 | |||
| f485dfd8d3 | |||
| 823bacf08a | |||
| b8ecb297ec | |||
| 7f7c80eab7 | |||
| 0c87af7d6b | |||
| 2e087cde5b | |||
| a7c1c85f71 | |||
| d1c7c00f19 | |||
| 999ccdcb19 | |||
| d3cd037fa7 | |||
| be42b73f5c | |||
| f76c798910 | |||
| dc1509e768 | |||
| 124b9c7abe | |||
| 534de0c414 | |||
| ae198ae043 | |||
| 520943ebf1 | |||
| 9ac306fe67 | |||
| 7a1d69d0d4 | |||
| c873fe5a22 | |||
| e06b0c4b0c | |||
| ed2130f649 | |||
| 448a33a60c | |||
| 8f86cb353e | |||
| 178129443f | |||
| a7c3b41afc | |||
| a5a568d548 | |||
| e3198edb86 | |||
| 8568cf7d49 | |||
| 1fb7a860a1 | |||
| 7eaee2649e | |||
| a17f467b98 | |||
| 3359839a9b | |||
| 7e51e629f9 | |||
| dc6c28a52d | |||
| 78aee0780a | |||
| bcd943a964 | |||
| 56608e84bd | |||
| 8d23e710ce | |||
| 4d11077b21 | |||
| 5c0bdfdc4c | |||
| 6130e10831 | |||
| c3e1c531d2 | |||
| b52719a535 | |||
| 1af252466f | |||
| 699d22fc28 | |||
| 5d1fe68906 | |||
| 52dcf35425 | |||
| a7550fbd9e | |||
| cc0171dfe1 | |||
| 913c5da70f | |||
| 40fecbfaf5 | |||
| b1646381b0 | |||
| bb1578796b | |||
| 0e5a38f072 | |||
| 39876ab858 | |||
| ff16a76481 | |||
| ffd68eb63d | |||
| 76c1da1aad | |||
| a91e03fa43 | |||
| 453106439f | |||
| 3da24fffa4 | |||
| 8d8ef6d480 | |||
| 1f9c4b3a22 | |||
| 7dfda95d86 | |||
| 40738b29e3 | |||
| 080865faa2 | |||
| e2b545991a | |||
| b7f8d0f179 | |||
| e3588781aa | |||
| e9b84f4d11 | |||
| 4f03970fd1 | |||
| 4979da6932 | |||
| 9987029791 | |||
| eece0a92e3 | |||
| 057f96796a | |||
| f475cecdb1 | |||
| 6296ed6d41 | |||
| ac0f729aa2 | |||
| 2937852cf9 | |||
| 2cf5bae571 | |||
| 2feb05be18 | |||
| 421767e1e5 | |||
| 6e9ff52dce | |||
| aa700f8960 | |||
| 2ef959c5ed | |||
| e49ab924cc | |||
| fc3c691588 | |||
| d465a3deba | |||
| 40c9c8044b | |||
| 70a96ea098 | |||
| d5cbec714e | |||
| 6903205484 | |||
| 4c81321847 | |||
| e5cea73e0c | |||
| 23308192b5 | |||
| 29fdf7e2ae | |||
| 098498dedd | |||
| b6fb8daae8 | |||
| 563f7d5564 | |||
| 1e5abc456b | |||
| 3b0fa015a7 | |||
| c73a1e8bea | |||
| 3bfdc0cf71 | |||
| a23ac4628f | |||
| 5ef4612249 | |||
| 17f66c5d60 | |||
| 51eb95ed31 | |||
| 080abaede1 | |||
| 97e332819d | |||
| 1e41c5517e | |||
| c7a88af11a | |||
| d8ddd0aab9 | |||
| 95cbadade5 | |||
| a85f4fb703 | |||
| e63f34638b | |||
| 7918fed81c | |||
| ac24c9bf5a | |||
| 7b914c731b | |||
| 7362c0ebb5 | |||
| ae213a4e4b | |||
| 187288f3aa | |||
| abc8c3d886 | |||
| 0b2493beb8 | |||
| 9cebba5911 | |||
| 4478328b2a | |||
| 55a7e1646d | |||
| b6b8491060 | |||
| 850053a136 | |||
| 1aa8758b0a | |||
| b1aa087b9f | |||
| 1e57a0372f | |||
| 9614ea59ec | |||
| 7a648cce16 | |||
| 8640776a21 | |||
| 0c45d3b09e | |||
| 59e4adb117 | |||
| d5a06bfe2e | |||
| 0f0676824c | |||
| caa647dc6b | |||
| 76b9ce0ac1 | |||
| d01d091b47 | |||
| 47ddcb54f1 | |||
| dda0e410ff | |||
| eae05167f8 | |||
| 16f21893a3 | |||
| 4ca724956b | |||
| 217a80ee76 | |||
| 8b166bf5b9 | |||
| 4c614661e7 | |||
| 9392f86333 | |||
| 0d888268a8 | |||
| b044d8533e | |||
| d810cb02c3 | |||
| 992a5cc132 | |||
| c50fda0f73 |
+241
@@ -1,3 +1,244 @@
|
|||||||
|
## [22.56.3] 9/23/2024
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Fix issue with Client::SaveDisciplines() not specifying character ID ([#4481](https://github.com/EQEmu/Server/pull/4477)) @Kinglykrab 2024-09-23
|
||||||
|
|
||||||
|
## [22.56.2] 9/20/2024
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Fix Issue with Database::ReserveName ([#4477](https://github.com/EQEmu/Server/pull/4477)) @Kinglykrab 2024-09-20
|
||||||
|
|
||||||
|
### Quest API
|
||||||
|
|
||||||
|
* Add GrantAllAAPoints() Overload To Perl/Lua ([#4474](https://github.com/EQEmu/Server/pull/4474)) @Kinglykrab 2024-09-20
|
||||||
|
|
||||||
|
## [22.56.1] 9/20/2024
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Fix Untrained Disciplines in Client::SaveDisciplines() ([#4472](https://github.com/EQEmu/Server/pull/4472)) @Kinglykrab 2024-09-13
|
||||||
|
* Fix Infinite Loop in Adventure::Finished() ([#4473](https://github.com/EQEmu/Server/pull/4473)) @oddx2k 2024-09-13
|
||||||
|
|
||||||
|
## [22.56.0] 9/12/2024
|
||||||
|
|
||||||
|
### Code
|
||||||
|
|
||||||
|
* Add IsCloseToBanker method ([#4462](https://github.com/EQEmu/Server/pull/4462)) @Akkadius 2024-08-27
|
||||||
|
|
||||||
|
### Feature
|
||||||
|
|
||||||
|
* Add Rule to Limit Task Update Messages ([#4459](https://github.com/EQEmu/Server/pull/4459)) @Kinglykrab 2024-08-28
|
||||||
|
* Allow NPCs to cast Sacrifice ([#4470](https://github.com/EQEmu/Server/pull/4470)) @fuzzlecutter 2024-09-12
|
||||||
|
* Lazy Load Bank Contents ([#4453](https://github.com/EQEmu/Server/pull/4453)) @catapultam-habeo 2024-08-27
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Add RULE_STRING to RuleManager::ResetRules ([#4467](https://github.com/EQEmu/Server/pull/4467)) @Kinglykrab 2024-09-07
|
||||||
|
* Fix Bard Effect in Migration 9237 ([#4468](https://github.com/EQEmu/Server/pull/4468)) @Kinglykrab 2024-09-09
|
||||||
|
* ModernAAScalingEnabled() Calculation Error ([#4469](https://github.com/EQEmu/Server/pull/4469)) @carolus21rex 2024-09-11
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
|
||||||
|
* Move Discipline Loading to Client::CompleteConnect() ([#4466](https://github.com/EQEmu/Server/pull/4466)) @Kinglykrab 2024-09-09
|
||||||
|
|
||||||
|
### Rules
|
||||||
|
|
||||||
|
* Add a Bandolier Swap Delay Rule ([#4465](https://github.com/EQEmu/Server/pull/4465)) @Kinglykrab 2024-09-08
|
||||||
|
|
||||||
|
## [22.55.1] 8/26/2024
|
||||||
|
|
||||||
|
### Code
|
||||||
|
|
||||||
|
* Remove unused methods ([#4449](https://github.com/EQEmu/Server/pull/4449)) @Kinglykrab 2024-08-22
|
||||||
|
|
||||||
|
### Feature
|
||||||
|
|
||||||
|
* Add Character:DefaultGuildRank Rule ([#4438](https://github.com/EQEmu/Server/pull/4438)) @Kinglykrab 2024-08-04
|
||||||
|
* Add Optional Return to EVENT_DAMAGE_TAKEN ([#4454](https://github.com/EQEmu/Server/pull/4454)) @Kinglykrab 2024-08-27
|
||||||
|
* Extend Spell Buckets Functionality ([#4441](https://github.com/EQEmu/Server/pull/4441)) @Kinglykrab 2024-08-22
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Apply Race & Class restrictions to Auto-Combines ([#4452](https://github.com/EQEmu/Server/pull/4452)) @catapultam-habeo 2024-08-20
|
||||||
|
* Attune Augments when Equipped ([#4446](https://github.com/EQEmu/Server/pull/4446)) @fryguy503 2024-08-10
|
||||||
|
* Correct missed maxlevel reference in exp.cpp ([#4463](https://github.com/EQEmu/Server/pull/4463)) @N0ctrnl 2024-08-27
|
||||||
|
* Ensure close of Tribute Item search ([#4439](https://github.com/EQEmu/Server/pull/4439)) @joligario 2024-08-04
|
||||||
|
* Fix AddCrystals() in Perl/Lua ([#4445](https://github.com/EQEmu/Server/pull/4445)) @Kinglykrab 2024-08-10
|
||||||
|
* Fix Bot Spell Entries IDs Capping at 32,767 ([#4444](https://github.com/EQEmu/Server/pull/4444)) @Kinglykrab 2024-08-27
|
||||||
|
* Fix Character ID of 0 being inserted into character_stats_record ([#4458](https://github.com/EQEmu/Server/pull/4458)) @Kinglykrab 2024-08-22
|
||||||
|
* Fix Issue with Removed #setfaction Command ([#4448](https://github.com/EQEmu/Server/pull/4448)) @Kinglykrab 2024-08-11
|
||||||
|
* Fix Lua Client FilteredMessage ([#4437](https://github.com/EQEmu/Server/pull/4437)) @Kinglykrab 2024-07-31
|
||||||
|
* Fix client hotbar exchanging items when zoning ([#4460](https://github.com/EQEmu/Server/pull/4460)) @neckkola 2024-08-27
|
||||||
|
* Fix issue with killed mob coordinates ([#4457](https://github.com/EQEmu/Server/pull/4457)) @Kinglykrab 2024-08-22
|
||||||
|
* Imitate Death should also clear zone feign aggro ([#4436](https://github.com/EQEmu/Server/pull/4436)) @fryguy503 2024-07-31
|
||||||
|
* client_max_level allow leveling to end of level ([#4455](https://github.com/EQEmu/Server/pull/4455)) @fryguy503 2024-08-20
|
||||||
|
|
||||||
|
### Improvement
|
||||||
|
|
||||||
|
* Filtered Messages Extension ([#4435](https://github.com/EQEmu/Server/pull/4435)) @fryguy503 2024-07-31
|
||||||
|
|
||||||
|
### Quest API
|
||||||
|
|
||||||
|
* Add AreTasksCompleted() to Perl/Lua. ([#4456](https://github.com/EQEmu/Server/pull/4456)) @Kinglykrab 2024-08-23
|
||||||
|
* Add Area-Based Quest Methods to Perl/Lua ([#4447](https://github.com/EQEmu/Server/pull/4447)) @Kinglykrab 2024-08-27
|
||||||
|
* Add Several Door Methods to Perl/Lua ([#4451](https://github.com/EQEmu/Server/pull/4451)) @Kinglykrab 2024-08-16
|
||||||
|
|
||||||
|
### World
|
||||||
|
|
||||||
|
* Fix slow world bootup bug ([#4461](https://github.com/EQEmu/Server/pull/4461)) @Akkadius 2024-08-27
|
||||||
|
|
||||||
|
## [22.54.0] 7/30/2024
|
||||||
|
|
||||||
|
### Code
|
||||||
|
|
||||||
|
* Cleanup Client File Exporting ([#4348](https://github.com/EQEmu/Server/pull/4348)) @Kinglykrab 2024-07-31
|
||||||
|
* Cleanup Stance Code ([#4368](https://github.com/EQEmu/Server/pull/4368)) @Kinglykrab 2024-07-03
|
||||||
|
* Mask GM Show Buff message behind EntityVariable ([#4419](https://github.com/EQEmu/Server/pull/4419)) @nytmyr 2024-07-22
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
* Extend #devtools Functionality ([#4425](https://github.com/EQEmu/Server/pull/4425)) @Kinglykrab 2024-07-23
|
||||||
|
|
||||||
|
### Databuckets
|
||||||
|
|
||||||
|
* Remove memory reserve from bulk load ([#4427](https://github.com/EQEmu/Server/pull/4427)) @Akkadius 2024-07-23
|
||||||
|
|
||||||
|
### Feature
|
||||||
|
|
||||||
|
* Add Barter/Buyer Features ([#4405](https://github.com/EQEmu/Server/pull/4405)) @neckkola 2024-07-30
|
||||||
|
* Add Parcel notification for online players when using the Quest API ([#4418](https://github.com/EQEmu/Server/pull/4418)) @neckkola 2024-07-22
|
||||||
|
* Implement Move Multiple Items ([#4259](https://github.com/EQEmu/Server/pull/4259)) @catapultam-habeo 2024-07-30
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Aegolism Spell line stacking ([#4399](https://github.com/EQEmu/Server/pull/4399)) @KayenEQ 2024-07-07
|
||||||
|
* AllowRaidTargetBlind logic backwards ([#4400](https://github.com/EQEmu/Server/pull/4400)) @fryguy503 2024-07-01
|
||||||
|
* AutoSplit unknown bug and cleanup. ([#4401](https://github.com/EQEmu/Server/pull/4401)) @fryguy503 2024-07-07
|
||||||
|
* Corpse Call removing Resurrection Effects ([#4410](https://github.com/EQEmu/Server/pull/4410)) @fryguy503 2024-07-22
|
||||||
|
* Fix #parcels add subcommand ([#4431](https://github.com/EQEmu/Server/pull/4431)) @neckkola 2024-07-29
|
||||||
|
* Fix #setlevel Allowing Skills Above Max ([#4423](https://github.com/EQEmu/Server/pull/4423)) @Kinglykrab 2024-07-23
|
||||||
|
* Fix Bot::SetBotStance ([#4426](https://github.com/EQEmu/Server/pull/4426)) @Kinglykrab 2024-07-23
|
||||||
|
* Fix Client::RemoveTitle ([#4421](https://github.com/EQEmu/Server/pull/4421)) @Kinglykrab 2024-07-23
|
||||||
|
* Fix EVENT_USE_SKILL with Sense Heading ([#4424](https://github.com/EQEmu/Server/pull/4424)) @Kinglykrab 2024-07-23
|
||||||
|
* Fix for random disconnects when a large number of guild members zone or disconnect ([#4402](https://github.com/EQEmu/Server/pull/4402)) @neckkola 2024-07-10
|
||||||
|
* Fix issue with quest::echo and quest::me ([#4433](https://github.com/EQEmu/Server/pull/4433)) @Kinglykrab 2024-07-30
|
||||||
|
* Personal tributes for bard items were not applying correctly ([#4416](https://github.com/EQEmu/Server/pull/4416)) @neckkola 2024-07-16
|
||||||
|
* Potential fix for some undesired ranged explotative behavior. ([#4413](https://github.com/EQEmu/Server/pull/4413)) @fryguy503 2024-07-22
|
||||||
|
* Proximity Aggro for Frustrated and Undead ([#4411](https://github.com/EQEmu/Server/pull/4411)) @fryguy503 2024-07-22
|
||||||
|
* Slay Adjustments ([#4389](https://github.com/EQEmu/Server/pull/4389)) @fryguy503 2024-07-07
|
||||||
|
* Stop DOSing ourselves with OP_WearChange ([#4432](https://github.com/EQEmu/Server/pull/4432)) @catapultam-habeo 2024-07-30
|
||||||
|
* [Quest API] Fix getraididbycharid and getgroupidbycharid ([#4417](https://github.com/EQEmu/Server/pull/4417)) @nytmyr 2024-07-16
|
||||||
|
|
||||||
|
### Improvement
|
||||||
|
|
||||||
|
* Flee Overhaul ([#4407](https://github.com/EQEmu/Server/pull/4407)) @fryguy503 2024-07-30
|
||||||
|
|
||||||
|
### Rules
|
||||||
|
|
||||||
|
* Add HasteCap and Hastev3Cap rules for NPCs, Bots and Mercs ([#4406](https://github.com/EQEmu/Server/pull/4406)) @nytmyr 2024-07-22
|
||||||
|
|
||||||
|
### Zone Instances
|
||||||
|
|
||||||
|
* Revert " Handle routing to instances when using evac/succor " (#4429) ([#4297](https://github.com/EQEmu/Server/pull/4297)) @Akkadius 2024-07-30
|
||||||
|
|
||||||
|
### Zoning
|
||||||
|
|
||||||
|
* Improve zone routing ([#4428](https://github.com/EQEmu/Server/pull/4428)) @Akkadius 2024-07-30
|
||||||
|
|
||||||
|
## [22.53.1] 6/16/2024
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Fix trader mode ([#4397](https://github.com/EQEmu/Server/pull/4397)) @joligario 2024-06-17
|
||||||
|
|
||||||
|
## [22.53.0] 6/14/2024
|
||||||
|
|
||||||
|
### Bug
|
||||||
|
|
||||||
|
* Anon players should not show in /who all ([#4392](https://github.com/EQEmu/Server/pull/4392)) @fryguy503 2024-06-14
|
||||||
|
* Escape should put player into SOS if owned. ([#4388](https://github.com/EQEmu/Server/pull/4388)) @fryguy503 2024-06-07
|
||||||
|
* Prevent Resurrection Spells from being resisted ([#4393](https://github.com/EQEmu/Server/pull/4393)) @fryguy503 2024-06-14
|
||||||
|
|
||||||
|
### Code
|
||||||
|
|
||||||
|
* Cleanup Account Status Code ([#4376](https://github.com/EQEmu/Server/pull/4376)) @Kinglykrab 2024-06-02
|
||||||
|
* Cleanup Body Type Code ([#4366](https://github.com/EQEmu/Server/pull/4366)) @Kinglykrab 2024-06-02
|
||||||
|
* Cleanup Object Type Code ([#4375](https://github.com/EQEmu/Server/pull/4375)) @Kinglykrab 2024-06-14
|
||||||
|
* Remove unused code in emu_constants.h ([#4384](https://github.com/EQEmu/Server/pull/4384)) @Kinglykrab 2024-06-14
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Fix #goto Target ([#4382](https://github.com/EQEmu/Server/pull/4382)) @Kinglykrab 2024-06-03
|
||||||
|
* Fix Swarm Pet Damage Messages ([#4383](https://github.com/EQEmu/Server/pull/4383)) @Kinglykrab 2024-06-04
|
||||||
|
* Fix for players having empty bazaar window dropdown list, even though trader is tagged as a trader. ([#4391](https://github.com/EQEmu/Server/pull/4391)) @neckkola 2024-06-14
|
||||||
|
* Fix potential trader crash when serialized item not found ([#4386](https://github.com/EQEmu/Server/pull/4386)) @joligario 2024-06-14
|
||||||
|
|
||||||
|
### Rules
|
||||||
|
|
||||||
|
* Add Invisible Augment Rules ([#4385](https://github.com/EQEmu/Server/pull/4385)) @Kinglykrab 2024-06-14
|
||||||
|
* Classic Harm Touch Formula ([#4394](https://github.com/EQEmu/Server/pull/4394)) @fryguy503 2024-06-14
|
||||||
|
* Mend/Sneak allow success tuning ([#4390](https://github.com/EQEmu/Server/pull/4390)) @fryguy503 2024-06-14
|
||||||
|
* Snare Override Movement Bonus ([#4381](https://github.com/EQEmu/Server/pull/4381)) @fryguy503 2024-06-02
|
||||||
|
|
||||||
|
## [22.52.0] 6/1/2024
|
||||||
|
|
||||||
|
### Code
|
||||||
|
|
||||||
|
* Cleanup Bucket Comparison Code ([#4374](https://github.com/EQEmu/Server/pull/4374)) @Kinglykrab 2024-06-02
|
||||||
|
* Cleanup Bug Category Code ([#4367](https://github.com/EQEmu/Server/pull/4367)) @Kinglykrab 2024-06-01
|
||||||
|
* Cleanup Deity Code ([#4363](https://github.com/EQEmu/Server/pull/4363)) @Kinglykrab 2024-06-01
|
||||||
|
* Cleanup Special Ability Code ([#4365](https://github.com/EQEmu/Server/pull/4365)) @Kinglykrab 2024-06-01
|
||||||
|
* Remove unused code in common/eq_constants.h ([#4364](https://github.com/EQEmu/Server/pull/4364)) @Kinglykrab 2024-06-01
|
||||||
|
|
||||||
|
### Combat
|
||||||
|
|
||||||
|
* Adjustments to Crippling Blows/Slay Undead and Confirmed Critical Code ([#4354](https://github.com/EQEmu/Server/pull/4354)) @fryguy503 2024-05-27
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Add protection to ensure adventure points award are only attempted on players ([#4371](https://github.com/EQEmu/Server/pull/4371)) @joligario 2024-05-31
|
||||||
|
* Adjust Kick/RoundKick Damage Lower levels ([#4355](https://github.com/EQEmu/Server/pull/4355)) @fryguy503 2024-05-28
|
||||||
|
* Bazaar Search not working correctly for Iksar, Vashir, Drakkin and Froglok races ([#4379](https://github.com/EQEmu/Server/pull/4379)) @neckkola 2024-06-02
|
||||||
|
* Fix Unescaped String in Client::GotoPlayer ([#4373](https://github.com/EQEmu/Server/pull/4373)) @Kinglykrab 2024-06-01
|
||||||
|
|
||||||
|
### NPC Spells
|
||||||
|
|
||||||
|
* Fixed an issue where the repository spell adj value was overriding the spell difficulty default value ([#4370](https://github.com/EQEmu/Server/pull/4370)) @regneq 2024-06-01
|
||||||
|
|
||||||
|
### Quest API
|
||||||
|
|
||||||
|
* Add Item Link Methods to Perl/Lua ([#4359](https://github.com/EQEmu/Server/pull/4359)) @Kinglykrab 2024-06-01
|
||||||
|
|
||||||
|
### Quests
|
||||||
|
|
||||||
|
* Fix Lua encounter double register ([#4369](https://github.com/EQEmu/Server/pull/4369)) @Akkadius 2024-05-31
|
||||||
|
* Fix issue with Lua encounters loading in certain circumstances ([#4378](https://github.com/EQEmu/Server/pull/4378)) @Akkadius 2024-06-01
|
||||||
|
|
||||||
|
### Rules
|
||||||
|
|
||||||
|
* Add Skill Base Damage Rules ([#4360](https://github.com/EQEmu/Server/pull/4360)) @Kinglykrab 2024-06-01
|
||||||
|
|
||||||
|
### Skills
|
||||||
|
|
||||||
|
* Fix caps out of bounds issue ([#4377](https://github.com/EQEmu/Server/pull/4377)) @Akkadius 2024-06-01
|
||||||
|
|
||||||
|
## [22.51.1] 5/27/2024
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Adjust return for perl release check @Akkadius 2024-05-26
|
||||||
|
* Corrected issue with bazaar purchase via parcels where an incorrect quantity would be calculated. ([#4352](https://github.com/EQEmu/Server/pull/4352)) @neckkola 2024-05-27
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
|
||||||
|
* Improve SkillCaps::GetTrainLevel() Efficiency ([#4350](https://github.com/EQEmu/Server/pull/4350)) @Kinglykrab 2024-05-26
|
||||||
|
|
||||||
|
### Rules
|
||||||
|
|
||||||
|
* Legacy Compute Defense against modern agi based defense. ([#4349](https://github.com/EQEmu/Server/pull/4349)) @fryguy503 2024-05-27
|
||||||
|
|
||||||
## [22.51.0] 5/26/2024
|
## [22.51.0] 5/26/2024
|
||||||
|
|
||||||
### Commands
|
### Commands
|
||||||
|
|||||||
+39
-140
@@ -29,9 +29,13 @@
|
|||||||
#include "../../common/content/world_content_service.h"
|
#include "../../common/content/world_content_service.h"
|
||||||
#include "../../common/zone_store.h"
|
#include "../../common/zone_store.h"
|
||||||
#include "../../common/path_manager.h"
|
#include "../../common/path_manager.h"
|
||||||
|
#include "../../common/repositories/base_data_repository.h"
|
||||||
|
#include "../../common/repositories/db_str_repository.h"
|
||||||
#include "../../common/repositories/skill_caps_repository.h"
|
#include "../../common/repositories/skill_caps_repository.h"
|
||||||
|
#include "../../common/repositories/spells_new_repository.h"
|
||||||
#include "../../common/file.h"
|
#include "../../common/file.h"
|
||||||
#include "../../common/events/player_event_logs.h"
|
#include "../../common/events/player_event_logs.h"
|
||||||
|
#include "../../common/skill_caps.h"
|
||||||
|
|
||||||
EQEmuLogSys LogSys;
|
EQEmuLogSys LogSys;
|
||||||
WorldContentService content_service;
|
WorldContentService content_service;
|
||||||
@@ -98,25 +102,22 @@ int main(int argc, char **argv)
|
|||||||
->LoadLogDatabaseSettings()
|
->LoadLogDatabaseSettings()
|
||||||
->StartFileLogs();
|
->StartFileLogs();
|
||||||
|
|
||||||
std::string arg_1;
|
std::string export_type;
|
||||||
|
|
||||||
if (argv[1]) {
|
if (argv[1]) {
|
||||||
arg_1 = argv[1];
|
export_type = argv[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg_1 == "spells") {
|
if (Strings::EqualFold(export_type, "spells")) {
|
||||||
ExportSpells(&content_db);
|
ExportSpells(&content_db);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} else if (Strings::EqualFold(export_type, "skills")) {
|
||||||
if (arg_1 == "skills") {
|
|
||||||
ExportSkillCaps(&content_db);
|
ExportSkillCaps(&content_db);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} else if (Strings::EqualFold(export_type, "basedata") || Strings::EqualFold(export_type, "base_data")) {
|
||||||
if (arg_1 == "basedata") {
|
|
||||||
ExportBaseData(&content_db);
|
ExportBaseData(&content_db);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} else if (Strings::EqualFold(export_type, "dbstr") || Strings::EqualFold(export_type, "dbstring")) {
|
||||||
if (arg_1 == "dbstring") {
|
|
||||||
ExportDBStrings(&database);
|
ExportDBStrings(&database);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -131,181 +132,79 @@ int main(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportSpells(SharedDatabase *db)
|
void ExportSpells(SharedDatabase* db)
|
||||||
{
|
{
|
||||||
LogInfo("Exporting Spells");
|
std::ofstream file(fmt::format("{}/export/spells_us.txt", path.GetServerPath()));
|
||||||
|
if (!file || !file.is_open()) {
|
||||||
std::string file = fmt::format("{}/export/spells_us.txt", path.GetServerPath());
|
|
||||||
FILE *f = fopen(file.c_str(), "w");
|
|
||||||
if (!f) {
|
|
||||||
LogError("Unable to open export/spells_us.txt to write, skipping.");
|
LogError("Unable to open export/spells_us.txt to write, skipping.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string query = "SELECT * FROM spells_new ORDER BY id";
|
const auto& lines = SpellsNewRepository::GetSpellFileLines(*db);
|
||||||
auto results = db->QueryDatabase(query);
|
|
||||||
|
|
||||||
if (results.Success()) {
|
const std::string& file_string = Strings::Implode("\n", lines);
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
|
||||||
std::string line;
|
|
||||||
unsigned int fields = results.ColumnCount();
|
|
||||||
for (unsigned int i = 0; i < fields; ++i) {
|
|
||||||
if (i != 0) {
|
|
||||||
line.push_back('^');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row[i] != nullptr) {
|
file << file_string;
|
||||||
line += row[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(f, "%s\n", line.c_str());
|
file.close();
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(f);
|
LogInfo("Exported [{}] Spell{}", lines.size(), lines.size() != 1 ? "s" : "");
|
||||||
}
|
|
||||||
|
|
||||||
bool SkillUsable(SharedDatabase* db, int skill_id, int class_id)
|
|
||||||
{
|
|
||||||
const auto& l = SkillCapsRepository::GetWhere(
|
|
||||||
*db,
|
|
||||||
fmt::format(
|
|
||||||
"`class_id` = {} AND `skill_id` = {} ORDER BY `cap` DESC LIMIT 1",
|
|
||||||
class_id,
|
|
||||||
skill_id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return !l.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 GetSkill(SharedDatabase* db, int skill_id, int class_id, int level)
|
|
||||||
{
|
|
||||||
const auto& l = SkillCapsRepository::GetWhere(
|
|
||||||
*db,
|
|
||||||
fmt::format(
|
|
||||||
"`class_id` = {} AND `skill_id` = {} AND `level` = {}",
|
|
||||||
class_id,
|
|
||||||
skill_id,
|
|
||||||
level
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (l.empty()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto e = l.front();
|
|
||||||
|
|
||||||
return e.cap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportSkillCaps(SharedDatabase* db)
|
void ExportSkillCaps(SharedDatabase* db)
|
||||||
{
|
{
|
||||||
LogInfo("Exporting Skill Caps");
|
|
||||||
|
|
||||||
std::ofstream file(fmt::format("{}/export/SkillCaps.txt", path.GetServerPath()));
|
std::ofstream file(fmt::format("{}/export/SkillCaps.txt", path.GetServerPath()));
|
||||||
if (!file || !file.is_open()) {
|
if (!file || !file.is_open()) {
|
||||||
LogError("Unable to open export/SkillCaps.txt to write, skipping.");
|
LogError("Unable to open export/SkillCaps.txt to write, skipping.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8 skill_cap_max_level = (
|
const auto& lines = SkillCapsRepository::GetSkillCapFileLines(*db);
|
||||||
RuleI(Character, SkillCapMaxLevel) > 0 ?
|
|
||||||
RuleI(Character, SkillCapMaxLevel) :
|
|
||||||
RuleI(Character, MaxLevel)
|
|
||||||
);
|
|
||||||
|
|
||||||
for (uint8 class_id = Class::Warrior; class_id <= Class::Berserker; class_id++) {
|
const std::string& file_string = Strings::Implode("\n", lines);
|
||||||
for (uint8 skill_id = EQ::skills::Skill1HBlunt; skill_id <= EQ::skills::Skill2HPiercing; skill_id++) {
|
|
||||||
if (SkillUsable(db, skill_id, class_id)) {
|
|
||||||
uint32 previous_cap = 0;
|
|
||||||
for (uint8 level = 1; level <= skill_cap_max_level; level++) {
|
|
||||||
uint32 cap = GetSkill(db, skill_id, class_id, level);
|
|
||||||
if (cap < previous_cap) {
|
|
||||||
cap = previous_cap;
|
|
||||||
}
|
|
||||||
|
|
||||||
file << fmt::format("{}^{}^{}^{}^0", class_id, skill_id, level, cap) << std::endl;
|
file << file_string;
|
||||||
|
|
||||||
previous_cap = cap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
|
LogInfo("Exported [{}] Skill Cap{}", lines.size(), lines.size() != 1 ? "s" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportBaseData(SharedDatabase *db)
|
void ExportBaseData(SharedDatabase *db)
|
||||||
{
|
{
|
||||||
LogInfo("Exporting Base Data");
|
std::ofstream file(fmt::format("{}/export/BaseData.txt", path.GetServerPath()));
|
||||||
|
if (!file || !file.is_open()) {
|
||||||
std::string file = fmt::format("{}/export/BaseData.txt", path.GetServerPath());
|
|
||||||
FILE *f = fopen(file.c_str(), "w");
|
|
||||||
if (!f) {
|
|
||||||
LogError("Unable to open export/BaseData.txt to write, skipping.");
|
LogError("Unable to open export/BaseData.txt to write, skipping.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string query = "SELECT * FROM base_data ORDER BY level, class";
|
const auto& lines = BaseDataRepository::GetBaseDataFileLines(*db);
|
||||||
auto results = db->QueryDatabase(query);
|
|
||||||
if (results.Success()) {
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
|
||||||
std::string line;
|
|
||||||
unsigned int fields = results.ColumnCount();
|
|
||||||
for (unsigned int rowIndex = 0; rowIndex < fields; ++rowIndex) {
|
|
||||||
if (rowIndex != 0) {
|
|
||||||
line.push_back('^');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row[rowIndex] != nullptr) {
|
const std::string& file_string = Strings::Implode("\n", lines);
|
||||||
line += row[rowIndex];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(f, "%s\n", line.c_str());
|
file << file_string;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(f);
|
file.close();
|
||||||
|
|
||||||
|
LogInfo("Exported [{}] Base Data Entr{}", lines.size(), lines.size() != 1 ? "ies" : "y");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportDBStrings(SharedDatabase *db)
|
void ExportDBStrings(SharedDatabase *db)
|
||||||
{
|
{
|
||||||
LogInfo("Exporting DB Strings");
|
std::ofstream file(fmt::format("{}/export/dbstr_us.txt", path.GetServerPath()));
|
||||||
|
if (!file || !file.is_open()) {
|
||||||
std::string file = fmt::format("{}/export/dbstr_us.txt", path.GetServerPath());
|
|
||||||
FILE *f = fopen(file.c_str(), "w");
|
|
||||||
if (!f) {
|
|
||||||
LogError("Unable to open export/dbstr_us.txt to write, skipping.");
|
LogError("Unable to open export/dbstr_us.txt to write, skipping.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(f, "Major^Minor^String(New)\n");
|
const auto& lines = DbStrRepository::GetDBStrFileLines(*db);
|
||||||
const std::string query = "SELECT * FROM db_str ORDER BY id, type";
|
|
||||||
auto results = db->QueryDatabase(query);
|
|
||||||
if (results.Success()) {
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
|
||||||
std::string line;
|
|
||||||
unsigned int fields = results.ColumnCount();
|
|
||||||
for (unsigned int rowIndex = 0; rowIndex < fields; ++rowIndex) {
|
|
||||||
if (rowIndex != 0) {
|
|
||||||
line.push_back('^');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row[rowIndex] != nullptr) {
|
const std::string& file_string = Strings::Implode("\n", lines);
|
||||||
line += row[rowIndex];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(f, "%s\n", line.c_str());
|
file << file_string;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(f);
|
file.close();
|
||||||
|
|
||||||
|
LogInfo("Exported [{}] Database String{}", lines.size(), lines.size() != 1 ? "s" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-2
@@ -3,6 +3,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
|
|||||||
SET(common_sources
|
SET(common_sources
|
||||||
base_packet.cpp
|
base_packet.cpp
|
||||||
bazaar.cpp
|
bazaar.cpp
|
||||||
|
bodytypes.cpp
|
||||||
classes.cpp
|
classes.cpp
|
||||||
cli/eqemu_command_handler.cpp
|
cli/eqemu_command_handler.cpp
|
||||||
compression.cpp
|
compression.cpp
|
||||||
@@ -110,6 +111,8 @@ SET(common_sources
|
|||||||
net/websocket_server.cpp
|
net/websocket_server.cpp
|
||||||
net/websocket_server_connection.cpp
|
net/websocket_server_connection.cpp
|
||||||
patches/patches.cpp
|
patches/patches.cpp
|
||||||
|
patches/larion.cpp
|
||||||
|
patches/larion_limits.cpp
|
||||||
patches/sod.cpp
|
patches/sod.cpp
|
||||||
patches/sod_limits.cpp
|
patches/sod_limits.cpp
|
||||||
patches/sof.cpp
|
patches/sof.cpp
|
||||||
@@ -157,6 +160,7 @@ SET(repositories
|
|||||||
repositories/base/base_bugs_repository.h
|
repositories/base/base_bugs_repository.h
|
||||||
repositories/base/base_bug_reports_repository.h
|
repositories/base/base_bug_reports_repository.h
|
||||||
repositories/base/base_buyer_repository.h
|
repositories/base/base_buyer_repository.h
|
||||||
|
repositories/base/base_buyer_trade_items_repository.h
|
||||||
repositories/base/base_character_activities_repository.h
|
repositories/base/base_character_activities_repository.h
|
||||||
repositories/base/base_character_alternate_abilities_repository.h
|
repositories/base/base_character_alternate_abilities_repository.h
|
||||||
repositories/base/base_character_alt_currency_repository.h
|
repositories/base/base_character_alt_currency_repository.h
|
||||||
@@ -338,7 +342,8 @@ SET(repositories
|
|||||||
repositories/books_repository.h
|
repositories/books_repository.h
|
||||||
repositories/bugs_repository.h
|
repositories/bugs_repository.h
|
||||||
repositories/bug_reports_repository.h
|
repositories/bug_reports_repository.h
|
||||||
repositories/buyer_repository.h
|
repositories/buyer_buy_lines_repository.h
|
||||||
|
repositories/buyer_trade_items_repository.h
|
||||||
repositories/character_activities_repository.h
|
repositories/character_activities_repository.h
|
||||||
repositories/character_alternate_abilities_repository.h
|
repositories/character_alternate_abilities_repository.h
|
||||||
repositories/character_alt_currency_repository.h
|
repositories/character_alt_currency_repository.h
|
||||||
@@ -650,7 +655,11 @@ SET(common_headers
|
|||||||
net/websocket_server.h
|
net/websocket_server.h
|
||||||
net/websocket_server_connection.h
|
net/websocket_server_connection.h
|
||||||
patches/patches.h
|
patches/patches.h
|
||||||
patches/sod.h
|
patches/larion.h
|
||||||
|
patches/larion_limits.h
|
||||||
|
patches/larion_ops.h
|
||||||
|
patches/larion_structs.h
|
||||||
|
patches/sod.h
|
||||||
patches/sod_limits.h
|
patches/sod_limits.h
|
||||||
patches/sod_ops.h
|
patches/sod_ops.h
|
||||||
patches/sod_structs.h
|
patches/sod_structs.h
|
||||||
@@ -736,6 +745,10 @@ SOURCE_GROUP(Net FILES
|
|||||||
|
|
||||||
SOURCE_GROUP(Patches FILES
|
SOURCE_GROUP(Patches FILES
|
||||||
patches/patches.h
|
patches/patches.h
|
||||||
|
patches/larion.h
|
||||||
|
patches/larion_limits.h
|
||||||
|
patches/larion_ops.h
|
||||||
|
patches/larion_structs.h
|
||||||
patches/sod.h
|
patches/sod.h
|
||||||
patches/sod_limits.h
|
patches/sod_limits.h
|
||||||
patches/sod_ops.h
|
patches/sod_ops.h
|
||||||
@@ -764,6 +777,8 @@ SOURCE_GROUP(Patches FILES
|
|||||||
patches/uf_ops.h
|
patches/uf_ops.h
|
||||||
patches/uf_structs.h
|
patches/uf_structs.h
|
||||||
patches/patches.cpp
|
patches/patches.cpp
|
||||||
|
patches/larion.cpp
|
||||||
|
patches/larion_limits.cpp
|
||||||
patches/sod.cpp
|
patches/sod.cpp
|
||||||
patches/sod_limits.cpp
|
patches/sod_limits.cpp
|
||||||
patches/sof.cpp
|
patches/sof.cpp
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ public:
|
|||||||
void WriteUInt8(uint8 value) { *(uint8 *)(pBuffer + _wpos) = value; _wpos += sizeof(uint8); }
|
void WriteUInt8(uint8 value) { *(uint8 *)(pBuffer + _wpos) = value; _wpos += sizeof(uint8); }
|
||||||
void WriteUInt32(uint32 value) { *(uint32 *)(pBuffer + _wpos) = value; _wpos += sizeof(uint32); }
|
void WriteUInt32(uint32 value) { *(uint32 *)(pBuffer + _wpos) = value; _wpos += sizeof(uint32); }
|
||||||
void WriteUInt64(uint64 value) { *(uint64 *)(pBuffer + _wpos) = value; _wpos += sizeof(uint64); }
|
void WriteUInt64(uint64 value) { *(uint64 *)(pBuffer + _wpos) = value; _wpos += sizeof(uint64); }
|
||||||
|
void WriteSInt16(int32 value) { *(int16*)(pBuffer + _wpos) = value; _wpos += sizeof(int16); }
|
||||||
void WriteUInt16(uint32 value) { *(uint16 *)(pBuffer + _wpos) = value; _wpos += sizeof(uint16); }
|
void WriteUInt16(uint32 value) { *(uint16 *)(pBuffer + _wpos) = value; _wpos += sizeof(uint16); }
|
||||||
void WriteSInt32(int32 value) { *(int32 *)(pBuffer + _wpos) = value; _wpos += sizeof(int32); }
|
void WriteSInt32(int32 value) { *(int32 *)(pBuffer + _wpos) = value; _wpos += sizeof(int32); }
|
||||||
void WriteFloat(float value) { *(float *)(pBuffer + _wpos) = value; _wpos += sizeof(float); }
|
void WriteFloat(float value) { *(float *)(pBuffer + _wpos) = value; _wpos += sizeof(float); }
|
||||||
|
|||||||
+2
-2
@@ -47,7 +47,7 @@ Bazaar::GetSearchResults(
|
|||||||
search_criteria_trader.append(fmt::format(" AND trader.char_id = {}", search.trader_id));
|
search_criteria_trader.append(fmt::format(" AND trader.char_id = {}", search.trader_id));
|
||||||
}
|
}
|
||||||
if (search.min_cost != 0) {
|
if (search.min_cost != 0) {
|
||||||
search_criteria_trader.append(fmt::format(" AND trader.item_cost >= {}", search.min_cost));
|
search_criteria_trader.append(fmt::format(" AND trader.item_cost >= {}", search.min_cost * 1000));
|
||||||
}
|
}
|
||||||
if (search.max_cost != 0) {
|
if (search.max_cost != 0) {
|
||||||
search_criteria_trader.append(fmt::format(" AND trader.item_cost <= {}", (uint64) search.max_cost * 1000));
|
search_criteria_trader.append(fmt::format(" AND trader.item_cost <= {}", (uint64) search.max_cost * 1000));
|
||||||
@@ -314,7 +314,7 @@ Bazaar::GetSearchResults(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
.should_check = search.race != 0xFFFFFFFF,
|
.should_check = search.race != 0xFFFFFFFF,
|
||||||
.condition = static_cast<bool>(item->Races & GetPlayerRaceBit(search.race))
|
.condition = static_cast<bool>(item->Races & GetPlayerRaceBit(GetRaceIDFromPlayerRaceValue(search.race)))
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.should_check = search.augment != 0,
|
.should_check = search.augment != 0,
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#include "../common/global_define.h"
|
||||||
|
#include "../common/bodytypes.h"
|
||||||
|
|
||||||
|
std::string BodyType::GetName(uint8 body_type_id)
|
||||||
|
{
|
||||||
|
return IsValid(body_type_id) ? body_type_names[body_type_id] : "UNKNOWN BODY TYPE";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BodyType::IsValid(uint8 body_type_id)
|
||||||
|
{
|
||||||
|
return body_type_names.find(body_type_id) != body_type_names.end();
|
||||||
|
}
|
||||||
+90
-46
@@ -18,52 +18,96 @@
|
|||||||
#ifndef BODYTYPES_H
|
#ifndef BODYTYPES_H
|
||||||
#define BODYTYPES_H
|
#define BODYTYPES_H
|
||||||
|
|
||||||
typedef enum {
|
#include "types.h"
|
||||||
BT_Humanoid = 1,
|
#include <map>
|
||||||
BT_Lycanthrope = 2,
|
#include <string>
|
||||||
BT_Undead = 3,
|
|
||||||
BT_Giant = 4,
|
|
||||||
BT_Construct = 5,
|
|
||||||
BT_Extraplanar = 6,
|
|
||||||
BT_Magical = 7, //this name might be a bit off,
|
|
||||||
BT_SummonedUndead = 8,
|
|
||||||
BT_RaidGiant = 9, //Velious era Raid Giant
|
|
||||||
BT_RaidColdain = 10, //Velious era Raid Coldain
|
|
||||||
BT_NoTarget = 11, //no name, can't target this bodytype
|
|
||||||
BT_Vampire = 12,
|
|
||||||
BT_Atenha_Ra = 13,
|
|
||||||
BT_Greater_Akheva = 14,
|
|
||||||
BT_Khati_Sha = 15,
|
|
||||||
BT_Seru = 16,
|
|
||||||
BT_Grieg_Veneficus = 17,
|
|
||||||
BT_Draz_Nurakk = 18,
|
|
||||||
BT_Zek = 19, //"creatures from the Plane of War."
|
|
||||||
BT_Luggald = 20,
|
|
||||||
BT_Animal = 21,
|
|
||||||
BT_Insect = 22,
|
|
||||||
BT_Monster = 23,
|
|
||||||
BT_Summoned = 24, //Elemental?
|
|
||||||
BT_Plant = 25,
|
|
||||||
BT_Dragon = 26,
|
|
||||||
BT_Summoned2 = 27,
|
|
||||||
BT_Summoned3 = 28,
|
|
||||||
BT_Dragon2 = 29, //database data indicates this is a dragon type (kunark and DoN?)
|
|
||||||
BT_VeliousDragon = 30, //might not be a tight set
|
|
||||||
BT_Familiar = 31,
|
|
||||||
BT_Dragon3 = 32,
|
|
||||||
BT_Boxes = 33,
|
|
||||||
BT_Muramite = 34, //tribal dudes
|
|
||||||
// ...
|
|
||||||
BT_NoTarget2 = 60,
|
|
||||||
// ...
|
|
||||||
BT_SwarmPet = 63, //Looks like weapon proc related temp pets and few misc pets, should not be used for checking swarm pets in general.
|
|
||||||
BT_MonsterSummon = 64,
|
|
||||||
// 65, trap or effect related?
|
|
||||||
BT_InvisMan = 66, //no name, seen on 'InvisMan', can be /targeted
|
|
||||||
BT_Special = 67
|
|
||||||
} bodyType;
|
|
||||||
/* bodytypes above 64 make the mob not show up */
|
|
||||||
|
|
||||||
constexpr int format_as(bodyType type) { return static_cast<int>(type); }
|
// body types above 64 make the mob invisible
|
||||||
|
namespace BodyType {
|
||||||
|
constexpr uint8 Humanoid = 1;
|
||||||
|
constexpr uint8 Lycanthrope = 2;
|
||||||
|
constexpr uint8 Undead = 3;
|
||||||
|
constexpr uint8 Giant = 4;
|
||||||
|
constexpr uint8 Construct = 5;
|
||||||
|
constexpr uint8 Extraplanar = 6;
|
||||||
|
constexpr uint8 Magical = 7; // this name might be a bit off,
|
||||||
|
constexpr uint8 SummonedUndead = 8;
|
||||||
|
constexpr uint8 RaidGiant = 9; // Velious era Raid Giant
|
||||||
|
constexpr uint8 RaidColdain = 10; // Velious era Raid Coldain
|
||||||
|
constexpr uint8 NoTarget = 11; // no name, can't target this bodytype
|
||||||
|
constexpr uint8 Vampire = 12;
|
||||||
|
constexpr uint8 AtenHaRa = 13;
|
||||||
|
constexpr uint8 GreaterAkheva = 14;
|
||||||
|
constexpr uint8 KhatiSha = 15;
|
||||||
|
constexpr uint8 Seru = 16;
|
||||||
|
constexpr uint8 GriegVeneficus = 17;
|
||||||
|
constexpr uint8 DrazNurakk = 18;
|
||||||
|
constexpr uint8 Zek = 19; //"creatures from the Plane of War."
|
||||||
|
constexpr uint8 Luggald = 20;
|
||||||
|
constexpr uint8 Animal = 21;
|
||||||
|
constexpr uint8 Insect = 22;
|
||||||
|
constexpr uint8 Monster = 23;
|
||||||
|
constexpr uint8 Summoned = 24; // Elemental?
|
||||||
|
constexpr uint8 Plant = 25;
|
||||||
|
constexpr uint8 Dragon = 26;
|
||||||
|
constexpr uint8 Summoned2 = 27;
|
||||||
|
constexpr uint8 Summoned3 = 28;
|
||||||
|
constexpr uint8 Dragon2 = 29; // database data indicates this is a dragon type (Kunark and DoN?)
|
||||||
|
constexpr uint8 VeliousDragon = 30; // might not be a tight set
|
||||||
|
constexpr uint8 Familiar = 31;
|
||||||
|
constexpr uint8 Dragon3 = 32;
|
||||||
|
constexpr uint8 Boxes = 33;
|
||||||
|
constexpr uint8 Muramite = 34; // tribal dudes
|
||||||
|
constexpr uint8 NoTarget2 = 60;
|
||||||
|
constexpr uint8 SwarmPet = 63; // Looks like weapon proc related temp pets and few misc pets, should not be used for checking swarm pets in general.
|
||||||
|
constexpr uint8 MonsterSummon = 64;
|
||||||
|
constexpr uint8 InvisibleMan = 66; // no name, seen on 'InvisMan', can be /targeted
|
||||||
|
constexpr uint8 Special = 67;
|
||||||
|
|
||||||
|
std::string GetName(uint8 body_type_id);
|
||||||
|
bool IsValid(uint8 body_type_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::map<uint8, std::string> body_type_names = {
|
||||||
|
{ BodyType::Humanoid, "Humanoid" },
|
||||||
|
{ BodyType::Lycanthrope, "Lycanthrope" },
|
||||||
|
{ BodyType::Undead, "Undead" },
|
||||||
|
{ BodyType::Giant, "Giant" },
|
||||||
|
{ BodyType::Construct, "Construct" },
|
||||||
|
{ BodyType::Extraplanar, "Extraplanar" },
|
||||||
|
{ BodyType::Magical, "Magical" },
|
||||||
|
{ BodyType::SummonedUndead, "Summoned Undead" },
|
||||||
|
{ BodyType::RaidGiant, "Raid Giant" },
|
||||||
|
{ BodyType::RaidColdain, "Raid Coldain" },
|
||||||
|
{ BodyType::NoTarget, "Untargetable" },
|
||||||
|
{ BodyType::Vampire, "Vampire" },
|
||||||
|
{ BodyType::AtenHaRa, "Aten Ha Ra" },
|
||||||
|
{ BodyType::GreaterAkheva, "Greater Akheva" },
|
||||||
|
{ BodyType::KhatiSha, "Khati Sha" },
|
||||||
|
{ BodyType::Seru, "Seru" },
|
||||||
|
{ BodyType::GriegVeneficus, "Grieg Veneficus" },
|
||||||
|
{ BodyType::DrazNurakk, "Draz Nurakk" },
|
||||||
|
{ BodyType::Zek, "Zek" },
|
||||||
|
{ BodyType::Luggald, "Luggald" },
|
||||||
|
{ BodyType::Animal, "Animal" },
|
||||||
|
{ BodyType::Insect, "Insect" },
|
||||||
|
{ BodyType::Monster, "Monster" },
|
||||||
|
{ BodyType::Summoned, "Summoned" },
|
||||||
|
{ BodyType::Plant, "Plant" },
|
||||||
|
{ BodyType::Dragon, "Dragon" },
|
||||||
|
{ BodyType::Summoned2, "Summoned 2" },
|
||||||
|
{ BodyType::Summoned3, "Summoned 3" },
|
||||||
|
{ BodyType::Dragon2, "Dragon 2" },
|
||||||
|
{ BodyType::VeliousDragon, "Velious Dragon" },
|
||||||
|
{ BodyType::Familiar, "Familiar" },
|
||||||
|
{ BodyType::Dragon3, "Dragon 3" },
|
||||||
|
{ BodyType::Boxes, "Boxes" },
|
||||||
|
{ BodyType::Muramite, "Muramite" },
|
||||||
|
{ BodyType::NoTarget2, "Untargetable 2" },
|
||||||
|
{ BodyType::SwarmPet, "Swarm Pet" },
|
||||||
|
{ BodyType::MonsterSummon, "Monster Summon" },
|
||||||
|
{ BodyType::InvisibleMan, "Invisible Man" },
|
||||||
|
{ BodyType::Special, "Special" },
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "../rulesys.h"
|
#include "../rulesys.h"
|
||||||
#include "../eqemu_logsys.h"
|
#include "../eqemu_logsys.h"
|
||||||
#include "../repositories/instance_list_repository.h"
|
#include "../repositories/instance_list_repository.h"
|
||||||
|
#include "../zone_store.h"
|
||||||
|
|
||||||
|
|
||||||
WorldContentService::WorldContentService()
|
WorldContentService::WorldContentService()
|
||||||
@@ -183,8 +184,8 @@ void WorldContentService::ReloadContentFlags()
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetContentFlags(set_content_flags);
|
SetContentFlags(set_content_flags);
|
||||||
LoadZones();
|
|
||||||
LoadStaticGlobalZoneInstances();
|
LoadStaticGlobalZoneInstances();
|
||||||
|
zone_store.LoadZones(*m_content_database);
|
||||||
}
|
}
|
||||||
|
|
||||||
Database *WorldContentService::GetDatabase() const
|
Database *WorldContentService::GetDatabase() const
|
||||||
@@ -236,18 +237,6 @@ void WorldContentService::SetContentFlag(const std::string &content_flag_name, b
|
|||||||
ReloadContentFlags();
|
ReloadContentFlags();
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleZoneRoutingMiddleware is meant to handle content and context aware zone routing
|
|
||||||
//
|
|
||||||
// example # 1
|
|
||||||
// lavastorm (pre-don) version 0 (classic)
|
|
||||||
// lavastorm (don) version 1
|
|
||||||
// we want to route players to the correct version of lavastorm based on the current server side expansion
|
|
||||||
// in order to do that the simplest and cleanest way we intercept the zoning process and route players to an "instance" of the zone
|
|
||||||
// the reason why we're doing this is because all of the zoning logic already is handled by two keys "zone_id" and "instance_id"
|
|
||||||
// we can leverage static, never expires instances to handle this but to the client they don't see it any other way than a public normal zone
|
|
||||||
// scripts handle all the same way, you don't have to think about instances, the middleware will handle the magic
|
|
||||||
// the versions of zones are represented by two zone entries that have potentially different min/max expansion and/or different content flags
|
|
||||||
// we decide to route the client to the correct version of the zone based on the current server side expansion
|
|
||||||
void WorldContentService::HandleZoneRoutingMiddleware(ZoneChange_Struct *zc)
|
void WorldContentService::HandleZoneRoutingMiddleware(ZoneChange_Struct *zc)
|
||||||
{
|
{
|
||||||
auto r = FindZone(zc->zoneID, zc->instanceID);
|
auto r = FindZone(zc->zoneID, zc->instanceID);
|
||||||
@@ -261,93 +250,72 @@ void WorldContentService::HandleZoneRoutingMiddleware(ZoneChange_Struct *zc)
|
|||||||
// LoadStaticGlobalZoneInstances loads all static global zone instances
|
// LoadStaticGlobalZoneInstances loads all static global zone instances
|
||||||
// these are zones that are never set to expire and are global
|
// these are zones that are never set to expire and are global
|
||||||
// these are used commonly in v1/v2/v3 versions of the same zone for expansion routing
|
// these are used commonly in v1/v2/v3 versions of the same zone for expansion routing
|
||||||
WorldContentService * WorldContentService::LoadStaticGlobalZoneInstances()
|
WorldContentService *WorldContentService::LoadStaticGlobalZoneInstances()
|
||||||
{
|
{
|
||||||
m_zone_instances = InstanceListRepository::GetWhere(*GetDatabase(), fmt::format("never_expires = 1 AND is_global = 1"));
|
m_zone_static_instances = InstanceListRepository::GetWhere(
|
||||||
|
*GetDatabase(),
|
||||||
|
fmt::format("never_expires = 1 AND is_global = 1")
|
||||||
|
);
|
||||||
|
|
||||||
LogInfo("Loaded [{}] zone_instances", m_zone_instances.size());
|
LogInfo("Loaded [{}] zone_instances", m_zone_static_instances.size());
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadZones sets the zones for the world content service
|
// FindZone handles content and context aware zone routing (middleware)
|
||||||
// this is used for zone routing middleware
|
//
|
||||||
// we pull the zone list from the zone repository and feed from the zone store for now
|
// this is a middleware function that is meant to be used in the zone change process
|
||||||
// we're holding a copy in the content service - but we're talking 250kb of data in memory to handle routing of zoning
|
// this hooks all core zone changes within the server and routes the player to the correct zone
|
||||||
WorldContentService * WorldContentService::LoadZones()
|
// returning a zone_id of non-zero means the middleware will route the player
|
||||||
{
|
// returning a zone_id of 0 means the middleware will not route the player
|
||||||
m_zones = ZoneRepository::All(*GetContentDatabase());
|
// this is useful for handling multiple versions of the same zone
|
||||||
|
//
|
||||||
LogInfo("Loaded [{}] zones", m_zones.size());
|
// implementation >
|
||||||
|
// the zoning and process spawning logic already is handled by two keys "zone_id" and "instance_id"
|
||||||
return this;
|
// we leverage static, never expires instances to handle this and client still sees it as a normal zone
|
||||||
}
|
//
|
||||||
|
// content awareness >
|
||||||
// FindZone is critical to the zone routing middleware and any logic that needs to route players to the correct zone
|
// simply use the zone_id, server content settings and the middleware will handle the rest
|
||||||
// era contextual routing, multiple version of zones, etc
|
// you don't have to think about instances in any data tables (use instance_id 0)
|
||||||
|
// you don't have to keep track of instance ids in scripts (use instance_id 0)
|
||||||
|
// the versions of zones are represented by two zone entries that have potentially different min/max expansion and/or different content flags
|
||||||
|
// we decide to route the client to the correct version of the zone based on the current server side expansion
|
||||||
|
//
|
||||||
|
// example >
|
||||||
|
// we want to route players to the correct version of lavastorm based on the current server side expansion (DoesZonePassContentFiltering)
|
||||||
|
// lavastorm (pre-don) version 0 (classic)
|
||||||
|
// zone table entry for version = 0, min_expansion = 0, max_expansion = 8
|
||||||
|
// instance_list table entry for lavastorm has version = 0, is_global = 1, never_expires = 1
|
||||||
|
// lavastorm (don) version 1
|
||||||
|
// zone table entry for version = 1, min_expansion = 9, max_expansion = 99
|
||||||
|
// instance_list table entry for lavastorm has version = 1, is_global = 1, never_expires = 1
|
||||||
WorldContentService::FindZoneResult WorldContentService::FindZone(uint32 zone_id, uint32 instance_id)
|
WorldContentService::FindZoneResult WorldContentService::FindZone(uint32 zone_id, uint32 instance_id)
|
||||||
{
|
{
|
||||||
// if there's an active dynamic instance, we don't need to route
|
for (const auto &z: zone_store.GetZones()) {
|
||||||
if (instance_id > 0) {
|
for (auto &i: m_zone_static_instances) {
|
||||||
auto inst = InstanceListRepository::FindOne(*GetDatabase(), instance_id);
|
if (
|
||||||
if (inst.id != 0 && !inst.is_global && !inst.never_expires) {
|
z.zoneidnumber == zone_id &&
|
||||||
return WorldContentService::FindZoneResult{
|
DoesZonePassContentFiltering(z) &&
|
||||||
.zone_id = 0,
|
i.zone == zone_id &&
|
||||||
};
|
i.version == z.version) {
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &z: m_zones) {
|
if (instance_id > 0 && i.id != instance_id) {
|
||||||
if (z.zoneidnumber == zone_id) {
|
continue;
|
||||||
auto f = ContentFlags{
|
|
||||||
.min_expansion = z.min_expansion,
|
|
||||||
.max_expansion = z.max_expansion,
|
|
||||||
.content_flags = z.content_flags,
|
|
||||||
.content_flags_disabled = z.content_flags_disabled
|
|
||||||
};
|
|
||||||
|
|
||||||
if (DoesPassContentFiltering(f)) {
|
|
||||||
LogInfo(
|
|
||||||
"Attempting to route player to zone [{}] ({}) version [{}] long_name [{}]",
|
|
||||||
z.short_name,
|
|
||||||
z.zoneidnumber,
|
|
||||||
z.version,
|
|
||||||
z.long_name
|
|
||||||
);
|
|
||||||
|
|
||||||
// first pass, explicit match on public static global zone instances
|
|
||||||
for (auto &i: m_zone_instances) {
|
|
||||||
if (i.zone == zone_id && i.version == z.version) {
|
|
||||||
LogInfo(
|
|
||||||
"Routed player to instance [{}] of zone [{}] ({}) version [{}] long_name [{}] notes [{}]",
|
|
||||||
i.id,
|
|
||||||
z.short_name,
|
|
||||||
z.zoneidnumber,
|
|
||||||
z.version,
|
|
||||||
z.long_name,
|
|
||||||
i.notes
|
|
||||||
);
|
|
||||||
|
|
||||||
return WorldContentService::FindZoneResult{
|
|
||||||
.zone_id = static_cast<uint32>(z.zoneidnumber),
|
|
||||||
.instance = i,
|
|
||||||
.zone = z
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LogInfo(
|
LogInfo(
|
||||||
"Routed player to non-instance zone [{}] ({}) version [{}] long_name [{}] notes [{}]",
|
"Routed player to public static instance [{}] of zone [{}] ({}) version [{}] long_name [{}] notes [{}]",
|
||||||
|
i.id,
|
||||||
z.short_name,
|
z.short_name,
|
||||||
z.zoneidnumber,
|
z.zoneidnumber,
|
||||||
z.version,
|
z.version,
|
||||||
z.long_name,
|
z.long_name,
|
||||||
z.note
|
i.notes
|
||||||
);
|
);
|
||||||
|
|
||||||
return WorldContentService::FindZoneResult{
|
return WorldContentService::FindZoneResult{
|
||||||
.zone_id = static_cast<uint32>(z.zoneidnumber),
|
.zone_id = static_cast<uint32>(z.zoneidnumber),
|
||||||
.instance = InstanceListRepository::NewEntity(),
|
.instance = i,
|
||||||
.zone = z
|
.zone = z
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -359,7 +327,7 @@ WorldContentService::FindZoneResult WorldContentService::FindZone(uint32 zone_id
|
|||||||
|
|
||||||
bool WorldContentService::IsInPublicStaticInstance(uint32 instance_id)
|
bool WorldContentService::IsInPublicStaticInstance(uint32 instance_id)
|
||||||
{
|
{
|
||||||
for (auto &i: m_zone_instances) {
|
for (auto &i: m_zone_static_instances) {
|
||||||
if (i.id == instance_id) {
|
if (i.id == instance_id) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -367,3 +335,15 @@ bool WorldContentService::IsInPublicStaticInstance(uint32 instance_id)
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WorldContentService::DoesZonePassContentFiltering(const ZoneRepository::Zone &z)
|
||||||
|
{
|
||||||
|
auto f = ContentFlags{
|
||||||
|
.min_expansion = z.min_expansion,
|
||||||
|
.max_expansion = z.max_expansion,
|
||||||
|
.content_flags = z.content_flags,
|
||||||
|
.content_flags_disabled = z.content_flags_disabled
|
||||||
|
};
|
||||||
|
|
||||||
|
return DoesPassContentFiltering(f);
|
||||||
|
}
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ public:
|
|||||||
WorldContentService * SetExpansionContext();
|
WorldContentService * SetExpansionContext();
|
||||||
|
|
||||||
bool DoesPassContentFiltering(const ContentFlags& f);
|
bool DoesPassContentFiltering(const ContentFlags& f);
|
||||||
|
bool DoesZonePassContentFiltering(const ZoneRepository::Zone& z);
|
||||||
|
|
||||||
WorldContentService * SetDatabase(Database *database);
|
WorldContentService * SetDatabase(Database *database);
|
||||||
Database *GetDatabase() const;
|
Database *GetDatabase() const;
|
||||||
@@ -189,10 +190,8 @@ private:
|
|||||||
Database *m_content_database;
|
Database *m_content_database;
|
||||||
|
|
||||||
// holds a record of the zone table from the database
|
// holds a record of the zone table from the database
|
||||||
std::vector<ZoneRepository::Zone> m_zones = {};
|
|
||||||
WorldContentService *LoadStaticGlobalZoneInstances();
|
WorldContentService *LoadStaticGlobalZoneInstances();
|
||||||
std::vector<InstanceListRepository::InstanceList> m_zone_instances;
|
std::vector<InstanceListRepository::InstanceList> m_zone_static_instances;
|
||||||
WorldContentService * LoadZones();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern WorldContentService content_service;
|
extern WorldContentService content_service;
|
||||||
|
|||||||
@@ -101,6 +101,24 @@ void CRC32::SetEQChecksum(uchar* in_data, uint32 in_length, uint32 start_at)
|
|||||||
memcpy(in_data, (char*)&check, 4);
|
memcpy(in_data, (char*)&check, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned long CRC32::GetEQChecksum(uchar* in_data, uint32 in_length, uint32 start_at)
|
||||||
|
{
|
||||||
|
unsigned long data;
|
||||||
|
unsigned long check = 0xffffffff;
|
||||||
|
|
||||||
|
for (uint32 i = start_at; i < in_length; i++)
|
||||||
|
{
|
||||||
|
data = in_data[i];
|
||||||
|
data = data ^ (check);
|
||||||
|
data = data & 0x000000ff;
|
||||||
|
check = check >> 8;
|
||||||
|
data = CRC32Table[data];
|
||||||
|
check = check ^ data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return check;
|
||||||
|
}
|
||||||
|
|
||||||
uint32 CRC32::Update(const uint8* buf, uint32 bufsize, uint32 crc32var) {
|
uint32 CRC32::Update(const uint8* buf, uint32 bufsize, uint32 crc32var) {
|
||||||
for(uint32 i=0; i < bufsize; i++)
|
for(uint32 i=0; i < bufsize; i++)
|
||||||
Calc(buf[i], crc32var);
|
Calc(buf[i], crc32var);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ public:
|
|||||||
static uint32 Generate(const uint8* buf, uint32 bufsize);
|
static uint32 Generate(const uint8* buf, uint32 bufsize);
|
||||||
static uint32 GenerateNoFlip(const uint8* buf, uint32 bufsize); // Same as Generate(), but without the ~
|
static uint32 GenerateNoFlip(const uint8* buf, uint32 bufsize); // Same as Generate(), but without the ~
|
||||||
static void SetEQChecksum(uchar* in_data, uint32 in_length, uint32 start_at=4);
|
static void SetEQChecksum(uchar* in_data, uint32 in_length, uint32 start_at=4);
|
||||||
|
static unsigned long GetEQChecksum(uchar* in_data, uint32 in_length, uint32 start_at = 4);
|
||||||
|
|
||||||
// Multiple buffer CRC32
|
// Multiple buffer CRC32
|
||||||
static uint32 Update(const uint8* buf, uint32 bufsize, uint32 crc32 = 0xFFFFFFFF);
|
static uint32 Update(const uint8* buf, uint32 bufsize, uint32 crc32 = 0xFFFFFFFF);
|
||||||
|
|||||||
+57
-14
@@ -66,6 +66,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
|
#include "data_verification.h"
|
||||||
#include "eq_packet_structs.h"
|
#include "eq_packet_structs.h"
|
||||||
#include "extprofile.h"
|
#include "extprofile.h"
|
||||||
#include "strings.h"
|
#include "strings.h"
|
||||||
@@ -77,6 +78,8 @@
|
|||||||
#include "zone_store.h"
|
#include "zone_store.h"
|
||||||
#include "repositories/merchantlist_temp_repository.h"
|
#include "repositories/merchantlist_temp_repository.h"
|
||||||
#include "repositories/bot_data_repository.h"
|
#include "repositories/bot_data_repository.h"
|
||||||
|
#include "repositories/trader_repository.h"
|
||||||
|
#include "repositories/buyer_repository.h"
|
||||||
|
|
||||||
extern Client client;
|
extern Client client;
|
||||||
|
|
||||||
@@ -282,16 +285,31 @@ bool Database::SetAccountStatus(const std::string& account_name, int16 status)
|
|||||||
|
|
||||||
bool Database::ReserveName(uint32 account_id, const std::string& name)
|
bool Database::ReserveName(uint32 account_id, const std::string& name)
|
||||||
{
|
{
|
||||||
const auto& l = CharacterDataRepository::GetWhere(
|
const std::string& where_filter = fmt::format(
|
||||||
*this,
|
"`name` = '{}'",
|
||||||
fmt::format(
|
Strings::Escape(name)
|
||||||
"`name` = '{}'",
|
|
||||||
Strings::Escape(name)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!l.empty()) {
|
if (RuleB(Bots, Enabled)) {
|
||||||
LogInfo("Account: [{}] tried to request name: [{}], but it is already taken", account_id, name);
|
const auto& b = BotDataRepository::GetWhere(*this, where_filter);
|
||||||
|
|
||||||
|
if (!b.empty()) {
|
||||||
|
LogInfo("Account [{}] requested name [{}] but name is already taken by a bot", account_id, name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& c = CharacterDataRepository::GetWhere(*this, where_filter);
|
||||||
|
|
||||||
|
if (!c.empty()) {
|
||||||
|
LogInfo("Account [{}] requested name [{}] but name is already taken by a character", account_id, name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& n = NpcTypesRepository::GetWhere(*this, where_filter);
|
||||||
|
|
||||||
|
if (!n.empty()) {
|
||||||
|
LogInfo("Account [{}] requested name [{}] but name is already taken by an NPC", account_id, name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,13 +324,15 @@ bool Database::ReserveName(uint32 account_id, const std::string& name)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int guild_id = RuleI(Character, DefaultGuild);
|
const uint32 guild_id = RuleI(Character, DefaultGuild);
|
||||||
|
const uint8 guild_rank = EQ::Clamp(RuleI(Character, DefaultGuildRank), 0, 8);
|
||||||
if (guild_id != 0) {
|
if (guild_id != 0) {
|
||||||
if (e.id) {
|
if (e.id) {
|
||||||
auto g = GuildMembersRepository::NewEntity();
|
auto g = GuildMembersRepository::NewEntity();
|
||||||
|
|
||||||
g.char_id = e.id;
|
g.char_id = e.id;
|
||||||
g.guild_id = guild_id;
|
g.guild_id = guild_id;
|
||||||
|
g.rank_ = guild_rank;
|
||||||
|
|
||||||
GuildMembersRepository::InsertOne(*this, g);
|
GuildMembersRepository::InsertOne(*this, g);
|
||||||
}
|
}
|
||||||
@@ -1628,16 +1648,29 @@ uint32 Database::GetGuildIDByCharID(uint32 character_id)
|
|||||||
|
|
||||||
uint32 Database::GetGroupIDByCharID(uint32 character_id)
|
uint32 Database::GetGroupIDByCharID(uint32 character_id)
|
||||||
{
|
{
|
||||||
const auto& e = GroupIdRepository::FindOne(*this, character_id);
|
const auto& e = GroupIdRepository::GetWhere(
|
||||||
|
*this,
|
||||||
|
fmt::format(
|
||||||
|
"`character_id` = {}",
|
||||||
|
character_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return e.character_id ? e.group_id : 0;
|
return e.size() == 1 ? e.front().group_id : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Database::GetRaidIDByCharID(uint32 character_id)
|
uint32 Database::GetRaidIDByCharID(uint32 character_id)
|
||||||
{
|
{
|
||||||
const auto& e = RaidMembersRepository::FindOne(*this, character_id);
|
|
||||||
|
|
||||||
return e.charid ? e.raidid : 0;
|
const auto& e = RaidMembersRepository::GetWhere(
|
||||||
|
*this,
|
||||||
|
fmt::format(
|
||||||
|
"`charid` = {}",
|
||||||
|
character_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return e.size() == 1 ? e.front().raidid : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 Database::CountInvSnapshots()
|
int64 Database::CountInvSnapshots()
|
||||||
@@ -1827,7 +1860,7 @@ bool Database::CopyCharacter(
|
|||||||
|
|
||||||
const int64 new_character_id = (CharacterDataRepository::GetMaxId(*this) + 1);
|
const int64 new_character_id = (CharacterDataRepository::GetMaxId(*this) + 1);
|
||||||
|
|
||||||
std::vector<std::string> tables_to_zero_id = { "keyring", "data_buckets" };
|
std::vector<std::string> tables_to_zero_id = { "keyring", "data_buckets", "character_instance_safereturns" };
|
||||||
|
|
||||||
TransactionBegin();
|
TransactionBegin();
|
||||||
|
|
||||||
@@ -2104,3 +2137,13 @@ void Database::ClearGuildOnlineStatus()
|
|||||||
{
|
{
|
||||||
GuildMembersRepository::ClearOnlineStatus(*this);
|
GuildMembersRepository::ClearOnlineStatus(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Database::ClearTraderDetails()
|
||||||
|
{
|
||||||
|
TraderRepository::Truncate(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Database::ClearBuyerDetails()
|
||||||
|
{
|
||||||
|
BuyerRepository::DeleteBuyer(*this, 0);
|
||||||
|
}
|
||||||
|
|||||||
@@ -244,6 +244,8 @@ public:
|
|||||||
|
|
||||||
void PurgeAllDeletedDataBuckets();
|
void PurgeAllDeletedDataBuckets();
|
||||||
void ClearGuildOnlineStatus();
|
void ClearGuildOnlineStatus();
|
||||||
|
void ClearTraderDetails();
|
||||||
|
void ClearBuyerDetails();
|
||||||
|
|
||||||
|
|
||||||
/* Database Variables */
|
/* Database Variables */
|
||||||
|
|||||||
@@ -4947,7 +4947,7 @@ UPDATE `aa_ability` SET `auto_grant_enabled` = 1 WHERE `grant_only` = 0 AND `cha
|
|||||||
.version = 9237,
|
.version = 9237,
|
||||||
.description = "2023_10_15_import_13th_floor.sql",
|
.description = "2023_10_15_import_13th_floor.sql",
|
||||||
.check = "SHOW COLUMNS FROM `items` LIKE 'bardeffect';",
|
.check = "SHOW COLUMNS FROM `items` LIKE 'bardeffect';",
|
||||||
.condition = "contains",
|
.condition = "missing",
|
||||||
.match = "mediumint",
|
.match = "mediumint",
|
||||||
.sql = R"(
|
.sql = R"(
|
||||||
ALTER TABLE `items`
|
ALTER TABLE `items`
|
||||||
@@ -5660,6 +5660,104 @@ ALTER TABLE `trader`
|
|||||||
DROP PRIMARY KEY,
|
DROP PRIMARY KEY,
|
||||||
ADD PRIMARY KEY (`id`),
|
ADD PRIMARY KEY (`id`),
|
||||||
ADD INDEX `charid_slotid` (`char_id`, `slot_id`);
|
ADD INDEX `charid_slotid` (`char_id`, `slot_id`);
|
||||||
|
)"
|
||||||
|
},
|
||||||
|
ManifestEntry{
|
||||||
|
.version = 9281,
|
||||||
|
.description = "2024_06_24_update_buyer_support.sql",
|
||||||
|
.check = "SHOW COLUMNS FROM `buyer` LIKE 'id'",
|
||||||
|
.condition = "empty",
|
||||||
|
.match = "",
|
||||||
|
.sql = R"(
|
||||||
|
ALTER TABLE `buyer`
|
||||||
|
ADD COLUMN `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
|
||||||
|
CHANGE COLUMN `charid` `char_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `id`,
|
||||||
|
ADD COLUMN `char_entity_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `char_id`,
|
||||||
|
ADD COLUMN `char_name` VARCHAR(64) NULL DEFAULT NULL AFTER `char_entity_id`,
|
||||||
|
ADD COLUMN `char_zone_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `char_name`,
|
||||||
|
ADD COLUMN `char_zone_instance_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `char_zone_id`,
|
||||||
|
ADD COLUMN `transaction_date` DATETIME NULL DEFAULT NULL AFTER `char_zone_instance_id`,
|
||||||
|
ADD COLUMN `welcome_message` VARCHAR(256) NULL DEFAULT NULL AFTER `transaction_date`,
|
||||||
|
DROP COLUMN `buyslot`,
|
||||||
|
DROP COLUMN `itemid`,
|
||||||
|
DROP COLUMN `itemname`,
|
||||||
|
DROP COLUMN `quantity`,
|
||||||
|
DROP COLUMN `price`,
|
||||||
|
DROP PRIMARY KEY,
|
||||||
|
ADD PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
ADD INDEX `charid` (`char_id`);
|
||||||
|
|
||||||
|
CREATE TABLE `buyer_buy_lines` (
|
||||||
|
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`buyer_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
|
||||||
|
`char_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||||
|
`buy_slot_id` INT(11) NOT NULL DEFAULT '0',
|
||||||
|
`item_id` INT(11) NOT NULL DEFAULT '0',
|
||||||
|
`item_qty` INT(11) NOT NULL DEFAULT '0',
|
||||||
|
`item_price` INT(11) NOT NULL DEFAULT '0',
|
||||||
|
`item_icon` INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||||
|
`item_name` VARCHAR(64) NOT NULL DEFAULT '' COLLATE 'latin1_swedish_ci',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
INDEX `buyerid_charid_buyslotid` (`buyer_id`, `char_id`, `buy_slot_id`) USING BTREE
|
||||||
|
)
|
||||||
|
COLLATE='latin1_swedish_ci'
|
||||||
|
ENGINE=InnoDB
|
||||||
|
AUTO_INCREMENT=1;
|
||||||
|
|
||||||
|
CREATE TABLE `buyer_trade_items` (
|
||||||
|
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`buyer_buy_lines_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
|
||||||
|
`item_id` INT(11) NOT NULL DEFAULT '0',
|
||||||
|
`item_qty` INT(11) NOT NULL DEFAULT '0',
|
||||||
|
`item_icon` INT(11) NOT NULL DEFAULT '0',
|
||||||
|
`item_name` VARCHAR(64) NOT NULL DEFAULT '0' COLLATE 'latin1_swedish_ci',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
INDEX `buyerbuylinesid` (`buyer_buy_lines_id`) USING BTREE
|
||||||
|
)
|
||||||
|
COLLATE='latin1_swedish_ci'
|
||||||
|
ENGINE=InnoDB
|
||||||
|
AUTO_INCREMENT=1;
|
||||||
|
)"
|
||||||
|
},
|
||||||
|
ManifestEntry{
|
||||||
|
.version = 9282,
|
||||||
|
.description = "2024_08_02_spell_buckets_comparison.sql",
|
||||||
|
.check = "SHOW COLUMNS FROM `spell_buckets` LIKE 'bucket_comparison'",
|
||||||
|
.condition = "empty",
|
||||||
|
.match = "",
|
||||||
|
.sql = R"(
|
||||||
|
ALTER TABLE `spell_buckets`
|
||||||
|
CHANGE COLUMN `spellid` `spell_id` int UNSIGNED NOT NULL FIRST,
|
||||||
|
CHANGE COLUMN `key` `bucket_name` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '' AFTER `spell_id`,
|
||||||
|
CHANGE COLUMN `value` `bucket_value` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '' AFTER `bucket_name`,
|
||||||
|
ADD COLUMN `bucket_comparison` tinyint UNSIGNED NOT NULL DEFAULT 0 AFTER `bucket_value`,
|
||||||
|
DROP PRIMARY KEY,
|
||||||
|
ADD PRIMARY KEY (`spell_id`) USING BTREE;
|
||||||
|
)"
|
||||||
|
},
|
||||||
|
ManifestEntry{
|
||||||
|
.version = 9283,
|
||||||
|
.description = "2024_08_05_fix_client_hotbar",
|
||||||
|
.check = "SHOW COLUMNS FROM `inventory` LIKE 'guid'",
|
||||||
|
.condition = "empty",
|
||||||
|
.match = "",
|
||||||
|
.sql = R"(
|
||||||
|
ALTER TABLE `inventory`
|
||||||
|
ADD COLUMN `guid` BIGINT UNSIGNED NULL DEFAULT '0' AFTER `ornament_hero_model`;
|
||||||
|
ALTER TABLE `inventory_snapshots`
|
||||||
|
ADD COLUMN `guid` BIGINT UNSIGNED NULL DEFAULT '0' AFTER `ornament_hero_model`;
|
||||||
|
)"
|
||||||
|
},
|
||||||
|
ManifestEntry{
|
||||||
|
.version = 9284,
|
||||||
|
.description = "2024_10_08_character_exp_modifiers_default.sql",
|
||||||
|
.check = "SHOW CREATE TABLE `character_exp_modifiers`",
|
||||||
|
.condition = "contains",
|
||||||
|
.match = "`exp_modifier` float NOT NULL,",
|
||||||
|
.sql = R"(
|
||||||
|
ALTER TABLE `character_exp_modifiers`
|
||||||
|
MODIFY COLUMN `aa_modifier` float NOT NULL DEFAULT 1.0 AFTER `instance_version`,
|
||||||
|
MODIFY COLUMN `exp_modifier` float NOT NULL DEFAULT 1.0 AFTER `aa_modifier`;
|
||||||
)"
|
)"
|
||||||
}
|
}
|
||||||
// -- template; copy/paste this when you need to create a new entry
|
// -- template; copy/paste this when you need to create a new entry
|
||||||
|
|||||||
@@ -150,6 +150,17 @@ ADD COLUMN `augment_six` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_five
|
|||||||
.sql = R"(
|
.sql = R"(
|
||||||
ALTER TABLE `bot_data`
|
ALTER TABLE `bot_data`
|
||||||
ADD COLUMN `extra_haste` mediumint(8) NOT NULL DEFAULT 0 AFTER `wis`;
|
ADD COLUMN `extra_haste` mediumint(8) NOT NULL DEFAULT 0 AFTER `wis`;
|
||||||
|
)"
|
||||||
|
},
|
||||||
|
ManifestEntry{
|
||||||
|
.version = 9045,
|
||||||
|
.description = "2024_08_05_bot_spells_entries_unsigned_spell_id.sql",
|
||||||
|
.check = "SHOW COLUMNS FROM `bot_spells_entries` LIKE 'spell_id'",
|
||||||
|
.condition = "empty",
|
||||||
|
.match = "",
|
||||||
|
.sql = R"(
|
||||||
|
ALTER TABLE `bot_spells_entries`
|
||||||
|
CHANGE COLUMN `spellid` `spell_id` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `npc_spells_id`;
|
||||||
)"
|
)"
|
||||||
}
|
}
|
||||||
// -- template; copy/paste this when you need to create a new entry
|
// -- template; copy/paste this when you need to create a new entry
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ namespace DatabaseSchema {
|
|||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
{"adventure_stats", "player_id"},
|
{"adventure_stats", "player_id"},
|
||||||
{"buyer", "charid"},
|
|
||||||
{"char_recipe_list", "char_id"},
|
{"char_recipe_list", "char_id"},
|
||||||
{"character_activities", "charid"},
|
{"character_activities", "charid"},
|
||||||
{"character_alt_currency", "char_id"},
|
{"character_alt_currency", "char_id"},
|
||||||
@@ -107,6 +106,8 @@ namespace DatabaseSchema {
|
|||||||
"adventure_details",
|
"adventure_details",
|
||||||
"adventure_stats",
|
"adventure_stats",
|
||||||
"buyer",
|
"buyer",
|
||||||
|
"buyer_buy_lines",
|
||||||
|
"buyer_trade_items",
|
||||||
"char_recipe_list",
|
"char_recipe_list",
|
||||||
"character_activities",
|
"character_activities",
|
||||||
"character_alt_currency",
|
"character_alt_currency",
|
||||||
@@ -325,6 +326,9 @@ namespace DatabaseSchema {
|
|||||||
"banned_ips",
|
"banned_ips",
|
||||||
"bug_reports",
|
"bug_reports",
|
||||||
"bugs",
|
"bugs",
|
||||||
|
"buyer",
|
||||||
|
"buyer_buy_lines",
|
||||||
|
"buyer_trade_items",
|
||||||
"completed_shared_task_activity_state",
|
"completed_shared_task_activity_state",
|
||||||
"completed_shared_task_members",
|
"completed_shared_task_members",
|
||||||
"completed_shared_tasks",
|
"completed_shared_tasks",
|
||||||
|
|||||||
+6
-70
@@ -19,81 +19,17 @@
|
|||||||
|
|
||||||
#include "deity.h"
|
#include "deity.h"
|
||||||
|
|
||||||
EQ::deity::DeityTypeBit EQ::deity::GetDeityBitmask(DeityType deity_type)
|
uint32 Deity::GetBitmask(uint32 deity_id)
|
||||||
{
|
{
|
||||||
switch (deity_type) {
|
return IsValid(deity_id) ? deity_bitmasks[deity_id] : Deity::Bitmask::All;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<EQ::deity::DeityType, std::string>& EQ::deity::GetDeityMap()
|
std::string Deity::GetName(uint32 deity_id)
|
||||||
{
|
{
|
||||||
static const std::map<EQ::deity::DeityType, std::string> deity_map = {
|
return IsValid(deity_id) ? deity_names[deity_id] : "UNKNOWN DEITY";
|
||||||
{ 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EQ::deity::GetDeityName(DeityType deity_type)
|
bool Deity::IsValid(uint32 deity_id)
|
||||||
{
|
{
|
||||||
|
return deity_names.find(deity_id) != deity_names.end();
|
||||||
if (EQ::deity::GetDeityMap().find(deity_type) != EQ::deity::GetDeityMap().end()) {
|
|
||||||
return EQ::deity::GetDeityMap().find(deity_type)->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string();
|
|
||||||
}
|
}
|
||||||
|
|||||||
+85
-52
@@ -23,62 +23,95 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
namespace Deity {
|
||||||
|
constexpr uint32 Unknown = 0;
|
||||||
|
constexpr uint32 Agnostic1 = 140;
|
||||||
|
constexpr uint32 Bertoxxulous = 201;
|
||||||
|
constexpr uint32 BrellSirilis = 202;
|
||||||
|
constexpr uint32 CazicThule = 203;
|
||||||
|
constexpr uint32 ErollisiMarr = 204;
|
||||||
|
constexpr uint32 Bristlebane = 205;
|
||||||
|
constexpr uint32 Innoruuk = 206;
|
||||||
|
constexpr uint32 Karana = 207;
|
||||||
|
constexpr uint32 MithanielMarr = 208;
|
||||||
|
constexpr uint32 Prexus = 209;
|
||||||
|
constexpr uint32 Quellious = 210;
|
||||||
|
constexpr uint32 RallosZek = 211;
|
||||||
|
constexpr uint32 RodcetNife = 212;
|
||||||
|
constexpr uint32 SolusekRo = 213;
|
||||||
|
constexpr uint32 TheTribunal = 214;
|
||||||
|
constexpr uint32 Tunare = 215;
|
||||||
|
constexpr uint32 Veeshan = 216;
|
||||||
|
constexpr uint32 Agnostic2 = 396;
|
||||||
|
|
||||||
namespace EQ
|
namespace Bitmask {
|
||||||
{
|
constexpr uint32 Agnostic = 1;
|
||||||
namespace deity {
|
constexpr uint32 Bertoxxulous = 2;
|
||||||
enum DeityType {
|
constexpr uint32 BrellSirilis = 4;
|
||||||
DeityUnknown = 0,
|
constexpr uint32 CazicThule = 8;
|
||||||
DeityAgnostic_LB = 140,
|
constexpr uint32 ErollisiMarr = 16;
|
||||||
DeityBertoxxulous = 201,
|
constexpr uint32 Bristlebane = 32;
|
||||||
DeityBrellSirilis,
|
constexpr uint32 Innoruuk = 64;
|
||||||
DeityCazicThule,
|
constexpr uint32 Karana = 128;
|
||||||
DeityErollisiMarr,
|
constexpr uint32 MithanielMarr = 256;
|
||||||
DeityBristlebane,
|
constexpr uint32 Prexus = 512;
|
||||||
DeityInnoruuk,
|
constexpr uint32 Quellious = 1024;
|
||||||
DeityKarana,
|
constexpr uint32 RallosZek = 2048;
|
||||||
DeityMithanielMarr,
|
constexpr uint32 RodcetNife = 4096;
|
||||||
DeityPrexus,
|
constexpr uint32 SolusekRo = 8192;
|
||||||
DeityQuellious,
|
constexpr uint32 TheTribunal = 16384;
|
||||||
DeityRallosZek,
|
constexpr uint32 Tunare = 32768;
|
||||||
DeityRodcetNife,
|
constexpr uint32 Veeshan = 65536;
|
||||||
DeitySolusekRo,
|
constexpr uint32 All = std::numeric_limits<uint32>::max();
|
||||||
DeityTheTribunal,
|
}
|
||||||
DeityTunare,
|
|
||||||
DeityVeeshan,
|
|
||||||
DeityAgnostic = 396
|
|
||||||
};
|
|
||||||
|
|
||||||
enum DeityTypeBit : uint32 {
|
uint32 GetBitmask(uint32 deity_id);
|
||||||
bit_DeityAgnostic = 0x00000001,
|
std::string GetName(uint32 deity_id);
|
||||||
bit_DeityBertoxxulous = 0x00000002,
|
bool IsValid(uint32 deity_id);
|
||||||
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 = UINT32_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr int format_as(DeityType type) { return static_cast<int>(type); }
|
static std::map<uint32, std::string> deity_names = {
|
||||||
|
{ Deity::Agnostic1, "Agnostic" },
|
||||||
|
{ Deity::Agnostic2, "Agnostic" },
|
||||||
|
{ Deity::Bertoxxulous, "Bertoxxulous" },
|
||||||
|
{ Deity::BrellSirilis, "Brell Serilis" },
|
||||||
|
{ Deity::Bristlebane, "Bristlebane" },
|
||||||
|
{ Deity::CazicThule, "Cazic-Thule" },
|
||||||
|
{ Deity::ErollisiMarr, "Erollisi Marr" },
|
||||||
|
{ Deity::Innoruuk, "Innoruuk" },
|
||||||
|
{ Deity::Karana, "Karana" },
|
||||||
|
{ Deity::MithanielMarr, "Mithaniel Marr" },
|
||||||
|
{ Deity::Prexus, "Prexus" },
|
||||||
|
{ Deity::Quellious, "Quellious" },
|
||||||
|
{ Deity::RallosZek, "Rallos Zek" },
|
||||||
|
{ Deity::RodcetNife, "Rodcet Nife" },
|
||||||
|
{ Deity::SolusekRo, "Solusek Ro" },
|
||||||
|
{ Deity::TheTribunal, "The Tribunal" },
|
||||||
|
{ Deity::Tunare, "Tunare" },
|
||||||
|
{ Deity::Veeshan, "Veeshan" }
|
||||||
|
};
|
||||||
|
|
||||||
extern DeityTypeBit GetDeityBitmask(DeityType deity_type);
|
static std::map<uint32, uint32> deity_bitmasks = {
|
||||||
extern std::string GetDeityName(DeityType deity_type);
|
{ Deity::Agnostic1, Deity::Bitmask::Agnostic },
|
||||||
extern const std::map<DeityType, std::string>& GetDeityMap();
|
{ Deity::Agnostic2, Deity::Bitmask::Agnostic },
|
||||||
|
{ Deity::Bertoxxulous, Deity::Bitmask::Bertoxxulous },
|
||||||
} /*deity*/
|
{ Deity::BrellSirilis, Deity::Bitmask::BrellSirilis },
|
||||||
|
{ Deity::CazicThule, Deity::Bitmask::CazicThule },
|
||||||
} /*EQEmu*/
|
{ Deity::ErollisiMarr, Deity::Bitmask::ErollisiMarr },
|
||||||
|
{ Deity::Bristlebane, Deity::Bitmask::Bristlebane },
|
||||||
|
{ Deity::Innoruuk, Deity::Bitmask::Innoruuk },
|
||||||
|
{ Deity::Karana, Deity::Bitmask::Karana },
|
||||||
|
{ Deity::MithanielMarr, Deity::Bitmask::MithanielMarr },
|
||||||
|
{ Deity::Prexus, Deity::Bitmask::Prexus },
|
||||||
|
{ Deity::Quellious, Deity::Bitmask::Quellious },
|
||||||
|
{ Deity::RallosZek, Deity::Bitmask::RallosZek },
|
||||||
|
{ Deity::RodcetNife, Deity::Bitmask::RodcetNife },
|
||||||
|
{ Deity::SolusekRo, Deity::Bitmask::SolusekRo },
|
||||||
|
{ Deity::TheTribunal, Deity::Bitmask::TheTribunal },
|
||||||
|
{ Deity::Tunare, Deity::Bitmask::Tunare },
|
||||||
|
{ Deity::Veeshan, Deity::Bitmask::Veeshan }
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* COMMON_DEITY_H */
|
#endif /* COMMON_DEITY_H */
|
||||||
|
|||||||
+61
-338
@@ -59,103 +59,40 @@ int16 EQ::invtype::GetInvTypeSize(int16 inv_type) {
|
|||||||
return local_array[inv_type];
|
return local_array[inv_type];
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* EQ::bug::CategoryIDToCategoryName(CategoryID category_id) {
|
uint32 Bug::GetID(const std::string& category_name)
|
||||||
switch (category_id) {
|
{
|
||||||
case catVideo:
|
for (const auto& e : bug_category_names) {
|
||||||
return "Video";
|
if (e.second == category_name) {
|
||||||
case catAudio:
|
return e.first;
|
||||||
return "Audio";
|
}
|
||||||
case catPathing:
|
|
||||||
return "Pathing";
|
|
||||||
case catQuest:
|
|
||||||
return "Quest";
|
|
||||||
case catTradeskills:
|
|
||||||
return "Tradeskills";
|
|
||||||
case catSpellStacking:
|
|
||||||
return "Spell stacking";
|
|
||||||
case catDoorsPortals:
|
|
||||||
return "Doors/Portals";
|
|
||||||
case catItems:
|
|
||||||
return "Items";
|
|
||||||
case catNPC:
|
|
||||||
return "NPC";
|
|
||||||
case catDialogs:
|
|
||||||
return "Dialogs";
|
|
||||||
case catLoNTCG:
|
|
||||||
return "LoN - TCG";
|
|
||||||
case catMercenaries:
|
|
||||||
return "Mercenaries";
|
|
||||||
case catOther:
|
|
||||||
default:
|
|
||||||
return "Other";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EQ::bug::CategoryID EQ::bug::CategoryNameToCategoryID(const char* category_name) {
|
|
||||||
if (!category_name)
|
|
||||||
return catOther;
|
|
||||||
|
|
||||||
if (!strcmp(category_name, "Video"))
|
|
||||||
return catVideo;
|
|
||||||
if (!strcmp(category_name, "Audio"))
|
|
||||||
return catAudio;
|
|
||||||
if (!strcmp(category_name, "Pathing"))
|
|
||||||
return catPathing;
|
|
||||||
if (!strcmp(category_name, "Quest"))
|
|
||||||
return catQuest;
|
|
||||||
if (!strcmp(category_name, "Tradeskills"))
|
|
||||||
return catTradeskills;
|
|
||||||
if (!strcmp(category_name, "Spell stacking"))
|
|
||||||
return catSpellStacking;
|
|
||||||
if (!strcmp(category_name, "Doors/Portals"))
|
|
||||||
return catDoorsPortals;
|
|
||||||
if (!strcmp(category_name, "Items"))
|
|
||||||
return catItems;
|
|
||||||
if (!strcmp(category_name, "NPC"))
|
|
||||||
return catNPC;
|
|
||||||
if (!strcmp(category_name, "Dialogs"))
|
|
||||||
return catDialogs;
|
|
||||||
if (!strcmp(category_name, "LoN - TCG"))
|
|
||||||
return catLoNTCG;
|
|
||||||
if (!strcmp(category_name, "Mercenaries"))
|
|
||||||
return catMercenaries;
|
|
||||||
|
|
||||||
return catOther;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *EQ::constants::GetStanceName(StanceType stance_type) {
|
|
||||||
switch (stance_type) {
|
|
||||||
case stanceUnknown:
|
|
||||||
return "Unknown";
|
|
||||||
case stancePassive:
|
|
||||||
return "Passive";
|
|
||||||
case stanceBalanced:
|
|
||||||
return "Balanced";
|
|
||||||
case stanceEfficient:
|
|
||||||
return "Efficient";
|
|
||||||
case stanceReactive:
|
|
||||||
return "Reactive";
|
|
||||||
case stanceAggressive:
|
|
||||||
return "Aggressive";
|
|
||||||
case stanceAssist:
|
|
||||||
return "Assist";
|
|
||||||
case stanceBurn:
|
|
||||||
return "Burn";
|
|
||||||
case stanceEfficient2:
|
|
||||||
return "Efficient2";
|
|
||||||
case stanceBurnAE:
|
|
||||||
return "BurnAE";
|
|
||||||
default:
|
|
||||||
return "Invalid";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int EQ::constants::ConvertStanceTypeToIndex(StanceType stance_type) {
|
|
||||||
if (EQ::ValueWithin(stance_type, EQ::constants::stancePassive, EQ::constants::stanceBurnAE)) {
|
|
||||||
return (stance_type - EQ::constants::stancePassive);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return Bug::Category::Other;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Bug::GetName(uint32 category_id)
|
||||||
|
{
|
||||||
|
return IsValid(category_id) ? bug_category_names[category_id] : "UNKNOWN BUG CATEGORY";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bug::IsValid(uint32 category_id)
|
||||||
|
{
|
||||||
|
return bug_category_names.find(category_id) != bug_category_names.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Stance::GetName(uint8 stance_id)
|
||||||
|
{
|
||||||
|
return IsValid(stance_id) ? stance_names[stance_id] : "UNKNOWN STANCE";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Stance::IsValid(uint8 stance_id)
|
||||||
|
{
|
||||||
|
return stance_names.find(stance_id) != stance_names.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 Stance::GetIndex(uint8 stance_id)
|
||||||
|
{
|
||||||
|
return IsValid(stance_id) ? (stance_id - Stance::Passive) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<uint8, std::string>& EQ::constants::GetLanguageMap()
|
const std::map<uint8, std::string>& EQ::constants::GetLanguageMap()
|
||||||
@@ -249,102 +186,6 @@ std::string EQ::constants::GetFlyModeName(int8 flymode_id)
|
|||||||
return EQ::constants::GetFlyModeMap().find(flymode_id)->second;
|
return EQ::constants::GetFlyModeMap().find(flymode_id)->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<bodyType, std::string>& EQ::constants::GetBodyTypeMap()
|
|
||||||
{
|
|
||||||
static const std::map<bodyType, std::string> bodytype_map = {
|
|
||||||
{ BT_Humanoid, "Humanoid" },
|
|
||||||
{ BT_Lycanthrope, "Lycanthrope" },
|
|
||||||
{ BT_Undead, "Undead" },
|
|
||||||
{ BT_Giant, "Giant" },
|
|
||||||
{ BT_Construct, "Construct" },
|
|
||||||
{ BT_Extraplanar, "Extraplanar" },
|
|
||||||
{ BT_Magical, "Magical" },
|
|
||||||
{ BT_SummonedUndead, "Summoned Undead" },
|
|
||||||
{ BT_RaidGiant, "Raid Giant" },
|
|
||||||
{ BT_RaidColdain, "Raid Coldain" },
|
|
||||||
{ BT_NoTarget, "Untargetable" },
|
|
||||||
{ BT_Vampire, "Vampire" },
|
|
||||||
{ BT_Atenha_Ra, "Aten Ha Ra" },
|
|
||||||
{ BT_Greater_Akheva, "Greater Akheva" },
|
|
||||||
{ BT_Khati_Sha, "Khati Sha" },
|
|
||||||
{ BT_Seru, "Seru" },
|
|
||||||
{ BT_Grieg_Veneficus, "Grieg Veneficus" },
|
|
||||||
{ BT_Draz_Nurakk, "Draz Nurakk" },
|
|
||||||
{ BT_Zek, "Zek" },
|
|
||||||
{ BT_Luggald, "Luggald" },
|
|
||||||
{ BT_Animal, "Animal" },
|
|
||||||
{ BT_Insect, "Insect" },
|
|
||||||
{ BT_Monster, "Monster" },
|
|
||||||
{ BT_Summoned, "Summoned" },
|
|
||||||
{ BT_Plant, "Plant" },
|
|
||||||
{ BT_Dragon, "Dragon" },
|
|
||||||
{ BT_Summoned2, "Summoned 2" },
|
|
||||||
{ BT_Summoned3, "Summoned 3" },
|
|
||||||
{ BT_Dragon2, "Dragon 2" },
|
|
||||||
{ BT_VeliousDragon, "Velious Dragon" },
|
|
||||||
{ BT_Familiar, "Familiar" },
|
|
||||||
{ BT_Dragon3, "Dragon 3" },
|
|
||||||
{ BT_Boxes, "Boxes" },
|
|
||||||
{ BT_Muramite, "Muramite" },
|
|
||||||
{ BT_NoTarget2, "Untargetable 2" },
|
|
||||||
{ BT_SwarmPet, "Swarm Pet" },
|
|
||||||
{ BT_MonsterSummon, "Monster Summon" },
|
|
||||||
{ BT_InvisMan, "Invisible Man" },
|
|
||||||
{ BT_Special, "Special" },
|
|
||||||
};
|
|
||||||
|
|
||||||
return bodytype_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string EQ::constants::GetBodyTypeName(bodyType bodytype_id)
|
|
||||||
{
|
|
||||||
if (EQ::constants::GetBodyTypeMap().find(bodytype_id) != EQ::constants::GetBodyTypeMap().end()) {
|
|
||||||
return EQ::constants::GetBodyTypeMap().find(bodytype_id)->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::map<uint8, std::string>& EQ::constants::GetAccountStatusMap()
|
|
||||||
{
|
|
||||||
static const std::map<uint8, std::string> account_status_map = {
|
|
||||||
{ AccountStatus::Player, "Player" },
|
|
||||||
{ AccountStatus::Steward, "Steward" },
|
|
||||||
{ AccountStatus::ApprenticeGuide, "Apprentice Guide" },
|
|
||||||
{ AccountStatus::Guide, "Guide" },
|
|
||||||
{ AccountStatus::QuestTroupe, "Quest Troupe" },
|
|
||||||
{ AccountStatus::SeniorGuide, "Senior Guide" },
|
|
||||||
{ AccountStatus::GMTester, "GM Tester" },
|
|
||||||
{ AccountStatus::EQSupport, "EQ Support" },
|
|
||||||
{ AccountStatus::GMStaff, "GM Staff" },
|
|
||||||
{ AccountStatus::GMAdmin, "GM Admin" },
|
|
||||||
{ AccountStatus::GMLeadAdmin, "GM Lead Admin" },
|
|
||||||
{ AccountStatus::QuestMaster, "Quest Master" },
|
|
||||||
{ AccountStatus::GMAreas, "GM Areas" },
|
|
||||||
{ AccountStatus::GMCoder, "GM Coder" },
|
|
||||||
{ AccountStatus::GMMgmt, "GM Mgmt" },
|
|
||||||
{ AccountStatus::GMImpossible, "GM Impossible" },
|
|
||||||
{ AccountStatus::Max, "GM Max" }
|
|
||||||
};
|
|
||||||
|
|
||||||
return account_status_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string EQ::constants::GetAccountStatusName(uint8 account_status)
|
|
||||||
{
|
|
||||||
for (
|
|
||||||
auto status_level = EQ::constants::GetAccountStatusMap().rbegin();
|
|
||||||
status_level != EQ::constants::GetAccountStatusMap().rend();
|
|
||||||
++status_level
|
|
||||||
) {
|
|
||||||
if (account_status >= status_level->first) {
|
|
||||||
return status_level->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::map<uint8, std::string>& EQ::constants::GetConsiderLevelMap()
|
const std::map<uint8, std::string>& EQ::constants::GetConsiderLevelMap()
|
||||||
{
|
{
|
||||||
static const std::map<uint8, std::string> consider_level_map = {
|
static const std::map<uint8, std::string> consider_level_map = {
|
||||||
@@ -435,84 +276,6 @@ std::string EQ::constants::GetSpawnAnimationName(uint8 animation_id)
|
|||||||
return EQ::constants::GetSpawnAnimationMap().find(animation_id)->second;
|
return EQ::constants::GetSpawnAnimationMap().find(animation_id)->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<int, std::string>& EQ::constants::GetObjectTypeMap()
|
|
||||||
{
|
|
||||||
static const std::map<int, std::string> object_type_map = {
|
|
||||||
{ ObjectTypes::SmallBag, "Small Bag" },
|
|
||||||
{ ObjectTypes::LargeBag, "Large Bag" },
|
|
||||||
{ ObjectTypes::Quiver, "Quiver" },
|
|
||||||
{ ObjectTypes::BeltPouch, "Belt Pouch" },
|
|
||||||
{ ObjectTypes::WristPouch, "Wrist Pouch" },
|
|
||||||
{ ObjectTypes::Backpack, "Backpack" },
|
|
||||||
{ ObjectTypes::SmallChest, "Small Chest" },
|
|
||||||
{ ObjectTypes::LargeChest, "Large Chest" },
|
|
||||||
{ ObjectTypes::Bandolier, "Bandolier" },
|
|
||||||
{ ObjectTypes::Medicine, "Medicine" },
|
|
||||||
{ ObjectTypes::Tinkering, "Tinkering" },
|
|
||||||
{ ObjectTypes::Lexicon, "Lexicon" },
|
|
||||||
{ ObjectTypes::PoisonMaking, "Mortar and Pestle" },
|
|
||||||
{ ObjectTypes::Quest, "Quest" },
|
|
||||||
{ ObjectTypes::MixingBowl, "Mixing Bowl" },
|
|
||||||
{ ObjectTypes::Baking, "Baking" },
|
|
||||||
{ ObjectTypes::Tailoring, "Tailoring" },
|
|
||||||
{ ObjectTypes::Blacksmithing, "Blacksmithing" },
|
|
||||||
{ ObjectTypes::Fletching, "Fletching" },
|
|
||||||
{ ObjectTypes::Brewing, "Brewing" },
|
|
||||||
{ ObjectTypes::JewelryMaking, "Jewelry Making" },
|
|
||||||
{ ObjectTypes::Pottery, "Pottery" },
|
|
||||||
{ ObjectTypes::Kiln, "Kiln" },
|
|
||||||
{ ObjectTypes::KeyMaker, "Key Maker" },
|
|
||||||
{ ObjectTypes::ResearchWIZ, "Lexicon" },
|
|
||||||
{ ObjectTypes::ResearchMAG, "Lexicon" },
|
|
||||||
{ ObjectTypes::ResearchNEC, "Lexicon" },
|
|
||||||
{ ObjectTypes::ResearchENC, "Lexicon" },
|
|
||||||
{ ObjectTypes::Unknown, "Unknown" },
|
|
||||||
{ ObjectTypes::ResearchPractice, "Lexicon" },
|
|
||||||
{ ObjectTypes::Alchemy, "Alchemy" },
|
|
||||||
{ ObjectTypes::HighElfForge, "High Elf Forge" },
|
|
||||||
{ ObjectTypes::DarkElfForge, "Dark Elf Forge" },
|
|
||||||
{ ObjectTypes::OgreForge, "Ogre Forge" },
|
|
||||||
{ ObjectTypes::DwarfForge, "Dwarf Forge" },
|
|
||||||
{ ObjectTypes::GnomeForge, "Gnome Forge" },
|
|
||||||
{ ObjectTypes::BarbarianForge, "Barbarian Forge" },
|
|
||||||
{ ObjectTypes::IksarForge, "Iksar Forge" },
|
|
||||||
{ ObjectTypes::HumanForgeOne, "Human Forge" },
|
|
||||||
{ ObjectTypes::HumanForgeTwo, "Human Forge" },
|
|
||||||
{ ObjectTypes::HalflingTailoringOne, "Halfling Tailoring" },
|
|
||||||
{ ObjectTypes::HalflingTailoringTwo, "Halfling Tailoring" },
|
|
||||||
{ ObjectTypes::EruditeTailoring, "Erudite Tailoring" },
|
|
||||||
{ ObjectTypes::WoodElfTailoring, "Wood Elf Tailoring" },
|
|
||||||
{ ObjectTypes::WoodElfFletching, "Wood Elf Fletching" },
|
|
||||||
{ ObjectTypes::IksarPottery, "Iksar Pottery" },
|
|
||||||
{ ObjectTypes::Fishing, "Fishing" },
|
|
||||||
{ ObjectTypes::TrollForge, "Troll Forge" },
|
|
||||||
{ ObjectTypes::WoodElfForge, "Wood Elf Forge" },
|
|
||||||
{ ObjectTypes::HalflingForge, "Halfling Forge" },
|
|
||||||
{ ObjectTypes::EruditeForge, "Erudite Forge" },
|
|
||||||
{ ObjectTypes::Merchant, "Merchant" },
|
|
||||||
{ ObjectTypes::FroglokForge, "Froglok Forge" },
|
|
||||||
{ ObjectTypes::Augmenter, "Augmenter" },
|
|
||||||
{ ObjectTypes::Churn, "Churn" },
|
|
||||||
{ ObjectTypes::TransformationMold, "Transformation Mold" },
|
|
||||||
{ ObjectTypes::DetransformationMold, "Detransformation Mold" },
|
|
||||||
{ ObjectTypes::Unattuner, "Unattuner" },
|
|
||||||
{ ObjectTypes::TradeskillBag, "Tradeskill Bag" },
|
|
||||||
{ ObjectTypes::CollectibleBag, "Collectible Bag" },
|
|
||||||
{ ObjectTypes::NoDeposit, "No Deposit" }
|
|
||||||
};
|
|
||||||
|
|
||||||
return object_type_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string EQ::constants::GetObjectTypeName(int object_type)
|
|
||||||
{
|
|
||||||
if (!EQ::ValueWithin(object_type, ObjectTypes::SmallBag, ObjectTypes::NoDeposit)) {
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
return EQ::constants::GetObjectTypeMap().find(object_type)->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::map<uint8, std::string> &EQ::constants::GetWeatherTypeMap()
|
const std::map<uint8, std::string> &EQ::constants::GetWeatherTypeMap()
|
||||||
{
|
{
|
||||||
static const std::map<uint8, std::string> weather_type_map = {
|
static const std::map<uint8, std::string> weather_type_map = {
|
||||||
@@ -640,79 +403,14 @@ std::string EQ::constants::GetAppearanceTypeName(uint32 appearance_type)
|
|||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<uint32, std::string>& EQ::constants::GetSpecialAbilityMap()
|
std::string SpecialAbility::GetName(int ability_id)
|
||||||
{
|
{
|
||||||
static const std::map<uint32, std::string> special_ability_map = {
|
return IsValid(ability_id) ? special_ability_names[ability_id] : "UNKNOWN SPECIAL ABILITY";
|
||||||
{ SPECATK_SUMMON, "Summon" },
|
|
||||||
{ SPECATK_ENRAGE, "Enrage" },
|
|
||||||
{ SPECATK_RAMPAGE, "Rampage" },
|
|
||||||
{ SPECATK_AREA_RAMPAGE, "Area Rampage" },
|
|
||||||
{ SPECATK_FLURRY, "Flurry" },
|
|
||||||
{ SPECATK_TRIPLE, "Triple Attack" },
|
|
||||||
{ SPECATK_QUAD, "Quadruple Attack" },
|
|
||||||
{ SPECATK_INNATE_DW, "Dual Wield" },
|
|
||||||
{ SPECATK_BANE, "Bane Attack" },
|
|
||||||
{ SPECATK_MAGICAL, "Magical Attack" },
|
|
||||||
{ SPECATK_RANGED_ATK, "Ranged Attack" },
|
|
||||||
{ UNSLOWABLE, "Immune to Slow" },
|
|
||||||
{ UNMEZABLE, "Immune to Mesmerize" },
|
|
||||||
{ UNCHARMABLE, "Immune to Charm" },
|
|
||||||
{ UNSTUNABLE, "Immune to Stun" },
|
|
||||||
{ UNSNAREABLE, "Immune to Snare" },
|
|
||||||
{ UNFEARABLE, "Immune to Fear" },
|
|
||||||
{ UNDISPELLABLE, "Immune to Dispell" },
|
|
||||||
{ IMMUNE_MELEE, "Immune to Melee" },
|
|
||||||
{ IMMUNE_MAGIC, "Immune to Magic" },
|
|
||||||
{ IMMUNE_FLEEING, "Immune to Fleeing" },
|
|
||||||
{ IMMUNE_MELEE_EXCEPT_BANE, "Immune to Melee except Bane" },
|
|
||||||
{ IMMUNE_MELEE_NONMAGICAL, "Immune to Non-Magical Melee" },
|
|
||||||
{ IMMUNE_AGGRO, "Immune to Aggro" },
|
|
||||||
{ IMMUNE_AGGRO_ON, "Immune to Being Aggro" },
|
|
||||||
{ IMMUNE_CASTING_FROM_RANGE, "Immune to Ranged Spells" },
|
|
||||||
{ IMMUNE_FEIGN_DEATH, "Immune to Feign Death" },
|
|
||||||
{ IMMUNE_TAUNT, "Immune to Taunt" },
|
|
||||||
{ NPC_TUNNELVISION, "Tunnel Vision" },
|
|
||||||
{ NPC_NO_BUFFHEAL_FRIENDS, "Does Not Heal of Buff Allies" },
|
|
||||||
{ IMMUNE_PACIFY, "Immune to Pacify" },
|
|
||||||
{ LEASH, "Leashed" },
|
|
||||||
{ TETHER, "Tethered" },
|
|
||||||
{ DESTRUCTIBLE_OBJECT, "Destructible Object" },
|
|
||||||
{ NO_HARM_FROM_CLIENT, "Immune to Harm from Client" },
|
|
||||||
{ ALWAYS_FLEE, "Always Flees" },
|
|
||||||
{ FLEE_PERCENT, "Flee Percentage" },
|
|
||||||
{ ALLOW_BENEFICIAL, "Allows Beneficial Spells" },
|
|
||||||
{ DISABLE_MELEE, "Melee is Disabled" },
|
|
||||||
{ NPC_CHASE_DISTANCE, "Chase Distance" },
|
|
||||||
{ ALLOW_TO_TANK, "Allowed to Tank" },
|
|
||||||
{ IGNORE_ROOT_AGGRO_RULES, "Ignores Root Aggro" },
|
|
||||||
{ CASTING_RESIST_DIFF, "Casting Resist Difficulty" },
|
|
||||||
{ COUNTER_AVOID_DAMAGE, "Counter Damage Avoidance" },
|
|
||||||
{ PROX_AGGRO, "Proximity Aggro" },
|
|
||||||
{ IMMUNE_RANGED_ATTACKS, "Immune to Ranged Attacks" },
|
|
||||||
{ IMMUNE_DAMAGE_CLIENT, "Immune to Client Damage" },
|
|
||||||
{ IMMUNE_DAMAGE_NPC, "Immune to NPC Damage" },
|
|
||||||
{ IMMUNE_AGGRO_CLIENT, "Immune to Client Aggro" },
|
|
||||||
{ IMMUNE_AGGRO_NPC, "Immune to NPC Aggro" },
|
|
||||||
{ MODIFY_AVOID_DAMAGE, "Modify Damage Avoidance" },
|
|
||||||
{ IMMUNE_FADING_MEMORIES, "Immune to Memory Fades" },
|
|
||||||
{ IMMUNE_OPEN, "Immune to Open" },
|
|
||||||
{ IMMUNE_ASSASSINATE, "Immune to Assassinate" },
|
|
||||||
{ IMMUNE_HEADSHOT, "Immune to Headshot" },
|
|
||||||
{ IMMUNE_AGGRO_BOT, "Immune to Bot Aggro" },
|
|
||||||
{ IMMUNE_DAMAGE_BOT, "Immune to Bot Damage" },
|
|
||||||
};
|
|
||||||
|
|
||||||
return special_ability_map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EQ::constants::GetSpecialAbilityName(uint32 ability_id)
|
bool SpecialAbility::IsValid(int ability_id)
|
||||||
{
|
{
|
||||||
const auto& a = EQ::constants::GetSpecialAbilityMap().find(ability_id);
|
return special_ability_names.find(ability_id) != special_ability_names.end();
|
||||||
if (a != EQ::constants::GetSpecialAbilityMap().end()) {
|
|
||||||
return a->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<uint32, std::string>& EQ::constants::GetConsiderColorMap()
|
const std::map<uint32, std::string>& EQ::constants::GetConsiderColorMap()
|
||||||
@@ -736,3 +434,28 @@ std::string EQ::constants::GetConsiderColorName(uint32 consider_color)
|
|||||||
const auto& c = EQ::constants::GetConsiderColorMap().find(consider_color);
|
const auto& c = EQ::constants::GetConsiderColorMap().find(consider_color);
|
||||||
return c != EQ::constants::GetConsiderColorMap().end() ? c->second : std::string();
|
return c != EQ::constants::GetConsiderColorMap().end() ? c->second : std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string AccountStatus::GetName(uint8 account_status)
|
||||||
|
{
|
||||||
|
for (
|
||||||
|
auto e = account_status_names.rbegin();
|
||||||
|
e != account_status_names.rend();
|
||||||
|
++e
|
||||||
|
) {
|
||||||
|
if (account_status >= e->first) {
|
||||||
|
return e->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "UNKNOWN ACCOUNT STATUS";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ComparisonType::GetName(uint8 type)
|
||||||
|
{
|
||||||
|
return IsValid(type) ? comparison_types[type] : "UNKNOWN COMPARISON TYPE";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComparisonType::IsValid(uint8 type)
|
||||||
|
{
|
||||||
|
return comparison_types.find(type) != comparison_types.end();
|
||||||
|
}
|
||||||
|
|||||||
+283
-221
@@ -26,6 +26,76 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
namespace AccountStatus {
|
||||||
|
constexpr uint8 Player = 0;
|
||||||
|
constexpr uint8 Steward = 10;
|
||||||
|
constexpr uint8 ApprenticeGuide = 20;
|
||||||
|
constexpr uint8 Guide = 50;
|
||||||
|
constexpr uint8 QuestTroupe = 80;
|
||||||
|
constexpr uint8 SeniorGuide = 81;
|
||||||
|
constexpr uint8 GMTester = 85;
|
||||||
|
constexpr uint8 EQSupport = 90;
|
||||||
|
constexpr uint8 GMStaff = 95;
|
||||||
|
constexpr uint8 GMAdmin = 100;
|
||||||
|
constexpr uint8 GMLeadAdmin = 150;
|
||||||
|
constexpr uint8 QuestMaster = 160;
|
||||||
|
constexpr uint8 GMAreas = 170;
|
||||||
|
constexpr uint8 GMCoder = 180;
|
||||||
|
constexpr uint8 GMMgmt = 200;
|
||||||
|
constexpr uint8 GMImpossible = 250;
|
||||||
|
constexpr uint8 Max = 255;
|
||||||
|
|
||||||
|
std::string GetName(uint8 account_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::map<uint8, std::string> account_status_names = {
|
||||||
|
{ AccountStatus::Player, "Player" },
|
||||||
|
{ AccountStatus::Steward, "Steward" },
|
||||||
|
{ AccountStatus::ApprenticeGuide, "Apprentice Guide" },
|
||||||
|
{ AccountStatus::Guide, "Guide" },
|
||||||
|
{ AccountStatus::QuestTroupe, "Quest Troupe" },
|
||||||
|
{ AccountStatus::SeniorGuide, "Senior Guide" },
|
||||||
|
{ AccountStatus::GMTester, "GM Tester" },
|
||||||
|
{ AccountStatus::EQSupport, "EQ Support" },
|
||||||
|
{ AccountStatus::GMStaff, "GM Staff" },
|
||||||
|
{ AccountStatus::GMAdmin, "GM Admin" },
|
||||||
|
{ AccountStatus::GMLeadAdmin, "GM Lead Admin" },
|
||||||
|
{ AccountStatus::QuestMaster, "Quest Master" },
|
||||||
|
{ AccountStatus::GMAreas, "GM Areas" },
|
||||||
|
{ AccountStatus::GMCoder, "GM Coder" },
|
||||||
|
{ AccountStatus::GMMgmt, "GM Mgmt" },
|
||||||
|
{ AccountStatus::GMImpossible, "GM Impossible" },
|
||||||
|
{ AccountStatus::Max, "GM Max" }
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace ComparisonType {
|
||||||
|
constexpr uint8 Equal = 0;
|
||||||
|
constexpr uint8 NotEqual = 1;
|
||||||
|
constexpr uint8 GreaterOrEqual = 2;
|
||||||
|
constexpr uint8 LesserOrEqual = 3;
|
||||||
|
constexpr uint8 Greater = 4;
|
||||||
|
constexpr uint8 Lesser = 5;
|
||||||
|
constexpr uint8 Any = 6;
|
||||||
|
constexpr uint8 NotAny = 7;
|
||||||
|
constexpr uint8 Between = 8;
|
||||||
|
constexpr uint8 NotBetween = 9;
|
||||||
|
|
||||||
|
std::string GetName(uint8 type);
|
||||||
|
bool IsValid(uint8 type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::map<uint8, std::string> comparison_types = {
|
||||||
|
{ ComparisonType::Equal, "Equal" },
|
||||||
|
{ ComparisonType::NotEqual, "Not Equal" },
|
||||||
|
{ ComparisonType::GreaterOrEqual, "Greater or Equal" },
|
||||||
|
{ ComparisonType::LesserOrEqual, "Lesser or Equal" },
|
||||||
|
{ ComparisonType::Greater, "Greater" },
|
||||||
|
{ ComparisonType::Lesser, "Lesser" },
|
||||||
|
{ ComparisonType::Any, "Any" },
|
||||||
|
{ ComparisonType::NotAny, "Not Any" },
|
||||||
|
{ ComparisonType::Between, "Between" },
|
||||||
|
{ ComparisonType::NotBetween, "Not Between" },
|
||||||
|
};
|
||||||
|
|
||||||
// local definitions are the result of using hybrid-client or server-only values and methods
|
// local definitions are the result of using hybrid-client or server-only values and methods
|
||||||
namespace EQ
|
namespace EQ
|
||||||
@@ -204,19 +274,6 @@ namespace EQ
|
|||||||
const size_t SAY_LINK_CLOSER_SIZE = 1;
|
const size_t SAY_LINK_CLOSER_SIZE = 1;
|
||||||
const size_t SAY_LINK_MAXIMUM_SIZE = (SAY_LINK_OPENER_SIZE + SAY_LINK_BODY_SIZE + SAY_LINK_TEXT_SIZE + SAY_LINK_CLOSER_SIZE);
|
const size_t SAY_LINK_MAXIMUM_SIZE = (SAY_LINK_OPENER_SIZE + SAY_LINK_BODY_SIZE + SAY_LINK_TEXT_SIZE + SAY_LINK_CLOSER_SIZE);
|
||||||
|
|
||||||
enum StanceType : int {
|
|
||||||
stanceUnknown = 0,
|
|
||||||
stancePassive,
|
|
||||||
stanceBalanced,
|
|
||||||
stanceEfficient,
|
|
||||||
stanceReactive,
|
|
||||||
stanceAggressive,
|
|
||||||
stanceAssist,
|
|
||||||
stanceBurn,
|
|
||||||
stanceEfficient2,
|
|
||||||
stanceBurnAE
|
|
||||||
};
|
|
||||||
|
|
||||||
enum BotSpellIDs : int {
|
enum BotSpellIDs : int {
|
||||||
Warrior = 3001,
|
Warrior = 3001,
|
||||||
Cleric,
|
Cleric,
|
||||||
@@ -267,70 +324,6 @@ namespace EQ
|
|||||||
Looting
|
Looting
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ObjectTypes : int {
|
|
||||||
SmallBag,
|
|
||||||
LargeBag,
|
|
||||||
Quiver,
|
|
||||||
BeltPouch,
|
|
||||||
WristPouch,
|
|
||||||
Backpack,
|
|
||||||
SmallChest,
|
|
||||||
LargeChest,
|
|
||||||
Bandolier,
|
|
||||||
Medicine,
|
|
||||||
Tinkering,
|
|
||||||
Lexicon,
|
|
||||||
PoisonMaking,
|
|
||||||
Quest,
|
|
||||||
MixingBowl,
|
|
||||||
Baking,
|
|
||||||
Tailoring,
|
|
||||||
Blacksmithing,
|
|
||||||
Fletching,
|
|
||||||
Brewing,
|
|
||||||
JewelryMaking,
|
|
||||||
Pottery,
|
|
||||||
Kiln,
|
|
||||||
KeyMaker,
|
|
||||||
ResearchWIZ,
|
|
||||||
ResearchMAG,
|
|
||||||
ResearchNEC,
|
|
||||||
ResearchENC,
|
|
||||||
Unknown,
|
|
||||||
ResearchPractice,
|
|
||||||
Alchemy,
|
|
||||||
HighElfForge,
|
|
||||||
DarkElfForge,
|
|
||||||
OgreForge,
|
|
||||||
DwarfForge,
|
|
||||||
GnomeForge,
|
|
||||||
BarbarianForge,
|
|
||||||
IksarForge,
|
|
||||||
HumanForgeOne,
|
|
||||||
HumanForgeTwo,
|
|
||||||
HalflingTailoringOne,
|
|
||||||
HalflingTailoringTwo,
|
|
||||||
EruditeTailoring,
|
|
||||||
WoodElfTailoring,
|
|
||||||
WoodElfFletching,
|
|
||||||
IksarPottery,
|
|
||||||
Fishing,
|
|
||||||
TrollForge,
|
|
||||||
WoodElfForge,
|
|
||||||
HalflingForge,
|
|
||||||
EruditeForge,
|
|
||||||
Merchant,
|
|
||||||
FroglokForge,
|
|
||||||
Augmenter,
|
|
||||||
Churn,
|
|
||||||
TransformationMold,
|
|
||||||
DetransformationMold,
|
|
||||||
Unattuner,
|
|
||||||
TradeskillBag,
|
|
||||||
CollectibleBag,
|
|
||||||
NoDeposit
|
|
||||||
};
|
|
||||||
|
|
||||||
enum WeatherTypes : uint8 {
|
enum WeatherTypes : uint8 {
|
||||||
None,
|
None,
|
||||||
Raining,
|
Raining,
|
||||||
@@ -356,9 +349,6 @@ namespace EQ
|
|||||||
Proximity
|
Proximity
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *GetStanceName(StanceType stance_type);
|
|
||||||
int ConvertStanceTypeToIndex(StanceType stance_type);
|
|
||||||
|
|
||||||
extern const std::map<uint8, std::string>& GetLanguageMap();
|
extern const std::map<uint8, std::string>& GetLanguageMap();
|
||||||
std::string GetLanguageName(uint8 language_id);
|
std::string GetLanguageName(uint8 language_id);
|
||||||
|
|
||||||
@@ -368,12 +358,6 @@ namespace EQ
|
|||||||
extern const std::map<int8, std::string>& GetFlyModeMap();
|
extern const std::map<int8, std::string>& GetFlyModeMap();
|
||||||
std::string GetFlyModeName(int8 flymode_id);
|
std::string GetFlyModeName(int8 flymode_id);
|
||||||
|
|
||||||
extern const std::map<bodyType, std::string>& GetBodyTypeMap();
|
|
||||||
std::string GetBodyTypeName(bodyType bodytype_id);
|
|
||||||
|
|
||||||
extern const std::map<uint8, std::string>& GetAccountStatusMap();
|
|
||||||
std::string GetAccountStatusName(uint8 account_status);
|
|
||||||
|
|
||||||
extern const std::map<uint8, std::string>& GetConsiderLevelMap();
|
extern const std::map<uint8, std::string>& GetConsiderLevelMap();
|
||||||
std::string GetConsiderLevelName(uint8 consider_level);
|
std::string GetConsiderLevelName(uint8 consider_level);
|
||||||
|
|
||||||
@@ -386,9 +370,6 @@ namespace EQ
|
|||||||
extern const std::map<uint8, std::string>& GetSpawnAnimationMap();
|
extern const std::map<uint8, std::string>& GetSpawnAnimationMap();
|
||||||
std::string GetSpawnAnimationName(uint8 animation_id);
|
std::string GetSpawnAnimationName(uint8 animation_id);
|
||||||
|
|
||||||
extern const std::map<int, std::string>& GetObjectTypeMap();
|
|
||||||
std::string GetObjectTypeName(int object_type);
|
|
||||||
|
|
||||||
extern const std::map<uint8, std::string>& GetWeatherTypeMap();
|
extern const std::map<uint8, std::string>& GetWeatherTypeMap();
|
||||||
std::string GetWeatherTypeName(uint8 weather_type);
|
std::string GetWeatherTypeName(uint8 weather_type);
|
||||||
|
|
||||||
@@ -401,16 +382,9 @@ namespace EQ
|
|||||||
extern const std::map<uint32, std::string>& GetAppearanceTypeMap();
|
extern const std::map<uint32, std::string>& GetAppearanceTypeMap();
|
||||||
std::string GetAppearanceTypeName(uint32 animation_type);
|
std::string GetAppearanceTypeName(uint32 animation_type);
|
||||||
|
|
||||||
extern const std::map<uint32, std::string>& GetSpecialAbilityMap();
|
|
||||||
std::string GetSpecialAbilityName(uint32 ability_id);
|
|
||||||
|
|
||||||
extern const std::map<uint32, std::string>& GetConsiderColorMap();
|
extern const std::map<uint32, std::string>& GetConsiderColorMap();
|
||||||
std::string GetConsiderColorName(uint32 consider_color);
|
std::string GetConsiderColorName(uint32 consider_color);
|
||||||
|
|
||||||
const int STANCE_TYPE_FIRST = stancePassive;
|
|
||||||
const int STANCE_TYPE_LAST = stanceBurnAE;
|
|
||||||
const int STANCE_TYPE_COUNT = stanceBurnAE;
|
|
||||||
|
|
||||||
} /*constants*/
|
} /*constants*/
|
||||||
|
|
||||||
namespace profile {
|
namespace profile {
|
||||||
@@ -464,37 +438,6 @@ namespace EQ
|
|||||||
|
|
||||||
} // namespace spells
|
} // namespace spells
|
||||||
|
|
||||||
namespace bug {
|
|
||||||
enum CategoryID : uint32 {
|
|
||||||
catOther = 0,
|
|
||||||
catVideo,
|
|
||||||
catAudio,
|
|
||||||
catPathing,
|
|
||||||
catQuest,
|
|
||||||
catTradeskills,
|
|
||||||
catSpellStacking,
|
|
||||||
catDoorsPortals,
|
|
||||||
catItems,
|
|
||||||
catNPC,
|
|
||||||
catDialogs,
|
|
||||||
catLoNTCG,
|
|
||||||
catMercenaries
|
|
||||||
};
|
|
||||||
|
|
||||||
enum OptionalInfoFlag : uint32 {
|
|
||||||
infoNoOptionalInfo = 0x0,
|
|
||||||
infoCanDuplicate = 0x1,
|
|
||||||
infoCrashBug = 0x2,
|
|
||||||
infoTargetInfo = 0x4,
|
|
||||||
infoCharacterFlags = 0x8,
|
|
||||||
infoUnknownValue = 0xFFFFFFF0
|
|
||||||
};
|
|
||||||
|
|
||||||
const char* CategoryIDToCategoryName(CategoryID category_id);
|
|
||||||
CategoryID CategoryNameToCategoryID(const char* category_name);
|
|
||||||
|
|
||||||
} // namespace bug
|
|
||||||
|
|
||||||
enum WaypointStatus : int {
|
enum WaypointStatus : int {
|
||||||
RoamBoxPauseInProgress = -3,
|
RoamBoxPauseInProgress = -3,
|
||||||
QuestControlNoGrid = -2,
|
QuestControlNoGrid = -2,
|
||||||
@@ -508,7 +451,7 @@ namespace EQ
|
|||||||
Raid,
|
Raid,
|
||||||
Guild
|
Guild
|
||||||
};
|
};
|
||||||
}; // namespace consent
|
};
|
||||||
} /*EQEmu*/
|
} /*EQEmu*/
|
||||||
|
|
||||||
enum ServerLockType : int {
|
enum ServerLockType : int {
|
||||||
@@ -517,26 +460,6 @@ enum ServerLockType : int {
|
|||||||
Unlock
|
Unlock
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AccountStatus : uint8 {
|
|
||||||
Player = 0,
|
|
||||||
Steward = 10,
|
|
||||||
ApprenticeGuide = 20,
|
|
||||||
Guide = 50,
|
|
||||||
QuestTroupe = 80,
|
|
||||||
SeniorGuide = 81,
|
|
||||||
GMTester = 85,
|
|
||||||
EQSupport = 90,
|
|
||||||
GMStaff = 95,
|
|
||||||
GMAdmin = 100,
|
|
||||||
GMLeadAdmin = 150,
|
|
||||||
QuestMaster = 160,
|
|
||||||
GMAreas = 170,
|
|
||||||
GMCoder = 180,
|
|
||||||
GMMgmt = 200,
|
|
||||||
GMImpossible = 250,
|
|
||||||
Max = 255
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Invisibility : uint8 {
|
enum Invisibility : uint8 {
|
||||||
Visible,
|
Visible,
|
||||||
Invisible,
|
Invisible,
|
||||||
@@ -588,19 +511,6 @@ enum ReloadWorld : uint8 {
|
|||||||
ForceRepop
|
ForceRepop
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BucketComparison : uint8 {
|
|
||||||
BucketEqualTo = 0,
|
|
||||||
BucketNotEqualTo,
|
|
||||||
BucketGreaterThanOrEqualTo,
|
|
||||||
BucketLesserThanOrEqualTo,
|
|
||||||
BucketGreaterThan,
|
|
||||||
BucketLesserThan,
|
|
||||||
BucketIsAny,
|
|
||||||
BucketIsNotAny,
|
|
||||||
BucketIsBetween,
|
|
||||||
BucketIsNotBetween
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class EntityFilterType {
|
enum class EntityFilterType {
|
||||||
All,
|
All,
|
||||||
Bots,
|
Bots,
|
||||||
@@ -614,67 +524,131 @@ enum class ApplySpellType {
|
|||||||
Raid
|
Raid
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
namespace SpecialAbility {
|
||||||
SPECATK_SUMMON = 1,
|
constexpr int Summon = 1;
|
||||||
SPECATK_ENRAGE = 2,
|
constexpr int Enrage = 2;
|
||||||
SPECATK_RAMPAGE = 3,
|
constexpr int Rampage = 3;
|
||||||
SPECATK_AREA_RAMPAGE = 4,
|
constexpr int AreaRampage = 4;
|
||||||
SPECATK_FLURRY = 5,
|
constexpr int Flurry = 5;
|
||||||
SPECATK_TRIPLE = 6,
|
constexpr int TripleAttack = 6;
|
||||||
SPECATK_QUAD = 7,
|
constexpr int QuadrupleAttack = 7;
|
||||||
SPECATK_INNATE_DW = 8,
|
constexpr int DualWield = 8;
|
||||||
SPECATK_BANE = 9,
|
constexpr int BaneAttack = 9;
|
||||||
SPECATK_MAGICAL = 10,
|
constexpr int MagicalAttack = 10;
|
||||||
SPECATK_RANGED_ATK = 11,
|
constexpr int RangedAttack = 11;
|
||||||
UNSLOWABLE = 12,
|
constexpr int SlowImmunity = 12;
|
||||||
UNMEZABLE = 13,
|
constexpr int MesmerizeImmunity = 13;
|
||||||
UNCHARMABLE = 14,
|
constexpr int CharmImmunity = 14;
|
||||||
UNSTUNABLE = 15,
|
constexpr int StunImmunity = 15;
|
||||||
UNSNAREABLE = 16,
|
constexpr int SnareImmunity = 16;
|
||||||
UNFEARABLE = 17,
|
constexpr int FearImmunity = 17;
|
||||||
UNDISPELLABLE = 18,
|
constexpr int DispellImmunity = 18;
|
||||||
IMMUNE_MELEE = 19,
|
constexpr int MeleeImmunity = 19;
|
||||||
IMMUNE_MAGIC = 20,
|
constexpr int MagicImmunity = 20;
|
||||||
IMMUNE_FLEEING = 21,
|
constexpr int FleeingImmunity = 21;
|
||||||
IMMUNE_MELEE_EXCEPT_BANE = 22,
|
constexpr int MeleeImmunityExceptBane = 22;
|
||||||
IMMUNE_MELEE_NONMAGICAL = 23,
|
constexpr int MeleeImmunityExceptMagical = 23;
|
||||||
IMMUNE_AGGRO = 24,
|
constexpr int AggroImmunity = 24;
|
||||||
IMMUNE_AGGRO_ON = 25,
|
constexpr int BeingAggroImmunity = 25;
|
||||||
IMMUNE_CASTING_FROM_RANGE = 26,
|
constexpr int CastingFromRangeImmunity = 26;
|
||||||
IMMUNE_FEIGN_DEATH = 27,
|
constexpr int FeignDeathImmunity = 27;
|
||||||
IMMUNE_TAUNT = 28,
|
constexpr int TauntImmunity = 28;
|
||||||
NPC_TUNNELVISION = 29,
|
constexpr int TunnelVision = 29;
|
||||||
NPC_NO_BUFFHEAL_FRIENDS = 30,
|
constexpr int NoBuffHealFriends = 30;
|
||||||
IMMUNE_PACIFY = 31,
|
constexpr int PacifyImmunity = 31;
|
||||||
LEASH = 32,
|
constexpr int Leash = 32;
|
||||||
TETHER = 33,
|
constexpr int Tether = 33;
|
||||||
DESTRUCTIBLE_OBJECT = 34,
|
constexpr int DestructibleObject = 34;
|
||||||
NO_HARM_FROM_CLIENT = 35,
|
constexpr int HarmFromClientImmunity = 35;
|
||||||
ALWAYS_FLEE = 36,
|
constexpr int AlwaysFlee = 36;
|
||||||
FLEE_PERCENT = 37,
|
constexpr int FleePercent = 37;
|
||||||
ALLOW_BENEFICIAL = 38,
|
constexpr int AllowBeneficial = 38;
|
||||||
DISABLE_MELEE = 39,
|
constexpr int DisableMelee = 39;
|
||||||
NPC_CHASE_DISTANCE = 40,
|
constexpr int NPCChaseDistance = 40;
|
||||||
ALLOW_TO_TANK = 41,
|
constexpr int AllowedToTank = 41;
|
||||||
IGNORE_ROOT_AGGRO_RULES = 42,
|
constexpr int IgnoreRootAggroRules = 42;
|
||||||
CASTING_RESIST_DIFF = 43,
|
constexpr int CastingResistDifficulty = 43;
|
||||||
COUNTER_AVOID_DAMAGE = 44, // Modify by percent NPC's opponents chance to riposte, block, parry or dodge individually, or for all skills
|
constexpr int CounterAvoidDamage = 44;
|
||||||
PROX_AGGRO = 45,
|
constexpr int ProximityAggro = 45;
|
||||||
IMMUNE_RANGED_ATTACKS = 46,
|
constexpr int RangedAttackImmunity = 46;
|
||||||
IMMUNE_DAMAGE_CLIENT = 47,
|
constexpr int ClientDamageImmunity = 47;
|
||||||
IMMUNE_DAMAGE_NPC = 48,
|
constexpr int NPCDamageImmunity = 48;
|
||||||
IMMUNE_AGGRO_CLIENT = 49,
|
constexpr int ClientAggroImmunity = 49;
|
||||||
IMMUNE_AGGRO_NPC = 50,
|
constexpr int NPCAggroImmunity = 50;
|
||||||
MODIFY_AVOID_DAMAGE = 51, // Modify by percent the NPCs chance to riposte, block, parry or dodge individually, or for all skills
|
constexpr int ModifyAvoidDamage = 51;
|
||||||
IMMUNE_FADING_MEMORIES = 52,
|
constexpr int MemoryFadeImmunity = 52;
|
||||||
IMMUNE_OPEN = 53,
|
constexpr int OpenImmunity = 53;
|
||||||
IMMUNE_ASSASSINATE = 54,
|
constexpr int AssassinateImmunity = 54;
|
||||||
IMMUNE_HEADSHOT = 55,
|
constexpr int HeadshotImmunity = 55;
|
||||||
IMMUNE_AGGRO_BOT = 56,
|
constexpr int BotAggroImmunity = 56;
|
||||||
IMMUNE_DAMAGE_BOT = 57,
|
constexpr int BotDamageImmunity = 57;
|
||||||
MAX_SPECIAL_ATTACK = 58
|
constexpr int Max = 58;
|
||||||
};
|
|
||||||
|
|
||||||
|
constexpr int MaxParameters = 9;
|
||||||
|
|
||||||
|
std::string GetName(int ability_id);
|
||||||
|
bool IsValid(int ability_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::map<int, std::string> special_ability_names = {
|
||||||
|
{ SpecialAbility::Summon, "Summon" },
|
||||||
|
{ SpecialAbility::Enrage, "Enrage" },
|
||||||
|
{ SpecialAbility::Rampage, "Rampage" },
|
||||||
|
{ SpecialAbility::AreaRampage, "Area Rampage" },
|
||||||
|
{ SpecialAbility::Flurry, "Flurry" },
|
||||||
|
{ SpecialAbility::TripleAttack, "Triple Attack" },
|
||||||
|
{ SpecialAbility::QuadrupleAttack, "Quadruple Attack" },
|
||||||
|
{ SpecialAbility::DualWield, "Dual Wield" },
|
||||||
|
{ SpecialAbility::BaneAttack, "Bane Attack" },
|
||||||
|
{ SpecialAbility::MagicalAttack, "Magical Attack" },
|
||||||
|
{ SpecialAbility::RangedAttack, "Ranged Attack" },
|
||||||
|
{ SpecialAbility::SlowImmunity, "Immune to Slow" },
|
||||||
|
{ SpecialAbility::MesmerizeImmunity, "Immune to Mesmerize" },
|
||||||
|
{ SpecialAbility::CharmImmunity, "Immune to Charm" },
|
||||||
|
{ SpecialAbility::StunImmunity, "Immune to Stun" },
|
||||||
|
{ SpecialAbility::SnareImmunity, "Immune to Snare" },
|
||||||
|
{ SpecialAbility::FearImmunity, "Immune to Fear" },
|
||||||
|
{ SpecialAbility::DispellImmunity, "Immune to Dispell" },
|
||||||
|
{ SpecialAbility::MeleeImmunity, "Immune to Melee" },
|
||||||
|
{ SpecialAbility::MagicImmunity, "Immune to Magic" },
|
||||||
|
{ SpecialAbility::FleeingImmunity, "Immune to Fleeing" },
|
||||||
|
{ SpecialAbility::MeleeImmunityExceptBane, "Immune to Melee except Bane" },
|
||||||
|
{ SpecialAbility::MeleeImmunityExceptMagical, "Immune to Non-Magical Melee" },
|
||||||
|
{ SpecialAbility::AggroImmunity, "Immune to Aggro" },
|
||||||
|
{ SpecialAbility::BeingAggroImmunity, "Immune to Being Aggro" },
|
||||||
|
{ SpecialAbility::CastingFromRangeImmunity, "Immune to Ranged Spells" },
|
||||||
|
{ SpecialAbility::FeignDeathImmunity, "Immune to Feign Death" },
|
||||||
|
{ SpecialAbility::TauntImmunity, "Immune to Taunt" },
|
||||||
|
{ SpecialAbility::TunnelVision, "Tunnel Vision" },
|
||||||
|
{ SpecialAbility::NoBuffHealFriends, "Does Not Heal or Buff Allies" },
|
||||||
|
{ SpecialAbility::PacifyImmunity, "Immune to Pacify" },
|
||||||
|
{ SpecialAbility::Leash, "Leashed" },
|
||||||
|
{ SpecialAbility::Tether, "Tethered" },
|
||||||
|
{ SpecialAbility::DestructibleObject, "Destructible Object" },
|
||||||
|
{ SpecialAbility::HarmFromClientImmunity, "Immune to Harm from Client" },
|
||||||
|
{ SpecialAbility::AlwaysFlee, "Always Flees" },
|
||||||
|
{ SpecialAbility::FleePercent, "Flee Percentage" },
|
||||||
|
{ SpecialAbility::AllowBeneficial, "Allows Beneficial Spells" },
|
||||||
|
{ SpecialAbility::DisableMelee, "Melee is Disabled" },
|
||||||
|
{ SpecialAbility::NPCChaseDistance, "Chase Distance" },
|
||||||
|
{ SpecialAbility::AllowedToTank, "Allowed to Tank" },
|
||||||
|
{ SpecialAbility::IgnoreRootAggroRules, "Ignores Root Aggro" },
|
||||||
|
{ SpecialAbility::CastingResistDifficulty, "Casting Resist Difficulty" },
|
||||||
|
{ SpecialAbility::CounterAvoidDamage, "Counter Damage Avoidance" },
|
||||||
|
{ SpecialAbility::ProximityAggro, "Proximity Aggro" },
|
||||||
|
{ SpecialAbility::RangedAttackImmunity, "Immune to Ranged Attacks" },
|
||||||
|
{ SpecialAbility::ClientDamageImmunity, "Immune to Client Damage" },
|
||||||
|
{ SpecialAbility::NPCDamageImmunity, "Immune to NPC Damage" },
|
||||||
|
{ SpecialAbility::ClientAggroImmunity, "Immune to Client Aggro" },
|
||||||
|
{ SpecialAbility::NPCAggroImmunity, "Immune to NPC Aggro" },
|
||||||
|
{ SpecialAbility::ModifyAvoidDamage, "Modify Damage Avoidance" },
|
||||||
|
{ SpecialAbility::MemoryFadeImmunity, "Immune to Memory Fades" },
|
||||||
|
{ SpecialAbility::OpenImmunity, "Immune to Open" },
|
||||||
|
{ SpecialAbility::AssassinateImmunity, "Immune to Assassinate" },
|
||||||
|
{ SpecialAbility::HeadshotImmunity, "Immune to Headshot" },
|
||||||
|
{ SpecialAbility::BotAggroImmunity, "Immune to Bot Aggro" },
|
||||||
|
{ SpecialAbility::BotDamageImmunity, "Immune to Bot Damage" },
|
||||||
|
};
|
||||||
|
|
||||||
namespace HeroicBonusBucket
|
namespace HeroicBonusBucket
|
||||||
{
|
{
|
||||||
@@ -700,4 +674,92 @@ namespace HeroicBonusBucket
|
|||||||
const std::string DexEnduranceRegen = "HDEX-EnduranceRegen";
|
const std::string DexEnduranceRegen = "HDEX-EnduranceRegen";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Bug {
|
||||||
|
namespace Category {
|
||||||
|
constexpr uint32 Other = 0;
|
||||||
|
constexpr uint32 Video = 1;
|
||||||
|
constexpr uint32 Audio = 2;
|
||||||
|
constexpr uint32 Pathing = 3;
|
||||||
|
constexpr uint32 Quest = 4;
|
||||||
|
constexpr uint32 Tradeskills = 5;
|
||||||
|
constexpr uint32 SpellStacking = 6;
|
||||||
|
constexpr uint32 DoorsPortals = 7;
|
||||||
|
constexpr uint32 Items = 8;
|
||||||
|
constexpr uint32 NPC = 9;
|
||||||
|
constexpr uint32 Dialogs = 10;
|
||||||
|
constexpr uint32 LoNTCG = 11;
|
||||||
|
constexpr uint32 Mercenaries = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace InformationFlag {
|
||||||
|
constexpr uint32 None = 0;
|
||||||
|
constexpr uint32 Repeatable = 1;
|
||||||
|
constexpr uint32 Crash = 2;
|
||||||
|
constexpr uint32 TargetInfo = 4;
|
||||||
|
constexpr uint32 CharacterFlags = 8;
|
||||||
|
constexpr uint32 Unknown = 4294967280;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 GetID(const std::string& category_name);
|
||||||
|
std::string GetName(uint32 category_id);
|
||||||
|
bool IsValid(uint32 category_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::map<uint32, std::string> bug_category_names = {
|
||||||
|
{ Bug::Category::Other, "Other" },
|
||||||
|
{ Bug::Category::Video, "Video" },
|
||||||
|
{ Bug::Category::Audio, "Audio" },
|
||||||
|
{ Bug::Category::Pathing, "Pathing" },
|
||||||
|
{ Bug::Category::Quest, "Quest" },
|
||||||
|
{ Bug::Category::Tradeskills, "Tradeskills" },
|
||||||
|
{ Bug::Category::SpellStacking, "Spell Stacking" },
|
||||||
|
{ Bug::Category::DoorsPortals, "Doors and Portals" },
|
||||||
|
{ Bug::Category::Items, "Items" },
|
||||||
|
{ Bug::Category::NPC, "NPC" },
|
||||||
|
{ Bug::Category::Dialogs, "Dialogs" },
|
||||||
|
{ Bug::Category::LoNTCG, "LoN - TCG" },
|
||||||
|
{ Bug::Category::Mercenaries, "Mercenaries" }
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Stance {
|
||||||
|
constexpr uint32 Unknown = 0;
|
||||||
|
constexpr uint32 Passive = 1;
|
||||||
|
constexpr uint32 Balanced = 2;
|
||||||
|
constexpr uint32 Efficient = 3;
|
||||||
|
constexpr uint32 Reactive = 4;
|
||||||
|
constexpr uint32 Aggressive = 5;
|
||||||
|
constexpr uint32 Assist = 6;
|
||||||
|
constexpr uint32 Burn = 7;
|
||||||
|
constexpr uint32 Efficient2 = 8;
|
||||||
|
constexpr uint32 AEBurn = 9;
|
||||||
|
|
||||||
|
std::string GetName(uint8 stance_id);
|
||||||
|
uint8 GetIndex(uint8 stance_id);
|
||||||
|
bool IsValid(uint8 stance_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::map<uint32, std::string> stance_names = {
|
||||||
|
{ Stance::Unknown, "Unknown" },
|
||||||
|
{ Stance::Passive, "Passive" },
|
||||||
|
{ Stance::Balanced, "Balanced" },
|
||||||
|
{ Stance::Efficient, "Efficient" },
|
||||||
|
{ Stance::Reactive, "Reactive" },
|
||||||
|
{ Stance::Aggressive, "Aggressive" },
|
||||||
|
{ Stance::Assist, "Assist" },
|
||||||
|
{ Stance::Burn, "Burn" },
|
||||||
|
{ Stance::Efficient2, "Efficient" },
|
||||||
|
{ Stance::AEBurn, "AE Burn" }
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace PCNPCOnlyFlagType {
|
||||||
|
constexpr int PC = 1;
|
||||||
|
constexpr int NPC = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace BookType {
|
||||||
|
constexpr uint8 Scroll = 0;
|
||||||
|
constexpr uint8 Book = 1;
|
||||||
|
constexpr uint8 ItemInfo = 2;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /*COMMON_EMU_CONSTANTS_H*/
|
#endif /*COMMON_EMU_CONSTANTS_H*/
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ N(OP_Buff),
|
|||||||
N(OP_BuffCreate),
|
N(OP_BuffCreate),
|
||||||
N(OP_BuffRemoveRequest),
|
N(OP_BuffRemoveRequest),
|
||||||
N(OP_Bug),
|
N(OP_Bug),
|
||||||
|
N(OP_BuyerItems),
|
||||||
N(OP_CameraEffect),
|
N(OP_CameraEffect),
|
||||||
N(OP_Camp),
|
N(OP_Camp),
|
||||||
N(OP_CancelSneakHide),
|
N(OP_CancelSneakHide),
|
||||||
@@ -533,6 +534,7 @@ N(OP_Stamina),
|
|||||||
N(OP_Stun),
|
N(OP_Stun),
|
||||||
N(OP_Surname),
|
N(OP_Surname),
|
||||||
N(OP_SwapSpell),
|
N(OP_SwapSpell),
|
||||||
|
N(OP_SystemFingerprint),
|
||||||
N(OP_TargetBuffs),
|
N(OP_TargetBuffs),
|
||||||
N(OP_TargetCommand),
|
N(OP_TargetCommand),
|
||||||
N(OP_TargetHoTT),
|
N(OP_TargetHoTT),
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ const char* EQ::versions::ClientVersionName(ClientVersion client_version)
|
|||||||
return "RoF";
|
return "RoF";
|
||||||
case ClientVersion::RoF2:
|
case ClientVersion::RoF2:
|
||||||
return "RoF2";
|
return "RoF2";
|
||||||
|
case ClientVersion::Larion:
|
||||||
|
return "Larion";
|
||||||
default:
|
default:
|
||||||
return "Invalid Version";
|
return "Invalid Version";
|
||||||
};
|
};
|
||||||
@@ -76,6 +78,8 @@ uint32 EQ::versions::ConvertClientVersionToClientVersionBit(ClientVersion client
|
|||||||
return bitRoF;
|
return bitRoF;
|
||||||
case ClientVersion::RoF2:
|
case ClientVersion::RoF2:
|
||||||
return bitRoF2;
|
return bitRoF2;
|
||||||
|
case ClientVersion::Larion:
|
||||||
|
return bitLarion;
|
||||||
default:
|
default:
|
||||||
return bitUnknown;
|
return bitUnknown;
|
||||||
}
|
}
|
||||||
@@ -96,6 +100,8 @@ EQ::versions::ClientVersion EQ::versions::ConvertClientVersionBitToClientVersion
|
|||||||
return ClientVersion::RoF;
|
return ClientVersion::RoF;
|
||||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::RoF2) - 1)) :
|
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::RoF2) - 1)) :
|
||||||
return ClientVersion::RoF2;
|
return ClientVersion::RoF2;
|
||||||
|
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::Larion) - 1)):
|
||||||
|
return ClientVersion::Larion;
|
||||||
default:
|
default:
|
||||||
return ClientVersion::Unknown;
|
return ClientVersion::Unknown;
|
||||||
}
|
}
|
||||||
@@ -184,6 +190,8 @@ const char* EQ::versions::MobVersionName(MobVersion mob_version)
|
|||||||
return "RoF";
|
return "RoF";
|
||||||
case MobVersion::RoF2:
|
case MobVersion::RoF2:
|
||||||
return "RoF2";
|
return "RoF2";
|
||||||
|
case MobVersion::Larion:
|
||||||
|
return "Larion";
|
||||||
case MobVersion::NPC:
|
case MobVersion::NPC:
|
||||||
return "NPC";
|
return "NPC";
|
||||||
case MobVersion::NPCMerchant:
|
case MobVersion::NPCMerchant:
|
||||||
@@ -212,6 +220,8 @@ const char* EQ::versions::MobVersionName(MobVersion mob_version)
|
|||||||
return "Offline RoF";
|
return "Offline RoF";
|
||||||
case MobVersion::OfflineRoF2:
|
case MobVersion::OfflineRoF2:
|
||||||
return "Offline RoF2";
|
return "Offline RoF2";
|
||||||
|
case MobVersion::OfflineLarion:
|
||||||
|
return "Offline Larion";
|
||||||
default:
|
default:
|
||||||
return "Invalid Version";
|
return "Invalid Version";
|
||||||
};
|
};
|
||||||
@@ -235,6 +245,8 @@ EQ::versions::ClientVersion EQ::versions::ConvertMobVersionToClientVersion(MobVe
|
|||||||
return ClientVersion::RoF;
|
return ClientVersion::RoF;
|
||||||
case MobVersion::RoF2:
|
case MobVersion::RoF2:
|
||||||
return ClientVersion::RoF2;
|
return ClientVersion::RoF2;
|
||||||
|
case MobVersion::Larion:
|
||||||
|
return ClientVersion::Larion;
|
||||||
default:
|
default:
|
||||||
return ClientVersion::Unknown;
|
return ClientVersion::Unknown;
|
||||||
}
|
}
|
||||||
@@ -258,6 +270,8 @@ EQ::versions::MobVersion EQ::versions::ConvertClientVersionToMobVersion(ClientVe
|
|||||||
return MobVersion::RoF;
|
return MobVersion::RoF;
|
||||||
case ClientVersion::RoF2:
|
case ClientVersion::RoF2:
|
||||||
return MobVersion::RoF2;
|
return MobVersion::RoF2;
|
||||||
|
case ClientVersion::Larion:
|
||||||
|
return MobVersion::Larion;
|
||||||
default:
|
default:
|
||||||
return MobVersion::Unknown;
|
return MobVersion::Unknown;
|
||||||
}
|
}
|
||||||
@@ -278,6 +292,8 @@ EQ::versions::MobVersion EQ::versions::ConvertPCMobVersionToOfflinePCMobVersion(
|
|||||||
return MobVersion::OfflineRoF;
|
return MobVersion::OfflineRoF;
|
||||||
case MobVersion::RoF2:
|
case MobVersion::RoF2:
|
||||||
return MobVersion::OfflineRoF2;
|
return MobVersion::OfflineRoF2;
|
||||||
|
case MobVersion::Larion:
|
||||||
|
return MobVersion::OfflineLarion;
|
||||||
default:
|
default:
|
||||||
return MobVersion::Unknown;
|
return MobVersion::Unknown;
|
||||||
}
|
}
|
||||||
@@ -298,6 +314,8 @@ EQ::versions::MobVersion EQ::versions::ConvertOfflinePCMobVersionToPCMobVersion(
|
|||||||
return MobVersion::RoF;
|
return MobVersion::RoF;
|
||||||
case MobVersion::OfflineRoF2:
|
case MobVersion::OfflineRoF2:
|
||||||
return MobVersion::RoF2;
|
return MobVersion::RoF2;
|
||||||
|
case MobVersion::OfflineLarion:
|
||||||
|
return MobVersion::Larion;
|
||||||
default:
|
default:
|
||||||
return MobVersion::Unknown;
|
return MobVersion::Unknown;
|
||||||
}
|
}
|
||||||
@@ -318,6 +336,8 @@ EQ::versions::ClientVersion EQ::versions::ConvertOfflinePCMobVersionToClientVers
|
|||||||
return ClientVersion::RoF;
|
return ClientVersion::RoF;
|
||||||
case MobVersion::OfflineRoF2:
|
case MobVersion::OfflineRoF2:
|
||||||
return ClientVersion::RoF2;
|
return ClientVersion::RoF2;
|
||||||
|
case MobVersion::OfflineLarion:
|
||||||
|
return ClientVersion::Larion;
|
||||||
default:
|
default:
|
||||||
return ClientVersion::Unknown;
|
return ClientVersion::Unknown;
|
||||||
}
|
}
|
||||||
@@ -338,6 +358,8 @@ EQ::versions::MobVersion EQ::versions::ConvertClientVersionToOfflinePCMobVersion
|
|||||||
return MobVersion::OfflineRoF;
|
return MobVersion::OfflineRoF;
|
||||||
case ClientVersion::RoF2:
|
case ClientVersion::RoF2:
|
||||||
return MobVersion::OfflineRoF2;
|
return MobVersion::OfflineRoF2;
|
||||||
|
case ClientVersion::Larion:
|
||||||
|
return MobVersion::OfflineLarion;
|
||||||
default:
|
default:
|
||||||
return MobVersion::Unknown;
|
return MobVersion::Unknown;
|
||||||
}
|
}
|
||||||
@@ -388,6 +410,27 @@ const char* EQ::expansions::ExpansionName(Expansion expansion)
|
|||||||
return "Rain of Fear";
|
return "Rain of Fear";
|
||||||
case Expansion::CotF:
|
case Expansion::CotF:
|
||||||
return "Call of the Forsaken";
|
return "Call of the Forsaken";
|
||||||
|
case Expansion::TDS:
|
||||||
|
return "The Darkened Sea";
|
||||||
|
case Expansion::TBM:
|
||||||
|
return "The Broken Mirror";
|
||||||
|
case Expansion::EoK:
|
||||||
|
return "Empires of Kunark";
|
||||||
|
case Expansion::RoS:
|
||||||
|
return "Ring of Scale";
|
||||||
|
case Expansion::TBL:
|
||||||
|
return "The Burning Lands";
|
||||||
|
case Expansion::ToV:
|
||||||
|
return "Torment of Velious";
|
||||||
|
case Expansion::CoV:
|
||||||
|
return "Claws of Veeshan";
|
||||||
|
case Expansion::ToL:
|
||||||
|
return "Terror of Luclin";
|
||||||
|
case Expansion::NoS:
|
||||||
|
return "Night of Shadows";
|
||||||
|
case Expansion::LS:
|
||||||
|
return "Laurion's Song";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "Invalid Expansion";
|
return "Invalid Expansion";
|
||||||
}
|
}
|
||||||
@@ -441,6 +484,26 @@ uint32 EQ::expansions::ConvertExpansionToExpansionBit(Expansion expansion)
|
|||||||
return bitRoF;
|
return bitRoF;
|
||||||
case Expansion::CotF:
|
case Expansion::CotF:
|
||||||
return bitCotF;
|
return bitCotF;
|
||||||
|
case Expansion::TDS:
|
||||||
|
return bitTDS;
|
||||||
|
case Expansion::TBM:
|
||||||
|
return bitTBM;
|
||||||
|
case Expansion::EoK:
|
||||||
|
return bitEoK;
|
||||||
|
case Expansion::RoS:
|
||||||
|
return bitRoS;
|
||||||
|
case Expansion::TBL:
|
||||||
|
return bitTBL;
|
||||||
|
case Expansion::ToV:
|
||||||
|
return bitToV;
|
||||||
|
case Expansion::CoV:
|
||||||
|
return bitCoV;
|
||||||
|
case Expansion::ToL:
|
||||||
|
return bitToL;
|
||||||
|
case Expansion::NoS:
|
||||||
|
return bitNoS;
|
||||||
|
case Expansion::LS:
|
||||||
|
return bitLS;
|
||||||
default:
|
default:
|
||||||
return bitEverQuest;
|
return bitEverQuest;
|
||||||
}
|
}
|
||||||
@@ -489,6 +552,26 @@ EQ::expansions::Expansion EQ::expansions::ConvertExpansionBitToExpansion(uint32
|
|||||||
return Expansion::RoF;
|
return Expansion::RoF;
|
||||||
case bitCotF:
|
case bitCotF:
|
||||||
return Expansion::CotF;
|
return Expansion::CotF;
|
||||||
|
case bitTDS:
|
||||||
|
return Expansion::TDS;
|
||||||
|
case bitTBM:
|
||||||
|
return Expansion::TBM;
|
||||||
|
case bitEoK:
|
||||||
|
return Expansion::EoK;
|
||||||
|
case bitRoS:
|
||||||
|
return Expansion::RoS;
|
||||||
|
case bitTBL:
|
||||||
|
return Expansion::TBL;
|
||||||
|
case bitToV:
|
||||||
|
return Expansion::ToV;
|
||||||
|
case bitCoV:
|
||||||
|
return Expansion::CoV;
|
||||||
|
case bitToL:
|
||||||
|
return Expansion::ToL;
|
||||||
|
case bitNoS:
|
||||||
|
return Expansion::NoS;
|
||||||
|
case bitLS:
|
||||||
|
return Expansion::LS;
|
||||||
default:
|
default:
|
||||||
return Expansion::EverQuest;
|
return Expansion::EverQuest;
|
||||||
}
|
}
|
||||||
@@ -537,6 +620,26 @@ uint32 EQ::expansions::ConvertExpansionToExpansionsMask(Expansion expansion)
|
|||||||
return maskRoF;
|
return maskRoF;
|
||||||
case Expansion::CotF:
|
case Expansion::CotF:
|
||||||
return maskCotF;
|
return maskCotF;
|
||||||
|
case Expansion::TDS:
|
||||||
|
return maskTDS;
|
||||||
|
case Expansion::TBM:
|
||||||
|
return maskTBM;
|
||||||
|
case Expansion::EoK:
|
||||||
|
return maskEoK;
|
||||||
|
case Expansion::RoS:
|
||||||
|
return maskRoS;
|
||||||
|
case Expansion::TBL:
|
||||||
|
return maskTBL;
|
||||||
|
case Expansion::ToV:
|
||||||
|
return maskToV;
|
||||||
|
case Expansion::CoV:
|
||||||
|
return maskCoV;
|
||||||
|
case Expansion::ToL:
|
||||||
|
return maskToL;
|
||||||
|
case Expansion::NoS:
|
||||||
|
return maskNoS;
|
||||||
|
case Expansion::LS:
|
||||||
|
return maskLS;
|
||||||
default:
|
default:
|
||||||
return maskEverQuest;
|
return maskEverQuest;
|
||||||
}
|
}
|
||||||
|
|||||||
+45
-9
@@ -36,7 +36,8 @@ namespace EQ
|
|||||||
SoD, // Build: 'Dec 19 2008 15:22:49'
|
SoD, // Build: 'Dec 19 2008 15:22:49'
|
||||||
UF, // Build: 'Jun 8 2010 16:44:32'
|
UF, // Build: 'Jun 8 2010 16:44:32'
|
||||||
RoF, // Build: 'Dec 10 2012 17:35:44'
|
RoF, // Build: 'Dec 10 2012 17:35:44'
|
||||||
RoF2 // Build: 'May 10 2013 23:30:08'
|
RoF2, // Build: 'May 10 2013 23:30:08'
|
||||||
|
Larion
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ClientVersionBitmask : uint32 {
|
enum ClientVersionBitmask : uint32 {
|
||||||
@@ -48,6 +49,7 @@ namespace EQ
|
|||||||
bitUF = 0x00000010,
|
bitUF = 0x00000010,
|
||||||
bitRoF = 0x00000020,
|
bitRoF = 0x00000020,
|
||||||
bitRoF2 = 0x00000040,
|
bitRoF2 = 0x00000040,
|
||||||
|
bitLarion = 0x00000080,
|
||||||
maskUnknown = 0x00000000,
|
maskUnknown = 0x00000000,
|
||||||
maskTitaniumAndEarlier = 0x00000003,
|
maskTitaniumAndEarlier = 0x00000003,
|
||||||
maskSoFAndEarlier = 0x00000007,
|
maskSoFAndEarlier = 0x00000007,
|
||||||
@@ -59,10 +61,11 @@ namespace EQ
|
|||||||
maskUFAndLater = 0xFFFFFFF0,
|
maskUFAndLater = 0xFFFFFFF0,
|
||||||
maskRoFAndLater = 0xFFFFFFE0,
|
maskRoFAndLater = 0xFFFFFFE0,
|
||||||
maskRoF2AndLater = 0xFFFFFFC0,
|
maskRoF2AndLater = 0xFFFFFFC0,
|
||||||
|
maskLarionAndLater = 0xFFFFFF80,
|
||||||
maskAllClients = 0xFFFFFFFF
|
maskAllClients = 0xFFFFFFFF
|
||||||
};
|
};
|
||||||
|
|
||||||
const ClientVersion LastClientVersion = ClientVersion::RoF2;
|
const ClientVersion LastClientVersion = ClientVersion::Larion;
|
||||||
const size_t ClientVersionCount = (static_cast<size_t>(LastClientVersion) + 1);
|
const size_t ClientVersionCount = (static_cast<size_t>(LastClientVersion) + 1);
|
||||||
|
|
||||||
bool IsValidClientVersion(ClientVersion client_version);
|
bool IsValidClientVersion(ClientVersion client_version);
|
||||||
@@ -80,6 +83,7 @@ namespace EQ
|
|||||||
UF,
|
UF,
|
||||||
RoF,
|
RoF,
|
||||||
RoF2,
|
RoF2,
|
||||||
|
Larion,
|
||||||
NPC,
|
NPC,
|
||||||
NPCMerchant,
|
NPCMerchant,
|
||||||
Merc,
|
Merc,
|
||||||
@@ -93,13 +97,14 @@ namespace EQ
|
|||||||
OfflineSoD,
|
OfflineSoD,
|
||||||
OfflineUF,
|
OfflineUF,
|
||||||
OfflineRoF,
|
OfflineRoF,
|
||||||
OfflineRoF2
|
OfflineRoF2,
|
||||||
|
OfflineLarion
|
||||||
};
|
};
|
||||||
|
|
||||||
const MobVersion LastMobVersion = MobVersion::OfflineRoF2;
|
const MobVersion LastMobVersion = MobVersion::OfflineLarion;
|
||||||
const MobVersion LastPCMobVersion = MobVersion::RoF2;
|
const MobVersion LastPCMobVersion = MobVersion::Larion;
|
||||||
const MobVersion LastNonPCMobVersion = MobVersion::BotPet;
|
const MobVersion LastNonPCMobVersion = MobVersion::BotPet;
|
||||||
const MobVersion LastOfflinePCMobVersion = MobVersion::OfflineRoF2;
|
const MobVersion LastOfflinePCMobVersion = MobVersion::OfflineLarion;
|
||||||
const size_t MobVersionCount = (static_cast<size_t>(LastMobVersion) + 1);
|
const size_t MobVersionCount = (static_cast<size_t>(LastMobVersion) + 1);
|
||||||
|
|
||||||
bool IsValidMobVersion(MobVersion mob_version);
|
bool IsValidMobVersion(MobVersion mob_version);
|
||||||
@@ -131,7 +136,8 @@ namespace EQ
|
|||||||
ucsSoDCombined = 'D',
|
ucsSoDCombined = 'D',
|
||||||
ucsUFCombined = 'E',
|
ucsUFCombined = 'E',
|
||||||
ucsRoFCombined = 'F',
|
ucsRoFCombined = 'F',
|
||||||
ucsRoF2Combined = 'G'
|
ucsRoF2Combined = 'G',
|
||||||
|
ucsLaurionCombined = 'G'
|
||||||
};
|
};
|
||||||
|
|
||||||
} /*versions*/
|
} /*versions*/
|
||||||
@@ -158,7 +164,17 @@ namespace EQ
|
|||||||
HoT,
|
HoT,
|
||||||
VoA,
|
VoA,
|
||||||
RoF,
|
RoF,
|
||||||
CotF
|
CotF,
|
||||||
|
TDS,
|
||||||
|
TBM,
|
||||||
|
EoK,
|
||||||
|
RoS,
|
||||||
|
TBL,
|
||||||
|
ToV,
|
||||||
|
CoV,
|
||||||
|
ToL,
|
||||||
|
NoS,
|
||||||
|
LS
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ExpansionBitmask : uint32 {
|
enum ExpansionBitmask : uint32 {
|
||||||
@@ -183,6 +199,16 @@ namespace EQ
|
|||||||
bitVoA = 0x00020000,
|
bitVoA = 0x00020000,
|
||||||
bitRoF = 0x00040000,
|
bitRoF = 0x00040000,
|
||||||
bitCotF = 0x00080000,
|
bitCotF = 0x00080000,
|
||||||
|
bitTDS = 0x00100000,
|
||||||
|
bitTBM = 0x00200000,
|
||||||
|
bitEoK = 0x00400000,
|
||||||
|
bitRoS = 0x00800000,
|
||||||
|
bitTBL = 0x01000000,
|
||||||
|
bitToV = 0x02000000,
|
||||||
|
bitCoV = 0x04000000,
|
||||||
|
bitToL = 0x08000000,
|
||||||
|
bitNoS = 0x10000000,
|
||||||
|
bitLS = 0x20000000,
|
||||||
maskEverQuest = 0x00000000,
|
maskEverQuest = 0x00000000,
|
||||||
maskRoK = 0x00000001,
|
maskRoK = 0x00000001,
|
||||||
maskSoV = 0x00000003,
|
maskSoV = 0x00000003,
|
||||||
@@ -203,7 +229,17 @@ namespace EQ
|
|||||||
maskHoT = 0x0001FFFF,
|
maskHoT = 0x0001FFFF,
|
||||||
maskVoA = 0x0003FFFF,
|
maskVoA = 0x0003FFFF,
|
||||||
maskRoF = 0x0007FFFF,
|
maskRoF = 0x0007FFFF,
|
||||||
maskCotF = 0x000FFFFF
|
maskCotF = 0x000FFFFF,
|
||||||
|
maskTDS = 0x001FFFFF,
|
||||||
|
maskTBM = 0x003FFFFF,
|
||||||
|
maskEoK = 0x007FFFFF,
|
||||||
|
maskRoS = 0x00FFFFFF,
|
||||||
|
maskTBL = 0x01FFFFFF,
|
||||||
|
maskToV = 0x03FFFFFF,
|
||||||
|
maskCoV = 0x07FFFFFF,
|
||||||
|
maskToL = 0x0FFFFFFF,
|
||||||
|
maskNoS = 0x1FFFFFFF,
|
||||||
|
maskLS = 0x3FFFFFFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* ExpansionName(Expansion expansion);
|
const char* ExpansionName(Expansion expansion);
|
||||||
|
|||||||
+7
-44
@@ -758,10 +758,10 @@ typedef enum {
|
|||||||
FilterFocusEffects = 22, //0=show, 1=hide
|
FilterFocusEffects = 22, //0=show, 1=hide
|
||||||
FilterPetSpells = 23, //0=show, 1=hide
|
FilterPetSpells = 23, //0=show, 1=hide
|
||||||
FilterHealOverTime = 24, //0=show, 1=mine only, 2=hide
|
FilterHealOverTime = 24, //0=show, 1=mine only, 2=hide
|
||||||
FilterUnknown25 = 25,
|
FilterItemSpeech = 25, //0=show, 1=hide // RoF2 Confirmed
|
||||||
FilterUnknown26 = 26,
|
FilterStrikethrough = 26, //0=show, 1=hide // RoF2 Confirmed
|
||||||
FilterUnknown27 = 27,
|
FilterStuns = 27, //0=show, 1=hide // RoF2 Confirmed
|
||||||
FilterUnknown28 = 28,
|
FilterBardSongsOnPets = 28, //0=show, 1=hide // RoF2 Confirmed
|
||||||
_FilterCount
|
_FilterCount
|
||||||
} eqFilterType;
|
} eqFilterType;
|
||||||
|
|
||||||
@@ -814,46 +814,6 @@ typedef enum {
|
|||||||
#define STAT_TIGER_CLAW 40
|
#define STAT_TIGER_CLAW 40
|
||||||
#define STAT_FRENZY 41
|
#define STAT_FRENZY 41
|
||||||
|
|
||||||
/*
|
|
||||||
** Recast timer types. Used as an off set to charProfileStruct timers.
|
|
||||||
**
|
|
||||||
** (Another orphaned enumeration...)
|
|
||||||
*/
|
|
||||||
enum RecastTimerTypes
|
|
||||||
{
|
|
||||||
RecTimer_0 = 0,
|
|
||||||
RecTimer_1,
|
|
||||||
RecTimer_WeaponHealClick, // 2
|
|
||||||
RecTimer_MuramiteBaneNukeClick, // 3
|
|
||||||
RecTimer_4,
|
|
||||||
RecTimer_DispellClick, // 5 (also click heal orbs?)
|
|
||||||
RecTimer_Epic, // 6
|
|
||||||
RecTimer_OoWBPClick, // 7
|
|
||||||
RecTimer_VishQuestClassItem, // 8
|
|
||||||
RecTimer_HealPotion, // 9
|
|
||||||
RecTimer_10,
|
|
||||||
RecTimer_11,
|
|
||||||
RecTimer_12,
|
|
||||||
RecTimer_13,
|
|
||||||
RecTimer_14,
|
|
||||||
RecTimer_15,
|
|
||||||
RecTimer_16,
|
|
||||||
RecTimer_17,
|
|
||||||
RecTimer_18,
|
|
||||||
RecTimer_ModRod, // 19
|
|
||||||
_RecTimerCount
|
|
||||||
};
|
|
||||||
|
|
||||||
enum GroupUpdateAction
|
|
||||||
{
|
|
||||||
GUA_Joined = 0,
|
|
||||||
GUA_Left = 1,
|
|
||||||
GUA_LastLeft = 6,
|
|
||||||
GUA_FullGroupInfo = 7,
|
|
||||||
GUA_MakeLeader = 8,
|
|
||||||
GUA_Started = 9
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8 DamageTypeSomething = 0x1C; //0x1c is something...
|
static const uint8 DamageTypeSomething = 0x1C; //0x1c is something...
|
||||||
static const uint8 DamageTypeFalling = 0xFC;
|
static const uint8 DamageTypeFalling = 0xFC;
|
||||||
static const uint8 DamageTypeSpell = 0xE7;
|
static const uint8 DamageTypeSpell = 0xE7;
|
||||||
@@ -1169,4 +1129,7 @@ enum ExpSource
|
|||||||
#define PARCEL_LIMIT 5
|
#define PARCEL_LIMIT 5
|
||||||
#define PARCEL_BEGIN_SLOT 1
|
#define PARCEL_BEGIN_SLOT 1
|
||||||
|
|
||||||
|
namespace DoorType {
|
||||||
|
constexpr uint32 BuyerStall = 155;
|
||||||
|
}
|
||||||
#endif /*COMMON_EQ_CONSTANTS_H*/
|
#endif /*COMMON_EQ_CONSTANTS_H*/
|
||||||
|
|||||||
@@ -104,6 +104,14 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
|
|||||||
RoF2::constants::EXPANSIONS_MASK,
|
RoF2::constants::EXPANSIONS_MASK,
|
||||||
RoF2::constants::CHARACTER_CREATION_LIMIT,
|
RoF2::constants::CHARACTER_CREATION_LIMIT,
|
||||||
RoF2::constants::SAY_LINK_BODY_SIZE
|
RoF2::constants::SAY_LINK_BODY_SIZE
|
||||||
|
),
|
||||||
|
/*[ClientVersion::Larion] =*/
|
||||||
|
EQ::constants::LookupEntry(
|
||||||
|
Larion::constants::EXPANSION,
|
||||||
|
Larion::constants::EXPANSION_BIT,
|
||||||
|
Larion::constants::EXPANSIONS_MASK,
|
||||||
|
Larion::constants::CHARACTER_CREATION_LIMIT,
|
||||||
|
Larion::constants::SAY_LINK_BODY_SIZE
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -370,6 +378,33 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
|||||||
RoF2::inventory::ConcatenateInvTypeLimbo,
|
RoF2::inventory::ConcatenateInvTypeLimbo,
|
||||||
RoF2::inventory::AllowOverLevelEquipment
|
RoF2::inventory::AllowOverLevelEquipment
|
||||||
),
|
),
|
||||||
|
/*[MobVersion::LS] =*/
|
||||||
|
EQ::inventory::LookupEntry(
|
||||||
|
EQ::inventory::LookupEntry::InventoryTypeSize_Struct(
|
||||||
|
EQ::invtype::POSSESSIONS_SIZE, RoF2::invtype::BANK_SIZE, RoF2::invtype::SHARED_BANK_SIZE,
|
||||||
|
RoF2::invtype::TRADE_SIZE, RoF2::invtype::WORLD_SIZE, RoF2::invtype::LIMBO_SIZE,
|
||||||
|
RoF2::invtype::TRIBUTE_SIZE, RoF2::invtype::TROPHY_TRIBUTE_SIZE, RoF2::invtype::GUILD_TRIBUTE_SIZE,
|
||||||
|
RoF2::invtype::MERCHANT_SIZE, RoF2::invtype::DELETED_SIZE, RoF2::invtype::CORPSE_SIZE,
|
||||||
|
RoF2::invtype::BAZAAR_SIZE, RoF2::invtype::INSPECT_SIZE, RoF2::invtype::REAL_ESTATE_SIZE,
|
||||||
|
RoF2::invtype::VIEW_MOD_PC_SIZE, RoF2::invtype::VIEW_MOD_BANK_SIZE, RoF2::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||||
|
RoF2::invtype::VIEW_MOD_LIMBO_SIZE, RoF2::invtype::ALT_STORAGE_SIZE, RoF2::invtype::ARCHIVED_SIZE,
|
||||||
|
RoF2::invtype::MAIL_SIZE, RoF2::invtype::GUILD_TROPHY_TRIBUTE_SIZE, RoF2::invtype::KRONO_SIZE,
|
||||||
|
RoF2::invtype::OTHER_SIZE
|
||||||
|
),
|
||||||
|
|
||||||
|
RoF2::invslot::EQUIPMENT_BITMASK,
|
||||||
|
RoF2::invslot::GENERAL_BITMASK,
|
||||||
|
RoF2::invslot::CURSOR_BITMASK,
|
||||||
|
RoF2::invslot::POSSESSIONS_BITMASK,
|
||||||
|
RoF2::invslot::CORPSE_BITMASK,
|
||||||
|
RoF2::invbag::SLOT_COUNT,
|
||||||
|
RoF2::invaug::SOCKET_COUNT,
|
||||||
|
|
||||||
|
RoF2::inventory::AllowEmptyBagInBag,
|
||||||
|
RoF2::inventory::AllowClickCastFromBag,
|
||||||
|
RoF2::inventory::ConcatenateInvTypeLimbo,
|
||||||
|
RoF2::inventory::AllowOverLevelEquipment
|
||||||
|
),
|
||||||
/*[MobVersion::NPC] =*/
|
/*[MobVersion::NPC] =*/
|
||||||
EQ::inventory::LookupEntry(
|
EQ::inventory::LookupEntry(
|
||||||
EQ::inventory::LookupEntry::InventoryTypeSize_Struct(
|
EQ::inventory::LookupEntry::InventoryTypeSize_Struct(
|
||||||
@@ -743,6 +778,33 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
|||||||
RoF2::invbag::SLOT_COUNT,
|
RoF2::invbag::SLOT_COUNT,
|
||||||
RoF2::invaug::SOCKET_COUNT,
|
RoF2::invaug::SOCKET_COUNT,
|
||||||
|
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
/*[MobVersion::OfflineLS] =*/
|
||||||
|
EQ::inventory::LookupEntry(
|
||||||
|
EQ::inventory::LookupEntry::InventoryTypeSize_Struct(
|
||||||
|
RoF2::INULL, RoF2::INULL, RoF2::INULL,
|
||||||
|
RoF2::invtype::TRADE_SIZE, RoF2::INULL, RoF2::INULL,
|
||||||
|
RoF2::INULL, RoF2::INULL, RoF2::INULL,
|
||||||
|
RoF2::invtype::MERCHANT_SIZE, RoF2::INULL, RoF2::INULL,
|
||||||
|
RoF2::invtype::BAZAAR_SIZE, RoF2::invtype::INSPECT_SIZE, RoF2::INULL,
|
||||||
|
RoF2::invtype::VIEW_MOD_PC_SIZE, RoF2::invtype::VIEW_MOD_BANK_SIZE, RoF2::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||||
|
RoF2::invtype::VIEW_MOD_LIMBO_SIZE, RoF2::INULL, RoF2::INULL,
|
||||||
|
RoF2::INULL, RoF2::INULL, RoF2::INULL,
|
||||||
|
RoF2::INULL
|
||||||
|
),
|
||||||
|
|
||||||
|
RoF2::INULL,
|
||||||
|
RoF2::INULL,
|
||||||
|
RoF2::INULL,
|
||||||
|
RoF2::INULL,
|
||||||
|
RoF2::INULL,
|
||||||
|
RoF2::invbag::SLOT_COUNT,
|
||||||
|
RoF2::invaug::SOCKET_COUNT,
|
||||||
|
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
@@ -994,6 +1056,10 @@ static const EQ::behavior::LookupEntry behavior_static_lookup_entries[EQ::versio
|
|||||||
EQ::behavior::LookupEntry(
|
EQ::behavior::LookupEntry(
|
||||||
RoF2::behavior::CoinHasWeight
|
RoF2::behavior::CoinHasWeight
|
||||||
),
|
),
|
||||||
|
/*[MobVersion::LS] =*/
|
||||||
|
EQ::behavior::LookupEntry(
|
||||||
|
RoF2::behavior::CoinHasWeight
|
||||||
|
),
|
||||||
/*[MobVersion::NPC] =*/
|
/*[MobVersion::NPC] =*/
|
||||||
EQ::behavior::LookupEntry(
|
EQ::behavior::LookupEntry(
|
||||||
EQ::behavior::CoinHasWeight
|
EQ::behavior::CoinHasWeight
|
||||||
@@ -1047,6 +1113,10 @@ static const EQ::behavior::LookupEntry behavior_static_lookup_entries[EQ::versio
|
|||||||
RoF::behavior::CoinHasWeight
|
RoF::behavior::CoinHasWeight
|
||||||
),
|
),
|
||||||
/*[MobVersion::OfflineRoF2] =*/
|
/*[MobVersion::OfflineRoF2] =*/
|
||||||
|
EQ::behavior::LookupEntry(
|
||||||
|
RoF2::behavior::CoinHasWeight
|
||||||
|
),
|
||||||
|
/*[MobVersion::OfflineLS] =*/
|
||||||
EQ::behavior::LookupEntry(
|
EQ::behavior::LookupEntry(
|
||||||
RoF2::behavior::CoinHasWeight
|
RoF2::behavior::CoinHasWeight
|
||||||
)
|
)
|
||||||
@@ -1202,6 +1272,19 @@ static const EQ::spells::LookupEntry spells_static_lookup_entries[EQ::versions::
|
|||||||
RoF2::spells::NPC_BUFFS,
|
RoF2::spells::NPC_BUFFS,
|
||||||
RoF2::spells::PET_BUFFS,
|
RoF2::spells::PET_BUFFS,
|
||||||
RoF2::spells::MERC_BUFFS
|
RoF2::spells::MERC_BUFFS
|
||||||
|
),
|
||||||
|
/*[ClientVersion::Larion] =*/
|
||||||
|
EQ::spells::LookupEntry(
|
||||||
|
Larion::spells::SPELL_ID_MAX,
|
||||||
|
Larion::spells::SPELLBOOK_SIZE,
|
||||||
|
UF::spells::SPELL_GEM_COUNT, // client translators are setup to allow the max value a client supports..however, the top 4 indices are not valid in this case
|
||||||
|
Larion::spells::LONG_BUFFS,
|
||||||
|
Larion::spells::SHORT_BUFFS,
|
||||||
|
Larion::spells::DISC_BUFFS,
|
||||||
|
Larion::spells::TOTAL_BUFFS,
|
||||||
|
Larion::spells::NPC_BUFFS,
|
||||||
|
Larion::spells::PET_BUFFS,
|
||||||
|
Larion::spells::MERC_BUFFS
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@
|
|||||||
#include "../common/patches/uf_limits.h"
|
#include "../common/patches/uf_limits.h"
|
||||||
#include "../common/patches/rof_limits.h"
|
#include "../common/patches/rof_limits.h"
|
||||||
#include "../common/patches/rof2_limits.h"
|
#include "../common/patches/rof2_limits.h"
|
||||||
|
#include "../common/patches/larion_limits.h"
|
||||||
|
|
||||||
namespace EQ
|
namespace EQ
|
||||||
{
|
{
|
||||||
|
|||||||
+392
-66
@@ -323,6 +323,7 @@ union
|
|||||||
bool show_name;
|
bool show_name;
|
||||||
bool guild_show;
|
bool guild_show;
|
||||||
bool trader;
|
bool trader;
|
||||||
|
bool buyer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlayerState_Struct {
|
struct PlayerState_Struct {
|
||||||
@@ -1620,6 +1621,32 @@ struct MoveItem_Struct
|
|||||||
/*0012*/
|
/*0012*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// New for RoF2 - Size: 12
|
||||||
|
struct InventorySlot_Struct
|
||||||
|
{
|
||||||
|
/*000*/ int16 Type; // Worn and Normal inventory = 0, Bank = 1, Shared Bank = 2, Delete Item = -1
|
||||||
|
/*002*/ int16 Unknown02;
|
||||||
|
/*004*/ int16 Slot;
|
||||||
|
/*006*/ int16 SubIndex;
|
||||||
|
/*008*/ int16 AugIndex; // Guessing - Seen 0xffff
|
||||||
|
/*010*/ int16 Unknown01; // Normally 0 - Seen 13262 when deleting an item, but didn't match item ID
|
||||||
|
/*012*/
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MultiMoveItemSub_Struct
|
||||||
|
{
|
||||||
|
/*0000*/ InventorySlot_Struct from_slot;
|
||||||
|
/*0012*/ InventorySlot_Struct to_slot;
|
||||||
|
/*0024*/ uint32 number_in_stack;
|
||||||
|
/*0028*/ uint8 unknown[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MultiMoveItem_Struct
|
||||||
|
{
|
||||||
|
/*0000*/ uint32 count;
|
||||||
|
/*0004*/ MultiMoveItemSub_Struct moves[0];
|
||||||
|
};
|
||||||
|
|
||||||
// both MoveItem_Struct/DeleteItem_Struct server structures will be changing to a structure-based slot format..this will
|
// both MoveItem_Struct/DeleteItem_Struct server structures will be changing to a structure-based slot format..this will
|
||||||
// be used for handling SoF/SoD/etc... time stamps sent using the MoveItem_Struct format. (nothing will be done with this
|
// be used for handling SoF/SoD/etc... time stamps sent using the MoveItem_Struct format. (nothing will be done with this
|
||||||
// info at the moment..but, it is forwarded on to the server for handling/future use)
|
// info at the moment..but, it is forwarded on to the server for handling/future use)
|
||||||
@@ -3113,60 +3140,369 @@ struct BazaarSearchResults_Struct {
|
|||||||
// Barter/Buyer
|
// Barter/Buyer
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
enum {
|
#define MAX_BUYER_COMPENSATION_ITEMS 10
|
||||||
Barter_BuyerSearch = 0,
|
|
||||||
Barter_SellerSearch = 1,
|
enum BarterBuyerActions {
|
||||||
Barter_BuyerModeOn = 2,
|
Barter_BuyerSearch = 0,
|
||||||
Barter_BuyerModeOff = 3,
|
Barter_SellerSearch = 1,
|
||||||
Barter_BuyerItemUpdate = 5,
|
Barter_BuyerModeOn = 2,
|
||||||
Barter_BuyerItemRemove = 6,
|
Barter_BuyerModeOff = 3,
|
||||||
Barter_SellItem = 7,
|
Barter_BuyerItemStart = 4,
|
||||||
|
Barter_BuyerItemUpdate = 5,
|
||||||
|
Barter_BuyerItemRemove = 6,
|
||||||
|
Barter_SellItem = 7,
|
||||||
Barter_SellerTransactionComplete = 8,
|
Barter_SellerTransactionComplete = 8,
|
||||||
Barter_BuyerTransactionComplete = 9,
|
Barter_BuyerTransactionComplete = 9,
|
||||||
Barter_BuyerInspectBegin = 10,
|
Barter_BuyerInspectBegin = 10,
|
||||||
Barter_BuyerInspectEnd = 11,
|
Barter_BuyerInspectEnd = 11,
|
||||||
Barter_BuyerAppearance = 12,
|
Barter_BuyerAppearance = 12,
|
||||||
Barter_BuyerInspectWindow = 13,
|
Barter_BuyerInspectWindow = 13,
|
||||||
Barter_BarterItemInspect = 14,
|
Barter_BarterItemInspect = 14,
|
||||||
Barter_SellerBrowsing = 15,
|
Barter_SellerBrowsing = 15,
|
||||||
Barter_BuyerSearchResults = 16,
|
Barter_BuyerSearchResults = 16,
|
||||||
Barter_Welcome = 17,
|
Barter_Welcome = 17,
|
||||||
Barter_WelcomeMessageUpdate = 19,
|
Barter_WelcomeMessageUpdate = 19,
|
||||||
Barter_BuyerItemInspect = 21,
|
Barter_Greeting = 20,
|
||||||
Barter_Unknown23 = 23
|
Barter_BuyerItemInspect = 21,
|
||||||
|
Barter_OpenBarterWindow = 23,
|
||||||
|
Barter_AddToBarterWindow = 26,
|
||||||
|
Barter_RemoveFromBarterWindow = 27,
|
||||||
|
Barter_RemoveFromMerchantWindow = 50, //Not a client item. Used for internal communications.
|
||||||
|
Barter_FailedTransaction = 51,
|
||||||
|
Barter_BuyerCouldNotBeFound = 52,
|
||||||
|
Barter_FailedBuyerChecks = 53,
|
||||||
|
Barter_SellerCouldNotBeFound = 54,
|
||||||
|
Barter_FailedSellerChecks = 55
|
||||||
|
};
|
||||||
|
|
||||||
|
enum BarterBuyerSubActions {
|
||||||
|
Barter_Success = 0,
|
||||||
|
Barter_Failure = 1,
|
||||||
|
Barter_DataOutOfDate = 4,
|
||||||
|
Barter_SellerDoesNotHaveItem = 6,
|
||||||
|
Barter_SameZone = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
enum BuyerBarter {
|
||||||
|
Off = 0,
|
||||||
|
On = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerRemoveItem_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 buy_slot_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerRemoveItemFromMerchantWindow_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 unknown_004;
|
||||||
|
uint32 buy_slot_id;
|
||||||
|
uint32 unknown_012;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerGeneric_Struct {
|
||||||
|
uint32 action;
|
||||||
|
char payload[];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerMessaging_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 sub_action;
|
||||||
|
uint32 zone_id;
|
||||||
|
uint32 buyer_id;
|
||||||
|
uint32 buyer_entity_id;
|
||||||
|
char buyer_name[64];
|
||||||
|
uint32 buy_item_id;
|
||||||
|
uint32 buy_item_qty;
|
||||||
|
uint64 buy_item_cost;
|
||||||
|
uint32 buy_item_icon;
|
||||||
|
uint32 seller_entity_id;
|
||||||
|
char seller_name[64];
|
||||||
|
char item_name[64];
|
||||||
|
uint32 slot;
|
||||||
|
uint32 seller_quantity;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerAddBuyertoBarterWindow_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 zone_id;
|
||||||
|
uint32 buyer_id;
|
||||||
|
uint32 buyer_entity_id;
|
||||||
|
char buyer_name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerRemoveBuyerFromBarterWindow_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 buyer_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerBrowsing_Struct {
|
||||||
|
uint32 action;
|
||||||
|
char char_name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerGreeting_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 buyer_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BuyerWelcomeMessageUpdate_Struct {
|
struct BuyerWelcomeMessageUpdate_Struct {
|
||||||
/*000*/ uint32 Action;
|
uint32 action;
|
||||||
/*004*/ char WelcomeMessage[256];
|
char welcome_message[256];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BuyerItemSearch_Struct {
|
struct BuyerLineTradeItems_Struct {
|
||||||
/*000*/ uint32 Unknown000;
|
uint32 item_id;
|
||||||
/*004*/ char SearchString[64];
|
uint32 item_quantity;
|
||||||
|
uint32 item_icon;
|
||||||
|
std::string item_name;
|
||||||
|
|
||||||
|
void operator*=(uint32 multiplier)
|
||||||
|
{
|
||||||
|
this->item_quantity *= multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive &archive)
|
||||||
|
{
|
||||||
|
archive(
|
||||||
|
CEREAL_NVP(item_id),
|
||||||
|
CEREAL_NVP(item_quantity),
|
||||||
|
CEREAL_NVP(item_icon),
|
||||||
|
CEREAL_NVP(item_name)
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BuyerItemSearchResultEntry_Struct {
|
struct BuyerLineItems_Struct {
|
||||||
/*000*/ char ItemName[64];
|
uint32 slot;
|
||||||
/*064*/ uint32 ItemID;
|
uint8 enabled;
|
||||||
/*068*/ uint32 Unknown068;
|
uint32 item_id;
|
||||||
/*072*/ uint32 Unknown072;
|
std::string item_name;
|
||||||
|
uint32 item_icon;
|
||||||
|
uint32 item_quantity;
|
||||||
|
uint8 item_toggle;
|
||||||
|
uint32 item_cost;
|
||||||
|
std::vector<BuyerLineTradeItems_Struct> trade_items;
|
||||||
|
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive &archive)
|
||||||
|
{
|
||||||
|
archive(
|
||||||
|
CEREAL_NVP(slot),
|
||||||
|
CEREAL_NVP(enabled),
|
||||||
|
CEREAL_NVP(item_id),
|
||||||
|
CEREAL_NVP(item_name),
|
||||||
|
CEREAL_NVP(item_icon),
|
||||||
|
CEREAL_NVP(item_quantity),
|
||||||
|
CEREAL_NVP(item_toggle),
|
||||||
|
CEREAL_NVP(item_cost),
|
||||||
|
CEREAL_NVP(trade_items)
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_BUYER_ITEMSEARCH_RESULTS 200
|
struct BuyerBuyLines_Struct {
|
||||||
|
uint32 action;
|
||||||
|
union {
|
||||||
|
uint32 no_items;
|
||||||
|
uint32 string_length;
|
||||||
|
};
|
||||||
|
std::vector<BuyerLineItems_Struct> buy_lines;
|
||||||
|
|
||||||
struct BuyerItemSearchResults_Struct {
|
template<class Archive>
|
||||||
uint32 Action;
|
void serialize(Archive &archive)
|
||||||
uint32 ResultCount;
|
{
|
||||||
BuyerItemSearchResultEntry_Struct Results[MAX_BUYER_ITEMSEARCH_RESULTS];
|
archive(
|
||||||
|
CEREAL_NVP(action),
|
||||||
|
CEREAL_NVP(no_items),
|
||||||
|
CEREAL_NVP(buy_lines)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerLineSellItem_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 sub_action;
|
||||||
|
uint32 error_code;
|
||||||
|
uint32 purchase_method; // 0 direct merchant, 1 via /barter window
|
||||||
|
uint32 buyer_entity_id;
|
||||||
|
uint32 buyer_id;
|
||||||
|
std::string buyer_name;
|
||||||
|
uint32 seller_entity_id;
|
||||||
|
std::string seller_name;
|
||||||
|
uint32 slot;
|
||||||
|
uint8 enabled;
|
||||||
|
uint32 item_id;
|
||||||
|
char item_name[64];
|
||||||
|
uint32 item_icon;
|
||||||
|
uint32 item_quantity;
|
||||||
|
uint8 item_toggle;
|
||||||
|
uint32 item_cost;
|
||||||
|
uint32 no_trade_items;
|
||||||
|
std::vector<BuyerLineTradeItems_Struct> trade_items;
|
||||||
|
uint32 seller_quantity;
|
||||||
|
uint32 zone_id;
|
||||||
|
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive &archive)
|
||||||
|
{
|
||||||
|
archive(
|
||||||
|
CEREAL_NVP(action),
|
||||||
|
CEREAL_NVP(sub_action),
|
||||||
|
CEREAL_NVP(error_code),
|
||||||
|
CEREAL_NVP(purchase_method),
|
||||||
|
CEREAL_NVP(buyer_entity_id),
|
||||||
|
CEREAL_NVP(buyer_id),
|
||||||
|
CEREAL_NVP(buyer_name),
|
||||||
|
CEREAL_NVP(seller_entity_id),
|
||||||
|
CEREAL_NVP(seller_name),
|
||||||
|
CEREAL_NVP(slot),
|
||||||
|
CEREAL_NVP(enabled),
|
||||||
|
CEREAL_NVP(item_id),
|
||||||
|
CEREAL_NVP(item_name),
|
||||||
|
CEREAL_NVP(item_icon),
|
||||||
|
CEREAL_NVP(item_quantity),
|
||||||
|
CEREAL_NVP(item_toggle),
|
||||||
|
CEREAL_NVP(item_cost),
|
||||||
|
CEREAL_NVP(no_trade_items),
|
||||||
|
CEREAL_NVP(trade_items),
|
||||||
|
CEREAL_NVP(seller_quantity),
|
||||||
|
CEREAL_NVP(zone_id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerLineItemsSearch_Struct {
|
||||||
|
uint32 slot;
|
||||||
|
uint8 enabled;
|
||||||
|
uint32 item_id;
|
||||||
|
char item_name[64];
|
||||||
|
uint32 item_icon;
|
||||||
|
uint32 item_quantity;
|
||||||
|
uint8 item_toggle;
|
||||||
|
uint32 item_cost;
|
||||||
|
uint32 buyer_id;
|
||||||
|
uint32 buyer_entity_id;
|
||||||
|
uint32 buyer_zone_id;
|
||||||
|
uint32 buyer_zone_instance_id;
|
||||||
|
std::string buyer_name;
|
||||||
|
std::vector<BuyerLineTradeItems_Struct> trade_items;
|
||||||
|
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive &archive)
|
||||||
|
{
|
||||||
|
archive(
|
||||||
|
CEREAL_NVP(slot),
|
||||||
|
CEREAL_NVP(enabled),
|
||||||
|
CEREAL_NVP(item_id),
|
||||||
|
CEREAL_NVP(item_name),
|
||||||
|
CEREAL_NVP(item_icon),
|
||||||
|
CEREAL_NVP(item_quantity),
|
||||||
|
CEREAL_NVP(item_toggle),
|
||||||
|
CEREAL_NVP(item_cost),
|
||||||
|
CEREAL_NVP(buyer_id),
|
||||||
|
CEREAL_NVP(buyer_entity_id),
|
||||||
|
CEREAL_NVP(buyer_zone_id),
|
||||||
|
CEREAL_NVP(buyer_zone_instance_id),
|
||||||
|
CEREAL_NVP(buyer_name),
|
||||||
|
CEREAL_NVP(trade_items)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerLineSearch_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 no_items;
|
||||||
|
std::string search_string;
|
||||||
|
uint32 transaction_id;
|
||||||
|
std::vector<BuyerLineItemsSearch_Struct> buy_line;
|
||||||
|
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive &archive)
|
||||||
|
{
|
||||||
|
archive(
|
||||||
|
CEREAL_NVP(action),
|
||||||
|
CEREAL_NVP(no_items),
|
||||||
|
CEREAL_NVP(search_string),
|
||||||
|
CEREAL_NVP(transaction_id),
|
||||||
|
CEREAL_NVP(buy_line)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerSetAppearance_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 entity_id;
|
||||||
|
uint32 status; // 0 off 1 on
|
||||||
|
char buyer_name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BarterItemSearchLinkRequest_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 searcher_id;
|
||||||
|
uint32 unknown_008;
|
||||||
|
uint32 unknown_012;
|
||||||
|
uint32 item_id;
|
||||||
|
uint32 unknown_020;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerInspectRequest_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 buyer_id;
|
||||||
|
uint32 approval;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BarterSearchRequest_Struct {
|
struct BarterSearchRequest_Struct {
|
||||||
uint32 Action;
|
uint32 action;
|
||||||
char SearchString[64];
|
char search_string[64];
|
||||||
uint32 SearchID;
|
uint32 transaction_id;
|
||||||
|
uint32 unknown_072;
|
||||||
|
uint32 buyer_id;
|
||||||
|
uint8 search_scope; //0 All Buyers, 1 Local Buyers
|
||||||
|
uint16 zone_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BuyerItemSearch_Struct {
|
||||||
|
uint32 action;
|
||||||
|
char search_string[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerItemSearchResultEntry_Struct {
|
||||||
|
char item_name[64];
|
||||||
|
uint32 item_id;
|
||||||
|
uint32 item_icon;
|
||||||
|
uint32 unknown_072;
|
||||||
|
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive &archive)
|
||||||
|
{
|
||||||
|
archive(
|
||||||
|
CEREAL_NVP(item_name),
|
||||||
|
CEREAL_NVP(item_id),
|
||||||
|
CEREAL_NVP(item_icon),
|
||||||
|
CEREAL_NVP(unknown_072)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerItemSearchResults_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 result_count;
|
||||||
|
std::vector<BuyerItemSearchResultEntry_Struct> results;
|
||||||
|
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive &archive)
|
||||||
|
{
|
||||||
|
archive(
|
||||||
|
CEREAL_NVP(action),
|
||||||
|
CEREAL_NVP(result_count),
|
||||||
|
CEREAL_NVP(results)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//old below here
|
||||||
struct BuyerItemSearchLinkRequest_Struct {
|
struct BuyerItemSearchLinkRequest_Struct {
|
||||||
/*000*/ uint32 Action; // 0x00000015
|
/*000*/ uint32 Action; // 0x00000015
|
||||||
/*004*/ uint32 ItemID;
|
/*004*/ uint32 ItemID;
|
||||||
@@ -3174,31 +3510,6 @@ struct BuyerItemSearchLinkRequest_Struct {
|
|||||||
/*012*/ uint32 Unknown012;
|
/*012*/ uint32 Unknown012;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BarterItemSearchLinkRequest_Struct {
|
|
||||||
/*000*/ uint32 Action; // 0x0000000E
|
|
||||||
/*004*/ uint32 SearcherID;
|
|
||||||
/*008*/ uint32 Unknown008;
|
|
||||||
/*012*/ uint32 Unknown012;
|
|
||||||
/*016*/ uint32 ItemID;
|
|
||||||
/*020*/ uint32 Unknown020;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BuyerInspectRequest_Struct {
|
|
||||||
uint32 Action;
|
|
||||||
uint32 BuyerID;
|
|
||||||
uint32 Approval;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BuyerBrowsing_Struct {
|
|
||||||
uint32 Action;
|
|
||||||
char PlayerName[64];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BuyerRemoveItem_Struct {
|
|
||||||
uint32 Action;
|
|
||||||
uint32 BuySlot;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ServerSideFilters_Struct {
|
struct ServerSideFilters_Struct {
|
||||||
uint8 clientattackfilters; // 0) No, 1) All (players) but self, 2) All (players) but group
|
uint8 clientattackfilters; // 0) No, 1) All (players) but self, 2) All (players) but group
|
||||||
uint8 npcattackfilters; // 0) No, 1) Ignore NPC misses (all), 2) Ignore NPC Misses + Attacks (all but self), 3) Ignores NPC Misses + Attacks (all but group)
|
uint8 npcattackfilters; // 0) No, 1) Ignore NPC misses (all), 2) Ignore NPC Misses + Attacks (all but self), 3) Ignores NPC Misses + Attacks (all but group)
|
||||||
@@ -6040,9 +6351,12 @@ enum BazaarTraderBarterActions {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum BazaarPurchaseActions {
|
enum BazaarPurchaseActions {
|
||||||
ByVendor = 0,
|
BazaarByVendor = 0,
|
||||||
ByParcel = 1,
|
BazaarByParcel = 1,
|
||||||
ByDirectToInventory = 2
|
BazaarByDirectToInventory = 2,
|
||||||
|
BarterByVendor = 0,
|
||||||
|
BarterInBazaar = 1,
|
||||||
|
BarterOutsideBazaar = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BazaarPurchaseSubActions {
|
enum BazaarPurchaseSubActions {
|
||||||
@@ -6116,6 +6430,18 @@ struct BazaarSearchMessaging_Struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BuylineItemDetails_Struct {
|
||||||
|
uint64 item_cost;
|
||||||
|
uint32 item_quantity;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EqGuid
|
||||||
|
{
|
||||||
|
uint32_t Id;
|
||||||
|
uint16_t WorldId;
|
||||||
|
uint16_t Reserved;
|
||||||
|
};
|
||||||
|
|
||||||
// Restore structure packing to default
|
// Restore structure packing to default
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
|
|||||||
@@ -789,50 +789,36 @@ std::string PlayerEventDiscordFormatter::FormatNPCHandinEvent(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string npc_info = fmt::format(
|
||||||
|
"{} ({})\n",
|
||||||
|
e.npc_name,
|
||||||
|
e.npc_id
|
||||||
|
);
|
||||||
|
|
||||||
|
npc_info += fmt::format(
|
||||||
|
"Is Quest Handin: {}",
|
||||||
|
e.is_quest_handin ? "Yes" : "No"
|
||||||
|
);
|
||||||
|
|
||||||
std::vector<DiscordField> f = {};
|
std::vector<DiscordField> f = {};
|
||||||
|
|
||||||
|
|
||||||
|
BuildDiscordField(&f, "NPC", npc_info);
|
||||||
|
|
||||||
if (!handin_items_info.empty()) {
|
if (!handin_items_info.empty()) {
|
||||||
BuildDiscordField(
|
BuildDiscordField(&f, "Handin Items", handin_items_info);
|
||||||
&f,
|
|
||||||
"Handin Items",
|
|
||||||
fmt::format(
|
|
||||||
"{}",
|
|
||||||
handin_items_info
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!handin_money_info.empty()) {
|
if (!handin_money_info.empty()) {
|
||||||
BuildDiscordField(
|
BuildDiscordField(&f, "Handin Money", handin_money_info);
|
||||||
&f,
|
|
||||||
"Handin Money",
|
|
||||||
fmt::format(
|
|
||||||
"{}",
|
|
||||||
handin_money_info
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!return_items_info.empty()) {
|
if (!return_items_info.empty()) {
|
||||||
BuildDiscordField(
|
BuildDiscordField(&f, "Return Items", return_items_info);
|
||||||
&f,
|
|
||||||
"Return Items",
|
|
||||||
fmt::format(
|
|
||||||
"{}",
|
|
||||||
return_items_info
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!return_money_info.empty()) {
|
if (!return_money_info.empty()) {
|
||||||
BuildDiscordField(
|
BuildDiscordField(&f, "Return Money", return_money_info);
|
||||||
&f,
|
|
||||||
"Return Money",
|
|
||||||
fmt::format(
|
|
||||||
"{}",
|
|
||||||
return_money_info
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<DiscordEmbed> embeds = {};
|
std::vector<DiscordEmbed> embeds = {};
|
||||||
|
|||||||
@@ -654,58 +654,59 @@ const int32_t RETENTION_DAYS_DEFAULT = 7;
|
|||||||
|
|
||||||
void PlayerEventLogs::SetSettingsDefaults()
|
void PlayerEventLogs::SetSettingsDefaults()
|
||||||
{
|
{
|
||||||
m_settings[PlayerEvent::GM_COMMAND].event_enabled = 1;
|
m_settings[PlayerEvent::GM_COMMAND].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::ZONING].event_enabled = 1;
|
m_settings[PlayerEvent::ZONING].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::AA_GAIN].event_enabled = 1;
|
m_settings[PlayerEvent::AA_GAIN].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::AA_PURCHASE].event_enabled = 1;
|
m_settings[PlayerEvent::AA_PURCHASE].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::FORAGE_SUCCESS].event_enabled = 0;
|
m_settings[PlayerEvent::FORAGE_SUCCESS].event_enabled = 0;
|
||||||
m_settings[PlayerEvent::FORAGE_FAILURE].event_enabled = 0;
|
m_settings[PlayerEvent::FORAGE_FAILURE].event_enabled = 0;
|
||||||
m_settings[PlayerEvent::FISH_SUCCESS].event_enabled = 0;
|
m_settings[PlayerEvent::FISH_SUCCESS].event_enabled = 0;
|
||||||
m_settings[PlayerEvent::FISH_FAILURE].event_enabled = 0;
|
m_settings[PlayerEvent::FISH_FAILURE].event_enabled = 0;
|
||||||
m_settings[PlayerEvent::ITEM_DESTROY].event_enabled = 1;
|
m_settings[PlayerEvent::ITEM_DESTROY].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::WENT_ONLINE].event_enabled = 0;
|
m_settings[PlayerEvent::WENT_ONLINE].event_enabled = 0;
|
||||||
m_settings[PlayerEvent::WENT_OFFLINE].event_enabled = 0;
|
m_settings[PlayerEvent::WENT_OFFLINE].event_enabled = 0;
|
||||||
m_settings[PlayerEvent::LEVEL_GAIN].event_enabled = 1;
|
m_settings[PlayerEvent::LEVEL_GAIN].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::LEVEL_LOSS].event_enabled = 1;
|
m_settings[PlayerEvent::LEVEL_LOSS].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::LOOT_ITEM].event_enabled = 1;
|
m_settings[PlayerEvent::LOOT_ITEM].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::MERCHANT_PURCHASE].event_enabled = 1;
|
m_settings[PlayerEvent::MERCHANT_PURCHASE].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::MERCHANT_SELL].event_enabled = 1;
|
m_settings[PlayerEvent::MERCHANT_SELL].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::GROUP_JOIN].event_enabled = 0;
|
m_settings[PlayerEvent::GROUP_JOIN].event_enabled = 0;
|
||||||
m_settings[PlayerEvent::GROUP_LEAVE].event_enabled = 0;
|
m_settings[PlayerEvent::GROUP_LEAVE].event_enabled = 0;
|
||||||
m_settings[PlayerEvent::RAID_JOIN].event_enabled = 0;
|
m_settings[PlayerEvent::RAID_JOIN].event_enabled = 0;
|
||||||
m_settings[PlayerEvent::RAID_LEAVE].event_enabled = 0;
|
m_settings[PlayerEvent::RAID_LEAVE].event_enabled = 0;
|
||||||
m_settings[PlayerEvent::GROUNDSPAWN_PICKUP].event_enabled = 1;
|
m_settings[PlayerEvent::GROUNDSPAWN_PICKUP].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::NPC_HANDIN].event_enabled = 1;
|
m_settings[PlayerEvent::NPC_HANDIN].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::SKILL_UP].event_enabled = 0;
|
m_settings[PlayerEvent::SKILL_UP].event_enabled = 0;
|
||||||
m_settings[PlayerEvent::TASK_ACCEPT].event_enabled = 1;
|
m_settings[PlayerEvent::TASK_ACCEPT].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::TASK_UPDATE].event_enabled = 1;
|
m_settings[PlayerEvent::TASK_UPDATE].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::TASK_COMPLETE].event_enabled = 1;
|
m_settings[PlayerEvent::TASK_COMPLETE].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::TRADE].event_enabled = 1;
|
m_settings[PlayerEvent::TRADE].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::GIVE_ITEM].event_enabled = 1;
|
m_settings[PlayerEvent::GIVE_ITEM].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::SAY].event_enabled = 0;
|
m_settings[PlayerEvent::SAY].event_enabled = 0;
|
||||||
m_settings[PlayerEvent::REZ_ACCEPTED].event_enabled = 1;
|
m_settings[PlayerEvent::REZ_ACCEPTED].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::DEATH].event_enabled = 1;
|
m_settings[PlayerEvent::DEATH].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::COMBINE_FAILURE].event_enabled = 1;
|
m_settings[PlayerEvent::COMBINE_FAILURE].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::COMBINE_SUCCESS].event_enabled = 1;
|
m_settings[PlayerEvent::COMBINE_SUCCESS].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::DROPPED_ITEM].event_enabled = 1;
|
m_settings[PlayerEvent::DROPPED_ITEM].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::SPLIT_MONEY].event_enabled = 1;
|
m_settings[PlayerEvent::SPLIT_MONEY].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::DZ_JOIN].event_enabled = 1;
|
m_settings[PlayerEvent::DZ_JOIN].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::DZ_LEAVE].event_enabled = 1;
|
m_settings[PlayerEvent::DZ_LEAVE].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::TRADER_PURCHASE].event_enabled = 1;
|
m_settings[PlayerEvent::TRADER_PURCHASE].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::TRADER_SELL].event_enabled = 1;
|
m_settings[PlayerEvent::TRADER_SELL].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::BANDOLIER_CREATE].event_enabled = 0;
|
m_settings[PlayerEvent::BANDOLIER_CREATE].event_enabled = 0;
|
||||||
m_settings[PlayerEvent::BANDOLIER_SWAP].event_enabled = 0;
|
m_settings[PlayerEvent::BANDOLIER_SWAP].event_enabled = 0;
|
||||||
m_settings[PlayerEvent::DISCOVER_ITEM].event_enabled = 1;
|
m_settings[PlayerEvent::DISCOVER_ITEM].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::POSSIBLE_HACK].event_enabled = 1;
|
m_settings[PlayerEvent::POSSIBLE_HACK].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::KILLED_NPC].event_enabled = 0;
|
m_settings[PlayerEvent::KILLED_NPC].event_enabled = 0;
|
||||||
m_settings[PlayerEvent::KILLED_NAMED_NPC].event_enabled = 1;
|
m_settings[PlayerEvent::KILLED_NAMED_NPC].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::KILLED_RAID_NPC].event_enabled = 1;
|
m_settings[PlayerEvent::KILLED_RAID_NPC].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::ITEM_CREATION].event_enabled = 1;
|
m_settings[PlayerEvent::ITEM_CREATION].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::GUILD_TRIBUTE_DONATE_ITEM].event_enabled = 1;
|
m_settings[PlayerEvent::GUILD_TRIBUTE_DONATE_ITEM].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::GUILD_TRIBUTE_DONATE_PLAT].event_enabled = 1;
|
m_settings[PlayerEvent::GUILD_TRIBUTE_DONATE_PLAT].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::PARCEL_SEND].event_enabled = 1;
|
m_settings[PlayerEvent::PARCEL_SEND].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::PARCEL_RETRIEVE].event_enabled = 1;
|
m_settings[PlayerEvent::PARCEL_RETRIEVE].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::PARCEL_DELETE].event_enabled = 1;
|
m_settings[PlayerEvent::PARCEL_DELETE].event_enabled = 1;
|
||||||
|
m_settings[PlayerEvent::BARTER_TRANSACTION].event_enabled = 1;
|
||||||
|
|
||||||
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
|
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
|
||||||
m_settings[i].retention_days = RETENTION_DAYS_DEFAULT;
|
m_settings[i].retention_days = RETENTION_DAYS_DEFAULT;
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ namespace PlayerEvent {
|
|||||||
PARCEL_SEND,
|
PARCEL_SEND,
|
||||||
PARCEL_RETRIEVE,
|
PARCEL_RETRIEVE,
|
||||||
PARCEL_DELETE,
|
PARCEL_DELETE,
|
||||||
|
BARTER_TRANSACTION,
|
||||||
MAX // dont remove
|
MAX // dont remove
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -122,7 +123,8 @@ namespace PlayerEvent {
|
|||||||
"Guild Tribute Donate Platinum",
|
"Guild Tribute Donate Platinum",
|
||||||
"Parcel Item Sent",
|
"Parcel Item Sent",
|
||||||
"Parcel Item Retrieved",
|
"Parcel Item Retrieved",
|
||||||
"Parcel Prune Routine"
|
"Parcel Prune Routine",
|
||||||
|
"Barter Transaction"
|
||||||
};
|
};
|
||||||
|
|
||||||
// Generic struct used by all events
|
// Generic struct used by all events
|
||||||
@@ -858,10 +860,12 @@ namespace PlayerEvent {
|
|||||||
|
|
||||||
class HandinEntry {
|
class HandinEntry {
|
||||||
public:
|
public:
|
||||||
uint32 item_id;
|
uint32 item_id;
|
||||||
std::string item_name;
|
std::string item_name;
|
||||||
uint16 charges;
|
std::vector<uint32> augment_ids;
|
||||||
bool attuned;
|
std::vector<std::string> augment_names;
|
||||||
|
uint16 charges;
|
||||||
|
bool attuned;
|
||||||
|
|
||||||
// cereal
|
// cereal
|
||||||
template<class Archive>
|
template<class Archive>
|
||||||
@@ -870,6 +874,8 @@ namespace PlayerEvent {
|
|||||||
ar(
|
ar(
|
||||||
CEREAL_NVP(item_id),
|
CEREAL_NVP(item_id),
|
||||||
CEREAL_NVP(item_name),
|
CEREAL_NVP(item_name),
|
||||||
|
CEREAL_NVP(augment_ids),
|
||||||
|
CEREAL_NVP(augment_names),
|
||||||
CEREAL_NVP(charges),
|
CEREAL_NVP(charges),
|
||||||
CEREAL_NVP(attuned)
|
CEREAL_NVP(attuned)
|
||||||
);
|
);
|
||||||
@@ -903,6 +909,7 @@ namespace PlayerEvent {
|
|||||||
HandinMoney handin_money;
|
HandinMoney handin_money;
|
||||||
std::vector<HandinEntry> return_items;
|
std::vector<HandinEntry> return_items;
|
||||||
HandinMoney return_money;
|
HandinMoney return_money;
|
||||||
|
bool is_quest_handin;
|
||||||
|
|
||||||
// cereal
|
// cereal
|
||||||
template<class Archive>
|
template<class Archive>
|
||||||
@@ -914,7 +921,8 @@ namespace PlayerEvent {
|
|||||||
CEREAL_NVP(handin_items),
|
CEREAL_NVP(handin_items),
|
||||||
CEREAL_NVP(handin_money),
|
CEREAL_NVP(handin_money),
|
||||||
CEREAL_NVP(return_items),
|
CEREAL_NVP(return_items),
|
||||||
CEREAL_NVP(return_money)
|
CEREAL_NVP(return_money),
|
||||||
|
CEREAL_NVP(is_quest_handin)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1081,6 +1089,32 @@ namespace PlayerEvent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BarterTransaction {
|
||||||
|
std::string status;
|
||||||
|
uint32 item_id;
|
||||||
|
uint32 item_quantity;
|
||||||
|
std::string item_name;
|
||||||
|
std::vector<BuyerLineTradeItems_Struct> trade_items;
|
||||||
|
std::string buyer_name;
|
||||||
|
std::string seller_name;
|
||||||
|
uint64 total_cost;
|
||||||
|
// cereal
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive &ar)
|
||||||
|
{
|
||||||
|
ar(
|
||||||
|
CEREAL_NVP(status),
|
||||||
|
CEREAL_NVP(item_id),
|
||||||
|
CEREAL_NVP(item_quantity),
|
||||||
|
CEREAL_NVP(item_name),
|
||||||
|
CEREAL_NVP(trade_items),
|
||||||
|
CEREAL_NVP(buyer_name),
|
||||||
|
CEREAL_NVP(seller_name),
|
||||||
|
CEREAL_NVP(total_cost)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //EQEMU_PLAYER_EVENTS_H
|
#endif //EQEMU_PLAYER_EVENTS_H
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ bool EQ::InventoryProfile::SwapItem(
|
|||||||
SwapItemFailState &fail_state,
|
SwapItemFailState &fail_state,
|
||||||
uint16 race_id,
|
uint16 race_id,
|
||||||
uint8 class_id,
|
uint8 class_id,
|
||||||
uint16 deity_id,
|
uint32 deity_id,
|
||||||
uint8 level
|
uint8 level
|
||||||
) {
|
) {
|
||||||
fail_state = swapInvalid;
|
fail_state = swapInvalid;
|
||||||
@@ -354,7 +354,7 @@ bool EQ::InventoryProfile::SwapItem(
|
|||||||
fail_state = swapRaceClass;
|
fail_state = swapRaceClass;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (deity_id && source_item->Deity && !(deity::GetDeityBitmask((deity::DeityType)deity_id) & source_item->Deity)) {
|
if (deity_id && source_item->Deity && !(Deity::GetBitmask(deity_id) & source_item->Deity)) {
|
||||||
fail_state = swapDeity;
|
fail_state = swapDeity;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -380,7 +380,7 @@ bool EQ::InventoryProfile::SwapItem(
|
|||||||
fail_state = swapRaceClass;
|
fail_state = swapRaceClass;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (deity_id && destination_item->Deity && !(deity::GetDeityBitmask((deity::DeityType)deity_id) & destination_item->Deity)) {
|
if (deity_id && destination_item->Deity && !(Deity::GetBitmask(deity_id) & destination_item->Deity)) {
|
||||||
fail_state = swapDeity;
|
fail_state = swapDeity;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1743,3 +1743,68 @@ std::vector<uint32> EQ::InventoryProfile::GetAugmentIDsBySlotID(int16 slot_id)
|
|||||||
|
|
||||||
return augments;
|
return augments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<int16> EQ::InventoryProfile::FindAllFreeSlotsThatFitItem(const EQ::ItemData *item_data)
|
||||||
|
{
|
||||||
|
std::vector<int16> free_slots{};
|
||||||
|
for (int16 i = EQ::invslot::GENERAL_BEGIN; i <= EQ::invslot::GENERAL_END; i++) {
|
||||||
|
if ((((uint64) 1 << i) & GetLookup()->PossessionsBitmask) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
EQ::ItemInstance *inv_item = GetItem(i);
|
||||||
|
|
||||||
|
if (!inv_item) {
|
||||||
|
// Found available slot in personal inventory
|
||||||
|
free_slots.push_back(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inv_item->IsClassBag() &&
|
||||||
|
EQ::InventoryProfile::CanItemFitInContainer(item_data, inv_item->GetItem())) {
|
||||||
|
|
||||||
|
int16 base_slot_id = EQ::InventoryProfile::CalcSlotId(i, EQ::invbag::SLOT_BEGIN);
|
||||||
|
uint8 bag_size = inv_item->GetItem()->BagSlots;
|
||||||
|
|
||||||
|
for (uint8 bag_slot = EQ::invbag::SLOT_BEGIN; bag_slot < bag_size; bag_slot++) {
|
||||||
|
auto bag_item = GetItem(base_slot_id + bag_slot);
|
||||||
|
if (!bag_item) {
|
||||||
|
// Found available slot within bag
|
||||||
|
free_slots.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return free_slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16 EQ::InventoryProfile::FindFirstFreeSlotThatFitsItem(const EQ::ItemData *item_data)
|
||||||
|
{
|
||||||
|
for (int16 i = EQ::invslot::GENERAL_BEGIN; i <= EQ::invslot::GENERAL_END; i++) {
|
||||||
|
if ((((uint64) 1 << i) & GetLookup()->PossessionsBitmask) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
EQ::ItemInstance *inv_item = GetItem(i);
|
||||||
|
|
||||||
|
if (!inv_item) {
|
||||||
|
// Found available slot in personal inventory
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inv_item->IsClassBag() &&
|
||||||
|
EQ::InventoryProfile::CanItemFitInContainer(item_data, inv_item->GetItem())) {
|
||||||
|
|
||||||
|
int16 base_slot_id = EQ::InventoryProfile::CalcSlotId(i, EQ::invbag::SLOT_BEGIN);
|
||||||
|
uint8 bag_size = inv_item->GetItem()->BagSlots;
|
||||||
|
|
||||||
|
for (uint8 bag_slot = EQ::invbag::SLOT_BEGIN; bag_slot < bag_size; bag_slot++) {
|
||||||
|
auto bag_item = GetItem(base_slot_id + bag_slot);
|
||||||
|
if (!bag_item) {
|
||||||
|
// Found available slot within bag
|
||||||
|
return base_slot_id + bag_slot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -132,7 +132,7 @@ namespace EQ
|
|||||||
|
|
||||||
// Swap items in inventory
|
// Swap items in inventory
|
||||||
enum SwapItemFailState : int8 { swapInvalid = -1, swapPass = 0, swapNotAllowed, swapNullData, swapRaceClass, swapDeity, swapLevel };
|
enum SwapItemFailState : int8 { swapInvalid = -1, swapPass = 0, swapNotAllowed, swapNullData, swapRaceClass, swapDeity, swapLevel };
|
||||||
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = Race::Doug, uint8 class_id = Class::None, uint16 deity_id = deity::DeityType::DeityUnknown, uint8 level = 0);
|
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = Race::Doug, uint8 class_id = Class::None, uint32 deity_id = Deity::Unknown, uint8 level = 0);
|
||||||
|
|
||||||
// Remove item from inventory
|
// Remove item from inventory
|
||||||
bool DeleteItem(int16 slot_id, int16 quantity = 0);
|
bool DeleteItem(int16 slot_id, int16 quantity = 0);
|
||||||
@@ -176,6 +176,8 @@ namespace EQ
|
|||||||
// Locate an available inventory slot
|
// Locate an available inventory slot
|
||||||
int16 FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size = 0, bool is_arrow = false);
|
int16 FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size = 0, bool is_arrow = false);
|
||||||
int16 FindFreeSlotForTradeItem(const ItemInstance* inst, int16 general_start = invslot::GENERAL_BEGIN, uint8 bag_start = invbag::SLOT_BEGIN);
|
int16 FindFreeSlotForTradeItem(const ItemInstance* inst, int16 general_start = invslot::GENERAL_BEGIN, uint8 bag_start = invbag::SLOT_BEGIN);
|
||||||
|
std::vector<int16> FindAllFreeSlotsThatFitItem(const EQ::ItemData *inst);
|
||||||
|
int16 FindFirstFreeSlotThatFitsItem(const EQ::ItemData *inst);
|
||||||
|
|
||||||
// Calculate slot_id for an item within a bag
|
// Calculate slot_id for an item within a bag
|
||||||
static int16 CalcSlotId(int16 slot_id); // Calc parent bag's slot_id
|
static int16 CalcSlotId(int16 slot_id); // Calc parent bag's slot_id
|
||||||
|
|||||||
+55
-21
@@ -81,45 +81,79 @@ bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets local address - pings google to inspect what interface was used locally
|
#ifdef _WIN32
|
||||||
* @return
|
#include <winsock2.h>
|
||||||
*/
|
#include <ws2tcpip.h>
|
||||||
|
#pragma comment(lib, "Ws2_32.lib")
|
||||||
|
#else
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
std::string IpUtil::GetLocalIPAddress()
|
std::string IpUtil::GetLocalIPAddress()
|
||||||
{
|
{
|
||||||
char my_ip_address[16];
|
#ifdef _WIN32
|
||||||
unsigned int my_port;
|
WSADATA wsaData;
|
||||||
|
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char my_ip_address[INET_ADDRSTRLEN];
|
||||||
struct sockaddr_in server_address{};
|
struct sockaddr_in server_address{};
|
||||||
struct sockaddr_in my_address{};
|
struct sockaddr_in my_address{};
|
||||||
int sockfd;
|
int sockfd;
|
||||||
|
|
||||||
// Connect to server
|
// Create a UDP socket
|
||||||
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
#ifdef _WIN32
|
||||||
|
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (sockfd == INVALID_SOCKET) {
|
||||||
|
WSACleanup();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (sockfd < 0) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Set server_addr
|
// Set server_addr (dummy address)
|
||||||
memset(&server_address, 0, sizeof(server_address));
|
memset(&server_address, 0, sizeof(server_address));
|
||||||
server_address.sin_family = AF_INET;
|
server_address.sin_family = AF_INET;
|
||||||
server_address.sin_addr.s_addr = inet_addr("172.217.160.99");
|
server_address.sin_addr.s_addr = inet_addr("8.8.8.8"); // Google DNS
|
||||||
server_address.sin_port = htons(80);
|
server_address.sin_port = htons(53); // DNS port
|
||||||
|
|
||||||
// Connect to server
|
// Perform a dummy connection to the server (UDP)
|
||||||
if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
|
connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address));
|
||||||
close(sockfd);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get my ip address and port
|
// Get my IP address
|
||||||
memset(&my_address, 0, sizeof(my_address));
|
memset(&my_address, 0, sizeof(my_address));
|
||||||
socklen_t len = sizeof(my_address);
|
socklen_t len = sizeof(my_address);
|
||||||
getsockname(sockfd, (struct sockaddr *) &my_address, &len);
|
getsockname(sockfd, (struct sockaddr *) &my_address, &len);
|
||||||
inet_ntop(AF_INET, &my_address.sin_addr, my_ip_address, sizeof(my_ip_address));
|
inet_ntop(AF_INET, &my_address.sin_addr, my_ip_address, sizeof(my_ip_address));
|
||||||
my_port = ntohs(my_address.sin_port);
|
|
||||||
|
|
||||||
return fmt::format("{}", my_ip_address);
|
#ifdef _WIN32
|
||||||
|
closesocket(sockfd);
|
||||||
|
WSACleanup();
|
||||||
|
#else
|
||||||
|
close(sockfd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LogInfo("Local IP Address [{}]", my_ip_address);
|
||||||
|
|
||||||
|
return std::string(my_ip_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets public address
|
* Gets public address
|
||||||
* Uses various websites as options to return raw public IP back to the client
|
* Uses various websites as options to return raw public IP back to the client
|
||||||
|
|||||||
+39
-36
@@ -32,10 +32,11 @@
|
|||||||
|
|
||||||
//#include <iostream>
|
//#include <iostream>
|
||||||
|
|
||||||
int32 NextItemInstSerialNumber = 1;
|
int32 next_item_serial_number = 1;
|
||||||
|
std::unordered_set<uint64> guids{};
|
||||||
static inline int32 GetNextItemInstSerialNumber() {
|
|
||||||
|
|
||||||
|
static inline int32 GetNextItemInstSerialNumber()
|
||||||
|
{
|
||||||
// The Bazaar relies on each item a client has up for Trade having a unique
|
// The Bazaar relies on each item a client has up for Trade having a unique
|
||||||
// identifier. This 'SerialNumber' is sent in Serialized item packets and
|
// identifier. This 'SerialNumber' is sent in Serialized item packets and
|
||||||
// is used in Bazaar packets to identify the item a player is buying or inspecting.
|
// is used in Bazaar packets to identify the item a player is buying or inspecting.
|
||||||
@@ -46,12 +47,18 @@ static inline int32 GetNextItemInstSerialNumber() {
|
|||||||
// NextItemInstSerialNumber is the next one to hand out.
|
// NextItemInstSerialNumber is the next one to hand out.
|
||||||
//
|
//
|
||||||
// It is very unlikely to reach 2,147,483,647. Maybe we should call abort(), rather than wrapping back to 1.
|
// It is very unlikely to reach 2,147,483,647. Maybe we should call abort(), rather than wrapping back to 1.
|
||||||
if(NextItemInstSerialNumber >= INT_MAX)
|
if (next_item_serial_number >= INT32_MAX) {
|
||||||
NextItemInstSerialNumber = 1;
|
next_item_serial_number = 1;
|
||||||
else
|
}
|
||||||
NextItemInstSerialNumber++;
|
else {
|
||||||
|
next_item_serial_number++;
|
||||||
|
}
|
||||||
|
|
||||||
return NextItemInstSerialNumber;
|
while (guids.contains(next_item_serial_number)) {
|
||||||
|
next_item_serial_number++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return next_item_serial_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -303,47 +310,34 @@ int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augment_type) const
|
|||||||
return INVALID_INDEX;
|
return INVALID_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto i = invaug::SOCKET_BEGIN;
|
for (int16 slot_id = invaug::SOCKET_BEGIN; slot_id <= invaug::SOCKET_END; ++slot_id) {
|
||||||
for (; i <= invaug::SOCKET_END; ++i) {
|
if (IsAugmentSlotAvailable(augment_type, slot_id)) {
|
||||||
if (GetItem(i)) {
|
return slot_id;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
augment_type == -1 ||
|
|
||||||
(
|
|
||||||
m_item->AugSlotType[i] &&
|
|
||||||
((1 << (m_item->AugSlotType[i] - 1)) & augment_type)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (i <= invaug::SOCKET_END) ? i : INVALID_INDEX;
|
return INVALID_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const
|
bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const
|
||||||
{
|
{
|
||||||
if (!m_item || !m_item->IsClassCommon()) {
|
if (!m_item || !m_item->IsClassCommon() || GetItem(slot)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
return (
|
||||||
(
|
(
|
||||||
!GetItem(slot) &&
|
augment_type == -1 ||
|
||||||
m_item->AugSlotVisible[slot]
|
(
|
||||||
|
m_item->AugSlotType[slot] &&
|
||||||
|
((1 << (m_item->AugSlotType[slot] - 1)) & augment_type)
|
||||||
|
)
|
||||||
) &&
|
) &&
|
||||||
augment_type == -1 ||
|
|
||||||
(
|
(
|
||||||
m_item->AugSlotType[slot] &&
|
RuleB(Items, AugmentItemAllowInvisibleAugments) ||
|
||||||
((1 << (m_item->AugSlotType[slot] - 1)) & augment_type)
|
m_item->AugSlotVisible[slot]
|
||||||
)
|
)
|
||||||
) {
|
);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve item inside container
|
// Retrieve item inside container
|
||||||
@@ -1292,7 +1286,7 @@ int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const
|
|||||||
return race;
|
return race;
|
||||||
}
|
}
|
||||||
|
|
||||||
int EQ::ItemInstance::GetItemBaneDamageBody(bodyType against, bool augments) const
|
int EQ::ItemInstance::GetItemBaneDamageBody(uint8 against, bool augments) const
|
||||||
{
|
{
|
||||||
int64 damage = 0;
|
int64 damage = 0;
|
||||||
const auto item = GetItem();
|
const auto item = GetItem();
|
||||||
@@ -1948,6 +1942,15 @@ int EQ::ItemInstance::GetItemSkillsStat(EQ::skills::SkillType skill, bool augmen
|
|||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EQ::ItemInstance::AddGUIDToMap(uint64 existing_serial_number)
|
||||||
|
{
|
||||||
|
guids.emplace(existing_serial_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::ItemInstance::ClearGUIDMap()
|
||||||
|
{
|
||||||
|
guids.clear();
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// class EvolveInfo
|
// class EvolveInfo
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ namespace EQ
|
|||||||
// these two are just quick checks
|
// these two are just quick checks
|
||||||
int GetItemBaneDamageBody(bool augments = false) const;
|
int GetItemBaneDamageBody(bool augments = false) const;
|
||||||
int GetItemBaneDamageRace(bool augments = false) const;
|
int GetItemBaneDamageRace(bool augments = false) const;
|
||||||
int GetItemBaneDamageBody(bodyType against, bool augments = false) const;
|
int GetItemBaneDamageBody(uint8 against, bool augments = false) const;
|
||||||
int GetItemBaneDamageRace(uint16 against, bool augments = false) const;
|
int GetItemBaneDamageRace(uint16 against, bool augments = false) const;
|
||||||
int GetItemMagical(bool augments = false) const;
|
int GetItemMagical(bool augments = false) const;
|
||||||
int GetItemHP(bool augments = false) const;
|
int GetItemHP(bool augments = false) const;
|
||||||
@@ -309,6 +309,8 @@ namespace EQ
|
|||||||
int GetItemSkillsStat(EQ::skills::SkillType skill, bool augments = false) const;
|
int GetItemSkillsStat(EQ::skills::SkillType skill, bool augments = false) const;
|
||||||
uint32 GetItemGuildFavor() const;
|
uint32 GetItemGuildFavor() const;
|
||||||
std::vector<uint32> GetAugmentIDs() const;
|
std::vector<uint32> GetAugmentIDs() const;
|
||||||
|
static void AddGUIDToMap(uint64 existing_serial_number);
|
||||||
|
static void ClearGUIDMap();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,55 @@
|
|||||||
|
/* EQEMu: Everquest Server Emulator
|
||||||
|
|
||||||
|
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 of the License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
are required to give you total support for your newly bought product;
|
||||||
|
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COMMON_LARION_H
|
||||||
|
#define COMMON_LARION_H
|
||||||
|
|
||||||
|
#include "../struct_strategy.h"
|
||||||
|
|
||||||
|
class EQStreamIdentifier;
|
||||||
|
|
||||||
|
namespace Larion
|
||||||
|
{
|
||||||
|
|
||||||
|
//these are the only public member of this namespace.
|
||||||
|
extern void Register(EQStreamIdentifier& into);
|
||||||
|
extern void Reload();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//you should not directly access anything below..
|
||||||
|
//I just dont feel like making a seperate header for it.
|
||||||
|
|
||||||
|
class Strategy : public StructStrategy {
|
||||||
|
public:
|
||||||
|
Strategy();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual std::string Describe() const;
|
||||||
|
virtual const EQ::versions::ClientVersion ClientVersion() const;
|
||||||
|
|
||||||
|
//magic macro to declare our opcode processors
|
||||||
|
#include "ss_declare.h"
|
||||||
|
#include "larion_ops.h"
|
||||||
|
};
|
||||||
|
|
||||||
|
}; /*Larion*/
|
||||||
|
|
||||||
|
#endif /*COMMON_LARION_H*/
|
||||||
@@ -0,0 +1,284 @@
|
|||||||
|
/* EQEMu: Everquest Server Emulator
|
||||||
|
|
||||||
|
Copyright (C) 2001-2016 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 "larion_limits.h"
|
||||||
|
|
||||||
|
#include "../strings.h"
|
||||||
|
|
||||||
|
|
||||||
|
int16 Larion::invtype::GetInvTypeSize(int16 inv_type)
|
||||||
|
{
|
||||||
|
switch (inv_type) {
|
||||||
|
case invtype::typePossessions:
|
||||||
|
return invtype::POSSESSIONS_SIZE;
|
||||||
|
case invtype::typeBank:
|
||||||
|
return invtype::BANK_SIZE;
|
||||||
|
case invtype::typeSharedBank:
|
||||||
|
return invtype::SHARED_BANK_SIZE;
|
||||||
|
case invtype::typeTrade:
|
||||||
|
return invtype::TRADE_SIZE;
|
||||||
|
case invtype::typeWorld:
|
||||||
|
return invtype::WORLD_SIZE;
|
||||||
|
case invtype::typeLimbo:
|
||||||
|
return invtype::LIMBO_SIZE;
|
||||||
|
case invtype::typeTribute:
|
||||||
|
return invtype::TRIBUTE_SIZE;
|
||||||
|
case invtype::typeTrophyTribute:
|
||||||
|
return invtype::TROPHY_TRIBUTE_SIZE;
|
||||||
|
case invtype::typeGuildTribute:
|
||||||
|
return invtype::GUILD_TRIBUTE_SIZE;
|
||||||
|
case invtype::typeMerchant:
|
||||||
|
return invtype::MERCHANT_SIZE;
|
||||||
|
case invtype::typeDeleted:
|
||||||
|
return invtype::DELETED_SIZE;
|
||||||
|
case invtype::typeCorpse:
|
||||||
|
return invtype::CORPSE_SIZE;
|
||||||
|
case invtype::typeBazaar:
|
||||||
|
return invtype::BAZAAR_SIZE;
|
||||||
|
case invtype::typeInspect:
|
||||||
|
return invtype::INSPECT_SIZE;
|
||||||
|
case invtype::typeRealEstate:
|
||||||
|
return invtype::REAL_ESTATE_SIZE;
|
||||||
|
case invtype::typeViewMODPC:
|
||||||
|
return invtype::VIEW_MOD_PC_SIZE;
|
||||||
|
case invtype::typeViewMODBank:
|
||||||
|
return invtype::VIEW_MOD_BANK_SIZE;
|
||||||
|
case invtype::typeViewMODSharedBank:
|
||||||
|
return invtype::VIEW_MOD_SHARED_BANK_SIZE;
|
||||||
|
case invtype::typeViewMODLimbo:
|
||||||
|
return invtype::VIEW_MOD_LIMBO_SIZE;
|
||||||
|
case invtype::typeAltStorage:
|
||||||
|
return invtype::ALT_STORAGE_SIZE;
|
||||||
|
case invtype::typeArchived:
|
||||||
|
return invtype::ARCHIVED_SIZE;
|
||||||
|
case invtype::typeMail:
|
||||||
|
return invtype::MAIL_SIZE;
|
||||||
|
case invtype::typeGuildTrophyTribute:
|
||||||
|
return invtype::GUILD_TROPHY_TRIBUTE_SIZE;
|
||||||
|
case invtype::typeKrono:
|
||||||
|
return invtype::KRONO_SIZE;
|
||||||
|
case invtype::typeOther:
|
||||||
|
return invtype::OTHER_SIZE;
|
||||||
|
default:
|
||||||
|
return INULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Larion::invtype::GetInvTypeName(int16 inv_type)
|
||||||
|
{
|
||||||
|
switch (inv_type) {
|
||||||
|
case invtype::TYPE_INVALID:
|
||||||
|
return "Invalid Type";
|
||||||
|
case invtype::typePossessions:
|
||||||
|
return "Possessions";
|
||||||
|
case invtype::typeBank:
|
||||||
|
return "Bank";
|
||||||
|
case invtype::typeSharedBank:
|
||||||
|
return "Shared Bank";
|
||||||
|
case invtype::typeTrade:
|
||||||
|
return "Trade";
|
||||||
|
case invtype::typeWorld:
|
||||||
|
return "World";
|
||||||
|
case invtype::typeLimbo:
|
||||||
|
return "Limbo";
|
||||||
|
case invtype::typeTribute:
|
||||||
|
return "Tribute";
|
||||||
|
case invtype::typeTrophyTribute:
|
||||||
|
return "Trophy Tribute";
|
||||||
|
case invtype::typeGuildTribute:
|
||||||
|
return "Guild Tribute";
|
||||||
|
case invtype::typeMerchant:
|
||||||
|
return "Merchant";
|
||||||
|
case invtype::typeDeleted:
|
||||||
|
return "Deleted";
|
||||||
|
case invtype::typeCorpse:
|
||||||
|
return "Corpse";
|
||||||
|
case invtype::typeBazaar:
|
||||||
|
return "Bazaar";
|
||||||
|
case invtype::typeInspect:
|
||||||
|
return "Inspect";
|
||||||
|
case invtype::typeRealEstate:
|
||||||
|
return "Real Estate";
|
||||||
|
case invtype::typeViewMODPC:
|
||||||
|
return "View MOD PC";
|
||||||
|
case invtype::typeViewMODBank:
|
||||||
|
return "View MOD Bank";
|
||||||
|
case invtype::typeViewMODSharedBank:
|
||||||
|
return "View MOD Shared Bank";
|
||||||
|
case invtype::typeViewMODLimbo:
|
||||||
|
return "View MOD Limbo";
|
||||||
|
case invtype::typeAltStorage:
|
||||||
|
return "Alt Storage";
|
||||||
|
case invtype::typeArchived:
|
||||||
|
return "Archived";
|
||||||
|
case invtype::typeMail:
|
||||||
|
return "Mail";
|
||||||
|
case invtype::typeGuildTrophyTribute:
|
||||||
|
return "Guild Trophy Tribute";
|
||||||
|
case invtype::typeKrono:
|
||||||
|
return "Krono";
|
||||||
|
case invtype::typeOther:
|
||||||
|
return "Other";
|
||||||
|
default:
|
||||||
|
return "Unknown Type";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Larion::invtype::IsInvTypePersistent(int16 inv_type)
|
||||||
|
{
|
||||||
|
switch (inv_type) {
|
||||||
|
case invtype::typePossessions:
|
||||||
|
case invtype::typeBank:
|
||||||
|
case invtype::typeSharedBank:
|
||||||
|
case invtype::typeTrade:
|
||||||
|
case invtype::typeWorld:
|
||||||
|
case invtype::typeLimbo:
|
||||||
|
case invtype::typeTribute:
|
||||||
|
case invtype::typeTrophyTribute:
|
||||||
|
case invtype::typeGuildTribute:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Larion::invslot::GetInvPossessionsSlotName(int16 inv_slot)
|
||||||
|
{
|
||||||
|
switch (inv_slot) {
|
||||||
|
case invslot::SLOT_INVALID:
|
||||||
|
return "Invalid Slot";
|
||||||
|
case invslot::slotCharm:
|
||||||
|
return "Charm";
|
||||||
|
case invslot::slotEar1:
|
||||||
|
return "Ear 1";
|
||||||
|
case invslot::slotHead:
|
||||||
|
return "Head";
|
||||||
|
case invslot::slotFace:
|
||||||
|
return "Face";
|
||||||
|
case invslot::slotEar2:
|
||||||
|
return "Ear 2";
|
||||||
|
case invslot::slotNeck:
|
||||||
|
return "Neck";
|
||||||
|
case invslot::slotShoulders:
|
||||||
|
return "Shoulders";
|
||||||
|
case invslot::slotArms:
|
||||||
|
return "Arms";
|
||||||
|
case invslot::slotBack:
|
||||||
|
return "Back";
|
||||||
|
case invslot::slotWrist1:
|
||||||
|
return "Wrist 1";
|
||||||
|
case invslot::slotWrist2:
|
||||||
|
return "Wrist 2";
|
||||||
|
case invslot::slotRange:
|
||||||
|
return "Range";
|
||||||
|
case invslot::slotHands:
|
||||||
|
return "Hands";
|
||||||
|
case invslot::slotPrimary:
|
||||||
|
return "Primary";
|
||||||
|
case invslot::slotSecondary:
|
||||||
|
return "Secondary";
|
||||||
|
case invslot::slotFinger1:
|
||||||
|
return "Finger 1";
|
||||||
|
case invslot::slotFinger2:
|
||||||
|
return "Finger 2";
|
||||||
|
case invslot::slotChest:
|
||||||
|
return "Chest";
|
||||||
|
case invslot::slotLegs:
|
||||||
|
return "Legs";
|
||||||
|
case invslot::slotFeet:
|
||||||
|
return "Feet";
|
||||||
|
case invslot::slotWaist:
|
||||||
|
return "Waist";
|
||||||
|
case invslot::slotPowerSource:
|
||||||
|
return "Power Source";
|
||||||
|
case invslot::slotAmmo:
|
||||||
|
return "Ammo";
|
||||||
|
case invslot::slotGeneral1:
|
||||||
|
return "General 1";
|
||||||
|
case invslot::slotGeneral2:
|
||||||
|
return "General 2";
|
||||||
|
case invslot::slotGeneral3:
|
||||||
|
return "General 3";
|
||||||
|
case invslot::slotGeneral4:
|
||||||
|
return "General 4";
|
||||||
|
case invslot::slotGeneral5:
|
||||||
|
return "General 5";
|
||||||
|
case invslot::slotGeneral6:
|
||||||
|
return "General 6";
|
||||||
|
case invslot::slotGeneral7:
|
||||||
|
return "General 7";
|
||||||
|
case invslot::slotGeneral8:
|
||||||
|
return "General 8";
|
||||||
|
case invslot::slotGeneral9:
|
||||||
|
return "General 9";
|
||||||
|
case invslot::slotGeneral10:
|
||||||
|
return "General 10";
|
||||||
|
case invslot::slotCursor:
|
||||||
|
return "Cursor";
|
||||||
|
default:
|
||||||
|
return "Unknown Slot";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Larion::invslot::GetInvSlotName(int16 inv_type, int16 inv_slot)
|
||||||
|
{
|
||||||
|
if (inv_type == invtype::typePossessions)
|
||||||
|
return invslot::GetInvPossessionsSlotName(inv_slot);
|
||||||
|
|
||||||
|
int16 type_size = invtype::GetInvTypeSize(inv_type);
|
||||||
|
|
||||||
|
if (!type_size || inv_slot == invslot::SLOT_INVALID)
|
||||||
|
return "Invalid Slot";
|
||||||
|
|
||||||
|
if ((inv_slot + 1) >= type_size)
|
||||||
|
return "Unknown Slot";
|
||||||
|
|
||||||
|
static std::string ret_str;
|
||||||
|
ret_str = StringFormat("Slot %i", (inv_slot + 1));
|
||||||
|
|
||||||
|
return ret_str.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Larion::invbag::GetInvBagIndexName(int16 bag_index)
|
||||||
|
{
|
||||||
|
if (bag_index == invbag::SLOT_INVALID)
|
||||||
|
return "Invalid Bag";
|
||||||
|
|
||||||
|
if (bag_index >= invbag::SLOT_COUNT)
|
||||||
|
return "Unknown Bag";
|
||||||
|
|
||||||
|
static std::string ret_str;
|
||||||
|
ret_str = StringFormat("Bag %i", (bag_index + 1));
|
||||||
|
|
||||||
|
return ret_str.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Larion::invaug::GetInvAugIndexName(int16 aug_index)
|
||||||
|
{
|
||||||
|
if (aug_index == invaug::SOCKET_INVALID)
|
||||||
|
return "Invalid Augment";
|
||||||
|
|
||||||
|
if (aug_index >= invaug::SOCKET_COUNT)
|
||||||
|
return "Unknown Augment";
|
||||||
|
|
||||||
|
static std::string ret_str;
|
||||||
|
ret_str = StringFormat("Augment %i", (aug_index + 1));
|
||||||
|
|
||||||
|
return ret_str.c_str();
|
||||||
|
}
|
||||||
@@ -0,0 +1,330 @@
|
|||||||
|
/* EQEMu: Everquest Server Emulator
|
||||||
|
|
||||||
|
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 of the License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
are required to give you total support for your newly bought product;
|
||||||
|
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COMMON_LARION_LIMITS_H
|
||||||
|
#define COMMON_LARION_LIMITS_H
|
||||||
|
|
||||||
|
#include "../types.h"
|
||||||
|
#include "../emu_versions.h"
|
||||||
|
#include "../skills.h"
|
||||||
|
|
||||||
|
namespace Larion
|
||||||
|
{
|
||||||
|
const int16 IINVALID = -1;
|
||||||
|
const int16 INULL = 0;
|
||||||
|
|
||||||
|
namespace inventory {
|
||||||
|
inline EQ::versions::ClientVersion GetInventoryRef() { return EQ::versions::ClientVersion::Larion; }
|
||||||
|
|
||||||
|
const bool ConcatenateInvTypeLimbo = false;
|
||||||
|
|
||||||
|
const bool AllowOverLevelEquipment = true;
|
||||||
|
|
||||||
|
const bool AllowEmptyBagInBag = true;
|
||||||
|
const bool AllowClickCastFromBag = true;
|
||||||
|
|
||||||
|
} /*inventory*/
|
||||||
|
|
||||||
|
namespace invtype {
|
||||||
|
inline EQ::versions::ClientVersion GetInvTypeRef() { return EQ::versions::ClientVersion::Larion; }
|
||||||
|
|
||||||
|
namespace enum_ {
|
||||||
|
enum InventoryTypes : int16 {
|
||||||
|
typePossessions = INULL,
|
||||||
|
typeBank,
|
||||||
|
typeSharedBank,
|
||||||
|
typeTrade,
|
||||||
|
typeWorld,
|
||||||
|
typeLimbo,
|
||||||
|
typeTribute,
|
||||||
|
typeTrophyTribute,
|
||||||
|
typeGuildTribute,
|
||||||
|
typeMerchant,
|
||||||
|
typeDeleted,
|
||||||
|
typeCorpse,
|
||||||
|
typeBazaar,
|
||||||
|
typeInspect,
|
||||||
|
typeRealEstate,
|
||||||
|
typeViewMODPC,
|
||||||
|
typeViewMODBank,
|
||||||
|
typeViewMODSharedBank,
|
||||||
|
typeViewMODLimbo,
|
||||||
|
typeAltStorage,
|
||||||
|
typeArchived,
|
||||||
|
typeMail,
|
||||||
|
typeGuildTrophyTribute,
|
||||||
|
typeKrono,
|
||||||
|
typeOther
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace enum_
|
||||||
|
using namespace enum_;
|
||||||
|
|
||||||
|
const int16 POSSESSIONS_SIZE = 34;
|
||||||
|
const int16 BANK_SIZE = 24;
|
||||||
|
const int16 SHARED_BANK_SIZE = 2;
|
||||||
|
const int16 TRADE_SIZE = 8;
|
||||||
|
const int16 WORLD_SIZE = 10;
|
||||||
|
const int16 LIMBO_SIZE = 36;
|
||||||
|
const int16 TRIBUTE_SIZE = 5;
|
||||||
|
const int16 TROPHY_TRIBUTE_SIZE = 0;//unknown
|
||||||
|
const int16 GUILD_TRIBUTE_SIZE = 2;//unverified
|
||||||
|
const int16 MERCHANT_SIZE = 200;
|
||||||
|
const int16 DELETED_SIZE = 0;//unknown - "Recovery Tab"
|
||||||
|
const int16 CORPSE_SIZE = POSSESSIONS_SIZE;
|
||||||
|
const int16 BAZAAR_SIZE = 200;
|
||||||
|
const int16 INSPECT_SIZE = 23;
|
||||||
|
const int16 REAL_ESTATE_SIZE = 0;//unknown
|
||||||
|
const int16 VIEW_MOD_PC_SIZE = POSSESSIONS_SIZE;
|
||||||
|
const int16 VIEW_MOD_BANK_SIZE = BANK_SIZE;
|
||||||
|
const int16 VIEW_MOD_SHARED_BANK_SIZE = SHARED_BANK_SIZE;
|
||||||
|
const int16 VIEW_MOD_LIMBO_SIZE = LIMBO_SIZE;
|
||||||
|
const int16 ALT_STORAGE_SIZE = 0;//unknown - "Shroud Bank"
|
||||||
|
const int16 ARCHIVED_SIZE = 0;//unknown
|
||||||
|
const int16 MAIL_SIZE = 0;//unknown
|
||||||
|
const int16 GUILD_TROPHY_TRIBUTE_SIZE = 0;//unknown
|
||||||
|
const int16 KRONO_SIZE = 0;//unknown
|
||||||
|
const int16 OTHER_SIZE = 0;//unknown
|
||||||
|
|
||||||
|
const int16 TRADE_NPC_SIZE = 4; // defined by implication
|
||||||
|
|
||||||
|
const int16 TYPE_INVALID = IINVALID;
|
||||||
|
const int16 TYPE_BEGIN = typePossessions;
|
||||||
|
const int16 TYPE_END = typeOther;
|
||||||
|
const int16 TYPE_COUNT = (TYPE_END - TYPE_BEGIN) + 1;
|
||||||
|
|
||||||
|
int16 GetInvTypeSize(int16 inv_type);
|
||||||
|
const char* GetInvTypeName(int16 inv_type);
|
||||||
|
|
||||||
|
bool IsInvTypePersistent(int16 inv_type);
|
||||||
|
|
||||||
|
} /*invtype*/
|
||||||
|
|
||||||
|
namespace invslot {
|
||||||
|
inline EQ::versions::ClientVersion GetInvSlotRef() { return EQ::versions::ClientVersion::Larion; }
|
||||||
|
|
||||||
|
namespace enum_ {
|
||||||
|
enum InventorySlots : int16 {
|
||||||
|
slotCharm = INULL,
|
||||||
|
slotEar1,
|
||||||
|
slotHead,
|
||||||
|
slotFace,
|
||||||
|
slotEar2,
|
||||||
|
slotNeck,
|
||||||
|
slotShoulders,
|
||||||
|
slotArms,
|
||||||
|
slotBack,
|
||||||
|
slotWrist1,
|
||||||
|
slotWrist2,
|
||||||
|
slotRange,
|
||||||
|
slotHands,
|
||||||
|
slotPrimary,
|
||||||
|
slotSecondary,
|
||||||
|
slotFinger1,
|
||||||
|
slotFinger2,
|
||||||
|
slotChest,
|
||||||
|
slotLegs,
|
||||||
|
slotFeet,
|
||||||
|
slotWaist,
|
||||||
|
slotPowerSource,
|
||||||
|
slotAmmo,
|
||||||
|
slotGeneral1,
|
||||||
|
slotGeneral2,
|
||||||
|
slotGeneral3,
|
||||||
|
slotGeneral4,
|
||||||
|
slotGeneral5,
|
||||||
|
slotGeneral6,
|
||||||
|
slotGeneral7,
|
||||||
|
slotGeneral8,
|
||||||
|
slotGeneral9,
|
||||||
|
slotGeneral10,
|
||||||
|
slotCursor
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr int16 format_as(InventorySlots slot) { return static_cast<int16>(slot); }
|
||||||
|
} // namespace enum_
|
||||||
|
using namespace enum_;
|
||||||
|
|
||||||
|
const int16 SLOT_INVALID = IINVALID;
|
||||||
|
const int16 SLOT_BEGIN = INULL;
|
||||||
|
|
||||||
|
const int16 POSSESSIONS_BEGIN = slotCharm;
|
||||||
|
const int16 POSSESSIONS_END = slotCursor;
|
||||||
|
const int16 POSSESSIONS_COUNT = (POSSESSIONS_END - POSSESSIONS_BEGIN) + 1;
|
||||||
|
|
||||||
|
const int16 EQUIPMENT_BEGIN = slotCharm;
|
||||||
|
const int16 EQUIPMENT_END = slotAmmo;
|
||||||
|
const int16 EQUIPMENT_COUNT = (EQUIPMENT_END - EQUIPMENT_BEGIN) + 1;
|
||||||
|
|
||||||
|
const int16 GENERAL_BEGIN = slotGeneral1;
|
||||||
|
const int16 GENERAL_END = slotGeneral10;
|
||||||
|
const int16 GENERAL_COUNT = (GENERAL_END - GENERAL_BEGIN) + 1;
|
||||||
|
|
||||||
|
const int16 BONUS_BEGIN = invslot::slotCharm;
|
||||||
|
const int16 BONUS_STAT_END = invslot::slotPowerSource;
|
||||||
|
const int16 BONUS_SKILL_END = invslot::slotAmmo;
|
||||||
|
|
||||||
|
const int16 CORPSE_BEGIN = invslot::slotGeneral1;
|
||||||
|
const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor;
|
||||||
|
|
||||||
|
const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF;
|
||||||
|
const uint64 GENERAL_BITMASK = 0x00000001FF800000;
|
||||||
|
const uint64 CURSOR_BITMASK = 0x0000000200000000;
|
||||||
|
const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+)
|
||||||
|
const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+)
|
||||||
|
|
||||||
|
|
||||||
|
const char* GetInvPossessionsSlotName(int16 inv_slot);
|
||||||
|
const char* GetInvSlotName(int16 inv_type, int16 inv_slot);
|
||||||
|
|
||||||
|
} /*invslot*/
|
||||||
|
|
||||||
|
namespace invbag {
|
||||||
|
inline EQ::versions::ClientVersion GetInvBagRef() { return EQ::versions::ClientVersion::Larion; }
|
||||||
|
|
||||||
|
const int16 SLOT_INVALID = IINVALID;
|
||||||
|
const int16 SLOT_BEGIN = INULL;
|
||||||
|
const int16 SLOT_END = 9; //254;
|
||||||
|
const int16 SLOT_COUNT = 10; //255; // server Size will be 255..unsure what actual client is (test)
|
||||||
|
|
||||||
|
const char* GetInvBagIndexName(int16 bag_index);
|
||||||
|
|
||||||
|
} /*invbag*/
|
||||||
|
|
||||||
|
namespace invaug {
|
||||||
|
inline EQ::versions::ClientVersion GetInvAugRef() { return EQ::versions::ClientVersion::Larion; }
|
||||||
|
|
||||||
|
const int16 SOCKET_INVALID = IINVALID;
|
||||||
|
const int16 SOCKET_BEGIN = INULL;
|
||||||
|
const int16 SOCKET_END = 5;
|
||||||
|
const int16 SOCKET_COUNT = 6;
|
||||||
|
|
||||||
|
const char* GetInvAugIndexName(int16 aug_index);
|
||||||
|
|
||||||
|
} /*invaug*/
|
||||||
|
|
||||||
|
namespace item {
|
||||||
|
inline EQ::versions::ClientVersion GetItemRef() { return EQ::versions::ClientVersion::Larion; }
|
||||||
|
|
||||||
|
//enum Unknown : int { // looks like item class..but, RoF has it too - nothing in UF-
|
||||||
|
// Unknown1 = 0,
|
||||||
|
// Unknown2 = 1,
|
||||||
|
// Unknown3 = 2,
|
||||||
|
// Unknown4 = 5 // krono?
|
||||||
|
//};
|
||||||
|
|
||||||
|
enum ItemPacketType : int {
|
||||||
|
ItemPacketMerchant = 100,
|
||||||
|
ItemPacketTradeView = 101,
|
||||||
|
ItemPacketLoot = 102,
|
||||||
|
ItemPacketTrade = 103,
|
||||||
|
ItemPacketCharInventory = 105,
|
||||||
|
ItemPacketLimbo = 106,
|
||||||
|
ItemPacketWorldContainer = 107,
|
||||||
|
ItemPacketTributeItem = 108,
|
||||||
|
ItemPacketGuildTribute = 109,
|
||||||
|
ItemPacket10 = 110,
|
||||||
|
ItemPacket11 = 111,
|
||||||
|
ItemPacket12 = 112,
|
||||||
|
ItemPacketRecovery = 113,
|
||||||
|
ItemPacket14 = 115 // Parcel? adds to merchant window too
|
||||||
|
};
|
||||||
|
|
||||||
|
} /*item*/
|
||||||
|
|
||||||
|
namespace profile {
|
||||||
|
inline EQ::versions::ClientVersion GetProfileRef() { return EQ::versions::ClientVersion::Larion; }
|
||||||
|
|
||||||
|
const int16 BANDOLIERS_SIZE = 20; // number of bandolier instances
|
||||||
|
const int16 BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance
|
||||||
|
|
||||||
|
const int16 POTION_BELT_SIZE = 5;
|
||||||
|
|
||||||
|
const int16 SKILL_ARRAY_SIZE = 100;
|
||||||
|
|
||||||
|
} /*profile*/
|
||||||
|
|
||||||
|
namespace constants {
|
||||||
|
inline EQ::versions::ClientVersion GetConstantsRef() { return EQ::versions::ClientVersion::Larion; }
|
||||||
|
|
||||||
|
const EQ::expansions::Expansion EXPANSION = EQ::expansions::Expansion::LS;
|
||||||
|
const uint32 EXPANSION_BIT = EQ::expansions::bitLS;
|
||||||
|
const uint32 EXPANSIONS_MASK = EQ::expansions::maskLS;
|
||||||
|
|
||||||
|
const size_t CHARACTER_CREATION_LIMIT = 12;
|
||||||
|
|
||||||
|
const size_t SAY_LINK_BODY_SIZE = 56;
|
||||||
|
const uint32 MAX_GUILD_ID = 50000;
|
||||||
|
|
||||||
|
} /*constants*/
|
||||||
|
|
||||||
|
namespace behavior {
|
||||||
|
inline EQ::versions::ClientVersion GetBehaviorRef() { return EQ::versions::ClientVersion::Larion; }
|
||||||
|
|
||||||
|
const bool CoinHasWeight = false;
|
||||||
|
|
||||||
|
} /*behavior*/
|
||||||
|
|
||||||
|
namespace skills {
|
||||||
|
inline EQ::versions::ClientVersion GetSkillsRef() { return EQ::versions::ClientVersion::Larion; }
|
||||||
|
|
||||||
|
const size_t LastUsableSkill = EQ::skills::Skill2HPiercing;
|
||||||
|
|
||||||
|
} /*skills*/
|
||||||
|
|
||||||
|
namespace spells {
|
||||||
|
inline EQ::versions::ClientVersion GetSkillsRef() { return EQ::versions::ClientVersion::Larion; }
|
||||||
|
|
||||||
|
enum class CastingSlot : uint32 {
|
||||||
|
Gem1 = 0,
|
||||||
|
Gem2 = 1,
|
||||||
|
Gem3 = 2,
|
||||||
|
Gem4 = 3,
|
||||||
|
Gem5 = 4,
|
||||||
|
Gem6 = 5,
|
||||||
|
Gem7 = 6,
|
||||||
|
Gem8 = 7,
|
||||||
|
Gem9 = 8,
|
||||||
|
Gem10 = 9,
|
||||||
|
Gem11 = 10,
|
||||||
|
Gem12 = 11,
|
||||||
|
MaxGems = 18, // fallacy..only 12 slot are useable...
|
||||||
|
Item = 12,
|
||||||
|
Discipline = 13,
|
||||||
|
AltAbility = 0xFF
|
||||||
|
};
|
||||||
|
|
||||||
|
const int SPELL_ID_MAX = 71999;
|
||||||
|
const int SPELLBOOK_SIZE = 1120;
|
||||||
|
const int SPELL_GEM_COUNT = static_cast<uint32>(CastingSlot::MaxGems);
|
||||||
|
const int SPELL_GEM_RECAST_TIMER = 15;
|
||||||
|
|
||||||
|
const int LONG_BUFFS = 42;
|
||||||
|
const int SHORT_BUFFS = 20;
|
||||||
|
const int DISC_BUFFS = 1;
|
||||||
|
const int TOTAL_BUFFS = LONG_BUFFS + SHORT_BUFFS + DISC_BUFFS;
|
||||||
|
const int NPC_BUFFS = 97;
|
||||||
|
const int PET_BUFFS = NPC_BUFFS;
|
||||||
|
const int MERC_BUFFS = LONG_BUFFS;
|
||||||
|
|
||||||
|
} /*spells*/
|
||||||
|
|
||||||
|
}; /* Larion */
|
||||||
|
|
||||||
|
#endif /*COMMON_LARION_LIMITS_H*/
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
//list of packets we need to encode on the way out:
|
||||||
|
E(OP_LogServer)
|
||||||
|
E(OP_SendMembership)
|
||||||
|
E(OP_SendMembershipDetails)
|
||||||
|
E(OP_SendMaxCharacters)
|
||||||
|
E(OP_SendCharInfo)
|
||||||
|
E(OP_ExpansionInfo)
|
||||||
|
E(OP_SpawnAppearance)
|
||||||
|
//E(OP_SendAATable)
|
||||||
|
E(OP_PlayerProfile)
|
||||||
|
E(OP_ZoneEntry)
|
||||||
|
E(OP_ZoneSpawns)
|
||||||
|
|
||||||
|
//list of packets we need to decode on the way in:
|
||||||
|
D(OP_ZoneEntry)
|
||||||
|
|
||||||
|
#undef E
|
||||||
|
#undef D
|
||||||
@@ -0,0 +1,233 @@
|
|||||||
|
#ifndef LARION_STRUCTS_H_
|
||||||
|
#define LARION_STRUCTS_H_
|
||||||
|
|
||||||
|
namespace Larion {
|
||||||
|
namespace structs {
|
||||||
|
// constants
|
||||||
|
static const uint32 MAX_PP_AA_ARRAY = 300;
|
||||||
|
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE;
|
||||||
|
static const uint32 MAX_PP_INNATE_SKILL = 25;
|
||||||
|
static const uint32 MAX_PP_DISCIPLINES = 300;
|
||||||
|
static const uint32 MAX_PP_COMBAT_ABILITY_TIMERS = 25;
|
||||||
|
static const uint32 MAX_PP_UNKNOWN_ABILITIES = 25;
|
||||||
|
static const uint32 MAX_RECAST_TYPES = 25;
|
||||||
|
static const uint32 MAX_ITEM_RECAST_TYPES = 100;
|
||||||
|
static const uint32 BUFF_COUNT = 62;
|
||||||
|
static const uint32 MAX_PP_LANGUAGE = 32;
|
||||||
|
#pragma pack(1)
|
||||||
|
|
||||||
|
struct LoginInfo_Struct {
|
||||||
|
/*000*/ char login_info[64];
|
||||||
|
/*064*/ uint8 unknown064[124];
|
||||||
|
/*188*/ uint8 zoning; // 01 if zoning, 00 if not
|
||||||
|
/*189*/ uint8 unknown189[275];
|
||||||
|
/*488*/
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ClientZoneEntry_Struct {
|
||||||
|
/*00*/ uint32 unknown00; // ***Placeholder
|
||||||
|
/*04*/ char char_name[64]; // Player firstname [32]
|
||||||
|
/*68*/ uint32 unknown68;
|
||||||
|
/*72*/ uint32 unknown72;
|
||||||
|
/*76*/ uint32 unknown76;
|
||||||
|
/*80*/ uint32 unknown80;
|
||||||
|
/*84*/ uint32 unknown84;
|
||||||
|
/*88*/ uint32 unknown88;
|
||||||
|
/*92*/
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Membership_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint8 membership; //0 not gold, 2 gold
|
||||||
|
/*001*/ uint32 races; // Seen ff ff 01 00
|
||||||
|
/*005*/ uint32 classes; // Seen ff ff 01 00
|
||||||
|
/*009*/ uint32 entrysize; // Seen 33
|
||||||
|
/*013*/ int32 entries[33]; // Most -1, 1, and 0 for Gold Status
|
||||||
|
/*145*/
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Membership_Entry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 purchase_id; // Seen 1, then increments 90287 to 90300
|
||||||
|
/*004*/ uint32 bitwise_entry; // Seen 16 to 65536 - Skips 4096
|
||||||
|
/*008*/
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Membership_Setting_Struct
|
||||||
|
{
|
||||||
|
/*000*/ int8 setting_index; // 0, 1, 2 or 3: f2p, silver, gold, platinum?
|
||||||
|
/*001*/ int32 setting_id; // 0 to 23 actually seen but the OP_Membership packet has up to 32
|
||||||
|
/*005*/ int32 setting_value;
|
||||||
|
/*009*/
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Membership_Details_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 membership_setting_count; // Seen 96
|
||||||
|
/*004*/ Membership_Setting_Struct settings[96]; // 864 Bytes
|
||||||
|
/*364*/ uint32 race_entry_count; // Seen 17
|
||||||
|
/*368*/ Membership_Entry_Struct membership_races[17]; // 136 Bytes
|
||||||
|
/*3f0*/ uint32 class_entry_count; // Seen 15
|
||||||
|
/*3f4*/ Membership_Entry_Struct membership_classes[17]; // 136 Bytes
|
||||||
|
/*47c*/ uint32 exit_url_length; // Length of the exit_url string (0 for none)
|
||||||
|
/*480*/ //char exit_url[42]; // Upgrade to Silver or Gold Membership URL
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MaxCharacters_Struct {
|
||||||
|
/*000*/ uint32 max_chars;
|
||||||
|
/*004*/ uint32 marketplace_chars;
|
||||||
|
/*008*/ int32 unknown008; //some of these probably deal with heroic characters or something
|
||||||
|
/*00c*/ int32 unknown00c;
|
||||||
|
/*010*/ int32 unknown010;
|
||||||
|
/*014*/ int32 unknown014;
|
||||||
|
/*018*/ int32 unknown018;
|
||||||
|
/*01c*/ int32 unknown01c;
|
||||||
|
/*020*/ int32 unknown020;
|
||||||
|
/*024*/ int32 unknown024;
|
||||||
|
/*028*/ int32 unknown028;
|
||||||
|
/*02c*/ int32 unknown02c;
|
||||||
|
/*030*/ int32 unknown030;
|
||||||
|
/*034*/ int32 unknown034;
|
||||||
|
/*038*/
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpansionInfo_Struct {
|
||||||
|
/*000*/ char Unknown000[64];
|
||||||
|
/*064*/ uint32 Expansions;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Visible equiptment.
|
||||||
|
* Size: 20 Octets
|
||||||
|
*/
|
||||||
|
struct Texture_Struct
|
||||||
|
{
|
||||||
|
uint32 Material;
|
||||||
|
uint32 Unknown1;
|
||||||
|
uint32 EliteMaterial;
|
||||||
|
uint32 HeroForgeModel;
|
||||||
|
uint32 Material2; // Same as material?
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Color_Struct
|
||||||
|
** Size: 4 bytes
|
||||||
|
** Used for convenience
|
||||||
|
** Merth: Gave struct a name so gcc 2.96 would compile
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
struct Tint_Struct
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint8 Blue;
|
||||||
|
uint8 Green;
|
||||||
|
uint8 Red;
|
||||||
|
uint8 UseTint; // if there's a tint this is FF
|
||||||
|
};
|
||||||
|
uint32 Color;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CharSelectEquip : Texture_Struct, Tint_Struct {};
|
||||||
|
|
||||||
|
struct CharacterSelectEntry_Struct
|
||||||
|
{
|
||||||
|
char Name[1];
|
||||||
|
uint32 Class;
|
||||||
|
uint32 Race;
|
||||||
|
uint8 Level;
|
||||||
|
uint32 ShroudClass;
|
||||||
|
uint32 ShroudRace;
|
||||||
|
uint16 Zone;
|
||||||
|
uint16 Instance;
|
||||||
|
uint8 Gender;
|
||||||
|
uint8 Face;
|
||||||
|
CharSelectEquip Equip[9];
|
||||||
|
uint8 Unknown1; //Seen 256
|
||||||
|
uint8 Unknown2; //Seen 0
|
||||||
|
uint32 DrakkinTattoo;
|
||||||
|
uint32 DrakkinDetails;
|
||||||
|
uint32 Deity;
|
||||||
|
uint32 PrimaryIDFile;
|
||||||
|
uint32 SecondaryIDFile;
|
||||||
|
uint8 HairColor;
|
||||||
|
uint8 BeardColor;
|
||||||
|
uint8 EyeColor1;
|
||||||
|
uint8 EyeColor2;
|
||||||
|
uint8 HairStyle;
|
||||||
|
uint8 Beard;
|
||||||
|
uint8 Enabled;
|
||||||
|
uint8 Tutorial;
|
||||||
|
uint32 DrakkinHeritage;
|
||||||
|
uint8 Unknown3;
|
||||||
|
uint8 GoHome;
|
||||||
|
uint32 LastLogin;
|
||||||
|
uint8 Unknown4; // Seen 0
|
||||||
|
uint8 Unknown5; // Seen 0
|
||||||
|
uint8 Unknown6; // Seen 0
|
||||||
|
uint8 Unknown7; // Seen 0
|
||||||
|
uint32 CharacterId; //A Guess, Character I made a little bit after has a number a few hundred after the first
|
||||||
|
uint32 Unknown8; // Seen 1
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Character Selection Struct
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
struct CharacterSelect_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 CharCount; //number of chars in this packet
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SpawnAppearance_Struct
|
||||||
|
{
|
||||||
|
/*0000*/ uint32 spawn_id; // ID of the spawn
|
||||||
|
/*0004*/ uint32 type; // Values associated with the type
|
||||||
|
/*0008*/ uint32 parameter; // Type of data sent
|
||||||
|
/*0012*/ uint32 unknown012;
|
||||||
|
/*0016*/ uint32 unknown016;
|
||||||
|
/*0020*/ uint32 unknown020;
|
||||||
|
/*0024*/
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Spawn_Struct_Bitfields
|
||||||
|
{
|
||||||
|
// byte 1
|
||||||
|
/*00*/ unsigned gender : 2; // Gender (0=male, 1=female, 2=monster)
|
||||||
|
/*02*/ unsigned ispet : 1; // Guessed based on observing live spawns
|
||||||
|
/*03*/ unsigned afk : 1; // 0=no, 1=afk
|
||||||
|
/*04*/ unsigned anon : 2; // 0=normal, 1=anon, 2=roleplay
|
||||||
|
/*06*/ unsigned gm : 1;
|
||||||
|
/*07*/ unsigned sneak : 1;
|
||||||
|
// byte 2
|
||||||
|
/*08*/ unsigned lfg : 1;
|
||||||
|
/*09*/ unsigned unk9 : 1;
|
||||||
|
/*10*/ unsigned invis : 12; // there are 3000 different (non-GM) invis levels
|
||||||
|
/*22*/ unsigned linkdead : 1; // 1 Toggles LD on or off after name. Correct for RoF2
|
||||||
|
/*23*/ unsigned showhelm : 1;
|
||||||
|
// byte 4
|
||||||
|
/*24*/ unsigned betabuffed : 1; // Prefixes name with !
|
||||||
|
/*25*/ unsigned trader : 1;
|
||||||
|
/*26*/ unsigned animationonpop : 1;
|
||||||
|
/*27*/ unsigned targetable : 1;
|
||||||
|
/*28*/ unsigned targetable_with_hotkey : 1;
|
||||||
|
/*29*/ unsigned showname : 1;
|
||||||
|
/*30*/ unsigned idleanimationsoff : 1; // what we called statue?
|
||||||
|
/*31*/ unsigned untargetable : 1; // bClickThrough
|
||||||
|
// byte 5
|
||||||
|
/*32*/ unsigned buyer : 1;
|
||||||
|
/*33*/ unsigned offline : 1;
|
||||||
|
/*34*/ unsigned interactiveobject : 1;
|
||||||
|
/*35*/ unsigned missile : 1;
|
||||||
|
/*36*/ unsigned title : 1;
|
||||||
|
/*37*/ unsigned suffix : 1;
|
||||||
|
/*38*/ unsigned unk38 : 1;
|
||||||
|
/*39*/ unsigned unk39 : 1;
|
||||||
|
};
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
}; //end namespace structs
|
||||||
|
}; //end namespace larion
|
||||||
|
|
||||||
|
#endif /*LARION_STRUCTS_H_*/
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
#include "sod.h"
|
#include "sod.h"
|
||||||
#include "rof.h"
|
#include "rof.h"
|
||||||
#include "rof2.h"
|
#include "rof2.h"
|
||||||
|
#include "larion.h"
|
||||||
|
|
||||||
void RegisterAllPatches(EQStreamIdentifier &into)
|
void RegisterAllPatches(EQStreamIdentifier &into)
|
||||||
{
|
{
|
||||||
@@ -36,6 +36,7 @@ void RegisterAllPatches(EQStreamIdentifier &into)
|
|||||||
UF::Register(into);
|
UF::Register(into);
|
||||||
RoF::Register(into);
|
RoF::Register(into);
|
||||||
RoF2::Register(into);
|
RoF2::Register(into);
|
||||||
|
Larion::Register(into);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReloadAllPatches()
|
void ReloadAllPatches()
|
||||||
@@ -46,4 +47,5 @@ void ReloadAllPatches()
|
|||||||
UF::Reload();
|
UF::Reload();
|
||||||
RoF::Reload();
|
RoF::Reload();
|
||||||
RoF2::Reload();
|
RoF2::Reload();
|
||||||
|
Larion::Reload();
|
||||||
}
|
}
|
||||||
|
|||||||
+522
-31
@@ -356,41 +356,91 @@ namespace RoF2
|
|||||||
|
|
||||||
ENCODE(OP_Barter)
|
ENCODE(OP_Barter)
|
||||||
{
|
{
|
||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
*p = nullptr;
|
*p = nullptr;
|
||||||
|
|
||||||
char *Buffer = (char *)in->pBuffer;
|
char *buffer = (char *) in->pBuffer;
|
||||||
|
uint32 sub_action = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
|
||||||
uint32 SubAction = VARSTRUCT_DECODE_TYPE(uint32, Buffer);
|
switch (sub_action) {
|
||||||
|
case Barter_BuyerAppearance: {
|
||||||
|
auto emu = (BuyerInspectRequest_Struct *) in->pBuffer;
|
||||||
|
|
||||||
if (SubAction != Barter_BuyerAppearance)
|
auto outapp = new EQApplicationPacket(OP_Barter, sizeof(structs::Buyer_SetAppearance_Struct));
|
||||||
{
|
auto eq = (structs::Buyer_SetAppearance_Struct *) outapp->pBuffer;
|
||||||
dest->FastQueuePacket(&in, ack_req);
|
|
||||||
|
|
||||||
return;
|
eq->action = structs::RoF2BuyerActions::BuyerAppearance;
|
||||||
|
eq->entity_id = emu->buyer_id;
|
||||||
|
eq->enabled = emu->approval;
|
||||||
|
|
||||||
|
dest->FastQueuePacket(&outapp);
|
||||||
|
safe_delete(in);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Barter_BuyerItemRemove: {
|
||||||
|
auto emu = (BuyerRemoveItem_Struct *) in->pBuffer;
|
||||||
|
|
||||||
|
auto outapp = new EQApplicationPacket(OP_BuyerItems, sizeof(structs::BuyerRemoveItem_Struct));
|
||||||
|
auto eq = (structs::BuyerRemoveItem_Struct *) outapp->pBuffer;
|
||||||
|
|
||||||
|
eq->action = structs::RoF2BuyerActions::BuyerModifyBuyLine;
|
||||||
|
eq->slot_id = emu->buy_slot_id;
|
||||||
|
eq->toggle = 0;
|
||||||
|
|
||||||
|
dest->FastQueuePacket(&outapp);
|
||||||
|
safe_delete(in);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Barter_BuyerInspectBegin: {
|
||||||
|
*(uint32 *) in->pBuffer = structs::RoF2BuyerActions::BuyerInspectBegin;
|
||||||
|
dest->FastQueuePacket(&in);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Barter_BuyerInspectEnd: {
|
||||||
|
*(uint32 *) in->pBuffer = structs::RoF2BuyerActions::BuyerInspectEnd;
|
||||||
|
dest->FastQueuePacket(&in);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Barter_SellerBrowsing: {
|
||||||
|
*(uint32 *) in->pBuffer = structs::RoF2BuyerActions::BuyerBrowsingBuyLine;
|
||||||
|
dest->FastQueuePacket(&in);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Barter_BuyerSearchResults: {
|
||||||
|
BuyerItemSearchResults_Struct bisr{};
|
||||||
|
auto emu = (BuyerGeneric_Struct *) in->pBuffer;
|
||||||
|
EQ::Util::MemoryStreamReader ss(
|
||||||
|
reinterpret_cast<char *>(emu->payload),
|
||||||
|
in->size - sizeof(BuyerGeneric_Struct)
|
||||||
|
);
|
||||||
|
cereal::BinaryInputArchive ar(ss);
|
||||||
|
ar(bisr);
|
||||||
|
|
||||||
|
LogTradingDetail("Sending item search results <green>[{}]", bisr.result_count);
|
||||||
|
|
||||||
|
uint32 packet_size = bisr.result_count * sizeof(structs::BuyerItemSearchResultEntry_Struct) + 8;
|
||||||
|
auto outapp = std::make_unique<EQApplicationPacket>(OP_Barter, packet_size);
|
||||||
|
auto eq = (char *) outapp->pBuffer;
|
||||||
|
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, structs::RoF2BuyerActions::BuyerSearchResults);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, bisr.result_count);
|
||||||
|
for (auto const &i: bisr.results) {
|
||||||
|
strn0cpy(eq, i.item_name, 64);
|
||||||
|
eq += 64;
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, i.item_id);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, i.item_icon);
|
||||||
|
VARSTRUCT_SKIP_TYPE(uint32, eq);
|
||||||
|
}
|
||||||
|
dest->QueuePacket(outapp.get());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
LogTradingDetail("Unhandled action <red>[{}]", sub_action);
|
||||||
|
dest->FastQueuePacket(&in);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *__emu_buffer = in->pBuffer;
|
|
||||||
|
|
||||||
in->size = 80;
|
|
||||||
|
|
||||||
in->pBuffer = new unsigned char[in->size];
|
|
||||||
|
|
||||||
char *OutBuffer = (char *)in->pBuffer;
|
|
||||||
|
|
||||||
char Name[64];
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, SubAction);
|
|
||||||
uint32 EntityID = VARSTRUCT_DECODE_TYPE(uint32, Buffer);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, EntityID);
|
|
||||||
uint8 Toggle = VARSTRUCT_DECODE_TYPE(uint8, Buffer);
|
|
||||||
VARSTRUCT_DECODE_STRING(Name, Buffer);
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, Name);
|
|
||||||
OutBuffer = (char *)in->pBuffer + 72;
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, Toggle);
|
|
||||||
|
|
||||||
delete[] __emu_buffer;
|
|
||||||
dest->FastQueuePacket(&in, ack_req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_BazaarSearch)
|
ENCODE(OP_BazaarSearch)
|
||||||
@@ -542,8 +592,8 @@ namespace RoF2
|
|||||||
LogTrading(
|
LogTrading(
|
||||||
"(RoF2) AddTraderToBazaarWindow action <green>[{}] trader_id <green>[{}] entity_id <green>[{}] zone_id <green>[{}]",
|
"(RoF2) AddTraderToBazaarWindow action <green>[{}] trader_id <green>[{}] entity_id <green>[{}] zone_id <green>[{}]",
|
||||||
eq->action,
|
eq->action,
|
||||||
eq->entity_id,
|
|
||||||
eq->trader_id,
|
eq->trader_id,
|
||||||
|
eq->entity_id,
|
||||||
eq->zone_id
|
eq->zone_id
|
||||||
);
|
);
|
||||||
dest->FastQueuePacket(&outapp);
|
dest->FastQueuePacket(&outapp);
|
||||||
@@ -682,6 +732,243 @@ namespace RoF2
|
|||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_BuyerItems)
|
||||||
|
{
|
||||||
|
EQApplicationPacket *inapp = *p;
|
||||||
|
*p = nullptr;
|
||||||
|
|
||||||
|
auto action = *(uint32 *) inapp->pBuffer;
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case Barter_BuyerItemUpdate: {
|
||||||
|
BuyerLineItems_Struct bl{};
|
||||||
|
auto emu = (BuyerGeneric_Struct *) inapp->pBuffer;
|
||||||
|
EQ::Util::MemoryStreamReader ss(
|
||||||
|
reinterpret_cast<char *>(emu->payload),
|
||||||
|
inapp->size - sizeof(BuyerGeneric_Struct)
|
||||||
|
);
|
||||||
|
cereal::BinaryInputArchive ar(ss);
|
||||||
|
ar(bl);
|
||||||
|
|
||||||
|
//packet size
|
||||||
|
auto packet_size = bl.item_name.length() + 1 + 34;
|
||||||
|
for (auto const &b: bl.trade_items) {
|
||||||
|
packet_size += b.item_name.length() + 1;
|
||||||
|
packet_size += 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto outapp = std::make_unique<EQApplicationPacket>(OP_BuyerItems, packet_size);
|
||||||
|
char *eq = (char *) outapp->pBuffer;
|
||||||
|
auto no_trade_items = bl.trade_items.size();
|
||||||
|
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, structs::RoF2BuyerActions::BuyerModifyBuyLine);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, 0);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, bl.slot);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint8, eq, bl.enabled ? 1 : 0);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, bl.item_id);
|
||||||
|
VARSTRUCT_ENCODE_STRING(eq, bl.item_name.c_str());
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, bl.item_icon);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, bl.item_quantity);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint8, eq, bl.item_toggle ? 1 : 0);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, bl.item_cost);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, no_trade_items);
|
||||||
|
|
||||||
|
for (int i = 0; i < no_trade_items; i++) {
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, bl.trade_items[i].item_id);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, bl.trade_items[i].item_quantity);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, bl.trade_items[i].item_icon);
|
||||||
|
VARSTRUCT_ENCODE_STRING(eq, bl.trade_items[i].item_name.c_str());
|
||||||
|
}
|
||||||
|
dest->QueuePacket(outapp.get());
|
||||||
|
safe_delete(inapp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Barter_BuyerInspectBegin: {
|
||||||
|
auto emu = (BuyerGeneric_Struct *) inapp->pBuffer;
|
||||||
|
|
||||||
|
BuyerLineItems_Struct bli{};
|
||||||
|
EQ::Util::MemoryStreamReader ss(
|
||||||
|
reinterpret_cast<char *>(emu->payload),
|
||||||
|
inapp->size - sizeof(BuyerGeneric_Struct)
|
||||||
|
);
|
||||||
|
cereal::BinaryInputArchive ar(ss);
|
||||||
|
ar(bli);
|
||||||
|
|
||||||
|
//packet size
|
||||||
|
auto packet_size = bli.item_name.length() + 1 + 34;
|
||||||
|
for (auto const &b: bli.trade_items) {
|
||||||
|
packet_size += b.item_name.length() + 1;
|
||||||
|
packet_size += 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto packet = std::make_unique<EQApplicationPacket>(OP_BuyerItems, packet_size);
|
||||||
|
char *eq = (char *) packet->pBuffer;
|
||||||
|
auto no_trade_items = bli.trade_items.size();
|
||||||
|
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, structs::RoF2BuyerActions::BuyerSendBuyLine);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, bli.slot);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, bli.slot);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint8, eq, bli.enabled ? 1 : 0);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, bli.item_id);
|
||||||
|
VARSTRUCT_ENCODE_STRING(eq, bli.item_name.c_str());
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, bli.item_icon);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, bli.item_quantity);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint8, eq, bli.item_toggle ? 1 : 0);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, bli.item_cost);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, no_trade_items);
|
||||||
|
|
||||||
|
for (auto const &i: bli.trade_items) {
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, i.item_id);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, i.item_quantity);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, i.item_icon);
|
||||||
|
VARSTRUCT_ENCODE_STRING(eq, i.item_name.c_str());
|
||||||
|
}
|
||||||
|
dest->QueuePacket(packet.get());
|
||||||
|
safe_delete(inapp);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Barter_BuyerSearch: {
|
||||||
|
BuyerLineSearch_Struct bls{};
|
||||||
|
auto emu = (BuyerGeneric_Struct *) inapp->pBuffer;
|
||||||
|
EQ::Util::MemoryStreamReader ss(
|
||||||
|
reinterpret_cast<char *>(emu->payload),
|
||||||
|
inapp->size - sizeof(BuyerGeneric_Struct)
|
||||||
|
);
|
||||||
|
cereal::BinaryInputArchive ar(ss);
|
||||||
|
ar(bls);
|
||||||
|
LogTrading("(RoF2) Barter_BuyerSearch action <green>[{}]", emu->action);
|
||||||
|
|
||||||
|
//Calculate size of packet
|
||||||
|
auto p_size = 0;
|
||||||
|
p_size += 5 * sizeof(uint32) + 1 * sizeof(uint8);
|
||||||
|
p_size += bls.search_string.length() + 1;
|
||||||
|
for (auto const &b: bls.buy_line) {
|
||||||
|
p_size += 6 * sizeof(uint32) + 2 * sizeof(uint8);
|
||||||
|
p_size += strlen(b.item_name) + 1;
|
||||||
|
p_size += b.buyer_name.length() + 1;
|
||||||
|
for (auto const &d: b.trade_items) {
|
||||||
|
if (d.item_id != 0) {
|
||||||
|
p_size += d.item_name.length() + 1;
|
||||||
|
p_size += 3 * sizeof(uint32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p_size += 3 * sizeof(uint32);
|
||||||
|
}
|
||||||
|
|
||||||
|
BuyerBuyLines_Struct bl{};
|
||||||
|
auto outapp = std::make_unique<EQApplicationPacket>(OP_BuyerItems, p_size);
|
||||||
|
auto eq = (char *) outapp->pBuffer;
|
||||||
|
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, 1);
|
||||||
|
VARSTRUCT_ENCODE_STRING(eq, bls.search_string.c_str());
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, bls.transaction_id);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, 0);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, 0);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint8, eq, 1);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, bls.no_items);
|
||||||
|
for (auto const &b: bls.buy_line) {
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, b.slot);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint8, eq, 1);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, b.item_id);
|
||||||
|
VARSTRUCT_ENCODE_STRING(eq, b.item_name);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, b.item_icon);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, b.item_quantity);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint8, eq, 1);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, b.item_cost);
|
||||||
|
auto no_sub_items = b.trade_items.size();
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, no_sub_items);
|
||||||
|
for (auto const &i: b.trade_items) {
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, i.item_id);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, i.item_quantity);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, i.item_icon);
|
||||||
|
VARSTRUCT_ENCODE_STRING(eq, i.item_name.c_str());
|
||||||
|
}
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, b.buyer_entity_id);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, b.buyer_id);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint16, eq, b.buyer_zone_id);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint16, eq, b.buyer_zone_instance_id);
|
||||||
|
VARSTRUCT_ENCODE_STRING(eq, b.buyer_name.c_str());
|
||||||
|
}
|
||||||
|
dest->QueuePacket(outapp.get());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Barter_RemoveFromMerchantWindow: {
|
||||||
|
auto emu = (BuyerRemoveItemFromMerchantWindow_Struct *) inapp->pBuffer;
|
||||||
|
|
||||||
|
emu->action = structs::RoF2BuyerActions::BuyerSendBuyLine;
|
||||||
|
dest->FastQueuePacket(&inapp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Barter_BuyerTransactionComplete:
|
||||||
|
case Barter_SellerTransactionComplete: {
|
||||||
|
BuyerLineSellItem_Struct blsi{};
|
||||||
|
auto emu = (BuyerGeneric_Struct *) inapp->pBuffer;
|
||||||
|
EQ::Util::MemoryStreamReader ss(
|
||||||
|
reinterpret_cast<char *>(emu->payload),
|
||||||
|
inapp->size - sizeof(BuyerGeneric_Struct)
|
||||||
|
);
|
||||||
|
cereal::BinaryInputArchive ar(ss);
|
||||||
|
ar(blsi);
|
||||||
|
|
||||||
|
//packet size
|
||||||
|
auto packet_size = strlen(blsi.item_name) * 2 + 2 + 48 + 30 + blsi.seller_name.length() + 1 +
|
||||||
|
blsi.buyer_name.length() + 1;
|
||||||
|
for (auto const &b: blsi.trade_items) {
|
||||||
|
packet_size += b.item_name.length() + 1;
|
||||||
|
packet_size += 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto outapp = std::make_unique<EQApplicationPacket>(OP_BuyerItems, packet_size);
|
||||||
|
auto eq = (char *) outapp->pBuffer;
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case Barter_BuyerTransactionComplete: {
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, structs::RoF2BuyerActions::BuyerBuyItem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Barter_SellerTransactionComplete: {
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, structs::RoF2BuyerActions::BuyerSellItem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, blsi.sub_action);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, blsi.error_code);
|
||||||
|
eq += 16;
|
||||||
|
VARSTRUCT_ENCODE_STRING(eq, blsi.buyer_name.c_str());
|
||||||
|
VARSTRUCT_ENCODE_STRING(eq, blsi.item_name);
|
||||||
|
VARSTRUCT_ENCODE_STRING(eq, blsi.seller_name.c_str());
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, 0xFFFFFFFF);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, 0xFFFFFFFF);
|
||||||
|
eq += 1;
|
||||||
|
VARSTRUCT_ENCODE_STRING(eq, blsi.item_name);
|
||||||
|
eq += 9;
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, blsi.item_cost);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, blsi.trade_items.size());
|
||||||
|
|
||||||
|
for (auto const &i: blsi.trade_items) {
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, 0);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, i.item_quantity);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, 0);
|
||||||
|
VARSTRUCT_ENCODE_STRING(eq, i.item_name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, 0);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, 0);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, 0);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, 0xFFFFFF);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, 0);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, eq, blsi.seller_quantity);
|
||||||
|
|
||||||
|
dest->QueuePacket(outapp.get());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
dest->FastQueuePacket(&inapp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ENCODE(OP_CancelTrade)
|
ENCODE(OP_CancelTrade)
|
||||||
{
|
{
|
||||||
ENCODE_LENGTH_EXACT(CancelTrade_Struct);
|
ENCODE_LENGTH_EXACT(CancelTrade_Struct);
|
||||||
@@ -2393,7 +2680,7 @@ namespace RoF2
|
|||||||
{
|
{
|
||||||
float instrument_mod = 0.0f;
|
float instrument_mod = 0.0f;
|
||||||
uint8 effect_type = emu->buffs[r].effect_type;
|
uint8 effect_type = emu->buffs[r].effect_type;
|
||||||
uint32 player_id = emu->buffs[r].player_id;;
|
uint32 player_id = emu->buffs[r].player_id;
|
||||||
|
|
||||||
if (emu->buffs[r].spellid != 0xFFFF && emu->buffs[r].spellid != 0)
|
if (emu->buffs[r].spellid != 0xFFFF && emu->buffs[r].spellid != 0)
|
||||||
{
|
{
|
||||||
@@ -4348,6 +4635,9 @@ namespace RoF2
|
|||||||
if (emu->DestructibleObject) {
|
if (emu->DestructibleObject) {
|
||||||
OtherData = OtherData | 0xe1; // Live has 0xe1 for OtherData
|
OtherData = OtherData | 0xe1; // Live has 0xe1 for OtherData
|
||||||
}
|
}
|
||||||
|
if (emu->buyer) {
|
||||||
|
OtherData = OtherData | 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData);
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData);
|
||||||
// float EmitterScalingRadius
|
// float EmitterScalingRadius
|
||||||
@@ -4664,6 +4954,66 @@ namespace RoF2
|
|||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECODE(OP_Barter)
|
||||||
|
{
|
||||||
|
auto action = *(uint32 *) __packet->pBuffer;
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case structs::RoF2BuyerActions::BuyerRemoveItem: {
|
||||||
|
auto emu = (BuyerGeneric_Struct *) __packet->pBuffer;
|
||||||
|
emu->action = Barter_BuyerItemRemove;
|
||||||
|
LogTradingDetail("(RoF2) Buyer Remove Item");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case structs::RoF2BuyerActions::BuyerInspectBegin: {
|
||||||
|
LogTradingDetail("(RoF2) Buyer Inspect Begin Item");
|
||||||
|
|
||||||
|
auto emu = (BuyerGeneric_Struct *) __packet->pBuffer;
|
||||||
|
emu->action = Barter_BuyerInspectBegin;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case structs::RoF2BuyerActions::BuyerInspectEnd: {
|
||||||
|
LogTradingDetail("(RoF2) Buyer Inspect End Item ");
|
||||||
|
|
||||||
|
auto emu = (BuyerGeneric_Struct *) __packet->pBuffer;
|
||||||
|
emu->action = Barter_BuyerInspectEnd;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case structs::RoF2BuyerActions::BuyerWelcomeMessage: {
|
||||||
|
LogTradingDetail("(RoF2) Buyer Welcome Message Update");
|
||||||
|
SETUP_DIRECT_DECODE(BuyerWelcomeMessageUpdate_Struct, structs::BuyerWelcomeMessageUpdate_Struct);
|
||||||
|
|
||||||
|
emu->action = Barter_WelcomeMessageUpdate;
|
||||||
|
strn0cpy(emu->welcome_message, eq->welcome_message, sizeof(emu->welcome_message));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case structs::RoF2BuyerActions::BuyerItemInspect: {
|
||||||
|
SETUP_DIRECT_DECODE(BarterItemSearchLinkRequest_Struct, structs::BarterItemSearchLinkRequest_Struct);
|
||||||
|
LogTradingDetail("(RoF2) Seller ID <green>[{}] Inspecting Item <green>[{}] from Buyer ID <green>[{}] ",
|
||||||
|
eq->seller_id,
|
||||||
|
eq->item_id,
|
||||||
|
eq->buyer_id
|
||||||
|
);
|
||||||
|
|
||||||
|
emu->action = Barter_BarterItemInspect;
|
||||||
|
emu->item_id = eq->item_id;
|
||||||
|
emu->searcher_id = eq->seller_id;
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
auto emu = (BuyerGeneric_Struct *) __packet->pBuffer;
|
||||||
|
LogTradingDetail("(RoF2) Pass thru OP_Barter packet action <red>[{}]", emu->action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DECODE(OP_BazaarSearch)
|
DECODE(OP_BazaarSearch)
|
||||||
{
|
{
|
||||||
char *Buffer = (char *)__packet->pBuffer;
|
char *Buffer = (char *)__packet->pBuffer;
|
||||||
@@ -4742,6 +5092,147 @@ namespace RoF2
|
|||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECODE(OP_BuyerItems)
|
||||||
|
{
|
||||||
|
auto action = *(uint32 *) __packet->pBuffer;
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case structs::RoF2BuyerActions::BuyerModifyBuyLine:
|
||||||
|
case structs::RoF2BuyerActions::BuyerBuyLine: {
|
||||||
|
BuyerBuyLines_Struct buyer_buy_lines{};
|
||||||
|
auto buffer = (char *) __packet->pBuffer;
|
||||||
|
|
||||||
|
buyer_buy_lines.action = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
|
||||||
|
buyer_buy_lines.no_items = 1;
|
||||||
|
if (action == structs::RoF2BuyerActions::BuyerBuyLine) {
|
||||||
|
buyer_buy_lines.no_items = VARSTRUCT_DECODE_TYPE(uint16, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
buyer_buy_lines.buy_lines.reserve(buyer_buy_lines.no_items);
|
||||||
|
for (int i = 0; i < buyer_buy_lines.no_items; i++) {
|
||||||
|
BuyerLineItems_Struct b{};
|
||||||
|
b.slot = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
b.enabled = VARSTRUCT_DECODE_TYPE(uint8, buffer);
|
||||||
|
b.item_id = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
b.item_name = std::string(buffer, strlen(buffer));
|
||||||
|
buffer += strlen(buffer) + 1;
|
||||||
|
b.item_icon = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
b.item_quantity = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
b.item_toggle = VARSTRUCT_DECODE_TYPE(uint8, buffer);
|
||||||
|
b.item_cost = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
auto trade_items = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
buyer_buy_lines.buy_lines.push_back(b);
|
||||||
|
|
||||||
|
if (trade_items > 0) {
|
||||||
|
buyer_buy_lines.buy_lines[i].trade_items.reserve(trade_items);
|
||||||
|
for (int x = 0; x < trade_items; x++) {
|
||||||
|
BuyerLineTradeItems_Struct blti{};
|
||||||
|
blti.item_id = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
blti.item_quantity = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
blti.item_icon = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
blti.item_name = std::string(buffer, strlen(buffer));
|
||||||
|
buffer += strlen(buffer) + 1;
|
||||||
|
buyer_buy_lines.buy_lines[i].trade_items.push_back(blti);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer += 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = nullptr;
|
||||||
|
std::stringstream ss{};
|
||||||
|
cereal::BinaryOutputArchive ar(ss);
|
||||||
|
{
|
||||||
|
ar(buyer_buy_lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto new_size = sizeof(BuyerGeneric_Struct) + ss.str().length();
|
||||||
|
auto new_packet = new unsigned char[new_size];
|
||||||
|
__packet->size = new_size;
|
||||||
|
__packet->pBuffer = new_packet;
|
||||||
|
auto emu = (BuyerGeneric_Struct *) __packet->pBuffer;
|
||||||
|
emu->action = Barter_BuyerItemUpdate;
|
||||||
|
|
||||||
|
if (action == structs::RoF2BuyerActions::BuyerBuyLine) {
|
||||||
|
emu->action = Barter_BuyerItemStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(emu->payload, ss.str().data(), ss.str().length());
|
||||||
|
__packet->SetOpcode(OP_Barter);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case structs::RoF2BuyerActions::BuyerSellItem: {
|
||||||
|
BuyerLineSellItem_Struct sell_item{};
|
||||||
|
|
||||||
|
char *buffer = (char *) __packet->pBuffer;
|
||||||
|
|
||||||
|
sell_item.action = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
sell_item.purchase_method = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
buffer += 4;
|
||||||
|
sell_item.buyer_entity_id = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
sell_item.buyer_id = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
buffer += 11;
|
||||||
|
sell_item.slot = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
sell_item.enabled = VARSTRUCT_DECODE_TYPE(uint8, buffer);
|
||||||
|
sell_item.item_id = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
VARSTRUCT_DECODE_STRING(sell_item.item_name, buffer);
|
||||||
|
sell_item.item_icon = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
sell_item.item_quantity = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
sell_item.item_toggle = VARSTRUCT_DECODE_TYPE(uint8, buffer);
|
||||||
|
sell_item.item_cost = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
sell_item.no_trade_items = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
|
||||||
|
if (sell_item.no_trade_items > 0) {
|
||||||
|
sell_item.trade_items.reserve(sell_item.no_trade_items);
|
||||||
|
for (int x = 0; x < sell_item.no_trade_items; x++) {
|
||||||
|
BuyerLineTradeItems_Struct blti{};
|
||||||
|
blti.item_id = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
blti.item_quantity = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
blti.item_icon = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
blti.item_name = std::string(buffer, strlen(buffer));
|
||||||
|
buffer += strlen(buffer) + 1;
|
||||||
|
sell_item.trade_items.push_back(blti);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sell_item.purchase_method) {
|
||||||
|
sell_item.buyer_entity_id = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
sell_item.buyer_id = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
sell_item.zone_id = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
sell_item.buyer_name = std::string(buffer, strlen(buffer));
|
||||||
|
buffer += sell_item.buyer_name.length() + 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buffer += 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
sell_item.seller_quantity = VARSTRUCT_DECODE_TYPE(uint32, buffer);
|
||||||
|
|
||||||
|
buffer += 4;
|
||||||
|
|
||||||
|
buffer = nullptr;
|
||||||
|
std::stringstream ss{};
|
||||||
|
cereal::BinaryOutputArchive ar(ss);
|
||||||
|
{
|
||||||
|
ar(sell_item);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto new_size = sizeof(BuyerGeneric_Struct) + ss.str().length();
|
||||||
|
auto new_packet = new unsigned char[new_size];
|
||||||
|
__packet->size = new_size;
|
||||||
|
__packet->pBuffer = new_packet;
|
||||||
|
auto emu = (BuyerGeneric_Struct *) __packet->pBuffer;
|
||||||
|
emu->action = Barter_SellItem;
|
||||||
|
|
||||||
|
memcpy(emu->payload, ss.str().data(), ss.str().length());
|
||||||
|
__packet->SetOpcode(OP_Barter);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DECODE(OP_CastSpell)
|
DECODE(OP_CastSpell)
|
||||||
{
|
{
|
||||||
DECODE_LENGTH_EXACT(structs::CastSpell_Struct);
|
DECODE_LENGTH_EXACT(structs::CastSpell_Struct);
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ E(OP_BeginCast)
|
|||||||
E(OP_BlockedBuffs)
|
E(OP_BlockedBuffs)
|
||||||
E(OP_Buff)
|
E(OP_Buff)
|
||||||
E(OP_BuffCreate)
|
E(OP_BuffCreate)
|
||||||
|
E(OP_BuyerItems)
|
||||||
E(OP_CancelTrade)
|
E(OP_CancelTrade)
|
||||||
E(OP_CastSpell)
|
E(OP_CastSpell)
|
||||||
E(OP_ChannelMessage)
|
E(OP_ChannelMessage)
|
||||||
@@ -149,11 +150,13 @@ D(OP_Animation)
|
|||||||
D(OP_ApplyPoison)
|
D(OP_ApplyPoison)
|
||||||
D(OP_AugmentInfo)
|
D(OP_AugmentInfo)
|
||||||
D(OP_AugmentItem)
|
D(OP_AugmentItem)
|
||||||
|
D(OP_Barter)
|
||||||
D(OP_BazaarSearch)
|
D(OP_BazaarSearch)
|
||||||
D(OP_BlockedBuffs)
|
D(OP_BlockedBuffs)
|
||||||
D(OP_BookButton)
|
D(OP_BookButton)
|
||||||
D(OP_Buff)
|
D(OP_Buff)
|
||||||
D(OP_BuffRemoveRequest)
|
D(OP_BuffRemoveRequest)
|
||||||
|
D(OP_BuyerItems)
|
||||||
D(OP_CastSpell)
|
D(OP_CastSpell)
|
||||||
D(OP_ChannelMessage)
|
D(OP_ChannelMessage)
|
||||||
D(OP_CharacterCreate)
|
D(OP_CharacterCreate)
|
||||||
|
|||||||
+142
-22
@@ -354,15 +354,15 @@ struct Spawn_Struct_Bitfields
|
|||||||
/*29*/ unsigned showname:1;
|
/*29*/ unsigned showname:1;
|
||||||
/*30*/ unsigned idleanimationsoff:1; // what we called statue?
|
/*30*/ unsigned idleanimationsoff:1; // what we called statue?
|
||||||
/*31*/ unsigned untargetable:1; // bClickThrough
|
/*31*/ unsigned untargetable:1; // bClickThrough
|
||||||
/* do these later
|
// byte 5
|
||||||
32 unsigned buyer:1;
|
/*32 unsigned buyer:1;
|
||||||
33 unsigned offline:1;
|
/*33 unsigned offline:1;
|
||||||
34 unsigned interactiveobject:1;
|
/*34 unsigned interactiveobject:1;
|
||||||
35 unsigned flung:1; // hmm this vfunc appears to do stuff with leve and flung variables
|
/*35 unsigned flung:1; // hmm this vfunc appears to do stuff with leve and flung variables
|
||||||
36 unsigned title:1;
|
/*36 unsigned title:1;
|
||||||
37 unsigned suffix:1;
|
/*37 unsigned suffix:1;
|
||||||
38 unsigned padding1:1;
|
/*38 unsigned padding1:1;
|
||||||
39 unsigned padding2:1;
|
/*39 unsigned padding2:1;
|
||||||
40 unsinged padding3:1;
|
40 unsinged padding3:1;
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
@@ -3107,19 +3107,139 @@ struct EnvDamage2_Struct {
|
|||||||
|
|
||||||
//Bazaar Stuff
|
//Bazaar Stuff
|
||||||
enum RoF2BazaarTraderBuyerActions {
|
enum RoF2BazaarTraderBuyerActions {
|
||||||
Zero = 0,
|
Zero = 0,
|
||||||
BeginTraderMode = 1,
|
BeginTraderMode = 1,
|
||||||
EndTraderMode = 2,
|
EndTraderMode = 2,
|
||||||
PriceUpdate = 3,
|
PriceUpdate = 3,
|
||||||
EndTransaction = 4,
|
EndTransaction = 4,
|
||||||
BazaarSearch = 7,
|
BazaarSearch = 7,
|
||||||
WelcomeMessage = 9,
|
WelcomeMessage = 9,
|
||||||
BuyTraderItem = 10,
|
BuyTraderItem = 10,
|
||||||
ListTraderItems = 11,
|
ListTraderItems = 11,
|
||||||
BazaarInspect = 18,
|
BazaarInspect = 18,
|
||||||
ClickTrader = 28,
|
ClickTrader = 28,
|
||||||
ItemMove = 19,
|
ItemMove = 19,
|
||||||
ReconcileItems = 20
|
ReconcileItems = 20
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RoF2BuyerActions {
|
||||||
|
BuyerSearchResults = 0x00,
|
||||||
|
BuyerBuyLine = 0x06,
|
||||||
|
BuyerModifyBuyLine = 0x07,
|
||||||
|
BuyerRemoveItem = 0x08,
|
||||||
|
BuyerSellItem = 0x09,
|
||||||
|
BuyerBuyItem = 0x0a,
|
||||||
|
BuyerInspectBegin = 0x0b,
|
||||||
|
BuyerInspectEnd = 0x0c,
|
||||||
|
BuyerAppearance = 0x0d,
|
||||||
|
BuyerSendBuyLine = 0x0e,
|
||||||
|
BuyerItemInspect = 0x0f,
|
||||||
|
BuyerBrowsingBuyLine = 0x10,
|
||||||
|
BarterWelcomeMessage = 0x11,
|
||||||
|
BuyerWelcomeMessage = 0x13,
|
||||||
|
BuyerGreeting = 0x14,
|
||||||
|
BuyerInventoryFull = 0x16
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BarterItemSearchLinkRequest_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 unknown_004;
|
||||||
|
uint32 seller_id;
|
||||||
|
uint32 buyer_id;
|
||||||
|
uint32 unknown_016;
|
||||||
|
uint32 slot_id; // 0xffffffff main buy line 0x0 trade_item_1, 0x1 trade_item_2
|
||||||
|
uint32 item_id;
|
||||||
|
uint32 unknown_028;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerWelcomeMessageUpdate_Struct {
|
||||||
|
uint32 action;
|
||||||
|
char unknown_004[64];
|
||||||
|
uint32 unknown_068;
|
||||||
|
char welcome_message[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Buyer_SetAppearance_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 entity_id;
|
||||||
|
char unknown[64];
|
||||||
|
uint32 enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerRemoveItem_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 unknown004;
|
||||||
|
uint32 slot_id;
|
||||||
|
uint32 toggle;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerLineSellItem_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 purchase_method; // 0 direct merchant, 1 via /barter window
|
||||||
|
uint32 unknown008;
|
||||||
|
uint32 buyer_entity_id;
|
||||||
|
uint32 seller_entity_id;
|
||||||
|
char unknown[15];
|
||||||
|
uint32 slot;
|
||||||
|
uint8 enabled;
|
||||||
|
uint32 item_id;
|
||||||
|
char item_name[64];
|
||||||
|
uint32 item_icon;
|
||||||
|
uint32 item_quantity;
|
||||||
|
uint8 item_toggle;
|
||||||
|
uint32 item_cost;
|
||||||
|
uint32 no_trade_items;
|
||||||
|
BuyerLineTradeItems_Struct trade_items[10];
|
||||||
|
char unknown2[13];
|
||||||
|
uint32 seller_quantity;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerLineItemsSearch_Struct {
|
||||||
|
uint32 slot;
|
||||||
|
uint8 enabled;
|
||||||
|
uint32 item_id;
|
||||||
|
char item_name[64];
|
||||||
|
uint32 item_icon;
|
||||||
|
uint32 item_quantity;
|
||||||
|
uint8 item_toggle;
|
||||||
|
uint32 item_cost;
|
||||||
|
uint32 buyer_id;
|
||||||
|
BuyerLineTradeItems_Struct trade_items[MAX_BUYER_COMPENSATION_ITEMS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerLineSearch_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 no_items;
|
||||||
|
std::vector<BuyerLineItemsSearch_Struct> buy_line;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerStart_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint16 no_buyer_lines;
|
||||||
|
uint32 slot;
|
||||||
|
uint8 enabled;
|
||||||
|
uint32 item_id;
|
||||||
|
char item_name[1]; // vary length
|
||||||
|
uint32 item_icon;
|
||||||
|
uint32 item_quantity;
|
||||||
|
uint8 toggle;
|
||||||
|
uint32 item_cost;
|
||||||
|
uint32 no_trade_items;
|
||||||
|
BuyerLineTradeItems_Struct trade_items[1]; // size is actually no_trade_items. If 0, then this is not in packet
|
||||||
|
char unknown[13];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerItemSearchResultEntry_Struct {
|
||||||
|
char item_name[64];
|
||||||
|
uint32 item_id;
|
||||||
|
uint32 item_icon;
|
||||||
|
uint32 unknown_072;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuyerItemSearchResults_Struct {
|
||||||
|
uint32 action;
|
||||||
|
uint32 result_count;
|
||||||
|
BuyerItemSearchResultEntry_Struct results[];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|||||||
@@ -2349,7 +2349,7 @@ namespace SoF
|
|||||||
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
|
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
|
||||||
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
|
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
|
||||||
|
|
||||||
emu->category_id = EQ::bug::CategoryNameToCategoryID(eq->category_name);
|
emu->category_id = Bug::GetID(eq->category_name);
|
||||||
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
|
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
|
||||||
|
|
||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
|
|||||||
@@ -2567,7 +2567,7 @@ namespace Titanium
|
|||||||
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
|
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
|
||||||
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
|
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
|
||||||
|
|
||||||
emu->category_id = EQ::bug::CategoryNameToCategoryID(eq->category_name);
|
emu->category_id = Bug::GetID(eq->category_name);
|
||||||
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
|
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
|
||||||
|
|
||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public:
|
|||||||
struct BotSpellsEntries {
|
struct BotSpellsEntries {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
int32_t npc_spells_id;
|
int32_t npc_spells_id;
|
||||||
int16_t spellid;
|
uint16_t spell_id;
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
uint8_t minlevel;
|
uint8_t minlevel;
|
||||||
uint8_t maxlevel;
|
uint8_t maxlevel;
|
||||||
@@ -46,7 +46,7 @@ public:
|
|||||||
return {
|
return {
|
||||||
"id",
|
"id",
|
||||||
"npc_spells_id",
|
"npc_spells_id",
|
||||||
"spellid",
|
"spell_id",
|
||||||
"type",
|
"type",
|
||||||
"minlevel",
|
"minlevel",
|
||||||
"maxlevel",
|
"maxlevel",
|
||||||
@@ -67,7 +67,7 @@ public:
|
|||||||
return {
|
return {
|
||||||
"id",
|
"id",
|
||||||
"npc_spells_id",
|
"npc_spells_id",
|
||||||
"spellid",
|
"spell_id",
|
||||||
"type",
|
"type",
|
||||||
"minlevel",
|
"minlevel",
|
||||||
"maxlevel",
|
"maxlevel",
|
||||||
@@ -122,7 +122,7 @@ public:
|
|||||||
|
|
||||||
e.id = 0;
|
e.id = 0;
|
||||||
e.npc_spells_id = 0;
|
e.npc_spells_id = 0;
|
||||||
e.spellid = 0;
|
e.spell_id = 0;
|
||||||
e.type = 0;
|
e.type = 0;
|
||||||
e.minlevel = 0;
|
e.minlevel = 0;
|
||||||
e.maxlevel = 255;
|
e.maxlevel = 255;
|
||||||
@@ -173,7 +173,7 @@ public:
|
|||||||
|
|
||||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||||
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
||||||
e.spellid = row[2] ? static_cast<int16_t>(atoi(row[2])) : 0;
|
e.spell_id = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||||
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||||
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||||
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
|
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
|
||||||
@@ -220,7 +220,7 @@ public:
|
|||||||
auto columns = Columns();
|
auto columns = Columns();
|
||||||
|
|
||||||
v.push_back(columns[1] + " = " + std::to_string(e.npc_spells_id));
|
v.push_back(columns[1] + " = " + std::to_string(e.npc_spells_id));
|
||||||
v.push_back(columns[2] + " = " + std::to_string(e.spellid));
|
v.push_back(columns[2] + " = " + std::to_string(e.spell_id));
|
||||||
v.push_back(columns[3] + " = " + std::to_string(e.type));
|
v.push_back(columns[3] + " = " + std::to_string(e.type));
|
||||||
v.push_back(columns[4] + " = " + std::to_string(e.minlevel));
|
v.push_back(columns[4] + " = " + std::to_string(e.minlevel));
|
||||||
v.push_back(columns[5] + " = " + std::to_string(e.maxlevel));
|
v.push_back(columns[5] + " = " + std::to_string(e.maxlevel));
|
||||||
@@ -256,7 +256,7 @@ public:
|
|||||||
|
|
||||||
v.push_back(std::to_string(e.id));
|
v.push_back(std::to_string(e.id));
|
||||||
v.push_back(std::to_string(e.npc_spells_id));
|
v.push_back(std::to_string(e.npc_spells_id));
|
||||||
v.push_back(std::to_string(e.spellid));
|
v.push_back(std::to_string(e.spell_id));
|
||||||
v.push_back(std::to_string(e.type));
|
v.push_back(std::to_string(e.type));
|
||||||
v.push_back(std::to_string(e.minlevel));
|
v.push_back(std::to_string(e.minlevel));
|
||||||
v.push_back(std::to_string(e.maxlevel));
|
v.push_back(std::to_string(e.maxlevel));
|
||||||
@@ -300,7 +300,7 @@ public:
|
|||||||
|
|
||||||
v.push_back(std::to_string(e.id));
|
v.push_back(std::to_string(e.id));
|
||||||
v.push_back(std::to_string(e.npc_spells_id));
|
v.push_back(std::to_string(e.npc_spells_id));
|
||||||
v.push_back(std::to_string(e.spellid));
|
v.push_back(std::to_string(e.spell_id));
|
||||||
v.push_back(std::to_string(e.type));
|
v.push_back(std::to_string(e.type));
|
||||||
v.push_back(std::to_string(e.minlevel));
|
v.push_back(std::to_string(e.minlevel));
|
||||||
v.push_back(std::to_string(e.maxlevel));
|
v.push_back(std::to_string(e.maxlevel));
|
||||||
@@ -348,7 +348,7 @@ public:
|
|||||||
|
|
||||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||||
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
||||||
e.spellid = row[2] ? static_cast<int16_t>(atoi(row[2])) : 0;
|
e.spell_id = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||||
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||||
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||||
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
|
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
|
||||||
@@ -387,7 +387,7 @@ public:
|
|||||||
|
|
||||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||||
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
||||||
e.spellid = row[2] ? static_cast<int16_t>(atoi(row[2])) : 0;
|
e.spell_id = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||||
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||||
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||||
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
|
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
|
||||||
@@ -476,7 +476,7 @@ public:
|
|||||||
|
|
||||||
v.push_back(std::to_string(e.id));
|
v.push_back(std::to_string(e.id));
|
||||||
v.push_back(std::to_string(e.npc_spells_id));
|
v.push_back(std::to_string(e.npc_spells_id));
|
||||||
v.push_back(std::to_string(e.spellid));
|
v.push_back(std::to_string(e.spell_id));
|
||||||
v.push_back(std::to_string(e.type));
|
v.push_back(std::to_string(e.type));
|
||||||
v.push_back(std::to_string(e.minlevel));
|
v.push_back(std::to_string(e.minlevel));
|
||||||
v.push_back(std::to_string(e.maxlevel));
|
v.push_back(std::to_string(e.maxlevel));
|
||||||
@@ -513,7 +513,7 @@ public:
|
|||||||
|
|
||||||
v.push_back(std::to_string(e.id));
|
v.push_back(std::to_string(e.id));
|
||||||
v.push_back(std::to_string(e.npc_spells_id));
|
v.push_back(std::to_string(e.npc_spells_id));
|
||||||
v.push_back(std::to_string(e.spellid));
|
v.push_back(std::to_string(e.spell_id));
|
||||||
v.push_back(std::to_string(e.type));
|
v.push_back(std::to_string(e.type));
|
||||||
v.push_back(std::to_string(e.minlevel));
|
v.push_back(std::to_string(e.minlevel));
|
||||||
v.push_back(std::to_string(e.maxlevel));
|
v.push_back(std::to_string(e.maxlevel));
|
||||||
|
|||||||
@@ -0,0 +1,475 @@
|
|||||||
|
/**
|
||||||
|
* 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://docs.eqemu.io/developer/repositories
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EQEMU_BASE_BUYER_BUY_LINES_REPOSITORY_H
|
||||||
|
#define EQEMU_BASE_BUYER_BUY_LINES_REPOSITORY_H
|
||||||
|
|
||||||
|
#include "../../database.h"
|
||||||
|
#include "../../strings.h"
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
class BaseBuyerBuyLinesRepository {
|
||||||
|
public:
|
||||||
|
struct BuyerBuyLines {
|
||||||
|
uint64_t id;
|
||||||
|
uint64_t buyer_id;
|
||||||
|
uint32_t char_id;
|
||||||
|
int32_t buy_slot_id;
|
||||||
|
int32_t item_id;
|
||||||
|
int32_t item_qty;
|
||||||
|
int32_t item_price;
|
||||||
|
uint32_t item_icon;
|
||||||
|
std::string item_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::string PrimaryKey()
|
||||||
|
{
|
||||||
|
return std::string("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::string> Columns()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
"id",
|
||||||
|
"buyer_id",
|
||||||
|
"char_id",
|
||||||
|
"buy_slot_id",
|
||||||
|
"item_id",
|
||||||
|
"item_qty",
|
||||||
|
"item_price",
|
||||||
|
"item_icon",
|
||||||
|
"item_name",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::string> SelectColumns()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
"id",
|
||||||
|
"buyer_id",
|
||||||
|
"char_id",
|
||||||
|
"buy_slot_id",
|
||||||
|
"item_id",
|
||||||
|
"item_qty",
|
||||||
|
"item_price",
|
||||||
|
"item_icon",
|
||||||
|
"item_name",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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("buyer_buy_lines");
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string BaseSelect()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"SELECT {} FROM {}",
|
||||||
|
SelectColumnsRaw(),
|
||||||
|
TableName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string BaseInsert()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"INSERT INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BuyerBuyLines NewEntity()
|
||||||
|
{
|
||||||
|
BuyerBuyLines e{};
|
||||||
|
|
||||||
|
e.id = 0;
|
||||||
|
e.buyer_id = 0;
|
||||||
|
e.char_id = 0;
|
||||||
|
e.buy_slot_id = 0;
|
||||||
|
e.item_id = 0;
|
||||||
|
e.item_qty = 0;
|
||||||
|
e.item_price = 0;
|
||||||
|
e.item_icon = 0;
|
||||||
|
e.item_name = "";
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BuyerBuyLines GetBuyerBuyLines(
|
||||||
|
const std::vector<BuyerBuyLines> &buyer_buy_liness,
|
||||||
|
int buyer_buy_lines_id
|
||||||
|
)
|
||||||
|
{
|
||||||
|
for (auto &buyer_buy_lines : buyer_buy_liness) {
|
||||||
|
if (buyer_buy_lines.id == buyer_buy_lines_id) {
|
||||||
|
return buyer_buy_lines;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
static BuyerBuyLines FindOne(
|
||||||
|
Database& db,
|
||||||
|
int buyer_buy_lines_id
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
|
buyer_buy_lines_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
if (results.RowCount() == 1) {
|
||||||
|
BuyerBuyLines e{};
|
||||||
|
|
||||||
|
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
|
||||||
|
e.buyer_id = row[1] ? strtoull(row[1], nullptr, 10) : 0;
|
||||||
|
e.char_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||||
|
e.buy_slot_id = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
|
||||||
|
e.item_id = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
|
||||||
|
e.item_qty = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
|
||||||
|
e.item_price = row[6] ? static_cast<int32_t>(atoi(row[6])) : 0;
|
||||||
|
e.item_icon = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||||
|
e.item_name = row[8] ? row[8] : "";
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int DeleteOne(
|
||||||
|
Database& db,
|
||||||
|
int buyer_buy_lines_id
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"DELETE FROM {} WHERE {} = {}",
|
||||||
|
TableName(),
|
||||||
|
PrimaryKey(),
|
||||||
|
buyer_buy_lines_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int UpdateOne(
|
||||||
|
Database& db,
|
||||||
|
const BuyerBuyLines &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto columns = Columns();
|
||||||
|
|
||||||
|
v.push_back(columns[1] + " = " + std::to_string(e.buyer_id));
|
||||||
|
v.push_back(columns[2] + " = " + std::to_string(e.char_id));
|
||||||
|
v.push_back(columns[3] + " = " + std::to_string(e.buy_slot_id));
|
||||||
|
v.push_back(columns[4] + " = " + std::to_string(e.item_id));
|
||||||
|
v.push_back(columns[5] + " = " + std::to_string(e.item_qty));
|
||||||
|
v.push_back(columns[6] + " = " + std::to_string(e.item_price));
|
||||||
|
v.push_back(columns[7] + " = " + std::to_string(e.item_icon));
|
||||||
|
v.push_back(columns[8] + " = '" + Strings::Escape(e.item_name) + "'");
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"UPDATE {} SET {} WHERE {} = {}",
|
||||||
|
TableName(),
|
||||||
|
Strings::Implode(", ", v),
|
||||||
|
PrimaryKey(),
|
||||||
|
e.id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BuyerBuyLines InsertOne(
|
||||||
|
Database& db,
|
||||||
|
BuyerBuyLines e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.buyer_id));
|
||||||
|
v.push_back(std::to_string(e.char_id));
|
||||||
|
v.push_back(std::to_string(e.buy_slot_id));
|
||||||
|
v.push_back(std::to_string(e.item_id));
|
||||||
|
v.push_back(std::to_string(e.item_qty));
|
||||||
|
v.push_back(std::to_string(e.item_price));
|
||||||
|
v.push_back(std::to_string(e.item_icon));
|
||||||
|
v.push_back("'" + Strings::Escape(e.item_name) + "'");
|
||||||
|
|
||||||
|
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<BuyerBuyLines> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.buyer_id));
|
||||||
|
v.push_back(std::to_string(e.char_id));
|
||||||
|
v.push_back(std::to_string(e.buy_slot_id));
|
||||||
|
v.push_back(std::to_string(e.item_id));
|
||||||
|
v.push_back(std::to_string(e.item_qty));
|
||||||
|
v.push_back(std::to_string(e.item_price));
|
||||||
|
v.push_back(std::to_string(e.item_icon));
|
||||||
|
v.push_back("'" + Strings::Escape(e.item_name) + "'");
|
||||||
|
|
||||||
|
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<BuyerBuyLines> All(Database& db)
|
||||||
|
{
|
||||||
|
std::vector<BuyerBuyLines> all_entries;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{}",
|
||||||
|
BaseSelect()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
all_entries.reserve(results.RowCount());
|
||||||
|
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
BuyerBuyLines e{};
|
||||||
|
|
||||||
|
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
|
||||||
|
e.buyer_id = row[1] ? strtoull(row[1], nullptr, 10) : 0;
|
||||||
|
e.char_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||||
|
e.buy_slot_id = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
|
||||||
|
e.item_id = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
|
||||||
|
e.item_qty = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
|
||||||
|
e.item_price = row[6] ? static_cast<int32_t>(atoi(row[6])) : 0;
|
||||||
|
e.item_icon = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||||
|
e.item_name = row[8] ? row[8] : "";
|
||||||
|
|
||||||
|
all_entries.push_back(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return all_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<BuyerBuyLines> GetWhere(Database& db, const std::string &where_filter)
|
||||||
|
{
|
||||||
|
std::vector<BuyerBuyLines> 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) {
|
||||||
|
BuyerBuyLines e{};
|
||||||
|
|
||||||
|
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
|
||||||
|
e.buyer_id = row[1] ? strtoull(row[1], nullptr, 10) : 0;
|
||||||
|
e.char_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||||
|
e.buy_slot_id = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
|
||||||
|
e.item_id = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
|
||||||
|
e.item_qty = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
|
||||||
|
e.item_price = row[6] ? static_cast<int32_t>(atoi(row[6])) : 0;
|
||||||
|
e.item_icon = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||||
|
e.item_name = row[8] ? row[8] : "";
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const BuyerBuyLines &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.buyer_id));
|
||||||
|
v.push_back(std::to_string(e.char_id));
|
||||||
|
v.push_back(std::to_string(e.buy_slot_id));
|
||||||
|
v.push_back(std::to_string(e.item_id));
|
||||||
|
v.push_back(std::to_string(e.item_qty));
|
||||||
|
v.push_back(std::to_string(e.item_price));
|
||||||
|
v.push_back(std::to_string(e.item_icon));
|
||||||
|
v.push_back("'" + Strings::Escape(e.item_name) + "'");
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<BuyerBuyLines> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.buyer_id));
|
||||||
|
v.push_back(std::to_string(e.char_id));
|
||||||
|
v.push_back(std::to_string(e.buy_slot_id));
|
||||||
|
v.push_back(std::to_string(e.item_id));
|
||||||
|
v.push_back(std::to_string(e.item_qty));
|
||||||
|
v.push_back(std::to_string(e.item_price));
|
||||||
|
v.push_back(std::to_string(e.item_icon));
|
||||||
|
v.push_back("'" + Strings::Escape(e.item_name) + "'");
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //EQEMU_BASE_BUYER_BUY_LINES_REPOSITORY_H
|
||||||
@@ -19,40 +19,46 @@
|
|||||||
class BaseBuyerRepository {
|
class BaseBuyerRepository {
|
||||||
public:
|
public:
|
||||||
struct Buyer {
|
struct Buyer {
|
||||||
int32_t charid;
|
uint64_t id;
|
||||||
int32_t buyslot;
|
uint32_t char_id;
|
||||||
int32_t itemid;
|
uint32_t char_entity_id;
|
||||||
std::string itemname;
|
std::string char_name;
|
||||||
int32_t quantity;
|
uint32_t char_zone_id;
|
||||||
int32_t price;
|
uint32_t char_zone_instance_id;
|
||||||
|
time_t transaction_date;
|
||||||
|
std::string welcome_message;
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::string PrimaryKey()
|
static std::string PrimaryKey()
|
||||||
{
|
{
|
||||||
return std::string("charid");
|
return std::string("id");
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::string> Columns()
|
static std::vector<std::string> Columns()
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
"charid",
|
"id",
|
||||||
"buyslot",
|
"char_id",
|
||||||
"itemid",
|
"char_entity_id",
|
||||||
"itemname",
|
"char_name",
|
||||||
"quantity",
|
"char_zone_id",
|
||||||
"price",
|
"char_zone_instance_id",
|
||||||
|
"transaction_date",
|
||||||
|
"welcome_message",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::string> SelectColumns()
|
static std::vector<std::string> SelectColumns()
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
"charid",
|
"id",
|
||||||
"buyslot",
|
"char_id",
|
||||||
"itemid",
|
"char_entity_id",
|
||||||
"itemname",
|
"char_name",
|
||||||
"quantity",
|
"char_zone_id",
|
||||||
"price",
|
"char_zone_instance_id",
|
||||||
|
"UNIX_TIMESTAMP(transaction_date)",
|
||||||
|
"welcome_message",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,12 +99,14 @@ public:
|
|||||||
{
|
{
|
||||||
Buyer e{};
|
Buyer e{};
|
||||||
|
|
||||||
e.charid = 0;
|
e.id = 0;
|
||||||
e.buyslot = 0;
|
e.char_id = 0;
|
||||||
e.itemid = 0;
|
e.char_entity_id = 0;
|
||||||
e.itemname = "";
|
e.char_name = "";
|
||||||
e.quantity = 0;
|
e.char_zone_id = 0;
|
||||||
e.price = 0;
|
e.char_zone_instance_id = 0;
|
||||||
|
e.transaction_date = 0;
|
||||||
|
e.welcome_message = "";
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -109,7 +117,7 @@ public:
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
for (auto &buyer : buyers) {
|
for (auto &buyer : buyers) {
|
||||||
if (buyer.charid == buyer_id) {
|
if (buyer.id == buyer_id) {
|
||||||
return buyer;
|
return buyer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,12 +143,14 @@ public:
|
|||||||
if (results.RowCount() == 1) {
|
if (results.RowCount() == 1) {
|
||||||
Buyer e{};
|
Buyer e{};
|
||||||
|
|
||||||
e.charid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
|
||||||
e.buyslot = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||||
e.itemid = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
|
e.char_entity_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||||
e.itemname = row[3] ? row[3] : "";
|
e.char_name = row[3] ? row[3] : "";
|
||||||
e.quantity = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
|
e.char_zone_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||||
e.price = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
|
e.char_zone_instance_id = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||||
|
e.transaction_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10);
|
||||||
|
e.welcome_message = row[7] ? row[7] : "";
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -174,12 +184,13 @@ public:
|
|||||||
|
|
||||||
auto columns = Columns();
|
auto columns = Columns();
|
||||||
|
|
||||||
v.push_back(columns[0] + " = " + std::to_string(e.charid));
|
v.push_back(columns[1] + " = " + std::to_string(e.char_id));
|
||||||
v.push_back(columns[1] + " = " + std::to_string(e.buyslot));
|
v.push_back(columns[2] + " = " + std::to_string(e.char_entity_id));
|
||||||
v.push_back(columns[2] + " = " + std::to_string(e.itemid));
|
v.push_back(columns[3] + " = '" + Strings::Escape(e.char_name) + "'");
|
||||||
v.push_back(columns[3] + " = '" + Strings::Escape(e.itemname) + "'");
|
v.push_back(columns[4] + " = " + std::to_string(e.char_zone_id));
|
||||||
v.push_back(columns[4] + " = " + std::to_string(e.quantity));
|
v.push_back(columns[5] + " = " + std::to_string(e.char_zone_instance_id));
|
||||||
v.push_back(columns[5] + " = " + std::to_string(e.price));
|
v.push_back(columns[6] + " = FROM_UNIXTIME(" + (e.transaction_date > 0 ? std::to_string(e.transaction_date) : "null") + ")");
|
||||||
|
v.push_back(columns[7] + " = '" + Strings::Escape(e.welcome_message) + "'");
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -187,7 +198,7 @@ public:
|
|||||||
TableName(),
|
TableName(),
|
||||||
Strings::Implode(", ", v),
|
Strings::Implode(", ", v),
|
||||||
PrimaryKey(),
|
PrimaryKey(),
|
||||||
e.charid
|
e.id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -201,12 +212,14 @@ public:
|
|||||||
{
|
{
|
||||||
std::vector<std::string> v;
|
std::vector<std::string> v;
|
||||||
|
|
||||||
v.push_back(std::to_string(e.charid));
|
v.push_back(std::to_string(e.id));
|
||||||
v.push_back(std::to_string(e.buyslot));
|
v.push_back(std::to_string(e.char_id));
|
||||||
v.push_back(std::to_string(e.itemid));
|
v.push_back(std::to_string(e.char_entity_id));
|
||||||
v.push_back("'" + Strings::Escape(e.itemname) + "'");
|
v.push_back("'" + Strings::Escape(e.char_name) + "'");
|
||||||
v.push_back(std::to_string(e.quantity));
|
v.push_back(std::to_string(e.char_zone_id));
|
||||||
v.push_back(std::to_string(e.price));
|
v.push_back(std::to_string(e.char_zone_instance_id));
|
||||||
|
v.push_back("FROM_UNIXTIME(" + (e.transaction_date > 0 ? std::to_string(e.transaction_date) : "null") + ")");
|
||||||
|
v.push_back("'" + Strings::Escape(e.welcome_message) + "'");
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -217,7 +230,7 @@ public:
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (results.Success()) {
|
if (results.Success()) {
|
||||||
e.charid = results.LastInsertedID();
|
e.id = results.LastInsertedID();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,12 +249,14 @@ public:
|
|||||||
for (auto &e: entries) {
|
for (auto &e: entries) {
|
||||||
std::vector<std::string> v;
|
std::vector<std::string> v;
|
||||||
|
|
||||||
v.push_back(std::to_string(e.charid));
|
v.push_back(std::to_string(e.id));
|
||||||
v.push_back(std::to_string(e.buyslot));
|
v.push_back(std::to_string(e.char_id));
|
||||||
v.push_back(std::to_string(e.itemid));
|
v.push_back(std::to_string(e.char_entity_id));
|
||||||
v.push_back("'" + Strings::Escape(e.itemname) + "'");
|
v.push_back("'" + Strings::Escape(e.char_name) + "'");
|
||||||
v.push_back(std::to_string(e.quantity));
|
v.push_back(std::to_string(e.char_zone_id));
|
||||||
v.push_back(std::to_string(e.price));
|
v.push_back(std::to_string(e.char_zone_instance_id));
|
||||||
|
v.push_back("FROM_UNIXTIME(" + (e.transaction_date > 0 ? std::to_string(e.transaction_date) : "null") + ")");
|
||||||
|
v.push_back("'" + Strings::Escape(e.welcome_message) + "'");
|
||||||
|
|
||||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
}
|
}
|
||||||
@@ -275,12 +290,14 @@ public:
|
|||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
Buyer e{};
|
Buyer e{};
|
||||||
|
|
||||||
e.charid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
|
||||||
e.buyslot = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||||
e.itemid = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
|
e.char_entity_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||||
e.itemname = row[3] ? row[3] : "";
|
e.char_name = row[3] ? row[3] : "";
|
||||||
e.quantity = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
|
e.char_zone_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||||
e.price = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
|
e.char_zone_instance_id = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||||
|
e.transaction_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10);
|
||||||
|
e.welcome_message = row[7] ? row[7] : "";
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
@@ -305,12 +322,14 @@ public:
|
|||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
Buyer e{};
|
Buyer e{};
|
||||||
|
|
||||||
e.charid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
|
||||||
e.buyslot = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||||
e.itemid = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
|
e.char_entity_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||||
e.itemname = row[3] ? row[3] : "";
|
e.char_name = row[3] ? row[3] : "";
|
||||||
e.quantity = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
|
e.char_zone_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||||
e.price = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
|
e.char_zone_instance_id = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||||
|
e.transaction_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10);
|
||||||
|
e.welcome_message = row[7] ? row[7] : "";
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
@@ -385,12 +404,14 @@ public:
|
|||||||
{
|
{
|
||||||
std::vector<std::string> v;
|
std::vector<std::string> v;
|
||||||
|
|
||||||
v.push_back(std::to_string(e.charid));
|
v.push_back(std::to_string(e.id));
|
||||||
v.push_back(std::to_string(e.buyslot));
|
v.push_back(std::to_string(e.char_id));
|
||||||
v.push_back(std::to_string(e.itemid));
|
v.push_back(std::to_string(e.char_entity_id));
|
||||||
v.push_back("'" + Strings::Escape(e.itemname) + "'");
|
v.push_back("'" + Strings::Escape(e.char_name) + "'");
|
||||||
v.push_back(std::to_string(e.quantity));
|
v.push_back(std::to_string(e.char_zone_id));
|
||||||
v.push_back(std::to_string(e.price));
|
v.push_back(std::to_string(e.char_zone_instance_id));
|
||||||
|
v.push_back("FROM_UNIXTIME(" + (e.transaction_date > 0 ? std::to_string(e.transaction_date) : "null") + ")");
|
||||||
|
v.push_back("'" + Strings::Escape(e.welcome_message) + "'");
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -413,12 +434,14 @@ public:
|
|||||||
for (auto &e: entries) {
|
for (auto &e: entries) {
|
||||||
std::vector<std::string> v;
|
std::vector<std::string> v;
|
||||||
|
|
||||||
v.push_back(std::to_string(e.charid));
|
v.push_back(std::to_string(e.id));
|
||||||
v.push_back(std::to_string(e.buyslot));
|
v.push_back(std::to_string(e.char_id));
|
||||||
v.push_back(std::to_string(e.itemid));
|
v.push_back(std::to_string(e.char_entity_id));
|
||||||
v.push_back("'" + Strings::Escape(e.itemname) + "'");
|
v.push_back("'" + Strings::Escape(e.char_name) + "'");
|
||||||
v.push_back(std::to_string(e.quantity));
|
v.push_back(std::to_string(e.char_zone_id));
|
||||||
v.push_back(std::to_string(e.price));
|
v.push_back(std::to_string(e.char_zone_instance_id));
|
||||||
|
v.push_back("FROM_UNIXTIME(" + (e.transaction_date > 0 ? std::to_string(e.transaction_date) : "null") + ")");
|
||||||
|
v.push_back("'" + Strings::Escape(e.welcome_message) + "'");
|
||||||
|
|
||||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,439 @@
|
|||||||
|
/**
|
||||||
|
* 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://docs.eqemu.io/developer/repositories
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EQEMU_BASE_BUYER_TRADE_ITEMS_REPOSITORY_H
|
||||||
|
#define EQEMU_BASE_BUYER_TRADE_ITEMS_REPOSITORY_H
|
||||||
|
|
||||||
|
#include "../../database.h"
|
||||||
|
#include "../../strings.h"
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
class BaseBuyerTradeItemsRepository {
|
||||||
|
public:
|
||||||
|
struct BuyerTradeItems {
|
||||||
|
uint64_t id;
|
||||||
|
uint64_t buyer_buy_lines_id;
|
||||||
|
int32_t item_id;
|
||||||
|
int32_t item_qty;
|
||||||
|
int32_t item_icon;
|
||||||
|
std::string item_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::string PrimaryKey()
|
||||||
|
{
|
||||||
|
return std::string("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::string> Columns()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
"id",
|
||||||
|
"buyer_buy_lines_id",
|
||||||
|
"item_id",
|
||||||
|
"item_qty",
|
||||||
|
"item_icon",
|
||||||
|
"item_name",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::string> SelectColumns()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
"id",
|
||||||
|
"buyer_buy_lines_id",
|
||||||
|
"item_id",
|
||||||
|
"item_qty",
|
||||||
|
"item_icon",
|
||||||
|
"item_name",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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("buyer_trade_items");
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string BaseSelect()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"SELECT {} FROM {}",
|
||||||
|
SelectColumnsRaw(),
|
||||||
|
TableName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string BaseInsert()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"INSERT INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BuyerTradeItems NewEntity()
|
||||||
|
{
|
||||||
|
BuyerTradeItems e{};
|
||||||
|
|
||||||
|
e.id = 0;
|
||||||
|
e.buyer_buy_lines_id = 0;
|
||||||
|
e.item_id = 0;
|
||||||
|
e.item_qty = 0;
|
||||||
|
e.item_icon = 0;
|
||||||
|
e.item_name = "0";
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BuyerTradeItems GetBuyerTradeItems(
|
||||||
|
const std::vector<BuyerTradeItems> &buyer_trade_itemss,
|
||||||
|
int buyer_trade_items_id
|
||||||
|
)
|
||||||
|
{
|
||||||
|
for (auto &buyer_trade_items : buyer_trade_itemss) {
|
||||||
|
if (buyer_trade_items.id == buyer_trade_items_id) {
|
||||||
|
return buyer_trade_items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
static BuyerTradeItems FindOne(
|
||||||
|
Database& db,
|
||||||
|
int buyer_trade_items_id
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
|
buyer_trade_items_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
if (results.RowCount() == 1) {
|
||||||
|
BuyerTradeItems e{};
|
||||||
|
|
||||||
|
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
|
||||||
|
e.buyer_buy_lines_id = row[1] ? strtoull(row[1], nullptr, 10) : 0;
|
||||||
|
e.item_id = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
|
||||||
|
e.item_qty = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
|
||||||
|
e.item_icon = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
|
||||||
|
e.item_name = row[5] ? row[5] : "0";
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int DeleteOne(
|
||||||
|
Database& db,
|
||||||
|
int buyer_trade_items_id
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"DELETE FROM {} WHERE {} = {}",
|
||||||
|
TableName(),
|
||||||
|
PrimaryKey(),
|
||||||
|
buyer_trade_items_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int UpdateOne(
|
||||||
|
Database& db,
|
||||||
|
const BuyerTradeItems &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto columns = Columns();
|
||||||
|
|
||||||
|
v.push_back(columns[1] + " = " + std::to_string(e.buyer_buy_lines_id));
|
||||||
|
v.push_back(columns[2] + " = " + std::to_string(e.item_id));
|
||||||
|
v.push_back(columns[3] + " = " + std::to_string(e.item_qty));
|
||||||
|
v.push_back(columns[4] + " = " + std::to_string(e.item_icon));
|
||||||
|
v.push_back(columns[5] + " = '" + Strings::Escape(e.item_name) + "'");
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"UPDATE {} SET {} WHERE {} = {}",
|
||||||
|
TableName(),
|
||||||
|
Strings::Implode(", ", v),
|
||||||
|
PrimaryKey(),
|
||||||
|
e.id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BuyerTradeItems InsertOne(
|
||||||
|
Database& db,
|
||||||
|
BuyerTradeItems e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.buyer_buy_lines_id));
|
||||||
|
v.push_back(std::to_string(e.item_id));
|
||||||
|
v.push_back(std::to_string(e.item_qty));
|
||||||
|
v.push_back(std::to_string(e.item_icon));
|
||||||
|
v.push_back("'" + Strings::Escape(e.item_name) + "'");
|
||||||
|
|
||||||
|
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<BuyerTradeItems> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.buyer_buy_lines_id));
|
||||||
|
v.push_back(std::to_string(e.item_id));
|
||||||
|
v.push_back(std::to_string(e.item_qty));
|
||||||
|
v.push_back(std::to_string(e.item_icon));
|
||||||
|
v.push_back("'" + Strings::Escape(e.item_name) + "'");
|
||||||
|
|
||||||
|
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<BuyerTradeItems> All(Database& db)
|
||||||
|
{
|
||||||
|
std::vector<BuyerTradeItems> all_entries;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{}",
|
||||||
|
BaseSelect()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
all_entries.reserve(results.RowCount());
|
||||||
|
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
BuyerTradeItems e{};
|
||||||
|
|
||||||
|
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
|
||||||
|
e.buyer_buy_lines_id = row[1] ? strtoull(row[1], nullptr, 10) : 0;
|
||||||
|
e.item_id = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
|
||||||
|
e.item_qty = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
|
||||||
|
e.item_icon = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
|
||||||
|
e.item_name = row[5] ? row[5] : "0";
|
||||||
|
|
||||||
|
all_entries.push_back(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return all_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<BuyerTradeItems> GetWhere(Database& db, const std::string &where_filter)
|
||||||
|
{
|
||||||
|
std::vector<BuyerTradeItems> 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) {
|
||||||
|
BuyerTradeItems e{};
|
||||||
|
|
||||||
|
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
|
||||||
|
e.buyer_buy_lines_id = row[1] ? strtoull(row[1], nullptr, 10) : 0;
|
||||||
|
e.item_id = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
|
||||||
|
e.item_qty = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
|
||||||
|
e.item_icon = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
|
||||||
|
e.item_name = row[5] ? row[5] : "0";
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const BuyerTradeItems &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.buyer_buy_lines_id));
|
||||||
|
v.push_back(std::to_string(e.item_id));
|
||||||
|
v.push_back(std::to_string(e.item_qty));
|
||||||
|
v.push_back(std::to_string(e.item_icon));
|
||||||
|
v.push_back("'" + Strings::Escape(e.item_name) + "'");
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<BuyerTradeItems> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.buyer_buy_lines_id));
|
||||||
|
v.push_back(std::to_string(e.item_id));
|
||||||
|
v.push_back(std::to_string(e.item_qty));
|
||||||
|
v.push_back(std::to_string(e.item_icon));
|
||||||
|
v.push_back("'" + Strings::Escape(e.item_name) + "'");
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //EQEMU_BASE_BUYER_TRADE_ITEMS_REPOSITORY_H
|
||||||
@@ -35,6 +35,7 @@ public:
|
|||||||
uint32_t ornamenticon;
|
uint32_t ornamenticon;
|
||||||
uint32_t ornamentidfile;
|
uint32_t ornamentidfile;
|
||||||
int32_t ornament_hero_model;
|
int32_t ornament_hero_model;
|
||||||
|
uint64_t guid;
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::string PrimaryKey()
|
static std::string PrimaryKey()
|
||||||
@@ -61,6 +62,7 @@ public:
|
|||||||
"ornamenticon",
|
"ornamenticon",
|
||||||
"ornamentidfile",
|
"ornamentidfile",
|
||||||
"ornament_hero_model",
|
"ornament_hero_model",
|
||||||
|
"guid",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,6 +85,7 @@ public:
|
|||||||
"ornamenticon",
|
"ornamenticon",
|
||||||
"ornamentidfile",
|
"ornamentidfile",
|
||||||
"ornament_hero_model",
|
"ornament_hero_model",
|
||||||
|
"guid",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,6 +142,7 @@ public:
|
|||||||
e.ornamenticon = 0;
|
e.ornamenticon = 0;
|
||||||
e.ornamentidfile = 0;
|
e.ornamentidfile = 0;
|
||||||
e.ornament_hero_model = 0;
|
e.ornament_hero_model = 0;
|
||||||
|
e.guid = 0;
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -191,6 +195,7 @@ public:
|
|||||||
e.ornamenticon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
e.ornamenticon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||||
e.ornamentidfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
e.ornamentidfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||||
e.ornament_hero_model = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
|
e.ornament_hero_model = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
|
||||||
|
e.guid = row[16] ? strtoull(row[16], nullptr, 10) : 0;
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -240,6 +245,7 @@ public:
|
|||||||
v.push_back(columns[13] + " = " + std::to_string(e.ornamenticon));
|
v.push_back(columns[13] + " = " + std::to_string(e.ornamenticon));
|
||||||
v.push_back(columns[14] + " = " + std::to_string(e.ornamentidfile));
|
v.push_back(columns[14] + " = " + std::to_string(e.ornamentidfile));
|
||||||
v.push_back(columns[15] + " = " + std::to_string(e.ornament_hero_model));
|
v.push_back(columns[15] + " = " + std::to_string(e.ornament_hero_model));
|
||||||
|
v.push_back(columns[16] + " = " + std::to_string(e.guid));
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -277,6 +283,7 @@ public:
|
|||||||
v.push_back(std::to_string(e.ornamenticon));
|
v.push_back(std::to_string(e.ornamenticon));
|
||||||
v.push_back(std::to_string(e.ornamentidfile));
|
v.push_back(std::to_string(e.ornamentidfile));
|
||||||
v.push_back(std::to_string(e.ornament_hero_model));
|
v.push_back(std::to_string(e.ornament_hero_model));
|
||||||
|
v.push_back(std::to_string(e.guid));
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -322,6 +329,7 @@ public:
|
|||||||
v.push_back(std::to_string(e.ornamenticon));
|
v.push_back(std::to_string(e.ornamenticon));
|
||||||
v.push_back(std::to_string(e.ornamentidfile));
|
v.push_back(std::to_string(e.ornamentidfile));
|
||||||
v.push_back(std::to_string(e.ornament_hero_model));
|
v.push_back(std::to_string(e.ornament_hero_model));
|
||||||
|
v.push_back(std::to_string(e.guid));
|
||||||
|
|
||||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
}
|
}
|
||||||
@@ -371,6 +379,7 @@ public:
|
|||||||
e.ornamenticon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
e.ornamenticon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||||
e.ornamentidfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
e.ornamentidfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||||
e.ornament_hero_model = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
|
e.ornament_hero_model = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
|
||||||
|
e.guid = row[16] ? strtoull(row[16], nullptr, 10) : 0;
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
@@ -411,6 +420,7 @@ public:
|
|||||||
e.ornamenticon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
e.ornamenticon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||||
e.ornamentidfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
e.ornamentidfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||||
e.ornament_hero_model = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
|
e.ornament_hero_model = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
|
||||||
|
e.guid = row[16] ? strtoull(row[16], nullptr, 10) : 0;
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
@@ -501,6 +511,7 @@ public:
|
|||||||
v.push_back(std::to_string(e.ornamenticon));
|
v.push_back(std::to_string(e.ornamenticon));
|
||||||
v.push_back(std::to_string(e.ornamentidfile));
|
v.push_back(std::to_string(e.ornamentidfile));
|
||||||
v.push_back(std::to_string(e.ornament_hero_model));
|
v.push_back(std::to_string(e.ornament_hero_model));
|
||||||
|
v.push_back(std::to_string(e.guid));
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -539,6 +550,7 @@ public:
|
|||||||
v.push_back(std::to_string(e.ornamenticon));
|
v.push_back(std::to_string(e.ornamenticon));
|
||||||
v.push_back(std::to_string(e.ornamentidfile));
|
v.push_back(std::to_string(e.ornamentidfile));
|
||||||
v.push_back(std::to_string(e.ornament_hero_model));
|
v.push_back(std::to_string(e.ornament_hero_model));
|
||||||
|
v.push_back(std::to_string(e.guid));
|
||||||
|
|
||||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public:
|
|||||||
uint32_t ornamenticon;
|
uint32_t ornamenticon;
|
||||||
uint32_t ornamentidfile;
|
uint32_t ornamentidfile;
|
||||||
int32_t ornament_hero_model;
|
int32_t ornament_hero_model;
|
||||||
|
uint64_t guid;
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::string PrimaryKey()
|
static std::string PrimaryKey()
|
||||||
@@ -63,6 +64,7 @@ public:
|
|||||||
"ornamenticon",
|
"ornamenticon",
|
||||||
"ornamentidfile",
|
"ornamentidfile",
|
||||||
"ornament_hero_model",
|
"ornament_hero_model",
|
||||||
|
"guid",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +88,7 @@ public:
|
|||||||
"ornamenticon",
|
"ornamenticon",
|
||||||
"ornamentidfile",
|
"ornamentidfile",
|
||||||
"ornament_hero_model",
|
"ornament_hero_model",
|
||||||
|
"guid",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,6 +146,7 @@ public:
|
|||||||
e.ornamenticon = 0;
|
e.ornamenticon = 0;
|
||||||
e.ornamentidfile = 0;
|
e.ornamentidfile = 0;
|
||||||
e.ornament_hero_model = 0;
|
e.ornament_hero_model = 0;
|
||||||
|
e.guid = 0;
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -196,6 +200,7 @@ public:
|
|||||||
e.ornamenticon = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
e.ornamenticon = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||||
e.ornamentidfile = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
|
e.ornamentidfile = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
|
||||||
e.ornament_hero_model = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
|
e.ornament_hero_model = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
|
||||||
|
e.guid = row[17] ? strtoull(row[17], nullptr, 10) : 0;
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -246,6 +251,7 @@ public:
|
|||||||
v.push_back(columns[14] + " = " + std::to_string(e.ornamenticon));
|
v.push_back(columns[14] + " = " + std::to_string(e.ornamenticon));
|
||||||
v.push_back(columns[15] + " = " + std::to_string(e.ornamentidfile));
|
v.push_back(columns[15] + " = " + std::to_string(e.ornamentidfile));
|
||||||
v.push_back(columns[16] + " = " + std::to_string(e.ornament_hero_model));
|
v.push_back(columns[16] + " = " + std::to_string(e.ornament_hero_model));
|
||||||
|
v.push_back(columns[17] + " = " + std::to_string(e.guid));
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -284,6 +290,7 @@ public:
|
|||||||
v.push_back(std::to_string(e.ornamenticon));
|
v.push_back(std::to_string(e.ornamenticon));
|
||||||
v.push_back(std::to_string(e.ornamentidfile));
|
v.push_back(std::to_string(e.ornamentidfile));
|
||||||
v.push_back(std::to_string(e.ornament_hero_model));
|
v.push_back(std::to_string(e.ornament_hero_model));
|
||||||
|
v.push_back(std::to_string(e.guid));
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -330,6 +337,7 @@ public:
|
|||||||
v.push_back(std::to_string(e.ornamenticon));
|
v.push_back(std::to_string(e.ornamenticon));
|
||||||
v.push_back(std::to_string(e.ornamentidfile));
|
v.push_back(std::to_string(e.ornamentidfile));
|
||||||
v.push_back(std::to_string(e.ornament_hero_model));
|
v.push_back(std::to_string(e.ornament_hero_model));
|
||||||
|
v.push_back(std::to_string(e.guid));
|
||||||
|
|
||||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
}
|
}
|
||||||
@@ -380,6 +388,7 @@ public:
|
|||||||
e.ornamenticon = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
e.ornamenticon = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||||
e.ornamentidfile = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
|
e.ornamentidfile = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
|
||||||
e.ornament_hero_model = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
|
e.ornament_hero_model = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
|
||||||
|
e.guid = row[17] ? strtoull(row[17], nullptr, 10) : 0;
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
@@ -421,6 +430,7 @@ public:
|
|||||||
e.ornamenticon = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
e.ornamenticon = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||||
e.ornamentidfile = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
|
e.ornamentidfile = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
|
||||||
e.ornament_hero_model = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
|
e.ornament_hero_model = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
|
||||||
|
e.guid = row[17] ? strtoull(row[17], nullptr, 10) : 0;
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
@@ -512,6 +522,7 @@ public:
|
|||||||
v.push_back(std::to_string(e.ornamenticon));
|
v.push_back(std::to_string(e.ornamenticon));
|
||||||
v.push_back(std::to_string(e.ornamentidfile));
|
v.push_back(std::to_string(e.ornamentidfile));
|
||||||
v.push_back(std::to_string(e.ornament_hero_model));
|
v.push_back(std::to_string(e.ornament_hero_model));
|
||||||
|
v.push_back(std::to_string(e.guid));
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -551,6 +562,7 @@ public:
|
|||||||
v.push_back(std::to_string(e.ornamenticon));
|
v.push_back(std::to_string(e.ornamenticon));
|
||||||
v.push_back(std::to_string(e.ornamentidfile));
|
v.push_back(std::to_string(e.ornamentidfile));
|
||||||
v.push_back(std::to_string(e.ornament_hero_model));
|
v.push_back(std::to_string(e.ornament_hero_model));
|
||||||
|
v.push_back(std::to_string(e.guid));
|
||||||
|
|
||||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,31 +19,34 @@
|
|||||||
class BaseSpellBucketsRepository {
|
class BaseSpellBucketsRepository {
|
||||||
public:
|
public:
|
||||||
struct SpellBuckets {
|
struct SpellBuckets {
|
||||||
uint64_t spellid;
|
uint32_t spell_id;
|
||||||
std::string key_;
|
std::string bucket_name;
|
||||||
std::string value;
|
std::string bucket_value;
|
||||||
|
uint8_t bucket_comparison;
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::string PrimaryKey()
|
static std::string PrimaryKey()
|
||||||
{
|
{
|
||||||
return std::string("spellid");
|
return std::string("spell_id");
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::string> Columns()
|
static std::vector<std::string> Columns()
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
"spellid",
|
"spell_id",
|
||||||
"`key`",
|
"bucket_name",
|
||||||
"value",
|
"bucket_value",
|
||||||
|
"bucket_comparison",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::string> SelectColumns()
|
static std::vector<std::string> SelectColumns()
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
"spellid",
|
"spell_id",
|
||||||
"`key`",
|
"bucket_name",
|
||||||
"value",
|
"bucket_value",
|
||||||
|
"bucket_comparison",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,9 +87,10 @@ public:
|
|||||||
{
|
{
|
||||||
SpellBuckets e{};
|
SpellBuckets e{};
|
||||||
|
|
||||||
e.spellid = 0;
|
e.spell_id = 0;
|
||||||
e.key_ = "";
|
e.bucket_name = "";
|
||||||
e.value = "";
|
e.bucket_value = "";
|
||||||
|
e.bucket_comparison = 0;
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -97,7 +101,7 @@ public:
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
for (auto &spell_buckets : spell_bucketss) {
|
for (auto &spell_buckets : spell_bucketss) {
|
||||||
if (spell_buckets.spellid == spell_buckets_id) {
|
if (spell_buckets.spell_id == spell_buckets_id) {
|
||||||
return spell_buckets;
|
return spell_buckets;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,9 +127,10 @@ public:
|
|||||||
if (results.RowCount() == 1) {
|
if (results.RowCount() == 1) {
|
||||||
SpellBuckets e{};
|
SpellBuckets e{};
|
||||||
|
|
||||||
e.spellid = row[0] ? strtoull(row[0], nullptr, 10) : 0;
|
e.spell_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||||
e.key_ = row[1] ? row[1] : "";
|
e.bucket_name = row[1] ? row[1] : "";
|
||||||
e.value = row[2] ? row[2] : "";
|
e.bucket_value = row[2] ? row[2] : "";
|
||||||
|
e.bucket_comparison = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -159,9 +164,10 @@ public:
|
|||||||
|
|
||||||
auto columns = Columns();
|
auto columns = Columns();
|
||||||
|
|
||||||
v.push_back(columns[0] + " = " + std::to_string(e.spellid));
|
v.push_back(columns[0] + " = " + std::to_string(e.spell_id));
|
||||||
v.push_back(columns[1] + " = '" + Strings::Escape(e.key_) + "'");
|
v.push_back(columns[1] + " = '" + Strings::Escape(e.bucket_name) + "'");
|
||||||
v.push_back(columns[2] + " = '" + Strings::Escape(e.value) + "'");
|
v.push_back(columns[2] + " = '" + Strings::Escape(e.bucket_value) + "'");
|
||||||
|
v.push_back(columns[3] + " = " + std::to_string(e.bucket_comparison));
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -169,7 +175,7 @@ public:
|
|||||||
TableName(),
|
TableName(),
|
||||||
Strings::Implode(", ", v),
|
Strings::Implode(", ", v),
|
||||||
PrimaryKey(),
|
PrimaryKey(),
|
||||||
e.spellid
|
e.spell_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -183,9 +189,10 @@ public:
|
|||||||
{
|
{
|
||||||
std::vector<std::string> v;
|
std::vector<std::string> v;
|
||||||
|
|
||||||
v.push_back(std::to_string(e.spellid));
|
v.push_back(std::to_string(e.spell_id));
|
||||||
v.push_back("'" + Strings::Escape(e.key_) + "'");
|
v.push_back("'" + Strings::Escape(e.bucket_name) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.value) + "'");
|
v.push_back("'" + Strings::Escape(e.bucket_value) + "'");
|
||||||
|
v.push_back(std::to_string(e.bucket_comparison));
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -196,7 +203,7 @@ public:
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (results.Success()) {
|
if (results.Success()) {
|
||||||
e.spellid = results.LastInsertedID();
|
e.spell_id = results.LastInsertedID();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,9 +222,10 @@ public:
|
|||||||
for (auto &e: entries) {
|
for (auto &e: entries) {
|
||||||
std::vector<std::string> v;
|
std::vector<std::string> v;
|
||||||
|
|
||||||
v.push_back(std::to_string(e.spellid));
|
v.push_back(std::to_string(e.spell_id));
|
||||||
v.push_back("'" + Strings::Escape(e.key_) + "'");
|
v.push_back("'" + Strings::Escape(e.bucket_name) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.value) + "'");
|
v.push_back("'" + Strings::Escape(e.bucket_value) + "'");
|
||||||
|
v.push_back(std::to_string(e.bucket_comparison));
|
||||||
|
|
||||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
}
|
}
|
||||||
@@ -251,9 +259,10 @@ public:
|
|||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
SpellBuckets e{};
|
SpellBuckets e{};
|
||||||
|
|
||||||
e.spellid = row[0] ? strtoull(row[0], nullptr, 10) : 0;
|
e.spell_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||||
e.key_ = row[1] ? row[1] : "";
|
e.bucket_name = row[1] ? row[1] : "";
|
||||||
e.value = row[2] ? row[2] : "";
|
e.bucket_value = row[2] ? row[2] : "";
|
||||||
|
e.bucket_comparison = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
@@ -278,9 +287,10 @@ public:
|
|||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
SpellBuckets e{};
|
SpellBuckets e{};
|
||||||
|
|
||||||
e.spellid = row[0] ? strtoull(row[0], nullptr, 10) : 0;
|
e.spell_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||||
e.key_ = row[1] ? row[1] : "";
|
e.bucket_name = row[1] ? row[1] : "";
|
||||||
e.value = row[2] ? row[2] : "";
|
e.bucket_value = row[2] ? row[2] : "";
|
||||||
|
e.bucket_comparison = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
@@ -355,9 +365,10 @@ public:
|
|||||||
{
|
{
|
||||||
std::vector<std::string> v;
|
std::vector<std::string> v;
|
||||||
|
|
||||||
v.push_back(std::to_string(e.spellid));
|
v.push_back(std::to_string(e.spell_id));
|
||||||
v.push_back("'" + Strings::Escape(e.key_) + "'");
|
v.push_back("'" + Strings::Escape(e.bucket_name) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.value) + "'");
|
v.push_back("'" + Strings::Escape(e.bucket_value) + "'");
|
||||||
|
v.push_back(std::to_string(e.bucket_comparison));
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -380,9 +391,10 @@ public:
|
|||||||
for (auto &e: entries) {
|
for (auto &e: entries) {
|
||||||
std::vector<std::string> v;
|
std::vector<std::string> v;
|
||||||
|
|
||||||
v.push_back(std::to_string(e.spellid));
|
v.push_back(std::to_string(e.spell_id));
|
||||||
v.push_back("'" + Strings::Escape(e.key_) + "'");
|
v.push_back("'" + Strings::Escape(e.bucket_name) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.value) + "'");
|
v.push_back("'" + Strings::Escape(e.bucket_value) + "'");
|
||||||
|
v.push_back(std::to_string(e.bucket_comparison));
|
||||||
|
|
||||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,24 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Custom extended repository methods here
|
// Custom extended repository methods here
|
||||||
|
static std::vector<std::string> GetBaseDataFileLines(Database& db)
|
||||||
|
{
|
||||||
|
std::vector<std::string> lines;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"SELECT CONCAT_WS('^', {}) FROM {} ORDER BY `level`, `class` ASC",
|
||||||
|
ColumnsRaw(),
|
||||||
|
TableName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
for (auto row : results) {
|
||||||
|
lines.emplace_back(row[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_DATA_REPOSITORY_H
|
#endif //EQEMU_BASE_DATA_REPOSITORY_H
|
||||||
|
|||||||
@@ -0,0 +1,360 @@
|
|||||||
|
#ifndef EQEMU_BUYER_BUY_LINES_REPOSITORY_H
|
||||||
|
#define EQEMU_BUYER_BUY_LINES_REPOSITORY_H
|
||||||
|
|
||||||
|
#include "../database.h"
|
||||||
|
#include "../strings.h"
|
||||||
|
#include "base/base_buyer_buy_lines_repository.h"
|
||||||
|
#include "buyer_trade_items_repository.h"
|
||||||
|
#include "character_data_repository.h"
|
||||||
|
#include "buyer_repository.h"
|
||||||
|
|
||||||
|
#include "../eq_packet_structs.h"
|
||||||
|
|
||||||
|
class BuyerBuyLinesRepository: public BaseBuyerBuyLinesRepository {
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* BuyerBuyLinesRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||||
|
* BuyerBuyLinesRepository::GetWhereNeverExpires()
|
||||||
|
* BuyerBuyLinesRepository::GetWhereXAndY()
|
||||||
|
* BuyerBuyLinesRepository::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
|
||||||
|
|
||||||
|
struct WelcomeData_Struct {
|
||||||
|
uint32 count_of_buyers;
|
||||||
|
uint32 count_of_items;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int CreateBuyLine(Database& db, const BuyerLineItems_Struct b, uint32 char_id)
|
||||||
|
{
|
||||||
|
auto buyer = BuyerRepository::GetWhere(db, fmt::format("`char_id` = '{}' LIMIT 1", char_id));
|
||||||
|
if (buyer.empty()){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuyerBuyLinesRepository::BuyerBuyLines buy_lines{};
|
||||||
|
buy_lines.id = 0;
|
||||||
|
buy_lines.buyer_id = buyer.front().id;
|
||||||
|
buy_lines.char_id = char_id;
|
||||||
|
buy_lines.buy_slot_id = b.slot;
|
||||||
|
buy_lines.item_id = b.item_id;
|
||||||
|
buy_lines.item_name = b.item_name;
|
||||||
|
buy_lines.item_icon = b.item_icon;
|
||||||
|
buy_lines.item_qty = b.item_quantity;
|
||||||
|
buy_lines.item_price = b.item_cost;
|
||||||
|
auto e = InsertOne(db, buy_lines);
|
||||||
|
|
||||||
|
std::vector<BuyerTradeItemsRepository::BuyerTradeItems> queue;
|
||||||
|
|
||||||
|
for (auto const &r: b.trade_items) {
|
||||||
|
BuyerTradeItemsRepository::BuyerTradeItems bti{};
|
||||||
|
bti.id = 0;
|
||||||
|
bti.buyer_buy_lines_id = e.id;
|
||||||
|
bti.item_id = r.item_id;
|
||||||
|
bti.item_qty = r.item_quantity;
|
||||||
|
bti.item_icon = r.item_icon;
|
||||||
|
bti.item_name = r.item_name;
|
||||||
|
|
||||||
|
if (bti.item_id) {
|
||||||
|
queue.push_back(bti);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!queue.empty()) {
|
||||||
|
BuyerTradeItemsRepository::InsertMany(db, queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ModifyBuyLine(Database& db, const BuyerLineItems_Struct b, uint32 char_id)
|
||||||
|
{
|
||||||
|
auto b_lines = GetWhere(db, fmt::format("`char_id` = '{}' AND `buy_slot_id` = '{}';", char_id, b.slot));
|
||||||
|
if (b_lines.empty() || b_lines.size() > 1){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto b_line = b_lines.front();
|
||||||
|
|
||||||
|
b_line.item_qty = b.item_quantity;
|
||||||
|
b_line.item_price = b.item_cost;
|
||||||
|
b_line.item_icon = b.item_icon;
|
||||||
|
auto e = UpdateOne(db, b_line);
|
||||||
|
|
||||||
|
std::vector<BuyerTradeItemsRepository::BuyerTradeItems> queue;
|
||||||
|
|
||||||
|
BuyerTradeItemsRepository::DeleteWhere(db, fmt::format("`buyer_buy_lines_id` = '{}';", b_line.id));
|
||||||
|
for (auto const &r: b.trade_items) {
|
||||||
|
BuyerTradeItemsRepository::BuyerTradeItems bti{};
|
||||||
|
bti.id = 0;
|
||||||
|
bti.buyer_buy_lines_id = b_line.id;
|
||||||
|
bti.item_id = r.item_id;
|
||||||
|
bti.item_qty = r.item_quantity;
|
||||||
|
bti.item_icon = r.item_icon;
|
||||||
|
bti.item_name = r.item_name;
|
||||||
|
|
||||||
|
if (bti.item_id) {
|
||||||
|
queue.push_back(bti);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!queue.empty()) {
|
||||||
|
BuyerTradeItemsRepository::InsertMany(db, queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool DeleteBuyLine(Database &db, uint32 char_id, int32 slot_id = 0xffffffff)
|
||||||
|
{
|
||||||
|
std::vector<BuyerBuyLines> buylines{};
|
||||||
|
if (slot_id == 0xffffffff) {
|
||||||
|
auto buylines = GetWhere(db, fmt::format("`char_id` = '{}'", char_id));
|
||||||
|
DeleteWhere(db, fmt::format("`char_id` = '{}'", char_id));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto buylines = GetWhere(db, fmt::format("`char_id` = '{}' AND `buy_slot_id` = '{}'", char_id, slot_id));
|
||||||
|
DeleteWhere(db, fmt::format("`char_id` = '{}' AND `buy_slot_id` = '{}'", char_id, slot_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buylines.empty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> buyline_ids{};
|
||||||
|
for (auto const &bl: buylines) {
|
||||||
|
buyline_ids.push_back((std::to_string(bl.id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!buyline_ids.empty()) {
|
||||||
|
BuyerTradeItemsRepository::DeleteWhere(
|
||||||
|
db,
|
||||||
|
fmt::format(
|
||||||
|
"`buyer_buy_lines_id` IN({})",
|
||||||
|
Strings::Implode(", ", buyline_ids)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<BuyerLineItems_Struct> GetBuyLines(Database &db, uint32 char_id)
|
||||||
|
{
|
||||||
|
std::vector<BuyerLineItems_Struct> all_entries{};
|
||||||
|
|
||||||
|
auto buy_line = GetWhere(db, fmt::format("`char_id` = '{}';", char_id));
|
||||||
|
if (buy_line.empty()){
|
||||||
|
return all_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto buy_line_trade_items = BuyerTradeItemsRepository::GetWhere(
|
||||||
|
db,
|
||||||
|
fmt::format(
|
||||||
|
"`buyer_buy_lines_id` IN (SELECT b.id FROM buyer_buy_lines AS b WHERE b.char_id = '{}')",
|
||||||
|
char_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
all_entries.reserve(buy_line.size());
|
||||||
|
|
||||||
|
for (auto const &l: buy_line) {
|
||||||
|
BuyerLineItems_Struct bli{};
|
||||||
|
bli.item_id = l.item_id;
|
||||||
|
bli.item_cost = l.item_price;
|
||||||
|
bli.item_quantity = l.item_qty;
|
||||||
|
bli.slot = l.buy_slot_id;
|
||||||
|
bli.item_name = l.item_name;
|
||||||
|
|
||||||
|
for (auto const &i: GetSubIDs(buy_line_trade_items, l.id)) {
|
||||||
|
BuyerLineTradeItems_Struct blti{};
|
||||||
|
blti.item_id = i.item_id;
|
||||||
|
blti.item_icon = i.item_icon;
|
||||||
|
blti.item_quantity = i.item_qty;
|
||||||
|
blti.item_id = i.item_id;
|
||||||
|
blti.item_name = i.item_name;
|
||||||
|
bli.trade_items.push_back(blti);
|
||||||
|
}
|
||||||
|
all_entries.push_back(bli);
|
||||||
|
}
|
||||||
|
|
||||||
|
return all_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BuyerLineSearch_Struct SearchBuyLines(
|
||||||
|
Database &db,
|
||||||
|
std::string &search_string,
|
||||||
|
uint32 char_id = 0,
|
||||||
|
uint32 zone_id = 0,
|
||||||
|
uint32 zone_instance_id = 0
|
||||||
|
)
|
||||||
|
{
|
||||||
|
BuyerLineSearch_Struct all_entries{};
|
||||||
|
std::string where_clause(fmt::format("`item_name` LIKE \"%{}%\" ", search_string));
|
||||||
|
|
||||||
|
if (char_id) {
|
||||||
|
where_clause += fmt::format("AND `char_id` = '{}' ", char_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zone_id) {
|
||||||
|
auto buyers = BuyerRepository::GetWhere(
|
||||||
|
db,
|
||||||
|
fmt::format(
|
||||||
|
"`char_zone_id` = '{}' AND char_zone_instance_id = '{}'",
|
||||||
|
zone_id,
|
||||||
|
zone_instance_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (buyers.empty()) {
|
||||||
|
return all_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> char_ids{};
|
||||||
|
for (auto const &bl : buyers) {
|
||||||
|
char_ids.push_back((std::to_string(bl.char_id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
where_clause += fmt::format("AND `char_id` IN ({}) ", Strings::Implode(", ", char_ids));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto buy_line = GetWhere(db, where_clause);
|
||||||
|
if (buy_line.empty()){
|
||||||
|
return all_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> ids{};
|
||||||
|
std::vector<std::string> char_ids{};
|
||||||
|
for (auto const &bl : buy_line) {
|
||||||
|
if (std::find(ids.begin(), ids.end(), std::to_string(bl.id)) == std::end(ids)) {
|
||||||
|
ids.push_back(std::to_string(bl.id));
|
||||||
|
}
|
||||||
|
if (std::find(char_ids.begin(), char_ids.end(), std::to_string(bl.char_id)) == std::end(char_ids)) {
|
||||||
|
char_ids.push_back((std::to_string(bl.char_id)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto buy_line_trade_items = BuyerTradeItemsRepository::GetWhere(
|
||||||
|
db,
|
||||||
|
fmt::format(
|
||||||
|
"`buyer_buy_lines_id` IN ({});",
|
||||||
|
Strings::Implode(", ", ids)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
auto char_names = BuyerRepository::GetWhere(
|
||||||
|
db,
|
||||||
|
fmt::format(
|
||||||
|
"`char_id` IN ({});",
|
||||||
|
Strings::Implode(", ", char_ids)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
all_entries.no_items = buy_line.size();
|
||||||
|
for (auto const &l: buy_line) {
|
||||||
|
BuyerLineItemsSearch_Struct blis{};
|
||||||
|
blis.slot = l.buy_slot_id;
|
||||||
|
blis.item_id = l.item_id;
|
||||||
|
blis.item_cost = l.item_price;
|
||||||
|
blis.item_icon = l.item_icon;
|
||||||
|
blis.item_quantity = l.item_qty;
|
||||||
|
blis.buyer_id = l.char_id;
|
||||||
|
auto it = std::find_if(
|
||||||
|
char_names.cbegin(),
|
||||||
|
char_names.cend(),
|
||||||
|
[&](BuyerRepository::Buyer e) { return e.char_id == l.char_id; }
|
||||||
|
);
|
||||||
|
blis.buyer_name = it != char_names.end() ? it->char_name : std::string("");
|
||||||
|
blis.buyer_entity_id = it != char_names.end() ? it->char_entity_id : 0;
|
||||||
|
blis.buyer_zone_id = it != char_names.end() ? it->char_zone_id : 0;
|
||||||
|
blis.buyer_zone_instance_id = it != char_names.end() ? it->char_zone_instance_id : 0;
|
||||||
|
strn0cpy(blis.item_name, l.item_name.c_str(), sizeof(blis.item_name));
|
||||||
|
|
||||||
|
for (auto const &i: GetSubIDs(buy_line_trade_items, l.id)) {
|
||||||
|
BuyerLineTradeItems_Struct e{};
|
||||||
|
e.item_id = i.item_id;
|
||||||
|
e.item_icon = i.item_icon;
|
||||||
|
e.item_quantity = i.item_qty;
|
||||||
|
e.item_id = i.item_id;
|
||||||
|
e.item_name = i.item_name;
|
||||||
|
|
||||||
|
blis.trade_items.push_back(e);
|
||||||
|
}
|
||||||
|
all_entries.buy_line.push_back(blis);
|
||||||
|
}
|
||||||
|
|
||||||
|
return all_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<BuyerTradeItemsRepository::BuyerTradeItems>
|
||||||
|
GetSubIDs(std::vector<BuyerTradeItemsRepository::BuyerTradeItems> &in, uint64 id)
|
||||||
|
{
|
||||||
|
std::vector<BuyerTradeItemsRepository::BuyerTradeItems> results{};
|
||||||
|
std::vector<uint64> indices{};
|
||||||
|
|
||||||
|
auto it = in.begin();
|
||||||
|
while ((it = std::find_if(
|
||||||
|
it,
|
||||||
|
in.end(),
|
||||||
|
[&](BuyerTradeItemsRepository::BuyerTradeItems const &e) {
|
||||||
|
return e.buyer_buy_lines_id == id;
|
||||||
|
}
|
||||||
|
))
|
||||||
|
!= in.end()
|
||||||
|
) {
|
||||||
|
indices.push_back(std::distance(in.begin(), it));
|
||||||
|
results.push_back(*it);
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WelcomeData_Struct GetWelcomeData(Database &db)
|
||||||
|
{
|
||||||
|
WelcomeData_Struct e{};
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase("SELECT COUNT(DISTINCT char_id), COUNT(char_id) FROM buyer;");
|
||||||
|
|
||||||
|
if (!results.RowCount()) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto r = results.begin();
|
||||||
|
e.count_of_buyers = Strings::ToInt(r[0]);
|
||||||
|
e.count_of_items = Strings::ToInt(r[1]);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //EQEMU_BUYER_BUY_LINES_REPOSITORY_H
|
||||||
@@ -4,6 +4,8 @@
|
|||||||
#include "../database.h"
|
#include "../database.h"
|
||||||
#include "../strings.h"
|
#include "../strings.h"
|
||||||
#include "base/base_buyer_repository.h"
|
#include "base/base_buyer_repository.h"
|
||||||
|
#include "base/base_buyer_trade_items_repository.h"
|
||||||
|
#include "base/base_buyer_buy_lines_repository.h"
|
||||||
|
|
||||||
class BuyerRepository: public BaseBuyerRepository {
|
class BuyerRepository: public BaseBuyerRepository {
|
||||||
public:
|
public:
|
||||||
@@ -45,6 +47,97 @@ public:
|
|||||||
|
|
||||||
// Custom extended repository methods here
|
// Custom extended repository methods here
|
||||||
|
|
||||||
|
static bool UpdateWelcomeMessage(Database& db, uint32 char_id, const char *message) {
|
||||||
|
|
||||||
|
auto const b = GetWhere(db, fmt::format("`char_id` = '{}';", char_id));
|
||||||
|
|
||||||
|
if (b.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto buyer = b.front();
|
||||||
|
buyer.welcome_message = message;
|
||||||
|
return UpdateOne(db, buyer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string GetWelcomeMessage(Database& db, uint32 char_id) {
|
||||||
|
|
||||||
|
auto const b = GetWhere(db, fmt::format("`char_id` = '{}' LIMIT 1;", char_id));
|
||||||
|
if (b.empty()) {
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.front().welcome_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int UpdateTransactionDate(Database& db, uint32 char_id, time_t transaction_date) {
|
||||||
|
auto b = GetWhere(db, fmt::format("`char_id` = '{}' LIMIT 1;", char_id));
|
||||||
|
if (b.empty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto e = b.front();
|
||||||
|
e.transaction_date = transaction_date;
|
||||||
|
|
||||||
|
return UpdateOne(db, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
static time_t GetTransactionDate(Database& db, uint32 char_id) {
|
||||||
|
auto b = GetWhere(db, fmt::format("`char_id` = '{}' LIMIT 1;", char_id));
|
||||||
|
if (b.empty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto e = b.front();
|
||||||
|
|
||||||
|
return e.transaction_date;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool DeleteBuyer(Database &db, uint32 char_id)
|
||||||
|
{
|
||||||
|
if (char_id == 0) {
|
||||||
|
Truncate(db);
|
||||||
|
BaseBuyerBuyLinesRepository::Truncate(db);
|
||||||
|
BaseBuyerTradeItemsRepository::Truncate(db);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto buyer = GetWhere(db, fmt::format("`char_id` = '{}' LIMIT 1;", char_id));
|
||||||
|
if (buyer.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto buy_lines = BaseBuyerBuyLinesRepository::GetWhere(
|
||||||
|
db,
|
||||||
|
fmt::format("`buyer_id` = '{}'", buyer.front().id)
|
||||||
|
);
|
||||||
|
if (buy_lines.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> buy_line_ids{};
|
||||||
|
for (auto const &bl: buy_lines) {
|
||||||
|
buy_line_ids.push_back(std::to_string(bl.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteWhere(db, fmt::format("`char_id` = '{}';", char_id));
|
||||||
|
if (buy_line_ids.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseBuyerBuyLinesRepository::DeleteWhere(
|
||||||
|
db,
|
||||||
|
fmt::format("`id` IN({})", Strings::Implode(", ", buy_line_ids))
|
||||||
|
);
|
||||||
|
BaseBuyerTradeItemsRepository::DeleteWhere(
|
||||||
|
db,
|
||||||
|
fmt::format(
|
||||||
|
"`buyer_buy_lines_id` IN({})",
|
||||||
|
Strings::Implode(", ", buy_line_ids))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BUYER_REPOSITORY_H
|
#endif //EQEMU_BUYER_REPOSITORY_H
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
#ifndef EQEMU_BUYER_TRADE_ITEMS_REPOSITORY_H
|
||||||
|
#define EQEMU_BUYER_TRADE_ITEMS_REPOSITORY_H
|
||||||
|
|
||||||
|
#include "../database.h"
|
||||||
|
#include "../strings.h"
|
||||||
|
#include "base/base_buyer_trade_items_repository.h"
|
||||||
|
|
||||||
|
class BuyerTradeItemsRepository: public BaseBuyerTradeItemsRepository {
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* BuyerTradeItemsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||||
|
* BuyerTradeItemsRepository::GetWhereNeverExpires()
|
||||||
|
* BuyerTradeItemsRepository::GetWhereXAndY()
|
||||||
|
* BuyerTradeItemsRepository::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<BuyerTradeItems> GetTradeItems(Database& db, const uint32 char_id)
|
||||||
|
{
|
||||||
|
std::vector<BuyerTradeItems> all_entries;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"SELECT bti.* "
|
||||||
|
"FROM buyer_trade_items AS bti "
|
||||||
|
"INNER JOIN buyer_buy_lines AS bbl ON bti.buyer_buy_lines_id = bbl.id "
|
||||||
|
"WHERE bbl.char_id = '{}';",
|
||||||
|
char_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
all_entries.reserve(results.RowCount());
|
||||||
|
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
BuyerTradeItems e{};
|
||||||
|
|
||||||
|
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
|
||||||
|
e.buyer_buy_lines_id = row[1] ? strtoull(row[1], nullptr, 10) : 0;
|
||||||
|
e.item_id = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
|
||||||
|
e.item_qty = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
|
||||||
|
e.item_icon = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
|
||||||
|
e.item_name = row[5] ? row[5] : "0";
|
||||||
|
|
||||||
|
all_entries.push_back(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return all_entries;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //EQEMU_BUYER_TRADE_ITEMS_REPOSITORY_H
|
||||||
@@ -49,8 +49,11 @@ public:
|
|||||||
// these are the base definitions for command_subsettings and can be over-ridden by the database
|
// these are the base definitions for command_subsettings and can be over-ridden by the database
|
||||||
std::vector<CommandSubsettingsRepository::CommandSubsettings> static_records = {
|
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 = "aa", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findaa"},
|
||||||
|
{.parent_command = "find", .sub_command = "body_type", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findbodytype"},
|
||||||
|
{.parent_command = "find", .sub_command = "bug_category", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findbugcategory"},
|
||||||
{.parent_command = "find", .sub_command = "character", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findcharacter"},
|
{.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 = "class", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findclass"},
|
||||||
|
{.parent_command = "find", .sub_command = "comparison_type", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findcomparisontype"},
|
||||||
{.parent_command = "find", .sub_command = "currency", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findcurrency"},
|
{.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 = "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 = "emote", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findemote"},
|
||||||
@@ -58,9 +61,12 @@ public:
|
|||||||
{.parent_command = "find", .sub_command = "item", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fi|finditem|itemsearch"},
|
{.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 = "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 = "npc_type", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fn|findnpc|findnpctype"},
|
||||||
|
{.parent_command = "find", .sub_command = "object_type", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findobjecttype"},
|
||||||
{.parent_command = "find", .sub_command = "race", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findrace"},
|
{.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 = "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 = "skill", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findskill"},
|
||||||
|
{.parent_command = "find", .sub_command = "special_ability", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fsa|findspecialability"},
|
||||||
|
{.parent_command = "find", .sub_command = "stance", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findstance"},
|
||||||
{.parent_command = "find", .sub_command = "spell", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fs|findspell"},
|
{.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 = "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 = "find", .sub_command = "zone", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fz|findzone"},
|
||||||
@@ -79,7 +85,6 @@ public:
|
|||||||
{.parent_command = "set", .sub_command = "endurance", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setendurance"},
|
{.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 = "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 = "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 = "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 = "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", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "gender"},
|
||||||
|
|||||||
@@ -44,7 +44,24 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Custom extended repository methods here
|
// Custom extended repository methods here
|
||||||
|
static std::vector<std::string> GetDBStrFileLines(Database& db)
|
||||||
|
{
|
||||||
|
std::vector<std::string> lines;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"SELECT CONCAT(CONCAT_WS('^', {}), '^0') FROM {} ORDER BY `id`, `type` ASC",
|
||||||
|
ColumnsRaw(),
|
||||||
|
TableName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
for (auto row : results) {
|
||||||
|
lines.emplace_back(row[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_DB_STR_REPOSITORY_H
|
#endif //EQEMU_DB_STR_REPOSITORY_H
|
||||||
|
|||||||
@@ -44,7 +44,23 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Custom extended repository methods here
|
// Custom extended repository methods here
|
||||||
|
static std::vector<std::string> GetSkillCapFileLines(Database& db)
|
||||||
|
{
|
||||||
|
std::vector<std::string> lines;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"SELECT CONCAT_WS('^', `class_id`, `skill_id`, `level`, `cap`, `class_`) FROM {} ORDER BY `class_id`, `skill_id`, `level` ASC",
|
||||||
|
TableName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
for (auto row : results) {
|
||||||
|
lines.emplace_back(row[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_SKILL_CAPS_REPOSITORY_H
|
#endif //EQEMU_SKILL_CAPS_REPOSITORY_H
|
||||||
|
|||||||
@@ -44,7 +44,25 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Custom extended repository methods here
|
// Custom extended repository methods here
|
||||||
|
static std::vector<std::string> GetSpellFileLines(Database& db)
|
||||||
|
{
|
||||||
|
std::vector<std::string> lines;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"SELECT CONCAT_WS('^', {}) FROM {} ORDER BY {} ASC",
|
||||||
|
ColumnsRaw(),
|
||||||
|
TableName(),
|
||||||
|
PrimaryKey()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
for (auto row : results) {
|
||||||
|
lines.emplace_back(row[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_SPELLS_NEW_REPOSITORY_H
|
#endif //EQEMU_SPELLS_NEW_REPOSITORY_H
|
||||||
|
|||||||
@@ -217,6 +217,10 @@ public:
|
|||||||
delete_ids.push_back(std::to_string(e.id));
|
delete_ids.push_back(std::to_string(e.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (delete_ids.empty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return DeleteWhere(db, fmt::format("`id` IN({})", Strings::Implode(",", delete_ids)));
|
return DeleteWhere(db, fmt::format("`id` IN({})", Strings::Implode(",", delete_ids)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -189,6 +189,8 @@ void RuleManager::ResetRules(bool reload) {
|
|||||||
m_RuleRealValues[ Real__##rule_name ] = default_value;
|
m_RuleRealValues[ Real__##rule_name ] = default_value;
|
||||||
#define RULE_BOOL(category_name, rule_name, default_value, notes) \
|
#define RULE_BOOL(category_name, rule_name, default_value, notes) \
|
||||||
m_RuleBoolValues[ Bool__##rule_name ] = default_value;
|
m_RuleBoolValues[ Bool__##rule_name ] = default_value;
|
||||||
|
#define RULE_STRING(category_name, rule_name, default_value, notes) \
|
||||||
|
m_RuleStringValues[ String__##rule_name ] = default_value;
|
||||||
#include "ruletypes.h"
|
#include "ruletypes.h"
|
||||||
|
|
||||||
// restore these rules to their pre-reset values
|
// restore these rules to their pre-reset values
|
||||||
|
|||||||
+42
-1
@@ -178,6 +178,7 @@ RULE_BOOL(Character, NoSkillsOnHorse, false, "Enabling this will prevent Bind Wo
|
|||||||
RULE_BOOL(Character, UseNoJunkFishing, false, "Disregards junk items when fishing")
|
RULE_BOOL(Character, UseNoJunkFishing, false, "Disregards junk items when fishing")
|
||||||
RULE_BOOL(Character, SoftDeletes, true, "When characters are deleted in character select, they are only soft deleted")
|
RULE_BOOL(Character, SoftDeletes, true, "When characters are deleted in character select, they are only soft deleted")
|
||||||
RULE_INT(Character, DefaultGuild, 0, "If not 0, new characters placed into the guild # indicated")
|
RULE_INT(Character, DefaultGuild, 0, "If not 0, new characters placed into the guild # indicated")
|
||||||
|
RULE_INT(Character, DefaultGuildRank, 8, "Default guild rank when Character:DefaultGuild is a non-0 value, default is 8 (Recruit)")
|
||||||
RULE_BOOL(Character, ProcessFearedProximity, false, "Processes proximity checks when feared")
|
RULE_BOOL(Character, ProcessFearedProximity, false, "Processes proximity checks when feared")
|
||||||
RULE_BOOL(Character, EnableCharacterEXPMods, false, "Enables character zone-based experience modifiers.")
|
RULE_BOOL(Character, EnableCharacterEXPMods, false, "Enables character zone-based experience modifiers.")
|
||||||
RULE_BOOL(Character, PVPEnableGuardFactionAssist, true, "Enables faction based assisting against the aggresor in pvp.")
|
RULE_BOOL(Character, PVPEnableGuardFactionAssist, true, "Enables faction based assisting against the aggresor in pvp.")
|
||||||
@@ -226,6 +227,9 @@ RULE_INT(Character, ClearXTargetDelay, 10, "Seconds between uses of the #clearxt
|
|||||||
RULE_BOOL(Character, PreventMountsFromZoning, false, "Enable to prevent mounts from zoning - Prior to December 15, 2004 this is enabled.")
|
RULE_BOOL(Character, PreventMountsFromZoning, false, "Enable to prevent mounts from zoning - Prior to December 15, 2004 this is enabled.")
|
||||||
RULE_BOOL(Character, GroupInvitesRequireTarget, false, "Enable to require players to have invitee on target (Disables /invite name) - Classic Style")
|
RULE_BOOL(Character, GroupInvitesRequireTarget, false, "Enable to require players to have invitee on target (Disables /invite name) - Classic Style")
|
||||||
RULE_BOOL(Character, PlayerTradingLoreFeedback, true, "If enabled, during a player to player trade, if lore items exist, it will output which items.")
|
RULE_BOOL(Character, PlayerTradingLoreFeedback, true, "If enabled, during a player to player trade, if lore items exist, it will output which items.")
|
||||||
|
RULE_INT(Character, MendAlwaysSucceedValue, 199, "Value at which mend will always succeed its skill check. Default: 199")
|
||||||
|
RULE_BOOL(Character, SneakAlwaysSucceedOver100, false, "When sneak skill is over 100, always succeed sneak/hide. Default: false")
|
||||||
|
RULE_INT(Character, BandolierSwapDelay, 0, "Bandolier swap delay in milliseconds, default is 0")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Mercs)
|
RULE_CATEGORY(Mercs)
|
||||||
@@ -240,6 +244,9 @@ RULE_INT(Mercs, AggroRadiusPuller, 25, "Determines the distance from which a mer
|
|||||||
RULE_INT(Mercs, ResurrectRadius, 50, "Determines the distance from which a healer merc will attempt to resurrect a group member's corpse")
|
RULE_INT(Mercs, ResurrectRadius, 50, "Determines the distance from which a healer merc will attempt to resurrect a group member's corpse")
|
||||||
RULE_INT(Mercs, ScaleRate, 100, "Merc scale factor")
|
RULE_INT(Mercs, ScaleRate, 100, "Merc scale factor")
|
||||||
RULE_BOOL(Mercs, AllowMercSuspendInCombat, true, "Allow merc suspend in combat")
|
RULE_BOOL(Mercs, AllowMercSuspendInCombat, true, "Allow merc suspend in combat")
|
||||||
|
RULE_BOOL(Mercs, MercsIgnoreLevelBasedHasteCaps, false, "Ignores hard coded level based haste caps.")
|
||||||
|
RULE_INT(Mercs, MercsHasteCap, 100, "Haste cap for non-v3(over haste) haste")
|
||||||
|
RULE_INT(Mercs, MercsHastev3Cap, 25, "Haste cap for v3(over haste) haste")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Guild)
|
RULE_CATEGORY(Guild)
|
||||||
@@ -331,6 +338,8 @@ RULE_STRING(World, IPExemptionZones, "", "Comma-delimited list of zones to exclu
|
|||||||
RULE_STRING(World, MOTD, "", "Server MOTD sent on login, change from empty to have this be used instead of variables table 'motd' value")
|
RULE_STRING(World, MOTD, "", "Server MOTD sent on login, change from empty to have this be used instead of variables table 'motd' value")
|
||||||
RULE_STRING(World, Rules, "", "Server Rules, change from empty to have this be used instead of variables table 'rules' value, lines are pipe (|) separated, example: A|B|C")
|
RULE_STRING(World, Rules, "", "Server Rules, change from empty to have this be used instead of variables table 'rules' value, lines are pipe (|) separated, example: A|B|C")
|
||||||
RULE_BOOL(World, EnableAutoLogin, false, "Enables or disables auto login of characters, allowing people to log characters in directly from loginserver to ingame")
|
RULE_BOOL(World, EnableAutoLogin, false, "Enables or disables auto login of characters, allowing people to log characters in directly from loginserver to ingame")
|
||||||
|
RULE_BOOL(World, EnablePVPRegions, true, "Enables or disables PVP Regions automatically setting your PVP flag")
|
||||||
|
RULE_INT(World, Id, 100, "Used by later clients to create GUIDs, expected to be Unique to the world but ultimately not that important")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Zone)
|
RULE_CATEGORY(Zone)
|
||||||
@@ -468,7 +477,6 @@ RULE_BOOL(Spells, OldRainTargets, false, "Use old incorrectly implemented maximu
|
|||||||
RULE_REAL(Spells, CallOfTheHeroAggroClearDist, 250.0, "Distance at which CoTH will wipe aggro. To disable and always enable aggro wipe on any distance of CoTH, set to 0.")
|
RULE_REAL(Spells, CallOfTheHeroAggroClearDist, 250.0, "Distance at which CoTH will wipe aggro. To disable and always enable aggro wipe on any distance of CoTH, set to 0.")
|
||||||
RULE_BOOL(Spells, NPCSpellPush, false, "Enable spell push on NPCs")
|
RULE_BOOL(Spells, NPCSpellPush, false, "Enable spell push on NPCs")
|
||||||
RULE_BOOL(Spells, July242002PetResists, true, "Enable Pets using PCs resist change from July 24 2002")
|
RULE_BOOL(Spells, July242002PetResists, true, "Enable Pets using PCs resist change from July 24 2002")
|
||||||
RULE_INT(Spells, AOEMaxTargets, 0, "Max number of targets a Targeted AOE spell can cast on. Set to 0 for no limit.")
|
|
||||||
RULE_BOOL(Spells, CazicTouchTargetsPetOwner, true, "If True, causes Cazic Touch to swap targets from pet to pet owner if a pet is tanking.")
|
RULE_BOOL(Spells, CazicTouchTargetsPetOwner, true, "If True, causes Cazic Touch to swap targets from pet to pet owner if a pet is tanking.")
|
||||||
RULE_BOOL(Spells, PreventFactionWarOnCharmBreak, false, "Enable spell interupts and dot removal on charm break to prevent faction wars.")
|
RULE_BOOL(Spells, PreventFactionWarOnCharmBreak, false, "Enable spell interupts and dot removal on charm break to prevent faction wars.")
|
||||||
RULE_BOOL(Spells, AllowDoubleInvis, true, "Allows you to cast invisibility spells on a player that is already invisible, live like behavior.")
|
RULE_BOOL(Spells, AllowDoubleInvis, true, "Allows you to cast invisibility spells on a player that is already invisible, live like behavior.")
|
||||||
@@ -503,9 +511,14 @@ RULE_BOOL(Spells, RequireMnemonicRetention, true, "Enabling will require spell s
|
|||||||
RULE_BOOL(Spells, EvacClearCharmPet, false, "Enable to have evac in zone clear charm from charm pets and detach buffs.")
|
RULE_BOOL(Spells, EvacClearCharmPet, false, "Enable to have evac in zone clear charm from charm pets and detach buffs.")
|
||||||
RULE_BOOL(Spells, ManaTapsRequireNPCMana, false, "Enabling will require target to have mana to tap. Default off as many npc's are caster class with 0 mana and need fixed.")
|
RULE_BOOL(Spells, ManaTapsRequireNPCMana, false, "Enabling will require target to have mana to tap. Default off as many npc's are caster class with 0 mana and need fixed.")
|
||||||
RULE_INT(Spells, HarmTouchCritRatio, 200, "Harmtouch crit bonus, on top of BaseCritRatio")
|
RULE_INT(Spells, HarmTouchCritRatio, 200, "Harmtouch crit bonus, on top of BaseCritRatio")
|
||||||
|
RULE_BOOL(Spells, UseClassicHarmTouchDamage, false, "Use pre 2007 Harm Touch calculations - Default: False")
|
||||||
RULE_BOOL(Spells, UseClassicSpellFocus, false, "Enabling will tell the server to handle random focus damage as classic spell imports lack the limit values.")
|
RULE_BOOL(Spells, UseClassicSpellFocus, false, "Enabling will tell the server to handle random focus damage as classic spell imports lack the limit values.")
|
||||||
RULE_BOOL(Spells, ManaTapsOnAnyClass, false, "Enabling this will allow you to cast mana taps on any class, this will bypass ManaTapsRequireNPCMana rule.")
|
RULE_BOOL(Spells, ManaTapsOnAnyClass, false, "Enabling this will allow you to cast mana taps on any class, this will bypass ManaTapsRequireNPCMana rule.")
|
||||||
RULE_INT(Spells, HealAmountMessageFilterThreshold, 100, "Lifetaps below this threshold will not have a message sent to the client (Heal will still process) 0 to Disable.")
|
RULE_INT(Spells, HealAmountMessageFilterThreshold, 100, "Lifetaps below this threshold will not have a message sent to the client (Heal will still process) 0 to Disable.")
|
||||||
|
RULE_BOOL(Spells, SnareOverridesSpeedBonuses, false, "Enabling will allow snares to override any speed bonuses the entity may have. Default: False")
|
||||||
|
RULE_INT(Spells, TargetedAOEMaxTargets, 4, "Max number of targets a Targeted AOE spell can cast on. Set to 0 for no limit.")
|
||||||
|
RULE_INT(Spells, PointBlankAOEMaxTargets, 0, "Max number of targets a Point-Blank AOE spell can cast on. Set to 0 for no limit.")
|
||||||
|
RULE_INT(Spells, DefaultAOEMaxTargets, 0, "Max number of targets that an AOE spell which does not meet other descriptions can cast on. Set to 0 for no limit.")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Combat)
|
RULE_CATEGORY(Combat)
|
||||||
@@ -614,6 +627,21 @@ RULE_INT(Combat, PCAttackPowerScaling, 100, "Applies scaling to PC Attack Power
|
|||||||
RULE_INT(Combat, PCAccuracyAvoidanceMod2Scale, 100, "Scale Factor for PC Accuracy and Avoidance (Mod2, found on items). Found a value of 100 to make both too strong (75 = x0.75). DEFAULT: 100 to not adjust existing Servers")
|
RULE_INT(Combat, PCAccuracyAvoidanceMod2Scale, 100, "Scale Factor for PC Accuracy and Avoidance (Mod2, found on items). Found a value of 100 to make both too strong (75 = x0.75). DEFAULT: 100 to not adjust existing Servers")
|
||||||
RULE_BOOL(Combat, AllowRaidTargetBlind, false, "Toggle to allow raid targets to be blinded, default is false (Live-like)")
|
RULE_BOOL(Combat, AllowRaidTargetBlind, false, "Toggle to allow raid targets to be blinded, default is false (Live-like)")
|
||||||
RULE_BOOL(Combat, RogueBackstabHasteCorrection, false, "Toggle to enable correction for Haste impacting Backstab DPS too much. DEFAULT: false")
|
RULE_BOOL(Combat, RogueBackstabHasteCorrection, false, "Toggle to enable correction for Haste impacting Backstab DPS too much. DEFAULT: false")
|
||||||
|
RULE_BOOL(Combat, LegacyComputeDefense, false, "Trim AGI Scaling of defense mostly for lower levels to help compensate for the newer agi based defense system. Default: False")
|
||||||
|
RULE_REAL(Combat, SlayDamageMultiplier, 1.0, "Slay Damage Adjustment - Multiply final slay damage by this value. Default: 1.0")
|
||||||
|
RULE_REAL(Combat, SlayRateMultiplier, 1.0, "Slay Rate Adjustments - Multiply final slay rate check by this value. Default: 1.0")
|
||||||
|
RULE_INT(Combat, MaximumLevelStunsCripplingBlow, 55, "Maximum level that Crippling Blows will stun a npc. Default: 55")
|
||||||
|
RULE_INT(Combat, ArcheryBaseDamage, 0, "Archery base damage, default is 0")
|
||||||
|
RULE_INT(Combat, BackstabBaseDamage, 0, "Backstab base damage, default is 0")
|
||||||
|
RULE_INT(Combat, BashBaseDamage, 2, "Bash base damage, default is 2")
|
||||||
|
RULE_INT(Combat, DragonPunchBaseDamage, 12, "Dragon Punch base damage, default is 12")
|
||||||
|
RULE_INT(Combat, EagleStrikeBaseDamage, 7, "Eagle Strike base damage, default is 7")
|
||||||
|
RULE_INT(Combat, FlyingKickBaseDamage, 25, "Flying Kick base damage, default is 25")
|
||||||
|
RULE_INT(Combat, FrenzyBaseDamage, 10, "Frenzy base damage, default is 10")
|
||||||
|
RULE_INT(Combat, KickBaseDamage, 3, "Kick base damage, default is 3")
|
||||||
|
RULE_INT(Combat, RoundKickBaseDamage, 5, "Round Kick base damage, default is 5")
|
||||||
|
RULE_INT(Combat, ThrowingBaseDamage, 0, "Throwing base damage, default is 0")
|
||||||
|
RULE_INT(Combat, TigerClawBaseDamage, 4, "Tiger Claw base damage, default is 4")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(NPC)
|
RULE_CATEGORY(NPC)
|
||||||
@@ -649,6 +677,9 @@ RULE_REAL(NPC, NPCHealOnGateAmount, 25, "How much the NPC will heal on gate if e
|
|||||||
RULE_BOOL(NPC, AnimalsOpenDoors, true, "Determines or not whether animals open doors or not when they approach them")
|
RULE_BOOL(NPC, AnimalsOpenDoors, true, "Determines or not whether animals open doors or not when they approach them")
|
||||||
RULE_INT(NPC, MaxRaceID, 732, "Maximum Race ID, RoF2 by default supports up to 732")
|
RULE_INT(NPC, MaxRaceID, 732, "Maximum Race ID, RoF2 by default supports up to 732")
|
||||||
RULE_BOOL(NPC, DisableLastNames, false, "Enable to disable NPC Last Names")
|
RULE_BOOL(NPC, DisableLastNames, false, "Enable to disable NPC Last Names")
|
||||||
|
RULE_BOOL(NPC, NPCIgnoreLevelBasedHasteCaps, false, "Ignores hard coded level based haste caps.")
|
||||||
|
RULE_INT(NPC, NPCHasteCap, 150, "Haste cap for non-v3(over haste) haste")
|
||||||
|
RULE_INT(NPC, NPCHastev3Cap, 25, "Haste cap for v3(over haste) haste")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Aggro)
|
RULE_CATEGORY(Aggro)
|
||||||
@@ -674,6 +705,7 @@ RULE_BOOL(Aggro, UndeadAlwaysAggro, true, "should undead always aggro?")
|
|||||||
RULE_INT(Aggro, BardAggroCap, 40, "per song bard aggro cap.")
|
RULE_INT(Aggro, BardAggroCap, 40, "per song bard aggro cap.")
|
||||||
RULE_INT(Aggro, InitialAggroBonus, 100, "Initial Aggro Bonus, Default: 100")
|
RULE_INT(Aggro, InitialAggroBonus, 100, "Initial Aggro Bonus, Default: 100")
|
||||||
RULE_INT(Aggro, InitialPetAggroBonus, 100, "Initial Pet Aggro Bonus, Default 100")
|
RULE_INT(Aggro, InitialPetAggroBonus, 100, "Initial Pet Aggro Bonus, Default 100")
|
||||||
|
RULE_STRING(Aggro, ExcludedFleeAllyFactionIDs, "0|5013|5014|5023|5032", "Common Faction IDs that are excluded from faction checks in EntityList::FleeAllyCount")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(TaskSystem)
|
RULE_CATEGORY(TaskSystem)
|
||||||
@@ -688,6 +720,7 @@ RULE_BOOL(TaskSystem, ExpRewardsIgnoreLevelBasedEXPMods, false, "Rewarding Level
|
|||||||
RULE_INT(TaskSystem, SharedTasksWorldProcessRate, 6000, "Timer interval (milliseconds) that shared tasks are processed in world")
|
RULE_INT(TaskSystem, SharedTasksWorldProcessRate, 6000, "Timer interval (milliseconds) that shared tasks are processed in world")
|
||||||
RULE_INT(TaskSystem, SharedTasksTerminateTimerMS, 120000, "Delay (milliseconds) until a shared task is terminated if requirements are no longer met after member removal (default: 2 minutes)")
|
RULE_INT(TaskSystem, SharedTasksTerminateTimerMS, 120000, "Delay (milliseconds) until a shared task is terminated if requirements are no longer met after member removal (default: 2 minutes)")
|
||||||
RULE_BOOL(TaskSystem, UpdateOneElementPerTask, true, "If true (live-like) task updates only increment the first matching activity. If false all matching elements will be incremented.")
|
RULE_BOOL(TaskSystem, UpdateOneElementPerTask, true, "If true (live-like) task updates only increment the first matching activity. If false all matching elements will be incremented.")
|
||||||
|
RULE_INT(TaskSystem, MaxUpdateMessages, 50, "Maximum update messages for non-GiveCash activity types in IncrementDoneCount")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Range)
|
RULE_CATEGORY(Range)
|
||||||
@@ -699,6 +732,7 @@ RULE_INT(Range, SpellParticles, 135, "The packet range in which spell particles
|
|||||||
RULE_INT(Range, DamageMessages, 50, "The packet range in which damage messages are sent (non-crit)")
|
RULE_INT(Range, DamageMessages, 50, "The packet range in which damage messages are sent (non-crit)")
|
||||||
RULE_INT(Range, SpellMessages, 75, "The packet range in which spell damage messages are sent")
|
RULE_INT(Range, SpellMessages, 75, "The packet range in which spell damage messages are sent")
|
||||||
RULE_INT(Range, SongMessages, 75, "The packet range in which song messages are sent")
|
RULE_INT(Range, SongMessages, 75, "The packet range in which song messages are sent")
|
||||||
|
RULE_INT(Range, StunMessages, 75, "The packet range in which stun messages are sent")
|
||||||
RULE_INT(Range, ClientPositionUpdates, 300, "Distance in which the own changed position is communicated to other clients")
|
RULE_INT(Range, ClientPositionUpdates, 300, "Distance in which the own changed position is communicated to other clients")
|
||||||
RULE_INT(Range, CriticalDamage, 80, "The packet range in which critical hit messages are sent")
|
RULE_INT(Range, CriticalDamage, 80, "The packet range in which critical hit messages are sent")
|
||||||
RULE_INT(Range, MobCloseScanDistance, 600, "Close scan distance")
|
RULE_INT(Range, MobCloseScanDistance, 600, "Close scan distance")
|
||||||
@@ -740,6 +774,9 @@ RULE_BOOL(Bots, CazicTouchBotsOwner, true, "Default True. Cazic Touch/DT will hi
|
|||||||
RULE_INT(Bots, BotsClickItemsMinLvl, 1, "Minimum level for bots to be able to use ^clickitem. Default 1.")
|
RULE_INT(Bots, BotsClickItemsMinLvl, 1, "Minimum level for bots to be able to use ^clickitem. Default 1.")
|
||||||
RULE_BOOL(Bots, BotsCanClickItems, true, "Enables the ability for bots to click items they have equipped. Default TRUE")
|
RULE_BOOL(Bots, BotsCanClickItems, true, "Enables the ability for bots to click items they have equipped. Default TRUE")
|
||||||
RULE_BOOL(Bots, CanClickMageEpicV1, true, "Whether or not bots are allowed to click Mage Epic 1.0. Default TRUE")
|
RULE_BOOL(Bots, CanClickMageEpicV1, true, "Whether or not bots are allowed to click Mage Epic 1.0. Default TRUE")
|
||||||
|
RULE_BOOL(Bots, BotsIgnoreLevelBasedHasteCaps, false, "Ignores hard coded level based haste caps.")
|
||||||
|
RULE_INT(Bots, BotsHasteCap, 100, "Haste cap for non-v3(over haste) haste")
|
||||||
|
RULE_INT(Bots, BotsHastev3Cap, 25, "Haste cap for v3(over haste) haste")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Chat)
|
RULE_CATEGORY(Chat)
|
||||||
@@ -786,6 +823,7 @@ RULE_INT(Bazaar, MaxBarterSearchResults, 200, "The maximum results returned in t
|
|||||||
RULE_REAL(Bazaar, ParcelDeliveryCostMod, 0.20, "Cost of parcel delivery for a bazaar purchase as a percentage of item cost. Default is 20% of item cost. RoF+ Only.")
|
RULE_REAL(Bazaar, ParcelDeliveryCostMod, 0.20, "Cost of parcel delivery for a bazaar purchase as a percentage of item cost. Default is 20% of item cost. RoF+ Only.")
|
||||||
RULE_INT(Bazaar, VoucherDeliveryCost, 200, "Number of vouchers for direct delivery for a bazaar purchase. Default is 200 vouchers. RoF+ Only.")
|
RULE_INT(Bazaar, VoucherDeliveryCost, 200, "Number of vouchers for direct delivery for a bazaar purchase. Default is 200 vouchers. RoF+ Only.")
|
||||||
RULE_BOOL(Bazaar, EnableParcelDelivery, true, "Enable bazaar purchases via parcel delivery. Default is True.")
|
RULE_BOOL(Bazaar, EnableParcelDelivery, true, "Enable bazaar purchases via parcel delivery. Default is True.")
|
||||||
|
RULE_INT(Bazaar, MaxBuyerInventorySearchResults, 200, "Maximum number of search results when a Buyer searches the global item list. Default is 200. RoF+ Only.")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Mail)
|
RULE_CATEGORY(Mail)
|
||||||
@@ -877,6 +915,7 @@ RULE_BOOL(Inventory, AllowAnyWeaponTransformation, false, "Weapons can use any w
|
|||||||
RULE_BOOL(Inventory, TransformSummonedBags, false, "Transforms summoned bags into disenchanted ones instead of deleting")
|
RULE_BOOL(Inventory, TransformSummonedBags, false, "Transforms summoned bags into disenchanted ones instead of deleting")
|
||||||
RULE_BOOL(Inventory, AllowMultipleOfSameAugment, false, "Allows multiple of the same augment to be placed in an item via #augmentitem or MQ2, set to true to allow")
|
RULE_BOOL(Inventory, AllowMultipleOfSameAugment, false, "Allows multiple of the same augment to be placed in an item via #augmentitem or MQ2, set to true to allow")
|
||||||
RULE_INT(Inventory, AlternateAugmentationSealer, 53, "Allows RoF+ clients to augment items from a special container type")
|
RULE_INT(Inventory, AlternateAugmentationSealer, 53, "Allows RoF+ clients to augment items from a special container type")
|
||||||
|
RULE_BOOL(Inventory, LazyLoadBank, true, "Don't load bank during zoning, only when in proximinity to a banker. May increase zone speed and stability")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Client)
|
RULE_CATEGORY(Client)
|
||||||
@@ -979,6 +1018,8 @@ RULE_BOOL(Items, DisableNoRent, false, "Enable this to disable No Rent Items")
|
|||||||
RULE_BOOL(Items, DisableNoTransfer, false, "Enable this to disable No Transfer Items")
|
RULE_BOOL(Items, DisableNoTransfer, false, "Enable this to disable No Transfer Items")
|
||||||
RULE_BOOL(Items, DisablePotionBelt, false, "Enable this to disable Potion Belt Items")
|
RULE_BOOL(Items, DisablePotionBelt, false, "Enable this to disable Potion Belt Items")
|
||||||
RULE_BOOL(Items, DisableSpellFocusEffects, false, "Enable this to disable Spell Focus Effects on Items")
|
RULE_BOOL(Items, DisableSpellFocusEffects, false, "Enable this to disable Spell Focus Effects on Items")
|
||||||
|
RULE_BOOL(Items, SummonItemAllowInvisibleAugments, false, "Enable this to allow augments to be put in invisible augment slots of items in Client::SummonItem")
|
||||||
|
RULE_BOOL(Items, AugmentItemAllowInvisibleAugments, false, "Enable this to allow augments to be put in invisible augment slots by players")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Parcel)
|
RULE_CATEGORY(Parcel)
|
||||||
|
|||||||
@@ -140,6 +140,7 @@
|
|||||||
|
|
||||||
#define ServerOP_TraderMessaging 0x0120
|
#define ServerOP_TraderMessaging 0x0120
|
||||||
#define ServerOP_BazaarPurchase 0x0121
|
#define ServerOP_BazaarPurchase 0x0121
|
||||||
|
#define ServerOP_BuyerMessaging 0x0122
|
||||||
|
|
||||||
#define ServerOP_InstanceUpdateTime 0x014F
|
#define ServerOP_InstanceUpdateTime 0x014F
|
||||||
#define ServerOP_AdventureRequest 0x0150
|
#define ServerOP_AdventureRequest 0x0150
|
||||||
|
|||||||
+116
-85
@@ -46,6 +46,8 @@
|
|||||||
#include "repositories/character_item_recast_repository.h"
|
#include "repositories/character_item_recast_repository.h"
|
||||||
#include "repositories/character_corpses_repository.h"
|
#include "repositories/character_corpses_repository.h"
|
||||||
#include "repositories/skill_caps_repository.h"
|
#include "repositories/skill_caps_repository.h"
|
||||||
|
#include "repositories/inventory_repository.h"
|
||||||
|
#include "repositories/books_repository.h"
|
||||||
|
|
||||||
namespace ItemField
|
namespace ItemField
|
||||||
{
|
{
|
||||||
@@ -300,15 +302,15 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const EQ::ItemInstance*
|
|||||||
// Update/Insert item
|
// Update/Insert item
|
||||||
const std::string query = StringFormat("REPLACE INTO inventory "
|
const std::string query = StringFormat("REPLACE INTO inventory "
|
||||||
"(charid, slotid, itemid, charges, instnodrop, custom_data, color, "
|
"(charid, slotid, itemid, charges, instnodrop, custom_data, color, "
|
||||||
"augslot1, augslot2, augslot3, augslot4, augslot5, augslot6, ornamenticon, ornamentidfile, ornament_hero_model) "
|
"augslot1, augslot2, augslot3, augslot4, augslot5, augslot6, ornamenticon, ornamentidfile, ornament_hero_model, guid) "
|
||||||
"VALUES( %lu, %lu, %lu, %lu, %lu, '%s', %lu, "
|
"VALUES( %lu, %lu, %lu, %lu, %lu, '%s', %lu, "
|
||||||
"%lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu)",
|
"%lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu)",
|
||||||
static_cast<unsigned long>(char_id), static_cast<unsigned long>(slot_id), static_cast<unsigned long>(inst->GetItem()->ID),
|
static_cast<unsigned long>(char_id), static_cast<unsigned long>(slot_id), static_cast<unsigned long>(inst->GetItem()->ID),
|
||||||
static_cast<unsigned long>(charges), static_cast<unsigned long>(inst->IsAttuned() ? 1 : 0),
|
static_cast<unsigned long>(charges), static_cast<unsigned long>(inst->IsAttuned() ? 1 : 0),
|
||||||
inst->GetCustomDataString().c_str(), static_cast<unsigned long>(inst->GetColor()),
|
inst->GetCustomDataString().c_str(), static_cast<unsigned long>(inst->GetColor()),
|
||||||
static_cast<unsigned long>(augslot[0]), static_cast<unsigned long>(augslot[1]), static_cast<unsigned long>(augslot[2]),
|
static_cast<unsigned long>(augslot[0]), static_cast<unsigned long>(augslot[1]), static_cast<unsigned long>(augslot[2]),
|
||||||
static_cast<unsigned long>(augslot[3]), static_cast<unsigned long>(augslot[4]), static_cast<unsigned long>(augslot[5]), static_cast<unsigned long>(inst->GetOrnamentationIcon()),
|
static_cast<unsigned long>(augslot[3]), static_cast<unsigned long>(augslot[4]), static_cast<unsigned long>(augslot[5]), static_cast<unsigned long>(inst->GetOrnamentationIcon()),
|
||||||
static_cast<unsigned long>(inst->GetOrnamentationIDFile()), static_cast<unsigned long>(inst->GetOrnamentHeroModel()));
|
static_cast<unsigned long>(inst->GetOrnamentationIDFile()), static_cast<unsigned long>(inst->GetOrnamentHeroModel()), inst->GetSerialNumber());
|
||||||
const auto results = QueryDatabase(query);
|
const auto results = QueryDatabase(query);
|
||||||
|
|
||||||
// Save bag contents, if slot supports bag contents
|
// Save bag contents, if slot supports bag contents
|
||||||
@@ -651,48 +653,67 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Retrieve character inventory
|
// Retrieve character inventory
|
||||||
const std::string query =
|
auto results = InventoryRepository::GetWhere(*this, fmt::format("`charid` = '{}' ORDER BY `slotid`;", char_id));
|
||||||
StringFormat("SELECT slotid, itemid, charges, color, augslot1, augslot2, augslot3, augslot4, augslot5, "
|
if (results.empty()) {
|
||||||
"augslot6, instnodrop, custom_data, ornamenticon, ornamentidfile, ornament_hero_model FROM "
|
LogError("Error loading inventory for char_id {} from the database.", char_id);
|
||||||
"inventory WHERE charid = %i ORDER BY slotid",
|
|
||||||
char_id);
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
if (!results.Success()) {
|
|
||||||
LogError("If you got an error related to the 'instnodrop' field, run the "
|
|
||||||
"following SQL Queries:\nalter table inventory add instnodrop "
|
|
||||||
"tinyint(1) unsigned default 0 not null;\n");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto const &row: results) {
|
||||||
|
if (row.guid != 0) {
|
||||||
|
EQ::ItemInstance::AddGUIDToMap(row.guid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const auto timestamps = GetItemRecastTimestamps(char_id);
|
const auto timestamps = GetItemRecastTimestamps(char_id);
|
||||||
|
auto cv_conflict = false;
|
||||||
|
const auto pmask = inv->GetLookup()->PossessionsBitmask;
|
||||||
|
const auto bank_size = inv->GetLookup()->InventoryTypeSize.Bank;
|
||||||
|
|
||||||
auto cv_conflict = false;
|
std::vector<InventoryRepository::Inventory> queue{};
|
||||||
const auto pmask = inv->GetLookup()->PossessionsBitmask;
|
for (auto &row: results) {
|
||||||
const auto bank_size = inv->GetLookup()->InventoryTypeSize.Bank;
|
const int16 slot_id = row.slotid;
|
||||||
|
const uint32 item_id = row.itemid;
|
||||||
|
const uint16 charges = row.charges;
|
||||||
|
const uint32 color = row.color;
|
||||||
|
const bool instnodrop = row.instnodrop;
|
||||||
|
const uint32 ornament_icon = row.ornamenticon;
|
||||||
|
const uint32 ornament_idfile = row.ornamentidfile;
|
||||||
|
const uint32 ornament_hero_model = row.ornament_hero_model;
|
||||||
|
|
||||||
for (auto& row = results.begin(); row != results.end(); ++row) {
|
uint32 aug[EQ::invaug::SOCKET_COUNT];
|
||||||
int16 slot_id = Strings::ToInt(row[0]);
|
aug[0] = row.augslot1;
|
||||||
|
aug[1] = row.augslot2;
|
||||||
|
aug[2] = row.augslot3;
|
||||||
|
aug[3] = row.augslot4;
|
||||||
|
aug[4] = row.augslot5;
|
||||||
|
aug[5] = row.augslot6;
|
||||||
|
|
||||||
if (slot_id <= EQ::invslot::POSSESSIONS_END && slot_id >= EQ::invslot::POSSESSIONS_BEGIN) { // Titanium thru UF check
|
if (slot_id <= EQ::invslot::POSSESSIONS_END && slot_id >= EQ::invslot::POSSESSIONS_BEGIN) {
|
||||||
|
// Titanium thru UF check
|
||||||
if (((static_cast<uint64>(1) << slot_id) & pmask) == 0) {
|
if (((static_cast<uint64>(1) << slot_id) & pmask) == 0) {
|
||||||
cv_conflict = true;
|
cv_conflict = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (slot_id <= EQ::invbag::GENERAL_BAGS_END && slot_id >= EQ::invbag::GENERAL_BAGS_BEGIN) { // Titanium thru UF check
|
else if (slot_id <= EQ::invbag::GENERAL_BAGS_END && slot_id >= EQ::invbag::GENERAL_BAGS_BEGIN) {
|
||||||
const auto parent_slot = EQ::invslot::GENERAL_BEGIN + ((slot_id - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT);
|
// Titanium thru UF check
|
||||||
|
const auto parent_slot = EQ::invslot::GENERAL_BEGIN + (
|
||||||
|
(slot_id - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT);
|
||||||
if (((static_cast<uint64>(1) << parent_slot) & pmask) == 0) {
|
if (((static_cast<uint64>(1) << parent_slot) & pmask) == 0) {
|
||||||
cv_conflict = true;
|
cv_conflict = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (slot_id <= EQ::invslot::BANK_END && slot_id >= EQ::invslot::BANK_BEGIN) { // Titanium check
|
else if (slot_id <= EQ::invslot::BANK_END && slot_id >= EQ::invslot::BANK_BEGIN) {
|
||||||
|
// Titanium check
|
||||||
if ((slot_id - EQ::invslot::BANK_BEGIN) >= bank_size) {
|
if ((slot_id - EQ::invslot::BANK_BEGIN) >= bank_size) {
|
||||||
cv_conflict = true;
|
cv_conflict = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (slot_id <= EQ::invbag::BANK_BAGS_END && slot_id >= EQ::invbag::BANK_BAGS_BEGIN) { // Titanium check
|
else if (slot_id <= EQ::invbag::BANK_BAGS_END && slot_id >= EQ::invbag::BANK_BAGS_BEGIN) {
|
||||||
|
// Titanium check
|
||||||
const auto parent_index = ((slot_id - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT);
|
const auto parent_index = ((slot_id - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT);
|
||||||
if (parent_index >= bank_size) {
|
if (parent_index >= bank_size) {
|
||||||
cv_conflict = true;
|
cv_conflict = true;
|
||||||
@@ -700,64 +721,55 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 item_id = Strings::ToUnsignedInt(row[1]);
|
auto *item = GetItem(item_id);
|
||||||
const uint16 charges = Strings::ToUnsignedInt(row[2]);
|
|
||||||
const uint32 color = Strings::ToUnsignedInt(row[3]);
|
|
||||||
|
|
||||||
uint32 aug[EQ::invaug::SOCKET_COUNT];
|
|
||||||
|
|
||||||
aug[0] = Strings::ToUnsignedInt(row[4]);
|
|
||||||
aug[1] = Strings::ToUnsignedInt(row[5]);
|
|
||||||
aug[2] = Strings::ToUnsignedInt(row[6]);
|
|
||||||
aug[3] = Strings::ToUnsignedInt(row[7]);
|
|
||||||
aug[4] = Strings::ToUnsignedInt(row[8]);
|
|
||||||
aug[5] = Strings::ToUnsignedInt(row[9]);
|
|
||||||
|
|
||||||
const bool instnodrop = (row[10] && static_cast<uint16>(Strings::ToUnsignedInt(row[10])));
|
|
||||||
|
|
||||||
const uint32 ornament_icon = Strings::ToUnsignedInt(row[12]);
|
|
||||||
const uint32 ornament_idfile = Strings::ToUnsignedInt(row[13]);
|
|
||||||
uint32 ornament_hero_model = Strings::ToUnsignedInt(row[14]);
|
|
||||||
|
|
||||||
const EQ::ItemData *item = GetItem(item_id);
|
|
||||||
|
|
||||||
if (!item) {
|
if (!item) {
|
||||||
LogError("Warning: charid [{}] has an invalid item_id [{}] in inventory slot [{}]", char_id, item_id,
|
LogError(
|
||||||
slot_id);
|
"Warning: charid [{}] has an invalid item_id [{}] in inventory slot [{}]",
|
||||||
|
char_id,
|
||||||
|
item_id,
|
||||||
|
slot_id
|
||||||
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQ::ItemInstance *inst = CreateBaseItem(item, charges);
|
auto *inst = CreateBaseItem(item, charges);
|
||||||
|
if (!inst) {
|
||||||
if (inst == nullptr)
|
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (row[11]) {
|
if (!row.custom_data.empty()) {
|
||||||
std::string data_str(row[11]);
|
inst->SetCustomDataString(row.custom_data);
|
||||||
inst->SetCustomDataString(data_str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inst->SetOrnamentIcon(ornament_icon);
|
inst->SetOrnamentIcon(ornament_icon);
|
||||||
inst->SetOrnamentationIDFile(ornament_idfile);
|
inst->SetOrnamentationIDFile(ornament_idfile);
|
||||||
inst->SetOrnamentHeroModel(item->HerosForgeModel);
|
inst->SetOrnamentHeroModel(item->HerosForgeModel);
|
||||||
|
|
||||||
if (instnodrop || (inst->GetItem()->Attuneable && slot_id >= EQ::invslot::EQUIPMENT_BEGIN && slot_id <= EQ::invslot::EQUIPMENT_END))
|
if (instnodrop || (inst->GetItem()->Attuneable && slot_id >= EQ::invslot::EQUIPMENT_BEGIN && slot_id <=
|
||||||
|
EQ::invslot::EQUIPMENT_END)) {
|
||||||
inst->SetAttuned(true);
|
inst->SetAttuned(true);
|
||||||
|
}
|
||||||
|
|
||||||
if (color > 0)
|
if (color > 0) {
|
||||||
inst->SetColor(color);
|
inst->SetColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
if (charges == 0x7FFF)
|
if (charges == 0x7FFF) {
|
||||||
inst->SetCharges(-1);
|
inst->SetCharges(-1);
|
||||||
else if (charges == 0 && inst->IsStackable()) // Stackable items need a minimum charge of 1 remain moveable.
|
}
|
||||||
|
else if (charges == 0 && inst->IsStackable()) {
|
||||||
|
// Stackable items need a minimum charge of 1 remain moveable.
|
||||||
inst->SetCharges(1);
|
inst->SetCharges(1);
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
inst->SetCharges(charges);
|
inst->SetCharges(charges);
|
||||||
|
}
|
||||||
|
|
||||||
if (item->RecastDelay) {
|
if (item->RecastDelay) {
|
||||||
if (item->RecastType != RECAST_TYPE_UNLINKED_ITEM && timestamps.count(item->RecastType)) {
|
if (item->RecastType != RECAST_TYPE_UNLINKED_ITEM && timestamps.count(item->RecastType)) {
|
||||||
inst->SetRecastTimestamp(timestamps.at(item->RecastType));
|
inst->SetRecastTimestamp(timestamps.at(item->RecastType));
|
||||||
} else if (item->RecastType == RECAST_TYPE_UNLINKED_ITEM && timestamps.count(item->ID)) {
|
}
|
||||||
|
else if (item->RecastType == RECAST_TYPE_UNLINKED_ITEM && timestamps.count(item->ID)) {
|
||||||
inst->SetRecastTimestamp(timestamps.at(item->ID));
|
inst->SetRecastTimestamp(timestamps.at(item->ID));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -767,35 +779,50 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
|
|||||||
|
|
||||||
if (item->IsClassCommon()) {
|
if (item->IsClassCommon()) {
|
||||||
for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) {
|
for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) {
|
||||||
if (aug[i])
|
if (aug[i]) {
|
||||||
inst->PutAugment(this, i, aug[i]);
|
inst->PutAugment(this, i, aug[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int16 put_slot_id;
|
int16 put_slot_id;
|
||||||
if (slot_id >= 8000 && slot_id <= 8999) {
|
if (slot_id >= 8000 && slot_id <= 8999) {
|
||||||
put_slot_id = inv->PushCursor(*inst);
|
put_slot_id = inv->PushCursor(*inst);
|
||||||
} else if (slot_id >= 3111 && slot_id <= 3179) {
|
}
|
||||||
|
else if (slot_id >= 3111 && slot_id <= 3179) {
|
||||||
// Admins: please report any occurrences of this error
|
// Admins: please report any occurrences of this error
|
||||||
LogError("Warning: Defunct location for item in inventory: charid={}, item_id={}, slot_id={} .. pushing to cursor...",
|
LogError(
|
||||||
char_id, item_id, slot_id);
|
"Warning: Defunct location for item in inventory: charid={}, item_id={}, slot_id={} .. pushing to cursor...",
|
||||||
|
char_id,
|
||||||
|
item_id,
|
||||||
|
slot_id
|
||||||
|
);
|
||||||
put_slot_id = inv->PushCursor(*inst);
|
put_slot_id = inv->PushCursor(*inst);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
put_slot_id = inv->PutItem(slot_id, *inst);
|
put_slot_id = inv->PutItem(slot_id, *inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
row.guid = inst->GetSerialNumber();
|
||||||
|
queue.push_back(row);
|
||||||
|
|
||||||
safe_delete(inst);
|
safe_delete(inst);
|
||||||
|
|
||||||
// Save ptr to item in inventory
|
// Save ptr to item in inventory
|
||||||
if (put_slot_id == INVALID_INDEX) {
|
if (put_slot_id == INVALID_INDEX) {
|
||||||
LogError("Warning: Invalid slot_id for item in inventory: charid=[{}], item_id=[{}], slot_id=[{}]",
|
LogError(
|
||||||
char_id, item_id, slot_id);
|
"Warning: Invalid slot_id for item in inventory: charid=[{}], item_id=[{}], slot_id=[{}]",
|
||||||
|
char_id,
|
||||||
|
item_id,
|
||||||
|
slot_id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cv_conflict) {
|
if (cv_conflict) {
|
||||||
const std::string& char_name = GetCharName(char_id);
|
const std::string &char_name = GetCharName(char_id);
|
||||||
LogError("ClientVersion/Expansion conflict during inventory load at zone entry for [{}] (charid: [{}], inver: [{}], gmi: [{}])",
|
LogError(
|
||||||
|
"ClientVersion/Expansion conflict during inventory load at zone entry for [{}] (charid: [{}], inver: [{}], gmi: [{}])",
|
||||||
char_name,
|
char_name,
|
||||||
char_id,
|
char_id,
|
||||||
EQ::versions::MobVersionName(inv->InventoryVersion()),
|
EQ::versions::MobVersionName(inv->InventoryVersion()),
|
||||||
@@ -803,6 +830,12 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!queue.empty()) {
|
||||||
|
InventoryRepository::ReplaceMany(*this, queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
EQ::ItemInstance::ClearGUIDMap();
|
||||||
|
|
||||||
// Retrieve shared inventory
|
// Retrieve shared inventory
|
||||||
return GetSharedBank(char_id, inv, true);
|
return GetSharedBank(char_id, inv, true);
|
||||||
}
|
}
|
||||||
@@ -1359,30 +1392,28 @@ const EQ::ItemData* SharedDatabase::IterateItems(uint32* id) const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SharedDatabase::GetBook(const char *txtfile, int16 *language)
|
Book_Struct SharedDatabase::GetBook(const std::string& text_file)
|
||||||
{
|
{
|
||||||
char txtfile2[20];
|
const auto& l = BooksRepository::GetWhere(
|
||||||
std::string txtout;
|
*this,
|
||||||
strcpy(txtfile2, txtfile);
|
fmt::format(
|
||||||
|
"`name` = '{}'",
|
||||||
|
Strings::Escape(text_file)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
const std::string query = StringFormat("SELECT txtfile, language FROM books WHERE name = '%s'", txtfile2);
|
Book_Struct b;
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
if (!results.Success()) {
|
if (l.empty()) {
|
||||||
txtout.assign(" ",1);
|
return b;
|
||||||
return txtout;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results.RowCount() == 0) {
|
const auto& e = l.front();
|
||||||
LogError("No book to send, ({})", txtfile);
|
|
||||||
txtout.assign(" ",1);
|
|
||||||
return txtout;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& row = results.begin();
|
b.language = e.language;
|
||||||
txtout.assign(row[0],strlen(row[0]));
|
b.text = e.txtfile;
|
||||||
*language = static_cast<int16>(Strings::ToInt(row[1]));
|
|
||||||
|
|
||||||
return txtout;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create appropriate EQ::ItemInstance class
|
// Create appropriate EQ::ItemInstance class
|
||||||
|
|||||||
+8
-3
@@ -41,8 +41,7 @@ struct NPCFactionList;
|
|||||||
struct FactionAssociations;
|
struct FactionAssociations;
|
||||||
|
|
||||||
|
|
||||||
namespace EQ
|
namespace EQ {
|
||||||
{
|
|
||||||
|
|
||||||
struct ItemData;
|
struct ItemData;
|
||||||
class ItemInstance;
|
class ItemInstance;
|
||||||
@@ -50,6 +49,12 @@ namespace EQ
|
|||||||
class MemoryMappedFile;
|
class MemoryMappedFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Book_Struct
|
||||||
|
{
|
||||||
|
uint8 language;
|
||||||
|
std::string text;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This object is inherited by world and zone's DB object,
|
This object is inherited by world and zone's DB object,
|
||||||
and is mainly here to facilitate shared memory, and other
|
and is mainly here to facilitate shared memory, and other
|
||||||
@@ -114,7 +119,7 @@ public:
|
|||||||
int admin
|
int admin
|
||||||
);
|
);
|
||||||
|
|
||||||
std::string GetBook(const char *txtfile, int16 *language);
|
Book_Struct GetBook(const std::string& text_file);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* items
|
* items
|
||||||
|
|||||||
+55
-20
@@ -1,4 +1,14 @@
|
|||||||
#include "skill_caps.h"
|
#include "skill_caps.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
|
// cache the skill cap max level in the database
|
||||||
|
std::map<uint8_t, int32_t> skill_max_level = {};
|
||||||
|
|
||||||
|
uint8 skill_cap_max_level = (
|
||||||
|
RuleI(Character, SkillCapMaxLevel) > 0 ?
|
||||||
|
RuleI(Character, SkillCapMaxLevel) :
|
||||||
|
RuleI(Character, MaxLevel)
|
||||||
|
);
|
||||||
|
|
||||||
SkillCaps *SkillCaps::SetContentDatabase(Database *db)
|
SkillCaps *SkillCaps::SetContentDatabase(Database *db)
|
||||||
{
|
{
|
||||||
@@ -7,21 +17,38 @@ SkillCaps *SkillCaps::SetContentDatabase(Database *db)
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t SkillCaps::GetSkillCapMaxLevel(uint8 class_id, EQ::skills::SkillType skill_id)
|
||||||
|
{
|
||||||
|
// pull the max value defined in the database if it exists
|
||||||
|
auto it = skill_max_level.find((class_id * 1000000) + skill_id);
|
||||||
|
if (it != skill_max_level.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return skill_cap_max_level;
|
||||||
|
}
|
||||||
|
|
||||||
SkillCapsRepository::SkillCaps SkillCaps::GetSkillCap(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level)
|
SkillCapsRepository::SkillCaps SkillCaps::GetSkillCap(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level)
|
||||||
{
|
{
|
||||||
if (!IsPlayerClass(class_id)) {
|
if (!IsPlayerClass(class_id) || static_cast<uint32>(skill_id) > EQ::skills::HIGHEST_SKILL + 1) {
|
||||||
return SkillCapsRepository::NewEntity();
|
return SkillCapsRepository::NewEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t key = (class_id * 1000000) + (level * 1000) + static_cast<uint32>(skill_id);
|
const uint8 max_level = GetSkillCapMaxLevel(class_id, skill_id);
|
||||||
auto pos = m_skill_caps.find(key);
|
if (level > max_level) {
|
||||||
|
level = max_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint64_t key = (class_id * 1000000) + (level * 1000) + static_cast<uint32>(skill_id);
|
||||||
|
auto pos = m_skill_caps.find(key);
|
||||||
if (pos != m_skill_caps.end()) {
|
if (pos != m_skill_caps.end()) {
|
||||||
return pos->second;
|
return pos->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SkillCapsRepository::NewEntity();
|
return SkillCapsRepository::NewEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SkillCaps::GetTrainLevel(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level)
|
uint8 SkillCaps::GetSkillTrainLevel(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
!IsPlayerClass(class_id) ||
|
!IsPlayerClass(class_id) ||
|
||||||
@@ -31,21 +58,12 @@ uint8 SkillCaps::GetTrainLevel(uint8 class_id, EQ::skills::SkillType skill_id, u
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8 skill_cap_max_level = (
|
const uint8 max_level = level > skill_cap_max_level ? level : skill_cap_max_level;
|
||||||
RuleI(Character, SkillCapMaxLevel) > 0 ?
|
const uint64_t key = (class_id * 1000000) + (level * 1000) + static_cast<uint32>(skill_id);
|
||||||
RuleI(Character, SkillCapMaxLevel) :
|
for (uint8 current_level = 1; current_level <= max_level; current_level++) {
|
||||||
RuleI(Character, MaxLevel)
|
auto pos = m_skill_caps.find(key);
|
||||||
);
|
if (pos != m_skill_caps.end()) {
|
||||||
|
return current_level;
|
||||||
const uint8 max_level = level > skill_cap_max_level ? level : skill_cap_max_level;
|
|
||||||
|
|
||||||
for (const auto &e: m_skill_caps) {
|
|
||||||
for (uint8 current_level = 1; current_level <= max_level; current_level++) {
|
|
||||||
uint64_t key = (class_id * 1000000) + (level * 1000) + static_cast<uint32>(skill_id);
|
|
||||||
auto pos = m_skill_caps.find(key);
|
|
||||||
if (pos != m_skill_caps.end()) {
|
|
||||||
return current_level;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,8 +85,25 @@ void SkillCaps::LoadSkillCaps()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t key = (e.class_id * 1000000) + (e.level * 1000) + e.skill_id;
|
const uint64_t key = (e.class_id * 1000000) + (e.level * 1000) + e.skill_id;
|
||||||
m_skill_caps[key] = e;
|
m_skill_caps[key] = e;
|
||||||
|
|
||||||
|
const int max_level_key = (e.class_id * 1000000) + e.skill_id;
|
||||||
|
auto it = skill_max_level.find(max_level_key);
|
||||||
|
if (it != skill_max_level.end()) {
|
||||||
|
// Key found, update the value if the new level is higher
|
||||||
|
if (e.level > it->second) {
|
||||||
|
it->second = e.level;
|
||||||
|
}
|
||||||
|
// we never want to exceed the defined rule skill cap max level
|
||||||
|
if (it->second > skill_cap_max_level) {
|
||||||
|
it->second = skill_cap_max_level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Key not found, insert the new key-value pair
|
||||||
|
skill_max_level[max_level_key] = e.level;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LogInfo(
|
LogInfo(
|
||||||
|
|||||||
+2
-1
@@ -10,9 +10,10 @@ class SkillCaps {
|
|||||||
public:
|
public:
|
||||||
inline void ClearSkillCaps() { m_skill_caps.clear(); }
|
inline void ClearSkillCaps() { m_skill_caps.clear(); }
|
||||||
SkillCapsRepository::SkillCaps GetSkillCap(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level);
|
SkillCapsRepository::SkillCaps GetSkillCap(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level);
|
||||||
uint8 GetTrainLevel(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level);
|
uint8 GetSkillTrainLevel(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level);
|
||||||
void LoadSkillCaps();
|
void LoadSkillCaps();
|
||||||
void ReloadSkillCaps();
|
void ReloadSkillCaps();
|
||||||
|
static int32_t GetSkillCapMaxLevel(uint8 class_id, EQ::skills::SkillType skill_id);
|
||||||
|
|
||||||
SkillCaps *SetContentDatabase(Database *db);
|
SkillCaps *SetContentDatabase(Database *db);
|
||||||
private:
|
private:
|
||||||
|
|||||||
+24
-19
@@ -127,24 +127,30 @@ bool EQ::skills::IsCastingSkill(SkillType skill)
|
|||||||
int32 EQ::skills::GetBaseDamage(SkillType skill)
|
int32 EQ::skills::GetBaseDamage(SkillType skill)
|
||||||
{
|
{
|
||||||
switch (skill) {
|
switch (skill) {
|
||||||
case SkillBash:
|
case SkillArchery:
|
||||||
return 2;
|
return RuleI(Combat, ArcheryBaseDamage);
|
||||||
case SkillDragonPunch:
|
case SkillBackstab:
|
||||||
return 12;
|
return RuleI(Combat, BackstabBaseDamage);
|
||||||
case SkillEagleStrike:
|
case SkillBash:
|
||||||
return 7;
|
return RuleI(Combat, BashBaseDamage);
|
||||||
case SkillFlyingKick:
|
case SkillDragonPunch:
|
||||||
return 25;
|
return RuleI(Combat, DragonPunchBaseDamage);
|
||||||
case SkillKick:
|
case SkillEagleStrike:
|
||||||
return 3;
|
return RuleI(Combat, EagleStrikeBaseDamage);
|
||||||
case SkillRoundKick:
|
case SkillFlyingKick:
|
||||||
return 5;
|
return RuleI(Combat, FlyingKickBaseDamage);
|
||||||
case SkillTigerClaw:
|
case SkillFrenzy:
|
||||||
return 4;
|
return RuleI(Combat, FrenzyBaseDamage);
|
||||||
case SkillFrenzy:
|
case SkillKick:
|
||||||
return 10;
|
return RuleI(Combat, KickBaseDamage);
|
||||||
default:
|
case SkillRoundKick:
|
||||||
return 0;
|
return RuleI(Combat, RoundKickBaseDamage);
|
||||||
|
case SkillThrowing:
|
||||||
|
return RuleI(Combat, ThrowingBaseDamage);
|
||||||
|
case SkillTigerClaw:
|
||||||
|
return RuleI(Combat, TigerClawBaseDamage);
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,7 +249,6 @@ const std::vector<EQ::skills::SkillType>& EQ::skills::GetExtraDamageSkills()
|
|||||||
EQ::skills::SkillFlyingKick,
|
EQ::skills::SkillFlyingKick,
|
||||||
EQ::skills::SkillKick,
|
EQ::skills::SkillKick,
|
||||||
EQ::skills::SkillRoundKick,
|
EQ::skills::SkillRoundKick,
|
||||||
EQ::skills::SkillRoundKick,
|
|
||||||
EQ::skills::SkillTigerClaw,
|
EQ::skills::SkillTigerClaw,
|
||||||
EQ::skills::SkillFrenzy
|
EQ::skills::SkillFrenzy
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -431,6 +431,16 @@ bool IsCharmSpell(uint16 spell_id)
|
|||||||
return IsEffectInSpell(spell_id, SE_Charm);
|
return IsEffectInSpell(spell_id, SE_Charm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsResurrectionSicknessSpell(uint16 spell_id) {
|
||||||
|
return (
|
||||||
|
spell_id == SPELL_RESURRECTION_SICKNESS ||
|
||||||
|
spell_id == SPELL_RESURRECTION_SICKNESS2 ||
|
||||||
|
spell_id == SPELL_RESURRECTION_SICKNESS3 ||
|
||||||
|
spell_id == SPELL_RESURRECTION_SICKNESS4 ||
|
||||||
|
spell_id == SPELL_REVIVAL_SICKNESS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsBlindSpell(uint16 spell_id)
|
bool IsBlindSpell(uint16 spell_id)
|
||||||
{
|
{
|
||||||
return IsEffectInSpell(spell_id, SE_Blind);
|
return IsEffectInSpell(spell_id, SE_Blind);
|
||||||
@@ -2315,3 +2325,108 @@ bool IsCastNotStandingSpell(uint16 spell_id) {
|
|||||||
*/
|
*/
|
||||||
return spells[spell_id].cast_not_standing;
|
return spells[spell_id].cast_not_standing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsAegolismSpell(uint16 spell_id) {
|
||||||
|
|
||||||
|
if (!IsValidSpell(spell_id)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_max_hp = false;
|
||||||
|
bool has_current_hp = false;
|
||||||
|
bool has_ac = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < EFFECT_COUNT; ++i) {
|
||||||
|
|
||||||
|
if (i == 0 && spells[spell_id].effect_id[i] != SE_StackingCommand_Block) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 1 && spells[spell_id].effect_id[i] == SE_TotalHP) {
|
||||||
|
has_max_hp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 2 && spells[spell_id].effect_id[i] == SE_CurrentHPOnce) {
|
||||||
|
has_current_hp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 3 && spells[spell_id].effect_id[i] == SE_ArmorClass) {
|
||||||
|
has_ac = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 4 && spells[spell_id].effect_id[i] != SE_StackingCommand_Overwrite) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_max_hp && has_current_hp && has_ac) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool AegolismStackingIsSymbolSpell(uint16 spell_id) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is hardcoded to be specific to the type of HP buffs that are removed if a mob has an Aegolism buff.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!IsValidSpell(spell_id)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_max_hp = false;
|
||||||
|
bool has_current_hp = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < EFFECT_COUNT; ++i) {
|
||||||
|
|
||||||
|
if ((i < 2 && spells[spell_id].effect_id[i] != SE_CHA) ||
|
||||||
|
i > 3 && spells[spell_id].effect_id[i] != SE_Blank) {
|
||||||
|
return 0;;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 2 && spells[spell_id].effect_id[i] == SE_TotalHP) {
|
||||||
|
has_max_hp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 3 && spells[spell_id].effect_id[i] == SE_CurrentHPOnce) {
|
||||||
|
has_current_hp = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_max_hp && has_current_hp) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AegolismStackingIsArmorClassSpell(uint16 spell_id) {
|
||||||
|
/*
|
||||||
|
This is hardcoded to be specific to the type of AC buffs that are removed if a mob has an Aegolism buff.
|
||||||
|
*/
|
||||||
|
if (!IsValidSpell(spell_id)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_ac = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < EFFECT_COUNT; ++i) {
|
||||||
|
|
||||||
|
if ((i < 3 && spells[spell_id].effect_id[i] != SE_CHA) ||
|
||||||
|
i > 3 && spells[spell_id].effect_id[i] != SE_Blank) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 3 && spells[spell_id].effect_id[i] == SE_ArmorClass) {
|
||||||
|
has_ac = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_ac) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1522,6 +1522,7 @@ bool IsSummonPetSpell(uint16 spell_id);
|
|||||||
bool IsSummonPCSpell(uint16 spell_id);
|
bool IsSummonPCSpell(uint16 spell_id);
|
||||||
bool IsPetSpell(uint16 spell_id);
|
bool IsPetSpell(uint16 spell_id);
|
||||||
bool IsCharmSpell(uint16 spell_id);
|
bool IsCharmSpell(uint16 spell_id);
|
||||||
|
bool IsResurrectionSicknessSpell(uint16 spell_id);
|
||||||
bool IsBlindSpell(uint16 spell_id);
|
bool IsBlindSpell(uint16 spell_id);
|
||||||
bool IsHealthSpell(uint16 spell_id);
|
bool IsHealthSpell(uint16 spell_id);
|
||||||
bool IsCastTimeReductionSpell(uint16 spell_id);
|
bool IsCastTimeReductionSpell(uint16 spell_id);
|
||||||
@@ -1624,5 +1625,8 @@ bool IsSpellUsableInThisZoneType(uint16 spell_id, uint8 zone_type);
|
|||||||
const char *GetSpellName(uint16 spell_id);
|
const char *GetSpellName(uint16 spell_id);
|
||||||
int GetSpellStatValue(uint16 spell_id, const char* stat_identifier, uint8 slot = 0);
|
int GetSpellStatValue(uint16 spell_id, const char* stat_identifier, uint8 slot = 0);
|
||||||
bool IsCastRestrictedSpell(uint16 spell_id);
|
bool IsCastRestrictedSpell(uint16 spell_id);
|
||||||
|
bool IsAegolismSpell(uint16 spell_id);
|
||||||
|
bool AegolismStackingIsSymbolSpell(uint16 spell_id);
|
||||||
|
bool AegolismStackingIsArmorClassSpell(uint16 spell_id);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+3
-3
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
// Build variables
|
// Build variables
|
||||||
// these get injected during the build pipeline
|
// these get injected during the build pipeline
|
||||||
#define CURRENT_VERSION "22.51.0-dev" // always append -dev to the current version for custom-builds
|
#define CURRENT_VERSION "22.56.3-dev" // always append -dev to the current version for custom-builds
|
||||||
#define LOGIN_VERSION "0.8.0"
|
#define LOGIN_VERSION "0.8.0"
|
||||||
#define COMPILE_DATE __DATE__
|
#define COMPILE_DATE __DATE__
|
||||||
#define COMPILE_TIME __TIME__
|
#define COMPILE_TIME __TIME__
|
||||||
@@ -42,8 +42,8 @@
|
|||||||
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CURRENT_BINARY_DATABASE_VERSION 9280
|
#define CURRENT_BINARY_DATABASE_VERSION 9284
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9044
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9045
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+42
-3
@@ -224,6 +224,23 @@ void Client::Handle_Login(const char *data, unsigned int size)
|
|||||||
if (server.db->GetLoginDataFromAccountInfo(user, db_loginserver, db_account_password_hash, db_account_id)) {
|
if (server.db->GetLoginDataFromAccountInfo(user, db_loginserver, db_account_password_hash, db_account_id)) {
|
||||||
result = VerifyLoginHash(user, db_loginserver, cred, db_account_password_hash);
|
result = VerifyLoginHash(user, db_loginserver, cred, db_account_password_hash);
|
||||||
|
|
||||||
|
#ifdef LSPX
|
||||||
|
// if user updated their password on the login server, update it here by validating their credentials with the login server
|
||||||
|
if (!result && db_loginserver == "eqemu") {
|
||||||
|
uint32 account_id = AccountManagement::CheckExternalLoginserverUserCredentials(user, cred);
|
||||||
|
if (account_id > 0) {
|
||||||
|
auto encryption_mode = server.options.GetEncryptionMode();
|
||||||
|
server.db->UpdateLoginserverAccountPasswordHash(
|
||||||
|
user,
|
||||||
|
db_loginserver,
|
||||||
|
eqcrypt_hash(user, cred, encryption_mode)
|
||||||
|
);
|
||||||
|
LogInfo("Updating eqemu account [{}] password hash", account_id);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
LogDebug("Success [{0}]", (result ? "true" : "false"));
|
LogDebug("Success [{0}]", (result ? "true" : "false"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -556,10 +573,13 @@ void Client::SendExpansionPacketData(PlayerLoginReply_Struct& plrs)
|
|||||||
{
|
{
|
||||||
SerializeBuffer buf;
|
SerializeBuffer buf;
|
||||||
//from eqlsstr_us.txt id of each expansion, excluding 'Everquest'
|
//from eqlsstr_us.txt id of each expansion, excluding 'Everquest'
|
||||||
int ExpansionLookup[20] = { 3007, 3008, 3009, 3010, 3012,
|
int ExpansionLookup[30] = { 3007, 3008, 3009, 3010, 3012,
|
||||||
3014, 3031, 3033, 3036, 3040,
|
3014, 3031, 3033, 3036, 3040,
|
||||||
3045, 3046, 3047, 3514, 3516,
|
3045, 3046, 3047, 3514, 3516,
|
||||||
3518, 3520, 3522, 3524 };
|
3518, 3520, 3522, 3524, 3526,
|
||||||
|
3528, 3530, 3532, 3534, 3535,
|
||||||
|
3536, 3537, 3538, 3539, 3540
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
if (server.options.IsDisplayExpansions()) {
|
if (server.options.IsDisplayExpansions()) {
|
||||||
@@ -567,7 +587,26 @@ void Client::SendExpansionPacketData(PlayerLoginReply_Struct& plrs)
|
|||||||
int32_t expansion = server.options.GetMaxExpansions();
|
int32_t expansion = server.options.GetMaxExpansions();
|
||||||
int32_t owned_expansion = (expansion << 1) | 1;
|
int32_t owned_expansion = (expansion << 1) | 1;
|
||||||
|
|
||||||
if (m_client_version == cv_sod) {
|
if (m_client_version == cv_larion) {
|
||||||
|
buf.WriteInt32(0x00);
|
||||||
|
buf.WriteInt32(0x00);
|
||||||
|
buf.WriteInt16(0x00);
|
||||||
|
buf.WriteInt32(30);
|
||||||
|
|
||||||
|
for (int i = 0; i < 30; i++)
|
||||||
|
{
|
||||||
|
buf.WriteUInt32(i + 1);
|
||||||
|
buf.WriteUInt8(1);
|
||||||
|
buf.WriteInt32(ExpansionLookup[i]);
|
||||||
|
buf.WriteInt32(6046);
|
||||||
|
buf.WriteUInt32(0xFFFFFFFF);
|
||||||
|
buf.WriteUInt32(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto out = std::make_unique<EQApplicationPacket>(OP_LoginExpansionPacketData, buf);
|
||||||
|
m_connection->QueuePacket(out.get());
|
||||||
|
}
|
||||||
|
else if (m_client_version == cv_sod) {
|
||||||
|
|
||||||
// header info of packet. Requires OP_LoginExpansionPacketData=0x0031 to be in login_opcodes_sod.conf
|
// header info of packet. Requires OP_LoginExpansionPacketData=0x0031 to be in login_opcodes_sod.conf
|
||||||
buf.WriteInt32(0x00);
|
buf.WriteInt32(0x00);
|
||||||
|
|||||||
@@ -138,6 +138,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
unsigned int GetPlaySequence() const { return m_play_sequence_id; }
|
unsigned int GetPlaySequence() const { return m_play_sequence_id; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the client version
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
LSClientVersion GetClientVersion() const { return m_client_version; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the connection for this client
|
* Gets the connection for this client
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -88,6 +88,46 @@ ClientManager::ClientManager()
|
|||||||
clients.push_back(c);
|
clients.push_back(c);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
int larion_port = server.config.GetVariableInt("client_configuration", "larion_port", 15900);
|
||||||
|
|
||||||
|
EQStreamManagerInterfaceOptions larion_opts(larion_port, false, false);
|
||||||
|
|
||||||
|
larion_stream = new EQ::Net::EQStreamManager(larion_opts);
|
||||||
|
larion_ops = new RegularOpcodeManager;
|
||||||
|
|
||||||
|
opcodes_path = fmt::format(
|
||||||
|
"{}/{}",
|
||||||
|
path.GetServerPath(),
|
||||||
|
server.config.GetVariableString(
|
||||||
|
"client_configuration",
|
||||||
|
"larion_opcodes",
|
||||||
|
"login_opcodes.conf"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!larion_ops->LoadOpcodes(opcodes_path.c_str())) {
|
||||||
|
LogError(
|
||||||
|
"ClientManager fatal error: couldn't load opcodes for Larion file [{0}]",
|
||||||
|
server.config.GetVariableString("client_configuration", "larion_opcodes", "login_opcodes.conf")
|
||||||
|
);
|
||||||
|
|
||||||
|
run_server = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
larion_stream->OnNewConnection(
|
||||||
|
[this](std::shared_ptr<EQ::Net::EQStream> stream) {
|
||||||
|
LogInfo(
|
||||||
|
"New Larion client connection from [{0}:{1}]",
|
||||||
|
long2ip(stream->GetRemoteIP()),
|
||||||
|
stream->GetRemotePort()
|
||||||
|
);
|
||||||
|
|
||||||
|
stream->SetOpcodeManager(&larion_ops);
|
||||||
|
Client* c = new Client(stream, cv_larion);
|
||||||
|
clients.push_back(c);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientManager::~ClientManager()
|
ClientManager::~ClientManager()
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ private:
|
|||||||
EQ::Net::EQStreamManager *titanium_stream;
|
EQ::Net::EQStreamManager *titanium_stream;
|
||||||
OpcodeManager *sod_ops;
|
OpcodeManager *sod_ops;
|
||||||
EQ::Net::EQStreamManager *sod_stream;
|
EQ::Net::EQStreamManager *sod_stream;
|
||||||
|
OpcodeManager *larion_ops;
|
||||||
|
EQ::Net::EQStreamManager* larion_stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -83,7 +83,8 @@ struct PlayEverquestResponse_Struct {
|
|||||||
|
|
||||||
enum LSClientVersion {
|
enum LSClientVersion {
|
||||||
cv_titanium,
|
cv_titanium,
|
||||||
cv_sod
|
cv_sod,
|
||||||
|
cv_larion
|
||||||
};
|
};
|
||||||
|
|
||||||
enum LSClientStatus {
|
enum LSClientStatus {
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#EQEmu Public Login Server OPCodes
|
||||||
|
OP_SessionReady=0x0001
|
||||||
|
OP_Login=0x0002
|
||||||
|
OP_ServerListRequest=0x0004
|
||||||
|
OP_PlayEverquestRequest=0x000d
|
||||||
|
OP_PlayEverquestResponse=0x0022
|
||||||
|
OP_ChatMessage=0x0017
|
||||||
|
OP_LoginAccepted=0x0018
|
||||||
|
OP_ServerListResponse=0x0019
|
||||||
|
OP_Poll=0x0029
|
||||||
|
OP_EnterChat=0x000f
|
||||||
|
OP_PollResponse=0x0011
|
||||||
|
OP_SystemFingerprint=0x0016
|
||||||
|
OP_ExpansionList=0x0030
|
||||||
@@ -137,7 +137,7 @@ std::unique_ptr<EQApplicationPacket> ServerManager::CreateServerListPacket(Clien
|
|||||||
use_local_ip ? "Local" : "Remote"
|
use_local_ip ? "Local" : "Remote"
|
||||||
);
|
);
|
||||||
|
|
||||||
world_server->SerializeForClientServerList(buf, use_local_ip);
|
world_server->SerializeForClientServerList(buf, use_local_ip, client->GetClientVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_unique<EQApplicationPacket>(OP_ServerListResponse, buf);
|
return std::make_unique<EQApplicationPacket>(OP_ServerListResponse, buf);
|
||||||
|
|||||||
@@ -977,8 +977,7 @@ bool WorldServer::ValidateWorldServerAdminLogin(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldServer::SerializeForClientServerList(SerializeBuffer &out, bool use_local_ip) const
|
void WorldServer::SerializeForClientServerListLegacy(class SerializeBuffer& out, bool use_local_ip) const {
|
||||||
{
|
|
||||||
// see LoginClientServerData_Struct
|
// see LoginClientServerData_Struct
|
||||||
if (use_local_ip) {
|
if (use_local_ip) {
|
||||||
out.WriteString(GetLocalIP());
|
out.WriteString(GetLocalIP());
|
||||||
@@ -988,18 +987,19 @@ void WorldServer::SerializeForClientServerList(SerializeBuffer &out, bool use_lo
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (GetServerListID()) {
|
switch (GetServerListID()) {
|
||||||
case LS::ServerType::Legends:
|
case LS::ServerType::Legends:
|
||||||
out.WriteInt32(LS::ServerTypeFlags::Legends);
|
out.WriteInt32(LS::ServerTypeFlags::Legends);
|
||||||
break;
|
break;
|
||||||
case LS::ServerType::Preferred:
|
case LS::ServerType::Preferred:
|
||||||
out.WriteInt32(LS::ServerTypeFlags::Preferred);
|
out.WriteInt32(LS::ServerTypeFlags::Preferred);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
out.WriteInt32(LS::ServerTypeFlags::Standard);
|
out.WriteInt32(LS::ServerTypeFlags::Standard);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
out.WriteUInt32(GetServerId());
|
out.WriteUInt32(GetServerId());
|
||||||
|
|
||||||
out.WriteString(GetServerLongName());
|
out.WriteString(GetServerLongName());
|
||||||
out.WriteString("us"); // country code
|
out.WriteString("us"); // country code
|
||||||
out.WriteString("en"); // language code
|
out.WriteString("en"); // language code
|
||||||
@@ -1020,6 +1020,61 @@ void WorldServer::SerializeForClientServerList(SerializeBuffer &out, bool use_lo
|
|||||||
out.WriteUInt32(GetPlayersOnline());
|
out.WriteUInt32(GetPlayersOnline());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldServer::SerializeForClientServerListLarion(class SerializeBuffer& out, bool use_local_ip) const {
|
||||||
|
if (use_local_ip) {
|
||||||
|
out.WriteString(GetLocalIP());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out.WriteString(GetRemoteIP());
|
||||||
|
}
|
||||||
|
|
||||||
|
out.WriteUInt32(9000);
|
||||||
|
out.WriteUInt32(0);
|
||||||
|
|
||||||
|
uint32_t flags = 32; //all servers i saw had this set
|
||||||
|
switch (GetServerListID()) {
|
||||||
|
case LS::ServerType::Legends:
|
||||||
|
flags += LS::ServerTypeFlags::Legends;
|
||||||
|
break;
|
||||||
|
case LS::ServerType::Preferred:
|
||||||
|
flags += LS::ServerTypeFlags::Preferred;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
flags += LS::ServerTypeFlags::Standard;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.WriteUInt32(flags);
|
||||||
|
out.WriteUInt32(GetServerId());
|
||||||
|
out.WriteString(GetServerLongName());
|
||||||
|
out.WriteString("EN");
|
||||||
|
out.WriteString("US");
|
||||||
|
|
||||||
|
if (GetStatus() < 0) {
|
||||||
|
if (GetZonesBooted() == 0) {
|
||||||
|
out.WriteInt32(LS::ServerStatusFlags::Down);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out.WriteInt32(LS::ServerStatusFlags::Locked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out.WriteInt32(LS::ServerStatusFlags::Up);
|
||||||
|
}
|
||||||
|
|
||||||
|
out.WriteUInt32(GetPlayersOnline());
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldServer::SerializeForClientServerList(SerializeBuffer& out, bool use_local_ip, LSClientVersion version) const
|
||||||
|
{
|
||||||
|
if (version == cv_larion) {
|
||||||
|
SerializeForClientServerListLarion(out, use_local_ip);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SerializeForClientServerListLegacy(out, use_local_ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param in_server_list_id
|
* @param in_server_list_id
|
||||||
* @return
|
* @return
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "../common/packet_dump.h"
|
#include "../common/packet_dump.h"
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
#include "../common/event/timer.h"
|
#include "../common/event/timer.h"
|
||||||
|
#include "login_types.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -148,8 +149,11 @@ public:
|
|||||||
|
|
||||||
bool HandleNewLoginserverRegisteredOnly(Database::DbWorldRegistration &world_registration);
|
bool HandleNewLoginserverRegisteredOnly(Database::DbWorldRegistration &world_registration);
|
||||||
bool HandleNewLoginserverInfoUnregisteredAllowed(Database::DbWorldRegistration &world_registration);
|
bool HandleNewLoginserverInfoUnregisteredAllowed(Database::DbWorldRegistration &world_registration);
|
||||||
|
private:
|
||||||
void SerializeForClientServerList(class SerializeBuffer& out, bool use_local_ip) const;
|
void SerializeForClientServerListLegacy(class SerializeBuffer& out, bool use_local_ip) const;
|
||||||
|
void SerializeForClientServerListLarion(class SerializeBuffer& out, bool use_local_ip) const;
|
||||||
|
public:
|
||||||
|
void SerializeForClientServerList(class SerializeBuffer& out, bool use_local_ip, LSClientVersion version) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "eqemu-server",
|
"name": "eqemu-server",
|
||||||
"version": "22.51.0",
|
"version": "22.56.3",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/EQEmu/Server.git"
|
"url": "https://github.com/EQEmu/Server.git"
|
||||||
|
|||||||
@@ -0,0 +1,730 @@
|
|||||||
|
# ShowEQ Import Notes:
|
||||||
|
# ZERO THE FILE first
|
||||||
|
# perl -pi -e 's/0x[0-9a-fA-F]{4}/0x0000/g' opcodes.conf
|
||||||
|
# Unknown Mapping:
|
||||||
|
# OP_Action2 -> OP_Damage
|
||||||
|
# OP_EnvDamage -> OP_Damage ---> might have been a one time mistake
|
||||||
|
# Name Differences:
|
||||||
|
# OP_CancelInvite -> OP_GroupCancelInvite
|
||||||
|
# OP_GMFind -> OP_FindPersonRequest
|
||||||
|
# OP_CommonMessage -> OP_ChannelMessage
|
||||||
|
|
||||||
|
OP_Unknown=0x0000
|
||||||
|
OP_ExploreUnknown=0x0000 # used for unknown explorer
|
||||||
|
|
||||||
|
# world packets
|
||||||
|
# Required to reach Char Select:
|
||||||
|
OP_SendLoginInfo=0x2fca
|
||||||
|
OP_ApproveWorld=0x0000
|
||||||
|
OP_LogServer=0x6d4d
|
||||||
|
OP_SendCharInfo=0x832
|
||||||
|
OP_ExpansionInfo=0x066d
|
||||||
|
OP_GuildsList=0x0000
|
||||||
|
OP_EnterWorld=0x6691
|
||||||
|
OP_PostEnterWorld=0x2062
|
||||||
|
OP_World_Client_CRC1=0x74c8
|
||||||
|
OP_World_Client_CRC2=0x3984
|
||||||
|
OP_World_Client_CRC3=0x6516
|
||||||
|
OP_SendSpellChecksum=0x0000
|
||||||
|
OP_SendSkillCapsChecksum=0x0000
|
||||||
|
|
||||||
|
# Character Select Related:
|
||||||
|
OP_SendMaxCharacters=0x13af
|
||||||
|
OP_SendMembership=0x2aca
|
||||||
|
OP_SendMembershipDetails=0x2608
|
||||||
|
OP_CharacterCreateRequest=0x0000
|
||||||
|
OP_CharacterCreate=0x0000
|
||||||
|
OP_DeleteCharacter=0x0000
|
||||||
|
OP_RandomNameGenerator=0x0000
|
||||||
|
OP_ApproveName=0x0000
|
||||||
|
OP_MOTD=0x0000
|
||||||
|
OP_SetChatServer=0x2726
|
||||||
|
OP_SetChatServer2=0x0000
|
||||||
|
OP_ZoneServerInfo=0x2273
|
||||||
|
OP_WorldComplete=0x195c
|
||||||
|
OP_WorldUnknown001=0x2049
|
||||||
|
OP_FloatListThing=0x0000
|
||||||
|
|
||||||
|
# Reasons for Disconnect:
|
||||||
|
OP_ZoneUnavail=0x0000
|
||||||
|
OP_WorldClientReady=0x0000
|
||||||
|
OP_CharacterStillInZone=0x0000
|
||||||
|
OP_WorldChecksumFailure=0x0000
|
||||||
|
OP_WorldLoginFailed=0x0000
|
||||||
|
OP_WorldLogout=0x0000
|
||||||
|
OP_WorldLevelTooHigh=0x0000
|
||||||
|
OP_CharInacessable=0x0000
|
||||||
|
OP_UserCompInfo=0x0000
|
||||||
|
OP_SendExeChecksum=0x0000
|
||||||
|
OP_SendBaseDataChecksum=0x0000
|
||||||
|
|
||||||
|
# Zone in opcodes
|
||||||
|
OP_AckPacket=0x77c9
|
||||||
|
OP_ZoneEntry=0x0000
|
||||||
|
OP_ReqNewZone=0x0000
|
||||||
|
OP_NewZone=0x0000
|
||||||
|
OP_ZoneSpawns=0x0000
|
||||||
|
OP_PlayerProfile=0x0000
|
||||||
|
OP_TimeOfDay=0x0000
|
||||||
|
OP_LevelUpdate=0x0000
|
||||||
|
OP_Stamina=0x0000
|
||||||
|
OP_RequestClientZoneChange=0x0000
|
||||||
|
OP_ZoneChange=0x0000
|
||||||
|
OP_LockoutTimerInfo=0x0000
|
||||||
|
OP_ZoneServerReady=0x0000
|
||||||
|
OP_ZoneInUnknown=0x0000
|
||||||
|
OP_LogoutReply=0x0000
|
||||||
|
OP_PreLogoutReply=0x0000
|
||||||
|
|
||||||
|
# Required to fully log in
|
||||||
|
OP_SpawnAppearance=0x0000
|
||||||
|
OP_ChangeSize=0x0000
|
||||||
|
OP_TributeUpdate=0x0000
|
||||||
|
OP_TributeTimer=0x0000
|
||||||
|
OP_SendTributes=0x0000
|
||||||
|
OP_RequestGuildTributes=0x0000
|
||||||
|
OP_TributeInfo=0x0000
|
||||||
|
OP_Weather=0x0000
|
||||||
|
OP_ReqClientSpawn=0x0000
|
||||||
|
OP_SpawnDoor=0x0000
|
||||||
|
OP_GroundSpawn=0x0000
|
||||||
|
OP_SendZonepoints=0x0000
|
||||||
|
OP_BlockedBuffs=0x0000
|
||||||
|
OP_RemoveBlockedBuffs=0x0000
|
||||||
|
OP_ClearBlockedBuffs=0x0000
|
||||||
|
OP_WorldObjectsSent=0x0000
|
||||||
|
OP_SendExpZonein=0x0000
|
||||||
|
OP_SendAATable=0x0000
|
||||||
|
OP_ClearAA=0x0000
|
||||||
|
OP_ClearLeadershipAbilities=0x0000
|
||||||
|
OP_RespondAA=0x0000
|
||||||
|
OP_UpdateAA=0x0000
|
||||||
|
OP_SendAAStats=0x0000
|
||||||
|
OP_AAExpUpdate=0x0000
|
||||||
|
OP_ExpUpdate=0x0000
|
||||||
|
OP_HPUpdate=0x0000
|
||||||
|
OP_ManaChange=0x0000
|
||||||
|
OP_TGB=0x0000
|
||||||
|
OP_SpecialMesg=0x0000
|
||||||
|
OP_GuildMemberList=0x0000
|
||||||
|
OP_GuildMOTD=0x0000
|
||||||
|
OP_CharInventory=0x0000
|
||||||
|
OP_WearChange=0x0000
|
||||||
|
OP_ClientUpdate=0x0000
|
||||||
|
OP_ClientReady=0x0000
|
||||||
|
OP_SetServerFilter=0x0000
|
||||||
|
|
||||||
|
# Guild Opcodes
|
||||||
|
OP_GetGuildMOTD=0x0000
|
||||||
|
OP_GetGuildMOTDReply=0x0000
|
||||||
|
OP_GuildMemberUpdate=0x0000
|
||||||
|
OP_GuildInvite=0x0000
|
||||||
|
OP_GuildRemove=0x0000
|
||||||
|
OP_GuildPeace=0x0000
|
||||||
|
OP_SetGuildMOTD=0x0000
|
||||||
|
OP_GuildWar=0x0000
|
||||||
|
OP_GuildLeader=0x0000
|
||||||
|
OP_GuildDelete=0x0000
|
||||||
|
OP_GuildInviteAccept=0x0000
|
||||||
|
OP_GuildDemote=0x0000
|
||||||
|
OP_GuildPromote=0x0000
|
||||||
|
OP_GuildPublicNote=0x0000
|
||||||
|
OP_GuildManageBanker=0x0000
|
||||||
|
OP_GuildBank=0x0000
|
||||||
|
OP_GuildBankItemList=0x0000
|
||||||
|
OP_SetGuildRank=0x0000
|
||||||
|
OP_GuildUpdate=0x0000
|
||||||
|
OP_GuildStatus=0x0000
|
||||||
|
OP_GuildCreate=0x0000
|
||||||
|
OP_GuildOpenGuildWindow=0x0000
|
||||||
|
OP_GuildMemberLevel=0x0000
|
||||||
|
OP_GuildMemberRankAltBanker=0x0000
|
||||||
|
OP_GuildMemberPublicNote=0x0000
|
||||||
|
OP_GuildMemberAdd=0x0000
|
||||||
|
OP_GuildMemberRename=0x0000
|
||||||
|
OP_GuildMemberDelete=0x0000
|
||||||
|
OP_GuildMemberDetails=0x0000
|
||||||
|
OP_GuildRenameGuild=0x0000
|
||||||
|
OP_LFGuild=0x0000
|
||||||
|
OP_GuildDeleteGuild=0x0000
|
||||||
|
|
||||||
|
# GM/Guide Opcodes
|
||||||
|
OP_GMServers=0x0000
|
||||||
|
OP_GMBecomeNPC=0x0000
|
||||||
|
OP_GMZoneRequest=0x0000
|
||||||
|
OP_GMZoneRequest2=0x0000
|
||||||
|
OP_GMGoto=0x0000
|
||||||
|
OP_GMSearchCorpse=0x0000
|
||||||
|
OP_GMHideMe=0x0000
|
||||||
|
OP_GMDelCorpse=0x0000
|
||||||
|
OP_GMApproval=0x0000
|
||||||
|
OP_GMToggle=0x0000
|
||||||
|
OP_GMSummon=0x0000
|
||||||
|
OP_GMEmoteZone=0x0000
|
||||||
|
OP_GMEmoteWorld=0x0000
|
||||||
|
OP_GMFind=0x0000
|
||||||
|
OP_GMKick=0x0000
|
||||||
|
OP_GMKill=0x0000
|
||||||
|
OP_GMNameChange=0x0000
|
||||||
|
OP_GMLastName=0x0000
|
||||||
|
|
||||||
|
# Misc Opcodes
|
||||||
|
OP_QueryUCSServerStatus=0x0000
|
||||||
|
OP_InspectRequest=0x0000
|
||||||
|
OP_InspectAnswer=0x0000
|
||||||
|
OP_InspectMessageUpdate=0x0000
|
||||||
|
OP_BeginCast=0x0000
|
||||||
|
OP_ColoredText=0x0000
|
||||||
|
OP_ConsentResponse=0x0000
|
||||||
|
OP_MemorizeSpell=0x0000
|
||||||
|
OP_LinkedReuse=0x0000
|
||||||
|
OP_SwapSpell=0x0000
|
||||||
|
OP_CastSpell=0x0000
|
||||||
|
OP_Consider=0x0000
|
||||||
|
OP_FormattedMessage=0x0000
|
||||||
|
OP_SimpleMessage=0x0000
|
||||||
|
OP_Buff=0x0000
|
||||||
|
OP_Illusion=0x0000
|
||||||
|
OP_MoneyOnCorpse=0x0000
|
||||||
|
OP_RandomReply=0x0000
|
||||||
|
OP_DenyResponse=0x0000
|
||||||
|
OP_SkillUpdate=0x04c
|
||||||
|
OP_GMTrainSkillConfirm=0x0000
|
||||||
|
OP_RandomReq=0x0000
|
||||||
|
OP_Death=0x0000
|
||||||
|
OP_GMTraining=0x0000
|
||||||
|
OP_GMEndTraining=0x0000
|
||||||
|
OP_GMTrainSkill=0x0000
|
||||||
|
OP_Animation=0x0000
|
||||||
|
OP_Begging=0x0000
|
||||||
|
OP_Consent=0x0000
|
||||||
|
OP_ConsentDeny=0x0000
|
||||||
|
OP_AutoFire=0x0000
|
||||||
|
OP_PetCommands=0x0000
|
||||||
|
OP_PetCommandState=0x0000
|
||||||
|
OP_PetHoTT=0x0000
|
||||||
|
OP_DeleteSpell=0x0000
|
||||||
|
OP_Surname=0x0000
|
||||||
|
OP_ClearSurname=0x0000
|
||||||
|
OP_FaceChange=0x0000
|
||||||
|
OP_SetFace=0x0000
|
||||||
|
OP_SenseHeading=0x0000
|
||||||
|
OP_Action=0x0000
|
||||||
|
OP_ConsiderCorpse=0x0000
|
||||||
|
OP_HideCorpse=0x0000
|
||||||
|
OP_CorpseDrag=0x0000
|
||||||
|
OP_CorpseDrop=0x0000
|
||||||
|
OP_Bug=0x0000
|
||||||
|
OP_Feedback=0x0000
|
||||||
|
OP_Report=0x0000
|
||||||
|
OP_Damage=0x0000
|
||||||
|
OP_ChannelMessage=0x0000
|
||||||
|
OP_Assist=0x0000
|
||||||
|
OP_AssistGroup=0x0000
|
||||||
|
OP_MoveCoin=0x0000
|
||||||
|
OP_ZonePlayerToBind=0x0000
|
||||||
|
OP_KeyRing=0x0000
|
||||||
|
OP_WhoAllRequest=0x0000
|
||||||
|
OP_WhoAllResponse=0x0000
|
||||||
|
OP_FriendsWho=0x0000
|
||||||
|
OP_ConfirmDelete=0x0000
|
||||||
|
OP_Logout=0x0000
|
||||||
|
OP_Rewind=0x0000
|
||||||
|
OP_TargetCommand=0x0000
|
||||||
|
OP_Hide=0x0000
|
||||||
|
OP_Jump=0x0000
|
||||||
|
OP_Camp=0x0000
|
||||||
|
OP_Emote=0x0000
|
||||||
|
OP_SetRunMode=0x0000
|
||||||
|
OP_BankerChange=0x0000
|
||||||
|
OP_TargetMouse=0x0000
|
||||||
|
OP_MobHealth=0x0000
|
||||||
|
OP_InitialMobHealth=0x0000 # Unused?
|
||||||
|
OP_TargetHoTT=0x0000
|
||||||
|
OP_TargetBuffs=0x0000
|
||||||
|
OP_XTargetResponse=0x0000
|
||||||
|
OP_XTargetRequest=0x0000
|
||||||
|
OP_XTargetAutoAddHaters=0x0000
|
||||||
|
OP_XTargetOpen=0x0000
|
||||||
|
OP_XTargetOpenResponse=0x0000
|
||||||
|
OP_BuffCreate=0x0000
|
||||||
|
OP_BuffRemoveRequest=0x0000
|
||||||
|
OP_DeleteSpawn=0x0000
|
||||||
|
OP_AutoAttack=0x0000
|
||||||
|
OP_AutoAttack2=0x0000
|
||||||
|
OP_Consume=0x0000
|
||||||
|
OP_MoveItem=0x0000
|
||||||
|
OP_MoveMultipleItems=0x0000
|
||||||
|
OP_DeleteItem=0x0000
|
||||||
|
OP_DeleteCharge=0x0000
|
||||||
|
OP_ItemPacket=0x0000
|
||||||
|
OP_ItemLinkResponse=0x0000
|
||||||
|
OP_ItemLinkClick=0x0000
|
||||||
|
OP_ItemPreview=0x0000
|
||||||
|
OP_NewSpawn=0x0000
|
||||||
|
OP_Track=0x0000
|
||||||
|
OP_TrackTarget=0x0000
|
||||||
|
OP_TrackUnknown=0x0000
|
||||||
|
OP_ClickDoor=0x0000
|
||||||
|
OP_MoveDoor=0x0000
|
||||||
|
OP_RemoveAllDoors=0x0000
|
||||||
|
OP_EnvDamage=0x0000
|
||||||
|
OP_BoardBoat=0x0000
|
||||||
|
OP_LeaveBoat=0x0000
|
||||||
|
OP_ControlBoat=0x0000
|
||||||
|
OP_Forage=0x0000
|
||||||
|
OP_SafeFallSuccess=0x0000
|
||||||
|
OP_RezzComplete=0x0000
|
||||||
|
OP_RezzRequest=0x0000
|
||||||
|
OP_RezzAnswer=0x0000
|
||||||
|
OP_Shielding=0x0000
|
||||||
|
OP_RequestDuel=0x0000
|
||||||
|
OP_MobRename=0x0000
|
||||||
|
OP_AugmentItem=0x0000
|
||||||
|
OP_WeaponEquip1=0x0000
|
||||||
|
OP_PlayerStateAdd=0x0000
|
||||||
|
OP_PlayerStateRemove=0x0000
|
||||||
|
OP_ApplyPoison=0x0000
|
||||||
|
OP_Save=0x0000
|
||||||
|
OP_TestBuff=0x0000
|
||||||
|
OP_CustomTitles=0x0000
|
||||||
|
OP_Split=0x0000
|
||||||
|
OP_YellForHelp=0x0000
|
||||||
|
OP_LoadSpellSet=0x0000
|
||||||
|
OP_Bandolier=0x0000
|
||||||
|
OP_PotionBelt=0x0000
|
||||||
|
OP_DuelDecline=0x0000
|
||||||
|
OP_DuelAccept=0x0000
|
||||||
|
OP_SaveOnZoneReq=0x0000
|
||||||
|
OP_ReadBook=0x0000
|
||||||
|
OP_Dye=0x0000
|
||||||
|
OP_InterruptCast=0x0000
|
||||||
|
OP_AAAction=0x0000
|
||||||
|
OP_LeadershipExpToggle=0x0000
|
||||||
|
OP_LeadershipExpUpdate=0x0000
|
||||||
|
OP_PurchaseLeadershipAA=0x0000
|
||||||
|
OP_UpdateLeadershipAA=0x0000
|
||||||
|
OP_MarkNPC=0x0000
|
||||||
|
OP_ClearNPCMarks=0x0000
|
||||||
|
OP_DelegateAbility=0x0000
|
||||||
|
OP_SetGroupTarget=0x0000
|
||||||
|
OP_Charm=0x0000
|
||||||
|
OP_Stun=0x0000
|
||||||
|
OP_SendFindableNPCs=0x0000
|
||||||
|
OP_FindPersonRequest=0x0000
|
||||||
|
OP_FindPersonReply=0x0000
|
||||||
|
OP_Sound=0x0000
|
||||||
|
OP_CashReward=0x0000
|
||||||
|
OP_PetBuffWindow=0x0000
|
||||||
|
OP_LevelAppearance=0x0000
|
||||||
|
OP_Translocate=0x0000
|
||||||
|
OP_Sacrifice=0x0000
|
||||||
|
OP_PopupResponse=0x0000
|
||||||
|
OP_OnLevelMessage=0x0000
|
||||||
|
OP_AugmentInfo=0x0000
|
||||||
|
OP_Petition=0x0000
|
||||||
|
OP_SomeItemPacketMaybe=0x0000
|
||||||
|
OP_PVPStats=0x0000
|
||||||
|
OP_PVPLeaderBoardRequest=0x0000
|
||||||
|
OP_PVPLeaderBoardReply=0x0000
|
||||||
|
OP_PVPLeaderBoardDetailsRequest=0x0000
|
||||||
|
OP_PVPLeaderBoardDetailsReply=0x0000
|
||||||
|
OP_RestState=0x0000
|
||||||
|
OP_RespawnWindow=0x0000
|
||||||
|
OP_LDoNButton=0x0000
|
||||||
|
OP_SetStartCity=0x0000
|
||||||
|
OP_VoiceMacroIn=0x0000
|
||||||
|
OP_VoiceMacroOut=0x0000
|
||||||
|
OP_ItemViewUnknown=0x0000
|
||||||
|
OP_VetRewardsAvaliable=0x0000
|
||||||
|
OP_VetClaimRequest=0x0000
|
||||||
|
OP_VetClaimReply=0x0000
|
||||||
|
OP_DisciplineUpdate=0x0000
|
||||||
|
OP_DisciplineTimer=0x0000
|
||||||
|
OP_BecomeCorpse=0x0000 # Unused?
|
||||||
|
OP_Action2=0x0000 # Unused?
|
||||||
|
OP_MobUpdate=0x0000
|
||||||
|
OP_NPCMoveUpdate=0x0000
|
||||||
|
OP_CameraEffect=0x0000
|
||||||
|
OP_SpellEffect=0x0000
|
||||||
|
OP_AddNimbusEffect=0x0000
|
||||||
|
OP_RemoveNimbusEffect=0x0000
|
||||||
|
OP_AltCurrency=0x0000
|
||||||
|
OP_AltCurrencyMerchantRequest=0x0000
|
||||||
|
OP_AltCurrencyMerchantReply=0x0000
|
||||||
|
OP_AltCurrencyPurchase=0x0000
|
||||||
|
OP_AltCurrencySell=0x0000
|
||||||
|
OP_AltCurrencySellSelection=0x0000
|
||||||
|
OP_AltCurrencyReclaim=0x0000
|
||||||
|
OP_CrystalCountUpdate=0x0000
|
||||||
|
OP_CrystalCreate=0x0000
|
||||||
|
OP_CrystalReclaim=0x0000
|
||||||
|
OP_Untargetable=0x0000
|
||||||
|
OP_IncreaseStats=0x0000
|
||||||
|
OP_Weblink=0x0000
|
||||||
|
OP_OpenContainer=0x0000
|
||||||
|
OP_Marquee=0x0000
|
||||||
|
OP_ItemRecastDelay=0x0000
|
||||||
|
#OP_OpenInventory=0x0000 # Likely does not exist in RoF -U
|
||||||
|
OP_ResetAA=0x0000
|
||||||
|
OP_Fling=0x0000
|
||||||
|
OP_CancelSneakHide=0x0000
|
||||||
|
OP_AggroMeterLockTarget=0x0000
|
||||||
|
OP_AggroMeterTargetInfo=0x0000
|
||||||
|
OP_AggroMeterUpdate=0x0000
|
||||||
|
OP_UnderWorld=0x0000 # clients sends up when they detect an underworld issue, might be useful for cheat detection
|
||||||
|
OP_KickPlayers=0x0000
|
||||||
|
OP_BookButton=0x0000
|
||||||
|
|
||||||
|
# Expeditions
|
||||||
|
OP_DzQuit=0x0000
|
||||||
|
OP_DzListTimers=0x0000
|
||||||
|
OP_DzAddPlayer=0x0000
|
||||||
|
OP_DzRemovePlayer=0x0000
|
||||||
|
OP_DzSwapPlayer=0x0000
|
||||||
|
OP_DzMakeLeader=0x0000
|
||||||
|
OP_DzPlayerList=0x0000
|
||||||
|
OP_DzExpeditionInvite=0x0000
|
||||||
|
OP_DzExpeditionInviteResponse=0x0000
|
||||||
|
OP_DzExpeditionInfo=0x0000
|
||||||
|
OP_DzExpeditionLockoutTimers=0x0000
|
||||||
|
OP_DzMemberList=0x0000
|
||||||
|
OP_DzMemberListName=0x0000
|
||||||
|
OP_DzMemberListStatus=0x0000
|
||||||
|
OP_DzSetLeaderName=0x0000
|
||||||
|
OP_DzExpeditionEndsWarning=0x0000
|
||||||
|
OP_DzCompass=0x0000
|
||||||
|
OP_DzChooseZone=0x0000
|
||||||
|
OP_DzChooseZoneReply=0x0000
|
||||||
|
|
||||||
|
# New Opcodes
|
||||||
|
OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ?
|
||||||
|
OP_ManaUpdate=0x0000
|
||||||
|
OP_EnduranceUpdate=0x0000
|
||||||
|
OP_MobManaUpdate=0x0000
|
||||||
|
OP_MobEnduranceUpdate=0x0000
|
||||||
|
|
||||||
|
# Mercenary Opcodes
|
||||||
|
OP_MercenaryDataUpdateRequest=0x0000
|
||||||
|
OP_MercenaryDataUpdate=0x0000
|
||||||
|
OP_MercenaryDataRequest=0x0000
|
||||||
|
OP_MercenaryDataResponse=0x0000
|
||||||
|
OP_MercenaryHire=0x0000
|
||||||
|
OP_MercenaryDismiss=0x0000
|
||||||
|
OP_MercenaryTimerRequest=0x0000
|
||||||
|
OP_MercenaryTimer=0x0000
|
||||||
|
OP_MercenaryUnknown1=0x0000
|
||||||
|
OP_MercenaryCommand=0x0000
|
||||||
|
OP_MercenarySuspendRequest=0x0000
|
||||||
|
OP_MercenarySuspendResponse=0x0000
|
||||||
|
OP_MercenaryUnsuspendResponse=0x0000
|
||||||
|
|
||||||
|
# Looting
|
||||||
|
OP_LootRequest=0x0000
|
||||||
|
OP_EndLootRequest=0x0000
|
||||||
|
OP_LootItem=0x0000
|
||||||
|
OP_LootComplete=0x0000
|
||||||
|
|
||||||
|
# bazaar trader stuff:
|
||||||
|
OP_BazaarSearch=0x0000
|
||||||
|
OP_TraderDelItem=0x0000
|
||||||
|
OP_BecomeTrader=0x0000
|
||||||
|
OP_TraderShop=0x0000
|
||||||
|
OP_TraderBulkSend=0x0000
|
||||||
|
OP_Trader=0x0000
|
||||||
|
OP_Barter=0x0000
|
||||||
|
OP_BuyerItems=0x0000
|
||||||
|
OP_TraderBuy=0x0000
|
||||||
|
OP_ShopItem=0x0000
|
||||||
|
OP_BazaarInspect=0x0000
|
||||||
|
OP_Bazaar=0x0000
|
||||||
|
OP_TraderItemUpdate=0x0000
|
||||||
|
|
||||||
|
# pc/npc trading
|
||||||
|
OP_TradeRequest=0x0000
|
||||||
|
OP_TradeAcceptClick=0x0000
|
||||||
|
OP_TradeRequestAck=0x0000
|
||||||
|
OP_TradeCoins=0x0000
|
||||||
|
OP_FinishTrade=0x0000
|
||||||
|
OP_CancelTrade=0x0000
|
||||||
|
OP_TradeMoneyUpdate=0x0000
|
||||||
|
OP_MoneyUpdate=0x0000
|
||||||
|
OP_TradeBusy=0x0000
|
||||||
|
|
||||||
|
# Sent after canceling trade or after closing tradeskill object
|
||||||
|
OP_FinishWindow=0x0000
|
||||||
|
OP_FinishWindow2=0x0000
|
||||||
|
|
||||||
|
# Sent on Live for what seems to be item existance verification
|
||||||
|
# Ex. Before Right Click Effect happens from items
|
||||||
|
OP_ItemVerifyRequest=0x0000
|
||||||
|
OP_ItemVerifyReply=0x0000
|
||||||
|
|
||||||
|
OP_ItemAdvancedLoreText=0x0000
|
||||||
|
|
||||||
|
# merchant stuff
|
||||||
|
OP_ShopPlayerSell=0x0000
|
||||||
|
OP_ShopRequest=0x0000
|
||||||
|
OP_ShopEnd=0x0000
|
||||||
|
OP_ShopEndConfirm=0x0000
|
||||||
|
OP_ShopPlayerBuy=0x0000
|
||||||
|
OP_ShopDelItem=0x0000
|
||||||
|
OP_ShopSendParcel=0x0000
|
||||||
|
OP_ShopDeleteParcel=0x0000
|
||||||
|
OP_ShopRetrieveParcel=0x0000
|
||||||
|
OP_ShopParcelIcon=0x0000
|
||||||
|
|
||||||
|
# tradeskill stuff:
|
||||||
|
OP_ClickObject=0x0000
|
||||||
|
OP_ClickObjectAction=0x0000
|
||||||
|
OP_ClearObject=0x0000
|
||||||
|
OP_RecipeDetails=0x0000
|
||||||
|
OP_RecipesFavorite=0x0000
|
||||||
|
OP_RecipesSearch=0x0000
|
||||||
|
OP_RecipeReply=0x0000
|
||||||
|
OP_RecipeAutoCombine=0x0000
|
||||||
|
OP_TradeSkillCombine=0x0000
|
||||||
|
|
||||||
|
# Tribute Packets:
|
||||||
|
OP_OpenTributeMaster=0x0000
|
||||||
|
OP_SelectTribute=0x0000
|
||||||
|
OP_TributeItem=0x0000
|
||||||
|
OP_TributeMoney=0x0000
|
||||||
|
OP_TributeToggle=0x0000
|
||||||
|
OP_TributePointUpdate=0x0000
|
||||||
|
OP_TributeNPC=0x0000
|
||||||
|
OP_GuildTributeInfo=0x0000
|
||||||
|
OP_OpenTributeReply=0x0000
|
||||||
|
OP_GuildTributeStatus=0x0000
|
||||||
|
OP_GuildSaveActiveTributes=0x0000
|
||||||
|
OP_GuildSendActiveTributes=0x0000
|
||||||
|
OP_GuildTributeToggleReq=0x0000
|
||||||
|
OP_GuildTributeToggleReply=0x0000
|
||||||
|
OP_GuildTributeFavorAndTimer=0x0000
|
||||||
|
OP_GuildTributeDonateItem=0x0000
|
||||||
|
OP_GuildTributeDonatePlat=0x0000
|
||||||
|
OP_GuildSelectTribute=0x0000
|
||||||
|
OP_GuildModifyBenefits=0x0000
|
||||||
|
OP_GuildOptInOut=0x0000
|
||||||
|
OP_SendGuildTributes=0x0000
|
||||||
|
OP_OpenGuildTributeMaster=0x0000
|
||||||
|
|
||||||
|
# Adventure packets:
|
||||||
|
OP_LeaveAdventure=0x0000
|
||||||
|
OP_AdventureFinish=0x0000
|
||||||
|
OP_AdventureInfoRequest=0x0000
|
||||||
|
OP_AdventureInfo=0x0000
|
||||||
|
OP_AdventureRequest=0x0000
|
||||||
|
OP_AdventureDetails=0x0000
|
||||||
|
OP_AdventureData=0x0000
|
||||||
|
OP_AdventureUpdate=0x0000
|
||||||
|
OP_AdventureMerchantRequest=0x0000
|
||||||
|
OP_AdventureMerchantResponse=0x0000
|
||||||
|
OP_AdventureMerchantPurchase=0x0000
|
||||||
|
OP_AdventureMerchantSell=0x0000
|
||||||
|
OP_AdventurePointsUpdate=0x0000
|
||||||
|
OP_AdventureStatsRequest=0x0000
|
||||||
|
OP_AdventureStatsReply=0x0000
|
||||||
|
OP_AdventureLeaderboardRequest=0x0000
|
||||||
|
OP_AdventureLeaderboardReply=0x0000
|
||||||
|
|
||||||
|
# Group Opcodes
|
||||||
|
OP_GroupDisband=0x0000
|
||||||
|
OP_GroupInvite=0x0000
|
||||||
|
OP_GroupFollow=0x0000
|
||||||
|
OP_GroupUpdate=0x0000
|
||||||
|
OP_GroupUpdateB=0x0000
|
||||||
|
OP_GroupCancelInvite=0x0000
|
||||||
|
OP_GroupAcknowledge=0x0000
|
||||||
|
OP_GroupDelete=0x0000
|
||||||
|
OP_CancelInvite=0x0000
|
||||||
|
OP_GroupFollow2=0x0000
|
||||||
|
OP_GroupInvite2=0x0000
|
||||||
|
OP_GroupDisbandYou=0x0000
|
||||||
|
OP_GroupDisbandOther=0x0000
|
||||||
|
OP_GroupLeaderChange=0x0000
|
||||||
|
OP_GroupRoles=0x0000
|
||||||
|
OP_GroupMakeLeader=0x0000
|
||||||
|
OP_DoGroupLeadershipAbility=0x0000
|
||||||
|
OP_GroupLeadershipAAUpdate=0x0000
|
||||||
|
OP_GroupMentor=0x0000
|
||||||
|
OP_InspectBuffs=0x0000
|
||||||
|
|
||||||
|
# LFG/LFP Opcodes
|
||||||
|
OP_LFGCommand=0x0000
|
||||||
|
OP_LFGGetMatchesRequest=0x0000
|
||||||
|
OP_LFGGetMatchesResponse=0x0000
|
||||||
|
OP_LFPGetMatchesRequest=0x0000
|
||||||
|
OP_LFPGetMatchesResponse=0x0000
|
||||||
|
OP_LFPCommand=0x0000
|
||||||
|
OP_LFGAppearance=0x0000
|
||||||
|
OP_LFGResponse=0x0000
|
||||||
|
|
||||||
|
# Raid Opcodes
|
||||||
|
OP_RaidInvite=0x0000
|
||||||
|
OP_RaidUpdate=0x0000
|
||||||
|
OP_RaidJoin=0x0000
|
||||||
|
OP_RaidDelegateAbility=0x0000
|
||||||
|
OP_MarkRaidNPC=0x0000
|
||||||
|
OP_RaidClearNPCMarks=0x0000
|
||||||
|
|
||||||
|
# Button-push commands
|
||||||
|
OP_Taunt=0x0000
|
||||||
|
OP_CombatAbility=0x0000
|
||||||
|
OP_SenseTraps=0x0000
|
||||||
|
OP_PickPocket=0x0000
|
||||||
|
OP_DisarmTraps=0x0000
|
||||||
|
OP_Disarm=0x0000
|
||||||
|
OP_Sneak=0x0000
|
||||||
|
OP_Fishing=0x0000
|
||||||
|
OP_InstillDoubt=0x0000
|
||||||
|
OP_FeignDeath=0x0000
|
||||||
|
OP_Mend=0x0000
|
||||||
|
OP_Bind_Wound=0x0000
|
||||||
|
OP_LDoNOpen=0x0000
|
||||||
|
#OP_LDoNDisarmTraps= #Same as OP_DisarmTraps in RoF
|
||||||
|
OP_LDoNPickLock=0x0000
|
||||||
|
OP_LDoNInspect=0x0000
|
||||||
|
|
||||||
|
# Task packets
|
||||||
|
OP_TaskDescription=0x0000
|
||||||
|
OP_TaskActivity=0x0000
|
||||||
|
OP_CompletedTasks=0x0000
|
||||||
|
OP_TaskActivityComplete=0x0000
|
||||||
|
OP_AcceptNewTask=0x0000
|
||||||
|
OP_CancelTask=0x0000
|
||||||
|
OP_AvaliableTask=0x0000
|
||||||
|
OP_TaskHistoryRequest=0x0000
|
||||||
|
OP_TaskHistoryReply=0x0000
|
||||||
|
OP_DeclineAllTasks=0x0000
|
||||||
|
OP_TaskRequestTimer=0x0000
|
||||||
|
OP_TaskSelectWindow=0x0000
|
||||||
|
|
||||||
|
# Shared Tasks
|
||||||
|
OP_SharedTaskMemberList=0x0000 #
|
||||||
|
OP_SharedTaskRemovePlayer=0x0000 # /taskremoveplayer
|
||||||
|
OP_SharedTaskAddPlayer=0x0000 # /taskaddplayer
|
||||||
|
OP_SharedTaskMakeLeader=0x0000 # /taskmakeleader
|
||||||
|
OP_SharedTaskInvite=0x0000 # Dialog window
|
||||||
|
OP_SharedTaskInviteResponse=0x0000 # Dialog window response
|
||||||
|
OP_SharedTaskAcceptNew=0x0000 #
|
||||||
|
OP_SharedTaskMemberChange=0x0000 #
|
||||||
|
OP_TaskTimers=0x0000 # /tasktimers
|
||||||
|
OP_SharedTaskQuit=0x0000 # /taskquit
|
||||||
|
OP_SharedTaskSelectWindow=0x0000
|
||||||
|
OP_SharedTaskPlayerList=0x0000 # /taskplayerlist
|
||||||
|
|
||||||
|
# Title opcodes
|
||||||
|
OP_NewTitlesAvailable=0x0000
|
||||||
|
OP_RequestTitles=0x0000
|
||||||
|
OP_SendTitleList=0x0000
|
||||||
|
OP_SetTitle=0x0000
|
||||||
|
OP_SetTitleReply=0x0000
|
||||||
|
|
||||||
|
# mail opcodes
|
||||||
|
OP_Command=0x0000
|
||||||
|
OP_MailboxHeader=0x0000
|
||||||
|
OP_MailHeader=0x0000
|
||||||
|
OP_MailBody=0x0000
|
||||||
|
OP_NewMail=0x0000
|
||||||
|
OP_SentConfirm=0x0000
|
||||||
|
|
||||||
|
########### Below this point should not be needed ###########
|
||||||
|
|
||||||
|
# This section are all unknown in Titanium
|
||||||
|
OP_ForceFindPerson=0x0000
|
||||||
|
OP_LocInfo=0x0000
|
||||||
|
OP_ReloadUI=0x0000
|
||||||
|
OP_ItemName=0x0000
|
||||||
|
OP_ItemLinkText=0x0000
|
||||||
|
OP_MultiLineMsg=0x0000
|
||||||
|
OP_MendHPUpdate=0x0000
|
||||||
|
OP_TargetReject=0x0000
|
||||||
|
OP_SafePoint=0x0000
|
||||||
|
OP_ApproveZone=0x0000
|
||||||
|
OP_ZoneComplete=0x0000
|
||||||
|
OP_ClientError=0x0000
|
||||||
|
OP_DumpName=0x0000
|
||||||
|
OP_Heartbeat=0x0000
|
||||||
|
OP_CrashDump=0x0000
|
||||||
|
OP_LoginComplete=0x0000
|
||||||
|
|
||||||
|
# discovered opcodes not yet used:
|
||||||
|
OP_PickLockSuccess=0x0000
|
||||||
|
OP_PlayMP3=0x0000
|
||||||
|
OP_ReclaimCrystals=0x0000
|
||||||
|
OP_DynamicWall=0x0000
|
||||||
|
OP_OpenDiscordMerchant=0x0000
|
||||||
|
OP_DiscordMerchantInventory=0x0000
|
||||||
|
OP_GiveMoney=0x0000
|
||||||
|
OP_RequestKnowledgeBase=0x0000
|
||||||
|
OP_KnowledgeBase=0x0000
|
||||||
|
OP_SlashAdventure=0x0000 # /adventure
|
||||||
|
OP_BecomePVPPrompt=0x0000
|
||||||
|
OP_MoveLogRequest=0x0000 # gone I think
|
||||||
|
OP_MoveLogDisregard=0x0000 # gone I think
|
||||||
|
|
||||||
|
# named unknowns, to make looking for real unknown easier
|
||||||
|
OP_AnnoyingZoneUnknown=0x0000
|
||||||
|
OP_Some6ByteHPUpdate=0x0000 #seems to happen when you target group members
|
||||||
|
OP_QueryResponseThing=0x0000
|
||||||
|
|
||||||
|
|
||||||
|
# realityincarnate: these are just here to stop annoying several thousand byte packet dumps
|
||||||
|
#OP_LoginUnknown1=0x0000 # OP_SendSpellChecksum
|
||||||
|
#OP_LoginUnknown2=0x0000 # OP_SendSkillCapsChecksum
|
||||||
|
|
||||||
|
# Petition Opcodes
|
||||||
|
OP_PetitionSearch=0x0000 #search term for petition
|
||||||
|
OP_PetitionSearchResults=0x0000 #(list of?) matches from search
|
||||||
|
OP_PetitionSearchText=0x0000 #text results of search
|
||||||
|
|
||||||
|
OP_PetitionUpdate=0x0000
|
||||||
|
OP_PetitionCheckout=0x0000
|
||||||
|
OP_PetitionCheckIn=0x0000
|
||||||
|
OP_PetitionQue=0x0000
|
||||||
|
OP_PetitionUnCheckout=0x0000
|
||||||
|
OP_PetitionDelete=0x0000
|
||||||
|
OP_DeletePetition=0x0000
|
||||||
|
OP_PetitionResolve=0x0000
|
||||||
|
OP_PDeletePetition=0x0000
|
||||||
|
OP_PetitionBug=0x0000
|
||||||
|
OP_PetitionRefresh=0x0000
|
||||||
|
OP_PetitionCheckout2=0x0000
|
||||||
|
OP_PetitionViewPetition=0x0000
|
||||||
|
|
||||||
|
# Login opcodes
|
||||||
|
OP_SessionReady=0x0000
|
||||||
|
OP_Login=0x0000
|
||||||
|
OP_ServerListRequest=0x0000
|
||||||
|
OP_PlayEverquestRequest=0x0000
|
||||||
|
OP_PlayEverquestResponse=0x0000
|
||||||
|
OP_ChatMessage=0x0000
|
||||||
|
OP_LoginAccepted=0x0000
|
||||||
|
OP_ServerListResponse=0x0000
|
||||||
|
OP_Poll=0x0000
|
||||||
|
OP_EnterChat=0x0000
|
||||||
|
OP_PollResponse=0x0000
|
||||||
|
|
||||||
|
# raw opcodes
|
||||||
|
OP_RAWSessionRequest=0x0000
|
||||||
|
OP_RAWSessionResponse=0x0000
|
||||||
|
OP_RAWCombined=0x0000
|
||||||
|
OP_RAWSessionDisconnect=0x0000
|
||||||
|
OP_RAWKeepAlive=0x0000
|
||||||
|
OP_RAWSessionStatRequest=0x0000
|
||||||
|
OP_RAWSessionStatResponse=0x0000
|
||||||
|
OP_RAWPacket=0x0000
|
||||||
|
OP_RAWFragment=0x0000
|
||||||
|
OP_RAWOutOfOrderAck=0x0000
|
||||||
|
OP_RAWAck=0x0000
|
||||||
|
OP_RAWAppCombined=0x0000
|
||||||
|
OP_RAWOutOfSession=0x0000
|
||||||
|
|
||||||
|
# we need to document the differences between these packets to make identifying them easier
|
||||||
|
OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs
|
||||||
|
OP_InitialHPUpdate=0x0000
|
||||||
|
|
||||||
|
#aura related
|
||||||
|
OP_UpdateAura=0x0000
|
||||||
|
OP_RemoveTrap=0x0000
|
||||||
@@ -433,6 +433,7 @@ OP_TraderShop=0x31df
|
|||||||
OP_TraderBulkSend=0x6a96
|
OP_TraderBulkSend=0x6a96
|
||||||
OP_Trader=0x4ef5
|
OP_Trader=0x4ef5
|
||||||
OP_Barter=0x243a
|
OP_Barter=0x243a
|
||||||
|
OP_BuyerItems=0x1a6a
|
||||||
OP_TraderBuy=0x0000
|
OP_TraderBuy=0x0000
|
||||||
OP_ShopItem=0x0000
|
OP_ShopItem=0x0000
|
||||||
OP_BazaarInspect=0x0000
|
OP_BazaarInspect=0x0000
|
||||||
|
|||||||
@@ -0,0 +1,388 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Ww][Ii][Nn]32/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# ASP.NET Scaffolding
|
||||||
|
ScaffoldingReadMe.txt
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.tlog
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Coverlet is a free, cross platform Code Coverage Tool
|
||||||
|
coverage*.json
|
||||||
|
coverage*.xml
|
||||||
|
coverage*.info
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Nuget personal access tokens and Credentials
|
||||||
|
nuget.config
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
|
.ionide/
|
||||||
|
|
||||||
|
# Fody - auto-generated XML schema
|
||||||
|
FodyWeavers.xsd
|
||||||
|
|
||||||
|
# VS Code files for those working on multiple tools
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
*.code-workspace
|
||||||
|
|
||||||
|
# Local History for Visual Studio Code
|
||||||
|
.history/
|
||||||
|
|
||||||
|
# Windows Installer files from build outputs
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# JetBrains Rider
|
||||||
|
.idea/
|
||||||
|
*.sln.iml
|
||||||
@@ -0,0 +1,621 @@
|
|||||||
|
using Ionic.Zlib;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace StreamParser.Common.Daybreak
|
||||||
|
{
|
||||||
|
public class Connection : IConnection
|
||||||
|
{
|
||||||
|
private class EncodeType
|
||||||
|
{
|
||||||
|
public const int None = 0;
|
||||||
|
public const int Compression = 1;
|
||||||
|
public const int XOR = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum SequenceOrder
|
||||||
|
{
|
||||||
|
Past,
|
||||||
|
Current,
|
||||||
|
Future
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly IParser _owner;
|
||||||
|
private readonly IPAddress _srcAddr;
|
||||||
|
private readonly int _srcPort;
|
||||||
|
private readonly IPAddress _dstAddr;
|
||||||
|
private readonly int _dstPort;
|
||||||
|
private readonly Util.Crc32 _crc_generator = new Util.Crc32();
|
||||||
|
private readonly Guid _id = Guid.NewGuid();
|
||||||
|
private uint _connect_code = 0;
|
||||||
|
private int _encode_key = 0;
|
||||||
|
private int _crc_bytes = 0;
|
||||||
|
private int[] _encode_pass = new int[2] { 0, 0 };
|
||||||
|
private ConnectionStream[] _client_streams = new ConnectionStream[4] {
|
||||||
|
new ConnectionStream(),
|
||||||
|
new ConnectionStream(),
|
||||||
|
new ConnectionStream(),
|
||||||
|
new ConnectionStream()
|
||||||
|
};
|
||||||
|
private ConnectionStream[] _server_streams = new ConnectionStream[4] {
|
||||||
|
new ConnectionStream(),
|
||||||
|
new ConnectionStream(),
|
||||||
|
new ConnectionStream(),
|
||||||
|
new ConnectionStream()
|
||||||
|
};
|
||||||
|
|
||||||
|
public IConnection.OnPacketRecvHandler OnPacketRecv { get; set; }
|
||||||
|
|
||||||
|
public IPAddress ClientAddress => _srcAddr;
|
||||||
|
public int ClientPort => _srcPort;
|
||||||
|
public IPAddress ServerAddress => _dstAddr;
|
||||||
|
public int ServerPort => _dstPort;
|
||||||
|
public Guid Id => _id;
|
||||||
|
|
||||||
|
public ConnectionType ConnectionType {
|
||||||
|
get
|
||||||
|
{
|
||||||
|
//World servers used to be coded to always be 9000 but live started using dynamic ports
|
||||||
|
//I've seen from 9000 to 9008 on live
|
||||||
|
if (_dstPort >= 9000 && _dstPort <= 9010)
|
||||||
|
{
|
||||||
|
return ConnectionType.World;
|
||||||
|
}
|
||||||
|
else if (_encode_pass[0] == EncodeType.None && _encode_pass[1] == EncodeType.None)
|
||||||
|
{
|
||||||
|
return ConnectionType.Login;
|
||||||
|
}
|
||||||
|
else if (_encode_pass[0] == EncodeType.XOR && _encode_pass[1] == EncodeType.None)
|
||||||
|
{
|
||||||
|
return ConnectionType.Chat;
|
||||||
|
}
|
||||||
|
else if (_encode_pass[0] == EncodeType.Compression && _encode_pass[1] == EncodeType.None)
|
||||||
|
{
|
||||||
|
return ConnectionType.Zone;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ConnectionType.Unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Connection(IParser owner, IPAddress srcAddr, int srcPort, IPAddress dstAddr, int dstPort)
|
||||||
|
{
|
||||||
|
_owner = owner;
|
||||||
|
_srcAddr = srcAddr;
|
||||||
|
_srcPort = srcPort;
|
||||||
|
_dstAddr = dstAddr;
|
||||||
|
_dstPort = dstPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ProcessPacket(IPAddress srcAddr, int srcPort, DateTime packetTime, ReadOnlySpan<byte> data)
|
||||||
|
{
|
||||||
|
if (data.Length < 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var opcode = data[1];
|
||||||
|
if (data[0] == 0 && (opcode == Opcode.KeepAlive || opcode == Opcode.OutboundPing))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PacketCanBeDecoded(data))
|
||||||
|
{
|
||||||
|
if (!ValidateCRC(data))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_encode_pass[0] == EncodeType.None && _encode_pass[1] == EncodeType.None)
|
||||||
|
{
|
||||||
|
ProcessDecodedPacket(srcAddr, srcPort, packetTime, data.Slice(0, data.Length - _crc_bytes));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//unfortunately we can't avoid a copy here
|
||||||
|
var temp = data.Slice(0, data.Length - _crc_bytes).ToArray();
|
||||||
|
for (int i = 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
switch(_encode_pass[i])
|
||||||
|
{
|
||||||
|
case EncodeType.Compression:
|
||||||
|
if(temp[0] == 0)
|
||||||
|
{
|
||||||
|
temp = Decompress(temp, 2, temp.Length - 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
temp = Decompress(temp, 1, temp.Length - 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EncodeType.XOR:
|
||||||
|
if (temp[0] == 0)
|
||||||
|
{
|
||||||
|
temp = Decode(temp, 2, temp.Length - 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
temp = Decode(temp, 1, temp.Length - 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessDecodedPacket(srcAddr, srcPort, packetTime, temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ProcessDecodedPacket(srcAddr, srcPort, packetTime, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessDecodedPacket(IPAddress srcAddr, int srcPort, DateTime packetTime, ReadOnlySpan<byte> data)
|
||||||
|
{
|
||||||
|
if (data.Length < 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data[0] == 0)
|
||||||
|
{
|
||||||
|
if (data.Length < 2)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var opcode = data[1];
|
||||||
|
switch (opcode)
|
||||||
|
{
|
||||||
|
case Opcode.SessionResponse:
|
||||||
|
if (_connect_code == 0)
|
||||||
|
{
|
||||||
|
if(data.Length != 21)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_connect_code = BitConverter.ToUInt32(data.Slice(2, 4));
|
||||||
|
_encode_key = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data.Slice(6, 4)));
|
||||||
|
_crc_bytes = data[10];
|
||||||
|
_encode_pass[0] = data[11];
|
||||||
|
_encode_pass[1] = data[12];
|
||||||
|
_owner.OnNewConnection?.Invoke(this, packetTime);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Opcode.SessionDisconnect:
|
||||||
|
if(_connect_code != 0)
|
||||||
|
{
|
||||||
|
_connect_code = 0;
|
||||||
|
_encode_key = 0;
|
||||||
|
_crc_bytes = 0;
|
||||||
|
_encode_pass[0] = 0;
|
||||||
|
_encode_pass[1] = 0;
|
||||||
|
_owner.OnLostConnection?.Invoke(this, packetTime);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Opcode.Combined:
|
||||||
|
{
|
||||||
|
int current = 2;
|
||||||
|
int end = data.Length;
|
||||||
|
while (current < end)
|
||||||
|
{
|
||||||
|
byte subpacket_length = data[current];
|
||||||
|
current += 1;
|
||||||
|
|
||||||
|
if (end < current + subpacket_length)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var subpacket = data.Slice(current, subpacket_length);
|
||||||
|
ProcessDecodedPacket(srcAddr, srcPort, packetTime, subpacket);
|
||||||
|
current += subpacket_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Opcode.AppCombined:
|
||||||
|
{
|
||||||
|
int current = 2;
|
||||||
|
int end = data.Length;
|
||||||
|
while (current < end)
|
||||||
|
{
|
||||||
|
int subpacket_length = 0;
|
||||||
|
if (data[current] == 0xff)
|
||||||
|
{
|
||||||
|
if (end < current + 3)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data[current + 1] == 0xff && data[current + 2] == 0xff)
|
||||||
|
{
|
||||||
|
if (end < current + 7)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
subpacket_length =
|
||||||
|
((data[current + 3]) << 24) |
|
||||||
|
((data[current + 4]) << 16) |
|
||||||
|
((data[current + 5]) << 8) |
|
||||||
|
(data[current + 6]);
|
||||||
|
|
||||||
|
current += 7;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
subpacket_length =
|
||||||
|
((data[current + 1]) << 8) |
|
||||||
|
(data[current + 2]);
|
||||||
|
|
||||||
|
current += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
subpacket_length = data[current];
|
||||||
|
current += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var subpacket = data.Slice(current, subpacket_length);
|
||||||
|
ProcessDecodedPacket(srcAddr, srcPort, packetTime, subpacket);
|
||||||
|
current += subpacket_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Opcode.Packet:
|
||||||
|
case Opcode.Packet2:
|
||||||
|
case Opcode.Packet3:
|
||||||
|
case Opcode.Packet4:
|
||||||
|
{
|
||||||
|
var stream_id = opcode - Opcode.Packet;
|
||||||
|
var stream = FindStream(srcAddr, srcPort, stream_id);
|
||||||
|
var sequence = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data.Slice(2, 2)));
|
||||||
|
var order = CompareSequence(stream.Sequence, sequence);
|
||||||
|
if (order == SequenceOrder.Future)
|
||||||
|
{
|
||||||
|
if (!stream.PacketQueue.ContainsKey(sequence))
|
||||||
|
{
|
||||||
|
stream.PacketQueue.Add(sequence, new ConnectionStream.QueuedPacket
|
||||||
|
{
|
||||||
|
Data = data.ToArray(),
|
||||||
|
PacketTime = packetTime
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (order == SequenceOrder.Current)
|
||||||
|
{
|
||||||
|
if (stream.PacketQueue.ContainsKey(sequence))
|
||||||
|
{
|
||||||
|
stream.PacketQueue.Remove(sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.Sequence++;
|
||||||
|
ProcessDecodedPacket(srcAddr, srcPort, packetTime, data.Slice(4));
|
||||||
|
ProcessQueue(srcAddr, srcPort, stream_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Opcode.Fragment:
|
||||||
|
case Opcode.Fragment2:
|
||||||
|
case Opcode.Fragment3:
|
||||||
|
case Opcode.Fragment4:
|
||||||
|
{
|
||||||
|
var stream_id = opcode - Opcode.Fragment;
|
||||||
|
var stream = FindStream(srcAddr, srcPort, stream_id);
|
||||||
|
var sequence = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data.Slice(2, 2)));
|
||||||
|
var order = CompareSequence(stream.Sequence, sequence);
|
||||||
|
if (order == SequenceOrder.Future)
|
||||||
|
{
|
||||||
|
if (!stream.PacketQueue.ContainsKey(sequence))
|
||||||
|
{
|
||||||
|
stream.PacketQueue.Add(sequence, new ConnectionStream.QueuedPacket
|
||||||
|
{
|
||||||
|
Data = data.ToArray(),
|
||||||
|
PacketTime = packetTime
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (order == SequenceOrder.Current)
|
||||||
|
{
|
||||||
|
if (stream.PacketQueue.ContainsKey(sequence))
|
||||||
|
{
|
||||||
|
stream.PacketQueue.Remove(sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.Sequence++;
|
||||||
|
|
||||||
|
if (stream.TotalFragmentedBytes == 0)
|
||||||
|
{
|
||||||
|
stream.TotalFragmentedBytes = (uint)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data.Slice(4, 4)));
|
||||||
|
stream.CurrentFragmentedBytes = (uint)(data.Length - 8);
|
||||||
|
|
||||||
|
if(stream.FragmentBuffer == null || stream.FragmentBuffer.Length < (stream.TotalFragmentedBytes + 512))
|
||||||
|
{
|
||||||
|
stream.FragmentBuffer = new byte[stream.TotalFragmentedBytes + 512];
|
||||||
|
}
|
||||||
|
|
||||||
|
var target = stream.FragmentBuffer.AsSpan();
|
||||||
|
data.Slice(8).CopyTo(target);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
var target = stream.FragmentBuffer.AsSpan((int)stream.CurrentFragmentedBytes);
|
||||||
|
data.Slice(4).CopyTo(target);
|
||||||
|
|
||||||
|
stream.CurrentFragmentedBytes += (uint)(data.Length - 4);
|
||||||
|
|
||||||
|
if (stream.CurrentFragmentedBytes >= stream.TotalFragmentedBytes)
|
||||||
|
{
|
||||||
|
ProcessDecodedPacket(srcAddr, srcPort, packetTime,
|
||||||
|
stream.FragmentBuffer.AsSpan(0, (int)stream.TotalFragmentedBytes));
|
||||||
|
stream.CurrentFragmentedBytes = 0;
|
||||||
|
stream.TotalFragmentedBytes = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessQueue(srcAddr, srcPort, stream_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Opcode.Padding:
|
||||||
|
OnPacketRecv?.Invoke(this, GetDirection(srcAddr, srcPort), packetTime, data.Slice(1));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
OnPacketRecv?.Invoke(this, GetDirection(srcAddr, srcPort), packetTime, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessQueue(IPAddress srcAddr, int srcPort, int stream_id)
|
||||||
|
{
|
||||||
|
var stream = FindStream(srcAddr, srcPort, stream_id);
|
||||||
|
var sequence = stream.Sequence;
|
||||||
|
|
||||||
|
//try to get the current sequence in the queue, if it exists then process it
|
||||||
|
ConnectionStream.QueuedPacket value;
|
||||||
|
if(stream.PacketQueue.TryGetValue(sequence, out value))
|
||||||
|
{
|
||||||
|
ProcessDecodedPacket(srcAddr, srcPort, value.PacketTime, value.Data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Match(IPAddress srcAddr, int srcPort, IPAddress dstAddr, int dstPort)
|
||||||
|
{
|
||||||
|
var p1 = _srcAddr.Equals(srcAddr) && _srcPort == srcPort && _dstAddr.Equals(dstAddr) && _dstPort == dstPort;
|
||||||
|
var p2 = _srcAddr.Equals(dstAddr) && _srcPort == dstPort && _dstAddr.Equals(srcAddr) && _dstPort == srcPort;
|
||||||
|
return p1 || p2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SequenceOrder CompareSequence(ushort expected, ushort actual)
|
||||||
|
{
|
||||||
|
int diff = (int)actual - (int)expected;
|
||||||
|
|
||||||
|
if (diff == 0)
|
||||||
|
{
|
||||||
|
return SequenceOrder.Current;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diff > 0)
|
||||||
|
{
|
||||||
|
if (diff > 10000)
|
||||||
|
{
|
||||||
|
return SequenceOrder.Past;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SequenceOrder.Future;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diff < -10000)
|
||||||
|
{
|
||||||
|
return SequenceOrder.Future;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SequenceOrder.Past;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool PacketCanBeDecoded(ReadOnlySpan<byte> p)
|
||||||
|
{
|
||||||
|
if (p.Length < 2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p[0] != 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var opcode = p[1];
|
||||||
|
|
||||||
|
if (opcode == Opcode.SessionRequest || opcode == Opcode.SessionResponse || opcode == Opcode.OutOfSession)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ValidateCRC(ReadOnlySpan<byte> p)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_crc_bytes == 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int actual = 0;
|
||||||
|
int calculated = _crc_generator.Calculate(p.Slice(0, p.Length - _crc_bytes), _encode_key);
|
||||||
|
switch (_crc_bytes)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
actual = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(p.Slice(p.Length - 2, 2))) & 0xFFFF;
|
||||||
|
calculated = calculated & 0xFFFF;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
actual = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(p.Slice(p.Length - 4, 4)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return actual == calculated;
|
||||||
|
} catch(Exception ex)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] Decompress(byte[] p, int offset, int length)
|
||||||
|
{
|
||||||
|
if (length < 2)
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
Span<byte> header = p.AsSpan(0, offset);
|
||||||
|
byte flag = p[offset];
|
||||||
|
Span<byte> payload = p.AsSpan(offset + 1, length - 1);
|
||||||
|
|
||||||
|
if (flag == 0x5a)
|
||||||
|
{
|
||||||
|
var pl = payload.ToArray();
|
||||||
|
var inflated = Inflate(payload.ToArray());
|
||||||
|
byte[] ret = new byte[offset + inflated.Length];
|
||||||
|
Array.Copy(p, 0, ret, 0, offset);
|
||||||
|
Array.Copy(inflated, 0, ret, offset, inflated.Length);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else if (flag == 0xa5)
|
||||||
|
{
|
||||||
|
byte[] ret = new byte[offset + length - 1];
|
||||||
|
Array.Copy(p, 0, ret, 0, offset);
|
||||||
|
Array.Copy(p, offset + 1, ret, offset, length - 1);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] Inflate(byte[] p)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var out_stream = new MemoryStream())
|
||||||
|
{
|
||||||
|
using (var in_stream = new MemoryStream(p))
|
||||||
|
{
|
||||||
|
var buffer = new byte[512];
|
||||||
|
using (var zs = new ZlibStream(in_stream, CompressionMode.Decompress))
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
r = zs.Read(buffer, 0, 512);
|
||||||
|
out_stream.Write(buffer, 0, r);
|
||||||
|
} while (r == 512);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ret = out_stream.ToArray();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] Decode(byte[] p, int offset, int length)
|
||||||
|
{
|
||||||
|
int key = _encode_key;
|
||||||
|
Span<byte> buffer = p.AsSpan(offset, length);
|
||||||
|
int i = 0;
|
||||||
|
for (i = 0; i + 4 <= length; i += 4)
|
||||||
|
{
|
||||||
|
int pt = BitConverter.ToInt32(buffer.Slice(i)) ^ key;
|
||||||
|
key = BitConverter.ToInt32(buffer.Slice(i));
|
||||||
|
|
||||||
|
if(BitConverter.TryWriteBytes(buffer.Slice(i), pt) == false)
|
||||||
|
{
|
||||||
|
throw new Exception("Error writing bytes back in decode.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte kc = (byte)(key & 0xFF);
|
||||||
|
for (; i < length; i++)
|
||||||
|
{
|
||||||
|
buffer[i] = (byte)(buffer[i] ^ kc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Direction GetDirection(IPAddress srcAddr, int srcPort)
|
||||||
|
{
|
||||||
|
if(srcAddr.Equals(_srcAddr) && srcPort == _srcPort)
|
||||||
|
{
|
||||||
|
return Direction.ClientToServer;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return Direction.ServerToClient;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConnectionStream FindStream(IPAddress srcAddr, int srcPort, int index)
|
||||||
|
{
|
||||||
|
if (index < 0 || index > 3)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dir = GetDirection(srcAddr, srcPort);
|
||||||
|
|
||||||
|
if(dir == Direction.ClientToServer)
|
||||||
|
{
|
||||||
|
return _client_streams[index];
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return _server_streams[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ConnectionStream
|
||||||
|
{
|
||||||
|
public class QueuedPacket
|
||||||
|
{
|
||||||
|
public byte[] Data { get; set; }
|
||||||
|
public DateTime PacketTime { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConnectionStream()
|
||||||
|
{
|
||||||
|
Sequence = 0;
|
||||||
|
CurrentFragmentedBytes = 0;
|
||||||
|
TotalFragmentedBytes = 0;
|
||||||
|
FragmentBuffer = null;
|
||||||
|
PacketQueue = new Dictionary<ushort, QueuedPacket>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ushort Sequence { get; set; }
|
||||||
|
public uint CurrentFragmentedBytes { get; set; }
|
||||||
|
public uint TotalFragmentedBytes { get; set; }
|
||||||
|
public byte[] FragmentBuffer { get; set; }
|
||||||
|
public Dictionary<ushort, QueuedPacket> PacketQueue { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace StreamParser.Common.Daybreak
|
||||||
|
{
|
||||||
|
public ref struct GamePacket
|
||||||
|
{
|
||||||
|
private readonly ReadOnlySpan<byte> _data;
|
||||||
|
|
||||||
|
public GamePacket(ReadOnlySpan<byte> data)
|
||||||
|
{
|
||||||
|
_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly override string ToString()
|
||||||
|
{
|
||||||
|
return ToString(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly string ToString(int columns)
|
||||||
|
{
|
||||||
|
int rows = _data.Length / columns;
|
||||||
|
if (_data.Length % columns != 0)
|
||||||
|
{
|
||||||
|
rows += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int expected = (10 + columns * 4) * rows;
|
||||||
|
var sb = new StringBuilder(expected);
|
||||||
|
|
||||||
|
for(var i = 0; i < rows; ++i)
|
||||||
|
{
|
||||||
|
sb.AppendFormat("{0} |", (i * columns).ToString("X5"));
|
||||||
|
|
||||||
|
for(var j = 0; j < columns; ++j)
|
||||||
|
{
|
||||||
|
var index = (i * 16) + j;
|
||||||
|
if (index >= _data.Length)
|
||||||
|
{
|
||||||
|
sb.Append(" ");
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
var c = _data[index];
|
||||||
|
sb.AppendFormat("{0,3}", c.ToString("X2"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Append(" | ");
|
||||||
|
|
||||||
|
for (var j = 0; j < columns; ++j)
|
||||||
|
{
|
||||||
|
var index = (i * 16) + j;
|
||||||
|
if (index >= _data.Length)
|
||||||
|
{
|
||||||
|
sb.Append(" ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var c = _data[index];
|
||||||
|
var ch = (char)c;
|
||||||
|
if (char.IsLetterOrDigit(ch) || char.IsPunctuation(ch) || char.IsSymbol(ch) || (ch == ' '))
|
||||||
|
{
|
||||||
|
sb.Append(ch);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.Append(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly string ToModelString(int max_taken, bool hex)
|
||||||
|
{
|
||||||
|
int expected = Math.Min(_data.Length, max_taken) * (hex ? 2 : 1);
|
||||||
|
if(expected <= 0)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sb = new StringBuilder(expected);
|
||||||
|
|
||||||
|
for(var i = 0; i < Math.Min(_data.Length, max_taken); ++i)
|
||||||
|
{
|
||||||
|
var c = _data[i];
|
||||||
|
if(hex)
|
||||||
|
{
|
||||||
|
sb.Append(c.ToString("X2"));
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
var ch = (char)c;
|
||||||
|
if (char.IsLetterOrDigit(ch) || char.IsPunctuation(ch) || char.IsSymbol(ch) || (ch == ' '))
|
||||||
|
{
|
||||||
|
sb.Append(ch);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.Append(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace StreamParser.Common.Daybreak
|
||||||
|
{
|
||||||
|
public enum Direction
|
||||||
|
{
|
||||||
|
ClientToServer,
|
||||||
|
ServerToClient
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ConnectionType
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
Login,
|
||||||
|
World,
|
||||||
|
Chat,
|
||||||
|
Zone
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IConnection
|
||||||
|
{
|
||||||
|
delegate void OnPacketRecvHandler(Connection connection, Direction direction, DateTime packetTime, ReadOnlySpan<byte> data);
|
||||||
|
OnPacketRecvHandler OnPacketRecv { get; set; }
|
||||||
|
|
||||||
|
void ProcessPacket(IPAddress srcAddr, int srcPort, DateTime packetTime, ReadOnlySpan<byte> data);
|
||||||
|
bool Match(IPAddress srcAddr, int srcPort, IPAddress dstAddr, int dstPort);
|
||||||
|
|
||||||
|
ConnectionType ConnectionType { get; }
|
||||||
|
IPAddress ClientAddress { get; }
|
||||||
|
int ClientPort { get; }
|
||||||
|
IPAddress ServerAddress { get; }
|
||||||
|
int ServerPort { get; }
|
||||||
|
Guid Id { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace StreamParser.Common.Daybreak
|
||||||
|
{
|
||||||
|
public interface IParser
|
||||||
|
{
|
||||||
|
delegate void ConnectionHandler(IConnection connection, DateTime connectionTime);
|
||||||
|
ConnectionHandler OnNewConnection { get; set; }
|
||||||
|
ConnectionHandler OnLostConnection { get; set; }
|
||||||
|
void Parse(string filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace StreamParser.Common.Daybreak
|
||||||
|
{
|
||||||
|
public class Opcode
|
||||||
|
{
|
||||||
|
public const byte Padding = 0;
|
||||||
|
public const byte SessionRequest = 1;
|
||||||
|
public const byte SessionResponse = 2;
|
||||||
|
public const byte Combined = 3;
|
||||||
|
public const byte SessionDisconnect = 5;
|
||||||
|
public const byte KeepAlive = 6;
|
||||||
|
public const byte SessionStatRequest = 7;
|
||||||
|
public const byte SessionStatResponse = 8;
|
||||||
|
public const byte Packet = 9;
|
||||||
|
public const byte Packet2 = 10;
|
||||||
|
public const byte Packet3 = 11;
|
||||||
|
public const byte Packet4 = 12;
|
||||||
|
public const byte Fragment = 13;
|
||||||
|
public const byte Fragment2 = 14;
|
||||||
|
public const byte Fragment3 = 15;
|
||||||
|
public const byte Fragment4 = 16;
|
||||||
|
public const byte OutOfOrderAck = 17;
|
||||||
|
public const byte OutOfOrderAck2 = 18;
|
||||||
|
public const byte OutOfOrderAck3 = 19;
|
||||||
|
public const byte OutOfOrderAck4 = 20;
|
||||||
|
public const byte Ack = 21;
|
||||||
|
public const byte Ack2 = 22;
|
||||||
|
public const byte Ack3 = 23;
|
||||||
|
public const byte Ack4 = 22;
|
||||||
|
public const byte AppCombined = 25;
|
||||||
|
public const byte OutboundPing = 28;
|
||||||
|
public const byte OutOfSession = 29;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using SharpPcap;
|
||||||
|
using SharpPcap.LibPcap;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace StreamParser.Common.Daybreak
|
||||||
|
{
|
||||||
|
public class Parser : IParser
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Dependencies
|
||||||
|
*/
|
||||||
|
private readonly ILogger<Parser> _logger;
|
||||||
|
private readonly List<IConnection> _connections = new List<IConnection>();
|
||||||
|
|
||||||
|
public IParser.ConnectionHandler OnNewConnection { get; set; }
|
||||||
|
public IParser.ConnectionHandler OnLostConnection { get; set; }
|
||||||
|
|
||||||
|
public Parser(ILogger<Parser> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Parse(string filename)
|
||||||
|
{
|
||||||
|
ICaptureDevice device = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
device = new CaptureFileReaderDevice(filename);
|
||||||
|
device.Open();
|
||||||
|
|
||||||
|
device.OnPacketArrival += new PacketArrivalEventHandler(OnPacketCapture);
|
||||||
|
|
||||||
|
device.Capture();
|
||||||
|
device.Close();
|
||||||
|
} catch(Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error reading device capture.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPacketCapture(object sender, PacketCapture capture)
|
||||||
|
{
|
||||||
|
var raw = capture.GetPacket();
|
||||||
|
if (raw.LinkLayerType == PacketDotNet.LinkLayers.Ethernet)
|
||||||
|
{
|
||||||
|
var packet = PacketDotNet.Packet.ParsePacket(raw.LinkLayerType, raw.Data);
|
||||||
|
var ipPacket = packet.Extract<PacketDotNet.IPv4Packet>();
|
||||||
|
var udpPacket = packet.Extract<PacketDotNet.UdpPacket>();
|
||||||
|
|
||||||
|
if (ipPacket != null && udpPacket != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ProcessPacket(ipPacket.SourceAddress,
|
||||||
|
udpPacket.SourcePort,
|
||||||
|
ipPacket.DestinationAddress,
|
||||||
|
udpPacket.DestinationPort,
|
||||||
|
raw.Timeval.Date,
|
||||||
|
udpPacket.PayloadData);
|
||||||
|
} catch(Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error processing packet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessPacket(IPAddress srcAddr, int srcPort, IPAddress dstAddr, int dstPort, DateTime packetTime, ReadOnlySpan<byte> data)
|
||||||
|
{
|
||||||
|
if(data.Length < 2)
|
||||||
|
{
|
||||||
|
_logger.LogTrace("Tossing packet, {0} was less than minimum packet size", data.Length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var c = FindConnection(srcAddr, srcPort, dstAddr, dstPort);
|
||||||
|
|
||||||
|
if(c != null)
|
||||||
|
{
|
||||||
|
c.ProcessPacket(srcAddr, srcPort, packetTime, data);
|
||||||
|
}
|
||||||
|
else if (data[0] == 0 && data[1] == Opcode.SessionRequest)
|
||||||
|
{
|
||||||
|
if(data.Length != 24)
|
||||||
|
{
|
||||||
|
_logger.LogTrace("Tossing packet, {0} was not the right size for a SessionRequest", data.Length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = new Connection(this, srcAddr, srcPort, dstAddr, dstPort);
|
||||||
|
_connections.Add(c);
|
||||||
|
c.ProcessPacket(srcAddr, srcPort, packetTime, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IConnection FindConnection(IPAddress srcAddr, int srcPort, IPAddress dstAddr, int dstPort)
|
||||||
|
{
|
||||||
|
foreach (var c in _connections)
|
||||||
|
{
|
||||||
|
if (c.Match(srcAddr, srcPort, dstAddr, dstPort))
|
||||||
|
{
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace StreamParser.Common.Util
|
||||||
|
{
|
||||||
|
public class Crc32
|
||||||
|
{
|
||||||
|
private uint[] _encodeTable =
|
||||||
|
{
|
||||||
|
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
|
||||||
|
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
||||||
|
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
|
||||||
|
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
|
||||||
|
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
|
||||||
|
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
|
||||||
|
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
|
||||||
|
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
|
||||||
|
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
|
||||||
|
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
|
||||||
|
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
|
||||||
|
0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
|
||||||
|
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
|
||||||
|
0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
|
||||||
|
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
|
||||||
|
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
|
||||||
|
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
|
||||||
|
0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
||||||
|
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
|
||||||
|
0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
|
||||||
|
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
|
||||||
|
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
|
||||||
|
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
|
||||||
|
0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
|
||||||
|
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
|
||||||
|
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
|
||||||
|
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
|
||||||
|
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
|
||||||
|
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
|
||||||
|
0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
|
||||||
|
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
|
||||||
|
0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
|
||||||
|
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
|
||||||
|
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
|
||||||
|
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
|
||||||
|
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
||||||
|
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
|
||||||
|
0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
|
||||||
|
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
|
||||||
|
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
|
||||||
|
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
|
||||||
|
0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
|
||||||
|
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
|
||||||
|
0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
|
||||||
|
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
|
||||||
|
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
|
||||||
|
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
|
||||||
|
0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
|
||||||
|
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
|
||||||
|
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
|
||||||
|
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
|
||||||
|
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
|
||||||
|
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
|
||||||
|
0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
||||||
|
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
|
||||||
|
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
|
||||||
|
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
|
||||||
|
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
|
||||||
|
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
|
||||||
|
0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
|
||||||
|
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
|
||||||
|
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
|
||||||
|
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
|
||||||
|
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
|
||||||
|
};
|
||||||
|
|
||||||
|
public int Calculate(ReadOnlySpan<byte> data)
|
||||||
|
{
|
||||||
|
uint crc = 0xffffffff;
|
||||||
|
|
||||||
|
for (int i = 0; i < data.Length; ++i)
|
||||||
|
{
|
||||||
|
crc = ((crc >> 8) & 0x00FFFFFF) ^ _encodeTable[(crc ^ data[i]) & 0x000000FF];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)~crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Calculate(ReadOnlySpan<byte> data, int key)
|
||||||
|
{
|
||||||
|
uint crc = 0xffffffff;
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
crc = ((crc >> 8) & 0x00FFFFFF) ^ _encodeTable[(crc ^ ((key >> (i * 8)) & 0xff)) & 0x000000FF];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < data.Length; ++i)
|
||||||
|
{
|
||||||
|
crc = ((crc >> 8) & 0x00FFFFFF) ^ _encodeTable[(crc ^ data[i]) & 0x000000FF];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)~crc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<RootNamespace>StreamParser.Common</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Iconic.Zlib.Netstandard" Version="1.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
|
||||||
|
<PackageReference Include="SharpPcap" Version="6.3.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.6.30114.105
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "stream_parser", "stream_parser\stream_parser.csproj", "{A5662497-4771-4A00-92E7-E7790CEB20E9}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "common", "common\common.csproj", "{FC625344-C003-4602-A571-D8811CF5B37A}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{FC625344-C003-4602-A571-D8811CF5B37A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{FC625344-C003-4602-A571-D8811CF5B37A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{FC625344-C003-4602-A571-D8811CF5B37A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{FC625344-C003-4602-A571-D8811CF5B37A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{FC625344-C003-4602-A571-D8811CF5B37A}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{FC625344-C003-4602-A571-D8811CF5B37A}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{FC625344-C003-4602-A571-D8811CF5B37A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{FC625344-C003-4602-A571-D8811CF5B37A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{FC625344-C003-4602-A571-D8811CF5B37A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{FC625344-C003-4602-A571-D8811CF5B37A}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{FC625344-C003-4602-A571-D8811CF5B37A}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{FC625344-C003-4602-A571-D8811CF5B37A}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {89CDF826-F878-4BF4-8583-B9E66FE8B61D}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
@@ -0,0 +1,337 @@
|
|||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using StreamParser.Common.Daybreak;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using CommandLine;
|
||||||
|
using System.Globalization;
|
||||||
|
using Org.BouncyCastle.Crypto.Engines;
|
||||||
|
using Org.BouncyCastle.Crypto.Modes;
|
||||||
|
using Org.BouncyCastle.Crypto;
|
||||||
|
using Org.BouncyCastle.Crypto.Parameters;
|
||||||
|
using Ionic.Zlib;
|
||||||
|
|
||||||
|
namespace StreamParser
|
||||||
|
{
|
||||||
|
public class ConsoleHostedService : IHostedService
|
||||||
|
{
|
||||||
|
private class ParsedPacket {
|
||||||
|
public byte[] Data { get; set; }
|
||||||
|
public Direction Direction { get; set; }
|
||||||
|
public DateTime Time { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ParsedConnection
|
||||||
|
{
|
||||||
|
public IPAddress ClientAddress { get; set; }
|
||||||
|
public int ClientPort { get; set; }
|
||||||
|
public IPAddress ServerAddress { get; set; }
|
||||||
|
public int ServerPort { get; set; }
|
||||||
|
public ConnectionType ConnectionType { get; set; }
|
||||||
|
public List<ParsedPacket> Packets { get; set; }
|
||||||
|
public DateTime ConnectedTime { get; set; }
|
||||||
|
public DateTime? DisconnectedTime { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly ILogger<ConsoleHostedService> _logger;
|
||||||
|
private readonly IHostApplicationLifetime _applicationLifetime;
|
||||||
|
private readonly IParser _parser;
|
||||||
|
private readonly Dictionary<Guid, ParsedConnection> _connections = new Dictionary<Guid, ParsedConnection>();
|
||||||
|
|
||||||
|
public ConsoleHostedService(ILogger<ConsoleHostedService> logger,
|
||||||
|
IHostApplicationLifetime applicationLifetime,
|
||||||
|
IParser parser)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_applicationLifetime = applicationLifetime;
|
||||||
|
_parser = parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_applicationLifetime.ApplicationStarted.Register(() =>
|
||||||
|
{
|
||||||
|
var args = Environment.GetCommandLineArgs();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CommandLine.Parser.Default.ParseArguments<ConsoleHostedServiceOptions>(args)
|
||||||
|
.WithParsed<ConsoleHostedServiceOptions>(o =>
|
||||||
|
{
|
||||||
|
_parser.OnNewConnection += OnNewConnection;
|
||||||
|
_parser.OnLostConnection += OnLostConnection;
|
||||||
|
|
||||||
|
foreach (var f in o.Input)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Parsing {0}...", f);
|
||||||
|
_parser.Parse(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var c in _connections)
|
||||||
|
{
|
||||||
|
if (c.Value.ConnectionType == ConnectionType.Unknown && !o.DumpUnknownStreams)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o.Text)
|
||||||
|
{
|
||||||
|
DumpConnectionToTextFile(c.Value, o.Output, o.Decrypt, o.DecompressOpcodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_applicationLifetime.StopApplication();
|
||||||
|
})
|
||||||
|
.WithNotParsed<ConsoleHostedServiceOptions>(e =>
|
||||||
|
{
|
||||||
|
bool stops_processing = false;
|
||||||
|
foreach (var err in e)
|
||||||
|
{
|
||||||
|
stops_processing = stops_processing || err.StopsProcessing || err is MissingRequiredOptionError;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stops_processing)
|
||||||
|
{
|
||||||
|
_applicationLifetime.StopApplication();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error parsing command line arguments");
|
||||||
|
_applicationLifetime.StopApplication();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNewConnection(IConnection connection, DateTime connectionTime)
|
||||||
|
{
|
||||||
|
_logger.LogTrace("New connection {0}:{1} <-> {2}:{3} of type {4}",
|
||||||
|
connection.ClientAddress,
|
||||||
|
connection.ClientPort,
|
||||||
|
connection.ServerAddress,
|
||||||
|
connection.ServerPort,
|
||||||
|
connection.ConnectionType);
|
||||||
|
connection.OnPacketRecv += OnPacketRecv;
|
||||||
|
|
||||||
|
_connections.Add(connection.Id, new ParsedConnection
|
||||||
|
{
|
||||||
|
ClientAddress = connection.ClientAddress,
|
||||||
|
ClientPort = connection.ClientPort,
|
||||||
|
ServerAddress = connection.ServerAddress,
|
||||||
|
ServerPort = connection.ServerPort,
|
||||||
|
ConnectionType = connection.ConnectionType,
|
||||||
|
Packets = new List<ParsedPacket>(),
|
||||||
|
ConnectedTime = connectionTime,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLostConnection(IConnection connection, DateTime connectionTime)
|
||||||
|
{
|
||||||
|
_logger.LogTrace("Lost connection {0}:{1} <-> {2}:{3}",
|
||||||
|
connection.ClientAddress,
|
||||||
|
connection.ClientPort,
|
||||||
|
connection.ServerAddress,
|
||||||
|
connection.ServerPort);
|
||||||
|
connection.OnPacketRecv -= OnPacketRecv;
|
||||||
|
|
||||||
|
var parsedConnection = _connections.GetValueOrDefault(connection.Id);
|
||||||
|
parsedConnection.DisconnectedTime = connectionTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPacketRecv(IConnection connection, Direction direction, DateTime packetTime, ReadOnlySpan<byte> data)
|
||||||
|
{
|
||||||
|
var parsedConnection = _connections.GetValueOrDefault(connection.Id);
|
||||||
|
parsedConnection.Packets.Add(new ParsedPacket
|
||||||
|
{
|
||||||
|
Data = data.ToArray(),
|
||||||
|
Direction = direction,
|
||||||
|
Time = packetTime
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DumpConnectionToTextFile(ParsedConnection c, string output, bool decrypt, IEnumerable<int> decompressOpcodes)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var path = output + string.Format("{0}-{1}.txt", c.ConnectionType.ToString().ToLower(), c.ConnectedTime.ToString("yyyyMMddHHmmssfff"));
|
||||||
|
if (File.Exists(path))
|
||||||
|
{
|
||||||
|
File.Delete(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
File.AppendAllText(path, string.Format("### type: {0}\n", c.ConnectionType));
|
||||||
|
File.AppendAllText(path, string.Format("### started: {0}\n", c.ConnectedTime.ToString("s")));
|
||||||
|
File.AppendAllText(path, string.Format("### ended: {0}\n", c.DisconnectedTime.HasValue ? c.DisconnectedTime.Value.ToString("s") : "unknown"));
|
||||||
|
File.AppendAllText(path, string.Format("### client: {0}:{1}\n", c.ClientAddress.ToString(), c.ClientPort));
|
||||||
|
File.AppendAllText(path, string.Format("### server: {0}:{1}\n\n", c.ServerAddress.ToString(), c.ServerPort));
|
||||||
|
|
||||||
|
foreach(var p in c.Packets)
|
||||||
|
{
|
||||||
|
ReadOnlySpan<byte> data = p.Data;
|
||||||
|
string dir = p.Direction == Direction.ClientToServer ? "Client -> Server" : "Server -> Client";
|
||||||
|
|
||||||
|
switch (c.ConnectionType)
|
||||||
|
{
|
||||||
|
case ConnectionType.Login:
|
||||||
|
{
|
||||||
|
int opcode = BitConverter.ToUInt16(data.Slice(0, 2));
|
||||||
|
{
|
||||||
|
File.AppendAllText(path,
|
||||||
|
string.Format("{0} [Opcode: 0x{1}, Size: {2}] ({3})\n", dir, opcode.ToString("X4"), data.Length - 2, p.Time.ToString("s")));
|
||||||
|
|
||||||
|
var gp = new GamePacket(data.Slice(2));
|
||||||
|
File.AppendAllText(path, string.Format("{0}\n", gp.ToString()));
|
||||||
|
|
||||||
|
if(decrypt && opcode == 2 || opcode == 24)
|
||||||
|
{
|
||||||
|
var encrypted_block = data.Slice(12, data.Length - 12);
|
||||||
|
var dec = EQDecrypt(encrypted_block);
|
||||||
|
|
||||||
|
if(dec != null)
|
||||||
|
{
|
||||||
|
File.AppendAllText(path, string.Format("[Decrypted Data, Offset: {0}, Size: {1}]\n", 10, dec.Length));
|
||||||
|
gp = new GamePacket(dec);
|
||||||
|
File.AppendAllText(path, string.Format("{0}\n", gp.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ConnectionType.Chat:
|
||||||
|
{
|
||||||
|
int opcode = data[0];
|
||||||
|
File.AppendAllText(path,
|
||||||
|
string.Format("{0} [Opcode: 0x{1}, Size: {2}] ({3})\n", dir, opcode.ToString("X2"), data.Length - 1, p.Time.ToString("s")));
|
||||||
|
|
||||||
|
var gp = new GamePacket(data.Slice(1));
|
||||||
|
File.AppendAllText(path, string.Format("{0}\n", gp.ToString()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
bool reported_decompressed = false;
|
||||||
|
int opcode = BitConverter.ToUInt16(data.Slice(0, 2));
|
||||||
|
foreach (var decompressOpcode in decompressOpcodes)
|
||||||
|
{
|
||||||
|
if (opcode == decompressOpcode && data.Length > 12)
|
||||||
|
{
|
||||||
|
if (data[10] == 0x78 && data[11] == 0xDA)
|
||||||
|
{
|
||||||
|
var totalLen = BitConverter.ToInt32(data.Slice(6, 4));
|
||||||
|
if (totalLen > 0)
|
||||||
|
{
|
||||||
|
var decompressed = Inflate(data.Slice(10));
|
||||||
|
if(decompressed != null)
|
||||||
|
{
|
||||||
|
var decompressed_gp = new GamePacket(decompressed);
|
||||||
|
File.AppendAllText(path,
|
||||||
|
string.Format("{0} [Opcode: 0x{1}, Size (decompressed): {2}] ({3})\n", dir, opcode.ToString("X4"), totalLen, p.Time.ToString("s")));
|
||||||
|
|
||||||
|
File.AppendAllText(path, string.Format("{0}\n", decompressed_gp.ToString()));
|
||||||
|
reported_decompressed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (data[6] == 0x78 && data[7] == 0xDA)
|
||||||
|
{
|
||||||
|
var totalLen = BitConverter.ToInt32(data.Slice(2, 4));
|
||||||
|
if (totalLen > 0)
|
||||||
|
{
|
||||||
|
var decompressed = Inflate(data.Slice(6));
|
||||||
|
if (decompressed != null)
|
||||||
|
{
|
||||||
|
File.AppendAllText(path,
|
||||||
|
string.Format("{0} [Opcode: 0x{1}, Size (decompressed): {2}] ({3})\n", dir, opcode.ToString("X4"), totalLen, p.Time.ToString("s")));
|
||||||
|
|
||||||
|
var decompressed_gp = new GamePacket(decompressed);
|
||||||
|
File.AppendAllText(path, string.Format("{0}\n", decompressed_gp.ToString()));
|
||||||
|
reported_decompressed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reported_decompressed)
|
||||||
|
{
|
||||||
|
File.AppendAllText(path,
|
||||||
|
string.Format("{0} [Opcode: 0x{1}, Size: {2}] ({3})\n", dir, opcode.ToString("X4"), data.Length - 2, p.Time.ToString("s")));
|
||||||
|
var gp = new GamePacket(data.Slice(2));
|
||||||
|
File.AppendAllText(path, string.Format("{0}\n", gp.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error dumping connection {0} to txt file", c.ConnectedTime.ToString("s"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] Inflate(ReadOnlySpan<byte> data)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var out_stream = new MemoryStream())
|
||||||
|
using (var in_stream = new MemoryStream(data.ToArray()))
|
||||||
|
{
|
||||||
|
const int bufferLen = 4096;
|
||||||
|
var buffer = new byte[bufferLen];
|
||||||
|
using (var zs = new ZlibStream(in_stream, CompressionMode.Decompress))
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
r = zs.Read(buffer, 0, bufferLen);
|
||||||
|
out_stream.Write(buffer, 0, r);
|
||||||
|
} while (r == bufferLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
var ret = out_stream.ToArray();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error inflating data");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] EQDecrypt(ReadOnlySpan<byte> data)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var desEngine = new DesEngine();
|
||||||
|
var cbcBlockCipher = new CbcBlockCipher(desEngine);
|
||||||
|
var bufferedBlockCipher = new BufferedBlockCipher(cbcBlockCipher);
|
||||||
|
bufferedBlockCipher.Init(false, new ParametersWithIV(new KeyParameter(new byte[16]), new byte[8]));
|
||||||
|
var cipherData = new byte[bufferedBlockCipher.GetOutputSize(data.Length)];
|
||||||
|
var outputLength = bufferedBlockCipher.ProcessBytes(data.ToArray(), 0, data.Length, cipherData, 0);
|
||||||
|
bufferedBlockCipher.DoFinal(cipherData, outputLength);
|
||||||
|
return cipherData;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error decrypting EQ Datablock");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using CommandLine;
|
||||||
|
|
||||||
|
namespace StreamParser
|
||||||
|
{
|
||||||
|
public class ConsoleHostedServiceOptions
|
||||||
|
{
|
||||||
|
[Option("input", Required = true, HelpText = "Input pcap files to be processed.")]
|
||||||
|
public IEnumerable<string> Input { get; set; }
|
||||||
|
|
||||||
|
[Option("output", Default = "output/", HelpText = "Directory to put output files")]
|
||||||
|
public string Output { get; set; }
|
||||||
|
|
||||||
|
[Option("text", Default = true, HelpText = "Dump connections to text files.")]
|
||||||
|
public bool Text { get; set; }
|
||||||
|
|
||||||
|
[Option("binary", Default = false, HelpText = "Dump connections to binary files.")]
|
||||||
|
public bool Binary { get; set; }
|
||||||
|
|
||||||
|
[Option("decrypt", Default = false, HelpText = "Decrypt the \"Encrypted\" packets.")]
|
||||||
|
public bool Decrypt { get; set; }
|
||||||
|
|
||||||
|
[Option("decompress", Default = null, HelpText = "Which opcodes to attempt to decompress")]
|
||||||
|
public IEnumerable<int> DecompressOpcodes { get; set; }
|
||||||
|
|
||||||
|
[Option("enable-unknown-streams", Default = false, HelpText = "Enable dumping of unknown streams; they will be skipped otherwise.")]
|
||||||
|
public bool DumpUnknownStreams { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using StreamParser.Common.Daybreak;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace StreamParser
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
CreateHostBuilder(args).Build().Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IHostBuilder CreateHostBuilder(string[] args)
|
||||||
|
{
|
||||||
|
return Host.CreateDefaultBuilder(args)
|
||||||
|
.ConfigureServices((hostContext, services) =>
|
||||||
|
{
|
||||||
|
services.AddScoped<IParser, Parser>();
|
||||||
|
services.AddHostedService<ConsoleHostedService>();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"stream_parser": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"commandLineArgs": "--input input/cap_login_to_zone_10_16_2024.pcap --output output_test/ --binary --decrypt --decompress 16742 168 30346",
|
||||||
|
"workingDirectory": "E:\\Projects\\stream_parser\\stream_parser\\bin\\Debug\\net6.0\\"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user