Compare commits

..

256 Commits

Author SHA1 Message Date
JJ 871f320311 [Release] 22.35.0 (#3754)
### Bots

* Add BotHealOnLevel to fully heal/mana on level. ([#3745](https://github.com/EQEmu/Server/pull/3745)) @nytmyr 2023-12-08
* Fix bots learning spells on level ([#3744](https://github.com/EQEmu/Server/pull/3744)) @nytmyr 2023-12-08

### Bug

* Fix blocked spells regression from #3638 ([#3753](https://github.com/EQEmu/Server/pull/3753)) @joligario 2023-12-11
* PR 3638 Missed the blocked spells repository updates ([#3748](https://github.com/EQEmu/Server/pull/3748)) @fryguy503 2023-12-08

### CMake

* Update minimum version of CMake ([#3743](https://github.com/EQEmu/Server/pull/3743)) @joligario 2023-12-08

### Code

* Remove hard-coded Status Checks ([#3727](https://github.com/EQEmu/Server/pull/3727)) @Kinglykrab 2023-12-03

### Commands

* #guild set CharName 0 did not remove char from guild. ([#3717](https://github.com/EQEmu/Server/pull/3717)) @noudess 2023-11-25
* #petname changes PC to Nobody if selected. ([#3720](https://github.com/EQEmu/Server/pull/3720)) @noudess 2023-11-26
* Add #show aas Command ([#3710](https://github.com/EQEmu/Server/pull/3710)) @Kinglykrab 2023-11-26
* Add #task complete Command ([#3711](https://github.com/EQEmu/Server/pull/3711)) @Kinglykrab 2023-11-26
* Cleanup #acceptrules Command ([#3716](https://github.com/EQEmu/Server/pull/3716)) @Kinglykrab 2023-11-26
* Cleanup #disarmtrap Command ([#3713](https://github.com/EQEmu/Server/pull/3713)) @Kinglykrab 2023-11-26
* Cleanup #list Command ([#3714](https://github.com/EQEmu/Server/pull/3714)) @Kinglykrab 2023-11-26
* Cleanup #movement Command ([#3715](https://github.com/EQEmu/Server/pull/3715)) @Kinglykrab 2023-11-26
* Cleanup #object Command ([#3722](https://github.com/EQEmu/Server/pull/3722)) @Kinglykrab 2023-12-03
* Cleanup #zonebootup and #zoneshutdown Commands ([#3729](https://github.com/EQEmu/Server/pull/3729)) @Kinglykrab 2023-12-03
* Fix formatting of #wpinfo output. ([#3728](https://github.com/EQEmu/Server/pull/3728)) @noudess 2023-12-01

### Database

* Add primary key to keyring table ([#3746](https://github.com/EQEmu/Server/pull/3746)) @Kinglykrab 2023-12-08
* Consolidate Starting Items Table ([#3723](https://github.com/EQEmu/Server/pull/3723)) @Kinglykrab 2023-11-30
* Extra whitespace in #3723 ([#3730](https://github.com/EQEmu/Server/pull/3730)) @joligario 2023-12-02
* Minor adjustment to #3726 ([#3732](https://github.com/EQEmu/Server/pull/3732)) @joligario 2023-12-03
* Modify `updated` column in `items` table with proper default. ([#3726](https://github.com/EQEmu/Server/pull/3726)) @joligario 2023-12-02
* Pull Spell Group Cache from Content DB ([#3749](https://github.com/EQEmu/Server/pull/3749)) @fryguy503 2023-12-08

### Faction

* Alliance line is only allowed 1 faction change at a time. ([#3718](https://github.com/EQEmu/Server/pull/3718)) @noudess 2023-11-26

### Fixes

* Changing Group Leader Invalidated GetLeaderName() ([#3712](https://github.com/EQEmu/Server/pull/3712)) @Kinglykrab 2023-11-26
* Fix 9245 SQL ([#3740](https://github.com/EQEmu/Server/pull/3740)) @Kinglykrab 2023-12-05
* Fix Swarm Pets Requiring NPC Aggros Flag ([#3738](https://github.com/EQEmu/Server/pull/3738)) @Kinglykrab 2023-12-05
* Guild Message Limits ([#3724](https://github.com/EQEmu/Server/pull/3724)) @neckkola 2023-11-29

### Quest API

* Add EVENT_AA_GAIN to AddAAPoints() ([#3733](https://github.com/EQEmu/Server/pull/3733)) @Kinglykrab 2023-12-03
* Add GMMove Overloads to Perl/Lua ([#3719](https://github.com/EQEmu/Server/pull/3719)) @Kinglykrab 2023-11-25

### Scripts

* Import items into `items_new` table instead of writing directly to the existing `items` table. ([#3725](https://github.com/EQEmu/Server/pull/3725)) @joligario 2023-11-30
* Revert database engine change from #3702. ([#3736](https://github.com/EQEmu/Server/pull/3736)) @joligario 2023-12-03
* Update 13th Floor Import Tool ([#3702](https://github.com/EQEmu/Server/pull/3702)) @joligario 2023-11-26
2023-12-10 22:07:09 -05:00
JJ a222128599 [Bug] Fix blocked spells regression from #3638 (#3753)
Fixes #3747
2023-12-10 21:40:06 -05:00
JJ 45b249e33d [CMake] Update minimum version of CMake (#3743)
```
CMake Deprecation Warning at client_files/CMakeLists.txt:1 (CMAKE_MINIMUM_REQUIRED):
  Compatibility with CMake < 3.5 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value or use a ...<max> suffix to tell
  CMake that the project does not need compatibility with older versions.
```
2023-12-08 12:48:59 -08:00
Fryguy c24834de5d [Database] Pull Spell Group Cache from Content DB (#3749) 2023-12-08 15:41:09 -05:00
Fryguy 841d7f2700 [Bug] PR 3638 Missed the blocked spells repository updates (#3748)
Ran generator to update blocked_spells Repo
2023-12-08 15:19:54 -05:00
Alex King 56c29154f0 [Database] Add primary key to keyring table (#3746)
* [Database] Add primary key to keyring table

# Notes
- Adds a primary key of `id` to `keyring` table so we can use it with repositories.

* Update version.h

* Update client.cpp

* Update client.cpp
2023-12-07 23:12:01 -05:00
nytmyr 6466c2ff21 [Bots] Add BotHealOnLevel to fully heal/mana on level. (#3745)
Adds the rule ***Bots, BotHealOnLevel***, default false, to control whether or not bots will gain full health and mana when their owner levels.
2023-12-07 22:25:17 -05:00
nytmyr 16dc210cd8 [Bots] Fix bots learning spells on level (#3744)
Previously bots would need to be zoned or camped/spawned to begin using new spells for their level.
2023-12-07 21:19:21 -05:00
Alex King 77045f558e [Bug Fix] Fix 9245 SQL (#3740)
* [Bug Fix] Fix 9245 SQL

# Notes
- Should be a `;` not `,`.

* Update database_update_manifest.cpp
2023-12-04 22:21:31 -05:00
Alex King e1fa2d5bc5 [Bug Fix] Fix Swarm Pets Requiring NPC Aggros Flag (#3738)
# Notes
- https://github.com/EQEmu/Server/pull/3595 made swarm pets require the `npc_aggro` flag to be set to attack.
2023-12-04 19:05:16 -05:00
Alex King b03f52de18 [Commands] Cleanup #object Command (#3722)
* [Commands] Cleanup #object Command

# Notes
- Cleanup messages and logic.
- Introduce enum for object types.
- Set ground work for object manipulation similar to door manipulation.

* Update object_manipulation.cpp

* Final push

* Update client_packet.cpp

* Update object_manipulation.cpp

* Update object_manipulation.cpp

* Update object.h

* Update client_packet.cpp

* Update client_packet.cpp

* Push.

* Update version.h

* Update database_update_manifest.cpp

* Update zone.cpp
2023-12-03 17:42:27 -05:00
JJ 226cc3d6cb [Scripts] Revert database engine change from #3702. (#3736)
InnoDB doesn't like the lengths. Will need to address that in the future.
2023-12-03 14:17:58 -05:00
Alex King 7f54e26dec [Quest API] Add EVENT_AA_GAIN to AddAAPoints() (#3733)
# Notes
- Using this method did not call `EVENT_AA_GAIN`.
2023-12-03 12:41:06 -05:00
Alex King 11a81d8e8a [Commands] Cleanup #zonebootup and #zoneshutdown Commands (#3729)
# Notes
- Cleanup messages and logic.
2023-12-03 12:40:54 -05:00
Alex King e719aa43cf [Cleanup] Remove hard-coded Status Checks (#3727)
* [Cleanup] Remove hard-coded Status Checks

# Notes
- Removed the hard-coded GM status checks since if you have access to the command we can now limit access to subcommands if necessary.

* Update client_packet.cpp
2023-12-03 11:44:30 -05:00
JJ 22994e3264 [Database] Minor adjustment to #3726 (#3732) 2023-12-03 10:18:27 -05:00
JJ cfbdecad19 [Database] Extra whitespace in #3723 (#3730) 2023-12-01 21:13:08 -05:00
JJ 2427f7e034 [Database] Modify updated column in items table with proper default. (#3726)
* [Database] Modify `updated` column in `items` table with proper default.
From https://mariadb.com/kb/en/datetime/, `datetime` can be ZERO_DATE (`0000-00-00` with no time component) or between `1000-01-01 00:00:00.000000` and `9999-12-31 23:59:59.999999`. Currently, `updated` is the only datetime field that is `NOT NULL` and improperly defaulted to `0000-00-00 00:00:00`. This change matches existing structures of the other `datetime` columns.

* Update items_repository.h

* Update base_items_repository.h

* Revert "Update items_repository.h"

This reverts commit 3599f26818.
2023-12-01 21:10:52 -05:00
Paul Coene 9a6403b196 [Commands] Fix formatting of #wpinfo output. (#3728) 2023-12-01 15:28:24 -05:00
JJ d8953c5156 [Scripts] Import items into items_new table instead of writing directly to the existing items table. (#3725) 2023-11-30 17:21:00 -05:00
Alex King 33b40e83b7 [Database] Consolidate Starting Items Table (#3723)
* [Database] Consolidate Starting Items Table

# Notes
- Convert `class`, `deityId`, `race`, and `zoneid` columns to `|` separated columns.
- Consolidates up to 15 rows per item down to a singular row.
- Allows ease of use for operators.
- Entire process is automated and creates a backup of pre-existing table.

* Update shareddb.cpp

* Unnecessary.
2023-11-30 14:37:08 -05:00
Mitch Freeman e75c31d524 [Bug Fix] Guild Message Limits (#3724)
Mail to 'Guild' was failing after after 50ish members.
The buffer was set at 512, which cut truncated the message and caused the issue.
Refactored to adjust the size of the buffer based on the inbound message size.
2023-11-28 19:03:32 -05:00
Paul Coene cf1f8d5460 [Commands] #petname changes PC to Nobody if selected. (#3720) 2023-11-26 14:50:44 -05:00
Paul Coene 690cacdaab [Faction] Alliance line is only allowed 1 faction change at a time. (#3718) 2023-11-26 01:13:16 -05:00
Alex King f9f45eedcd [Commands] Cleanup #acceptrules Command (#3716)
# Note
- Cleanup messages and logic.
- Utilize repositories in database methods.
2023-11-26 01:13:08 -05:00
Alex King 93ddffa57f [Commands] Cleanup #movement Command (#3715)
# Notes
- Cleanup messages and logic.
2023-11-26 01:13:03 -05:00
Alex King c9993fb698 [Commands] Cleanup #list Command (#3714)
* [Commands] Cleanup #list Command

# Notes
- Cleanup messages and logic.
- Introduce a struct so we don't have to duplicate so much code.

* Update list.cpp
2023-11-26 01:12:58 -05:00
Alex King aa0fbb8b45 [Commands] Cleanup #disarmtrap Command (#3713)
# Notes
- Cleanup messages and logic.
2023-11-26 00:27:22 -05:00
Alex King 62532c6bdd [Bug Fix] Changing Group Leader Invalidated GetLeaderName() (#3712)
# Notes
- Utilizes fixes posted in https://github.com/EQEmu/Server/issues/3706 to resolve https://github.com/EQEmu/Server/issues/368.
- Changing group leader caused issues because we assumed `member[0]` was always leader.
2023-11-26 00:27:15 -05:00
Alex King f8c3c03185 [Commands] Add #task complete Command (#3711)
# Notes
- `#task complete [Task ID]` allows operators to complete an entire task without updating individual activities.
2023-11-26 00:27:08 -05:00
Alex King 692a90f3f0 [Commands] Add #show aas Command (#3710)
# Notes
- Allows operators to view AAs a player has purchased from ingame and their ranks.
2023-11-26 00:27:02 -05:00
JJ 3a49d851ca [Scripts] Update 13th Floor Import Tool (#3702) 2023-11-26 00:20:10 -05:00
Alex King fdc5c27061 [Quest API] Add GMMove Overloads to Perl/Lua (#3719)
# Perl
- Add `$mob->GMMove(x, y, z, heading, save_guard_spot)`.

# Lua
- Add `mob:GMMove(x, y, z, heading, save_guard_spot)`.

# Notes
- Operators weren't able to disable saving guard spots, so moving with `GMMove` meant NPCs stayed where they were moved.
2023-11-25 18:15:37 -05:00
Paul Coene 56be69ddb1 [Commands] #guild set CharName 0 did not remove char from guild. (#3717)
* [Commands] #guild set CharName 0 did not remove char from guild.

* Fix cut-n-paste error on this branch
2023-11-25 11:27:43 -05:00
Alex King 9477ff72ac [Release] 22.34.2 (#3709)
### Admin

* Update date in changelog ([#3698](https://github.com/EQEmu/Server/pull/3698)) @joligario 2023-11-19

### Code

* Fix typo in #giveitem ([#3704](https://github.com/EQEmu/Server/pull/3704)) @Kinglykrab 2023-11-22

### Fixes

* Add "IgnoreLevelBasedHasteCaps" rule to GetHaste() ([#3705](https://github.com/EQEmu/Server/pull/3705)) @jcr4990 2023-11-23
* Fix bots/Mercenaries being removed from hatelist ([#3708](https://github.com/EQEmu/Server/pull/3708)) @Kinglykrab 2023-11-23
* Fix some spell types failing IsValidSpellRange check ([#3707](https://github.com/EQEmu/Server/pull/3707)) @nytmyr 2023-11-23

### Loginserver

* Update ticket login table structure ([#3703](https://github.com/EQEmu/Server/pull/3703)) @KimLS 2023-11-22
2023-11-24 13:23:10 -05:00
Alex King 6d8e80b1e5 [Bug Fix] Fix bots/Mercenaries being removed from hatelist (#3708)
# Notes
- https://github.com/EQEmu/Server/pull/3595 caused bots, bot pets, and mercenaries to be removed from hate list because we were only checking for `IsClient()` not `IsOfClientBotMerc()`.
- Resolves an issue mentioned [here](https://discord.com/channels/212663220849213441/1177288302383079534) where NPCs would run past bots/mercenaries to attack the owner.
2023-11-23 12:36:54 -05:00
Joel ebeaef598b [Bug Fix] Add "IgnoreLevelBasedHasteCaps" rule to GetHaste() (#3705) 2023-11-22 22:45:53 -05:00
nytmyr 60b65da7f2 [Bug Fix] Fix some spell types failing IsValidSpellRange check (#3707)
Hate Reduction, Slow and DoT spells were failing IsValidSpellRange checks due to improper spell IDs being checked.

They were using the first spell in a bot's spell list by checking botSpell.id vs the proper spells in the loop.
2023-11-22 22:44:59 -05:00
Alex King 100e6698ea [Cleanup] Fix typo in #giveitem (#3704) 2023-11-22 08:26:54 -05:00
Alex 2bd94ab7a2 [Loginserver] Update ticket login table structure (#3703)
* Updates login table to support tickets in a way that makes more sense.

* Change to snake_case as requested by Akka

---------

Co-authored-by: KimLS <KimLS@peqtgc.com>
2023-11-22 02:56:47 -06:00
Akkadius 4c8d68c24b [Release] 22.34.1 2023-11-20 09:12:11 -06:00
Akkadius 1755678b1f [Release] 22.34.1 2023-11-20 09:10:22 -06:00
JJ 39e2763968 [Admin] Update date in changelog (#3698) 2023-11-19 13:22:56 -05:00
Fryguy f7780b0247 [Bug Fix] NPC Faction War prevention. (#3595)
* [Bug] NPC Faction War prevention.

This should assist with prevention of NPC Faction waring. I have been using this code on my server for over 5 years with no coredumps or any noted bugs. This was brought up as users have reported a few events where they can trigger NPC's to fight each other.

* Correct a few entries to line up with updated code.

* Re-add missing RestTimer functionality
2023-11-19 11:40:15 -05:00
JJ c0fe0f11f7 [Release] 22.34.0 (#3697)
* Update CHANGELOG.md

* Update package.json

* Update version.h

* Update CHANGELOG.md
2023-11-19 11:21:39 -05:00
nytmyr a1f1f11940 [Bots] Add ownerraid, byclass and byrace actionables and fix group-based arguments for raids. (#3680)
This adds raid support to actionables for bot commands.

This also addresses Issue #3567

If in a group, group based commands will function as normal, however if in a raid they will support raids and use the group of the bot that fits  the criteria.

This adds new actionables as well; namely, **ownerraid**, **byclass** and **byrace**.

**byclass** and **byrace** use the int of the chosen class/race. IE Shadowknight is 5, Barbarian is 2. **^create help** is an easy way for players to identify numbers associated with classes and races.

**targetgroup** will now select all bots that meet the criteria within a raid group in addition to the current functionality of groups.
**namesgroup** will now select all bots that meet the criteria within a raid group in addition to the current functionality of groups.
**ownerraid** will select all bots in the raid owned by the player.
**byclass** will selects all bots in the group or raid owned by the player that match the class.
**byrace** will selects all bots in the group or raid owned by the player that match the race

This adds actionables to **^casterrange** and **^camp** as well.
2023-11-18 23:24:49 -05:00
Alex King 4c5013e09e [Cleanup] Cleanup #giveitem and #summonitem (#3692)
# Notes
- Adds summoned messages for `#giveitem` and `#summonitem`.
- `#summonitem` did not stop you from summoning items beyond your status level.
2023-11-18 21:22:12 -05:00
Alex King 838ffbd8c7 [Commands] Add #show aa_points Command (#3695)
# Notes
- Adds a command to view a player's current, spent, and total AA Points.
2023-11-18 19:23:35 -05:00
JJ 42b41d973c [GM Commands] Remove duplicate comment (#3691) 2023-11-18 19:08:56 -05:00
JJ e7761133a9 [GM Commands] Add #takeplatinum (#3690)
* [GM Commands] Add `#takeplatinum`

* Revert database manifest change

* Revert database version change

* Remove duplicated messages

* Remove hint as to why `#takeplatinum` might fail.
2023-11-18 19:08:48 -05:00
Alex King 93f2bea96e [Cleanup] Cleanup #show currencies Command (#3693)
* [Cleanup] Cleanup #show currencies Command

# Notes
- Cleans up messages.
- Adds `AA Points` as a viewable currency.
- Adds an enum for `MoneyTypes` and `MoneySubtypes` so we're not using magic numbers for `GetMoney` anymore.
- Converts money amounts to `uint64`.

* Update currencies.cpp

* Update currencies.cpp
2023-11-18 19:05:04 -05:00
regneq ded82ac6d6 [Spawn] (imported from takp) Added min_time and max_time to spawnentry. This will prevent a NPC from… (#3685)
* Added mintime and maxtime to spawnentry. This will prevent a NPC from spawning outside of the times specified. NPCs spawned in this way will then behave like normal NPCs. They will not despawn on their own, unlike spawn_events/spawn_conditions. NPCs using this that are alone in their spawngroup will attempt to spawn after their respawn timer has expired if the time of day is outside their range. Otherwise, another NPC in the spawngroup will be chosen to spawn. The normal rules (chance, spawn_limit) still apply to these NPCs, this is just another rule added to the system.

mintime and maxtime both represent the in-game EQ Hour. Valid values are 1-24. If either or both of the values are 0, then the NPC will not have any time restriction.

Added a new rule World:BootHour. This allows server admins to specify the EQ hour the server will boot to. Valid options are 1-24. Setting this rule to 0 (default) disables it and world will use whatever time is specified in the DB.

* generated base_spawnentry_repository.h from script

* removed the rule insert from database_update_manifest.cpp.

* Add logging, initializers, minor cleanup

* Remove if/else branch

* Update eqtime.cpp

* Initializers, logging

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-11-18 14:23:04 -06:00
JJ 6ef182edfd [Database] Pull pet power from content database (#3689) 2023-11-18 14:19:33 -06:00
Paul Coene e466ca1c6d [Illusions] RandomizeFeastures erased texture. (#3686) 2023-11-12 16:02:54 -05:00
Akkadius fa5a3155fe [Release] 22.33.0 2023-11-11 21:09:06 -06:00
Chris Miles a20d333f9d [Spawn2] Fix edge case with instances not copying disabled spawn state (#3688)
* [Spawn2] Fix edge case with instances not copying disabled spawn state

* Update spawn2.cpp
2023-11-11 21:00:50 -06:00
Alex King 853739b538 [Feature] Add Comment to Item Data/Quest API (#3669)
* [Feature] Add Comment to Item Data/Quest API

# Perl
- Add `quest::getitemcomment(item_id)`.
- Add `quest::getitemlore(item_id)`.
- Add `$questitemdata->GetComment()`.

# Lua
- Add `eq.get_item_comment(item_id)`.
- Add `eq.get_item_lore(item_id)`.
- Add `item:Comment()`.
# Notes
- Added the ability for operators to pull these fields from item data without a database hit.
- Fixed a bug in `embparser_api.cpp` where `GetZoneGravity` was connected to the wrong methods.

* Update embparser_api.cpp
2023-11-07 18:12:39 -05:00
Alex King 6094ec9c7b [Bug Fix] Fix GetZoneGravity package.add (#3684)
# Notes
- This was incorrect and would cause `GetZoneGravity()` to function improperly in Perl.
2023-11-07 18:12:25 -05:00
Akkadius 9da1d6b397 [Release] 22.32.1 2023-11-06 18:38:21 -06:00
Chris Miles 8ea7299a57 [Release] 22.32.0 (#3683) 2023-11-06 17:56:51 -06:00
Chris Miles 0811a899d1 [Spawn] Split spawn2 enabled into its own state table (#3664)
* [Spawn] Split spawn2 enabled into its own state table

* Update spawn2.cpp

* Update repo

* Make spawn2 enabled/disabled instance aware

* Update questmgr.cpp

* Make sure packet stuff is aware of instance_id

* Update questmgr.cpp

* Update database_update_manifest.cpp

* Cleanup

* Revert "Cleanup"

This reverts commit 64b58bfc52.

* Update database_instances.cpp
2023-11-06 17:34:42 -06:00
hg fad9599642 [Quest API] Add details to Lua event dispatch errors (#3679) 2023-11-06 17:31:34 -06:00
Fryguy 62711b13d8 Revert "[Bug Fix] Fix Killed XYZH support in EVENT_DEATH in Perl. (#3591)" (#3682)
This reverts commit 9b992167f0.
2023-11-06 17:30:55 -06:00
nytmyr 2702485206 [Bots] Fix invalid races from being created (#3681)
Previously this check allowed bots of invalid races to be created. If a race was neither a valid combination or a valid player race, it would pass the check and allow bots of any race to be created.

**^create 1 123 0** could create a Male Innoruuk Warrior
2023-11-06 17:03:34 -05:00
Mitch Freeman 0aadb891a1 [CRASH] Fix crash on CentOS when forming a raid with PCs or BOTs (#3676)
* [CRASH] Fix crash on CentOS

Update raid crash in CentOS.  raid constructors and learnmembers used a memset that was overwriting std::string structure.
Added default initializers to RaidMember struct

* Update based on feedback
2023-11-06 13:36:59 -05:00
JJ d812310c5b [GCC] Compatibility fix for GCC 13 (#3677)
Fixes ` ‘uint64_t’ does not name a type ` error under GCC 13
2023-11-05 14:05:15 -05:00
regneq 1420983700 [Spells] Added IsNightTime() for Dance of the Fireflies (#3667)
* Added IsNightOnly for Dance of the Fireflies spell which should only be cast at night from 7pm to 4pm.

* Update to include IsDayTime and replace magic numbers.
2023-11-04 13:58:08 -04:00
Alex King d25cc35f1b [Bug Fix] Add IsTGBCompatibleSpell() to package.add (#3675)
# Notes
- `IsTGBCompatibleSpell` was not exported properly.
2023-11-04 13:55:47 -04:00
Alex King ed7f395612 [Parser] Cleanup Spire Parsing for crosszonemoveplayerbycharid (#3674)
# Notes
- This formatting was causing Spire not to pick up the parameters.
2023-11-04 13:13:17 -04:00
Alex King 8dceb20dd8 [Parser] Cleanup Spire Parsing for crosszonemoveplayerbygroupid (#3673)
# Notes
- This formatting was causing Spire not to pick up the parameters.
2023-11-04 12:59:25 -04:00
Alex King 6929d180ca [Parser] Cleanup Spire Parsing for crosszonemoveplayerbyguildid (#3672)
# Notes
- This formatting was causing Spire not to pick up the parameters.
2023-11-04 12:45:21 -04:00
Alex King 011a66a75e [Parser] Cleanup Spire Parsing for crosszonemoveplayerbyexpeditionid (#3671)
# Notes
- This formatting was causing Spire not to pick up the parameters.
2023-11-04 12:31:47 -04:00
Alex King 07120563a2 [Bug Fix] Fix Perl__worldwideremovetask package (#3670)
# Notes
- Two lines were using the same parameters.
2023-11-04 12:18:25 -04:00
JJ cc985cbcd5 [Quest API] Add GetBaseRaceName() to Perl and Lua (#3668) 2023-10-31 21:43:04 -04:00
JJ 97caa79472 [Release] 22.31.3 (#3666)
* Update package.json

* Update version.h

* Update CHANGELOG.md
2023-10-31 20:26:30 -05:00
Alex King cfa575c756 [Logs] Convert Loot Messages to Error Logs (#3663)
* [Logs] Convert Loot Messages to Error Logs

# Notes
- These messages were sending to users and not being logged.
- `Message(Chat::Red, "Error: OP_EndLootRequest: Corpse not found (ent = 0)");` sends often when corpse expires right as you try to loot, so it makes the user think there's a true error.

* Update zoning.cpp
2023-10-31 18:58:06 -04:00
JJ 85063249b4 [Bug] Force raids off content database (#3665) 2023-10-31 18:46:03 -04:00
Akkadius 04d6f8feea [Release] 22.31.2 2023-10-31 09:47:18 -05:00
Akkadius dfc1bf0381 Revert "[Crash] Fix spell in AESpell related to beacons (#3659)"
This reverts commit 0b452f4ec1.
2023-10-31 09:46:08 -05:00
Akkadius 2237c3a056 [Release] 22.31.1 2023-10-31 08:08:29 -05:00
Akkadius 4af191c593 [Hotfix] Fix issue with blocked spells not loading properly 2023-10-31 08:06:51 -05:00
Chris Miles 0a3972deb9 [Release] 22.31.0 (#3662) 2023-10-29 18:50:46 -05:00
Chris Miles 9d2f258390 [Database] Add id to variables table (#3658) 2023-10-29 18:45:30 -05:00
Chris Miles 0b452f4ec1 [Crash] Fix spell in AESpell related to beacons (#3659) 2023-10-29 18:45:24 -05:00
Chris Miles fef629e1df [Crash] Fix crash when client pointer does not exist during #hotfix (#3661) 2023-10-29 18:45:18 -05:00
Chris Miles a5a51fbe44 [Linux] Add symbols to release builds (#3660)
* [Linux] Add symbols to release builds

* Update linux-build.sh
2023-10-29 18:45:11 -05:00
Paul Coene 47db92cdb6 [Trading] Fix part 3 of Issue 932. (#3654) 2023-10-29 09:50:04 -04:00
Akkadius 690301e80d [Release] 22.30.2 - Hotfix perl loading 2023-10-26 16:23:55 -05:00
Akkadius 1887e48b76 Revert "[Perl] Reload perl quests on zone bootup (#3648)"
This reverts commit 0bbfcf7adc.
2023-10-26 16:21:06 -05:00
JJ af2691eb12 [Release] 22.30.1 (#3656)
* Update package.json

* Update CHANGELOG.md

* Update version.h
2023-10-24 20:27:54 -04:00
Alex King 2df4289588 [Bug Fix] Fix empty InsertMany in bot starting items. (#3653)
Not checking if the vector is empty before it inserts still inserts when there’s nothing.
2023-10-24 18:15:42 -04:00
Akkadius 49d4d0acc3 [Release] 22.29.0 2023-10-23 22:41:58 -05:00
Paul Coene 5a663910a5 [Pets] Disallow effect of alliance line when cast on pets. (#3650)
* [Pets] Disallow effect of alliance line when cast on pets.

* Update spell_effects.cpp

---------

Co-authored-by: Alex King <89047260+Kinglykrab@users.noreply.github.com>
2023-10-23 22:40:24 -05:00
Chris Miles b027edd21e [API] Implement Zone Sidecar (#3635)
* Zone sidecar work

* Process management work

* Merge

* Sidecar work

* API config option

* Request proxy work

* Proxy headers and params

* Change port

* Remove code

* Sim work

* Sidecar work

* Update loot_simulator_controller.cpp

* Update loot_simulator_controller.cpp

* Formatting

* Post merge change

* Windows compile fix

* Update sidecar_api.cpp

* Update strings.cpp
2023-10-23 22:39:37 -05:00
hg 0bbfcf7adc [Perl] Reload perl quests on zone bootup (#3648)
Perl wasn't implementing quest interface's Init which is called by
Zone::Bootup. This should fix zone's that were in standby not using the
latest version of perl plugin scripts.
2023-10-23 22:39:19 -05:00
Chris Miles 7962a0bd38 [Perl] Implement eqemu-perl for Linux (#3652)
* [Perl] Implement eqemu-perl for Linux

* Update embperl.cpp
2023-10-23 22:38:46 -05:00
JJ 4d9b51df0a [Commands] Move #suspend from content database (#3651) 2023-10-23 20:01:49 -04:00
Alex King 508ecec6ea [Bug Fix] Fix Bot Starting Items SQL (#3649) 2023-10-23 17:19:30 -04:00
JJ f0c6fa2a26 [Release] 22.29.1 (#3647)
* Update version.h

* Update Changelog

* Update CHANGELOG.md

* Update package.json
2023-10-21 18:36:38 -05:00
JJ ad6dbb7beb [DB] Fix manifest for blocked spells (#3646) 2023-10-21 18:01:57 -04:00
JJ 6ddbb41617 [Bug Fix] Verifying mail keys when none exist (#3645)
No need to verify mail key when none exist.
Seen in http://spire.akkadius.com/dev/release/22.28.0?id=12069
2023-10-21 13:33:24 -04:00
JJ 8a558f6a29 [Bug Fix] Hotfix command without hotfix name (#3644)
If no hotfix name is provided, the hotfix command won't need the empty string.
2023-10-21 13:33:16 -04:00
Alex King 0585be0360 [Bug Fix] Fix issue with subcommand settings not working (#3643)
* [Bug Fix] Fix issue with subcommand settings not working

# Notes
- We were checking for `arguments >= 2` when we should just be checking for if there are any arguments and comparing `sep.arg[0]` (the command) and `sep.arg[1]` (the subcommand) to our `command_subsettings` to see if it exists and if we pass the requirements.
- This fix will let operators properly set a subcommand to a lower or higher status level than the parent command.

* Remove debug message.
2023-10-20 21:33:05 -04:00
Akkadius 6927baef7f [Release] 22.29.0 2023-10-20 17:47:35 -05:00
Alex King 52d64781b5 [Feature] Add Expansion and Content Flag support to Blocked Spells (#3638)
* [Feature] Add Expansion and Content Flag support to Blocked Spells

# Notes
- Allows operators to filter blocked spells behind expansions or content flags.
- Requested in https://github.com/EQEmu/Server/issues/3582

* [Tradeskills] Add learned_by_item_id field (#3637)

* [Feature] Add Expansion and Content Flag support to Blocked Spells

- Allows operators to filter blocked spells behind expansions or content flags.
- Requested in https://github.com/EQEmu/Server/issues/3582

---------

Co-authored-by: Chris Miles <akkadius1@gmail.com>
2023-10-20 17:45:58 -05:00
Aeadoin 0667fe435f [Bug Fix] Fix crash when checking Bot Group/Raid membership (#3641)
* [Bug Fix] Fix crash when checking Bot Group/Raid membership

* Update bot.cpp

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-10-20 17:45:41 -05:00
Chris Miles 9959070f24 [Perl] Static linker fix on Linux (#3642)
* Update CMakeLists.txt

* Update linux-build.sh

* test

* Test

* test

* brute force

* !?!

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Remove testing

* Update linux-build.sh
2023-10-20 17:43:04 -05:00
Akkadius 2a91f08845 [22.28.1] Perl Linux build fix 2023-10-20 15:25:25 -05:00
Chris Miles adc64005f1 [Rules] Add rule to configure max number of procs per round Combat:MaxProcs (#3640) 2023-10-20 14:57:50 -04:00
Alex King 605480f1c4 [Bug Fix] Fix Finishing Blow Proc Chance (#3639)
# Notes
- We were double adding `spellbonuses` and not adding `itembonuses` per https://github.com/EQEmu/Server/issues/3636.
2023-10-19 16:19:43 -04:00
Chris Miles 3b95601c62 [Tradeskills] Add learned_by_item_id field (#3637) 2023-10-18 18:27:34 -05:00
Alex King a4f2ed28f1 [Feature] Add Bot Starting Items (#3634)
* [Feature] Add Bot Starting Items

# Notes
- This table is similar to the player starting items table, however it uses bitmasks.
- Allows operators to give bots gear on creation.
- `races` of `0` for all races.
- `classes` of `0` for all classes.

* Update bot.cpp

* Update database_update_manifest_bots.cpp
2023-10-17 18:00:41 -04:00
Akkadius e19b969541 [Release] 22.28.0 - Hotfix changelog 2023-10-15 21:56:55 -05:00
JJ 4241556f75 [Release] 22.28.0 (#3633)
* [Release] 22.28.0

* Update package.json

* Update CHANGELOG.md
2023-10-15 22:45:23 -04:00
Chris Miles 961332b40c [Crash] Fix crash in Mob::ShowBuffs (#3632) 2023-10-15 21:14:55 -05:00
Chris Miles a1a861e0c4 [Bots] Fix bot removal on zone, regression from #3611 (#3631) 2023-10-15 20:46:07 -04:00
JJ 4bbb1aa92f [Scripts] Update 13th Floor importer (#3630)
* [Scripts] Update 13th Floor importer

Overhaul to script.
- Now uses `eqemu_config.json`
- More descriptive during the process
- Accounts for adjustments (`idfile`, `prockunk1`)
- No longer needs to adjust `UNK132`

* [DB] Adjust `items` structure for import (#3629)

Our `items` table has 5 fields that need to adjust in order to pull data from 13th Floor.

* [DB] Update `version.h`
2023-10-15 20:45:50 -04:00
Alex King 1212ccefef [Quest API] Add target ID and spell exports to events (#3620)
* [Quest API] Add target ID and spell exports to events

# Notes
- Add `$spell` export to `EVENT_CAST`, `EVENT_CAST_BEGIN`, `EVENT_CAST_BEGIN`, `EVENT_ITEM_CLICK`, `EVENT_ITEM_CLICK_CAST`, `EVENT_ITEM_CLICK_CLIENT`, `EVENT_ITEM_CLICK_CAST_CLIENT`, `EVENT_SPELL_EFFECT_BUFF_TIC_BOT`, `EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT`, `EVENT_SPELL_EFFECT_BUFF_TIC_NPC`, `EVENT_SPELL_EFFECT_BOT`, `EVENT_SPELL_EFFECT_CLIENT`, `EVENT_SPELL_EFFECT_NPC`, `EVENT_SPELL_FADE`, `EVENT_DEATH`, `EVENT_DEATH_COMPLETE`, `EVENT_DEATH_ZONE`, `EVENT_DAMAGE_GIVEN`, and `EVENT_DAMAGE_TAKEN` in Perl.
- Add `$target_id` export to `EVENT_CAST`, `EVENT_CAST_BEGIN`, and `EVENT_CAST_ON` in Perl.
- Add `e.target_id` export to `EVENT_CAST`, `EVENT_CAST_BEGIN`, and `EVENT_CAST_ON` in Lua.

* Add $target/e.target exports.

* Update spells.cpp
2023-10-15 19:40:25 -04:00
Aeadoin c203fec9b4 [Crash] Resolve crash when assigning empty raid note. (#3628)
* [Crash] Resolve crash when assigning empty raid note.

* const
2023-10-15 16:42:12 -04:00
Alex King 16ab1839e8 [Feature] Add Immune to Headshot Special Ability (#3624)
# Notes
- Allows mobs normally susceptible to Headshot to be made immune to it.
2023-10-13 21:43:33 -05:00
Mitch Freeman f5e4c6a127 [Feature] Update Raid Functions for Titanium and Underfoot (#3524)
* Update Raid Functions

Updated various raid features for:
Titanium
- Raid window now functional, including with BOTS
- Raid delegate assist/mark work
- Raid notes work
- Raid /rmark, /clearmarks work
Underfoot
- Raid window was already functional
- Raid delegate assist/mark work
- Raid notes work
- Raid /rmark, /clearmarks work

* Updates to resolve feedback

* Slight update for overlooked case in encode for RaidUpdate for clients above Ti.

* Updates to further address feedback.  Only updated translators for Ti/RoF2.  Once ok, I will update the others.

* Update linux-build.sh

* Final updates for other translators and the strncpy_s issue.

* Fix for strn0cpy in raids.cpp, translators, and defines.  Updated all in raids.cpp as well.

* Reveted defines change.

* Reverted accidental change

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-10-13 21:42:27 -05:00
Alex King 166c87c931 [Bots] Adjust Bot Movement Speed (#3615)
# Notes
- Bots were having a hard time keeping up with players.
- Part of this was due to using walk until a certain distance.
- Another part was their ctor only having `0.7f` run speed versus our Mob sanity check of `1.25f`.
- We check movement stuff now before idle checks so bots are more likely to start moving earlier.
2023-10-13 20:16:06 -05:00
Alex King 345dd442dd [Quest API] Add GrantAllAAPoints() to Perl/Lua and Modify #grantaa (#3616)
# Command
- Add optional `level` argument to `#grantaa` so you can grant AAs up the specified level.

# Perl
- Add `$client->GrantAllAAPoints()`.
- Add `$client->GrantAllAAPoints(level)`.

# Lua
- Add `client:GrantAllAAPoints()`.
- Add `client:GrantAllAAPoints(level)`.

# Notes
- Grants all AA abilities up to client's current level or a specified level.
2023-10-13 20:13:55 -05:00
Alex King 565baec675 [Bug Fix] Fix #cast defaulting to cast time (#3617)
# Notes
- Defaulted to using cast time instead of instant.
2023-10-13 20:12:34 -05:00
Alex King 9884c442e9 [Crash] Fix Crash with #summon (#3618)
# Notes
- Not setting target to a default of `nullptr` or in this case `c` gave undefined behavior.
2023-10-13 20:12:01 -05:00
JJ ad0b5d6a1c [Scripts] Update 13th Floor script for legacy research tome bagtypes (#3621)
Legacy research tomes have the wrong bagtype (BACKPACK) blocking the clients from showing the combine button.
2023-10-13 20:10:35 -05:00
Alex King b82b32e1d2 [Feature] Add Immune to Assassinate Special Ability (#3622)
# Notes
- Allows mobs normally susceptible to Assassinate to be made immune to it.
2023-10-13 21:01:06 -04:00
dependabot[bot] 2fb72e5729 Bump golang.org/x/net in /utils/scripts/build/should-release (#3619)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.7.0 to 0.17.0.
- [Commits](https://github.com/golang/net/compare/v0.7.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-13 19:52:58 -05:00
Alex King 3791bc788f [Parser Fix] Fix SendIllusion Spire parsing (#3623)
# Notes
- Spire parses methods based on parameters being on the same line, so these were not being parse properly since they were newlines.
2023-10-13 19:41:28 -05:00
Alex King 833fa55fdf [Feature] Add Extra Kick Classes (#3613)
* [Feature] Add Extra Kick Classes

# Notes
- Allows operators to add extra classes to the "Kick" skill.
- Without this only Warrior, Ranger, Monk, Beastlord, and Berserker could kick.

* Remove gotos.
2023-10-11 14:33:23 -04:00
Chris Miles 4fc3c27715 [Release] 22.27.0 (#3614)
* [Release] 22.27.0

* Update bot.cpp
2023-10-07 15:11:21 -05:00
Chris Miles cea3ad6a42 [Crash] Fix crash in #movechar (#3612) 2023-10-07 14:00:27 -05:00
Chris Miles d8926cd5f3 [Crash] Fix dangling pointer crash observed in SendHPPacketsFrom (#3611)
* [Crash] Fix dangling pointer crash observed in SendHPPacketsFrom

* Update bot.cpp
2023-10-07 14:00:19 -05:00
Chris Miles efb03164c7 [Crash] Fix crash in CastSpell Quest API input cast (#3610) 2023-10-07 14:00:11 -05:00
Chris Miles 455eb2e6d9 [Crash] Fix CanUseAlternateAdvancementRank crash (#3609) 2023-10-07 14:00:04 -05:00
Chris Miles b5b0e53da2 [Crash] Fix #summon crash (#3608)
* [Crash] Summon crash fix

* [Crash] Fix summon crash
2023-10-07 13:59:56 -05:00
Chris Miles 68cb94b39c [Crash] Bot member zoned crash fix (#3607) 2023-10-07 13:59:47 -05:00
Chris Miles 3d95b6c184 [Crash] Fix rarer crash with File::Makedir (#3606) 2023-10-07 13:59:40 -05:00
Alex King 7db7631308 [Bug Fix] Fix #show group_info Popup (#3605)
# Notes
- Wasn't using `DialogueWindow::TableCell` so they weren't showing up.
- Fixed `red1` to `red_1` so it shows.
2023-10-04 14:40:05 -04:00
Akkadius f053cd3b56 [Hotfix] Ensure Linux builds report failures 2023-10-03 11:59:50 -05:00
Alex King cf27f2bc88 [Quest API] Add Caster ID Parameter to FindBuff in Perl/Lua (#3590)
* [Quest API] Add Caster ID Parameter to FindBuff in Perl/Lua

# Perl
- Add `$mob->FindBuff(spell_id, caster_id)`.

# Lua
- Add `mob:FindBuff(spell_id, caster_id)`.

# Notes
- Allows operators to check if the spell ID is cast by a specific entity ID.
- We don't use `Mob*` reference here since the mob may have died, left zone, etc.

* Formatting.
2023-09-29 19:38:36 -04:00
JJ 79918ebaba [Logs] Change pathing log messages from Error to Pathing. (#3604)
Change pathing log messages from `Error` to `Pathing`.
2023-09-29 11:54:52 -04:00
Paul Coene 2a648507f2 [Bug Fix] Fix swarm pet names to use '_' instead of ' ' (#3601) 2023-09-19 18:21:47 -04:00
Clayton Dunwell f395ee0508 [Bug Fix] Invis vs. Undead/Animal Breaks Charm for Pets (#3587)
* IVU & IVA break charm pets #2212

* fix typing

* fix tab spacing

* Formatting

* Formatting for CalcInvisibleLevel

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-09-19 10:16:12 -04:00
Akkadius 7166fcc650 [Hotfix] Fix an issue with schema versioning for the AA update 2023-09-18 12:19:56 -05:00
Alex King ae8e58ddc5 [Release] 22.26.1 (#3599)
* [Release] 22.26.1

### Fixes

* Add Validation to #find, #set, and #show args ([#3598](https://github.com/EQEmu/Server/pull/3598)) @Kinglykrab 2023-09-17
2023-09-17 23:15:38 -04:00
Alex King 26e72c6857 [Bug Fix] Add Validation to #find, #set, and #show args (#3598)
# Notes
- We were not validating `sep->arg[i]` so we could possibly be pushing a `nullptr` in.
2023-09-17 21:20:27 -05:00
Chris Miles df1d740ae6 [Release] 22.26.0 (#3596) 2023-09-17 15:14:01 -05:00
Alex King d7e810232a [Bug Fix] Fix entity ID on death with #castspell (#3592)
# Notes
- Entities killed by a spell with #cast were not reporting their pre-death entity ID properly.
- Added an `entity_id_override` to `GetTargetDescription()` and added a pre-defined entity ID variable to the cast command so we can message the proper pre-death entity ID.
2023-09-17 13:40:31 -05:00
Alex King 9b992167f0 [Bug Fix] Fix Killed XYZH support in EVENT_DEATH in Perl. (#3591)
* [Bug Fix] Fix Killer XYZH support in EVENT_DEATH in Perl.

# Notes
- Fixes XYZH exports in Perl.

* Update embparser.cpp
2023-09-17 13:40:07 -05:00
Clayton Dunwell 65d4533568 [Bug Fix] Check for Song Skill Increase on Bard Pulse (#3586)
* check for song skill increase on bard pulse

* style changes

* fix spacing
2023-09-17 13:29:48 -05:00
Clayton Dunwell eb545a18a4 [Feature] Cleanup Group Split Money Logic (#3583)
* addresses #2498

* fix some logic #2498

* fixes #2498

* derpy derp derp #2498

* leave default argument to appease build

* Formatting

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-09-17 13:22:26 -05:00
Alex King f2f0228aa4 [Quest API] Add XYZ/XYZH Overloads to Cross Zone Move Methods (#3581)
# Perl
- Add `quest::crosszonemoveplayerbycharid(character_id, zone_short_name, x, y, z)`.
- Add `quest::crosszonemoveplayerbycharid(character_id, zone_short_name, x, y, z, heading)`.
- Add `quest::crosszonemoveplayerbygroupid(group_id, zone_short_name, x, y, z)`.
- Add `quest::crosszonemoveplayerbygroupid(group_id, zone_short_name, x, y, z, heading)`.
- Add `quest::crosszonemoveplayerbyraidid(raid_id, zone_short_name, x, y, z)`.
- Add `quest::crosszonemoveplayerbyraidid(raid_id, zone_short_name, x, y, z, heading)`.
- Add `quest::crosszonemoveplayerbyguildid(guild_id, zone_short_name, x, y, z)`.
- Add `quest::crosszonemoveplayerbyguildid(guild_id, zone_short_name, x, y, z, heading)`.
- Add `quest::crosszonemoveplayerbyexpeditionid(expedition_id, zone_short_name, x, y, z)`.
- Add `quest::crosszonemoveplayerbyexpeditionid(expedition_id, zone_short_name, x, y, z, heading)`.
- Add `quest::crosszonemoveplayerbyclientname(client_name, zone_short_name, x, y, z)`.
- Add `quest::crosszonemoveplayerbyclientname(client_name, zone_short_name, x, y, z, heading)`.
- Add `quest::crosszonemoveinstancebycharid(character_id, zone_short_name, x, y, z)`.
- Add `quest::crosszonemoveinstancebycharid(character_id, zone_short_name, x, y, z, heading)`.
- Add `quest::crosszonemoveinstancebygroupid(group_id, zone_short_name, x, y, z)`.
- Add `quest::crosszonemoveinstancebygroupid(group_id, zone_short_name, x, y, z, heading)`.
- Add `quest::crosszonemoveinstancebyraidid(raid_id, zone_short_name, x, y, z)`.
- Add `quest::crosszonemoveinstancebyraidid(raid_id, zone_short_name, x, y, z, heading)`.
- Add `quest::crosszonemoveinstancebyguildid(guild_id, zone_short_name, x, y, z)`.
- Add `quest::crosszonemoveinstancebyguildid(guild_id, zone_short_name, x, y, z, heading)`.
- Add `quest::crosszonemoveinstancebyexpeditionid(expedition_id, zone_short_name, x, y, z)`.
- Add `quest::crosszonemoveinstancebyexpeditionid(expedition_id, zone_short_name, x, y, z, heading)`.
- Add `quest::crosszonemoveinstancebyclientname(client_name, zone_short_name, x, y, z)`.
- Add `quest::crosszonemoveinstancebyclientname(client_name, zone_short_name, x, y, z, heading)`.

# Lua
- Add `eq.cross_zone_move_player_by_char_id(character_id, zone_short_name, x, y, z)`.
- Add `eq.cross_zone_move_player_by_char_id(character_id, zone_short_name, x, y, z, heading)`.
- Add `eq.cross_zone_move_player_by_group_id(group_id, zone_short_name, x, y, z)`.
- Add `eq.cross_zone_move_player_by_group_id(group_id, zone_short_name, x, y, z, heading)`.
- Add `eq.cross_zone_move_player_by_raid_id(raid_id, zone_short_name, x, y, z)`.
- Add `eq.cross_zone_move_player_by_raid_id(raid_id, zone_short_name, x, y, z, heading)`.
- Add `eq.cross_zone_move_player_by_guild_id(guild_id, zone_short_name, x, y, z)`.
- Add `eq.cross_zone_move_player_by_guild_id(guild_id, zone_short_name, x, y, z, heading)`.
- Add `eq.cross_zone_move_player_by_expedition_id(expedition_id, zone_short_name, x, y, z)`.
- Add `eq.cross_zone_move_player_by_expedition_id(expedition_id, zone_short_name, x, y, z, heading)`.
- Add `eq.cross_zone_move_player_by_client_name(client_name, zone_short_name, x, y, z)`.
- Add `eq.cross_zone_move_player_by_client_name(client_name, zone_short_name, x, y, z, heading)`.
- Add `eq.cross_zone_move_instance_by_char_id(character_id, zone_short_name, x, y, z)`.
- Add `eq.cross_zone_move_instance_by_char_id(character_id, zone_short_name, x, y, z, heading)`.
- Add `eq.cross_zone_move_instance_by_group_id(group_id, zone_short_name, x, y, z)`.
- Add `eq.cross_zone_move_instance_by_group_id(group_id, zone_short_name, x, y, z, heading)`.
- Add `eq.cross_zone_move_instance_by_raid_id(raid_id, zone_short_name, x, y, z)`.
- Add `eq.cross_zone_move_instance_by_raid_id(raid_id, zone_short_name, x, y, z, heading)`.
- Add `eq.cross_zone_move_instance_by_guild_id(guild_id, zone_short_name, x, y, z)`.
- Add `eq.cross_zone_move_instance_by_guild_id(guild_id, zone_short_name, x, y, z, heading)`.
- Add `eq.cross_zone_move_instance_by_expedition_id(expedition_id, zone_short_name, x, y, z)`.
- Add `eq.cross_zone_move_instance_by_expedition_id(expedition_id, zone_short_name, x, y, z, heading)`.
- Add `eq.cross_zone_move_instance_by_client_name(client_name, zone_short_name, x, y, z)`.
- Add `eq.cross_zone_move_instance_by_client_name(client_name, zone_short_name, x, y, z, heading)`.

# Notes
- Allows operators to send players to specific coordinates across zones instead of always sending to safe coordinates.
2023-09-17 13:16:25 -05:00
Alex King 06337fe762 [Feature] Add Defensive Proc Rules for Level Gap Penalty (#3580)
# Notes
- Allows operators to modify the level gap penalty and level gap required for the penalty for defensive procs' level gap penalty.
- Setting `Spells:DefensiveProcPenaltyLevelGap` to `-1` will disable the penalty.
2023-09-17 13:15:51 -05:00
hg 604c7ad4ab [Feature] Add opcodes for Cast and Scribe book buttons (#3578)
This is just the packet framework for the Scribe button on recipe books
and the Cast Spell button on books that allow casting spells on
targets. It will need to be hooked up to a content implementation
2023-09-17 13:14:38 -05:00
Alex King bab16771aa [Quest API] Add ApplySpell() and SetBuffDuration() overloads to Perl/Lua (#3576)
# Perl
- Add `$bot->ApplySpell(spell_id, duration, level)`.
- Add `$bot->ApplySpell(spell_id, duration, level, allow_pets)`.
- Add `$bot->ApplySpellGroup(spell_id, duration, level)`.
- Add `$bot->ApplySpellGroup(spell_id, duration, level, allow_pets)`.
- Add `$bot->ApplySpellRaid(spell_id)`.
- Add `$bot->ApplySpellRaid(spell_id, duration)`.
- Add `$bot->ApplySpellRaid(spell_id, duration, level)`.
- Add `$bot->ApplySpellRaid(spell_id, duration, level, allow_pets)`.
- Add `$bot->ApplySpellRaid(spell_id, duration, level, allow_pets, is_raid_group_only)`.
- Add `$bot->SetSpellDuration(spell_id, duration, level)`.
- Add `$bot->SetSpellDuration(spell_id, duration, level, allow_pets)`.
- Add `$bot->SetSpellDurationGroup(spell_id, duration, level)`.
- Add `$bot->SetSpellDurationGroup(spell_id, duration, level, allow_pets)`.
- Add `$bot->SetSpellDurationRaid(spell_id)`.
- Add `$bot->SetSpellDurationRaid(spell_id, duration)`.
- Add `$bot->SetSpellDurationRaid(spell_id, duration, level)`.
- Add `$bot->SetSpellDurationRaid(spell_id, duration, level, allow_pets)`.
- Add `$bot->SetSpellDurationRaid(spell_id, duration, level, allow_pets, is_raid_group_only)`.
- Add `$client->ApplySpell(spell_id, duration, level)`.
- Add `$client->ApplySpell(spell_id, duration, level, allow_pets)`.
- Add `$client->ApplySpellGroup(spell_id, duration, level)`.
- Add `$client->ApplySpellGroup(spell_id, duration, level, allow_pets)`.
- Add `$client->ApplySpellRaid(spell_id, duration, level)`.
- Add `$client->ApplySpellRaid(spell_id, duration, level, allow_pets)`.
- Add `$client->ApplySpellRaid(spell_id, duration, level, allow_pets, is_raid_group_only)`.
- Add `$client->ApplySpellRaid(spell_id, duration, level, allow_pets, is_raid_group_only, allow_bots)`.
- Add `$client->SetSpellDuration(spell_id, duration, level)`.
- Add `$client->SetSpellDuration(spell_id, duration, level, allow_pets)`.
- Add `$client->SetSpellDurationGroup(spell_id, duration, level)`.
- Add `$client->SetSpellDurationGroup(spell_id, duration, level, allow_pets)`.
- Add `$client->SetSpellDurationRaid(spell_id, duration, level)`.
- Add `$client->SetSpellDurationRaid(spell_id, duration, level, allow_pets)`.
- Add `$client->SetSpellDurationRaid(spell_id, duration, level, allow_pets, is_raid_group_only)`.
- Add `$client->SetSpellDurationRaid(spell_id, duration, level, allow_pets, is_raid_group_only, allow_bots)`.
- Add `$mob->ApplySpellBuff(spell_id, duration, level)`.
- Add `$mob->SetSpellDuration(spell_id, duration, level)`.

# Lua
- Add `bot:ApplySpell(spell_id, duration, level)`.
- Add `bot:ApplySpell(spell_id, duration, level, allow_pets)`.
- Add `bot:ApplySpellGroup(spell_id, duration, level)`.
- Add `bot:ApplySpellGroup(spell_id, duration, level, allow_pets)`.
- Add `bot:ApplySpellRaid(spell_id)`.
- Add `bot:ApplySpellRaid(spell_id, duration)`.
- Add `bot:ApplySpellRaid(spell_id, duration, level)`.
- Add `bot:ApplySpellRaid(spell_id, duration, level, allow_pets)`.
- Add `bot:ApplySpellRaid(spell_id, duration, level, allow_pets, is_raid_group_only)`.
- Add `bot:SetSpellDuration(spell_id, duration, level)`.
- Add `bot:SetSpellDuration(spell_id, duration, level, allow_pets)`.
- Add `bot:SetSpellDurationGroup(spell_id, duration, level)`.
- Add `bot:SetSpellDurationGroup(spell_id, duration, level, allow_pets)`.
- Add `bot:SetSpellDurationRaid(spell_id, duration, level)`.
- Add `bot:SetSpellDurationRaid(spell_id, duration, level, allow_pets)`.
- Add `bot:SetSpellDurationRaid(spell_id, duration, level, allow_pets, is_raid_group_only)`.
- Add `client:ApplySpell(spell_id, duration, level)`.
- Add `client:ApplySpell(spell_id, duration, level, allow_pets)`.
- Add `client:ApplySpellGroup(spell_id, duration, level)`.
- Add `client:ApplySpellGroup(spell_id, duration, level, allow_pets)`.
- Add `client:ApplySpellRaid(spell_id, duration, level)`.
- Add `client:ApplySpellRaid(spell_id, duration, level, allow_pets)`.
- Add `client:ApplySpellRaid(spell_id, duration, level, allow_pets, is_raid_group_only)`.
- Add `client:ApplySpellRaid(spell_id, duration, level, allow_pets, is_raid_group_only, allow_bots)`.
- Add `client:SetSpellDuration(spell_id, duration, level)`.
- Add `client:SetSpellDuration(spell_id, duration, level, allow_pets)`.
- Add `client:SetSpellDurationGroup(spell_id, duration, level)`.
- Add `client:SetSpellDurationGroup(spell_id, duration, level, allow_pets)`.
- Add `client:SetSpellDurationRaid(spell_id, duration, level)`.
- Add `client:SetSpellDurationRaid(spell_id, duration, level, allow_pets)`.
- Add `client:SetSpellDurationRaid(spell_id, duration, level, allow_pets, is_raid_group_only)`.
- Add `client:SetSpellDurationRaid(spell_id, duration, level, allow_pets, is_raid_group_only, allow_bots)`.
- Add `mob:ApplySpellBuff(spell_id, duration, level)`.
- Add `mob:SetSpellDuration(spell_id, duration, level)`.

# Notes
- This allows operators to override the spell level.
2023-09-17 13:14:13 -05:00
Alex d3a414a048 [Fixes] AA System Fixes (#3572)
* -Always load AAs beyond our current expansion (Will need this for refunding invalid AAs).
-AAs beyond our current expansion will no longer be buyable or sendable to clients.

* #reload aa will now reload character aa data.

* Base Implementation of auto grant AA

* -Add DB manifest entry
-Made has already purchased fn a bit better
-Added auto grant to db entry

* -Added grantaa command.
-Reworked grantaa to not spam the client with packets, it still does spam messages because the feedback is important.

* Port suggested changes for Finish AA purchase.

---------

Co-authored-by: KimLS <KimLS@peqtgc.com>
2023-09-17 13:12:43 -05:00
Paul Coene e85a8db8c4 [Messages] Swarm pet normal damage messages were missing (#3594) 2023-09-17 08:26:09 -04:00
Fryguy 12cc3c90ea [Bug] Additional Wild Ramp param was causing an overflow it appears at least on local testing. (#3589)
* [Logging] Add logging to track down Wild Ramp issue

* [Bug] Additional Wild Ramp param was causing an overflow it appears at least on local testing.
2023-09-11 15:57:04 -05:00
Paul Coene 9c656bc498 [Messages] Remove duplicate message on tracking begin (#3574) 2023-09-11 08:27:25 -04:00
Fryguy bc337979bb [Logging] Add logging to track down Wild Ramp issue (#3588) 2023-09-10 21:02:44 -05:00
Paul Coene a64425ebe6 [Commands] npc_edit faction and #setfaction duplicate and incorrect. (#3577)
* [Commands] npc_edit faction and #setfaction duplicate and incorrect.

* Fix assignment
2023-09-02 21:21:48 -04:00
Alex King ca933fce45 [Bug Fix] Fix #set faction/#setfaction Command (#3575)
# Notes
- This was an oversight on my part in `#set` command consolidation.
2023-09-02 17:30:40 -04:00
Akkadius 9c3498b431 [Release] 22.25.0 2023-08-28 19:51:37 -05:00
Akkadius d7e09a1f3b [Hotfix] Zoning logging edge case safety 2023-08-28 19:51:11 -05:00
Akkadius 1652e7a976 [Hotfix] Fix to zoning logging exception 2023-08-28 19:44:56 -05:00
JJ 37dda9bf41 [Instances] Refine id selection (#3568)
* [Instances] Refine id selection

Since the IDs start above the minimum, we needed to check if the first slot was available.

* Remove else by returning early, add validation before accessing row

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-08-28 19:28:15 -05:00
Paul Coene a2b78ff4e6 [Combat Messages] Fix issue where pet proc damage was not showing up (#3551)
* [Combat Messages] Fix issue where pet proc damage was not showing up

* Put back needed "skip" for some melee messages.

* spacing
2023-08-24 16:52:18 -04:00
Aeadoin 79a3ce8d7e [Bots] Add Support for Mana Pool AA Bonuses. (#3571) 2023-08-21 18:35:14 -04:00
Paul Coene d857fb3c48 [HotFix] Clearing target window on CHARM wear off had a side effect (#3570)
* [HotFix] Clearing target window on CHARM wear off had a side effect

* erroneous change removed
2023-08-21 18:16:22 -04:00
Chris Miles 2b4cd292e4 [Rules] Also reload rules in world when #reload rules invoked (#3566) 2023-08-21 17:43:55 -04:00
Aeadoin 3b7cfa6454 [Rules] Correct explanation of Bots:ManaRegen (#3569)
* [Rules] Correct explanation of Bots:ManaRegen

* update

* update
2023-08-21 17:43:02 -04:00
Vayle c5fa7e28c8 [Bug Fix] Minor adjustment to formula calc position to fix modifier bug. (#3565)
* Fix logic error in recent PR

* Adjust formula position
2023-08-20 22:18:08 -05:00
Akkadius 5d133a2b47 [Hotfix] Instance GetUnusedInstanceID crash fox 2023-08-20 21:30:37 -05:00
Chris Miles 7122ac33b2 [Quest API] Reload content flags globally when a content flag is set (#3564) 2023-08-20 20:56:40 -05:00
JJ c47644ea46 [Instances] Honor reserved instances (#3563)
* [Instances] Honor reserved instances

Logic to select next available instance id was incorrect.
The correct logic selected the max id + 1 or max reserved + 1, but then it would overwrite if we enabled recycling ids.
Additionally, it was incrementing the reserved ids and assigning ids to the max reserved id vice the next available.
Finally, it was running the logic twice.

* Fix updated SQL to use fmt
2023-08-20 19:21:51 -05:00
Vayle a61f951d0e [Rules] Add FinalRaidExpMultiplier Rule (#3554)
* FlatRaidExpModifierRule

* Formatting

* Remove enabled toggle

Enabled toggle not necessary as default value is 1.0

* Formatting

* Formatting

* Formatting
2023-08-20 16:31:36 -05:00
Paul Coene 4357b8c731 [Charm] Fix to update target windows on charm on/off (#3549)
* [Charm] Fix to update target windows on charm on/off

* Removed accidental change

* Removed magic #

* reformated brace style in function that was modified

* Use better names for clear variables

* Forgot header with name change

* More header name changes
2023-08-20 15:43:10 -05:00
Alex King 9cbe25f712 [Feature] Change #reload zone to reload zone headers globally. (#3557)
* [Feature] Change #reload zone to reload zone headers globally.

# Notes
- This allows operators to globally reload zone headers without going to every zone individually to do so.

* Update worldserver.cpp

* Update worldserver.cpp
2023-08-20 15:42:45 -05:00
Chris Miles c14a17e4de [Database] Extend dumper CLI utility to export static instance data (#3562)
* [Database] Extend dumper CLI utility to export static instance data

* Append

* Append
2023-08-20 15:42:23 -05:00
hg ab04a4c6df Remove hard limit on currency merchant (#3560) 2023-08-20 15:37:15 -05:00
Chris Miles c0cf9bb5aa [Expansions] Expansion settings tweaks (#3556)
* Expansion tweaks testing on PEQ

* Update zoning.cpp

* Update aa.cpp

* Update aa.cpp

* Tweak
2023-08-20 15:37:08 -05:00
JJ b5d23389ee [Database] Change primary key entry to NOT NULL (#3559)
Needed for MySQL 8 compatibility.
2023-08-20 15:36:51 -05:00
Alex King dc35ab5251 [Bug Fix] Fix #motd/#set motd Command (#3558)
# Notes
- This command was non-functional since the consolidation due to an oversight on my part.
2023-08-20 09:31:26 -04:00
Chris Miles 9cbfd5c8f0 [Logging] Add detailed zoning logging (#3555)
* WIP: Add zoning logging

* Update zoning.cpp
2023-08-19 23:53:34 -05:00
Fryguy 5631a0711f [Feature] Add adjustability for AERampage Range. (#3548)
* [Feature] Add adjustability for AERampage Range.

This functionality is needed for fights like Ture to be accurate, where their ramp range was 101% of their melee safe range.

Example in lua of utilizing this scripting

```
e.self:SetSpecialAbilityParam(SpecialAbility.area_rampage,8,101;
```

* Updates to address comments
2023-08-19 23:36:06 -05:00
Aeadoin 00e02b61ca [Bug Fix] Fix Bot::CheckDataBucket to work with Owner Buckets. (#3552) 2023-08-18 16:41:24 -04:00
regneq 108397b138 [Feature] Change money type to all lower case as EQ live money shares and split has it that way. (#3550) 2023-08-18 15:19:58 -04:00
Aeadoin 9a07142a9b [Bug Fix] Bots will now load AAs properly when spawned. (#3544)
* [Bug Fix] Bots will now load AAs properly when spawned.

* formatting

* formatting

* formatting

* formatting

* formatting (for real this time)

* formatting (for real this time)

* Formatting
2023-08-13 15:57:27 -04:00
Aeadoin 919a92bda3 [Bots] Remove In-Game Command References to Bot Groups (#3545) 2023-08-13 15:41:30 -04:00
Chris Miles 140aba9f69 [Spawns] Fixes a rarer issue where spawn2 is not being properly content filtered 2023-08-13 02:17:00 -05:00
Aeadoin c3d41e08f4 [Bug Fix] Bots no longer drop group on death, and raid fixes. (#3542) 2023-08-12 21:49:01 -04:00
Vayle 5d6a1aad50 [Rules] Add rule to restrict hand in of quest items to quest flagged NPCs. (#3536)
* Add rule to restrict handin of quest items to quest flagged npcs

* Minor format tweak

* Formatting
2023-08-12 21:48:40 -04:00
hg af91b2b41c [CMake] Define perlbind option for all targets (#3538)
This isn't designed well and wasn't handled correctly since the perlbind
library was getting built and linked with default options while zone was
using PERLBIND_NO_STRICT_SCALAR_TYPES. This was probably leading to some
unspecified behavior.
2023-08-12 21:48:08 -04:00
hg 2660aa79ab [CMake] Add cmake option to re-enable MSVC warnings (#3537) 2023-08-12 21:47:38 -04:00
Fryguy 730738faf9 [Bug] Escape item name in trader audit. (#3540)
* [Bug] Escape item name in trader audit.

Quick fix to escape the item names in Trader Audit.

* Update trading.cpp

---------

Co-authored-by: Alex King <89047260+Kinglykrab@users.noreply.github.com>
2023-08-12 21:47:22 -04:00
catapultam-habeo 2bb7bba724 [Rules] Add a rule to adjust the randomization range for Wizard\Caster Merc innate critical ratio. (#3543)
* initial commit

* oops.

* that wasn't supposed to be committed.

* Update effects.cpp

---------

Co-authored-by: Alex King <89047260+Kinglykrab@users.noreply.github.com>
2023-08-12 21:19:22 -04:00
Akkadius e93081dde0 [Hotfix] Add character_stats_record to player tables 2023-08-11 01:46:30 -05:00
Vayle 3a46bf7383 [Rules] Add rule to toggle pets accepting quest items (#3533)
* Add rule to disable handing quests items to pets

* Logic tweak

* Tweaks

Updated formatting and minor logic change

* Minor tweaks
2023-08-06 15:32:25 -04:00
Chris Miles aa6421afdf [Release] 22.24.0 (#3534)
* [Release] 22.24.0

* Update CHANGELOG.md
2023-08-05 13:58:51 -05:00
Chris Miles 6a7eaae122 [Fix] Bugs table should not target content database (#3535) 2023-08-05 13:53:54 -05:00
Chris Miles 714b474d2c [Character] Record character stats to character_stats_record table (#3522)
* [Character] Record character stats to

* Record stats on disconnect as well

* Record later in connect process

* Move enter zone code path so we're after bonuses

* Ok this spot for real

* Adjust recording

* Update client_packet.cpp

* Timestamps

* Update database_update_manifest.cpp

* Update client_packet.cpp

* Fix stat bonuses
2023-08-05 12:55:59 -05:00
Mitch Freeman e24d82f0fe [Bug Fix] Bug fix for raid mark NPC across zones (#3525)
* Fix for GENERIC_9_STRINGS

* Add Bot Heal Message Display

Creates a new rule to display Bot heal messages to the Bot Owner

* 2021-03-25 11L04pm

Spell and Heal Rule added to allow for Bot spell and heal damage to be sent to the Bot Owner's Group.  Also added a check to remove duplicate message for #damage on self.

* Update .gitignore

* BOT work

Added BOT logging damage/heals to owner
Added BOT message to owner for harmony fails
Made var Critical global to remove duplicate crit messages
Added a NULL check to Mob:GetCleanname()

* Bot Group Work

Fixed botid=charid spawn on zone issue
Added a group_list update on zone to refresh from database to fix a dangling pointer to a Bot object that was camped but was previously in a group within the zone being entered.
Modified Bot::ProcessBotGroupInvite to use the client of the bot when doing the Bot initialization so that a leader can invite another owner's Bot

* Jan 4

Basic structure in place for Raid::AddBot though not working

* Basement Jan 5

* End of day Jan 5
Working Raid Invite to a Bot.

* Update to Client::QueuePacket to not attempt to send a packet to a BoT.  Not clean, but a broad solution.

* Updated Raid::VerifyRaid

* Some Bot Raid working

* Before VS Crash

* Use Case 1, 2, 3,4,7 working.
Need to fix 5, 6, 8

* Work on usecase 5

* A few more use cases working

* New work on Raid invite with a invitor having a group

* Bot Raid inviting working for all use cases

* A few changes

* end of day jan 10

* Jan 11

* end of day Jan 11

* Bot Invite/Accept cleanup

* Start of moving raid bot functions to their own methods

* More bot raid changes

* More raid spell work

* end of day Jan 16

* spawn work

* Spawn on login working

* End of Day Jan 18

* Raid leader and mana/hp updates fixed

* Spell Tracking

* Issue with Bot Death in raid when casted upon.  1741 raid.cpp

* Bot Death fixed and few other crashes

* Working on botgroup removal

* Bot Disbanding Work 90%

* Looks like BOTs are working

* Fixed a bot crash

* bug tracing on entity list mismatch

* safe_delete resoves problem.  No to track down leak

* seems to be working

* Memory corruption found - sending packets to BoTs using Client class

* added Raid::IsRaidMemberBot()

* Update p_raid_instance

* g3

* Final - Bot Raid Working

* Fixed IsRaidMemberBot to remove memory leak
Fixed altcombat crash though RaidMainAssist (428) needs fixing

* add RaidMember.IsBot

* Repaired IsBot function to be more preformant.  Now works on standard performance machine

* Fixed Bard AE Target Spells
Removed assert for buffs

* updated based on Feb 2022 master updates

* Added bot_db_updates and version increment

* Cleanup of bot raid work and inclusion of bot_raid in cmake

* Fix repop crash

* Bot databse change to not use view

* Revert "Merge branch 'master' of https://github.com/neckkola/Server"

This reverts commit 1826830637, reversing
changes made to 7c1a139991.

* Updated syntax for 9230

Updated this syntax as to run on maria 10.1

* Revert "Updated syntax for 9230"

This reverts commit ffdd46c8b2.

* Fix for cross zone mark npc when entity ids are reused.

* Fixed and tested

added db change
and tested across zones

* Transition to direct attributes instead of encode

Update the pattern to utilize direct raid object attributes for entity id, zone id and instance id instead of an encoded single field.
2023-08-05 12:23:33 -05:00
Chris Miles 33a375677e [Fix] Fix issue with mob scanning when trying to use EVENT_SPAWN (#3529) 2023-08-04 13:05:33 -05:00
Chris Miles 8fce86c396 [Quest API] Adjust GetCloseMobList calls internally (#3530)
* [Quest API] Adjust GetCloseMobList calls internally

* Tweaks
2023-08-04 13:05:22 -05:00
Alex King 68b40f0239 [Cleanup] Cleanup #view zone_loot Command (#3523)
* [Cleanup] Cleanup #view zone_loot Command

# Notes
- An item ID was being required, we don't want to do that.
- Cleanup messages to only show item name/item ID

* Update zone_loot.cpp
2023-08-02 19:58:25 -04:00
Alex King 2dc2bac456 [Cleanup] Remove Strings::Commify from all identifier values (#3528)
# Notes
- Removes commification from unique identifiers.
2023-08-01 22:59:47 -05:00
Alex King 00a8a0cf88 [Bug Fix] Fix +/- 0.1 XYZ Door Manipulation (#3527)
# Notes
- We were checking if this was a number, not a float.
2023-08-01 22:16:29 -05:00
Alex King 5a466da96c [Feature] Add Support for Drakkin Heritage Illusions (#3521)
# Notes
- Fixes an issue where Drakkin illusions that used different Drakkin Heritages were not properly applying the Drakkin Heritage due to not sending the Face Appearance.
2023-08-01 14:28:13 -05:00
Akkadius de4f5ae491 [Release] 22.23.0 2023-07-31 20:17:17 -05:00
Alex King fb20d92166 [Bug Fix] Fix Appearance Issues (#3520)
* [Bug Fix] Fix Appearance Issues

# Notes
- Changing race, gender, or texture of a Mob could result in it changing sizes due to use not sending the size as part of the appearance packet.
- Also converts the parameterized method to a struct parameter so that we can optionally send things without back-filling multiple arguments.

* Gender cleanup.

* Fix.

* Formatting.
2023-07-31 20:15:13 -05:00
Paul Coene 6cff433d23 [Scaling/Bug Fix] Scaling where min and max damage was bugged (#3514)
* [Scaling/Bug Fix] Scaling where min and max damage were both 0 tossed out min_dmg

* Clamp values so independant calls dont leave us in odd state
2023-07-31 20:00:48 -05:00
Alex King 2da7ddad57 [Bug Fix] Fix NPC Cast Events not parsing properly. (#3518)
* [Bug Fix] Fix NPC Cast Events not parsing properly.

# Notes
- We were not using separated values.

* Update lua_parser_events.cpp
2023-07-31 19:59:56 -05:00
Chris Miles 55161e18c8 [Databuckets] Improvements to distributed cache, reload commands (#3519)
* [Databuckets] Improvements to distributed cache, reload commands

* Add to reload_types
2023-07-31 19:58:57 -05:00
Alex King 063d4fbd1a [Bug Fix] Fix #gm top level alias for #set gm (#3517)
# Notes
- Typo lead to `#gm on` and `#gm off` not functioning.
2023-07-30 13:20:17 -04:00
Akkadius c25cb0cc23 [Release] 22.22.1 2023-07-30 01:36:49 -05:00
Chris Miles ddac326239 [Doors] Add door blacklist (#3516)
* [Doors] Add door blacklist

* Renaming to simplify
2023-07-30 01:35:44 -05:00
Akkadius 14fe396510 [Database] Hotfix: Add command_subsettings to server tables 2023-07-28 22:22:43 -05:00
Chris Miles c968a0acdc [Release] 22.22.0 (#3513)
* [Release] 22.22.0

* Version other areas
2023-07-28 11:35:40 -05:00
Alex King 8c4cd34e01 [Quest API] Add GetMobTypeIdentifier() to Perl/Lua (#3512)
# Perl
- Add `$mob->GetMobTypeIdentifier()`.

# Lua
- Add `mob:GetMobTypeIdentifier()`.

# Notes
- Gets unique identifier independent of mob type.
2023-07-27 23:16:41 -05:00
Akkadius 0dbcf83a11 [Database] Fix console output in database:dump --dump-output-to-console 2023-07-25 11:45:26 -05:00
Alex King a75648f73f [Data Buckets] Distributed Databucket Caching (#3500)
* [Data Buckets] Zone-Based Data Bucket Caching

# Notes
- Adds a data bucket cache so we're not needlessly hitting the database every time we need to read a data bucket value.

* Cleanup and unify GetData access patterns

* Cache work

* Push

* Add to cache when we fetch and do a db hit

* Handle bucket misses in cache

* Formatting

* Logging

* [Data Buckets] Zone-Based Data Bucket Caching

- Adds a data bucket cache so we're not needlessly hitting the database every time we need to read a data bucket value.

* Cleanup and unify GetData access patterns

* Cache work

* Push

* Add to cache when we fetch and do a db hit

* Handle bucket misses in cache

* Formatting

* Remove redundant fetches from cache since GetData does the same thing

* Push progress

* Distributed cache work

* Logging

* Fix issue with scoping where same named keys could return overlapping results

* Misses cache tweak, logging, comments

* Add bot, client, and NPC bucket methods to Lua.

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-07-24 12:22:50 -05:00
Alex King 6c2886a71d [Cleanup] Fix casing in corpse money and decay time. (#3511)
# Notes
- These were uppercase and should be lowercase.
2023-07-23 16:19:07 -04:00
Alex King 1d96ddb60d [Bug Fix] Escape search string in #find item (#3510) 2023-07-22 18:20:00 -04:00
Vayle c30074be66 [Crash Fix] Guard against Spells:MaxTotalSlotsPET being set above client allowed maximum. (#3507)
* Guard against MaxTotalSlotsPET being set too high

This prevents a crash from MaxTotalSlotsPET being set too high.

* Tweak
2023-07-22 10:20:22 -04:00
Chris Miles b5652e6010 [Saylink] Fix cases where saylinks were not being cached (#3508)
* [Saylink] Fix cases where saylinks were not being cached

* Update say_link.cpp
2023-07-19 23:57:04 -05:00
Akkadius 202d2ed496 [Release] 22.21.2 2023-07-19 23:50:47 -05:00
Chris Miles 81cee49ea1 [Databuckets] Fix rarer same bucket name scoping overlap issue (#3509) 2023-07-19 23:49:11 -05:00
Akkadius 2d61cd2b9a [Release] 22.21.1 2023-07-18 20:50:56 -05:00
Vayle b06505b80a [Cleanup] Remove arbitrary teleport blocking in Tutorial and Load zones (#3506) 2023-07-18 20:56:21 -04:00
Chris Miles 4c2f9a4423 [Databuckets] Fix issue with expired databuckets not being expired and returned properly (#3504) 2023-07-18 17:18:36 -05:00
Alex King fb3159b657 [Bug Fix] #set title_suffix Argument Position (#3505)
# Notes
- Off by one on argument index.
2023-07-18 18:02:25 -04:00
Michael 8ebf5bbb78 [Bug] Show Petition and Show Petition_Info fix (#3503)
Where Statement was using incorrect field name.
2023-07-18 17:15:21 -04:00
Akkadius d2aae4d79c [Release] 22.21.0 2023-07-18 02:54:20 -05:00
Chris Miles f9dc9da42b [Pathing] Improvements to roambox logic, pathing (#3502)
* [Roambox] Improvements to roambox logic

* Update npc.cpp

* Update npc.cpp

* More pathing fixes
2023-07-18 02:52:04 -05:00
Chris Miles 3f3bbe98b5 [Data Buckets] Implement scoped data buckets (#3498)
* [Data Buckets] Implement scoped data buckets

* Update database_update_manifest.cpp

* Update data_bucket.cpp

* Update data_bucket.cpp

* Update data_bucket.cpp

* Update data_bucket.h

* Update database_update_manifest.cpp

* Add GetScopedDbFilters references

* Scope transfer
2023-07-16 14:52:28 -04:00
Chris Miles 59537ae977 [Z Clipping] Don't issue zclip adjustments when NPC is not moving (#3499) 2023-07-16 14:52:17 -04:00
Alex King ee45a28efe [Quest API] Add SetLDoNPoints() to Perl/Lua (#3496)
# Perl
- Add `$client->SetLDoNPoints(theme_id, points)`.

# Lua
- Add `client:SetLDoNPoints(theme_id, points)`.

# Notes
- Allows operators to directly set LDoN Points.
2023-07-15 21:46:49 -05:00
Jonathan Sider 70ce81fb0a [Bug Fix] Fix rule check and add rule for pickpocket command (#3492)
* Fix bugs in skills

-Add rule for allowing pickpocket
-Fix method that is supposed to check rule
-Changed Z axis range for pickpocket (was failing on giants)

* Add zoffset to account for taller models
2023-07-15 21:46:26 -05:00
Akkadius e06d28ad20 [Release] 22.20.1 2023-07-15 13:30:36 -05:00
Mitch Freeman d57489781c [Database] Fix database manifest entry for #3443
Updates the syntax for mariadb 10.1
2023-07-15 13:29:34 -05:00
Chris Miles 21d65c73b7 [Release] 22.20.0 (#3495) 2023-07-15 00:46:42 -05:00
Alex King 8f6d606f53 [Bug Fix] Fix Tradeskill Combines with augmented items (#3490)
* [Bug Fix] Fix Tradeskill Combines with augmented items

# Notes
- Keeps players from doing tradeskill combines with augmented items.
- Behavior is Live-like, we don't need a rule since `EVENT_COMBINE` is separate and processed prior to the recipe check.

* Update tradeskills.cpp

* Update tradeskills.cpp

* Cleanup

* Update tradeskills.cpp
2023-07-15 00:39:19 -05:00
Alex King f25e37d0c5 [Commands] Consolidate #set-like commands into a singular #set command (#3486)
* First push

* Final push.

* Consolidate zone commands in to one.

* Update command.cpp

* Remove debug messages.

* Test

* Add support for sub command status levels.

* Update command.cpp

* Update client.cpp

* Update database_update_manifest.cpp

* Update version.h

* Update item.cpp

* Update version.h

* Update database_update_manifest.cpp

* Fix command arguments.

* Help message.

* Update command.cpp

* Do DB injection/deletion

* Indent

* Update server_locked.cpp

* Update set.cpp

* Lock aliases

* Update command_subsettings_repository.h

* Update set.cpp

* Fix

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-07-15 00:37:51 -05:00
Alex King e55f9b9d27 [Feature] Add Support for item textures higher than 65,535 (#3494)
* [Feature] Add Support for item textures higher than 65,535

# Notes
- We were previously using `uint16` which has a max of `65,535`, but some of the new Live textures that are being used have values way beyond this.
- Updates quest API, commands, and database tables that also used `uint16`.

* Update version.h
2023-07-14 18:49:59 -04:00
Mitch Freeman b01486d767 [Feature] Update raid features (#3443)
* [RAID] Add Raid Features

[RAID] Add Raid Features

- Add delegate main assist
- Add delegate main marker
- Add target ring for main assisters.  Uses MA1, then MA2, then MA3
- Add /assist raid respecting /assist on and /assist off
- Add Raid Notes.  Functions across zones
- Add Raid XTarget functional
- Raid Leader can mark without being delegated Main Marker.  Must have the appropriate AA

* Update to new db routines

* Updated several formatting issues based on review

* Update to pp->tribute_time_remaining to avoid edge case.  Unrelated to raid updates.

* Updates to resolve comments/review.
Added a few edge case updates as well.

* Refactored to use database repositories for raid_details and raid_members.  Other updates as noted in review.

* Updated database manifest and fixed potential leak within Client::Handle_OP_AssistGroup

* Update for remaining review items

* Refactor SendAssistTarget to use struct/vector loop

* Have IsAssister use range based for loop and return bool

* General cleanup

* Simplify SendRaidAssistTarget to use struct / vector

* Formatting in Handle_OP_RaidDelegateAbility

* Format SendRemoveRaidXTargets and clean up error statements

* Format SendRemoveAllRaidXTargets

* Formatting

* Default return FindNextRaidDelegateSlot to -1

* Change fields to marked_npc_1/2/3 (missing last underscore)

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-07-12 22:04:50 -05:00
Jonathan Sider 50ce99ce3e [Bug Fix] Update bot naming check and add more explanation (#3491)
* Refactor my original PR

Block all puncation,numbers, and _

* Add error message
2023-07-12 21:59:17 -05:00
Alex King 4854201b2a [Quest API] Add Mob/Entity type check methods to Perl/Lua (#3493)
* [Quest API] Add Mob/Entity type check methods to Perl/Lua

# Perl
- Add `$mob->IsAura()`.
- Add `$mob->IsEncounter()`.
- Add `$mob->IsMerc()`.
- Add `$mob->IsOfClientBot()`.
- Add `$mob->IsOfClientBotMerc()`.
- Add `$mob->IsTemporaryPet()`.

# Lua
- Add `entity:IsAura()`.
- Add `entity:IsOfClientBot()`.
- Add `entity:IsOfClientBotMerc()`.
- Add `mob:IsTemporaryPet()`.

* Update lua_entity.cpp

* Update lua_mob.cpp
2023-07-12 21:20:07 -05:00
Jonathan Sider c81d05940a [Bots] Remove orphaned commands related to botgroup (#3489) 2023-07-09 00:00:28 -04:00
Paul Coene 47be17e2af [Bug Fix] Fix charmed pets to follow when charmed. (#3488)
* [Bug Fix] Fix charmed pets to follow when charmed.

* Added STOP (missed this on a local merge)
2023-07-08 19:58:45 -04:00
Chris Miles 809b3b6099 [Release] 22.19.0 (#3487) 2023-07-08 16:54:15 -05:00
Jonathan Sider f06c7e8834 [Bots] Add Pickpocket Command (#3484)
* Add Pickpocket Command

* Formatting

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-07-08 16:51:52 -05:00
Alex King 096448d23c [Commands] Add #itemsearch alias to #find aliases (#3485)
# Notes
- `#itemsearch` did not exist in this alias list.
2023-07-08 16:33:29 -05:00
Alex King e55fb1cafd [Commands] Consolidate #show commands into a singular #show command (#3478)
* [Cleanup] Consolidate #show commands into a singular #show command

# Notes
- All `#show` commands like `#showbuffs` are now subcommands of `#show`.
- All aliases like `#showbuffs` still function.

* Push up progress.

* Final push.

* Cleanup.

* Update ip_lookup.cpp

* emotes not emote

* Cleanup

* Update servertalk.h

* Update show.cpp

* Fix

* Final push.

* #aggro

* #who
2023-07-08 11:06:25 -04:00
Alex King d4962bb2ab [Cleanup] Move #find item summon links to front (#3483)
# Notes
- Move the summon links to the front so they're in a consistent location.
2023-07-04 23:08:29 -04:00
Jasdac 98e56bdfe9 [Rules] Add Skills:TrivialTradeskillCombinesNoFail Rule (#3481)
* Add TrivialNoFail rule

* feedback fixes

* Update tradeskills.cpp

* Update 1392_recipe_learning.sql

* Update ruletypes.h

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2023-07-04 22:47:56 -04:00
455 changed files with 48919 additions and 13311 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ volumes:
steps:
- name: Build Linux X64
image: akkadius/eqemu-server:v11
image: akkadius/eqemu-server:v13
environment:
GITHUB_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
+681
View File
@@ -1,3 +1,684 @@
## [22.35.0] - 12/10/2023
### Bots
* Add BotHealOnLevel to fully heal/mana on level. ([#3745](https://github.com/EQEmu/Server/pull/3745)) @nytmyr 2023-12-08
* Fix bots learning spells on level ([#3744](https://github.com/EQEmu/Server/pull/3744)) @nytmyr 2023-12-08
### Bug
* Fix blocked spells regression from #3638 ([#3753](https://github.com/EQEmu/Server/pull/3753)) @joligario 2023-12-11
* PR 3638 Missed the blocked spells repository updates ([#3748](https://github.com/EQEmu/Server/pull/3748)) @fryguy503 2023-12-08
### CMake
* Update minimum version of CMake ([#3743](https://github.com/EQEmu/Server/pull/3743)) @joligario 2023-12-08
### Code
* Remove hard-coded Status Checks ([#3727](https://github.com/EQEmu/Server/pull/3727)) @Kinglykrab 2023-12-03
### Commands
* #guild set CharName 0 did not remove char from guild. ([#3717](https://github.com/EQEmu/Server/pull/3717)) @noudess 2023-11-25
* #petname changes PC to Nobody if selected. ([#3720](https://github.com/EQEmu/Server/pull/3720)) @noudess 2023-11-26
* Add #show aas Command ([#3710](https://github.com/EQEmu/Server/pull/3710)) @Kinglykrab 2023-11-26
* Add #task complete Command ([#3711](https://github.com/EQEmu/Server/pull/3711)) @Kinglykrab 2023-11-26
* Cleanup #acceptrules Command ([#3716](https://github.com/EQEmu/Server/pull/3716)) @Kinglykrab 2023-11-26
* Cleanup #disarmtrap Command ([#3713](https://github.com/EQEmu/Server/pull/3713)) @Kinglykrab 2023-11-26
* Cleanup #list Command ([#3714](https://github.com/EQEmu/Server/pull/3714)) @Kinglykrab 2023-11-26
* Cleanup #movement Command ([#3715](https://github.com/EQEmu/Server/pull/3715)) @Kinglykrab 2023-11-26
* Cleanup #object Command ([#3722](https://github.com/EQEmu/Server/pull/3722)) @Kinglykrab 2023-12-03
* Cleanup #zonebootup and #zoneshutdown Commands ([#3729](https://github.com/EQEmu/Server/pull/3729)) @Kinglykrab 2023-12-03
* Fix formatting of #wpinfo output. ([#3728](https://github.com/EQEmu/Server/pull/3728)) @noudess 2023-12-01
### Database
* Add primary key to keyring table ([#3746](https://github.com/EQEmu/Server/pull/3746)) @Kinglykrab 2023-12-08
* Consolidate Starting Items Table ([#3723](https://github.com/EQEmu/Server/pull/3723)) @Kinglykrab 2023-11-30
* Extra whitespace in #3723 ([#3730](https://github.com/EQEmu/Server/pull/3730)) @joligario 2023-12-02
* Minor adjustment to #3726 ([#3732](https://github.com/EQEmu/Server/pull/3732)) @joligario 2023-12-03
* Modify `updated` column in `items` table with proper default. ([#3726](https://github.com/EQEmu/Server/pull/3726)) @joligario 2023-12-02
* Pull Spell Group Cache from Content DB ([#3749](https://github.com/EQEmu/Server/pull/3749)) @fryguy503 2023-12-08
### Faction
* Alliance line is only allowed 1 faction change at a time. ([#3718](https://github.com/EQEmu/Server/pull/3718)) @noudess 2023-11-26
### Fixes
* Changing Group Leader Invalidated GetLeaderName() ([#3712](https://github.com/EQEmu/Server/pull/3712)) @Kinglykrab 2023-11-26
* Fix 9245 SQL ([#3740](https://github.com/EQEmu/Server/pull/3740)) @Kinglykrab 2023-12-05
* Fix Swarm Pets Requiring NPC Aggros Flag ([#3738](https://github.com/EQEmu/Server/pull/3738)) @Kinglykrab 2023-12-05
* Guild Message Limits ([#3724](https://github.com/EQEmu/Server/pull/3724)) @neckkola 2023-11-29
### Quest API
* Add EVENT_AA_GAIN to AddAAPoints() ([#3733](https://github.com/EQEmu/Server/pull/3733)) @Kinglykrab 2023-12-03
* Add GMMove Overloads to Perl/Lua ([#3719](https://github.com/EQEmu/Server/pull/3719)) @Kinglykrab 2023-11-25
### Scripts
* Import items into `items_new` table instead of writing directly to the existing `items` table. ([#3725](https://github.com/EQEmu/Server/pull/3725)) @joligario 2023-11-30
* Revert database engine change from #3702. ([#3736](https://github.com/EQEmu/Server/pull/3736)) @joligario 2023-12-03
* Update 13th Floor Import Tool ([#3702](https://github.com/EQEmu/Server/pull/3702)) @joligario 2023-11-26
## [22.34.2] - 11/23/2023
### Admin
* Update date in changelog ([#3698](https://github.com/EQEmu/Server/pull/3698)) @joligario 2023-11-19
### Code
* Fix typo in #giveitem ([#3704](https://github.com/EQEmu/Server/pull/3704)) @Kinglykrab 2023-11-22
### Fixes
* Add "IgnoreLevelBasedHasteCaps" rule to GetHaste() ([#3705](https://github.com/EQEmu/Server/pull/3705)) @jcr4990 2023-11-23
* Fix bots/Mercenaries being removed from hatelist ([#3708](https://github.com/EQEmu/Server/pull/3708)) @Kinglykrab 2023-11-23
* Fix some spell types failing IsValidSpellRange check ([#3707](https://github.com/EQEmu/Server/pull/3707)) @nytmyr 2023-11-23
### Loginserver
* Update ticket login table structure ([#3703](https://github.com/EQEmu/Server/pull/3703)) @KimLS 2023-11-22
## [22.34.1] - 11/20/2023
### EQTime
Hotfix for world not spamming save messages by setting to detail level logging @Akkadius 2023-11-20
## [22.34.0] - 11/19/2023
### Bots
* Add ownerraid, byclass and byrace actionables and fix group-based arguments for raids. ([#3680](https://github.com/EQEmu/Server/pull/3680)) @nytmyr 2023-11-19
### Code
* Cleanup #giveitem and #summonitem ([#3692](https://github.com/EQEmu/Server/pull/3692)) @Kinglykrab 2023-11-19
* Cleanup #show currencies Command ([#3693](https://github.com/EQEmu/Server/pull/3693)) @Kinglykrab 2023-11-19
### Commands
* Add #show aa_points Command ([#3695](https://github.com/EQEmu/Server/pull/3695)) @Kinglykrab 2023-11-19
### Database
* Pull pet power from content database ([#3689](https://github.com/EQEmu/Server/pull/3689)) @joligario 2023-11-18
### GM Commands
* Add `#takeplatinum` ([#3690](https://github.com/EQEmu/Server/pull/3690)) @joligario 2023-11-19
* Remove duplicate comment ([#3691](https://github.com/EQEmu/Server/pull/3691)) @joligario 2023-11-19
### Illusions
* RandomizeFeastures erased texture. ([#3686](https://github.com/EQEmu/Server/pull/3686)) @noudess 2023-11-12
### Spawn
* (imported from takp) Added min_time and max_time to spawnentry. This will prevent a NPC from… ([#3685](https://github.com/EQEmu/Server/pull/3685)) @regneq 2023-11-18
## [22.33.0] - 11/11/2023
### Feature
* Add Comment to Item Data/Quest API ([#3669](https://github.com/EQEmu/Server/pull/3669)) @Kinglykrab 2023-11-07
### Spawn2
* Fix edge case with instances not copying disabled spawn state ([#3688](https://github.com/EQEmu/Server/pull/3688)) @Akkadius 2023-11-12
## [22.32.1] - 11/6/2023
### Hotfix
* Adjust spawn2_disabled migration to copy data over
## [22.32.0] - 11/6/2023
### Bots
* Fix invalid races from being created ([#3681](https://github.com/EQEmu/Server/pull/3681)) @nytmyr 2023-11-06
### Crash
* Fix crash on CentOS when forming a raid with PCs or BOTs ([#3676](https://github.com/EQEmu/Server/pull/3676)) @neckkola 2023-11-06
### Fixes
* Add IsTGBCompatibleSpell() to package.add ([#3675](https://github.com/EQEmu/Server/pull/3675)) @Kinglykrab 2023-11-04
* Fix Perl__worldwideremovetask package ([#3670](https://github.com/EQEmu/Server/pull/3670)) @Kinglykrab 2023-11-04
* Revert " Fix Killed XYZH support in EVENT_DEATH in Perl. " (#3682) ([#3591](https://github.com/EQEmu/Server/pull/3591)) @fryguy503 2023-11-06
CRASH
### GCC
* Compatibility fix for GCC 13 ([#3677](https://github.com/EQEmu/Server/pull/3677)) @joligario 2023-11-05
### Parser
* Cleanup Spire Parsing for crosszonemoveplayerbycharid ([#3674](https://github.com/EQEmu/Server/pull/3674)) @Kinglykrab 2023-11-04
* Cleanup Spire Parsing for crosszonemoveplayerbyexpeditionid ([#3671](https://github.com/EQEmu/Server/pull/3671)) @Kinglykrab 2023-11-04
* Cleanup Spire Parsing for crosszonemoveplayerbygroupid ([#3673](https://github.com/EQEmu/Server/pull/3673)) @Kinglykrab 2023-11-04
* Cleanup Spire Parsing for crosszonemoveplayerbyguildid ([#3672](https://github.com/EQEmu/Server/pull/3672)) @Kinglykrab 2023-11-04
### Quest API
* Add GetBaseRaceName() to Perl and Lua ([#3668](https://github.com/EQEmu/Server/pull/3668)) @joligario 2023-11-01
* Add details to Lua event dispatch errors ([#3679](https://github.com/EQEmu/Server/pull/3679)) @hgtw 2023-11-06
### Spawn
* Split spawn2 enabled into its own state table ([#3664](https://github.com/EQEmu/Server/pull/3664)) @Akkadius 2023-11-06
### Spells
* Added IsNightTime() for Dance of the Fireflies ([#3667](https://github.com/EQEmu/Server/pull/3667)) @regneq 2023-11-04
## [22.31.3] - 10/31/2023
### Bug
* Force raids off content database ([#3665](https://github.com/EQEmu/Server/pull/3665)) @joligario 2023-10-31
### Crash
* Revert " Fix spell in AESpell related to beacons " ([#3659](https://github.com/EQEmu/Server/pull/3659)) @Akkadius 2023-10-31
### Fixes
* Fix issue with blocked spells not loading properly @Akkadius 2023-10-31
### Logs
* Convert Loot Messages to Error Logs ([#3663](https://github.com/EQEmu/Server/pull/3663)) @Kinglykrab 2023-10-31
## [22.31.2] - 10/31/2023
### Fixes
* Hotfix issue with beacon spells crashing @Akkadius 2023-10-31
## [22.31.1] - 10/31/2023
### Fixes
* Hotfix issue with blocked spells not loading properly @Akkadius 2023-10-31
## [22.31.0] - 10/29/2023
### Crash
* Fix crash when client pointer does not exist during #hotfix ([#3661](https://github.com/EQEmu/Server/pull/3661)) @Akkadius 2023-10-29
* Fix spell in AESpell related to beacons ([#3659](https://github.com/EQEmu/Server/pull/3659)) @Akkadius 2023-10-29
### Database
* Add id to variables table ([#3658](https://github.com/EQEmu/Server/pull/3658)) @Akkadius 2023-10-29
### Linux
* Add symbols to release builds ([#3660](https://github.com/EQEmu/Server/pull/3660)) @Akkadius 2023-10-29
### Perl
* Revert " Reload perl quests on zone bootup " ([#3648](https://github.com/EQEmu/Server/pull/3648)) @Akkadius 2023-10-26
### Trading
* Fix part 3 of Issue 932. ([#3654](https://github.com/EQEmu/Server/pull/3654)) @noudess 2023-10-29
## [22.30.2] - 10/26/2023
### Fixes
Revert Perl regression in #3648 causing scripts to not reliably initialize on zone bootup. @Akkadius 2023-10-26
## [22.30.1] - 10/24/2023
### Fixes
* Fix empty InsertMany in bot starting items. ([#3653](https://github.com/EQEmu/Server/pull/3653)) @Kinglykrab 2023-10-24
## [22.30.0] - 10/23/2023
### API
* Implement Zone Sidecar ([#3635](https://github.com/EQEmu/Server/pull/3635)) @Akkadius 2023-10-24
### Commands
* Move #suspend from content database ([#3651](https://github.com/EQEmu/Server/pull/3651)) @joligario 2023-10-24
### Fixes
* Fix Bot Starting Items SQL ([#3649](https://github.com/EQEmu/Server/pull/3649)) @Kinglykrab 2023-10-23
### Perl
* Implement eqemu-perl for Linux ([#3652](https://github.com/EQEmu/Server/pull/3652)) @Akkadius 2023-10-24
* Reload perl quests on zone bootup ([#3648](https://github.com/EQEmu/Server/pull/3648)) @hgtw 2023-10-24
### Pets
* Disallow effect of alliance line when cast on pets. ([#3650](https://github.com/EQEmu/Server/pull/3650)) @noudess 2023-10-24
## [22.29.1] - 10/21/2023
### DB
* Fix manifest for blocked spells ([#3646](https://github.com/EQEmu/Server/pull/3646)) @joligario 2023-10-21
### Fixes
* Fix issue with subcommand settings not working ([#3643](https://github.com/EQEmu/Server/pull/3643)) @Kinglykrab 2023-10-21
* Hotfix command without hotfix name ([#3644](https://github.com/EQEmu/Server/pull/3644)) @joligario 2023-10-21
* Verifying mail keys when none exist ([#3645](https://github.com/EQEmu/Server/pull/3645)) @joligario 2023-10-21
## [22.29.0] - 10/20/2023
### Feature
* Add Expansion and Content Flag support to Blocked Spells ([#3638](https://github.com/EQEmu/Server/pull/3638)) @Kinglykrab 2023-10-20
### Fixes
* Fix crash when checking Bot Group/Raid membership ([#3641](https://github.com/EQEmu/Server/pull/3641)) @Aeadoin 2023-10-20
### Perl
* Static linker fix on Linux ([#3642](https://github.com/EQEmu/Server/pull/3642)) @Akkadius 2023-10-20
### Rules
* Add rule to configure max number of procs per round Combat:MaxProcs ([#3640](https://github.com/EQEmu/Server/pull/3640)) @Akkadius 2023-10-20
## [22.28.1] - 10/20/2023
### Build
* Perl Linux build fix
## [22.28.0] - 10/15/2023
### Bots
* Adjust Bot Movement Speed ([#3615](https://github.com/EQEmu/Server/pull/3615)) @Kinglykrab 2023-10-14
* Fix bot removal on zone, regression from #3611 ([#3631](https://github.com/EQEmu/Server/pull/3631)) @Akkadius 2023-10-16
### Crash
* Fix Crash with #summon ([#3618](https://github.com/EQEmu/Server/pull/3618)) @Kinglykrab 2023-10-14
* Fix crash in Mob::ShowBuffs ([#3632](https://github.com/EQEmu/Server/pull/3632)) @Akkadius 2023-10-16
* Resolve crash when assigning empty raid note. ([#3628](https://github.com/EQEmu/Server/pull/3628)) @Aeadoin 2023-10-15
### Feature
* Add Extra Kick Classes ([#3613](https://github.com/EQEmu/Server/pull/3613)) @Kinglykrab 2023-10-11
* Add Immune to Assassinate Special Ability ([#3622](https://github.com/EQEmu/Server/pull/3622)) @Kinglykrab 2023-10-14
* Add Immune to Headshot Special Ability ([#3624](https://github.com/EQEmu/Server/pull/3624)) @Kinglykrab 2023-10-14
* Update Raid Functions for Titanium and Underfoot ([#3524](https://github.com/EQEmu/Server/pull/3524)) @neckkola 2023-10-14
### Fixes
* Fix #cast defaulting to cast time ([#3617](https://github.com/EQEmu/Server/pull/3617)) @Kinglykrab 2023-10-14
### Parser Fix
* Fix SendIllusion Spire parsing ([#3623](https://github.com/EQEmu/Server/pull/3623)) @Kinglykrab 2023-10-14
### Quest API
* Add GrantAllAAPoints() to Perl/Lua and Modify #grantaa ([#3616](https://github.com/EQEmu/Server/pull/3616)) @Kinglykrab 2023-10-14
* Add target ID and spell exports to events ([#3620](https://github.com/EQEmu/Server/pull/3620)) @Kinglykrab 2023-10-15
### Scripts
* Update 13th Floor importer ([#3630](https://github.com/EQEmu/Server/pull/3630)) @joligario 2023-10-16
* Update 13th Floor script for legacy research tome bagtypes ([#3621](https://github.com/EQEmu/Server/pull/3621)) @joligario 2023-10-14
## [22.27.0] - 10/07/2023
### Crash
* Bot member zoned crash fix ([#3607](https://github.com/EQEmu/Server/pull/3607)) @Akkadius 2023-10-07
* Fix #summon crash ([#3608](https://github.com/EQEmu/Server/pull/3608)) @Akkadius 2023-10-07
* Fix CanUseAlternateAdvancementRank crash ([#3609](https://github.com/EQEmu/Server/pull/3609)) @Akkadius 2023-10-07
* Fix crash in #movechar ([#3612](https://github.com/EQEmu/Server/pull/3612)) @Akkadius 2023-10-07
* Fix crash in CastSpell Quest API input cast ([#3610](https://github.com/EQEmu/Server/pull/3610)) @Akkadius 2023-10-07
* Fix dangling pointer crash observed in SendHPPacketsFrom ([#3611](https://github.com/EQEmu/Server/pull/3611)) @Akkadius 2023-10-07
* Fix rarer crash with File::Makedir ([#3606](https://github.com/EQEmu/Server/pull/3606)) @Akkadius 2023-10-07
### Fixes
* Add Validation to #find, #set, and #show args ([#3598](https://github.com/EQEmu/Server/pull/3598)) @Kinglykrab 2023-09-18
* Ensure Linux builds report failures @Akkadius 2023-10-03
* Fix #show group_info Popup ([#3605](https://github.com/EQEmu/Server/pull/3605)) @Kinglykrab 2023-10-04
* Fix swarm pet names to use '_' instead of ' ' ([#3601](https://github.com/EQEmu/Server/pull/3601)) @noudess 2023-09-19
* Invis vs. Undead/Animal Breaks Charm for Pets ([#3587](https://github.com/EQEmu/Server/pull/3587)) @crdunwel 2023-09-19
### Logs
* Change pathing log messages from Error to Pathing. ([#3604](https://github.com/EQEmu/Server/pull/3604)) @joligario 2023-09-29
### Quest API
* Add Caster ID Parameter to FindBuff in Perl/Lua ([#3590](https://github.com/EQEmu/Server/pull/3590)) @Kinglykrab 2023-09-29
## [22.26.2] - 09/18/2023
### Fixes
* Fix an issue with schema versioning for the AA update
## [22.26.1] - 09/17/2023
### Fixes
* Add Validation to #find, #set, and #show args ([#3598](https://github.com/EQEmu/Server/pull/3598)) @Kinglykrab 2023-09-17
## [22.26.0] - 09/17/2023
### Bug
* Additional Wild Ramp param was causing an overflow it appears at least on local testing. ([#3589](https://github.com/EQEmu/Server/pull/3589)) @fryguy503 2023-09-11
### Commands
* npc_edit faction and #setfaction duplicate and incorrect. ([#3577](https://github.com/EQEmu/Server/pull/3577)) @noudess 2023-09-03
### Feature
* Add Defensive Proc Rules for Level Gap Penalty ([#3580](https://github.com/EQEmu/Server/pull/3580)) @Kinglykrab 2023-09-17
* Add opcodes for Cast and Scribe book buttons ([#3578](https://github.com/EQEmu/Server/pull/3578)) @hgtw 2023-09-17
* Cleanup Group Split Money Logic ([#3583](https://github.com/EQEmu/Server/pull/3583)) @crdunwel 2023-09-17
### Fixes
* AA System Fixes ([#3572](https://github.com/EQEmu/Server/pull/3572)) @KimLS 2023-09-17
* Check for Song Skill Increase on Bard Pulse ([#3586](https://github.com/EQEmu/Server/pull/3586)) @crdunwel 2023-09-17
* Fix #set faction/#setfaction Command ([#3575](https://github.com/EQEmu/Server/pull/3575)) @Kinglykrab 2023-09-02
* Fix Killed XYZH support in EVENT_DEATH in Perl. ([#3591](https://github.com/EQEmu/Server/pull/3591)) @Kinglykrab 2023-09-17
* Fix entity ID on death with #castspell ([#3592](https://github.com/EQEmu/Server/pull/3592)) @Kinglykrab 2023-09-17
* Zoning logging edge case safety @Akkadius 2023-08-29
### Logging
* Add logging to track down Wild Ramp issue ([#3588](https://github.com/EQEmu/Server/pull/3588)) @fryguy503 2023-09-11
### Messages
* Remove duplicate message on tracking begin ([#3574](https://github.com/EQEmu/Server/pull/3574)) @noudess 2023-09-11
* Swarm pet normal damage messages were missing ([#3594](https://github.com/EQEmu/Server/pull/3594)) @noudess 2023-09-17
### Quest API
* Add ApplySpell() and SetBuffDuration() overloads to Perl/Lua ([#3576](https://github.com/EQEmu/Server/pull/3576)) @Kinglykrab 2023-09-17
* Add XYZ/XYZH Overloads to Cross Zone Move Methods ([#3581](https://github.com/EQEmu/Server/pull/3581)) @Kinglykrab 2023-09-17
## [22.25.0] - 08/28/2023
### Bots
* Add Support for Mana Pool AA Bonuses. ([#3571](https://github.com/EQEmu/Server/pull/3571)) @Aeadoin 2023-08-21
* Remove In-Game Command References to Bot Groups ([#3545](https://github.com/EQEmu/Server/pull/3545)) @Aeadoin 2023-08-13
### Bug
* Escape item name in trader audit. ([#3540](https://github.com/EQEmu/Server/pull/3540)) @fryguy503 2023-08-13
### CMake
* Add cmake option to re-enable MSVC warnings ([#3537](https://github.com/EQEmu/Server/pull/3537)) @hgtw 2023-08-13
* Define perlbind option for all targets ([#3538](https://github.com/EQEmu/Server/pull/3538)) @hgtw 2023-08-13
### Charm
* Fix to update target windows on charm on/off ([#3549](https://github.com/EQEmu/Server/pull/3549)) @noudess 2023-08-20
### Combat Messages
* Fix issue where pet proc damage was not showing up ([#3551](https://github.com/EQEmu/Server/pull/3551)) @noudess 2023-08-24
### Database
* Change primary key entry to NOT NULL ([#3559](https://github.com/EQEmu/Server/pull/3559)) @joligario 2023-08-20
* Extend dumper CLI utility to export static instance data ([#3562](https://github.com/EQEmu/Server/pull/3562)) @Akkadius 2023-08-20
### Expansions
* Expansion settings tweaks ([#3556](https://github.com/EQEmu/Server/pull/3556)) @Akkadius 2023-08-20
### Feature
* Add adjustability for AERampage Range. ([#3548](https://github.com/EQEmu/Server/pull/3548)) @fryguy503 2023-08-20
* Change #reload zone to reload zone headers globally. ([#3557](https://github.com/EQEmu/Server/pull/3557)) @Kinglykrab 2023-08-20
* Change money type to all lower case as EQ live money shares and split has it that way. ([#3550](https://github.com/EQEmu/Server/pull/3550)) @regneq 2023-08-18
### Fixes
* Add character_stats_record to player tables @Akkadius 2023-08-11
* Bots no longer drop group on death, and raid fixes. ([#3542](https://github.com/EQEmu/Server/pull/3542)) @Aeadoin 2023-08-13
* Bots will now load AAs properly when spawned. ([#3544](https://github.com/EQEmu/Server/pull/3544)) @Aeadoin 2023-08-13
* Clearing target window on CHARM wear off had a side effect ([#3570](https://github.com/EQEmu/Server/pull/3570)) @noudess 2023-08-21
* Fix #motd/#set motd Command ([#3558](https://github.com/EQEmu/Server/pull/3558)) @Kinglykrab 2023-08-20
* Fix Bot::CheckDataBucket to work with Owner Buckets. ([#3552](https://github.com/EQEmu/Server/pull/3552)) @Aeadoin 2023-08-18
* Fix to zoning logging exception @Akkadius 2023-08-29
* Instance GetUnusedInstanceID crash fox @Akkadius 2023-08-21
* Minor adjustment to formula calc position to fix modifier bug. ([#3565](https://github.com/EQEmu/Server/pull/3565)) @Valorith 2023-08-21
### Instances
* Honor reserved instances ([#3563](https://github.com/EQEmu/Server/pull/3563)) @joligario 2023-08-21
* Refine id selection ([#3568](https://github.com/EQEmu/Server/pull/3568)) @joligario 2023-08-29
### Logging
* Add detailed zoning logging ([#3555](https://github.com/EQEmu/Server/pull/3555)) @Akkadius 2023-08-20
### Quest API
* Reload content flags globally when a content flag is set ([#3564](https://github.com/EQEmu/Server/pull/3564)) @Akkadius 2023-08-21
### Rules
* Add FinalRaidExpMultiplier Rule ([#3554](https://github.com/EQEmu/Server/pull/3554)) @Valorith 2023-08-20
* Add a rule to adjust the randomization range for Wizard\Caster Merc innate critical ratio. ([#3543](https://github.com/EQEmu/Server/pull/3543)) @catapultam-habeo 2023-08-13
* Add rule to restrict hand in of quest items to quest flagged NPCs. ([#3536](https://github.com/EQEmu/Server/pull/3536)) @Valorith 2023-08-13
* Add rule to toggle pets accepting quest items ([#3533](https://github.com/EQEmu/Server/pull/3533)) @Valorith 2023-08-06
* Also reload rules in world when #reload rules invoked ([#3566](https://github.com/EQEmu/Server/pull/3566)) @Akkadius 2023-08-21
* Correct explanation of Bots:ManaRegen ([#3569](https://github.com/EQEmu/Server/pull/3569)) @Aeadoin 2023-08-21
### Spawns
* Fixes a rarer issue where spawn2 is not being properly content filtered @Akkadius 2023-08-13
## [22.24.0] - 08/05/2023
### Character
* Record character stats to `character_stats_record` table ([#3522](https://github.com/EQEmu/Server/pull/3522)) @Akkadius 2023-08-05
### Code
* Cleanup #view zone_loot Command ([#3523](https://github.com/EQEmu/Server/pull/3523)) @Kinglykrab 2023-08-02
* Remove Strings::Commify from all identifier values ([#3528](https://github.com/EQEmu/Server/pull/3528)) @Kinglykrab 2023-08-02
### Feature
* Add Support for Drakkin Heritage Illusions ([#3521](https://github.com/EQEmu/Server/pull/3521)) @Kinglykrab 2023-08-01
### Fixes
* Bug fix for raid mark NPC across zones ([#3525](https://github.com/EQEmu/Server/pull/3525)) @neckkola 2023-08-05
* Bugs table should not target content database ([#3535](https://github.com/EQEmu/Server/pull/3535)) @Akkadius 2023-08-05
* Fix +/- 0.1 XYZ Door Manipulation ([#3527](https://github.com/EQEmu/Server/pull/3527)) @Kinglykrab 2023-08-02
* Fix issue with mob scanning when trying to use EVENT_SPAWN ([#3529](https://github.com/EQEmu/Server/pull/3529)) @Akkadius 2023-08-04
### Quest API
* Adjust GetCloseMobList calls internally ([#3530](https://github.com/EQEmu/Server/pull/3530)) @Akkadius 2023-08-04
## [22.23.0] - 07/31/2023
### Databuckets
* Improvements to distributed cache, reload commands ([#3519](https://github.com/EQEmu/Server/pull/3519)) @Akkadius 2023-08-01
### Fixes
* Fix #gm top level alias for #set gm ([#3517](https://github.com/EQEmu/Server/pull/3517)) @Kinglykrab 2023-07-30
* Fix Appearance Issues ([#3520](https://github.com/EQEmu/Server/pull/3520)) @Kinglykrab 2023-08-01
* Fix NPC Cast Events not parsing properly. ([#3518](https://github.com/EQEmu/Server/pull/3518)) @Kinglykrab 2023-08-01
### Scaling/Bug Fix
* Scaling where min and max damage was bugged ([#3514](https://github.com/EQEmu/Server/pull/3514)) @noudess 2023-08-01
## [22.22.1] - 07/30/2023
### Database
* Hotfix: Add command_subsettings to server tables @Akkadius 2023-07-29
### Doors
* Add door blacklist ([#3516](https://github.com/EQEmu/Server/pull/3516)) @Akkadius 2023-07-30
## [22.22.0] - 07/27/2023
### Code
* Fix casing in corpse money and decay time. ([#3511](https://github.com/EQEmu/Server/pull/3511)) @Kinglykrab 2023-07-23
### Crash Fix
* Guard against Spells:MaxTotalSlotsPET being set above client allowed maximum. ([#3507](https://github.com/EQEmu/Server/pull/3507)) @Valorith 2023-07-22
### Data Buckets
* Distributed Databucket Caching ([#3500](https://github.com/EQEmu/Server/pull/3500)) @Kinglykrab 2023-07-24
### Database
* Fix console output in database:dump --dump-output-to-console @Akkadius 2023-07-25
### Fixes
* Escape search string in #find item ([#3510](https://github.com/EQEmu/Server/pull/3510)) @Kinglykrab 2023-07-22
### Quest API
* Add GetMobTypeIdentifier() to Perl/Lua ([#3512](https://github.com/EQEmu/Server/pull/3512)) @Kinglykrab 2023-07-28
### Saylink
* Fix cases where saylinks were not being cached ([#3508](https://github.com/EQEmu/Server/pull/3508)) @Akkadius 2023-07-20
## [22.21.2] - 07/19/2023
### Databuckets
* Fix rarer same bucket name scoping overlap issue ([#3509](https://github.com/EQEmu/Server/pull/3509)) @Akkadius 2023-07-20
## [22.21.1] - 07/18/2023
### Bug
* Show Petition and Show Petition_Info fix ([#3503](https://github.com/EQEmu/Server/pull/3503)) @fryguy503 2023-07-18
### Code
* Remove arbitrary teleport blocking in Tutorial and Load zones ([#3506](https://github.com/EQEmu/Server/pull/3506)) @Valorith 2023-07-19
### Databuckets
* Fix issue with expired databuckets not being expired and returned properly ([#3504](https://github.com/EQEmu/Server/pull/3504)) @Akkadius 2023-07-18
### Fixes
* #set title_suffix Argument Position ([#3505](https://github.com/EQEmu/Server/pull/3505)) @Kinglykrab 2023-07-18
## [22.21.0] - 07/18/2023
### Data Buckets
* Implement scoped data buckets ([#3498](https://github.com/EQEmu/Server/pull/3498)) @Akkadius 2023-07-16
### Fixes
* Fix rule check and add rule for pickpocket command ([#3492](https://github.com/EQEmu/Server/pull/3492)) @tuday2 2023-07-16
### Pathing
* Improvements to roambox logic, pathing ([#3502](https://github.com/EQEmu/Server/pull/3502)) @Akkadius 2023-07-18
### Quest API
* Add SetLDoNPoints() to Perl/Lua ([#3496](https://github.com/EQEmu/Server/pull/3496)) @Kinglykrab 2023-07-16
### Z Clipping
* Don't issue zclip adjustments when NPC is not moving ([#3499](https://github.com/EQEmu/Server/pull/3499)) @Akkadius 2023-07-16
## [22.20.1] - 07/15/2023
### Database
* Fix database manifest entry for #3443 @neckkola 2023-07-15
## [22.20.0] - 07/15/2023
### Bots
* Remove orphaned commands related to botgroup ([#3489](https://github.com/EQEmu/Server/pull/3489)) @tuday2 2023-07-09
### Commands
* Consolidate #set-like commands into a singular #set command ([#3486](https://github.com/EQEmu/Server/pull/3486)) @Kinglykrab 2023-07-15
### Feature
* Add Support for item textures higher than 65,535 ([#3494](https://github.com/EQEmu/Server/pull/3494)) @Kinglykrab 2023-07-14
* Update raid features ([#3443](https://github.com/EQEmu/Server/pull/3443)) @neckkola 2023-07-13
### Fixes
* Fix Tradeskill Combines with augmented items ([#3490](https://github.com/EQEmu/Server/pull/3490)) @Kinglykrab 2023-07-15
* Fix charmed pets to follow when charmed. ([#3488](https://github.com/EQEmu/Server/pull/3488)) @noudess 2023-07-08
* Update bot naming check and add more explanation ([#3491](https://github.com/EQEmu/Server/pull/3491)) @tuday2 2023-07-13
### Quest API
* Add Mob/Entity type check methods to Perl/Lua ([#3493](https://github.com/EQEmu/Server/pull/3493)) @Kinglykrab 2023-07-13
## [22.19.0] - 07/08/2023
### Bots
* Add Pickpocket Command ([#3484](https://github.com/EQEmu/Server/pull/3484)) @tuday2 2023-07-08
### Code
* Move #find item summon links to front ([#3483](https://github.com/EQEmu/Server/pull/3483)) @Kinglykrab 2023-07-05
* Remove LoadItemDBFieldNames() from common/misc.cpp and common/misc.h ([#3473](https://github.com/EQEmu/Server/pull/3473)) @Kinglykrab 2023-07-04
### Commands
* Add #itemsearch alias to #find aliases ([#3485](https://github.com/EQEmu/Server/pull/3485)) @Kinglykrab 2023-07-08
* Consolidate #show commands into a singular #show command ([#3478](https://github.com/EQEmu/Server/pull/3478)) @Kinglykrab 2023-07-08
### Fixes
* Fix _PutItem having a slot_id of -1 on mobs with no items ([#3474](https://github.com/EQEmu/Server/pull/3474)) @Kinglykrab 2023-07-04
### Rules
* Add Skills:TrivialTradeskillCombinesNoFail Rule ([#3481](https://github.com/EQEmu/Server/pull/3481)) @JasXSL 2023-07-05
## [22.18.0] - 07/04/2023
### Commands
+22 -2
View File
@@ -23,7 +23,12 @@ IF (EQEMU_BUILD_STATIC)
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".a")
MESSAGE(STATUS "Building with static linking")
SET(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")
ENDIF(EQEMU_BUILD_STATIC)
IF (UNIX)
SET(PERL_LIBRARY "/opt/eqemu-perl/lib/5.32.1/x86_64-linux-thread-multi/CORE/libperl.so")
SET(PERL_INCLUDE_PATH "/opt/eqemu-perl/lib/5.32.1/x86_64-linux-thread-multi/CORE/")
SET(PERL_EXECUTABLE "/opt/eqemu-perl/bin/perl")
ENDIF ()
ENDIF (EQEMU_BUILD_STATIC)
IF(MSVC)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
@@ -32,7 +37,11 @@ IF(MSVC)
ADD_DEFINITIONS(-D_HAS_AUTO_PTR_ETC) # for Luabind on C++17
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
ADD_DEFINITIONS( "/W0 /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /nologo /Os")
OPTION(EQEMU_DISABLE_MSVC_WARNINGS "Disable MSVC compile warnings." ON)
IF(EQEMU_DISABLE_MSVC_WARNINGS)
ADD_DEFINITIONS( "/W0 /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /nologo /Os")
ENDIF(EQEMU_DISABLE_MSVC_WARNINGS)
ELSE(MSVC)
ADD_DEFINITIONS(-DHAS_UNION_SEMUN)
ENDIF(MSVC)
@@ -129,6 +138,13 @@ ELSE()
MESSAGE(STATUS "* mbedTLS: MISSING *")
ENDIF()
MESSAGE(STATUS "PERL_INCLUDE_PATH: ${PERL_INCLUDE_PATH}")
MESSAGE(STATUS "PERL_LIBRARY: ${PERL_LIBRARY}")
MESSAGE(STATUS "PERL_INCLUDE_DIR: ${PERL_INCLUDE_DIR}")
MESSAGE(STATUS "PERL_INCLUDE_DIRS: ${PERL_INCLUDE_DIRS}")
MESSAGE(STATUS "PERL_LIBRARIES: ${PERL_LIBRARIES}")
MESSAGE(STATUS "PERL_VERSION: ${PERL_VERSION}")
MESSAGE(STATUS "**************************************************")
#options
@@ -384,6 +400,10 @@ IF(PERL_LIBRARY_ENABLED)
INCLUDE_DIRECTORIES(SYSTEM "${PERL_LIBRARY_INCLUDE}")
ADD_DEFINITIONS(-DEMBPERL)
ADD_DEFINITIONS(-DEMBPERL_PLUGIN)
ADD_DEFINITIONS(-DPERLBIND_NO_STRICT_SCALAR_TYPES)
IF (UNIX AND EQEMU_BUILD_STATIC)
SET(SERVER_LIBS ${SERVER_LIBS} libcrypt.a)
ENDIF ()
ENDIF()
ENDIF()
+1 -1
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
add_subdirectory(import)
add_subdirectory(export)
+4
View File
@@ -70,6 +70,7 @@ SET(common_sources
perl_eqdb.cpp
perl_eqdb_res.cpp
process/process.cpp
process.cpp
proc_launcher.cpp
profanity_manager.cpp
ptimer.cpp
@@ -90,6 +91,7 @@ SET(common_sources
timer.cpp
unix.cpp
platform.cpp
json/json.hpp
json/jsoncpp.cpp
zone_store.cpp
net/console_server.cpp
@@ -583,12 +585,14 @@ SET(common_headers
path_manager.cpp
platform.h
process/process.h
process.h
proc_launcher.h
profanity_manager.h
profiler.h
ptimer.h
queue.h
races.h
raid.h
random.h
rdtsc.h
rulesys.h
+20 -27
View File
@@ -39,15 +39,15 @@ namespace EQEmuCommand {
{
if (cmd[{"-d", "--debug"}]) {
std::cout << "Positional args:\n";
for (auto &pos_arg : cmd.pos_args())
for (auto &pos_arg: cmd.pos_args())
std::cout << '\t' << pos_arg << std::endl;
std::cout << "\nFlags:\n";
for (auto &flag : cmd.flags())
for (auto &flag: cmd.flags())
std::cout << '\t' << flag << std::endl;
std::cout << "\nParameters:\n";
for (auto &param : cmd.params())
for (auto &param: cmd.params())
std::cout << '\t' << param.first << " : " << param.second << std::endl;
}
}
@@ -69,8 +69,8 @@ namespace EQEmuCommand {
{
bool arguments_filled = true;
int index = 2;
for (auto &arg : arguments) {
int index = 2;
for (auto &arg: arguments) {
if (cmd(arg).str().empty() && cmd(index).str().empty()) {
arguments_filled = false;
}
@@ -79,12 +79,12 @@ namespace EQEmuCommand {
if (!arguments_filled || (argc == 2 && !cmd[{"-h", "--help"}]) || (argc == 3 && cmd[{"-h", "--help"}])) {
std::string arguments_string;
for (auto &arg : arguments) {
for (auto &arg: arguments) {
arguments_string += " " + arg;
}
std::string options_string;
for (auto &opt : options) {
for (auto &opt: options) {
options_string += " " + opt + "\n";
}
@@ -124,14 +124,6 @@ namespace EQEmuCommand {
)
{
std::string description;
bool ran_command = false;
for (auto &it: in_function_map) {
if (it.first == argv[1]) {
(it.second)(argc, argv, cmd, description);
ran_command = true;
}
}
if (cmd[{"-h", "--help"}]) {
std::cout << std::endl;
std::cout <<
@@ -142,9 +134,7 @@ namespace EQEmuCommand {
<< std::endl
<< std::endl;
/**
* Get max command length for padding length
*/
// Get max command length for padding length
int max_command_length = 0;
for (auto &it: in_function_map) {
@@ -155,18 +145,14 @@ namespace EQEmuCommand {
}
}
/**
* Display command menu
*/
// Display command menu
std::string command_section;
for (auto &it: in_function_map) {
description.clear();
(it.second)(argc, argv, cmd, description);
/**
* Print section header
*/
// Print section header
std::string command_prefix = it.first.substr(0, it.first.find(":"));
if (command_prefix.find("test") != std::string::npos) {
@@ -178,9 +164,7 @@ namespace EQEmuCommand {
std::cout << termcolor::reset << command_prefix << std::endl;
}
/**
* Print commands
*/
// Print commands
std::stringstream command;
command << termcolor::colorize << termcolor::yellow << it.first << termcolor::reset;
printf(" %-*s %s\n", max_command_length, command.str().c_str(), description.c_str());
@@ -191,6 +175,15 @@ namespace EQEmuCommand {
std::exit(0);
}
bool ran_command = false;
for (auto &it: in_function_map) {
if (it.first == argv[1]) {
(it.second)(argc, argv, cmd, description);
ran_command = true;
}
}
if (ran_command) {
std::exit(0);
}
+41 -36
View File
@@ -29,6 +29,8 @@
#include <stdlib.h>
#include <string.h>
#include "../common/repositories/account_repository.h"
// Disgrace: for windows compile
#ifdef _WINDOWS
#include <windows.h>
@@ -1643,25 +1645,20 @@ void Database::ClearGroupLeader(uint32 gid) {
std::cout << "Unable to clear group leader: " << results.ErrorMessage() << std::endl;
}
uint8 Database::GetAgreementFlag(uint32 acctid) {
std::string query = StringFormat("SELECT rulesflag FROM account WHERE id=%i",acctid);
auto results = QueryDatabase(query);
if (!results.Success())
uint8 Database::GetAgreementFlag(uint32 account_id)
{
const auto& e = AccountRepository::FindOne(*this, account_id);
if (!e.id) {
return 0;
}
if (results.RowCount() != 1)
return 0;
auto row = results.begin();
return Strings::ToUnsignedInt(row[0]);
return e.rulesflag;
}
void Database::SetAgreementFlag(uint32 acctid) {
std::string query = StringFormat("UPDATE account SET rulesflag=1 where id=%i", acctid);
QueryDatabase(query);
void Database::SetAgreementFlag(uint32 account_id) {
auto e = AccountRepository::FindOne(*this, account_id);
e.rulesflag = 1;
AccountRepository::UpdateOne(*this, e);
}
void Database::ClearRaid(uint32 rid) {
@@ -2097,37 +2094,45 @@ void Database::ClearInvSnapshots(bool from_now) {
struct TimeOfDay_Struct Database::LoadTime(time_t &realtime)
{
TimeOfDay_Struct eqTime;
std::string query = StringFormat("SELECT minute,hour,day,month,year,realtime FROM eqtime limit 1");
TimeOfDay_Struct t{};
std::string query = StringFormat("SELECT minute,hour,day,month,year,realtime FROM eqtime limit 1");
auto results = QueryDatabase(query);
if (!results.Success() || results.RowCount() == 0){
if (!results.Success() || results.RowCount() == 0) {
LogInfo("Loading EQ time of day failed. Using defaults");
eqTime.minute = 0;
eqTime.hour = 9;
eqTime.day = 1;
eqTime.month = 1;
eqTime.year = 3100;
t.minute = 0;
t.hour = 9;
t.day = 1;
t.month = 1;
t.year = 3100;
realtime = time(nullptr);
}
else{
auto row = results.begin();
eqTime.minute = Strings::ToUnsignedInt(row[0]);
eqTime.hour = Strings::ToUnsignedInt(row[1]);
eqTime.day = Strings::ToUnsignedInt(row[2]);
eqTime.month = Strings::ToUnsignedInt(row[3]);
eqTime.year = Strings::ToUnsignedInt(row[4]);
realtime = Strings::ToBigInt(row[5]);
return t;
}
return eqTime;
auto row = results.begin();
uint8 hour = Strings::ToUnsignedInt(row[1]);
time_t realtime_ = Strings::ToBigInt(row[5]);
if (RuleI(World, BootHour) > 0 && RuleI(World, BootHour) <= 24) {
hour = RuleI(World, BootHour);
realtime_ = time(nullptr);
}
t.minute = Strings::ToUnsignedInt(row[0]);
t.hour = hour;
t.day = Strings::ToUnsignedInt(row[2]);
t.month = Strings::ToUnsignedInt(row[3]);
t.year = Strings::ToUnsignedInt(row[4]);
realtime = realtime_;
LogEqTime("Setting hour to [{}]", hour);
return t;
}
bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year)
{
std::string query = StringFormat("UPDATE eqtime set minute = %d, hour = %d, day = %d, month = %d, year = %d, realtime = %d limit 1", minute, hour, day, month, year, time(0));
std::string query = StringFormat("UPDATE eqtime set minute = %d, hour = %d, day = %d, month = %d, year = %d, realtime = %d limit 1", minute, hour, day, month, year, time(nullptr));
auto results = QueryDatabase(query);
return results.Success();
+2 -2
View File
@@ -188,10 +188,10 @@ public:
uint32 CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus = 0);
uint32 CreateAccount(const char* name, const char* password, int16 status, const char* loginserver, uint32 lsaccount_id);
uint32 GetAccountIDFromLSID(const std::string& in_loginserver_id, uint32 in_loginserver_account_id, char* in_account_name = 0, int16* in_status = 0);
uint8 GetAgreementFlag(uint32 acctid);
uint8 GetAgreementFlag(uint32 account_id);
void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus);
void SetAgreementFlag(uint32 acctid);
void SetAgreementFlag(uint32 account_id);
int GetIPExemption(std::string account_ip);
void SetIPExemption(std::string account_ip, int exemption_amount);
+18 -1
View File
@@ -279,6 +279,11 @@ void DatabaseDumpService::DatabaseDump()
}
}
if (IsDumpStaticInstanceData()) {
tables_to_dump += "instance_list";
options += " --no-create-info --where=\"instance_list.is_global > 0 and instance_list.never_expires > 0\"";
}
if (!dump_descriptor.empty()) {
SetDumpFileName(GetDumpFileName() + dump_descriptor);
}
@@ -324,7 +329,9 @@ void DatabaseDumpService::DatabaseDump()
}
}
LogSys.LoadLogSettingsDefaults();
if (!IsDumpOutputToConsole()) {
LogSys.LoadLogSettingsDefaults();
}
if (!pipe_file.empty()) {
std::string file = fmt::format("{}.sql", GetDumpFileNameWithPath());
@@ -604,3 +611,13 @@ void DatabaseDumpService::RemoveCredentialsFile()
std::filesystem::remove(CREDENTIALS_FILE);
}
}
bool DatabaseDumpService::IsDumpStaticInstanceData()
{
return dump_static_instance_data;
}
void DatabaseDumpService::SetDumpStaticInstanceData(bool b)
{
dump_static_instance_data = b;
}
+5
View File
@@ -58,6 +58,9 @@ public:
bool IsDumpMercTables() const;
void SetDumpMercTables(bool dump_bot_tables);
void SetDumpStaticInstanceData(bool b);
bool IsDumpStaticInstanceData();
private:
bool dump_all_tables = false;
bool dump_state_tables = false;
@@ -73,6 +76,8 @@ private:
bool dump_drop_table_syntax_only = false;
bool dump_bot_tables = false;
bool dump_merc_tables = false;
bool dump_static_instance_data = false;
std::string dump_path;
std::string dump_file_name;
@@ -4760,6 +4760,364 @@ UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
)"
},
ManifestEntry{
.version = 9230,
.description = "2023_06_23_raid_feature_updates",
.check = "SHOW COLUMNS FROM `raid_members` LIKE 'is_assister'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `raid_members`
ADD COLUMN `is_marker` TINYINT UNSIGNED DEFAULT 0 NOT NULL AFTER `islooter`,
ADD COLUMN `is_assister` TINYINT UNSIGNED DEFAULT 0 NOT NULL AFTER `is_marker`,
ADD COLUMN `note` VARCHAR(64) DEFAULT '' NOT NULL AFTER `is_assister`;
ALTER TABLE `raid_details`
ADD COLUMN `marked_npc_1` SMALLINT UNSIGNED DEFAULT 0 NOT NULL AFTER `motd`,
ADD COLUMN `marked_npc_2` SMALLINT UNSIGNED DEFAULT 0 NOT NULL AFTER `marked_npc_1`,
ADD COLUMN `marked_npc_3` SMALLINT UNSIGNED DEFAULT 0 NOT NULL AFTER `marked_npc_2`;
)",
},
ManifestEntry{
.version = 9231,
.description = "2023_07_14_npc_unsigned_melee_texture.sql",
.check = "SHOW COLUMNS FROM `npc_types` LIKE 'd_melee_texture1'",
.condition = "contains",
.match = "int(11) signed",
.sql = R"(ALTER TABLE `npc_types`
MODIFY COLUMN `d_melee_texture1` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `armortint_blue`,
MODIFY COLUMN `d_melee_texture2` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `d_melee_texture1`;
)",
},
ManifestEntry{
.version = 9232,
.description = "2023_07_11_command_subsettings.sql",
.check = "SHOW TABLES LIKE 'command_subsettings'",
.condition = "empty",
.match = "",
.sql = R"(CREATE TABLE `command_subsettings` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`parent_command` varchar(32) NOT NULL,
`sub_command` varchar(32) NOT NULL,
`access_level` int(11) UNSIGNED NOT NULL DEFAULT 0,
`top_level_aliases` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `command`(`parent_command`, `sub_command`)
)
)"
},
ManifestEntry{
.version = 9233,
.description = "2023_07_16_scoped_data_buckets.sql",
.check = "SHOW COLUMNS FROM `data_buckets` LIKE 'character_id'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `data_buckets`
ADD COLUMN `character_id` bigint(11) NOT NULL DEFAULT 0 AFTER `expires`,
ADD COLUMN `npc_id` bigint(11) NOT NULL DEFAULT 0 AFTER `character_id`,
ADD COLUMN `bot_id` bigint(11) NOT NULL DEFAULT 0 AFTER `npc_id`,
DROP INDEX `key_index`,
ADD UNIQUE INDEX `keys`(`key`,`character_id`,`npc_id`,`bot_id`);
UPDATE data_buckets SET character_id = SUBSTRING_INDEX(SUBSTRING_INDEX( `key`, '-', 2 ), '-', -1), `key` = SUBSTR(SUBSTRING_INDEX(`key`, SUBSTRING_INDEX( `key`, '-', 2 ), -1), 2) WHERE `key` LIKE 'character-%';
UPDATE data_buckets SET npc_id = SUBSTRING_INDEX(SUBSTRING_INDEX( `key`, '-', 2 ), '-', -1), `key` = SUBSTR(SUBSTRING_INDEX(`key`, SUBSTRING_INDEX( `key`, '-', 2 ), -1), 2) WHERE `key` LIKE 'npc-%';
UPDATE data_buckets SET bot_id = SUBSTRING_INDEX(SUBSTRING_INDEX( `key`, '-', 2 ), '-', -1), `key` = SUBSTR(SUBSTRING_INDEX(`key`, SUBSTRING_INDEX( `key`, '-', 2 ), -1), 2) WHERE `key` LIKE 'bot-%';
)"
},
ManifestEntry{
.version = 9234,
.description = "2023_07_27_update_raid_details.sql",
.check = "SHOW COLUMNS FROM `raid_details` LIKE 'marked_npc_1_entity_id';",
.condition = "empty",
.match = "",
.sql = R"(ALTER TABLE `raid_details`
CHANGE COLUMN `marked_npc_1` `marked_npc_1_entity_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `motd`,
ADD COLUMN `marked_npc_1_zone_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_1_entity_id`,
ADD COLUMN `marked_npc_1_instance_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_1_zone_id`,
CHANGE COLUMN `marked_npc_2` `marked_npc_2_entity_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_1_instance_id`,
ADD COLUMN `marked_npc_2_zone_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_2_entity_id`,
ADD COLUMN `marked_npc_2_instance_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_2_zone_id`,
CHANGE COLUMN `marked_npc_3` `marked_npc_3_entity_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_2_instance_id`,
ADD COLUMN `marked_npc_3_zone_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_3_entity_id`,
ADD COLUMN `marked_npc_3_instance_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_3_zone_id`;
)"
},
ManifestEntry{
.version = 9235,
.description = "2023_07_31_character_stats_record.sql",
.check = "SHOW TABLES LIKE 'character_stats_record'",
.condition = "empty",
.match = "",
.sql = R"(
CREATE TABLE `character_stats_record` (
`character_id` int NOT NULL,
`name` varchar(100) NULL,
`status` int NULL DEFAULT 0,
`level` int NULL DEFAULT 0,
`class` int NULL DEFAULT 0,
`race` int NULL DEFAULT 0,
`aa_points` int NULL DEFAULT 0,
`hp` bigint NULL DEFAULT 0,
`mana` bigint NULL DEFAULT 0,
`endurance` bigint NULL DEFAULT 0,
`ac` int NULL DEFAULT 0,
`strength` int NULL DEFAULT 0,
`stamina` int NULL DEFAULT 0,
`dexterity` int NULL DEFAULT 0,
`agility` int NULL DEFAULT 0,
`intelligence` int NULL DEFAULT 0,
`wisdom` int NULL DEFAULT 0,
`charisma` int NULL DEFAULT 0,
`magic_resist` int NULL DEFAULT 0,
`fire_resist` int NULL DEFAULT 0,
`cold_resist` int NULL DEFAULT 0,
`poison_resist` int NULL DEFAULT 0,
`disease_resist` int NULL DEFAULT 0,
`corruption_resist` int NULL DEFAULT 0,
`heroic_strength` int NULL DEFAULT 0,
`heroic_stamina` int NULL DEFAULT 0,
`heroic_dexterity` int NULL DEFAULT 0,
`heroic_agility` int NULL DEFAULT 0,
`heroic_intelligence` int NULL DEFAULT 0,
`heroic_wisdom` int NULL DEFAULT 0,
`heroic_charisma` int NULL DEFAULT 0,
`heroic_magic_resist` int NULL DEFAULT 0,
`heroic_fire_resist` int NULL DEFAULT 0,
`heroic_cold_resist` int NULL DEFAULT 0,
`heroic_poison_resist` int NULL DEFAULT 0,
`heroic_disease_resist` int NULL DEFAULT 0,
`heroic_corruption_resist` int NULL DEFAULT 0,
`haste` int NULL DEFAULT 0,
`accuracy` int NULL DEFAULT 0,
`attack` int NULL DEFAULT 0,
`avoidance` int NULL DEFAULT 0,
`clairvoyance` int NULL DEFAULT 0,
`combat_effects` int NULL DEFAULT 0,
`damage_shield_mitigation` int NULL DEFAULT 0,
`damage_shield` int NULL DEFAULT 0,
`dot_shielding` int NULL DEFAULT 0,
`hp_regen` int NULL DEFAULT 0,
`mana_regen` int NULL DEFAULT 0,
`endurance_regen` int NULL DEFAULT 0,
`shielding` int NULL DEFAULT 0,
`spell_damage` int NULL DEFAULT 0,
`spell_shielding` int NULL DEFAULT 0,
`strikethrough` int NULL DEFAULT 0,
`stun_resist` int NULL DEFAULT 0,
`backstab` int NULL DEFAULT 0,
`wind` int NULL DEFAULT 0,
`brass` int NULL DEFAULT 0,
`string` int NULL DEFAULT 0,
`percussion` int NULL DEFAULT 0,
`singing` int NULL DEFAULT 0,
`baking` int NULL DEFAULT 0,
`alchemy` int NULL DEFAULT 0,
`tailoring` int NULL DEFAULT 0,
`blacksmithing` int NULL DEFAULT 0,
`fletching` int NULL DEFAULT 0,
`brewing` int NULL DEFAULT 0,
`jewelry` int NULL DEFAULT 0,
`pottery` int NULL DEFAULT 0,
`research` int NULL DEFAULT 0,
`alcohol` int NULL DEFAULT 0,
`fishing` int NULL DEFAULT 0,
`tinkering` int NULL DEFAULT 0,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`character_id`)
);
)"
},
ManifestEntry{
.version = 9236,
.description = "2023_08_24_aa_ability_auto_grant.sql",
.check = "SHOW COLUMNS FROM `aa_ability` LIKE 'auto_grant_enabled';",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `aa_ability` ADD COLUMN `auto_grant_enabled` TINYINT(4) NOT NULL DEFAULT '0' AFTER `reset_on_death`;
UPDATE `aa_ability` SET `auto_grant_enabled` = 1 WHERE `grant_only` = 0 AND `charges` = 0 AND `category` = -1;
)"
},
ManifestEntry{
.version = 9237,
.description = "2023_10_15_import_13th_floor.sql",
.check = "SHOW COLUMNS FROM `items` LIKE 'bardeffect';",
.condition = "contains",
.match = "mediumint",
.sql = R"(
ALTER TABLE `items`
MODIFY COLUMN `scriptfileid` MEDIUMINT(6) NOT NULL DEFAULT 0,
MODIFY COLUMN `powersourcecapacity` MEDIUMINT(7) NOT NULL DEFAULT 0,
MODIFY COLUMN `augdistiller` INT(11) UNSIGNED NOT NULL DEFAULT 0,
MODIFY COLUMN `scrollunk1` INT(11) UNSIGNED NOT NULL DEFAULT 0,
MODIFY COLUMN `bardeffect` MEDIUMINT(6) NOT NULL DEFAULT 0;
)"
},
ManifestEntry{
.version = 9238,
.description = "2023_10_18_tradeskill_add_learned_by_item_id.sql",
.check = "SHOW COLUMNS FROM `tradeskill_recipe` LIKE 'learned_by_item_id'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `tradeskill_recipe`
ADD COLUMN `learned_by_item_id` int(11) NOT NULL DEFAULT 0 AFTER `must_learn`;
)"
},
ManifestEntry{
.version = 9239,
.description = "2023_10_18_blocked_spells_expansions_content_flags.sql",
.check = "SHOW COLUMNS FROM `blocked_spells` LIKE 'min_expansion'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `blocked_spells`
ADD COLUMN `min_expansion` tinyint(4) NOT NULL DEFAULT -1 AFTER `description`,
ADD COLUMN `max_expansion` tinyint(4) NOT NULL DEFAULT -1 AFTER `min_expansion`,
ADD COLUMN `content_flags` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `max_expansion`,
ADD COLUMN `content_flags_disabled` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `content_flags`;
)"
},
ManifestEntry{
.version = 9240,
.description = "2023_10_29_variables_id.sql",
.check = "SHOW COLUMNS FROM `variables` LIKE 'id'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `variables`
ADD COLUMN `id` int(11) NOT NULL AUTO_INCREMENT FIRST,
DROP PRIMARY KEY,
ADD PRIMARY KEY (`id`) USING BTREE,
ADD UNIQUE INDEX(`varname`);
)"
},
ManifestEntry{
.version = 9241,
.description = "2023_10_29_split_spawn2_enabled.sql",
.check = "SHOW TABLES LIKE 'spawn2_disabled'",
.condition = "empty",
.match = "",
.sql = R"(
CREATE TABLE `spawn2_backup_2023_10_29` LIKE `spawn2`;
INSERT INTO `spawn2_backup_2023_10_29` SELECT * FROM `spawn2`;
CREATE TABLE `spawn2_disabled` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`spawn2_id` int(11) DEFAULT NULL,
`instance_id` int(11) DEFAULT 0,
`disabled` smallint(11) DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `spawn2_id` (`spawn2_id`,`instance_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
INSERT INTO spawn2_disabled (spawn2_id, disabled) SELECT id, 1 FROM spawn2 WHERE enabled = 0;
ALTER TABLE `spawn2` DROP COLUMN `enabled`;
)"
},
ManifestEntry{
.version = 9242,
.description = "2023_11_7_mintime_maxtime_spawnentry.sql",
.check = "SHOW COLUMNS FROM `spawnentry` LIKE 'min_time'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `spawnentry`
ADD COLUMN `min_time` smallint(4) NOT NULL DEFAULT 0 AFTER `condition_value_filter`,
ADD COLUMN `max_time` smallint(4) NOT NULL DEFAULT 0 AFTER `min_time`;
)"
},
ManifestEntry{
.version = 9243,
.description = "2023_11_27_starting_items_revamp.sql",
.check = "SHOW COLUMNS FROM `starting_items` LIKE 'race_list'",
.condition = "empty",
.match = "",
.sql = R"(
CREATE TABLE `starting_items_backup_9243` LIKE `starting_items`;
INSERT INTO `starting_items_backup_9243` SELECT * FROM `starting_items`;
CREATE TABLE `starting_items_new` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`race_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
`class_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
`deity_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
`zone_id_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
`item_id` int(11) UNSIGNED NOT NULL DEFAULT 0,
`item_charges` tinyint(3) UNSIGNED NOT NULL DEFAULT 1,
`gm` mediumint(3) UNSIGNED NOT NULL DEFAULT 0,
`slot` mediumint(9) NOT NULL DEFAULT -1,
`min_expansion` tinyint(4) NOT NULL DEFAULT -1,
`max_expansion` tinyint(4) NOT NULL DEFAULT -1,
`content_flags` varchar(100) NULL,
`content_flags_disabled` varchar(100) NULL,
PRIMARY KEY (`id`)
);
INSERT INTO
`starting_items_new`
(
SELECT
0 AS `id`,
GROUP_CONCAT(DISTINCT `class` ORDER BY class ASC SEPARATOR '|') AS `class_list`,
GROUP_CONCAT(DISTINCT `race` ORDER BY race ASC SEPARATOR '|') AS `race_list`,
GROUP_CONCAT(DISTINCT `deityid` ORDER BY deityid ASC SEPARATOR '|') AS `deity_list`,
GROUP_CONCAT(DISTINCT `zoneid` ORDER BY zoneid ASC SEPARATOR '|') AS `zone_list`,
`itemid`,
`item_charges`,
`gm`,
`slot`,
`min_expansion`,
`max_expansion`,
`content_flags`,
`content_flags_disabled`
FROM
`starting_items`
GROUP BY
`itemid`
);
DROP TABLE `starting_items`;
RENAME TABLE `starting_items_new` TO `starting_items`;
)"
},
ManifestEntry{
.version = 9244,
.description = "2023_11_30_items_table_schema.sql",
.check = "SHOW COLUMNS FROM `items` LIKE 'updated'",
.condition = "contains",
.match = "0000-00-00 00:00:00",
.sql = R"(
ALTER TABLE `items` MODIFY COLUMN `updated` datetime NULL DEFAULT NULL;
)"
},
ManifestEntry{
.version = 9245,
.description = "2023_12_03_object_incline.sql",
.check = "SHOW COLUMNS FROM `object` LIKE 'incline'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `object` CHANGE COLUMN `unknown08` `size_percentage` float NOT NULL DEFAULT 0 AFTER `icon`;
ALTER TABLE `object` CHANGE COLUMN `unknown10` `solid_type` mediumint(5) NOT NULL DEFAULT 0 AFTER `size`;
ALTER TABLE `object` CHANGE COLUMN `unknown20` `incline` int(11) NOT NULL DEFAULT 0 AFTER `solid_type`;
)"
},
ManifestEntry{
.version = 9246,
.description = "2023_12_07_keyring_id.sql",
.check = "SHOW COLUMNS FROM `keyring` LIKE 'id'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `keyring`
ADD COLUMN `id` int UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
ADD PRIMARY KEY (`id`);
)"
}
// -- template; copy/paste this when you need to create a new entry
// ManifestEntry{
@@ -61,6 +61,29 @@ DROP TABLE IF EXISTS `bot_group_members`;
SET FOREIGN_KEY_CHECKS = 1;
)",
},
ManifestEntry{
.version = 9040,
.description = "2023_11_16_bot_starting_items.sql",
.check = "SHOW TABLES LIKE 'bot_starting_items'",
.condition = "empty",
.match = "",
.sql = R"(
CREATE TABLE `bot_starting_items` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`races` int(11) UNSIGNED NOT NULL DEFAULT 0,
`classes` int(11) UNSIGNED NOT NULL DEFAULT 0,
`item_id` int(11) UNSIGNED NOT NULL DEFAULT 0,
`item_charges` tinyint(3) UNSIGNED NOT NULL DEFAULT 1,
`min_status` tinyint(3) UNSIGNED NOT NULL DEFAULT 0,
`slot_id` mediumint(9) NOT NULL DEFAULT -1,
`min_expansion` tinyint(4) NOT NULL DEFAULT -1,
`max_expansion` tinyint(4) NOT NULL DEFAULT -1,
`content_flags` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
`content_flags_disabled` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci;
)"
}
// -- template; copy/paste this when you need to create a new entry
// ManifestEntry{
// .version = 9228,
+92 -56
View File
@@ -29,6 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/repositories/raid_members_repository.h"
#include "../common/repositories/respawn_times_repository.h"
#include "../common/repositories/spawn_condition_values_repository.h"
#include "repositories/spawn2_disabled_repository.h"
#include "database.h"
@@ -49,6 +50,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include <sys/time.h>
#endif
bool Database::AddClientToInstance(uint16 instance_id, uint32 character_id)
{
auto e = InstanceListPlayerRepository::NewEntity();
@@ -131,85 +133,118 @@ bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version
bool Database::GetUnusedInstanceID(uint16 &instance_id)
{
uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances);
uint32 max = 32000;
uint32 max_instance_id = 32000;
// sanity check reserved
if (max_reserved_instance_id >= max_instance_id) {
instance_id = 0;
return false;
}
// recycle instances
if (RuleB(Instances, RecycleInstanceIds)) {
//query to get first unused id above reserved
auto query = fmt::format(
SQL(
SELECT id
FROM instance_list
WHERE id = {};
),
max_reserved_instance_id + 1
);
auto results = QueryDatabase(query);
// could not successfully query - bail out
if (!results.Success()) {
instance_id = 0;
return false;
}
// first id is available
if (results.RowCount() == 0) {
instance_id = max_reserved_instance_id + 1;
return true;
}
// now look for next available above reserved
query = fmt::format(
SQL(
SELECT MIN(i.id + 1) AS next_available
FROM instance_list i
LEFT JOIN instance_list i2 ON i.id + 1 = i2.id
WHERE i.id >= {}
AND i2.id IS NULL;
),
max_reserved_instance_id
);
results = QueryDatabase(query);
// could not successfully query - bail out
if (!results.Success()) {
instance_id = 0;
return false;
}
// did not retrieve any rows - bail out
if (results.RowCount() == 0) {
instance_id = 0;
return false;
}
auto row = results.begin();
// check that id is within limits
if (row[0] && Strings::ToInt(row[0]) <= max_instance_id) {
instance_id = Strings::ToInt(row[0]);
return true;
}
// no available instance ids
instance_id = 0;
return false;
}
// get max unused id above reserved
auto query = fmt::format(
"SELECT IFNULL(MAX(id), {}) + 1 FROM instance_list WHERE id > {}",
max_reserved_instance_id,
max_reserved_instance_id
);
if (RuleB(Instances, RecycleInstanceIds)) {
query = (
SQL(
SELECT i.id + 1 AS next_available
FROM instance_list i
LEFT JOIN instance_list i2 ON i2.id = i.id + 1
WHERE i2.id IS NULL
ORDER BY i.id
LIMIT 0, 1;
)
);
}
auto results = QueryDatabase(query);
// could not successfully query - bail out
if (!results.Success()) {
instance_id = 0;
return false;
}
// did not retrieve any rows - bail out
if (results.RowCount() == 0) {
instance_id = max_reserved_instance_id;
return true;
instance_id = 0;
return false;
}
auto row = results.begin();
if (Strings::ToInt(row[0]) <= max) {
// no instances currently used
if (!row[0]) {
instance_id = max_reserved_instance_id + 1;
return true;
}
// check that id is within limits
if (Strings::ToInt(row[0]) <= max_instance_id) {
instance_id = Strings::ToInt(row[0]);
return true;
}
if (instance_id < max_reserved_instance_id) {
instance_id = max_reserved_instance_id;
return true;
}
query = fmt::format("SELECT id FROM instance_list where id > {} ORDER BY id", max_reserved_instance_id);
results = QueryDatabase(query);
if (!results.Success()) {
instance_id = 0;
return false;
}
if (results.RowCount() == 0) {
instance_id = 0;
return false;
}
max_reserved_instance_id++;
for (auto row : results) {
if (max_reserved_instance_id < Strings::ToUnsignedInt(row[0])) {
instance_id = max_reserved_instance_id;
return true;
}
if (max_reserved_instance_id > max) {
instance_id = 0;
return false;
}
max_reserved_instance_id++;
}
instance_id = max_reserved_instance_id;
return true;
// no available instance ids
instance_id = 0;
return false;
}
bool Database::IsGlobalInstance(uint16 instance_id)
@@ -520,6 +555,7 @@ void Database::PurgeExpiredInstances()
CharacterCorpsesRepository::BuryInstances(*this, imploded_instance_ids);
DynamicZoneMembersRepository::DeleteByManyInstances(*this, imploded_instance_ids);
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
Spawn2DisabledRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
}
void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
+4
View File
@@ -66,6 +66,7 @@ namespace DatabaseSchema {
{"character_potionbelt", "id"},
{"character_skills", "id"},
{"character_spells", "id"},
{"character_stats_record", "character_id"},
{"character_task_timers", "character_id"},
{"character_tasks", "charid"},
{"character_tribute", "character_id"},
@@ -134,6 +135,7 @@ namespace DatabaseSchema {
"character_potionbelt",
"character_skills",
"character_spells",
"character_stats_record",
"character_task_timers",
"character_tasks",
"character_tribute",
@@ -258,6 +260,7 @@ namespace DatabaseSchema {
"chatchannels",
"chatchannel_reserved_names",
"command_settings",
"command_subsettings",
"content_flags",
"db_str",
"eqtime",
@@ -342,6 +345,7 @@ namespace DatabaseSchema {
"respawn_times",
"saylink",
"server_scheduled_events",
"spawn2_disabled",
"player_event_log_settings",
"player_event_logs",
"shared_task_activity_state",
+4
View File
@@ -62,6 +62,7 @@ N(OP_BeginCast),
N(OP_Bind_Wound),
N(OP_BlockedBuffs),
N(OP_BoardBoat),
N(OP_BookButton),
N(OP_Buff),
N(OP_BuffCreate),
N(OP_BuffRemoveRequest),
@@ -316,6 +317,7 @@ N(OP_LootRequest),
N(OP_ManaChange),
N(OP_ManaUpdate),
N(OP_MarkNPC),
N(OP_MarkRaidNPC),
N(OP_Marquee),
N(OP_MemorizeSpell),
N(OP_Mend),
@@ -398,6 +400,8 @@ N(OP_PVPLeaderBoardRequest),
N(OP_PVPStats),
N(OP_QueryResponseThing),
N(OP_QueryUCSServerStatus),
N(OP_RaidDelegateAbility),
N(OP_RaidClearNPCMarks),
N(OP_RaidInvite),
N(OP_RaidJoin),
N(OP_RaidUpdate),
+23
View File
@@ -1052,4 +1052,27 @@ enum ScribeSpellActions
Unmemorize
};
enum SpellTimeRestrictions
{
NoRestriction,
Day,
Night
};
enum MoneyTypes
{
Copper,
Silver,
Gold,
Platinum
};
enum MoneySubtypes
{
Personal,
Bank,
Cursor,
SharedBank // Platinum Only
};
#endif /*COMMON_EQ_CONSTANTS_H*/
+28 -10
View File
@@ -2559,7 +2559,10 @@ struct GMEmoteZone_Struct {
struct BookText_Struct {
uint8 window; // where to display the text (0xFF means new window)
uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly others.
uint32 invslot; // Only used in SoF and later clients.
int16 invslot; // Only used in SoF and later clients.
int32 target_id;
int8 can_cast;
int8 can_scribe;
char booktext[1]; // Variable Length
};
// This is the request to read a book.
@@ -2568,11 +2571,18 @@ struct BookText_Struct {
struct BookRequest_Struct {
uint8 window; // where to display the text (0xFF means new window)
uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly others.
uint32 invslot; // Only used in Sof and later clients;
int16 subslot; // The subslot inside of a bag if it is inside one.
int16 invslot; // Only used in Sof and later clients;
int32 target_id;
char txtfile[20];
};
// used by Scribe and CastSpell book buttons
struct BookButton_Struct
{
int16 invslot; // server slot
int32 target_id;
};
/*
** Object/Ground Spawn struct
** Used for Forges, Ovens, ground spawns, items dropped to ground, etc
@@ -2584,11 +2594,11 @@ struct BookRequest_Struct {
struct Object_Struct {
/*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list
/*08*/ float size; //
/*10*/ uint16 solidtype; //
/*10*/ uint16 solid_type; //
/*12*/ uint32 drop_id; // Unique object id for zone
/*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in
/*18*/ uint16 zone_instance; //
/*20*/ uint32 unknown020; //
/*20*/ uint32 incline; //
/*24*/ uint32 unknown024; //
/*28*/ float tilt_x;
/*32*/ float tilt_y;
@@ -4105,7 +4115,9 @@ struct UpdateLeadershipAA_Struct {
enum
{
GroupLeadershipAbility_MarkNPC = 0
GroupLeadershipAbility_MarkNPC = 0,
RaidLeadershipAbility_MarkNPC = 16,
RaidLeadershipAbility_MainAssist = 19
};
struct DoGroupLeadershipAbility_Struct
@@ -4149,8 +4161,9 @@ struct InspectBuffs_Struct {
struct RaidGeneral_Struct {
/*00*/ uint32 action; //=10
/*04*/ char player_name[64]; //should both be the player's name
/*64*/ char leader_name[64];
/*132*/ uint32 parameter;
/*68*/ uint32 unknown1;
/*72*/ char leader_name[64];
/*136*/ uint32 parameter;
};
struct RaidAddMember_Struct {
@@ -4161,9 +4174,14 @@ struct RaidAddMember_Struct {
/*139*/ uint8 flags[5]; //no idea if these are needed...
};
struct RaidNote_Struct {
/*000*/ RaidGeneral_Struct general;
/*140*/ char note[64];
};
struct RaidMOTD_Struct {
/*000*/ RaidGeneral_Struct general; // leader_name and action only used
/*136*/ char motd[0]; // max size is 1024, but reply is variable
/*000*/ RaidGeneral_Struct general;
/*140*/ char motd[1024];
};
struct RaidLeadershipUpdate_Struct {
+2
View File
@@ -100,6 +100,8 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
log_settings[Logs::Discord].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::QuestErrors].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::QuestErrors].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::EqTime].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::EqTime].log_to_gmsay = static_cast<uint8>(Logs::General);
/**
* RFC 5424
+6
View File
@@ -137,6 +137,9 @@ namespace Logs {
Bugs,
QuestErrors,
PlayerEvents,
DataBuckets,
Zoning,
EqTime,
MaxCategoryID /* Don't Remove this */
};
@@ -233,6 +236,9 @@ namespace Logs {
"Bugs",
"QuestErrors",
"PlayerEvents",
"DataBuckets",
"Zoning",
"EqTime",
};
}
+30
View File
@@ -794,6 +794,36 @@
OutF(LogSys, Logs::Detail, Logs::PlayerEvents, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogDataBuckets(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::DataBuckets))\
OutF(LogSys, Logs::General, Logs::DataBuckets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogDataBucketsDetail(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::DataBuckets))\
OutF(LogSys, Logs::Detail, Logs::DataBuckets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogZoning(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::Zoning))\
OutF(LogSys, Logs::General, Logs::Zoning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogZoningDetail(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::Zoning))\
OutF(LogSys, Logs::Detail, Logs::Zoning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogEqTime(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::EqTime))\
OutF(LogSys, Logs::General, Logs::EqTime, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogEqTimeDetail(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::EqTime))\
OutF(LogSys, Logs::Detail, Logs::EqTime, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define Log(debug_level, log_category, message, ...) do {\
if (LogSys.IsLogEnabled(debug_level, log_category))\
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
+51 -7
View File
@@ -46,16 +46,16 @@ EQTime::EQTime()
timezone = 0;
memset(&eqTime, 0, sizeof(eqTime));
//Defaults for time
TimeOfDay_Struct start;
start.day = 1;
start.hour = 9;
start.minute = 0;
start.month = 1;
start.year = 3100;
TimeOfDay_Struct t{};
t.day = 1;
t.hour = 9;
t.minute = 0;
t.month = 1;
t.year = 3100;
//Set default time zone
timezone = 0;
//Start EQTimer
SetCurrentEQTimeOfDay(start, time(0));
SetCurrentEQTimeOfDay(t, time(nullptr));
}
//getEQTimeOfDay - Reads timeConvert and writes the result to eqTimeOfDay
@@ -200,3 +200,47 @@ void EQTime::ToString(TimeOfDay_Struct *t, std::string &str) {
buf[127] = '\0';
str = buf;
}
bool EQTime::IsDayTime() {
TimeOfDay_Struct tod{}; //Day time is 5am to 6:59pm (14 hours in-game)
GetCurrentEQTimeOfDay(&tod); //TODO: what if it fails and returns zero?
if (tod.hour >= 5 || tod.hour < 19) {
return true;
}
return false;
}
bool EQTime::IsNightTime() {
TimeOfDay_Struct tod{}; //Night time is 7pm to 4:59am (10 hours in-game)
GetCurrentEQTimeOfDay(&tod); //TODO: what if it fails and returns zero?
if (tod.hour >= 19 || tod.hour < 5) {
return true;
}
return false;
}
bool EQTime::IsInbetweenTime(uint8 min_time, uint8 max_time) {
TimeOfDay_Struct tod{};
GetCurrentEQTimeOfDay(&tod);
if (min_time == 0 || max_time == 0 || min_time > 24 || max_time > 24) {
return true;
}
if (max_time < min_time) {
if ((tod.hour >= min_time && tod.hour > max_time) || (tod.hour < min_time && tod.hour <= max_time)) {
return true;
}
}
else {
if (tod.hour >= min_time && tod.hour <= max_time) {
return true;
}
}
return false;
}
+3
View File
@@ -28,6 +28,9 @@ public:
uint32 getEQTimeZone() { return timezone; }
uint32 getEQTimeZoneHr() { return timezone/60; }
uint32 getEQTimeZoneMin() { return timezone%60; }
bool IsDayTime();
bool IsNightTime();
bool IsInbetweenTime(uint8 min_time, uint8 max_time);
//Set functions
int SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real);
-35
View File
@@ -238,41 +238,6 @@ enum { //some random constants
// Timer to update aggrometer
#define AGGRO_METER_UPDATE_MS 1000
//Some hard coded statuses from commands and other places:
enum {
minStatusToBeGM = 40,
minStatusToUseGMCommands = 80,
minStatusToKick = 150,
minStatusToAvoidFalling = 100,
minStatusToHaveInvalidSpells = 80,
minStatusToHaveInvalidSkills = 80,
minStatusToIgnoreZoneFlags = 80,
minStatusToSeeOthersZoneFlags = 80,
minStatusToEditOtherGuilds = 80,
commandMovecharSelfOnly = 80, //below this == only self move allowed
commandMovecharToSpecials = 200, //ability to send people to cshom/load zones
commandZoneToSpecials = 80, //zone to cshome, out of load zones
commandToggleAI = 250, //can turn NPC AI on and off
commandCastSpecials = 100, //can cast special spells
commandInstacast = 100, //insta-cast all #casted spells
commandLevelAboveCap = 100, //can #level players above level cap
commandLevelNPCAboveCap = 100, //can #level NPCs above level cap
commandSetSkillsOther = 100, //ability to setskills on others
commandRaceOthers = 100, //ability to #race on others
commandGenderOthers = 100, //ability to #gender on others
commandTextureOthers = 100, //ability to #texture on others
commandDoAnimOthers = 100, //can #doanim on others
commandLockZones = 101, //can lock or unlock zones
commandEditPlayerCorpses = 150, //can Edit Player Corpses
commandChangeFlags = 200, //ability to set/refresh flags
commandBanPlayers = 100, //can set bans on players
commandChangeDatarate = 201, //edit client's data rate
commandZoneToCoords = 0, //can #zone with coords
commandInterrogateInv = 100, //below this == only log on error state and self-only target dump
commandInvSnapshot = 150 //ability to clear/restore snapshots
};
// This is the item ID we use for say links, we use the max that fits in 5 ASCII chars
#define SAYLINK_ITEM_ID 0xFFFFF
+8 -2
View File
@@ -55,8 +55,14 @@ bool File::Exists(const std::string &name)
*/
void File::Makedir(const std::string &directory_name)
{
fs::create_directory(directory_name);
fs::permissions(directory_name, fs::perms::owner_all);
try {
fs::create_directory(directory_name);
fs::permissions(directory_name, fs::perms::owner_all);
}
catch (const fs::filesystem_error &ex) {
std::cout << "Failed to create directory: " << directory_name << std::endl;
std::cout << ex.what() << std::endl;
}
}
std::string File::FindEqemuConfigPath()
+4
View File
@@ -230,6 +230,10 @@ bool EQ::ItemData::IsTypeShield() const
return (ItemType == item::ItemTypeShield);
}
bool EQ::ItemData::IsQuestItem() const {
return QuestItemFlag;
}
bool EQ::ItemData::CheckLoreConflict(const ItemData* l_item, const ItemData* r_item)
{
if (!l_item || !r_item)
+2
View File
@@ -356,6 +356,7 @@ namespace EQ
struct ItemData {
// Non packet based fields
uint8 MinStatus {};
char Comment[255] {};
// Packet based fields
uint8 ItemClass {}; // Item Type: 0=common, 1=container, 2=book
@@ -546,6 +547,7 @@ namespace EQ
bool IsType1HWeapon() const;
bool IsType2HWeapon() const;
bool IsTypeShield() const;
bool IsQuestItem() const;
static bool CheckLoreConflict(const ItemData* l_item, const ItemData* r_item);
bool CheckLoreConflict(const ItemData* item) const { return CheckLoreConflict(this, item); }
+5 -3
View File
@@ -720,12 +720,14 @@ EQ::ItemInstance* EQ::ItemInstance::RemoveAugment(uint8 index)
bool EQ::ItemInstance::IsAugmented()
{
if (!m_item || !m_item->IsClassCommon())
if (!m_item || !m_item->IsClassCommon()) {
return false;
}
for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) {
if (GetAugmentItemID(index))
for (uint8 slot_id = invaug::SOCKET_BEGIN; slot_id <= invaug::SOCKET_END; ++slot_id) {
if (GetAugmentItemID(slot_id)) {
return true;
}
}
return false;
+24640
View File
File diff suppressed because it is too large Load Diff
+135 -88
View File
@@ -34,6 +34,7 @@
#include "../rulesys.h"
#include "../path_manager.h"
#include "../races.h"
#include "../raid.h"
#include <iostream>
#include <sstream>
@@ -2608,88 +2609,124 @@ namespace RoF
ENCODE(OP_RaidJoin)
{
EQApplicationPacket *inapp = *p;
unsigned char * __emu_buffer = inapp->pBuffer;
RaidCreate_Struct *raid_create = (RaidCreate_Struct*)__emu_buffer;
EQApplicationPacket* inapp = *p;
*p = nullptr;
unsigned char* __emu_buffer = inapp->pBuffer;
RaidCreate_Struct* emu = (RaidCreate_Struct*)__emu_buffer;
auto outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
structs::RaidGeneral_Struct *general = (structs::RaidGeneral_Struct*)outapp_create->pBuffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
structs::RaidGeneral_Struct* general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
general->action = 8;
general->parameter = 1;
strn0cpy(general->leader_name, raid_create->leader_name, 64);
strn0cpy(general->player_name, raid_create->leader_name, 64);
general->action = raidCreate;
general->parameter = RaidCommandAcceptInvite;
strn0cpy(general->leader_name, emu->leader_name, sizeof(emu->leader_name));
strn0cpy(general->player_name, emu->leader_name, sizeof(emu->leader_name));
dest->FastQueuePacket(&outapp);
dest->FastQueuePacket(&outapp_create);
safe_delete(inapp);
}
ENCODE(OP_RaidUpdate)
{
EQApplicationPacket *inapp = *p;
EQApplicationPacket* inapp = *p;
*p = nullptr;
unsigned char * __emu_buffer = inapp->pBuffer;
RaidGeneral_Struct *raid_gen = (RaidGeneral_Struct*)__emu_buffer;
unsigned char* __emu_buffer = inapp->pBuffer;
RaidGeneral_Struct* raid_gen = (RaidGeneral_Struct*)__emu_buffer;
if (raid_gen->action == 0) // raid add has longer length than other raid updates
switch (raid_gen->action)
{
RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer;
case raidAdd:
{
RaidAddMember_Struct* emu = (RaidAddMember_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct));
structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer;
structs::RaidAddMember_Struct* eq = (structs::RaidAddMember_Struct*)outapp->pBuffer;
add_member->raidGen.action = in_add_member->raidGen.action;
add_member->raidGen.parameter = in_add_member->raidGen.parameter;
strn0cpy(add_member->raidGen.leader_name, in_add_member->raidGen.leader_name, 64);
strn0cpy(add_member->raidGen.player_name, in_add_member->raidGen.player_name, 64);
add_member->_class = in_add_member->_class;
add_member->level = in_add_member->level;
add_member->isGroupLeader = in_add_member->isGroupLeader;
add_member->flags[0] = in_add_member->flags[0];
add_member->flags[1] = in_add_member->flags[1];
add_member->flags[2] = in_add_member->flags[2];
add_member->flags[3] = in_add_member->flags[3];
add_member->flags[4] = in_add_member->flags[4];
dest->FastQueuePacket(&outapp);
}
else if (raid_gen->action == 35)
{
RaidMOTD_Struct *inmotd = (RaidMOTD_Struct *)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) +
strlen(inmotd->motd) + 1);
structs::RaidMOTD_Struct *outmotd = (structs::RaidMOTD_Struct *)outapp->pBuffer;
OUT(raidGen.action);
OUT(raidGen.parameter);
OUT_str(raidGen.leader_name);
OUT_str(raidGen.player_name);
OUT(_class);
OUT(level);
OUT(isGroupLeader);
OUT(flags[0]);
OUT(flags[1]);
OUT(flags[2]);
OUT(flags[3]);
OUT(flags[4]);
outmotd->general.action = inmotd->general.action;
strn0cpy(outmotd->general.player_name, inmotd->general.player_name, 64);
strn0cpy(outmotd->motd, inmotd->motd, strlen(inmotd->motd) + 1);
dest->FastQueuePacket(&outapp);
break;
}
else if (raid_gen->action == 14 || raid_gen->action == 30)
case raidSetMotd:
{
RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer;
auto outapp =
new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer;
RaidMOTD_Struct* emu = (RaidMOTD_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct));
structs::RaidMOTD_Struct* eq = (structs::RaidMOTD_Struct*)outapp->pBuffer;
OUT(general.action);
OUT_str(general.player_name);
OUT_str(general.leader_name);
OUT_str(motd);
outlaa->action = inlaa->action;
strn0cpy(outlaa->player_name, inlaa->player_name, 64);
strn0cpy(outlaa->leader_name, inlaa->leader_name, 64);
memcpy(&outlaa->raid, &inlaa->raid, sizeof(RaidLeadershipAA_Struct));
dest->FastQueuePacket(&outapp);
break;
}
else
case raidSetLeaderAbilities:
case raidMakeLeader:
{
RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer;
RaidLeadershipUpdate_Struct* emu = (RaidLeadershipUpdate_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
structs::RaidLeadershipUpdate_Struct* eq = (structs::RaidLeadershipUpdate_Struct*)outapp->pBuffer;
OUT(action);
OUT_str(player_name);
OUT_str(leader_name);
memcpy(&eq->raid, &emu->raid, sizeof(RaidLeadershipAA_Struct));
dest->FastQueuePacket(&outapp);
break;
}
case raidSetNote:
{
auto emu = (RaidNote_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidNote_Struct));
auto eq = (structs::RaidNote_Struct*)outapp->pBuffer;
OUT(general.action);
OUT_str(general.leader_name);
OUT_str(general.player_name);
OUT_str(note);
dest->FastQueuePacket(&outapp);
break;
}
case raidNoRaid:
{
dest->QueuePacket(inapp);
break;
}
default:
{
RaidGeneral_Struct* emu = (RaidGeneral_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
structs::RaidGeneral_Struct *raid_general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
strn0cpy(raid_general->leader_name, in_raid_general->leader_name, 64);
strn0cpy(raid_general->player_name, in_raid_general->player_name, 64);
raid_general->action = in_raid_general->action;
raid_general->parameter = in_raid_general->parameter;
dest->FastQueuePacket(&outapp);
}
structs::RaidGeneral_Struct* eq = (structs::RaidGeneral_Struct*)outapp->pBuffer;
OUT(action);
OUT(parameter);
OUT_str(leader_name);
OUT_str(player_name);
dest->FastQueuePacket(&outapp);
break;
}
}
safe_delete(inapp);
}
@@ -4861,37 +4898,47 @@ namespace RoF
{
DECODE_LENGTH_ATLEAST(structs::RaidGeneral_Struct);
// This is a switch on the RaidGeneral action
switch (*(uint32 *)__packet->pBuffer) {
case 35: { // raidMOTD
// we don't have a nice macro for this
structs::RaidMOTD_Struct *__eq_buffer = (structs::RaidMOTD_Struct *)__packet->pBuffer;
__eq_buffer->motd[1023] = '\0';
size_t motd_size = strlen(__eq_buffer->motd) + 1;
__packet->size = sizeof(RaidMOTD_Struct) + motd_size;
__packet->pBuffer = new unsigned char[__packet->size];
RaidMOTD_Struct *emu = (RaidMOTD_Struct *)__packet->pBuffer;
structs::RaidMOTD_Struct *eq = (structs::RaidMOTD_Struct *)__eq_buffer;
strn0cpy(emu->general.player_name, eq->general.player_name, 64);
strn0cpy(emu->motd, eq->motd, motd_size);
IN(general.action);
IN(general.parameter);
FINISH_DIRECT_DECODE();
break;
}
case 36: { // raidPlayerNote unhandled
break;
}
default: {
DECODE_LENGTH_EXACT(structs::RaidGeneral_Struct);
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
strn0cpy(emu->leader_name, eq->leader_name, 64);
strn0cpy(emu->player_name, eq->player_name, 64);
IN(action);
IN(parameter);
FINISH_DIRECT_DECODE();
break;
}
RaidGeneral_Struct* rgs = (RaidGeneral_Struct*)__packet->pBuffer;
switch (rgs->action)
{
case raidSetMotd:
{
SETUP_VAR_DECODE(RaidMOTD_Struct, structs::RaidMOTD_Struct, motd);
IN(general.action);
IN(general.parameter);
IN_str(general.leader_name);
IN_str(general.player_name);
IN_str(motd);
FINISH_VAR_DECODE();
break;
}
case raidSetNote:
{
SETUP_VAR_DECODE(RaidNote_Struct, structs::RaidNote_Struct, note);
IN(general.action);
IN(general.parameter);
IN_str(general.leader_name);
IN_str(general.player_name);
IN_str(note);
FINISH_VAR_DECODE();
break;
}
default:
{
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
IN(action);
IN(parameter);
IN_str(leader_name);
IN_str(player_name);
FINISH_DIRECT_DECODE();
break;
}
}
}
+152 -91
View File
@@ -35,6 +35,7 @@
#include "../path_manager.h"
#include "../classes.h"
#include "../races.h"
#include "../raid.h"
#include <iostream>
#include <sstream>
@@ -2677,88 +2678,124 @@ namespace RoF2
ENCODE(OP_RaidJoin)
{
EQApplicationPacket *inapp = *p;
unsigned char * __emu_buffer = inapp->pBuffer;
RaidCreate_Struct *raid_create = (RaidCreate_Struct*)__emu_buffer;
EQApplicationPacket* inapp = *p;
*p = nullptr;
unsigned char* __emu_buffer = inapp->pBuffer;
RaidCreate_Struct* emu = (RaidCreate_Struct*)__emu_buffer;
auto outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
structs::RaidGeneral_Struct *general = (structs::RaidGeneral_Struct*)outapp_create->pBuffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
structs::RaidGeneral_Struct* general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
general->action = 8;
general->parameter = 1;
strn0cpy(general->leader_name, raid_create->leader_name, 64);
strn0cpy(general->player_name, raid_create->leader_name, 64);
general->action = raidCreate;
general->parameter = RaidCommandAcceptInvite;
strn0cpy(general->leader_name, emu->leader_name, sizeof(emu->leader_name));
strn0cpy(general->player_name, emu->leader_name, sizeof(emu->leader_name));
dest->FastQueuePacket(&outapp);
dest->FastQueuePacket(&outapp_create);
safe_delete(inapp);
}
ENCODE(OP_RaidUpdate)
{
EQApplicationPacket *inapp = *p;
EQApplicationPacket* inapp = *p;
*p = nullptr;
unsigned char * __emu_buffer = inapp->pBuffer;
RaidGeneral_Struct *raid_gen = (RaidGeneral_Struct*)__emu_buffer;
unsigned char* __emu_buffer = inapp->pBuffer;
RaidGeneral_Struct* raid_gen = (RaidGeneral_Struct*)__emu_buffer;
if (raid_gen->action == 0) // raid add has longer length than other raid updates
switch (raid_gen->action)
{
RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer;
case raidAdd:
{
RaidAddMember_Struct* emu = (RaidAddMember_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct));
structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer;
structs::RaidAddMember_Struct* eq = (structs::RaidAddMember_Struct*)outapp->pBuffer;
add_member->raidGen.action = in_add_member->raidGen.action;
add_member->raidGen.parameter = in_add_member->raidGen.parameter;
strn0cpy(add_member->raidGen.leader_name, in_add_member->raidGen.leader_name, 64);
strn0cpy(add_member->raidGen.player_name, in_add_member->raidGen.player_name, 64);
add_member->_class = in_add_member->_class;
add_member->level = in_add_member->level;
add_member->isGroupLeader = in_add_member->isGroupLeader;
add_member->flags[0] = in_add_member->flags[0];
add_member->flags[1] = in_add_member->flags[1];
add_member->flags[2] = in_add_member->flags[2];
add_member->flags[3] = in_add_member->flags[3];
add_member->flags[4] = in_add_member->flags[4];
dest->FastQueuePacket(&outapp);
}
else if (raid_gen->action == 35)
{
RaidMOTD_Struct *inmotd = (RaidMOTD_Struct *)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) +
strlen(inmotd->motd) + 1);
structs::RaidMOTD_Struct *outmotd = (structs::RaidMOTD_Struct *)outapp->pBuffer;
OUT(raidGen.action);
OUT(raidGen.parameter);
OUT_str(raidGen.leader_name);
OUT_str(raidGen.player_name);
OUT(_class);
OUT(level);
OUT(isGroupLeader);
OUT(flags[0]);
OUT(flags[1]);
OUT(flags[2]);
OUT(flags[3]);
OUT(flags[4]);
outmotd->general.action = inmotd->general.action;
strn0cpy(outmotd->general.player_name, inmotd->general.player_name, 64);
strn0cpy(outmotd->motd, inmotd->motd, strlen(inmotd->motd) + 1);
dest->FastQueuePacket(&outapp);
break;
}
else if (raid_gen->action == 14 || raid_gen->action == 30)
case raidSetMotd:
{
RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer;
auto outapp =
new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer;
RaidMOTD_Struct* emu = (RaidMOTD_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct));
structs::RaidMOTD_Struct* eq = (structs::RaidMOTD_Struct*)outapp->pBuffer;
OUT(general.action);
OUT_str(general.player_name);
OUT_str(general.leader_name);
OUT_str(motd);
outlaa->action = inlaa->action;
strn0cpy(outlaa->player_name, inlaa->player_name, 64);
strn0cpy(outlaa->leader_name, inlaa->leader_name, 64);
memcpy(&outlaa->raid, &inlaa->raid, sizeof(RaidLeadershipAA_Struct));
dest->FastQueuePacket(&outapp);
break;
}
else
case raidSetLeaderAbilities:
case raidMakeLeader:
{
RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer;
RaidLeadershipUpdate_Struct* emu = (RaidLeadershipUpdate_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
structs::RaidLeadershipUpdate_Struct* eq = (structs::RaidLeadershipUpdate_Struct*)outapp->pBuffer;
OUT(action);
OUT_str(player_name);
OUT_str(leader_name);
memcpy(&eq->raid, &emu->raid, sizeof(RaidLeadershipAA_Struct));
dest->FastQueuePacket(&outapp);
break;
}
case raidSetNote:
{
auto emu = (RaidNote_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidNote_Struct));
auto eq = (structs::RaidNote_Struct*)outapp->pBuffer;
OUT(general.action);
OUT_str(general.leader_name);
OUT_str(general.player_name);
OUT_str(note);
dest->FastQueuePacket(&outapp);
break;
}
case raidNoRaid:
{
dest->QueuePacket(inapp);
break;
}
default:
{
RaidGeneral_Struct* emu = (RaidGeneral_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
structs::RaidGeneral_Struct *raid_general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
strn0cpy(raid_general->leader_name, in_raid_general->leader_name, 64);
strn0cpy(raid_general->player_name, in_raid_general->player_name, 64);
raid_general->action = in_raid_general->action;
raid_general->parameter = in_raid_general->parameter;
dest->FastQueuePacket(&outapp);
}
structs::RaidGeneral_Struct* eq = (structs::RaidGeneral_Struct*)outapp->pBuffer;
OUT(action);
OUT(parameter);
OUT_str(leader_name);
OUT_str(player_name);
dest->FastQueuePacket(&outapp);
break;
}
}
safe_delete(inapp);
}
@@ -2772,7 +2809,10 @@ namespace RoF2
else
eq->window = emu->window;
OUT(type);
OUT(invslot);
eq->invslot = ServerToRoF2TypelessSlot(emu->invslot, invtype::typePossessions);
OUT(target_id);
OUT(can_cast);
OUT(can_scribe);
strn0cpy(eq->txtfile, emu->booktext, sizeof(eq->txtfile));
FINISH_ENCODE();
@@ -4398,6 +4438,17 @@ namespace RoF2
FINISH_DIRECT_DECODE();
}
DECODE(OP_BookButton)
{
DECODE_LENGTH_EXACT(structs::BookButton_Struct);
SETUP_DIRECT_DECODE(BookButton_Struct, structs::BookButton_Struct);
emu->invslot = static_cast<int16_t>(RoF2ToServerTypelessSlot(eq->slot, invtype::typePossessions));
IN(target_id);
FINISH_DIRECT_DECODE();
}
DECODE(OP_Buff)
{
DECODE_LENGTH_EXACT(structs::SpellBuffPacket_Struct);
@@ -5064,37 +5115,47 @@ namespace RoF2
{
DECODE_LENGTH_ATLEAST(structs::RaidGeneral_Struct);
// This is a switch on the RaidGeneral action
switch (*(uint32 *)__packet->pBuffer) {
case 35: { // raidMOTD
// we don't have a nice macro for this
structs::RaidMOTD_Struct *__eq_buffer = (structs::RaidMOTD_Struct *)__packet->pBuffer;
__eq_buffer->motd[1023] = '\0';
size_t motd_size = strlen(__eq_buffer->motd) + 1;
__packet->size = sizeof(RaidMOTD_Struct) + motd_size;
__packet->pBuffer = new unsigned char[__packet->size];
RaidMOTD_Struct *emu = (RaidMOTD_Struct *)__packet->pBuffer;
structs::RaidMOTD_Struct *eq = (structs::RaidMOTD_Struct *)__eq_buffer;
strn0cpy(emu->general.player_name, eq->general.player_name, 64);
strn0cpy(emu->motd, eq->motd, motd_size);
IN(general.action);
IN(general.parameter);
FINISH_DIRECT_DECODE();
break;
}
case 36: { // raidPlayerNote unhandled
break;
}
default: {
DECODE_LENGTH_EXACT(structs::RaidGeneral_Struct);
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
strn0cpy(emu->leader_name, eq->leader_name, 64);
strn0cpy(emu->player_name, eq->player_name, 64);
IN(action);
IN(parameter);
FINISH_DIRECT_DECODE();
break;
}
RaidGeneral_Struct* rgs = (RaidGeneral_Struct*)__packet->pBuffer;
switch (rgs->action)
{
case raidSetMotd:
{
SETUP_VAR_DECODE(RaidMOTD_Struct, structs::RaidMOTD_Struct, motd);
IN(general.action);
IN(general.parameter);
IN_str(general.leader_name);
IN_str(general.player_name);
IN_str(motd);
FINISH_VAR_DECODE();
break;
}
case raidSetNote:
{
SETUP_VAR_DECODE(RaidNote_Struct, structs::RaidNote_Struct, note);
IN(general.action);
IN(general.parameter);
IN_str(general.leader_name);
IN_str(general.player_name);
IN_str(note);
FINISH_VAR_DECODE();
break;
}
default:
{
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
IN(action);
IN(parameter);
IN_str(leader_name);
IN_str(player_name);
FINISH_DIRECT_DECODE();
break;
}
}
}
@@ -5104,8 +5165,8 @@ namespace RoF2
SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct);
IN(type);
IN(invslot);
IN(subslot);
emu->invslot = static_cast<int16_t>(RoF2ToServerTypelessSlot(eq->invslot, invtype::typePossessions));
IN(target_id);
emu->window = (uint8)eq->window;
strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile));
+1
View File
@@ -150,6 +150,7 @@ D(OP_AugmentInfo)
D(OP_AugmentItem)
D(OP_BazaarSearch)
D(OP_BlockedBuffs)
D(OP_BookButton)
D(OP_Buff)
D(OP_BuffRemoveRequest)
D(OP_CastSpell)
+24 -11
View File
@@ -2868,15 +2868,23 @@ struct BookText_Struct {
// This is just a "text file" on the server
// or in our case, the 'name' column in our books table.
struct BookRequest_Struct {
/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window).
/*0004*/ uint16 invslot; // Is the slot, but the RoF2 conversion causes it to fail. Turned to 0 since it isnt required anyway.
/*0006*/ int16 subslot; // Inventory sub-slot (0-x)
/*0008*/ uint16 unknown006; // Seen FFFF
/*0010*/ uint16 unknown008; // seen 0000
/*0012*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others
/*0016*/ uint32 unknown0012;
/*0020*/ uint16 unknown0016;
/*0022*/ char txtfile[8194];
/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window).
/*0004*/ TypelessInventorySlot_Struct invslot; // book ItemIndex (with int16_t alignment padding)
/*0012*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others
/*0016*/ uint32 target_id; // client's target when using the book
/*0020*/ uint8 can_cast; // show Cast Spell button in book window
/*0021*/ uint8 can_scribe; // show Scribe button in book window
/*0022*/ char txtfile[8194];
/*8216*/
};
// used by Scribe and CastSpell book buttons
struct BookButton_Struct
{
/*0000*/ TypelessInventorySlot_Struct slot; // book ItemIndex (with int16_t alignment padding)
/*0008*/ int32 target_id; // client's target when using the book button
/*0012*/ int32 unused; // always 0 from button packets
/*0016*/
};
/*
@@ -4190,9 +4198,14 @@ struct RaidAddMember_Struct {
/*139*/ uint8 flags[5]; //no idea if these are needed...
};
struct RaidNote_Struct {
/*000*/ RaidGeneral_Struct general;
/*140*/ char note[64];
};
struct RaidMOTD_Struct {
/*000*/ RaidGeneral_Struct general; // leader_name and action only used
/*140*/ char motd[0]; // max size 1024, but reply is variable
/*000*/ RaidGeneral_Struct general;
/*140*/ char motd[1024];
};
struct RaidLeadershipUpdate_Struct {
+6 -1
View File
@@ -4136,9 +4136,14 @@ struct RaidAddMember_Struct {
/*139*/ uint8 flags[5]; //no idea if these are needed...
};
struct RaidNote_Struct {
/*000*/ RaidGeneral_Struct general;
/*140*/ char note[64];
};
struct RaidMOTD_Struct {
/*000*/ RaidGeneral_Struct general; // leader_name and action only used
/*140*/ char motd[0]; // max size 1024, but reply is variable
/*140*/ char motd[1024]; // max size is 1024, but reply is variable
};
struct RaidLeadershipUpdate_Struct {
+151 -89
View File
@@ -34,6 +34,7 @@
#include "../rulesys.h"
#include "../path_manager.h"
#include "../races.h"
#include "../raid.h"
#include <iostream>
#include <sstream>
@@ -1686,88 +1687,124 @@ namespace SoD
ENCODE(OP_RaidJoin)
{
EQApplicationPacket *inapp = *p;
unsigned char * __emu_buffer = inapp->pBuffer;
RaidCreate_Struct *raid_create = (RaidCreate_Struct*)__emu_buffer;
EQApplicationPacket* inapp = *p;
*p = nullptr;
unsigned char* __emu_buffer = inapp->pBuffer;
RaidCreate_Struct* emu = (RaidCreate_Struct*)__emu_buffer;
auto outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
structs::RaidGeneral_Struct *general = (structs::RaidGeneral_Struct*)outapp_create->pBuffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
structs::RaidGeneral_Struct* general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
general->action = 8;
general->parameter = 1;
strn0cpy(general->leader_name, raid_create->leader_name, 64);
strn0cpy(general->player_name, raid_create->leader_name, 64);
general->action = raidCreate;
general->parameter = RaidCommandAcceptInvite;
strn0cpy(general->leader_name, emu->leader_name, sizeof(emu->leader_name));
strn0cpy(general->player_name, emu->leader_name, sizeof(emu->leader_name));
dest->FastQueuePacket(&outapp);
dest->FastQueuePacket(&outapp_create);
safe_delete(inapp);
}
ENCODE(OP_RaidUpdate)
{
EQApplicationPacket *inapp = *p;
EQApplicationPacket* inapp = *p;
*p = nullptr;
unsigned char * __emu_buffer = inapp->pBuffer;
RaidGeneral_Struct *raid_gen = (RaidGeneral_Struct*)__emu_buffer;
unsigned char* __emu_buffer = inapp->pBuffer;
RaidGeneral_Struct* raid_gen = (RaidGeneral_Struct*)__emu_buffer;
if (raid_gen->action == 0) // raid add has longer length than other raid updates
switch (raid_gen->action)
{
RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer;
case raidAdd:
{
RaidAddMember_Struct* emu = (RaidAddMember_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct));
structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer;
structs::RaidAddMember_Struct* eq = (structs::RaidAddMember_Struct*)outapp->pBuffer;
add_member->raidGen.action = in_add_member->raidGen.action;
add_member->raidGen.parameter = in_add_member->raidGen.parameter;
strn0cpy(add_member->raidGen.leader_name, in_add_member->raidGen.leader_name, 64);
strn0cpy(add_member->raidGen.player_name, in_add_member->raidGen.player_name, 64);
add_member->_class = in_add_member->_class;
add_member->level = in_add_member->level;
add_member->isGroupLeader = in_add_member->isGroupLeader;
add_member->flags[0] = in_add_member->flags[0];
add_member->flags[1] = in_add_member->flags[1];
add_member->flags[2] = in_add_member->flags[2];
add_member->flags[3] = in_add_member->flags[3];
add_member->flags[4] = in_add_member->flags[4];
dest->FastQueuePacket(&outapp);
}
else if (raid_gen->action == 35)
{
RaidMOTD_Struct *inmotd = (RaidMOTD_Struct *)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) +
strlen(inmotd->motd) + 1);
structs::RaidMOTD_Struct *outmotd = (structs::RaidMOTD_Struct *)outapp->pBuffer;
OUT(raidGen.action);
OUT(raidGen.parameter);
OUT_str(raidGen.leader_name);
OUT_str(raidGen.player_name);
OUT(_class);
OUT(level);
OUT(isGroupLeader);
OUT(flags[0]);
OUT(flags[1]);
OUT(flags[2]);
OUT(flags[3]);
OUT(flags[4]);
outmotd->general.action = inmotd->general.action;
strn0cpy(outmotd->general.player_name, inmotd->general.player_name, 64);
strn0cpy(outmotd->motd, inmotd->motd, strlen(inmotd->motd) + 1);
dest->FastQueuePacket(&outapp);
break;
}
else if (raid_gen->action == 14 || raid_gen->action == 30)
case raidSetMotd:
{
RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer;
auto outapp =
new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer;
RaidMOTD_Struct* emu = (RaidMOTD_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct));
structs::RaidMOTD_Struct* eq = (structs::RaidMOTD_Struct*)outapp->pBuffer;
OUT(general.action);
OUT_str(general.player_name);
OUT_str(general.leader_name);
OUT_str(motd);
outlaa->action = inlaa->action;
strn0cpy(outlaa->player_name, inlaa->player_name, 64);
strn0cpy(outlaa->leader_name, inlaa->leader_name, 64);
memcpy(&outlaa->raid, &inlaa->raid, sizeof(RaidLeadershipAA_Struct));
dest->FastQueuePacket(&outapp);
break;
}
else
case raidSetLeaderAbilities:
case raidMakeLeader:
{
RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer;
RaidLeadershipUpdate_Struct* emu = (RaidLeadershipUpdate_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
structs::RaidLeadershipUpdate_Struct* eq = (structs::RaidLeadershipUpdate_Struct*)outapp->pBuffer;
OUT(action);
OUT_str(player_name);
OUT_str(leader_name);
memcpy(&eq->raid, &emu->raid, sizeof(RaidLeadershipAA_Struct));
dest->FastQueuePacket(&outapp);
break;
}
case raidSetNote:
{
auto emu = (RaidNote_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidNote_Struct));
auto eq = (structs::RaidNote_Struct*)outapp->pBuffer;
OUT(general.action);
OUT_str(general.leader_name);
OUT_str(general.player_name);
OUT_str(note);
dest->FastQueuePacket(&outapp);
break;
}
case raidNoRaid:
{
dest->QueuePacket(inapp);
break;
}
default:
{
RaidGeneral_Struct* emu = (RaidGeneral_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
structs::RaidGeneral_Struct *raid_general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
strn0cpy(raid_general->leader_name, in_raid_general->leader_name, 64);
strn0cpy(raid_general->player_name, in_raid_general->player_name, 64);
raid_general->action = in_raid_general->action;
raid_general->parameter = in_raid_general->parameter;
dest->FastQueuePacket(&outapp);
}
structs::RaidGeneral_Struct* eq = (structs::RaidGeneral_Struct*)outapp->pBuffer;
OUT(action);
OUT(parameter);
OUT_str(leader_name);
OUT_str(player_name);
dest->FastQueuePacket(&outapp);
break;
}
}
safe_delete(inapp);
}
@@ -1782,6 +1819,9 @@ namespace SoD
eq->window = emu->window;
OUT(type);
eq->invslot = ServerToSoDSlot(emu->invslot);
OUT(target_id);
OUT(can_cast);
OUT(can_scribe);
strn0cpy(eq->txtfile, emu->booktext, sizeof(eq->txtfile));
FINISH_ENCODE();
@@ -2817,6 +2857,17 @@ namespace SoD
FINISH_DIRECT_DECODE();
}
DECODE(OP_BookButton)
{
DECODE_LENGTH_EXACT(structs::BookButton_Struct);
SETUP_DIRECT_DECODE(BookButton_Struct, structs::BookButton_Struct);
emu->invslot = static_cast<int16_t>(SoDToServerSlot(eq->invslot));
IN(target_id);
FINISH_DIRECT_DECODE();
}
DECODE(OP_Buff)
{
DECODE_LENGTH_EXACT(structs::SpellBuffPacket_Struct);
@@ -3324,37 +3375,47 @@ namespace SoD
{
DECODE_LENGTH_ATLEAST(structs::RaidGeneral_Struct);
// This is a switch on the RaidGeneral action
switch (*(uint32 *)__packet->pBuffer) {
case 35: { // raidMOTD
// we don't have a nice macro for this
structs::RaidMOTD_Struct *__eq_buffer = (structs::RaidMOTD_Struct *)__packet->pBuffer;
__eq_buffer->motd[1023] = '\0';
size_t motd_size = strlen(__eq_buffer->motd) + 1;
__packet->size = sizeof(RaidMOTD_Struct) + motd_size;
__packet->pBuffer = new unsigned char[__packet->size];
RaidMOTD_Struct *emu = (RaidMOTD_Struct *)__packet->pBuffer;
structs::RaidMOTD_Struct *eq = (structs::RaidMOTD_Struct *)__eq_buffer;
strn0cpy(emu->general.player_name, eq->general.player_name, 64);
strn0cpy(emu->motd, eq->motd, motd_size);
IN(general.action);
IN(general.parameter);
FINISH_DIRECT_DECODE();
break;
}
case 36: { // raidPlayerNote unhandled
break;
}
default: {
DECODE_LENGTH_EXACT(structs::RaidGeneral_Struct);
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
strn0cpy(emu->leader_name, eq->leader_name, 64);
strn0cpy(emu->player_name, eq->player_name, 64);
IN(action);
IN(parameter);
FINISH_DIRECT_DECODE();
break;
}
RaidGeneral_Struct* rgs = (RaidGeneral_Struct*)__packet->pBuffer;
switch (rgs->action)
{
case raidSetMotd:
{
SETUP_VAR_DECODE(RaidMOTD_Struct, structs::RaidMOTD_Struct, motd);
IN(general.action);
IN(general.parameter);
IN_str(general.leader_name);
IN_str(general.player_name);
IN_str(motd);
FINISH_VAR_DECODE();
break;
}
case raidSetNote:
{
SETUP_VAR_DECODE(RaidNote_Struct, structs::RaidNote_Struct, note);
IN(general.action);
IN(general.parameter);
IN_str(general.leader_name);
IN_str(general.player_name);
IN_str(note);
FINISH_VAR_DECODE();
break;
}
default:
{
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
IN(action);
IN(parameter);
IN_str(leader_name);
IN_str(player_name);
FINISH_DIRECT_DECODE();
break;
}
}
}
@@ -3364,7 +3425,8 @@ namespace SoD
SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct);
IN(type);
emu->invslot = SoDToServerSlot(eq->invslot);
emu->invslot = static_cast<int16_t>(SoDToServerSlot(eq->invslot));
IN(target_id);
emu->window = (uint8)eq->window;
strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile));
+1
View File
@@ -103,6 +103,7 @@ D(OP_ApplyPoison)
D(OP_AugmentInfo)
D(OP_AugmentItem)
D(OP_BazaarSearch)
D(OP_BookButton)
D(OP_Buff)
D(OP_CastSpell)
D(OP_ChannelMessage)
+21 -7
View File
@@ -2351,12 +2351,21 @@ struct BookText_Struct {
// This is just a "text file" on the server
// or in our case, the 'name' column in our books table.
struct BookRequest_Struct {
/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window).
/*0004*/ uint32 invslot; // The inventory slot the book is in. Not used, but echoed in the response packet.
/*0008*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others
/*0012*/ uint32 unknown0012;
/*0016*/ uint16 unknown0016;
/*0018*/ char txtfile[8194];
/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window).
/*0004*/ uint32 invslot; // The inventory slot the book is in
/*0008*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others
/*0012*/ uint32 target_id;
/*0016*/ uint8 can_cast;
/*0017*/ uint8 can_scribe;
/*0018*/ char txtfile[8194];
};
// used by Scribe and CastSpell book buttons
struct BookButton_Struct
{
/*0000*/ int32 invslot;
/*0004*/ int32 target_id; // client's target when using the book
/*0008*/ int32 unused; // always 0 from button packets
};
/*
@@ -3583,9 +3592,14 @@ struct RaidAddMember_Struct {
/*139*/ uint8 flags[5]; //no idea if these are needed...
};
struct RaidNote_Struct {
/*000*/ RaidGeneral_Struct general;
/*140*/ char note[64];
};
struct RaidMOTD_Struct {
/*000*/ RaidGeneral_Struct general; // leader_name and action only used
/*140*/ char motd[0]; // max size 1024, but reply is variable
/*140*/ char motd[1024]; // max size is 1024, but reply is variable
};
struct RaidLeadershipUpdate_Struct {
+151 -89
View File
@@ -33,6 +33,7 @@
#include "sof_structs.h"
#include "../rulesys.h"
#include "../path_manager.h"
#include "../raid.h"
#include <iostream>
#include <sstream>
@@ -1356,88 +1357,124 @@ namespace SoF
ENCODE(OP_RaidJoin)
{
EQApplicationPacket *inapp = *p;
unsigned char * __emu_buffer = inapp->pBuffer;
RaidCreate_Struct *raid_create = (RaidCreate_Struct*)__emu_buffer;
EQApplicationPacket* inapp = *p;
*p = nullptr;
unsigned char* __emu_buffer = inapp->pBuffer;
RaidCreate_Struct* emu = (RaidCreate_Struct*)__emu_buffer;
auto outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
structs::RaidGeneral_Struct *general = (structs::RaidGeneral_Struct*)outapp_create->pBuffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
structs::RaidGeneral_Struct* general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
general->action = 8;
general->parameter = 1;
strn0cpy(general->leader_name, raid_create->leader_name, 64);
strn0cpy(general->player_name, raid_create->leader_name, 64);
general->action = raidCreate;
general->parameter = RaidCommandAcceptInvite;
strn0cpy(general->leader_name, emu->leader_name, sizeof(emu->leader_name));
strn0cpy(general->player_name, emu->leader_name, sizeof(emu->leader_name));
dest->FastQueuePacket(&outapp);
dest->FastQueuePacket(&outapp_create);
safe_delete(inapp);
}
ENCODE(OP_RaidUpdate)
{
EQApplicationPacket *inapp = *p;
EQApplicationPacket* inapp = *p;
*p = nullptr;
unsigned char * __emu_buffer = inapp->pBuffer;
RaidGeneral_Struct *raid_gen = (RaidGeneral_Struct*)__emu_buffer;
unsigned char* __emu_buffer = inapp->pBuffer;
RaidGeneral_Struct* raid_gen = (RaidGeneral_Struct*)__emu_buffer;
if (raid_gen->action == 0) // raid add has longer length than other raid updates
switch (raid_gen->action)
{
RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer;
case raidAdd:
{
RaidAddMember_Struct* emu = (RaidAddMember_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct));
structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer;
structs::RaidAddMember_Struct* eq = (structs::RaidAddMember_Struct*)outapp->pBuffer;
add_member->raidGen.action = in_add_member->raidGen.action;
add_member->raidGen.parameter = in_add_member->raidGen.parameter;
strn0cpy(add_member->raidGen.leader_name, in_add_member->raidGen.leader_name, 64);
strn0cpy(add_member->raidGen.player_name, in_add_member->raidGen.player_name, 64);
add_member->_class = in_add_member->_class;
add_member->level = in_add_member->level;
add_member->isGroupLeader = in_add_member->isGroupLeader;
add_member->flags[0] = in_add_member->flags[0];
add_member->flags[1] = in_add_member->flags[1];
add_member->flags[2] = in_add_member->flags[2];
add_member->flags[3] = in_add_member->flags[3];
add_member->flags[4] = in_add_member->flags[4];
dest->FastQueuePacket(&outapp);
}
else if (raid_gen->action == 35)
{
RaidMOTD_Struct *inmotd = (RaidMOTD_Struct *)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) +
strlen(inmotd->motd) + 1);
structs::RaidMOTD_Struct *outmotd = (structs::RaidMOTD_Struct *)outapp->pBuffer;
OUT(raidGen.action);
OUT(raidGen.parameter);
OUT_str(raidGen.leader_name);
OUT_str(raidGen.player_name);
OUT(_class);
OUT(level);
OUT(isGroupLeader);
OUT(flags[0]);
OUT(flags[1]);
OUT(flags[2]);
OUT(flags[3]);
OUT(flags[4]);
outmotd->general.action = inmotd->general.action;
strn0cpy(outmotd->general.player_name, inmotd->general.player_name, 64);
strn0cpy(outmotd->motd, inmotd->motd, strlen(inmotd->motd) + 1);
dest->FastQueuePacket(&outapp);
break;
}
else if (raid_gen->action == 14 || raid_gen->action == 30)
case raidSetMotd:
{
RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer;
auto outapp =
new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer;
RaidMOTD_Struct* emu = (RaidMOTD_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct));
structs::RaidMOTD_Struct* eq = (structs::RaidMOTD_Struct*)outapp->pBuffer;
OUT(general.action);
OUT_str(general.player_name);
OUT_str(general.leader_name);
OUT_str(motd);
outlaa->action = inlaa->action;
strn0cpy(outlaa->player_name, inlaa->player_name, 64);
strn0cpy(outlaa->leader_name, inlaa->leader_name, 64);
memcpy(&outlaa->raid, &inlaa->raid, sizeof(RaidLeadershipAA_Struct));
dest->FastQueuePacket(&outapp);
break;
}
else
case raidSetLeaderAbilities:
case raidMakeLeader:
{
RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer;
RaidLeadershipUpdate_Struct* emu = (RaidLeadershipUpdate_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
structs::RaidLeadershipUpdate_Struct* eq = (structs::RaidLeadershipUpdate_Struct*)outapp->pBuffer;
OUT(action);
OUT_str(player_name);
OUT_str(leader_name);
memcpy(&eq->raid, &emu->raid, sizeof(RaidLeadershipAA_Struct));
dest->FastQueuePacket(&outapp);
break;
}
case raidSetNote:
{
auto emu = (RaidNote_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidNote_Struct));
auto eq = (structs::RaidNote_Struct*)outapp->pBuffer;
OUT(general.action);
OUT_str(general.leader_name);
OUT_str(general.player_name);
OUT_str(note);
dest->FastQueuePacket(&outapp);
break;
}
case raidNoRaid:
{
dest->QueuePacket(inapp);
break;
}
default:
{
RaidGeneral_Struct* emu = (RaidGeneral_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
structs::RaidGeneral_Struct *raid_general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
strn0cpy(raid_general->leader_name, in_raid_general->leader_name, 64);
strn0cpy(raid_general->player_name, in_raid_general->player_name, 64);
raid_general->action = in_raid_general->action;
raid_general->parameter = in_raid_general->parameter;
dest->FastQueuePacket(&outapp);
}
structs::RaidGeneral_Struct* eq = (structs::RaidGeneral_Struct*)outapp->pBuffer;
OUT(action);
OUT(parameter);
OUT_str(leader_name);
OUT_str(player_name);
dest->FastQueuePacket(&outapp);
break;
}
}
safe_delete(inapp);
}
@@ -1452,6 +1489,9 @@ namespace SoF
eq->window = emu->window;
OUT(type);
eq->invslot = ServerToSoFSlot(emu->invslot);
OUT(target_id);
OUT(can_cast);
OUT(can_scribe);
strn0cpy(eq->txtfile, emu->booktext, sizeof(eq->txtfile));
FINISH_ENCODE();
@@ -2261,6 +2301,17 @@ namespace SoF
FINISH_DIRECT_DECODE();
}
DECODE(OP_BookButton)
{
DECODE_LENGTH_EXACT(structs::BookButton_Struct);
SETUP_DIRECT_DECODE(BookButton_Struct, structs::BookButton_Struct);
emu->invslot = static_cast<int16_t>(SoFToServerSlot(eq->invslot));
IN(target_id);
FINISH_DIRECT_DECODE();
}
DECODE(OP_Buff)
{
DECODE_LENGTH_EXACT(structs::SpellBuffPacket_Struct);
@@ -2729,37 +2780,47 @@ namespace SoF
{
DECODE_LENGTH_ATLEAST(structs::RaidGeneral_Struct);
// This is a switch on the RaidGeneral action
switch (*(uint32 *)__packet->pBuffer) {
case 35: { // raidMOTD
// we don't have a nice macro for this
structs::RaidMOTD_Struct *__eq_buffer = (structs::RaidMOTD_Struct *)__packet->pBuffer;
__eq_buffer->motd[1023] = '\0';
size_t motd_size = strlen(__eq_buffer->motd) + 1;
__packet->size = sizeof(RaidMOTD_Struct) + motd_size;
__packet->pBuffer = new unsigned char[__packet->size];
RaidMOTD_Struct *emu = (RaidMOTD_Struct *)__packet->pBuffer;
structs::RaidMOTD_Struct *eq = (structs::RaidMOTD_Struct *)__eq_buffer;
strn0cpy(emu->general.player_name, eq->general.player_name, 64);
strn0cpy(emu->motd, eq->motd, motd_size);
IN(general.action);
IN(general.parameter);
FINISH_DIRECT_DECODE();
break;
}
case 36: { // raidPlayerNote unhandled
break;
}
default: {
DECODE_LENGTH_EXACT(structs::RaidGeneral_Struct);
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
strn0cpy(emu->leader_name, eq->leader_name, 64);
strn0cpy(emu->player_name, eq->player_name, 64);
IN(action);
IN(parameter);
FINISH_DIRECT_DECODE();
break;
}
RaidGeneral_Struct* rgs = (RaidGeneral_Struct*)__packet->pBuffer;
switch (rgs->action)
{
case raidSetMotd:
{
SETUP_VAR_DECODE(RaidMOTD_Struct, structs::RaidMOTD_Struct, motd);
IN(general.action);
IN(general.parameter);
IN_str(general.leader_name);
IN_str(general.player_name);
IN_str(motd);
FINISH_VAR_DECODE();
break;
}
case raidSetNote:
{
SETUP_VAR_DECODE(RaidNote_Struct, structs::RaidNote_Struct, note);
IN(general.action);
IN(general.parameter);
IN_str(general.leader_name);
IN_str(general.player_name);
IN_str(note);
FINISH_VAR_DECODE();
break;
}
default:
{
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
IN(action);
IN(parameter);
IN_str(leader_name);
IN_str(player_name);
FINISH_DIRECT_DECODE();
break;
}
}
}
@@ -2769,7 +2830,8 @@ namespace SoF
SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct);
IN(type);
emu->invslot = SoFToServerSlot(eq->invslot);
emu->invslot = static_cast<int16_t>(SoFToServerSlot(eq->invslot));
IN(target_id);
emu->window = (uint8)eq->window;
strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile));
+1
View File
@@ -94,6 +94,7 @@ D(OP_AltCurrencySellSelection)
D(OP_ApplyPoison)
D(OP_AugmentInfo)
D(OP_AugmentItem)
D(OP_BookButton)
D(OP_Buff)
D(OP_Bug)
D(OP_CastSpell)
+21 -7
View File
@@ -2321,12 +2321,21 @@ struct BookText_Struct {
// This is just a "text file" on the server
// or in our case, the 'name' column in our books table.
struct BookRequest_Struct {
/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window).
/*0004*/ uint32 invslot; // The inventory slot the book is in. Not used, but echoed in the response packet.
/*0008*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others
/*0012*/ uint32 unknown0012;
/*0016*/ uint16 unknown0016;
/*0018*/ char txtfile[8194];
/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window).
/*0004*/ uint32 invslot; // The inventory slot the book is in
/*0008*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others
/*0012*/ uint32 target_id;
/*0016*/ uint8 can_cast;
/*0017*/ uint8 can_scribe;
/*0018*/ char txtfile[8194];
};
// used by Scribe and CastSpell book buttons
struct BookButton_Struct
{
/*0000*/ int32 invslot;
/*0004*/ int32 target_id; // client's target when using the book
/*0008*/ int32 unused; // always 0 from button packets
};
/*
@@ -3508,9 +3517,14 @@ struct RaidAddMember_Struct {
/*139*/ uint8 flags[5]; //no idea if these are needed...
};
struct RaidNote_Struct {
/*000*/ RaidGeneral_Struct general;
/*140*/ char note[64];
};
struct RaidMOTD_Struct {
/*000*/ RaidGeneral_Struct general; // leader_name and action only used
/*140*/ char motd[0]; // max size 1024, but reply is variable
/*140*/ char motd[1024]; // max size is 1024, but reply is variable
};
struct RaidLeadershipUpdate_Struct {
+12
View File
@@ -128,6 +128,15 @@
emu_struct *emu = (emu_struct *) __packet->pBuffer; \
eq_struct *eq = (eq_struct *) __eq_buffer;
#define SETUP_VAR_DECODE(emu_struct, eq_struct, var_field) \
unsigned char *__eq_buffer = __packet->pBuffer; \
eq_struct* in = (eq_struct*)__packet->pBuffer; \
auto size = strlen(in->var_field); \
__packet->size = sizeof(emu_struct) + size + 1; \
__packet->pBuffer = new unsigned char[__packet->size]; \
emu_struct *emu = (emu_struct *) __packet->pBuffer; \
eq_struct *eq = (eq_struct *) __eq_buffer;
#define MEMSET_IN(emu_struct) \
memset(__packet->pBuffer, 0, sizeof(emu_struct));
@@ -146,6 +155,9 @@
delete[] __eq_buffer; \
p->SetOpcode(OP_Unknown);
#define FINISH_VAR_DECODE() \
delete[] __eq_buffer;
//call to finish an encoder using SETUP_DIRECT_DECODE
#define FINISH_DIRECT_DECODE() \
delete[] __eq_buffer;
+171
View File
@@ -33,6 +33,7 @@
#include "../item_instance.h"
#include "titanium_structs.h"
#include "../path_manager.h"
#include "../raid.h"
#include <sstream>
@@ -1245,6 +1246,119 @@ namespace Titanium
FINISH_ENCODE();
}
ENCODE(OP_MarkRaidNPC)
{
ENCODE_LENGTH_EXACT(MarkNPC_Struct);
SETUP_DIRECT_ENCODE(MarkNPC_Struct, MarkNPC_Struct);
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MarkNPC, sizeof(MarkNPC_Struct));
MarkNPC_Struct* mnpcs = (MarkNPC_Struct*)outapp->pBuffer;
mnpcs->TargetID = emu->TargetID;
mnpcs->Number = emu->Number;
dest->QueuePacket(outapp);
safe_delete(outapp);
FINISH_ENCODE();
}
ENCODE(OP_RaidUpdate)
{
EQApplicationPacket* inapp = *p;
*p = nullptr;
unsigned char* __emu_buffer = inapp->pBuffer;
RaidGeneral_Struct* raid_gen = (RaidGeneral_Struct*)__emu_buffer;
switch (raid_gen->action)
{
case raidAdd:
{
RaidAddMember_Struct* emu = (RaidAddMember_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct));
structs::RaidAddMember_Struct* eq = (structs::RaidAddMember_Struct*)outapp->pBuffer;
OUT(raidGen.action);
OUT(raidGen.parameter);
OUT_str(raidGen.leader_name);
OUT_str(raidGen.player_name);
OUT(_class);
OUT(level);
OUT(isGroupLeader);
dest->FastQueuePacket(&outapp);
break;
}
case raidSetMotd:
{
RaidMOTD_Struct* emu = (RaidMOTD_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct));
structs::RaidMOTD_Struct* eq = (structs::RaidMOTD_Struct*)outapp->pBuffer;
OUT(general.action);
OUT_str(general.player_name);
OUT_str(general.leader_name);
OUT_str(motd);
dest->FastQueuePacket(&outapp);
break;
}
case raidSetLeaderAbilities:
case raidMakeLeader:
{
RaidLeadershipUpdate_Struct* emu = (RaidLeadershipUpdate_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
structs::RaidLeadershipUpdate_Struct* eq = (structs::RaidLeadershipUpdate_Struct*)outapp->pBuffer;
OUT(action);
OUT_str(player_name);
OUT_str(leader_name);
memcpy(&eq->raid, &emu->raid, sizeof(RaidLeadershipAA_Struct));
dest->FastQueuePacket(&outapp);
break;
}
case raidSetNote:
{
auto emu = (RaidNote_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidNote_Struct));
auto eq = (structs::RaidNote_Struct*)outapp->pBuffer;
OUT(general.action);
OUT_str(general.leader_name);
OUT_str(general.player_name);
OUT_str(note);
dest->FastQueuePacket(&outapp);
break;
}
case raidNoRaid:
{
dest->QueuePacket(inapp);
break;
}
default:
{
RaidGeneral_Struct* emu = (RaidGeneral_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
structs::RaidGeneral_Struct* eq = (structs::RaidGeneral_Struct*)outapp->pBuffer;
OUT(action);
OUT(parameter);
OUT_str(leader_name);
OUT_str(player_name);
dest->FastQueuePacket(&outapp);
break;
}
}
safe_delete(inapp);
}
ENCODE(OP_ReadBook)
{
// no apparent slot translation needed
@@ -2272,6 +2386,63 @@ namespace Titanium
FINISH_DIRECT_DECODE();
}
DECODE(OP_RaidInvite)
{
DECODE_LENGTH_ATLEAST(structs::RaidGeneral_Struct);
RaidGeneral_Struct* rgs = (RaidGeneral_Struct*)__packet->pBuffer;
switch (rgs->action)
{
case raidSetMotd:
{
SETUP_VAR_DECODE(RaidMOTD_Struct, structs::RaidMOTD_Struct, motd);
IN(general.action);
IN(general.parameter);
IN_str(general.leader_name);
IN_str(general.player_name);
auto len = 0;
if (__packet->size < sizeof(structs::RaidMOTD_Struct)) {
len = __packet->size - sizeof(structs::RaidGeneral_Struct);
}
else {
len = sizeof(eq->motd);
}
strn0cpy(emu->motd, eq->motd, len > 1024 ? 1024 : len);
emu->motd[len - 1] = '\0';
FINISH_VAR_DECODE();
break;
}
case raidSetNote:
{
SETUP_VAR_DECODE(RaidNote_Struct, structs::RaidNote_Struct, note);
IN(general.action);
IN(general.parameter);
IN_str(general.leader_name);
IN_str(general.player_name);
IN_str(note);
FINISH_VAR_DECODE();
break;
}
default:
{
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
IN(action);
IN(parameter);
IN_str(leader_name);
IN_str(player_name);
FINISH_DIRECT_DECODE();
break;
}
}
}
DECODE(OP_ReadBook)
{
// no apparent slot translation needed
+3
View File
@@ -61,6 +61,8 @@ E(OP_OnLevelMessage)
E(OP_PetBuffWindow)
E(OP_PlayerProfile)
E(OP_NewSpawn)
E(OP_MarkRaidNPC)
E(OP_RaidUpdate)
E(OP_ReadBook)
E(OP_RespondAA)
E(OP_SendCharInfo)
@@ -106,6 +108,7 @@ D(OP_LoadSpellSet)
D(OP_LootItem)
D(OP_MoveItem)
D(OP_PetCommands)
D(OP_RaidInvite)
D(OP_ReadBook)
D(OP_SetServerFilter)
D(OP_ShopPlayerSell)
+29 -13
View File
@@ -3017,23 +3017,39 @@ struct leadExpUpdateStruct {
/*0028*/ uint32 unknown0028;
};
struct RaidGeneral_Struct {
/*00*/ uint32 action; //=10
/*04*/ char player_name[64]; //should both be the player's name
/*04*/ char leader_name[64];
/*000*/ uint32 action; //=10
/*004*/ char player_name[64]; //should both be the player's name
/*068*/ char leader_name[64];
/*132*/ uint32 parameter;
};
struct RaidAdd_Struct {
/*000*/ uint32 action; //=0
/*004*/ char player_name[64]; //should both be the player's name
/*068*/ char leader_name[64];
/*132*/ uint8 _class;
/*133*/ uint8 level;
/*134*/ uint8 has_group;
/*135*/ uint8 unknown135; //seems to be 0x42 or 0
struct RaidAddMember_Struct {
/*000*/ RaidGeneral_Struct raidGen;
/*136*/ uint8 _class;
/*137*/ uint8 level;
/*138*/ uint8 isGroupLeader;
/*139*/ uint8 unknown139; //seems to be 0x42 or 0
};
struct RaidNote_Struct {
/*000*/ RaidGeneral_Struct general;
/*136*/ char note[64];
};
struct RaidMOTD_Struct {
/*000*/ RaidGeneral_Struct general; // leader_name and action only used
/*136*/ char motd[1024]; // max size is 1024, but reply is variable
};
struct RaidLeadershipUpdate_Struct {
/*000*/ uint32 action;
/*004*/ char player_name[64];
// /*068*/ uint32 Unknown068;
/*072*/ char leader_name[64];
/*136*/ GroupLeadershipAA_Struct group; //unneeded
/*200*/ RaidLeadershipAA_Struct raid;
/*264*/ char Unknown264[128];
};
struct RaidCreate_Struct {
+151 -90
View File
@@ -35,6 +35,7 @@
#include "../path_manager.h"
#include "../classes.h"
#include "../races.h"
#include "../raid.h"
#include <iostream>
#include <sstream>
@@ -1931,88 +1932,124 @@ namespace UF
ENCODE(OP_RaidJoin)
{
EQApplicationPacket *inapp = *p;
unsigned char * __emu_buffer = inapp->pBuffer;
RaidCreate_Struct *raid_create = (RaidCreate_Struct*)__emu_buffer;
EQApplicationPacket* inapp = *p;
*p = nullptr;
unsigned char* __emu_buffer = inapp->pBuffer;
RaidCreate_Struct* emu = (RaidCreate_Struct*)__emu_buffer;
auto outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
structs::RaidGeneral_Struct *general = (structs::RaidGeneral_Struct*)outapp_create->pBuffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
structs::RaidGeneral_Struct* general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
general->action = 8;
general->parameter = 1;
strn0cpy(general->leader_name, raid_create->leader_name, 64);
strn0cpy(general->player_name, raid_create->leader_name, 64);
general->action = raidCreate;
general->parameter = RaidCommandAcceptInvite;
strn0cpy(general->leader_name, emu->leader_name, sizeof(emu->leader_name));
strn0cpy(general->player_name, emu->leader_name, sizeof(emu->leader_name));
dest->FastQueuePacket(&outapp);
dest->FastQueuePacket(&outapp_create);
safe_delete(inapp);
}
ENCODE(OP_RaidUpdate)
{
EQApplicationPacket *inapp = *p;
EQApplicationPacket* inapp = *p;
*p = nullptr;
unsigned char * __emu_buffer = inapp->pBuffer;
RaidGeneral_Struct *raid_gen = (RaidGeneral_Struct*)__emu_buffer;
unsigned char* __emu_buffer = inapp->pBuffer;
RaidGeneral_Struct* raid_gen = (RaidGeneral_Struct*)__emu_buffer;
if (raid_gen->action == 0) // raid add has longer length than other raid updates
switch (raid_gen->action)
{
RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer;
case raidAdd:
{
RaidAddMember_Struct* emu = (RaidAddMember_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct));
structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer;
structs::RaidAddMember_Struct* eq = (structs::RaidAddMember_Struct*)outapp->pBuffer;
add_member->raidGen.action = in_add_member->raidGen.action;
add_member->raidGen.parameter = in_add_member->raidGen.parameter;
strn0cpy(add_member->raidGen.leader_name, in_add_member->raidGen.leader_name, 64);
strn0cpy(add_member->raidGen.player_name, in_add_member->raidGen.player_name, 64);
add_member->_class = in_add_member->_class;
add_member->level = in_add_member->level;
add_member->isGroupLeader = in_add_member->isGroupLeader;
add_member->flags[0] = in_add_member->flags[0];
add_member->flags[1] = in_add_member->flags[1];
add_member->flags[2] = in_add_member->flags[2];
add_member->flags[3] = in_add_member->flags[3];
add_member->flags[4] = in_add_member->flags[4];
dest->FastQueuePacket(&outapp);
}
else if (raid_gen->action == 35)
{
RaidMOTD_Struct *inmotd = (RaidMOTD_Struct *)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) +
strlen(inmotd->motd) + 1);
structs::RaidMOTD_Struct *outmotd = (structs::RaidMOTD_Struct *)outapp->pBuffer;
OUT(raidGen.action);
OUT(raidGen.parameter);
OUT_str(raidGen.leader_name);
OUT_str(raidGen.player_name);
OUT(_class);
OUT(level);
OUT(isGroupLeader);
OUT(flags[0]);
OUT(flags[1]);
OUT(flags[2]);
OUT(flags[3]);
OUT(flags[4]);
outmotd->general.action = inmotd->general.action;
strn0cpy(outmotd->general.player_name, inmotd->general.player_name, 64);
strn0cpy(outmotd->motd, inmotd->motd, strlen(inmotd->motd) + 1);
dest->FastQueuePacket(&outapp);
break;
}
else if (raid_gen->action == 14 || raid_gen->action == 30)
case raidSetMotd:
{
RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer;
auto outapp =
new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer;
RaidMOTD_Struct* emu = (RaidMOTD_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct));
structs::RaidMOTD_Struct* eq = (structs::RaidMOTD_Struct*)outapp->pBuffer;
OUT(general.action);
OUT_str(general.player_name);
OUT_str(general.leader_name);
OUT_str(motd);
outlaa->action = inlaa->action;
strn0cpy(outlaa->player_name, inlaa->player_name, 64);
strn0cpy(outlaa->leader_name, inlaa->leader_name, 64);
memcpy(&outlaa->raid, &inlaa->raid, sizeof(RaidLeadershipAA_Struct));
dest->FastQueuePacket(&outapp);
break;
}
else
case raidSetLeaderAbilities:
case raidMakeLeader:
{
RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer;
RaidLeadershipUpdate_Struct* emu = (RaidLeadershipUpdate_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
structs::RaidLeadershipUpdate_Struct* eq = (structs::RaidLeadershipUpdate_Struct*)outapp->pBuffer;
OUT(action);
OUT_str(player_name);
OUT_str(leader_name);
memcpy(&eq->raid, &emu->raid, sizeof(RaidLeadershipAA_Struct));
dest->FastQueuePacket(&outapp);
break;
}
case raidSetNote:
{
auto emu = (RaidNote_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidNote_Struct));
auto eq = (structs::RaidNote_Struct*)outapp->pBuffer;
OUT(general.action);
OUT_str(general.leader_name);
OUT_str(general.player_name);
OUT_str(note);
dest->FastQueuePacket(&outapp);
break;
}
case raidNoRaid:
{
dest->QueuePacket(inapp);
break;
}
default:
{
RaidGeneral_Struct* emu = (RaidGeneral_Struct*)__emu_buffer;
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct));
structs::RaidGeneral_Struct *raid_general = (structs::RaidGeneral_Struct*)outapp->pBuffer;
strn0cpy(raid_general->leader_name, in_raid_general->leader_name, 64);
strn0cpy(raid_general->player_name, in_raid_general->player_name, 64);
raid_general->action = in_raid_general->action;
raid_general->parameter = in_raid_general->parameter;
dest->FastQueuePacket(&outapp);
}
structs::RaidGeneral_Struct* eq = (structs::RaidGeneral_Struct*)outapp->pBuffer;
OUT(action);
OUT(parameter);
OUT_str(leader_name);
OUT_str(player_name);
dest->FastQueuePacket(&outapp);
break;
}
}
safe_delete(inapp);
}
@@ -2027,6 +2064,9 @@ namespace UF
eq->window = emu->window;
OUT(type);
eq->invslot = ServerToUFSlot(emu->invslot);
OUT(target_id);
OUT(can_cast);
OUT(can_scribe);
strn0cpy(eq->txtfile, emu->booktext, sizeof(eq->txtfile));
FINISH_ENCODE();
@@ -3105,6 +3145,17 @@ namespace UF
FINISH_DIRECT_DECODE();
}
DECODE(OP_BookButton)
{
DECODE_LENGTH_EXACT(structs::BookButton_Struct);
SETUP_DIRECT_DECODE(BookButton_Struct, structs::BookButton_Struct);
emu->invslot = static_cast<int16_t>(UFToServerSlot(eq->invslot));
IN(target_id);
FINISH_DIRECT_DECODE();
}
DECODE(OP_Buff)
{
DECODE_LENGTH_EXACT(structs::SpellBuffPacket_Struct);
@@ -3623,39 +3674,48 @@ namespace UF
{
DECODE_LENGTH_ATLEAST(structs::RaidGeneral_Struct);
// This is a switch on the RaidGeneral action
switch (*(uint32 *)__packet->pBuffer) {
case 35: { // raidMOTD
// we don't have a nice macro for this
structs::RaidMOTD_Struct *__eq_buffer = (structs::RaidMOTD_Struct *)__packet->pBuffer;
__eq_buffer->motd[1023] = '\0';
size_t motd_size = strlen(__eq_buffer->motd) + 1;
__packet->size = sizeof(RaidMOTD_Struct) + motd_size;
__packet->pBuffer = new unsigned char[__packet->size];
RaidMOTD_Struct *emu = (RaidMOTD_Struct *)__packet->pBuffer;
structs::RaidMOTD_Struct *eq = (structs::RaidMOTD_Struct *)__eq_buffer;
strn0cpy(emu->general.player_name, eq->general.player_name, 64);
strn0cpy(emu->motd, eq->motd, motd_size);
IN(general.action);
IN(general.parameter);
FINISH_DIRECT_DECODE();
break;
}
case 36: { // raidPlayerNote unhandled
break;
}
default: {
DECODE_LENGTH_EXACT(structs::RaidGeneral_Struct);
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
strn0cpy(emu->leader_name, eq->leader_name, 64);
strn0cpy(emu->player_name, eq->player_name, 64);
IN(action);
IN(parameter);
FINISH_DIRECT_DECODE();
break;
}
}
RaidGeneral_Struct* rgs = (RaidGeneral_Struct*)__packet->pBuffer;
switch (rgs->action)
{
case raidSetMotd:
{
SETUP_VAR_DECODE(RaidMOTD_Struct, structs::RaidMOTD_Struct, motd);
IN(general.action);
IN(general.parameter);
IN_str(general.leader_name);
IN_str(general.player_name);
IN_str(motd);
FINISH_VAR_DECODE();
break;
}
case raidSetNote:
{
SETUP_VAR_DECODE(RaidNote_Struct, structs::RaidNote_Struct, note);
IN(general.action);
IN(general.parameter);
IN_str(general.leader_name);
IN_str(general.player_name);
IN_str(note);
FINISH_VAR_DECODE();
break;
}
default:
{
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);
IN(action);
IN(parameter);
IN_str(leader_name);
IN_str(player_name);
FINISH_DIRECT_DECODE();
break;
}
}
}
DECODE(OP_ReadBook)
@@ -3664,7 +3724,8 @@ namespace UF
SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct);
IN(type);
emu->invslot = UFToServerSlot(eq->invslot);
emu->invslot = static_cast<int16_t>(UFToServerSlot(eq->invslot));
IN(target_id);
emu->window = (uint8)eq->window;
strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile));
+1
View File
@@ -110,6 +110,7 @@ D(OP_ApplyPoison)
D(OP_AugmentInfo)
D(OP_AugmentItem)
D(OP_BazaarSearch)
D(OP_BookButton)
D(OP_Buff)
D(OP_BuffRemoveRequest)
D(OP_CastSpell)
+22 -8
View File
@@ -2400,12 +2400,21 @@ struct BookText_Struct {
// This is just a "text file" on the server
// or in our case, the 'name' column in our books table.
struct BookRequest_Struct {
/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window).
/*0004*/ uint32 invslot; // The inventory slot the book is in. Not used, but echoed in the response packet.
/*0008*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others
/*0012*/ uint32 unknown0012;
/*0016*/ uint16 unknown0016;
/*0018*/ char txtfile[8194];
/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window).
/*0004*/ uint32 invslot; // The inventory slot the book is in
/*0008*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others
/*0012*/ uint32 target_id;
/*0016*/ uint8 can_cast;
/*0017*/ uint8 can_scribe;
/*0018*/ char txtfile[8194];
};
// used by Scribe and CastSpell book buttons
struct BookButton_Struct
{
/*0000*/ int32 invslot;
/*0004*/ int32 target_id; // client's target when using the book
/*0008*/ int32 unused; // always 0 from button packets
};
/*
@@ -3638,9 +3647,14 @@ struct RaidAddMember_Struct {
/*139*/ uint8 flags[5]; //no idea if these are needed...
};
struct RaidNote_Struct {
/*000*/ RaidGeneral_Struct general;
/*140*/ char note[64];
};
struct RaidMOTD_Struct {
/*000*/ RaidGeneral_Struct general; // leader_name and action only used
/*140*/ char motd[0]; // max size 1024, but reply is variable
/*000*/ RaidGeneral_Struct general;
/*140*/ char motd[1024];
};
struct RaidLeadershipUpdate_Struct {
+2
View File
@@ -72,6 +72,8 @@ std::string GetPlatformName()
return "HC";
case EQEmuExePlatform::ExePlatformTests:
return "Tests";
case EQEmuExePlatform::ExePlatformZoneSidecar:
return "ZoneSidecar";
default:
return "";
}
+2 -1
View File
@@ -37,7 +37,8 @@ enum EQEmuExePlatform
ExePlatformClientImport,
ExePlatformClientExport,
ExePlatformHC,
ExePlatformTests
ExePlatformTests,
ExePlatformZoneSidecar
};
void RegisterExecutablePlatform(EQEmuExePlatform p);
+44
View File
@@ -0,0 +1,44 @@
#include <string>
#include <fstream>
#include <algorithm>
#include "process.h"
inline std::string random_string(size_t length)
{
auto randchar = []() -> char {
const char charset[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz";
const size_t max_index = (sizeof(charset) - 1);
return charset[static_cast<size_t>(std::rand()) % max_index];
};
std::string str(length, 0);
std::generate_n(str.begin(), length, randchar);
return str;
}
std::string Process::execute(const std::string &cmd, bool return_result)
{
std::string random = "/tmp/" + random_string(25);
const char *file_name = random.c_str();
if (return_result) {
#ifdef _WINDOWS
std::system((cmd + " > " + file_name + " 2>&1").c_str());
#else
std::system((cmd + " > " + file_name + " 2>&1").c_str());
#endif
}
else {
std::system((cmd).c_str());
}
std::string result;
if (return_result) {
std::ifstream file(file_name);
result = {std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()};
std::remove(file_name);
}
return result;
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef EQEMU_PROCESS_H
#define EQEMU_PROCESS_H
class Process {
public:
static std::string execute(const std::string &cmd, bool return_result = true);
};
#endif //EQEMU_PROCESS_H
+4 -2
View File
@@ -1594,11 +1594,13 @@ float GetRaceGenderDefaultHeight(int race, int gender)
const auto size = sizeof(male_height) / sizeof(male_height[0]);
if (race >= size)
if (race >= size) {
return 6.0f;
}
if (gender == 1)
if (gender == FEMALE) {
return female_height[race];
}
return male_height[race];
}
+72
View File
@@ -0,0 +1,72 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef RAID_H
#define RAID_H
enum { //raid packet types:
raidAdd = 0,
raidRemove2 = 1, //parameter=0
raidMemberNameChange = 2,
raidRemove1 = 3, //parameter=0xFFFFFFFF
raidNoLongerLeader = 4,
raidDisband = 5,
raidMembers = 6, //len 395+, details + members list
raidNoAssignLeadership = 7,
raidCreate = 8, //len 72
raidUnknown = 9, // unused?
raidNoRaid = 10, //parameter=0
raidChangeLootType = 11,
raidStringID = 12,
raidChangeGroupLeader = 13, //136 raid leader, new group leader, group_id?
raidSetLeaderAbilities = 14, //472
raidSetLeaderData = 15, // 14,15 SoE names, not sure on difference, 14 packet has 0x100 bytes 15 0x214 in addition to raid general
raidChangeGroup = 16, //?? len 136 old leader, new leader, 0 (preceeded with a remove2)
raidLock = 17, //len 136 leader?, leader, 0
raidUnlock = 18, //len 136 leader?, leader, 0
raidRedStringID = 19,
raidSetLeader = 20, //len 388, contains 'details' struct without members; also used for "invite to raid"
raidMakeLeader = 30,
raidSetMotd = 35,
raidSetNote = 36,
};
enum { //raid command types
RaidCommandInviteIntoExisting = 0, //in use
RaidCommandAcceptInvite = 1, //in use
RaidCommandInvite = 3, //in use
RaidCommandDisband = 5, //in use
RaidCommandMoveGroup = 6, //in use
RaidCommandRemoveGroupLeader = 7,
RaidCommandRaidLock = 8, //in use
RaidCommandRaidUnlock = 9, //in use
RaidCommandLootType = 20, //in use
RaidCommandAddLooter = 21, //in use
RaidCommandRemoveLooter = 22, //in use
RaidCommandMakeLeader = 30,
RaidCommandInviteFail = 31, //already in raid, waiting on invite from other raid, etc
RaidCommandLootType2 = 32, //in use
RaidCommandAddLooter2 = 33, //in use
RaidCommandRemoveLooter2 = 34, //in use
RaidCommandSetMotd = 35,
RaidCommandSetNote = 36,
};
#endif
@@ -16,6 +16,7 @@
#include "../../strings.h"
#include <ctime>
class BaseBlockedSpellsRepository {
public:
struct BlockedSpells {
@@ -31,6 +32,10 @@ public:
float z_diff;
std::string message;
std::string description;
int8_t min_expansion;
int8_t max_expansion;
std::string content_flags;
std::string content_flags_disabled;
};
static std::string PrimaryKey()
@@ -53,6 +58,10 @@ public:
"z_diff",
"message",
"description",
"min_expansion",
"max_expansion",
"content_flags",
"content_flags_disabled",
};
}
@@ -71,6 +80,10 @@ public:
"z_diff",
"message",
"description",
"min_expansion",
"max_expansion",
"content_flags",
"content_flags_disabled",
};
}
@@ -111,18 +124,22 @@ public:
{
BlockedSpells e{};
e.id = 0;
e.spellid = 0;
e.type = 0;
e.zoneid = 0;
e.x = 0;
e.y = 0;
e.z = 0;
e.x_diff = 0;
e.y_diff = 0;
e.z_diff = 0;
e.message = "";
e.description = "";
e.id = 0;
e.spellid = 0;
e.type = 0;
e.zoneid = 0;
e.x = 0;
e.y = 0;
e.z = 0;
e.x_diff = 0;
e.y_diff = 0;
e.z_diff = 0;
e.message = "";
e.description = "";
e.min_expansion = -1;
e.max_expansion = -1;
e.content_flags = "";
e.content_flags_disabled = "";
return e;
}
@@ -148,8 +165,9 @@ public:
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
blocked_spells_id
)
);
@@ -158,18 +176,22 @@ public:
if (results.RowCount() == 1) {
BlockedSpells e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.type = static_cast<int8_t>(atoi(row[2]));
e.zoneid = static_cast<int32_t>(atoi(row[3]));
e.x = strtof(row[4], nullptr);
e.y = strtof(row[5], nullptr);
e.z = strtof(row[6], nullptr);
e.x_diff = strtof(row[7], nullptr);
e.y_diff = strtof(row[8], nullptr);
e.z_diff = strtof(row[9], nullptr);
e.message = row[10] ? row[10] : "";
e.description = row[11] ? row[11] : "";
e.id = static_cast<int32_t>(atoi(row[0]));
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.type = static_cast<int8_t>(atoi(row[2]));
e.zoneid = static_cast<int32_t>(atoi(row[3]));
e.x = strtof(row[4], nullptr);
e.y = strtof(row[5], nullptr);
e.z = strtof(row[6], nullptr);
e.x_diff = strtof(row[7], nullptr);
e.y_diff = strtof(row[8], nullptr);
e.z_diff = strtof(row[9], nullptr);
e.message = row[10] ? row[10] : "";
e.description = row[11] ? row[11] : "";
e.min_expansion = static_cast<int8_t>(atoi(row[12]));
e.max_expansion = static_cast<int8_t>(atoi(row[13]));
e.content_flags = row[14] ? row[14] : "";
e.content_flags_disabled = row[15] ? row[15] : "";
return e;
}
@@ -214,6 +236,10 @@ public:
v.push_back(columns[9] + " = " + std::to_string(e.z_diff));
v.push_back(columns[10] + " = '" + Strings::Escape(e.message) + "'");
v.push_back(columns[11] + " = '" + Strings::Escape(e.description) + "'");
v.push_back(columns[12] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[13] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[14] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[15] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -247,6 +273,10 @@ public:
v.push_back(std::to_string(e.z_diff));
v.push_back("'" + Strings::Escape(e.message) + "'");
v.push_back("'" + Strings::Escape(e.description) + "'");
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -288,6 +318,10 @@ public:
v.push_back(std::to_string(e.z_diff));
v.push_back("'" + Strings::Escape(e.message) + "'");
v.push_back("'" + Strings::Escape(e.description) + "'");
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -321,18 +355,22 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
BlockedSpells e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.type = static_cast<int8_t>(atoi(row[2]));
e.zoneid = static_cast<int32_t>(atoi(row[3]));
e.x = strtof(row[4], nullptr);
e.y = strtof(row[5], nullptr);
e.z = strtof(row[6], nullptr);
e.x_diff = strtof(row[7], nullptr);
e.y_diff = strtof(row[8], nullptr);
e.z_diff = strtof(row[9], nullptr);
e.message = row[10] ? row[10] : "";
e.description = row[11] ? row[11] : "";
e.id = static_cast<int32_t>(atoi(row[0]));
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.type = static_cast<int8_t>(atoi(row[2]));
e.zoneid = static_cast<int32_t>(atoi(row[3]));
e.x = strtof(row[4], nullptr);
e.y = strtof(row[5], nullptr);
e.z = strtof(row[6], nullptr);
e.x_diff = strtof(row[7], nullptr);
e.y_diff = strtof(row[8], nullptr);
e.z_diff = strtof(row[9], nullptr);
e.message = row[10] ? row[10] : "";
e.description = row[11] ? row[11] : "";
e.min_expansion = static_cast<int8_t>(atoi(row[12]));
e.max_expansion = static_cast<int8_t>(atoi(row[13]));
e.content_flags = row[14] ? row[14] : "";
e.content_flags_disabled = row[15] ? row[15] : "";
all_entries.push_back(e);
}
@@ -357,18 +395,22 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
BlockedSpells e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.type = static_cast<int8_t>(atoi(row[2]));
e.zoneid = static_cast<int32_t>(atoi(row[3]));
e.x = strtof(row[4], nullptr);
e.y = strtof(row[5], nullptr);
e.z = strtof(row[6], nullptr);
e.x_diff = strtof(row[7], nullptr);
e.y_diff = strtof(row[8], nullptr);
e.z_diff = strtof(row[9], nullptr);
e.message = row[10] ? row[10] : "";
e.description = row[11] ? row[11] : "";
e.id = static_cast<int32_t>(atoi(row[0]));
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.type = static_cast<int8_t>(atoi(row[2]));
e.zoneid = static_cast<int32_t>(atoi(row[3]));
e.x = strtof(row[4], nullptr);
e.y = strtof(row[5], nullptr);
e.z = strtof(row[6], nullptr);
e.x_diff = strtof(row[7], nullptr);
e.y_diff = strtof(row[8], nullptr);
e.z_diff = strtof(row[9], nullptr);
e.message = row[10] ? row[10] : "";
e.description = row[11] ? row[11] : "";
e.min_expansion = static_cast<int8_t>(atoi(row[12]));
e.max_expansion = static_cast<int8_t>(atoi(row[13]));
e.content_flags = row[14] ? row[14] : "";
e.content_flags_disabled = row[15] ? row[15] : "";
all_entries.push_back(e);
}
@@ -0,0 +1,414 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
*/
#ifndef EQEMU_BASE_BOT_STARTING_ITEMS_REPOSITORY_H
#define EQEMU_BASE_BOT_STARTING_ITEMS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotStartingItemsRepository {
public:
struct BotStartingItems {
uint32_t id;
uint32_t races;
uint32_t classes;
uint32_t item_id;
uint8_t item_charges;
int32_t slot_id;
int8_t min_expansion;
int8_t max_expansion;
std::string content_flags;
std::string content_flags_disabled;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"races",
"classes",
"item_id",
"item_charges",
"slot_id",
"min_expansion",
"max_expansion",
"content_flags",
"content_flags_disabled",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"races",
"classes",
"item_id",
"item_charges",
"slot_id",
"min_expansion",
"max_expansion",
"content_flags",
"content_flags_disabled",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("bot_starting_items");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotStartingItems NewEntity()
{
BotStartingItems e{};
e.id = 0;
e.races = 0;
e.classes = 0;
e.item_id = 0;
e.item_charges = 1;
e.slot_id = -1;
e.min_expansion = -1;
e.max_expansion = -1;
e.content_flags = "";
e.content_flags_disabled = "";
return e;
}
static BotStartingItems GetBotStartingItems(
const std::vector<BotStartingItems> &bot_starting_itemss,
int bot_starting_items_id
)
{
for (auto &bot_starting_items : bot_starting_itemss) {
if (bot_starting_items.id == bot_starting_items_id) {
return bot_starting_items;
}
}
return NewEntity();
}
static BotStartingItems FindOne(
Database& db,
int bot_starting_items_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
bot_starting_items_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotStartingItems e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.races = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.classes = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.item_id = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.item_charges = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.slot_id = static_cast<int32_t>(atoi(row[5]));
e.min_expansion = static_cast<int8_t>(atoi(row[6]));
e.max_expansion = static_cast<int8_t>(atoi(row[7]));
e.content_flags = row[8] ? row[8] : "";
e.content_flags_disabled = row[9] ? row[9] : "";
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_starting_items_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_starting_items_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotStartingItems &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.races));
v.push_back(columns[2] + " = " + std::to_string(e.classes));
v.push_back(columns[3] + " = " + std::to_string(e.item_id));
v.push_back(columns[4] + " = " + std::to_string(e.item_charges));
v.push_back(columns[5] + " = " + std::to_string(e.slot_id));
v.push_back(columns[6] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[7] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[8] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[9] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotStartingItems InsertOne(
Database& db,
BotStartingItems e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.races));
v.push_back(std::to_string(e.classes));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotStartingItems> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.races));
v.push_back(std::to_string(e.classes));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<BotStartingItems> All(Database& db)
{
std::vector<BotStartingItems> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotStartingItems e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.races = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.classes = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.item_id = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.item_charges = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.slot_id = static_cast<int32_t>(atoi(row[5]));
e.min_expansion = static_cast<int8_t>(atoi(row[6]));
e.max_expansion = static_cast<int8_t>(atoi(row[7]));
e.content_flags = row[8] ? row[8] : "";
e.content_flags_disabled = row[9] ? row[9] : "";
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotStartingItems> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotStartingItems> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {}",
BaseSelect(),
where_filter
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotStartingItems e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.races = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.classes = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.item_id = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.item_charges = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.slot_id = static_cast<int32_t>(atoi(row[5]));
e.min_expansion = static_cast<int8_t>(atoi(row[6]));
e.max_expansion = static_cast<int8_t>(atoi(row[7]));
e.content_flags = row[8] ? row[8] : "";
e.content_flags_disabled = row[9] ? row[9] : "";
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_BOT_STARTING_ITEMS_REPOSITORY_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,364 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
*/
#ifndef EQEMU_BASE_COMMAND_SUBSETTINGS_REPOSITORY_H
#define EQEMU_BASE_COMMAND_SUBSETTINGS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseCommandSubsettingsRepository {
public:
struct CommandSubsettings {
uint32_t id;
std::string parent_command;
std::string sub_command;
uint32_t access_level;
std::string top_level_aliases;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"parent_command",
"sub_command",
"access_level",
"top_level_aliases",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"parent_command",
"sub_command",
"access_level",
"top_level_aliases",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("command_subsettings");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static CommandSubsettings NewEntity()
{
CommandSubsettings e{};
e.id = 0;
e.parent_command = "";
e.sub_command = "";
e.access_level = 0;
e.top_level_aliases = "";
return e;
}
static CommandSubsettings GetCommandSubsettings(
const std::vector<CommandSubsettings> &command_subsettingss,
int command_subsettings_id
)
{
for (auto &command_subsettings : command_subsettingss) {
if (command_subsettings.id == command_subsettings_id) {
return command_subsettings;
}
}
return NewEntity();
}
static CommandSubsettings FindOne(
Database& db,
int command_subsettings_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
command_subsettings_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
CommandSubsettings e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.parent_command = row[1] ? row[1] : "";
e.sub_command = row[2] ? row[2] : "";
e.access_level = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.top_level_aliases = row[4] ? row[4] : "";
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int command_subsettings_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
command_subsettings_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const CommandSubsettings &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = '" + Strings::Escape(e.parent_command) + "'");
v.push_back(columns[2] + " = '" + Strings::Escape(e.sub_command) + "'");
v.push_back(columns[3] + " = " + std::to_string(e.access_level));
v.push_back(columns[4] + " = '" + Strings::Escape(e.top_level_aliases) + "'");
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static CommandSubsettings InsertOne(
Database& db,
CommandSubsettings e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.parent_command) + "'");
v.push_back("'" + Strings::Escape(e.sub_command) + "'");
v.push_back(std::to_string(e.access_level));
v.push_back("'" + Strings::Escape(e.top_level_aliases) + "'");
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<CommandSubsettings> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.parent_command) + "'");
v.push_back("'" + Strings::Escape(e.sub_command) + "'");
v.push_back(std::to_string(e.access_level));
v.push_back("'" + Strings::Escape(e.top_level_aliases) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<CommandSubsettings> All(Database& db)
{
std::vector<CommandSubsettings> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
CommandSubsettings e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.parent_command = row[1] ? row[1] : "";
e.sub_command = row[2] ? row[2] : "";
e.access_level = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.top_level_aliases = row[4] ? row[4] : "";
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<CommandSubsettings> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<CommandSubsettings> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {}",
BaseSelect(),
where_filter
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
CommandSubsettings e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.parent_command = row[1] ? row[1] : "";
e.sub_command = row[2] ? row[2] : "";
e.access_level = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.top_level_aliases = row[4] ? row[4] : "";
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_COMMAND_SUBSETTINGS_REPOSITORY_H
@@ -15,7 +15,7 @@
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
#include <cereal/cereal.hpp>
class BaseDataBucketsRepository {
public:
@@ -24,6 +24,24 @@ public:
std::string key_;
std::string value;
uint32_t expires;
int64_t character_id;
int64_t npc_id;
int64_t bot_id;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(id),
CEREAL_NVP(key_),
CEREAL_NVP(value),
CEREAL_NVP(expires),
CEREAL_NVP(character_id),
CEREAL_NVP(npc_id),
CEREAL_NVP(bot_id)
);
}
};
static std::string PrimaryKey()
@@ -38,6 +56,9 @@ public:
"`key`",
"value",
"expires",
"character_id",
"npc_id",
"bot_id",
};
}
@@ -48,6 +69,9 @@ public:
"`key`",
"value",
"expires",
"character_id",
"npc_id",
"bot_id",
};
}
@@ -88,10 +112,13 @@ public:
{
DataBuckets e{};
e.id = 0;
e.key_ = "";
e.value = "";
e.expires = 0;
e.id = 0;
e.key_ = "";
e.value = "";
e.expires = 0;
e.character_id = 0;
e.npc_id = 0;
e.bot_id = 0;
return e;
}
@@ -128,10 +155,13 @@ public:
if (results.RowCount() == 1) {
DataBuckets e{};
e.id = strtoull(row[0], nullptr, 10);
e.key_ = row[1] ? row[1] : "";
e.value = row[2] ? row[2] : "";
e.expires = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.id = strtoull(row[0], nullptr, 10);
e.key_ = row[1] ? row[1] : "";
e.value = row[2] ? row[2] : "";
e.expires = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.character_id = strtoll(row[4], nullptr, 10);
e.npc_id = strtoll(row[5], nullptr, 10);
e.bot_id = strtoll(row[6], nullptr, 10);
return e;
}
@@ -168,6 +198,9 @@ public:
v.push_back(columns[1] + " = '" + Strings::Escape(e.key_) + "'");
v.push_back(columns[2] + " = '" + Strings::Escape(e.value) + "'");
v.push_back(columns[3] + " = " + std::to_string(e.expires));
v.push_back(columns[4] + " = " + std::to_string(e.character_id));
v.push_back(columns[5] + " = " + std::to_string(e.npc_id));
v.push_back(columns[6] + " = " + std::to_string(e.bot_id));
auto results = db.QueryDatabase(
fmt::format(
@@ -193,6 +226,9 @@ public:
v.push_back("'" + Strings::Escape(e.key_) + "'");
v.push_back("'" + Strings::Escape(e.value) + "'");
v.push_back(std::to_string(e.expires));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.npc_id));
v.push_back(std::to_string(e.bot_id));
auto results = db.QueryDatabase(
fmt::format(
@@ -226,6 +262,9 @@ public:
v.push_back("'" + Strings::Escape(e.key_) + "'");
v.push_back("'" + Strings::Escape(e.value) + "'");
v.push_back(std::to_string(e.expires));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.npc_id));
v.push_back(std::to_string(e.bot_id));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -259,10 +298,13 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
DataBuckets e{};
e.id = strtoull(row[0], nullptr, 10);
e.key_ = row[1] ? row[1] : "";
e.value = row[2] ? row[2] : "";
e.expires = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.id = strtoull(row[0], nullptr, 10);
e.key_ = row[1] ? row[1] : "";
e.value = row[2] ? row[2] : "";
e.expires = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.character_id = strtoll(row[4], nullptr, 10);
e.npc_id = strtoll(row[5], nullptr, 10);
e.bot_id = strtoll(row[6], nullptr, 10);
all_entries.push_back(e);
}
@@ -287,10 +329,13 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
DataBuckets e{};
e.id = strtoull(row[0], nullptr, 10);
e.key_ = row[1] ? row[1] : "";
e.value = row[2] ? row[2] : "";
e.expires = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.id = strtoull(row[0], nullptr, 10);
e.key_ = row[1] ? row[1] : "";
e.value = row[2] ? row[2] : "";
e.expires = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.character_id = strtoll(row[4], nullptr, 10);
e.npc_id = strtoll(row[5], nullptr, 10);
e.bot_id = strtoll(row[6], nullptr, 10);
all_entries.push_back(e);
}
@@ -75,7 +75,7 @@ public:
int32_t damageshield;
int32_t deity;
int32_t delay;
int32_t augdistiller;
uint32_t augdistiller;
int32_t dotshielding;
int32_t dr;
int32_t clicktype;
@@ -227,7 +227,7 @@ public:
int32_t focusunk5;
std::string focusunk6;
int32_t focusunk7;
int32_t scrollunk1;
uint32_t scrollunk1;
int32_t scrollunk2;
int32_t scrollunk3;
int32_t scrollunk4;
@@ -266,10 +266,10 @@ public:
std::string created;
int16_t elitematerial;
int16_t ldonsellbackrate;
int16_t scriptfileid;
int32_t scriptfileid;
int16_t expendablearrow;
int16_t powersourcecapacity;
int16_t bardeffect;
int32_t powersourcecapacity;
int32_t bardeffect;
int16_t bardeffecttype;
int16_t bardlevel2;
int16_t bardlevel;
@@ -1307,7 +1307,7 @@ public:
e.damageshield = static_cast<int32_t>(atoi(row[52]));
e.deity = static_cast<int32_t>(atoi(row[53]));
e.delay = static_cast<int32_t>(atoi(row[54]));
e.augdistiller = static_cast<int32_t>(atoi(row[55]));
e.augdistiller = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
e.dotshielding = static_cast<int32_t>(atoi(row[56]));
e.dr = static_cast<int32_t>(atoi(row[57]));
e.clicktype = static_cast<int32_t>(atoi(row[58]));
@@ -1459,7 +1459,7 @@ public:
e.focusunk5 = static_cast<int32_t>(atoi(row[204]));
e.focusunk6 = row[205] ? row[205] : "";
e.focusunk7 = static_cast<int32_t>(atoi(row[206]));
e.scrollunk1 = static_cast<int32_t>(atoi(row[207]));
e.scrollunk1 = static_cast<uint32_t>(strtoul(row[207], nullptr, 10));
e.scrollunk2 = static_cast<int32_t>(atoi(row[208]));
e.scrollunk3 = static_cast<int32_t>(atoi(row[209]));
e.scrollunk4 = static_cast<int32_t>(atoi(row[210]));
@@ -1498,10 +1498,10 @@ public:
e.created = row[243] ? row[243] : "";
e.elitematerial = static_cast<int16_t>(atoi(row[244]));
e.ldonsellbackrate = static_cast<int16_t>(atoi(row[245]));
e.scriptfileid = static_cast<int16_t>(atoi(row[246]));
e.scriptfileid = static_cast<int32_t>(atoi(row[246]));
e.expendablearrow = static_cast<int16_t>(atoi(row[247]));
e.powersourcecapacity = static_cast<int16_t>(atoi(row[248]));
e.bardeffect = static_cast<int16_t>(atoi(row[249]));
e.powersourcecapacity = static_cast<int32_t>(atoi(row[248]));
e.bardeffect = static_cast<int32_t>(atoi(row[249]));
e.bardeffecttype = static_cast<int16_t>(atoi(row[250]));
e.bardlevel2 = static_cast<int16_t>(atoi(row[251]));
e.bardlevel = static_cast<int16_t>(atoi(row[252]));
@@ -2563,7 +2563,7 @@ public:
e.damageshield = static_cast<int32_t>(atoi(row[52]));
e.deity = static_cast<int32_t>(atoi(row[53]));
e.delay = static_cast<int32_t>(atoi(row[54]));
e.augdistiller = static_cast<int32_t>(atoi(row[55]));
e.augdistiller = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
e.dotshielding = static_cast<int32_t>(atoi(row[56]));
e.dr = static_cast<int32_t>(atoi(row[57]));
e.clicktype = static_cast<int32_t>(atoi(row[58]));
@@ -2715,7 +2715,7 @@ public:
e.focusunk5 = static_cast<int32_t>(atoi(row[204]));
e.focusunk6 = row[205] ? row[205] : "";
e.focusunk7 = static_cast<int32_t>(atoi(row[206]));
e.scrollunk1 = static_cast<int32_t>(atoi(row[207]));
e.scrollunk1 = static_cast<uint32_t>(strtoul(row[207], nullptr, 10));
e.scrollunk2 = static_cast<int32_t>(atoi(row[208]));
e.scrollunk3 = static_cast<int32_t>(atoi(row[209]));
e.scrollunk4 = static_cast<int32_t>(atoi(row[210]));
@@ -2754,10 +2754,10 @@ public:
e.created = row[243] ? row[243] : "";
e.elitematerial = static_cast<int16_t>(atoi(row[244]));
e.ldonsellbackrate = static_cast<int16_t>(atoi(row[245]));
e.scriptfileid = static_cast<int16_t>(atoi(row[246]));
e.scriptfileid = static_cast<int32_t>(atoi(row[246]));
e.expendablearrow = static_cast<int16_t>(atoi(row[247]));
e.powersourcecapacity = static_cast<int16_t>(atoi(row[248]));
e.bardeffect = static_cast<int16_t>(atoi(row[249]));
e.powersourcecapacity = static_cast<int32_t>(atoi(row[248]));
e.bardeffect = static_cast<int32_t>(atoi(row[249]));
e.bardeffecttype = static_cast<int16_t>(atoi(row[250]));
e.bardlevel2 = static_cast<int16_t>(atoi(row[251]));
e.bardlevel = static_cast<int16_t>(atoi(row[252]));
@@ -2872,7 +2872,7 @@ public:
e.damageshield = static_cast<int32_t>(atoi(row[52]));
e.deity = static_cast<int32_t>(atoi(row[53]));
e.delay = static_cast<int32_t>(atoi(row[54]));
e.augdistiller = static_cast<int32_t>(atoi(row[55]));
e.augdistiller = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
e.dotshielding = static_cast<int32_t>(atoi(row[56]));
e.dr = static_cast<int32_t>(atoi(row[57]));
e.clicktype = static_cast<int32_t>(atoi(row[58]));
@@ -3024,7 +3024,7 @@ public:
e.focusunk5 = static_cast<int32_t>(atoi(row[204]));
e.focusunk6 = row[205] ? row[205] : "";
e.focusunk7 = static_cast<int32_t>(atoi(row[206]));
e.scrollunk1 = static_cast<int32_t>(atoi(row[207]));
e.scrollunk1 = static_cast<uint32_t>(strtoul(row[207], nullptr, 10));
e.scrollunk2 = static_cast<int32_t>(atoi(row[208]));
e.scrollunk3 = static_cast<int32_t>(atoi(row[209]));
e.scrollunk4 = static_cast<int32_t>(atoi(row[210]));
@@ -3063,10 +3063,10 @@ public:
e.created = row[243] ? row[243] : "";
e.elitematerial = static_cast<int16_t>(atoi(row[244]));
e.ldonsellbackrate = static_cast<int16_t>(atoi(row[245]));
e.scriptfileid = static_cast<int16_t>(atoi(row[246]));
e.scriptfileid = static_cast<int32_t>(atoi(row[246]));
e.expendablearrow = static_cast<int16_t>(atoi(row[247]));
e.powersourcecapacity = static_cast<int16_t>(atoi(row[248]));
e.bardeffect = static_cast<int16_t>(atoi(row[249]));
e.powersourcecapacity = static_cast<int32_t>(atoi(row[248]));
e.bardeffect = static_cast<int32_t>(atoi(row[249]));
e.bardeffecttype = static_cast<int16_t>(atoi(row[250]));
e.bardlevel2 = static_cast<int16_t>(atoi(row[251]));
e.bardlevel = static_cast<int16_t>(atoi(row[252]));
@@ -0,0 +1,344 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
*/
#ifndef EQEMU_BASE_KEYRING_REPOSITORY_H
#define EQEMU_BASE_KEYRING_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseKeyringRepository {
public:
struct Keyring {
uint32_t id;
int32_t char_id;
int32_t item_id;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"char_id",
"item_id",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"char_id",
"item_id",
};
}
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("keyring");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static Keyring NewEntity()
{
Keyring e{};
e.id = 0;
e.char_id = 0;
e.item_id = 0;
return e;
}
static Keyring GetKeyring(
const std::vector<Keyring> &keyrings,
int keyring_id
)
{
for (auto &keyring : keyrings) {
if (keyring.id == keyring_id) {
return keyring;
}
}
return NewEntity();
}
static Keyring FindOne(
Database& db,
int keyring_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
keyring_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
Keyring e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.char_id = static_cast<int32_t>(atoi(row[1]));
e.item_id = static_cast<int32_t>(atoi(row[2]));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int keyring_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
keyring_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const Keyring &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.char_id));
v.push_back(columns[2] + " = " + std::to_string(e.item_id));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static Keyring InsertOne(
Database& db,
Keyring e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.item_id));
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<Keyring> &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.char_id));
v.push_back(std::to_string(e.item_id));
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<Keyring> All(Database& db)
{
std::vector<Keyring> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
Keyring e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.char_id = static_cast<int32_t>(atoi(row[1]));
e.item_id = static_cast<int32_t>(atoi(row[2]));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<Keyring> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<Keyring> 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) {
Keyring e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.char_id = static_cast<int32_t>(atoi(row[1]));
e.item_id = static_cast<int32_t>(atoi(row[2]));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_KEYRING_REPOSITORY_H
@@ -66,8 +66,8 @@ public:
uint8_t armortint_red;
uint8_t armortint_green;
uint8_t armortint_blue;
int32_t d_melee_texture1;
int32_t d_melee_texture2;
uint32_t d_melee_texture1;
uint32_t d_melee_texture2;
std::string ammo_idfile;
uint8_t prim_melee_type;
uint8_t sec_melee_type;
@@ -583,7 +583,7 @@ public:
e.exp_mod = 100;
e.heroic_strikethrough = 0;
e.faction_amount = 0;
e.keeps_sold_items = 0;
e.keeps_sold_items = 1;
return e;
}
@@ -666,8 +666,8 @@ public:
e.armortint_red = static_cast<uint8_t>(strtoul(row[43], nullptr, 10));
e.armortint_green = static_cast<uint8_t>(strtoul(row[44], nullptr, 10));
e.armortint_blue = static_cast<uint8_t>(strtoul(row[45], nullptr, 10));
e.d_melee_texture1 = static_cast<int32_t>(atoi(row[46]));
e.d_melee_texture2 = static_cast<int32_t>(atoi(row[47]));
e.d_melee_texture1 = static_cast<uint32_t>(strtoul(row[46], nullptr, 10));
e.d_melee_texture2 = static_cast<uint32_t>(strtoul(row[47], nullptr, 10));
e.ammo_idfile = row[48] ? row[48] : "";
e.prim_melee_type = static_cast<uint8_t>(strtoul(row[49], nullptr, 10));
e.sec_melee_type = static_cast<uint8_t>(strtoul(row[50], nullptr, 10));
@@ -1289,8 +1289,8 @@ public:
e.armortint_red = static_cast<uint8_t>(strtoul(row[43], nullptr, 10));
e.armortint_green = static_cast<uint8_t>(strtoul(row[44], nullptr, 10));
e.armortint_blue = static_cast<uint8_t>(strtoul(row[45], nullptr, 10));
e.d_melee_texture1 = static_cast<int32_t>(atoi(row[46]));
e.d_melee_texture2 = static_cast<int32_t>(atoi(row[47]));
e.d_melee_texture1 = static_cast<uint32_t>(strtoul(row[46], nullptr, 10));
e.d_melee_texture2 = static_cast<uint32_t>(strtoul(row[47], nullptr, 10));
e.ammo_idfile = row[48] ? row[48] : "";
e.prim_melee_type = static_cast<uint8_t>(strtoul(row[49], nullptr, 10));
e.sec_melee_type = static_cast<uint8_t>(strtoul(row[50], nullptr, 10));
@@ -1440,8 +1440,8 @@ public:
e.armortint_red = static_cast<uint8_t>(strtoul(row[43], nullptr, 10));
e.armortint_green = static_cast<uint8_t>(strtoul(row[44], nullptr, 10));
e.armortint_blue = static_cast<uint8_t>(strtoul(row[45], nullptr, 10));
e.d_melee_texture1 = static_cast<int32_t>(atoi(row[46]));
e.d_melee_texture2 = static_cast<int32_t>(atoi(row[47]));
e.d_melee_texture1 = static_cast<uint32_t>(strtoul(row[46], nullptr, 10));
e.d_melee_texture2 = static_cast<uint32_t>(strtoul(row[47], nullptr, 10));
e.ammo_idfile = row[48] ? row[48] : "";
e.prim_melee_type = static_cast<uint8_t>(strtoul(row[49], nullptr, 10));
e.sec_melee_type = static_cast<uint8_t>(strtoul(row[50], nullptr, 10));
@@ -16,6 +16,7 @@
#include "../../strings.h"
#include <ctime>
class BaseObjectRepository {
public:
struct Object {
@@ -31,9 +32,9 @@ public:
std::string objectname;
int32_t type;
int32_t icon;
int32_t unknown08;
int32_t unknown10;
int32_t unknown20;
float size_percentage;
int32_t solid_type;
int32_t incline;
int32_t unknown24;
int32_t unknown60;
int32_t unknown64;
@@ -71,9 +72,9 @@ public:
"objectname",
"type",
"icon",
"unknown08",
"unknown10",
"unknown20",
"size_percentage",
"solid_type",
"incline",
"unknown24",
"unknown60",
"unknown64",
@@ -107,9 +108,9 @@ public:
"objectname",
"type",
"icon",
"unknown08",
"unknown10",
"unknown20",
"size_percentage",
"solid_type",
"incline",
"unknown24",
"unknown60",
"unknown64",
@@ -177,9 +178,9 @@ public:
e.objectname = "";
e.type = 0;
e.icon = 0;
e.unknown08 = 0;
e.unknown10 = 0;
e.unknown20 = 0;
e.size_percentage = 0;
e.solid_type = 0;
e.incline = 0;
e.unknown24 = 0;
e.unknown60 = 0;
e.unknown64 = 0;
@@ -220,8 +221,9 @@ public:
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
object_id
)
);
@@ -242,9 +244,9 @@ public:
e.objectname = row[9] ? row[9] : "";
e.type = static_cast<int32_t>(atoi(row[10]));
e.icon = static_cast<int32_t>(atoi(row[11]));
e.unknown08 = static_cast<int32_t>(atoi(row[12]));
e.unknown10 = static_cast<int32_t>(atoi(row[13]));
e.unknown20 = static_cast<int32_t>(atoi(row[14]));
e.size_percentage = strtof(row[12], nullptr);
e.solid_type = static_cast<int32_t>(atoi(row[13]));
e.incline = static_cast<int32_t>(atoi(row[14]));
e.unknown24 = static_cast<int32_t>(atoi(row[15]));
e.unknown60 = static_cast<int32_t>(atoi(row[16]));
e.unknown64 = static_cast<int32_t>(atoi(row[17]));
@@ -304,9 +306,9 @@ public:
v.push_back(columns[9] + " = '" + Strings::Escape(e.objectname) + "'");
v.push_back(columns[10] + " = " + std::to_string(e.type));
v.push_back(columns[11] + " = " + std::to_string(e.icon));
v.push_back(columns[12] + " = " + std::to_string(e.unknown08));
v.push_back(columns[13] + " = " + std::to_string(e.unknown10));
v.push_back(columns[14] + " = " + std::to_string(e.unknown20));
v.push_back(columns[12] + " = " + std::to_string(e.size_percentage));
v.push_back(columns[13] + " = " + std::to_string(e.solid_type));
v.push_back(columns[14] + " = " + std::to_string(e.incline));
v.push_back(columns[15] + " = " + std::to_string(e.unknown24));
v.push_back(columns[16] + " = " + std::to_string(e.unknown60));
v.push_back(columns[17] + " = " + std::to_string(e.unknown64));
@@ -355,9 +357,9 @@ public:
v.push_back("'" + Strings::Escape(e.objectname) + "'");
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.icon));
v.push_back(std::to_string(e.unknown08));
v.push_back(std::to_string(e.unknown10));
v.push_back(std::to_string(e.unknown20));
v.push_back(std::to_string(e.size_percentage));
v.push_back(std::to_string(e.solid_type));
v.push_back(std::to_string(e.incline));
v.push_back(std::to_string(e.unknown24));
v.push_back(std::to_string(e.unknown60));
v.push_back(std::to_string(e.unknown64));
@@ -414,9 +416,9 @@ public:
v.push_back("'" + Strings::Escape(e.objectname) + "'");
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.icon));
v.push_back(std::to_string(e.unknown08));
v.push_back(std::to_string(e.unknown10));
v.push_back(std::to_string(e.unknown20));
v.push_back(std::to_string(e.size_percentage));
v.push_back(std::to_string(e.solid_type));
v.push_back(std::to_string(e.incline));
v.push_back(std::to_string(e.unknown24));
v.push_back(std::to_string(e.unknown60));
v.push_back(std::to_string(e.unknown64));
@@ -477,9 +479,9 @@ public:
e.objectname = row[9] ? row[9] : "";
e.type = static_cast<int32_t>(atoi(row[10]));
e.icon = static_cast<int32_t>(atoi(row[11]));
e.unknown08 = static_cast<int32_t>(atoi(row[12]));
e.unknown10 = static_cast<int32_t>(atoi(row[13]));
e.unknown20 = static_cast<int32_t>(atoi(row[14]));
e.size_percentage = strtof(row[12], nullptr);
e.solid_type = static_cast<int32_t>(atoi(row[13]));
e.incline = static_cast<int32_t>(atoi(row[14]));
e.unknown24 = static_cast<int32_t>(atoi(row[15]));
e.unknown60 = static_cast<int32_t>(atoi(row[16]));
e.unknown64 = static_cast<int32_t>(atoi(row[17]));
@@ -531,9 +533,9 @@ public:
e.objectname = row[9] ? row[9] : "";
e.type = static_cast<int32_t>(atoi(row[10]));
e.icon = static_cast<int32_t>(atoi(row[11]));
e.unknown08 = static_cast<int32_t>(atoi(row[12]));
e.unknown10 = static_cast<int32_t>(atoi(row[13]));
e.unknown20 = static_cast<int32_t>(atoi(row[14]));
e.size_percentage = strtof(row[12], nullptr);
e.solid_type = static_cast<int32_t>(atoi(row[13]));
e.incline = static_cast<int32_t>(atoi(row[14]));
e.unknown24 = static_cast<int32_t>(atoi(row[15]));
e.unknown60 = static_cast<int32_t>(atoi(row[16]));
e.unknown64 = static_cast<int32_t>(atoi(row[17]));
@@ -16,6 +16,7 @@
#include "../../strings.h"
#include <ctime>
class BaseRaidDetailsRepository {
public:
struct RaidDetails {
@@ -23,6 +24,15 @@ public:
int32_t loottype;
int8_t locked;
std::string motd;
uint32_t marked_npc_1_entity_id;
uint32_t marked_npc_1_zone_id;
uint32_t marked_npc_1_instance_id;
uint32_t marked_npc_2_entity_id;
uint32_t marked_npc_2_zone_id;
uint32_t marked_npc_2_instance_id;
uint32_t marked_npc_3_entity_id;
uint32_t marked_npc_3_zone_id;
uint32_t marked_npc_3_instance_id;
};
static std::string PrimaryKey()
@@ -37,6 +47,15 @@ public:
"loottype",
"locked",
"motd",
"marked_npc_1_entity_id",
"marked_npc_1_zone_id",
"marked_npc_1_instance_id",
"marked_npc_2_entity_id",
"marked_npc_2_zone_id",
"marked_npc_2_instance_id",
"marked_npc_3_entity_id",
"marked_npc_3_zone_id",
"marked_npc_3_instance_id",
};
}
@@ -47,6 +66,15 @@ public:
"loottype",
"locked",
"motd",
"marked_npc_1_entity_id",
"marked_npc_1_zone_id",
"marked_npc_1_instance_id",
"marked_npc_2_entity_id",
"marked_npc_2_zone_id",
"marked_npc_2_instance_id",
"marked_npc_3_entity_id",
"marked_npc_3_zone_id",
"marked_npc_3_instance_id",
};
}
@@ -87,10 +115,19 @@ public:
{
RaidDetails e{};
e.raidid = 0;
e.loottype = 0;
e.locked = 0;
e.motd = "";
e.raidid = 0;
e.loottype = 0;
e.locked = 0;
e.motd = "";
e.marked_npc_1_entity_id = 0;
e.marked_npc_1_zone_id = 0;
e.marked_npc_1_instance_id = 0;
e.marked_npc_2_entity_id = 0;
e.marked_npc_2_zone_id = 0;
e.marked_npc_2_instance_id = 0;
e.marked_npc_3_entity_id = 0;
e.marked_npc_3_zone_id = 0;
e.marked_npc_3_instance_id = 0;
return e;
}
@@ -116,8 +153,9 @@ public:
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
raid_details_id
)
);
@@ -126,10 +164,19 @@ public:
if (results.RowCount() == 1) {
RaidDetails e{};
e.raidid = static_cast<int32_t>(atoi(row[0]));
e.loottype = static_cast<int32_t>(atoi(row[1]));
e.locked = static_cast<int8_t>(atoi(row[2]));
e.motd = row[3] ? row[3] : "";
e.raidid = static_cast<int32_t>(atoi(row[0]));
e.loottype = static_cast<int32_t>(atoi(row[1]));
e.locked = static_cast<int8_t>(atoi(row[2]));
e.motd = row[3] ? row[3] : "";
e.marked_npc_1_entity_id = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.marked_npc_1_zone_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.marked_npc_1_instance_id = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.marked_npc_2_entity_id = static_cast<uint32_t>(strtoul(row[7], nullptr, 10));
e.marked_npc_2_zone_id = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
e.marked_npc_2_instance_id = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
e.marked_npc_3_entity_id = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
e.marked_npc_3_zone_id = static_cast<uint32_t>(strtoul(row[11], nullptr, 10));
e.marked_npc_3_instance_id = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
return e;
}
@@ -167,6 +214,15 @@ public:
v.push_back(columns[1] + " = " + std::to_string(e.loottype));
v.push_back(columns[2] + " = " + std::to_string(e.locked));
v.push_back(columns[3] + " = '" + Strings::Escape(e.motd) + "'");
v.push_back(columns[4] + " = " + std::to_string(e.marked_npc_1_entity_id));
v.push_back(columns[5] + " = " + std::to_string(e.marked_npc_1_zone_id));
v.push_back(columns[6] + " = " + std::to_string(e.marked_npc_1_instance_id));
v.push_back(columns[7] + " = " + std::to_string(e.marked_npc_2_entity_id));
v.push_back(columns[8] + " = " + std::to_string(e.marked_npc_2_zone_id));
v.push_back(columns[9] + " = " + std::to_string(e.marked_npc_2_instance_id));
v.push_back(columns[10] + " = " + std::to_string(e.marked_npc_3_entity_id));
v.push_back(columns[11] + " = " + std::to_string(e.marked_npc_3_zone_id));
v.push_back(columns[12] + " = " + std::to_string(e.marked_npc_3_instance_id));
auto results = db.QueryDatabase(
fmt::format(
@@ -192,6 +248,15 @@ public:
v.push_back(std::to_string(e.loottype));
v.push_back(std::to_string(e.locked));
v.push_back("'" + Strings::Escape(e.motd) + "'");
v.push_back(std::to_string(e.marked_npc_1_entity_id));
v.push_back(std::to_string(e.marked_npc_1_zone_id));
v.push_back(std::to_string(e.marked_npc_1_instance_id));
v.push_back(std::to_string(e.marked_npc_2_entity_id));
v.push_back(std::to_string(e.marked_npc_2_zone_id));
v.push_back(std::to_string(e.marked_npc_2_instance_id));
v.push_back(std::to_string(e.marked_npc_3_entity_id));
v.push_back(std::to_string(e.marked_npc_3_zone_id));
v.push_back(std::to_string(e.marked_npc_3_instance_id));
auto results = db.QueryDatabase(
fmt::format(
@@ -225,6 +290,15 @@ public:
v.push_back(std::to_string(e.loottype));
v.push_back(std::to_string(e.locked));
v.push_back("'" + Strings::Escape(e.motd) + "'");
v.push_back(std::to_string(e.marked_npc_1_entity_id));
v.push_back(std::to_string(e.marked_npc_1_zone_id));
v.push_back(std::to_string(e.marked_npc_1_instance_id));
v.push_back(std::to_string(e.marked_npc_2_entity_id));
v.push_back(std::to_string(e.marked_npc_2_zone_id));
v.push_back(std::to_string(e.marked_npc_2_instance_id));
v.push_back(std::to_string(e.marked_npc_3_entity_id));
v.push_back(std::to_string(e.marked_npc_3_zone_id));
v.push_back(std::to_string(e.marked_npc_3_instance_id));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -258,10 +332,19 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
RaidDetails e{};
e.raidid = static_cast<int32_t>(atoi(row[0]));
e.loottype = static_cast<int32_t>(atoi(row[1]));
e.locked = static_cast<int8_t>(atoi(row[2]));
e.motd = row[3] ? row[3] : "";
e.raidid = static_cast<int32_t>(atoi(row[0]));
e.loottype = static_cast<int32_t>(atoi(row[1]));
e.locked = static_cast<int8_t>(atoi(row[2]));
e.motd = row[3] ? row[3] : "";
e.marked_npc_1_entity_id = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.marked_npc_1_zone_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.marked_npc_1_instance_id = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.marked_npc_2_entity_id = static_cast<uint32_t>(strtoul(row[7], nullptr, 10));
e.marked_npc_2_zone_id = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
e.marked_npc_2_instance_id = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
e.marked_npc_3_entity_id = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
e.marked_npc_3_zone_id = static_cast<uint32_t>(strtoul(row[11], nullptr, 10));
e.marked_npc_3_instance_id = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
all_entries.push_back(e);
}
@@ -286,10 +369,19 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
RaidDetails e{};
e.raidid = static_cast<int32_t>(atoi(row[0]));
e.loottype = static_cast<int32_t>(atoi(row[1]));
e.locked = static_cast<int8_t>(atoi(row[2]));
e.motd = row[3] ? row[3] : "";
e.raidid = static_cast<int32_t>(atoi(row[0]));
e.loottype = static_cast<int32_t>(atoi(row[1]));
e.locked = static_cast<int8_t>(atoi(row[2]));
e.motd = row[3] ? row[3] : "";
e.marked_npc_1_entity_id = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.marked_npc_1_zone_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.marked_npc_1_instance_id = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.marked_npc_2_entity_id = static_cast<uint32_t>(strtoul(row[7], nullptr, 10));
e.marked_npc_2_zone_id = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
e.marked_npc_2_instance_id = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
e.marked_npc_3_entity_id = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
e.marked_npc_3_zone_id = static_cast<uint32_t>(strtoul(row[11], nullptr, 10));
e.marked_npc_3_instance_id = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
all_entries.push_back(e);
}
@@ -31,6 +31,9 @@ public:
int8_t isgroupleader;
int8_t israidleader;
int8_t islooter;
uint8_t is_marker;
uint8_t is_assister;
std::string note;
};
static std::string PrimaryKey()
@@ -52,6 +55,9 @@ public:
"isgroupleader",
"israidleader",
"islooter",
"is_marker",
"is_assister",
"note",
};
}
@@ -69,6 +75,9 @@ public:
"isgroupleader",
"israidleader",
"islooter",
"is_marker",
"is_assister",
"note",
};
}
@@ -120,6 +129,9 @@ public:
e.isgroupleader = 0;
e.israidleader = 0;
e.islooter = 0;
e.is_marker = 0;
e.is_assister = 0;
e.note = "";
return e;
}
@@ -167,6 +179,9 @@ public:
e.isgroupleader = static_cast<int8_t>(atoi(row[8]));
e.israidleader = static_cast<int8_t>(atoi(row[9]));
e.islooter = static_cast<int8_t>(atoi(row[10]));
e.is_marker = static_cast<uint8_t>(strtoul(row[11], nullptr, 10));
e.is_assister = static_cast<uint8_t>(strtoul(row[12], nullptr, 10));
e.note = row[13] ? row[13] : "";
return e;
}
@@ -210,6 +225,9 @@ public:
v.push_back(columns[8] + " = " + std::to_string(e.isgroupleader));
v.push_back(columns[9] + " = " + std::to_string(e.israidleader));
v.push_back(columns[10] + " = " + std::to_string(e.islooter));
v.push_back(columns[11] + " = " + std::to_string(e.is_marker));
v.push_back(columns[12] + " = " + std::to_string(e.is_assister));
v.push_back(columns[13] + " = '" + Strings::Escape(e.note) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -242,6 +260,9 @@ public:
v.push_back(std::to_string(e.isgroupleader));
v.push_back(std::to_string(e.israidleader));
v.push_back(std::to_string(e.islooter));
v.push_back(std::to_string(e.is_marker));
v.push_back(std::to_string(e.is_assister));
v.push_back("'" + Strings::Escape(e.note) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -282,6 +303,9 @@ public:
v.push_back(std::to_string(e.isgroupleader));
v.push_back(std::to_string(e.israidleader));
v.push_back(std::to_string(e.islooter));
v.push_back(std::to_string(e.is_marker));
v.push_back(std::to_string(e.is_assister));
v.push_back("'" + Strings::Escape(e.note) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -326,6 +350,9 @@ public:
e.isgroupleader = static_cast<int8_t>(atoi(row[8]));
e.israidleader = static_cast<int8_t>(atoi(row[9]));
e.islooter = static_cast<int8_t>(atoi(row[10]));
e.is_marker = static_cast<uint8_t>(strtoul(row[11], nullptr, 10));
e.is_assister = static_cast<uint8_t>(strtoul(row[12], nullptr, 10));
e.note = row[13] ? row[13] : "";
all_entries.push_back(e);
}
@@ -361,6 +388,9 @@ public:
e.isgroupleader = static_cast<int8_t>(atoi(row[8]));
e.israidleader = static_cast<int8_t>(atoi(row[9]));
e.islooter = static_cast<int8_t>(atoi(row[10]));
e.is_marker = static_cast<uint8_t>(strtoul(row[11], nullptr, 10));
e.is_assister = static_cast<uint8_t>(strtoul(row[12], nullptr, 10));
e.note = row[13] ? row[13] : "";
all_entries.push_back(e);
}
@@ -0,0 +1,354 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
*/
#ifndef EQEMU_BASE_SPAWN2_DISABLED_REPOSITORY_H
#define EQEMU_BASE_SPAWN2_DISABLED_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseSpawn2DisabledRepository {
public:
struct Spawn2Disabled {
int64_t id;
int32_t spawn2_id;
int32_t instance_id;
int16_t disabled;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"spawn2_id",
"instance_id",
"disabled",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"spawn2_id",
"instance_id",
"disabled",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("spawn2_disabled");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static Spawn2Disabled NewEntity()
{
Spawn2Disabled e{};
e.id = 0;
e.spawn2_id = 0;
e.instance_id = 0;
e.disabled = 0;
return e;
}
static Spawn2Disabled GetSpawn2Disabled(
const std::vector<Spawn2Disabled> &spawn2_disableds,
int spawn2_disabled_id
)
{
for (auto &spawn2_disabled : spawn2_disableds) {
if (spawn2_disabled.id == spawn2_disabled_id) {
return spawn2_disabled;
}
}
return NewEntity();
}
static Spawn2Disabled FindOne(
Database& db,
int spawn2_disabled_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
spawn2_disabled_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
Spawn2Disabled e{};
e.id = strtoll(row[0], nullptr, 10);
e.spawn2_id = static_cast<int32_t>(atoi(row[1]));
e.instance_id = static_cast<int32_t>(atoi(row[2]));
e.disabled = static_cast<int16_t>(atoi(row[3]));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int spawn2_disabled_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
spawn2_disabled_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const Spawn2Disabled &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.spawn2_id));
v.push_back(columns[2] + " = " + std::to_string(e.instance_id));
v.push_back(columns[3] + " = " + std::to_string(e.disabled));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static Spawn2Disabled InsertOne(
Database& db,
Spawn2Disabled e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.spawn2_id));
v.push_back(std::to_string(e.instance_id));
v.push_back(std::to_string(e.disabled));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<Spawn2Disabled> &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.spawn2_id));
v.push_back(std::to_string(e.instance_id));
v.push_back(std::to_string(e.disabled));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<Spawn2Disabled> All(Database& db)
{
std::vector<Spawn2Disabled> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
Spawn2Disabled e{};
e.id = strtoll(row[0], nullptr, 10);
e.spawn2_id = static_cast<int32_t>(atoi(row[1]));
e.instance_id = static_cast<int32_t>(atoi(row[2]));
e.disabled = static_cast<int16_t>(atoi(row[3]));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<Spawn2Disabled> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<Spawn2Disabled> 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) {
Spawn2Disabled e{};
e.id = strtoll(row[0], nullptr, 10);
e.spawn2_id = static_cast<int32_t>(atoi(row[1]));
e.instance_id = static_cast<int32_t>(atoi(row[2]));
e.disabled = static_cast<int16_t>(atoi(row[3]));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_SPAWN2_DISABLED_REPOSITORY_H
@@ -16,6 +16,7 @@
#include "../../strings.h"
#include <ctime>
class BaseSpawn2Repository {
public:
struct Spawn2 {
@@ -33,7 +34,6 @@ public:
int8_t path_when_zone_idle;
uint32_t _condition;
int32_t cond_value;
uint8_t enabled;
uint8_t animation;
int8_t min_expansion;
int8_t max_expansion;
@@ -63,7 +63,6 @@ public:
"path_when_zone_idle",
"_condition",
"cond_value",
"enabled",
"animation",
"min_expansion",
"max_expansion",
@@ -89,7 +88,6 @@ public:
"path_when_zone_idle",
"_condition",
"cond_value",
"enabled",
"animation",
"min_expansion",
"max_expansion",
@@ -149,7 +147,6 @@ public:
e.path_when_zone_idle = 0;
e._condition = 0;
e.cond_value = 1;
e.enabled = 1;
e.animation = 0;
e.min_expansion = -1;
e.max_expansion = -1;
@@ -180,8 +177,9 @@ public:
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
spawn2_id
)
);
@@ -204,12 +202,11 @@ public:
e.path_when_zone_idle = static_cast<int8_t>(atoi(row[11]));
e._condition = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.cond_value = static_cast<int32_t>(atoi(row[13]));
e.enabled = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
e.animation = static_cast<uint8_t>(strtoul(row[15], nullptr, 10));
e.min_expansion = static_cast<int8_t>(atoi(row[16]));
e.max_expansion = static_cast<int8_t>(atoi(row[17]));
e.content_flags = row[18] ? row[18] : "";
e.content_flags_disabled = row[19] ? row[19] : "";
e.animation = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
e.min_expansion = static_cast<int8_t>(atoi(row[15]));
e.max_expansion = static_cast<int8_t>(atoi(row[16]));
e.content_flags = row[17] ? row[17] : "";
e.content_flags_disabled = row[18] ? row[18] : "";
return e;
}
@@ -256,12 +253,11 @@ public:
v.push_back(columns[11] + " = " + std::to_string(e.path_when_zone_idle));
v.push_back(columns[12] + " = " + std::to_string(e._condition));
v.push_back(columns[13] + " = " + std::to_string(e.cond_value));
v.push_back(columns[14] + " = " + std::to_string(e.enabled));
v.push_back(columns[15] + " = " + std::to_string(e.animation));
v.push_back(columns[16] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[17] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[18] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[19] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
v.push_back(columns[14] + " = " + std::to_string(e.animation));
v.push_back(columns[15] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[16] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[17] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[18] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -297,7 +293,6 @@ public:
v.push_back(std::to_string(e.path_when_zone_idle));
v.push_back(std::to_string(e._condition));
v.push_back(std::to_string(e.cond_value));
v.push_back(std::to_string(e.enabled));
v.push_back(std::to_string(e.animation));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
@@ -346,7 +341,6 @@ public:
v.push_back(std::to_string(e.path_when_zone_idle));
v.push_back(std::to_string(e._condition));
v.push_back(std::to_string(e.cond_value));
v.push_back(std::to_string(e.enabled));
v.push_back(std::to_string(e.animation));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
@@ -399,12 +393,11 @@ public:
e.path_when_zone_idle = static_cast<int8_t>(atoi(row[11]));
e._condition = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.cond_value = static_cast<int32_t>(atoi(row[13]));
e.enabled = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
e.animation = static_cast<uint8_t>(strtoul(row[15], nullptr, 10));
e.min_expansion = static_cast<int8_t>(atoi(row[16]));
e.max_expansion = static_cast<int8_t>(atoi(row[17]));
e.content_flags = row[18] ? row[18] : "";
e.content_flags_disabled = row[19] ? row[19] : "";
e.animation = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
e.min_expansion = static_cast<int8_t>(atoi(row[15]));
e.max_expansion = static_cast<int8_t>(atoi(row[16]));
e.content_flags = row[17] ? row[17] : "";
e.content_flags_disabled = row[18] ? row[18] : "";
all_entries.push_back(e);
}
@@ -443,12 +436,11 @@ public:
e.path_when_zone_idle = static_cast<int8_t>(atoi(row[11]));
e._condition = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.cond_value = static_cast<int32_t>(atoi(row[13]));
e.enabled = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
e.animation = static_cast<uint8_t>(strtoul(row[15], nullptr, 10));
e.min_expansion = static_cast<int8_t>(atoi(row[16]));
e.max_expansion = static_cast<int8_t>(atoi(row[17]));
e.content_flags = row[18] ? row[18] : "";
e.content_flags_disabled = row[19] ? row[19] : "";
e.animation = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
e.min_expansion = static_cast<int8_t>(atoi(row[15]));
e.max_expansion = static_cast<int8_t>(atoi(row[16]));
e.content_flags = row[17] ? row[17] : "";
e.content_flags_disabled = row[18] ? row[18] : "";
all_entries.push_back(e);
}
@@ -16,6 +16,7 @@
#include "../../strings.h"
#include <ctime>
class BaseSpawnentryRepository {
public:
struct Spawnentry {
@@ -23,6 +24,8 @@ public:
int32_t npcID;
int16_t chance;
int32_t condition_value_filter;
int16_t min_time;
int16_t max_time;
int8_t min_expansion;
int8_t max_expansion;
std::string content_flags;
@@ -41,6 +44,8 @@ public:
"npcID",
"chance",
"condition_value_filter",
"min_time",
"max_time",
"min_expansion",
"max_expansion",
"content_flags",
@@ -55,6 +60,8 @@ public:
"npcID",
"chance",
"condition_value_filter",
"min_time",
"max_time",
"min_expansion",
"max_expansion",
"content_flags",
@@ -103,6 +110,8 @@ public:
e.npcID = 0;
e.chance = 0;
e.condition_value_filter = 1;
e.min_time = 0;
e.max_time = 0;
e.min_expansion = -1;
e.max_expansion = -1;
e.content_flags = "";
@@ -132,8 +141,9 @@ public:
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
spawnentry_id
)
);
@@ -146,10 +156,12 @@ public:
e.npcID = static_cast<int32_t>(atoi(row[1]));
e.chance = static_cast<int16_t>(atoi(row[2]));
e.condition_value_filter = static_cast<int32_t>(atoi(row[3]));
e.min_expansion = static_cast<int8_t>(atoi(row[4]));
e.max_expansion = static_cast<int8_t>(atoi(row[5]));
e.content_flags = row[6] ? row[6] : "";
e.content_flags_disabled = row[7] ? row[7] : "";
e.min_time = static_cast<int16_t>(atoi(row[4]));
e.max_time = static_cast<int16_t>(atoi(row[5]));
e.min_expansion = static_cast<int8_t>(atoi(row[6]));
e.max_expansion = static_cast<int8_t>(atoi(row[7]));
e.content_flags = row[8] ? row[8] : "";
e.content_flags_disabled = row[9] ? row[9] : "";
return e;
}
@@ -187,10 +199,12 @@ public:
v.push_back(columns[1] + " = " + std::to_string(e.npcID));
v.push_back(columns[2] + " = " + std::to_string(e.chance));
v.push_back(columns[3] + " = " + std::to_string(e.condition_value_filter));
v.push_back(columns[4] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[5] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[6] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[7] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
v.push_back(columns[4] + " = " + std::to_string(e.min_time));
v.push_back(columns[5] + " = " + std::to_string(e.max_time));
v.push_back(columns[6] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[7] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[8] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[9] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -216,6 +230,8 @@ public:
v.push_back(std::to_string(e.npcID));
v.push_back(std::to_string(e.chance));
v.push_back(std::to_string(e.condition_value_filter));
v.push_back(std::to_string(e.min_time));
v.push_back(std::to_string(e.max_time));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
@@ -253,6 +269,8 @@ public:
v.push_back(std::to_string(e.npcID));
v.push_back(std::to_string(e.chance));
v.push_back(std::to_string(e.condition_value_filter));
v.push_back(std::to_string(e.min_time));
v.push_back(std::to_string(e.max_time));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
@@ -294,10 +312,12 @@ public:
e.npcID = static_cast<int32_t>(atoi(row[1]));
e.chance = static_cast<int16_t>(atoi(row[2]));
e.condition_value_filter = static_cast<int32_t>(atoi(row[3]));
e.min_expansion = static_cast<int8_t>(atoi(row[4]));
e.max_expansion = static_cast<int8_t>(atoi(row[5]));
e.content_flags = row[6] ? row[6] : "";
e.content_flags_disabled = row[7] ? row[7] : "";
e.min_time = static_cast<int16_t>(atoi(row[4]));
e.max_time = static_cast<int16_t>(atoi(row[5]));
e.min_expansion = static_cast<int8_t>(atoi(row[6]));
e.max_expansion = static_cast<int8_t>(atoi(row[7]));
e.content_flags = row[8] ? row[8] : "";
e.content_flags_disabled = row[9] ? row[9] : "";
all_entries.push_back(e);
}
@@ -326,10 +346,12 @@ public:
e.npcID = static_cast<int32_t>(atoi(row[1]));
e.chance = static_cast<int16_t>(atoi(row[2]));
e.condition_value_filter = static_cast<int32_t>(atoi(row[3]));
e.min_expansion = static_cast<int8_t>(atoi(row[4]));
e.max_expansion = static_cast<int8_t>(atoi(row[5]));
e.content_flags = row[6] ? row[6] : "";
e.content_flags_disabled = row[7] ? row[7] : "";
e.min_time = static_cast<int16_t>(atoi(row[4]));
e.max_time = static_cast<int16_t>(atoi(row[5]));
e.min_expansion = static_cast<int8_t>(atoi(row[6]));
e.max_expansion = static_cast<int8_t>(atoi(row[7]));
e.content_flags = row[8] ? row[8] : "";
e.content_flags_disabled = row[9] ? row[9] : "";
all_entries.push_back(e);
}
@@ -16,17 +16,18 @@
#include "../../strings.h"
#include <ctime>
class BaseStartingItemsRepository {
public:
struct StartingItems {
uint32_t id;
int32_t race;
int32_t class_;
int32_t deityid;
int32_t zoneid;
int32_t itemid;
std::string race_list;
std::string class_list;
std::string deity_list;
std::string zone_id_list;
uint32_t item_id;
uint8_t item_charges;
int8_t gm;
uint8_t gm;
int32_t slot;
int8_t min_expansion;
int8_t max_expansion;
@@ -43,11 +44,11 @@ public:
{
return {
"id",
"race",
"`class`",
"deityid",
"zoneid",
"itemid",
"race_list",
"class_list",
"deity_list",
"zone_id_list",
"item_id",
"item_charges",
"gm",
"slot",
@@ -62,11 +63,11 @@ public:
{
return {
"id",
"race",
"`class`",
"deityid",
"zoneid",
"itemid",
"race_list",
"class_list",
"deity_list",
"zone_id_list",
"item_id",
"item_charges",
"gm",
"slot",
@@ -115,11 +116,11 @@ public:
StartingItems e{};
e.id = 0;
e.race = 0;
e.class_ = 0;
e.deityid = 0;
e.zoneid = 0;
e.itemid = 0;
e.race_list = "";
e.class_list = "";
e.deity_list = "";
e.zone_id_list = "";
e.item_id = 0;
e.item_charges = 1;
e.gm = 0;
e.slot = -1;
@@ -152,8 +153,9 @@ public:
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
starting_items_id
)
);
@@ -163,13 +165,13 @@ public:
StartingItems e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.race = static_cast<int32_t>(atoi(row[1]));
e.class_ = static_cast<int32_t>(atoi(row[2]));
e.deityid = static_cast<int32_t>(atoi(row[3]));
e.zoneid = static_cast<int32_t>(atoi(row[4]));
e.itemid = static_cast<int32_t>(atoi(row[5]));
e.race_list = row[1] ? row[1] : "";
e.class_list = row[2] ? row[2] : "";
e.deity_list = row[3] ? row[3] : "";
e.zone_id_list = row[4] ? row[4] : "";
e.item_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.item_charges = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.gm = static_cast<int8_t>(atoi(row[7]));
e.gm = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.slot = static_cast<int32_t>(atoi(row[8]));
e.min_expansion = static_cast<int8_t>(atoi(row[9]));
e.max_expansion = static_cast<int8_t>(atoi(row[10]));
@@ -208,11 +210,11 @@ public:
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.race));
v.push_back(columns[2] + " = " + std::to_string(e.class_));
v.push_back(columns[3] + " = " + std::to_string(e.deityid));
v.push_back(columns[4] + " = " + std::to_string(e.zoneid));
v.push_back(columns[5] + " = " + std::to_string(e.itemid));
v.push_back(columns[1] + " = '" + Strings::Escape(e.race_list) + "'");
v.push_back(columns[2] + " = '" + Strings::Escape(e.class_list) + "'");
v.push_back(columns[3] + " = '" + Strings::Escape(e.deity_list) + "'");
v.push_back(columns[4] + " = '" + Strings::Escape(e.zone_id_list) + "'");
v.push_back(columns[5] + " = " + std::to_string(e.item_id));
v.push_back(columns[6] + " = " + std::to_string(e.item_charges));
v.push_back(columns[7] + " = " + std::to_string(e.gm));
v.push_back(columns[8] + " = " + std::to_string(e.slot));
@@ -242,11 +244,11 @@ public:
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.race));
v.push_back(std::to_string(e.class_));
v.push_back(std::to_string(e.deityid));
v.push_back(std::to_string(e.zoneid));
v.push_back(std::to_string(e.itemid));
v.push_back("'" + Strings::Escape(e.race_list) + "'");
v.push_back("'" + Strings::Escape(e.class_list) + "'");
v.push_back("'" + Strings::Escape(e.deity_list) + "'");
v.push_back("'" + Strings::Escape(e.zone_id_list) + "'");
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.gm));
v.push_back(std::to_string(e.slot));
@@ -284,11 +286,11 @@ public:
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.race));
v.push_back(std::to_string(e.class_));
v.push_back(std::to_string(e.deityid));
v.push_back(std::to_string(e.zoneid));
v.push_back(std::to_string(e.itemid));
v.push_back("'" + Strings::Escape(e.race_list) + "'");
v.push_back("'" + Strings::Escape(e.class_list) + "'");
v.push_back("'" + Strings::Escape(e.deity_list) + "'");
v.push_back("'" + Strings::Escape(e.zone_id_list) + "'");
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.gm));
v.push_back(std::to_string(e.slot));
@@ -330,13 +332,13 @@ public:
StartingItems e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.race = static_cast<int32_t>(atoi(row[1]));
e.class_ = static_cast<int32_t>(atoi(row[2]));
e.deityid = static_cast<int32_t>(atoi(row[3]));
e.zoneid = static_cast<int32_t>(atoi(row[4]));
e.itemid = static_cast<int32_t>(atoi(row[5]));
e.race_list = row[1] ? row[1] : "";
e.class_list = row[2] ? row[2] : "";
e.deity_list = row[3] ? row[3] : "";
e.zone_id_list = row[4] ? row[4] : "";
e.item_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.item_charges = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.gm = static_cast<int8_t>(atoi(row[7]));
e.gm = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.slot = static_cast<int32_t>(atoi(row[8]));
e.min_expansion = static_cast<int8_t>(atoi(row[9]));
e.max_expansion = static_cast<int8_t>(atoi(row[10]));
@@ -367,13 +369,13 @@ public:
StartingItems e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.race = static_cast<int32_t>(atoi(row[1]));
e.class_ = static_cast<int32_t>(atoi(row[2]));
e.deityid = static_cast<int32_t>(atoi(row[3]));
e.zoneid = static_cast<int32_t>(atoi(row[4]));
e.itemid = static_cast<int32_t>(atoi(row[5]));
e.race_list = row[1] ? row[1] : "";
e.class_list = row[2] ? row[2] : "";
e.deity_list = row[3] ? row[3] : "";
e.zone_id_list = row[4] ? row[4] : "";
e.item_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.item_charges = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.gm = static_cast<int8_t>(atoi(row[7]));
e.gm = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.slot = static_cast<int32_t>(atoi(row[8]));
e.min_expansion = static_cast<int8_t>(atoi(row[9]));
e.max_expansion = static_cast<int8_t>(atoi(row[10]));
@@ -0,0 +1,50 @@
#ifndef EQEMU_BOT_STARTING_ITEMS_REPOSITORY_H
#define EQEMU_BOT_STARTING_ITEMS_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_bot_starting_items_repository.h"
class BotStartingItemsRepository: public BaseBotStartingItemsRepository {
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
*
* BotStartingItemsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* BotStartingItemsRepository::GetWhereNeverExpires()
* BotStartingItemsRepository::GetWhereXAndY()
* BotStartingItemsRepository::DeleteWhereXAndY()
*
* Most of the above could be covered by base methods, but if you as a developer
* find yourself re-using logic for other parts of the code, its best to just make a
* method that can be re-used easily elsewhere especially if it can use a base repository
* method and encapsulate filters there
*/
// Custom extended repository methods here
};
#endif //EQEMU_BOT_STARTING_ITEMS_REPOSITORY_H
@@ -0,0 +1,50 @@
#ifndef EQEMU_CHARACTER_STATS_RECORD_REPOSITORY_H
#define EQEMU_CHARACTER_STATS_RECORD_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_character_stats_record_repository.h"
class CharacterStatsRecordRepository: public BaseCharacterStatsRecordRepository {
public:
/**
* This file was auto generated and can be modified and extended upon
*
* Base repository methods are automatically
* generated in the "base" version of this repository. The base repository
* is immutable and to be left untouched, while methods in this class
* are used as extension methods for more specific persistence-layer
* accessors or mutators.
*
* Base Methods (Subject to be expanded upon in time)
*
* Note: Not all tables are designed appropriately to fit functionality with all base methods
*
* InsertOne
* UpdateOne
* DeleteOne
* FindOne
* GetWhere(std::string where_filter)
* DeleteWhere(std::string where_filter)
* InsertMany
* All
*
* Example custom methods in a repository
*
* CharacterStatsRecordRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* CharacterStatsRecordRepository::GetWhereNeverExpires()
* CharacterStatsRecordRepository::GetWhereXAndY()
* CharacterStatsRecordRepository::DeleteWhereXAndY()
*
* Most of the above could be covered by base methods, but if you as a developer
* find yourself re-using logic for other parts of the code, its best to just make a
* method that can be re-used easily elsewhere especially if it can use a base repository
* method and encapsulate filters there
*/
// Custom extended repository methods here
};
#endif //EQEMU_CHARACTER_STATS_RECORD_REPOSITORY_H
@@ -0,0 +1,223 @@
#ifndef EQEMU_COMMAND_SUBSETTINGS_REPOSITORY_H
#define EQEMU_COMMAND_SUBSETTINGS_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_command_subsettings_repository.h"
class CommandSubsettingsRepository: public BaseCommandSubsettingsRepository {
public:
/**
* This file was auto generated and can be modified and extended upon
*
* Base repository methods are automatically
* generated in the "base" version of this repository. The base repository
* is immutable and to be left untouched, while methods in this class
* are used as extension methods for more specific persistence-layer
* accessors or mutators.
*
* Base Methods (Subject to be expanded upon in time)
*
* Note: Not all tables are designed appropriately to fit functionality with all base methods
*
* InsertOne
* UpdateOne
* DeleteOne
* FindOne
* GetWhere(std::string where_filter)
* DeleteWhere(std::string where_filter)
* InsertMany
* All
*
* Example custom methods in a repository
*
* CommandSubsettingsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* CommandSubsettingsRepository::GetWhereNeverExpires()
* CommandSubsettingsRepository::GetWhereXAndY()
* CommandSubsettingsRepository::DeleteWhereXAndY()
*
* Most of the above could be covered by base methods, but if you as a developer
* find yourself re-using logic for other parts of the code, its best to just make a
* method that can be re-used easily elsewhere especially if it can use a base repository
* method and encapsulate filters there
*/
// Custom extended repository methods here
static std::vector<CommandSubsettingsRepository::CommandSubsettings> GetAll(Database& db)
{
// these are the base definitions for command_subsettings and can be over-ridden by the database
std::vector<CommandSubsettingsRepository::CommandSubsettings> static_records = {
{.parent_command = "find", .sub_command = "aa", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findaa"},
{.parent_command = "find", .sub_command = "character", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findcharacter"},
{.parent_command = "find", .sub_command = "class", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findclass"},
{.parent_command = "find", .sub_command = "currency", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findcurrency"},
{.parent_command = "find", .sub_command = "deity", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "finddeity"},
{.parent_command = "find", .sub_command = "emote", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findemote"},
{.parent_command = "find", .sub_command = "faction", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findfaction"},
{.parent_command = "find", .sub_command = "item", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fi|finditem|itemsearch"},
{.parent_command = "find", .sub_command = "language", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findlanguage"},
{.parent_command = "find", .sub_command = "npc_type", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fn|findnpc|findnpctype"},
{.parent_command = "find", .sub_command = "race", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findrace"},
{.parent_command = "find", .sub_command = "recipe", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findrecipe"},
{.parent_command = "find", .sub_command = "skill", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findskill"},
{.parent_command = "find", .sub_command = "spell", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fs|findspell"},
{.parent_command = "find", .sub_command = "task", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findtask"},
{.parent_command = "find", .sub_command = "zone", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fz|findzone"},
{.parent_command = "set", .sub_command = "aa_exp", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setaaxp|setaaexp"},
{.parent_command = "set", .sub_command = "aa_points", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setaapts|setaapoints"},
{.parent_command = "set", .sub_command = "adventure_points", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setadventurepoints"},
{.parent_command = "set", .sub_command = "alternate_currency", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setaltcurrency"},
{.parent_command = "set", .sub_command = "animation", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setanim"},
{.parent_command = "set", .sub_command = "anon", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setanon"},
{.parent_command = "set", .sub_command = "bind", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "bind"},
{.parent_command = "set", .sub_command = "checksum", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "updatechecksum"},
{.parent_command = "set", .sub_command = "class_permanent", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "permaclass"},
{.parent_command = "set", .sub_command = "crystals", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setcrystals"},
{.parent_command = "set", .sub_command = "date", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "date"},
{.parent_command = "set", .sub_command = "endurance", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setendurance"},
{.parent_command = "set", .sub_command = "endurance_full", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "endurance"},
{.parent_command = "set", .sub_command = "exp", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setxp|setexp"},
{.parent_command = "set", .sub_command = "faction", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setfaction"},
{.parent_command = "set", .sub_command = "flymode", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "flymode"},
{.parent_command = "set", .sub_command = "freeze", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "freeze|unfreeze"},
{.parent_command = "set", .sub_command = "gender", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "gender"},
{.parent_command = "set", .sub_command = "gender_permanent", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "permagender"},
{.parent_command = "set", .sub_command = "gm", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "gm"},
{.parent_command = "set", .sub_command = "gm_speed", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "gmspeed"},
{.parent_command = "set", .sub_command = "gm_status", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "flag"},
{.parent_command = "set", .sub_command = "god_mode", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "godmode"},
{.parent_command = "set", .sub_command = "haste", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "haste"},
{.parent_command = "set", .sub_command = "hero_model", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "heromodel"},
{.parent_command = "set", .sub_command = "hide_me", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "hideme"},
{.parent_command = "set", .sub_command = "hp", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "sethp"},
{.parent_command = "set", .sub_command = "hp_full", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "heal"},
{.parent_command = "set", .sub_command = "invulnerable", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "invul|invulnerable"},
{.parent_command = "set", .sub_command = "language", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setlanguage"},
{.parent_command = "set", .sub_command = "last_name", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "lastname"},
{.parent_command = "set", .sub_command = "level", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "level"},
{.parent_command = "set", .sub_command = "loginserver_info", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setlsinfo"},
{.parent_command = "set", .sub_command = "mana", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setmana"},
{.parent_command = "set", .sub_command = "mana_full", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "mana"},
{.parent_command = "set", .sub_command = "motd", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "motd"},
{.parent_command = "set", .sub_command = "name", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "name"},
{.parent_command = "set", .sub_command = "ooc_mute", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "oocmute"},
{.parent_command = "set", .sub_command = "password", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setpass"},
{.parent_command = "set", .sub_command = "pvp", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "pvp"},
{.parent_command = "set", .sub_command = "pvp_points", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setpvppoints"},
{.parent_command = "set", .sub_command = "race", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "race"},
{.parent_command = "set", .sub_command = "race_permanent", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "permarace"},
{.parent_command = "set", .sub_command = "server_locked", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "lock|serverlock|serverunlock|unlock"},
{.parent_command = "set", .sub_command = "skill", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setskill"},
{.parent_command = "set", .sub_command = "skill_all", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setallskill|setallskills|setskillall"},
{.parent_command = "set", .sub_command = "skill_all_max", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "maxskills"},
{.parent_command = "set", .sub_command = "start_zone", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setstartzone"},
{.parent_command = "set", .sub_command = "temporary_name", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "tempname"},
{.parent_command = "set", .sub_command = "texture", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "texture"},
{.parent_command = "set", .sub_command = "time", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "time"},
{.parent_command = "set", .sub_command = "time_zone", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "timezone"},
{.parent_command = "set", .sub_command = "title", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "title"},
{.parent_command = "set", .sub_command = "title_suffix", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "titlesuffix"},
{.parent_command = "set", .sub_command = "weather", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "weather"},
{.parent_command = "set", .sub_command = "zone", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "zclip|zcolor|zheader|zonelock|zsafecoords|zsky|zunderworld"},
{.parent_command = "show", .sub_command = "aas", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showaas"},
{.parent_command = "show", .sub_command = "aa_points", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showaapoints|showaapts"},
{.parent_command = "show", .sub_command = "aggro", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "aggro"},
{.parent_command = "show", .sub_command = "buffs", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showbuffs"},
{.parent_command = "show", .sub_command = "buried_corpse_count", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "getplayerburiedcorpsecount"},
{.parent_command = "show", .sub_command = "client_version_summary", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "cvs"},
{.parent_command = "show", .sub_command = "currencies", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "viewcurrencies"},
{.parent_command = "show", .sub_command = "distance", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "distance"},
{.parent_command = "show", .sub_command = "emote", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "emoteview"},
{.parent_command = "show", .sub_command = "field_of_view", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fov"},
{.parent_command = "show", .sub_command = "flags", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "flags"},
{.parent_command = "show", .sub_command = "group_info", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "ginfo"},
{.parent_command = "show", .sub_command = "hatelist", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "hatelist"},
{.parent_command = "show", .sub_command = "inventory", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "peekinv"},
{.parent_command = "show", .sub_command = "ip_lookup", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "iplookup"},
{.parent_command = "show", .sub_command = "line_of_sight", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "checklos"},
{.parent_command = "show", .sub_command = "network", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "network"},
{.parent_command = "show", .sub_command = "network_stats", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "netstats"},
{.parent_command = "show", .sub_command = "npc_global_loot", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "shownpcgloballoot"},
{.parent_command = "show", .sub_command = "npc_stats", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "npcstats"},
{.parent_command = "show", .sub_command = "npc_type", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "viewnpctype"},
{.parent_command = "show", .sub_command = "peqzone_flags", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "peqzone_flags"},
{.parent_command = "show", .sub_command = "petition", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "listpetition|viewpetition"},
{.parent_command = "show", .sub_command = "petition_info", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "petitioninfo"},
{.parent_command = "show", .sub_command = "proximity", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "proximity"},
{.parent_command = "show", .sub_command = "quest_errors", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "questerrors"},
{.parent_command = "show", .sub_command = "quest_globals", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "globalview"},
{.parent_command = "show", .sub_command = "recipe", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "viewrecipe"},
{.parent_command = "show", .sub_command = "server_info", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "serverinfo"},
{.parent_command = "show", .sub_command = "skills", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showskills"},
{.parent_command = "show", .sub_command = "spawn_status", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "spawnstatus"},
{.parent_command = "show", .sub_command = "spells", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showspells"},
{.parent_command = "show", .sub_command = "spells_list", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showspellslist"},
{.parent_command = "show", .sub_command = "stats", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showstats"},
{.parent_command = "show", .sub_command = "timers", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "timers"},
{.parent_command = "show", .sub_command = "traps", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "trapinfo"},
{.parent_command = "show", .sub_command = "uptime", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "uptime"},
{.parent_command = "show", .sub_command = "variable", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "getvariable"},
{.parent_command = "show", .sub_command = "version", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "version"},
{.parent_command = "show", .sub_command = "waypoints", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "wpinfo"},
{.parent_command = "show", .sub_command = "who", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "who"},
{.parent_command = "show", .sub_command = "xtargets", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "xtargets"},
{.parent_command = "show", .sub_command = "zone_global_loot", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showzonegloballoot"},
{.parent_command = "show", .sub_command = "zone_loot", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "viewzoneloot"},
{.parent_command = "show", .sub_command = "zone_points", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showzonepoints"},
{.parent_command = "show", .sub_command = "zone_stats", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "zstats"},
{.parent_command = "show", .sub_command = "zone_status", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "zonestatus"},
};
auto db_sub_settings = All(db);
// inject commands in the database that are not already there
std::vector<CommandSubsettingsRepository::CommandSubsettings> new_records = {};
for (const auto &r: static_records) {
bool found = false;
for (const auto &db_r: db_sub_settings) {
if (r.parent_command == db_r.parent_command && r.sub_command == db_r.sub_command) {
found = true;
}
}
if (!found) {
LogInfo("New command [{}] sub-command [{}] added to database table [{}] !", r.parent_command, r.sub_command, TableName());
new_records.emplace_back(r);
}
}
if (!new_records.empty()) {
InsertMany(db, new_records);
// if any were added, we need to reload the list
db_sub_settings = All(db);
}
// remove commands from the database that are not in the static list
bool any_deleted = false;
for (const auto &db_r: db_sub_settings) {
bool found = false;
for (const auto &r: static_records) {
if (r.parent_command == db_r.parent_command && r.sub_command == db_r.sub_command) {
found = true;
}
}
if (!found) {
LogInfo("Command [{}] sub-command [{}] removed from database table [{}] !", db_r.parent_command, db_r.sub_command, TableName());
DeleteWhere(db, fmt::format("parent_command = '{}' AND sub_command = '{}'", db_r.parent_command, db_r.sub_command));
any_deleted = true;
}
}
// if any were deleted, re-read the database
if (any_deleted) {
db_sub_settings = All(db);
}
// return the final list of what's in the database
return db_sub_settings;
}
};
#endif //EQEMU_COMMAND_SUBSETTINGS_REPOSITORY_H
+1 -1
View File
@@ -53,7 +53,7 @@ public:
auto query = fmt::format(
"SELECT `id` FROM {} WHERE LOWER(`name`) LIKE '%%{}%%' ORDER BY id ASC",
TableName(),
search_string
Strings::Escape(search_string)
);
if (query_limit >= 1) {
+50
View File
@@ -0,0 +1,50 @@
#ifndef EQEMU_KEYRING_REPOSITORY_H
#define EQEMU_KEYRING_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_keyring_repository.h"
class KeyringRepository: public BaseKeyringRepository {
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
*
* KeyringRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* KeyringRepository::GetWhereNeverExpires()
* KeyringRepository::GetWhereXAndY()
* KeyringRepository::DeleteWhereXAndY()
*
* Most of the above could be covered by base methods, but if you as a developer
* find yourself re-using logic for other parts of the code, its best to just make a
* method that can be re-used easily elsewhere especially if it can use a base repository
* method and encapsulate filters there
*/
// Custom extended repository methods here
};
#endif //EQEMU_KEYRING_REPOSITORY_H
@@ -44,7 +44,28 @@ public:
*/
// Custom extended repository methods here
static int UpdateRaidMarkedNPC(
Database& db,
int32_t raid_id,
uint32_t marked_npc_entity_id,
uint32_t marked_npc_zone_id,
uint32_t marked_npc_instance_id,
uint32_t slot_number
) {
auto results = db.QueryDatabase(
fmt::format(
"UPDATE `{0}` SET `marked_npc_{4}_entity_id` = '{1}',`marked_npc_{4}_zone_id` = '{2}',`marked_npc_{4}_instance_id` = '{3}' WHERE raidid = '{5}';",
TableName(),
marked_npc_entity_id,
marked_npc_zone_id,
marked_npc_instance_id,
slot_number,
raid_id
)
);
return results.Success() ? results.RowsAffected() : 0;
}
};
#endif //EQEMU_RAID_DETAILS_REPOSITORY_H
+53 -1
View File
@@ -44,7 +44,59 @@ public:
*/
// Custom extended repository methods here
static int UpdateRaidNote(
Database& db,
int32_t raid_id,
const std::string& note,
const std::string& character_name
) {
auto results = db.QueryDatabase(
fmt::format("UPDATE `{}` SET `note` = '{}' WHERE raidid = '{}' AND name = '{}';",
TableName(),
Strings::Escape(note),
raid_id,
Strings::Escape(character_name)
)
);
return results.Success() ? results.RowsAffected() : 0;
}
static int UpdateRaidAssister(
Database& db,
int32_t raid_id,
const std::string& character_name,
uint8_t value
) {
auto results = db.QueryDatabase(
fmt::format(
"UPDATE `{}` SET `is_assister` = '{}' WHERE raidid = '{}' AND `name` = '{}';",
TableName(),
value,
raid_id,
Strings::Escape(character_name)
)
);
return results.Success() ? results.RowsAffected() : 0;
}
static int UpdateRaidMarker(
Database& db,
int32_t raid_id,
const std::string& character_name,
uint8_t value
) {
auto results = db.QueryDatabase(
fmt::format(
"UPDATE `{}` SET `is_marker` = '{}' WHERE raidid = '{}' AND `name` = '{}';",
TableName(),
value,
raid_id,
Strings::Escape(character_name)
)
);
return results.Success() ? results.RowsAffected() : 0;
}
};
#endif //EQEMU_RAID_MEMBERS_REPOSITORY_H
@@ -0,0 +1,50 @@
#ifndef EQEMU_SPAWN2_DISABLED_REPOSITORY_H
#define EQEMU_SPAWN2_DISABLED_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_spawn2_disabled_repository.h"
class Spawn2DisabledRepository: public BaseSpawn2DisabledRepository {
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
*
* Spawn2DisabledRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* Spawn2DisabledRepository::GetWhereNeverExpires()
* Spawn2DisabledRepository::GetWhereXAndY()
* Spawn2DisabledRepository::DeleteWhereXAndY()
*
* Most of the above could be covered by base methods, but if you as a developer
* find yourself re-using logic for other parts of the code, its best to just make a
* method that can be re-used easily elsewhere especially if it can use a base repository
* method and encapsulate filters there
*/
// Custom extended repository methods here
};
#endif //EQEMU_SPAWN2_DISABLED_REPOSITORY_H
+19 -3
View File
@@ -58,6 +58,7 @@ RULE_REAL(Character, ExpMultiplier, 0.5, "If greater than 0, the experience gain
RULE_REAL(Character, AAExpMultiplier, 0.5, "If greater than 0, the AA experience gained is multiplied by this value. ")
RULE_REAL(Character, GroupExpMultiplier, 0.5, "The experience in a group is multiplied by this value in addition to the group multiplier. The group multiplier is: 2 members=x 1.2, 3=x1.4, 4=x1.6, 5=x1.8, 6=x2.16")
RULE_REAL(Character, RaidExpMultiplier, 0.2, "The experience gained in raids is multiplied by (1-RaidExpMultiplier) ")
RULE_REAL(Character, FinalRaidExpMultiplier, 1.0, "Multiplies all raid experience by this value. Default: 1.0")
RULE_BOOL(Character, UseXPConScaling, true, "When activated, the experience is modified depending on the difference between player level and NPC level. The values from the rules GreenModifier to RedModifier are used")
RULE_INT(Character, ShowExpValues, 0, "Show experience values. 0=normal, 1=show raw experience values, 2=show raw experience values and percent")
RULE_INT(Character, GreenModifier, 20, "The experience obtained for green con mobs is multiplied by value/100")
@@ -241,6 +242,7 @@ RULE_CATEGORY_END()
RULE_CATEGORY(Skills)
RULE_INT(Skills, MaxTrainTradeskills, 21, "Highest level for trading skills that can be learnt by the trainer")
RULE_BOOL(Skills, UseLimitTradeskillSearchSkillDiff, true, "Enables the limit for the maximum difference between trivial and skill for recipe searches and favorites")
RULE_BOOL(Skills, TrivialTradeskillCombinesNoFail, false, "Enable to make all trivial tradeskill combines unable to fail")
RULE_INT(Skills, MaxTradeskillSearchSkillDiff, 50, "The maximum difference in skill between the trivial of an item and the skill of the player if the trivial is higher than the skill. Recipes that have not been learnt or made at least once via the Experiment mode will be removed from searches based on this criteria.")
RULE_INT(Skills, MaxTrainSpecializations, 50, "Maximum level a GM trainer will train casting specializations")
RULE_INT(Skills, SwimmingStartValue, 100, "Start value of swimming skill")
@@ -255,6 +257,7 @@ RULE_REAL(Pets, AttackCommandRange, 150, "Range at which a pet will respond to a
RULE_BOOL(Pets, UnTargetableSwarmPet, false, "Setting whether swarm pets should be targetable")
RULE_REAL(Pets, PetPowerLevelCap, 10, "Maximum number of levels a player pet can go up with pet power")
RULE_BOOL(Pets, CanTakeNoDrop, false, "Setting whether anyone can give no-drop items to pets")
RULE_BOOL(Pets, CanTakeQuestItems, true, "Setting whether anyone can give quest items to pets")
RULE_BOOL(Pets, LivelikeBreakCharmOnInvis, true, "Default: true will break charm on any type of invis (hide/ivu/iva/etc) false will only break if the pet can not see you (ex. you have an undead pet and cast IVU")
RULE_BOOL(Pets, ClientPetsUseOwnerNameInLastName, true, "Disable this to keep client pet's last names from being owner_name's pet")
RULE_CATEGORY_END()
@@ -286,7 +289,8 @@ RULE_BOOL(World, GMAccountIPList, false, "Check IP list against GM accounts. Thi
RULE_INT(World, MinGMAntiHackStatus, 1, "Minimum status to check against AntiHack list")
RULE_INT(World, SoFStartZoneID, -1, "Sets the Starting Zone for SoF Clients separate from Titanium Clients (-1 is disabled)")
RULE_INT(World, TitaniumStartZoneID, -1, "Sets the Starting Zone for Titanium Clients (-1 is disabled). Replaces the old method")
RULE_INT(World, ExpansionSettings, 16383, "Sets the expansion settings for the server, This is sent on login to world and affects client expansion settings. Defaults to all expansions enabled up to TSS, value is bitmask")
RULE_INT(World, ExpansionSettings, 16383, "Sets the expansion settings bitmask for the server, This is sent on login to world and affects client expansion settings. Defaults to all expansions enabled up to TSS, value is bitmask")
RULE_INT(World, CharacterSelectExpansionSettings, -1, "Sets the expansion settings bitmask for character select if you wish to override. -1 is off")
RULE_BOOL(World, UseClientBasedExpansionSettings, true, "If true it will overrule World, ExpansionSettings and set someone's expansion based on the client they're using")
RULE_INT(World, PVPSettings, 0, "Sets the PVP settings for the server. 1=Rallos Zek RuleSet, 2=Tallon/Vallon Zek Ruleset, 4=Sullon Zek Ruleset, 6=Discord Ruleset, anything above 6 is the Discord Ruleset without the no-drop restrictions removed. NOTE: edit IsAttackAllowed in Zone-table to accomodate for these rules")
RULE_INT(World, PVPMinLevel, 0, "Minimum level to pvp")
@@ -299,6 +303,8 @@ RULE_BOOL(World, EnforceCharacterLimitAtLogin, false, "Enforce the limit for cha
RULE_BOOL(World, EnableDevTools, true, "Enable or Disable the Developer Tools globally (Most of the time you want this enabled)")
RULE_BOOL(World, EnableChecksumVerification, false, "Enable or Disable the Checksum Verification for eqgame.exe and spells_us.txt")
RULE_INT(World, MaximumQuestErrors, 30, "Changes the maximum number of quest errors that can be displayed in #questerrors, default is 30")
RULE_INT(World, BootHour, 0, "Sets the in-game hour world will set when it first boots. 0-24 are valid options, where 0 disables this rule")
RULE_BOOL(World, UseItemLinksForKeyRing, false, "Uses item links for Key Ring Listing instead of item name")
RULE_CATEGORY_END()
RULE_CATEGORY(Zone)
@@ -448,10 +454,14 @@ RULE_BOOL(Spells, TargetsTargetRequiresCombatRange, true, "Disable to remove com
RULE_BOOL(Spells, NPCBuffLevelRestrictions, false, "Impose BuffLevelRestrictions on NPCs if true")
RULE_INT(Spells, ResurrectionEffectBlock, 2, "0 = allow overwrites/rule disabled. If set to 1 = Block all buffs that would overwrite Resurrection Effects. If set to 2 = Will not overwrite Resurrection Effects, instead moves new buff to an empty slot if available. Default is 2.")
RULE_BOOL(Spells, WaterMatchRequiredForLoS, true, "Enable/Disable the requirement of both the attacker/victim being both in or out of water for spells LoS to pass.")
RULE_INT(Spells, WizardCritMinimumRandomRatio, 20, "The minimum value for the random range which Wizards and Caster DPS Mercs innately have for spell crit ratio. Set to 20 for vanilla values.")
RULE_INT(Spells, WizardCritMaximumRandomRatio, 70, "The maximum value for the random range which Wizards and Caster DPS Mercs innately have for spell crit ratio. Set to 70 for vanilla values.")
RULE_INT(Spells, DefensiveProcPenaltyLevelGap, 6, "Defensive Proc Penalty Level Gap where procs start losing their proc rate at RuleR(Spells, DefensiveProcPenaltyModifier)% per level difference")
RULE_REAL(Spells, DefensiveProcPenaltyLevelGapModifier, 10.0f, "Defensive Proc Penalty Level Gap Modifier where procs start losing their proc rate at defined % after RuleI(Spells, DefensiveProcLevelGap) level difference")
RULE_CATEGORY_END()
RULE_CATEGORY(Combat)
RULE_REAL(Combat, AERampageSafeZone, 0.018, "max hit ae ramp reduction range")
RULE_REAL(Combat, AERampageMaxDistance, 70, "Max AERampage range (% of max combat distance)")
RULE_INT(Combat, PetBaseCritChance, 0, "Pet base crit chance")
RULE_INT(Combat, NPCBashKickLevel, 6, "The level that NPCcan KICK/BASH")
RULE_INT(Combat, MeleeCritDifficulty, 8900, "Value against which is rolled to check if a melee crit is triggered. Lower is easier")
@@ -522,6 +532,8 @@ RULE_BOOL(Combat, BackstabIgnoresElemental, false, "Enable or disable Elemental
RULE_BOOL(Combat, BackstabIgnoresBane, false, "Enable or disable Bane weapon damage affecting backstab damage, false by default.")
RULE_BOOL(Combat, SummonMeleeRange, true, "Enable or disable summoning of a player when already in melee range of the summoner.")
RULE_BOOL(Combat, WaterMatchRequiredForAutoFireLoS, true, "Enable/Disable the requirement of both the attacker/victim being both in or out of water for AutoFire LoS to pass.")
RULE_INT(Combat, ExtraAllowedKickClassesBitmask, 0, "Bitmask for allowing extra classes beyond Warrior, Ranger, Beastlord, and Berserker to kick, No Extra Classes (0) by default")
RULE_INT(Combat, MaxProcs, 4, "Adjustable maximum number of procs per round, the hard cap is MAX_PROCS (11). Requires mob repop or client zone when changed")
RULE_CATEGORY_END()
RULE_CATEGORY(NPC)
@@ -539,6 +551,7 @@ RULE_INT(NPC, LastFightingDelayMovingMin, 10000, "Minimum time before mob goes h
RULE_INT(NPC, LastFightingDelayMovingMax, 20000, "Maximum time before mob goes home after all aggro loss (milliseconds)")
RULE_BOOL(NPC, SmartLastFightingDelayMoving, true, "When true, mobs that started going home previously will do so again immediately if still on FD hate list")
RULE_BOOL(NPC, ReturnNonQuestNoDropItems, false, "Returns NO DROP items on NPC that don't have an EVENT_TRADE sub in their script")
RULE_BOOL(NPC, ReturnQuestItemsFromNonQuestNPCs, false, "Returns Quest items traded to NPCs that are not flagged as a Quest NPC")
RULE_INT(NPC, StartEnrageValue, 9, " Percentage HP that an NPC will begin to enrage")
RULE_BOOL(NPC, LiveLikeEnrage, false, "If set to true then only player controlled pets will enrage")
RULE_BOOL(NPC, EnableMeritBasedFaction, false, "If set to true, faction will be given in the same way as experience (solo/group/raid)")
@@ -618,7 +631,7 @@ RULE_BOOL(Bots, FinishBuffing, false, "Allow for buffs to complete even if the b
RULE_BOOL(Bots, GroupBuffing, false, "Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB")
RULE_INT(Bots, HealRotationMaxMembers, 24, "Maximum number of heal rotation members")
RULE_INT(Bots, HealRotationMaxTargets, 12, "Maximum number of heal rotation targets")
RULE_REAL(Bots, ManaRegen, 2.0, "Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players")
RULE_REAL(Bots, ManaRegen, 2.0, "Adjust mana regen. Acts as a final multiplier, stacks with Rule Character:ManaRegenMultiplier.")
RULE_BOOL(Bots, PreferNoManaCommandSpells, true, "Give sorting priority to newer no-mana spells (i.e., 'Bind Affinity')")
RULE_BOOL(Bots, QuestableSpawnLimit, false, "Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl")
RULE_INT(Bots, SpawnLimit, 71, "Number of bots a character can have spawned at one time, You + 71 bots is a 12 group pseudo-raid")
@@ -636,6 +649,8 @@ RULE_BOOL(Bots, OldRaceRezEffects, false, "Older clients had ID 757 for races wi
RULE_BOOL(Bots, ResurrectionSickness, true, "Use Resurrection Sickness based on Resurrection spell cast, set to false to disable Resurrection Sickness.")
RULE_INT(Bots, OldResurrectionSicknessSpell, 757, "757 is Default Old Resurrection Sickness Spell")
RULE_INT(Bots, ResurrectionSicknessSpell, 756, "756 is Default Resurrection Sickness Spell")
RULE_BOOL(Bots, AllowPickpocketCommand, true, "Allows the use of the bot command 'pickpocket'")
RULE_BOOL(Bots, BotHealOnLevel, false, "Setting whether a bot should heal completely when leveling. Default FALSE.")
RULE_CATEGORY_END()
RULE_CATEGORY(Chat)
@@ -812,6 +827,7 @@ RULE_CATEGORY_END()
RULE_CATEGORY(Expansion)
RULE_INT(Expansion, CurrentExpansion, -1, "The current expansion enabled for the server [-1 = ALL, 0 = Classic, 1 = Kunark etc.]")
RULE_BOOL(Expansion, UseCurrentExpansionAAOnly, false, "When true will only load AA ranks that match CurrentExpansion rule")
RULE_INT(Expansion, AutoGrantAAExpansion, -1, "Expansion to auto grant AAs up to, [-1 = Disabled, 0 = Classic, 1 = Kunark etc.]")
RULE_CATEGORY_END()
RULE_CATEGORY(Instances)
+2 -1
View File
@@ -376,7 +376,7 @@ std::string EQ::SayLinkEngine::InjectSaylinksIfNotExist(const char *message)
void EQ::SayLinkEngine::LoadCachedSaylinks()
{
auto saylinks = SaylinkRepository::GetWhere(database, "phrase not like '%#%'");
auto saylinks = SaylinkRepository::GetWhere(database, "phrase not REGEXP BINARY '[A-Z]' and phrase not REGEXP '[0-9]'");
LogSaylink("Loaded [{}] saylinks into cache", saylinks.size());
g_cached_saylinks = saylinks;
}
@@ -399,6 +399,7 @@ SaylinkRepository::Saylink EQ::SayLinkEngine::GetOrSaveSaylink(std::string sayli
// return if found from the database
if (!saylinks.empty()) {
g_cached_saylinks.emplace_back(saylinks[0]);
return saylinks[0];
}
+1
View File
@@ -19,6 +19,7 @@
#include <string>
#include <vector>
#include <stdint.h>
typedef struct eq_cpu_info_s {
std::string model;
+98 -77
View File
@@ -10,6 +10,7 @@
#include <cereal/types/chrono.hpp>
#include <cereal/types/string.hpp>
#include <cereal/types/vector.hpp>
#include <glm/vec4.hpp>
#define SERVER_TIMEOUT 45000 // how often keepalive gets sent
#define INTERSERVER_TIMER 10000
@@ -113,6 +114,7 @@
#define ServerOP_GroupFollowAck 0x0111
#define ServerOP_GroupCancelInvite 0x0112
#define ServerOP_RaidMOTD 0x0113
#define ServerOP_RaidNote 0x0114
#define ServerOP_InstanceUpdateTime 0x014F
#define ServerOP_AdventureRequest 0x0150
@@ -248,6 +250,7 @@
#define ServerOP_ReloadZonePoints 0x4122
#define ServerOP_ReloadDzTemplates 0x4123
#define ServerOP_ReloadZoneData 0x4124
#define ServerOP_ReloadDataBucketsCache 0x4125
#define ServerOP_CZDialogueWindow 0x4500
#define ServerOP_CZLDoNUpdate 0x4501
@@ -285,6 +288,8 @@
// player events
#define ServerOP_PlayerEvent 0x5100
#define ServerOP_DataBucketCacheUpdate 0x5200
enum {
CZUpdateType_Character,
CZUpdateType_Group,
@@ -456,12 +461,12 @@ struct SPackSendQueue {
uchar buffer[0];
};
struct ServerZoneStateChange_struct {
uint32 ZoneServerID;
char adminname[64];
uint32 zoneid;
uint16 instanceid;
bool makestatic;
struct ServerZoneStateChange_Struct {
uint32 zone_server_id;
uint32 zone_id;
uint16 instance_id;
bool is_static;
char admin_name[64];
};
struct ServerZoneIncomingClient_Struct {
@@ -1072,7 +1077,11 @@ struct ServerRaidMessage_Struct {
struct ServerRaidMOTD_Struct {
uint32 rid;
char motd[0];
char motd[1024];
};
struct ServerRaidNote_Struct {
uint32 rid;
};
struct ServerLFGMatchesRequest_Struct {
@@ -1133,10 +1142,10 @@ struct ServerInstanceUpdateTime_Struct
uint32 new_duration;
};
struct ServerSpawnStatusChange_Struct
{
struct ServerSpawnStatusChange_Struct {
uint32 id;
bool new_status;
bool new_status;
uint32 instance_id;
};
struct ServerQGlobalUpdate_Struct
@@ -1478,95 +1487,96 @@ struct CZClientMessageString_Struct {
struct CZDialogueWindow_Struct {
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
char message[4096];
char client_name[64]; // Only used by Character Name Type, else empty
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
char message[4096];
char client_name[64]; // Only used by Character Name Type, else empty
};
struct CZLDoNUpdate_Struct {
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
uint8 update_subtype; // 0 - Loss, 1 - Points, 2 - Win
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
uint8 update_subtype; // 0 - Loss, 1 - Points, 2 - Win
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
uint32 theme_id;
int points; // Only used in Points Subtype, else 1
char client_name[64]; // Only used by Character Name Type, else empty
int points; // Only used in Points Subtype, else 1
char client_name[64]; // Only used by Character Name Type, else empty
};
struct CZMarquee_Struct {
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
uint32 type;
uint32 priority;
uint32 fade_in;
uint32 fade_out;
uint32 duration;
char message[512];
char client_name[64]; // Only used by Character Name Type, else empty
char message[512];
char client_name[64]; // Only used by Character Name Type, else empty
};
struct CZMessage_Struct {
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
int update_identifier; // Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
int update_identifier; // Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
uint32 type;
char message[512];
char client_name[64]; // Only used by Character Name Type, else empty
char message[512];
char client_name[64]; // Only used by Character Name Type, else empty
};
struct CZMove_Struct {
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
uint8 update_subtype; // 0 - Move Zone, 1 - Move Zone Instance
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
uint16 instance_id; // Only used by Move Zone Instance, else 0
char zone_short_name[32]; // Only by with Move Zone, else empty
char client_name[64]; // Only used by Character Name Type, else empty
std::string client_name = std::string(); // Only used by Character Name Type, else empty
glm::vec4 coordinates = glm::vec4(0.f); // XYZ or XYZH, heading is optional, defaults to 0.
uint16 instance_id = 0; // Only used by Move Zone Instance, else 0
uint32 update_identifier = 0; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
uint8 update_subtype; // 0 - Move Zone, 1 - Move Zone Instance
std::string zone_short_name = std::string(); // Only used by Move Zone, else empty
};
struct CZSetEntityVariable_Struct {
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name, 6 - NPC
int update_identifier; // Group ID, Raid ID, Guild ID, Expedition ID, or NPC ID based on update type, 0 for Character Name
char variable_name[256];
char variable_value[256];
char client_name[64]; // Only used by Character Type, else empty
int update_identifier; // Group ID, Raid ID, Guild ID, Expedition ID, or NPC ID based on update type, 0 for Character Name
char variable_name[256];
char variable_value[256];
char client_name[64]; // Only used by Character Type, else empty
};
struct CZSignal_Struct {
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name, 6 - NPC
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, Expedition ID, or NPC ID based on update type, 0 for Character Name
int signal_id;
char client_name[64]; // Only used by Character Name Type, else empty
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, Expedition ID, or NPC ID based on update type, 0 for Character Name
int signal_id;
char client_name[64]; // Only used by Character Name Type, else empty
};
struct CZSpell_Struct {
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
uint8 update_subtype; // 0 - Cast Spell, 1 - Remove Spell
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
uint8 update_subtype; // 0 - Cast Spell, 1 - Remove Spell
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
uint32 spell_id;
char client_name[64]; // Only used by Character Name Type, else empty
char client_name[64]; // Only used by Character Name Type, else empty
};
struct CZTaskUpdate_Struct {
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
uint8 update_subtype; // 0 - Activity Reset, 1 - Activity Update, 2 - Assign Task, 3 - Disable Task, 4 - Enable Task, 5 - Fail Task, 6 - Remove Task
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
uint8 update_subtype; // 0 - Activity Reset, 1 - Activity Update, 2 - Assign Task, 3 - Disable Task, 4 - Enable Task, 5 - Fail Task, 6 - Remove Task
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
uint32 task_identifier;
int task_subidentifier; // Activity ID for Activity Reset and Activity Update, NPC Entity ID for Assign Task, else -1
int update_count; // Only used by Activity Update, else 1
bool enforce_level_requirement; // Only used by Assign Task
char client_name[64]; // Only used by Character Name Type, else empty
int task_subidentifier; // Activity ID for Activity Reset and Activity Update, NPC Entity ID for Assign Task, else -1
int update_count; // Only used by Activity Update, else 1
bool enforce_level_requirement; // Only used by Assign Task
char client_name[64]; // Only used by Character Name Type, else empty
};
struct WWDialogueWindow_Struct {
char message[4096];
char message[4096];
uint8 min_status;
uint8 max_status;
};
struct WWLDoNUpdate_Struct {
uint8 update_type; // 0 - Loss, 1 - Points, 2 - Win
uint8 update_type; // 0 - Loss, 1 - Points, 2 - Win
uint32 theme_id;
int points; // Only used in Points Subtype, else 1
uint8 min_status;
uint8 max_status;
int points; // Only used in Points Subtype, else 1
uint8 min_status;
uint8 max_status;
};
struct WWMarquee_Struct {
@@ -1575,56 +1585,57 @@ struct WWMarquee_Struct {
uint32 fade_in;
uint32 fade_out;
uint32 duration;
char message[512];
uint8 min_status;
uint8 max_status;
char message[512];
uint8 min_status;
uint8 max_status;
};
struct WWMessage_Struct {
uint32 type;
char message[512];
uint8 min_status;
uint8 max_status;
char message[512];
uint8 min_status;
uint8 max_status;
};
struct WWMove_Struct {
uint8 update_type; // 0 - Move Zone, 1 - Move Zone Instance
char zone_short_name[32]; // Used with Move Zone
uint8 update_type; // 0 - Move Zone, 1 - Move Zone Instance
char zone_short_name[32]; // Used with Move Zone
uint16 instance_id; // Used with Move Zone Instance
uint8 min_status;
uint8 max_status;
uint8 min_status;
uint8 max_status;
};
struct WWSetEntityVariable_Struct {
uint8 update_type; // 0 - Character, 1 - NPC
char variable_name[256];
char variable_value[256];
char variable_name[256];
char variable_value[256];
uint8 min_status;
uint8 max_status;
};
struct WWSignal_Struct {
uint8 update_type; // 0 - Character, 1 - NPC
int signal_id;
int signal_id;
uint8 min_status;
uint8 max_status;
};
struct WWSpell_Struct {
uint8 update_type; // 0 - Cast Spell, 1 - Remove Spell
uint8 update_type; // 0 - Cast Spell, 1 - Remove Spell
uint32 spell_id;
uint8 min_status;
uint8 max_status;
uint8 min_status;
uint8 max_status;
};
struct WWTaskUpdate_Struct {
uint8 update_type; // 0 - Activity Reset, 1 - Activity Update, 2 - Assign Task, 3 - Disable Task, 4 - Enable Task, 5 - Fail Task, 6 - Remove Task
uint8 update_type; // 0 - Activity Reset, 1 - Activity Update, 2 - Assign Task, 3 - Disable Task, 4 - Enable Task, 5 - Fail Task, 6 - Remove Task
uint32 task_identifier;
int task_subidentifier; // Activity ID for Activity Reset and Activity Update, NPC Entity ID for Assign Task, else -1
int update_count; // Update Count for Activity Update, else 1
bool enforce_level_requirement; // Only used by Assign Task, else false
uint8 min_status;
uint8 max_status;
int task_subidentifier; // Activity ID for Activity Reset and Activity Update, NPC Entity ID for Assign Task, else -1
int update_count; // Update Count for Activity Update, else 1
bool enforce_level_requirement; // Only used by Assign Task, else false
uint8 min_status;
uint8 max_status;
};
struct ReloadWorld_Struct {
@@ -1815,6 +1826,11 @@ struct ServerSendPlayerEvent_Struct {
char cereal_data[0];
};
struct ServerDataBucketCacheUpdate_Struct {
uint32_t cereal_size;
char cereal_data[0];
};
struct ServerFlagUpdate_Struct {
uint32 account_id;
int16 admin;
@@ -1824,6 +1840,11 @@ struct ServerOOCMute_Struct {
bool is_muted;
};
struct ServerZoneStatus_Struct {
char name[64];
int16 admin;
};
#pragma pack()
#endif
+128 -46
View File
@@ -41,6 +41,7 @@
#include "repositories/criteria/content_filter_criteria.h"
#include "repositories/account_repository.h"
#include "repositories/faction_association_repository.h"
#include "repositories/starting_items_repository.h"
#include "path_manager.h"
#include "repositories/loottable_repository.h"
@@ -51,7 +52,9 @@ namespace ItemField
#define F(x) x,
#include "item_fieldlist.h"
#undef F
updated
updated,
minstatus,
comment,
};
}
@@ -444,45 +447,81 @@ bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) {
return true;
}
bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, EQ::InventoryProfile* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) {
bool SharedDatabase::SetStartingItems(
PlayerProfile_Struct *pp,
EQ::InventoryProfile *inv,
uint32 si_race,
uint32 si_class,
uint32 si_deity,
uint32 si_current_zone,
char *si_name,
int admin_level
)
{
const EQ::ItemData *item_data;
const EQ::ItemData *myitem;
const auto &l = StartingItemsRepository::All(*this);
const std::string query = StringFormat(
"SELECT itemid, item_charges, slot FROM starting_items "
"WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND "
"(deityid = %i or deityid = 0) AND (zoneid = %i or zoneid = 0) AND "
"gm <= %i %s ORDER BY id",
si_race,
si_class,
si_deity,
si_current_zone,
admin_level,
ContentFilterCriteria::apply().c_str()
);
auto results = QueryDatabase(query);
if (!results.Success()) {
if (l.empty()) {
return false;
}
std::vector<StartingItemsRepository::StartingItems> v;
for (auto& row = results.begin(); row != results.end(); ++row) {
const int32 itemid = Strings::ToInt(row[0]);
const int32 charges = Strings::ToInt(row[1]);
int32 slot = Strings::ToInt(row[2]);
myitem = GetItem(itemid);
for (const auto &e : l) {
const auto &classes = Strings::Split(e.class_list, "|");
const auto &deities = Strings::Split(e.deity_list, "|");
const auto &races = Strings::Split(e.race_list, "|");
const auto &zones = Strings::Split(e.zone_id_list, "|");
if(!myitem)
const std::string &all = std::to_string(0);
if (classes[0] != all) {
if (!Strings::Contains(classes, std::to_string(si_class))) {
continue;
}
}
if (deities[0] != all) {
if (!Strings::Contains(deities, std::to_string(si_deity))) {
continue;
}
}
if (races[0] != all) {
if (!Strings::Contains(races, std::to_string(si_race))) {
continue;
}
}
if (zones[0] != all) {
if (!Strings::Contains(zones, std::to_string(si_current_zone))) {
continue;
}
}
v.emplace_back(e);
}
for (const auto &e : v) {
const uint32 item_id = e.item_id;
const uint8 item_charges = e.item_charges;
int32 slot = e.slot;
item_data = GetItem(item_id);
if (!item_data) {
continue;
}
const EQ::ItemInstance* myinst = CreateBaseItem(myitem, charges);
const auto *inst = CreateBaseItem(item_data, item_charges);
if(slot < 0)
slot = inv->FindFreeSlot(0, 0);
if (slot < EQ::invslot::slotCharm) {
slot = inv->FindFreeSlot(false, false);
}
inv->PutItem(slot, *myinst);
safe_delete(myinst);
inv->PutItem(slot, *inst);
safe_delete(inst);
}
return true;
@@ -965,7 +1004,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
#define F(x) "`"#x"`,"
#include "item_fieldlist.h"
#undef F
"updated FROM items ORDER BY id";
"updated, minstatus, comment FROM items ORDER BY id";
auto results = QueryDatabase(query);
if (!results.Success()) {
return;
@@ -977,9 +1016,13 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
// Unique Identifier
item.ID = Strings::ToUnsignedInt(row[ItemField::id]);
// Name and Lore
// Minimum Status
item.MinStatus = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::minstatus]));
// Name, Lore, and Comment
strn0cpy(item.Name, row[ItemField::name], sizeof(item.Name));
strn0cpy(item.Lore, row[ItemField::lore], sizeof(item.Lore));
strn0cpy(item.Comment, row[ItemField::comment], sizeof(item.Comment));
// Flags
item.ArtifactFlag = Strings::ToBool(row[ItemField::artifactflag]);
@@ -1635,25 +1678,29 @@ bool SharedDatabase::GetCommandSettings(std::map<std::string, std::pair<uint8, s
{
command_settings.clear();
const std::string query = "SELECT `command`, `access`, `aliases` FROM `command_settings`";
const std::string& query = "SELECT `command`, `access`, `aliases` FROM `command_settings`";
auto results = QueryDatabase(query);
if (!results.Success())
if (!results.Success() || !results.RowCount()) {
return false;
}
for (auto& row = results.begin(); row != results.end(); ++row) {
for (auto row : results) {
command_settings[row[0]].first = Strings::ToUnsignedInt(row[1]);
if (row[2][0] == 0)
if (row[2][0] == 0) {
continue;
}
std::vector<std::string> aliases = Strings::Split(row[2], '|');
for (auto iter = aliases.begin(); iter != aliases.end(); ++iter) {
if (iter->empty())
for (const auto& e : aliases) {
if (e.empty()) {
continue;
command_settings[row[0]].second.push_back(*iter);
}
command_settings[row[0]].second.push_back(e);
}
}
return true;
return true;
}
bool SharedDatabase::UpdateInjectedCommandSettings(const std::vector<std::pair<std::string, uint8>> &injected)
@@ -1668,13 +1715,15 @@ bool SharedDatabase::UpdateInjectedCommandSettings(const std::vector<std::pair<s
)
);
if (!QueryDatabase(query).Success()) {
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
LogInfo(
"[{0}] New Command(s) Added",
injected.size()
"[{}] New Command{} Added",
injected.size(),
injected.size() != 1 ? "s" : ""
);
}
@@ -1684,25 +1733,58 @@ bool SharedDatabase::UpdateInjectedCommandSettings(const std::vector<std::pair<s
bool SharedDatabase::UpdateOrphanedCommandSettings(const std::vector<std::string> &orphaned)
{
if (orphaned.size()) {
const std::string query = fmt::format(
std::string query = fmt::format(
"DELETE FROM `command_settings` WHERE `command` IN ({})",
Strings::ImplodePair(",", std::pair<char, char>('\'', '\''), orphaned)
);
if (!QueryDatabase(query).Success()) {
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
query = fmt::format(
"DELETE FROM `command_subsettings` WHERE `parent_command` IN ({})",
Strings::ImplodePair(",", std::pair<char, char>('\'', '\''), orphaned)
);
auto results_two = QueryDatabase(query);
if (!results_two.Success()) {
return false;
}
LogInfo(
"{} Orphaned Command{} Deleted",
"{} Orphaned Command{} Deleted | {} Orphaned Subcommand{} Deleted",
orphaned.size(),
(orphaned.size() == 1 ? "" : "s")
orphaned.size() != 1 ? "s" : "",
results_two.RowsAffected(),
results_two.RowsAffected() != 1 ? "s" : ""
);
}
return true;
}
bool SharedDatabase::GetCommandSubSettings(std::vector<CommandSubsettingsRepository::CommandSubsettings> &command_subsettings)
{
command_subsettings.clear();
const auto& l = CommandSubsettingsRepository::GetAll(*this);
if (l.empty()) {
return false;
}
command_subsettings.reserve(l.size());
for (const auto& e : l) {
command_subsettings.emplace_back(e);
}
return true;
}
bool SharedDatabase::LoadSkillCaps(const std::string &prefix) {
skill_caps_mmf.reset(nullptr);
+2
View File
@@ -28,6 +28,7 @@
#include "fixed_memory_hash_set.h"
#include "fixed_memory_variable_hash_set.h"
#include "say_link.h"
#include "repositories/command_subsettings_repository.h"
#include <list>
#include <map>
@@ -77,6 +78,7 @@ public:
bool GetCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &command_settings);
bool UpdateInjectedCommandSettings(const std::vector<std::pair<std::string, uint8>> &injected);
bool UpdateOrphanedCommandSettings(const std::vector<std::string> &orphaned);
bool GetCommandSubSettings(std::vector<CommandSubsettingsRepository::CommandSubsettings> &command_subsettings);
uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID);
bool SetGMInvul(uint32 account_id, bool gminvul);
bool SetGMFlymode(uint32 account_id, uint8 flymode);
+52 -31
View File
@@ -42,10 +42,32 @@
#include <stdio.h>
#include <iostream>
#include <random>
#include <string>
//Const char based
#include "strings_legacy.cpp" // legacy c functions
#include "strings_misc.cpp" // anything non "Strings" scoped
std::string Strings::Random(size_t length)
{
static auto &chrs = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
thread_local static std::mt19937 rg{std::random_device{}()};
thread_local static std::uniform_int_distribution<std::string::size_type> pick(0, sizeof(chrs) - 2);
std::string s;
s.reserve(length);
while (length--) {
s += chrs[pick(rg)];
}
return s;
}
std::vector<std::string> Strings::Split(const std::string &str, const char delim)
{
std::vector<std::string> ret;
@@ -64,7 +86,7 @@ std::vector<std::string> Strings::Split(const std::string &str, const char delim
}
// this one takes delimiter length into consideration
std::vector<std::string> Strings::Split(const std::string& s, const std::string& delimiter)
std::vector<std::string> Strings::Split(const std::string &s, const std::string &delimiter)
{
size_t pos_start = 0, pos_end, delim_len = delimiter.length();
std::string token;
@@ -376,7 +398,7 @@ std::string Strings::Money(uint64 platinum, uint64 gold, uint64 silver, uint64 c
std::string money_string = "Unknown";
if (copper && silver && gold && platinum) { // CSGP
money_string = fmt::format(
"{} Platinum, {} Gold, {} Silver, and {} Copper",
"{} platinum, {} gold, {} silver, and {} copper",
Strings::Commify(std::to_string(platinum)),
Strings::Commify(std::to_string(gold)),
Strings::Commify(std::to_string(silver)),
@@ -385,7 +407,7 @@ std::string Strings::Money(uint64 platinum, uint64 gold, uint64 silver, uint64 c
}
else if (copper && silver && !gold && platinum) { // CSP
money_string = fmt::format(
"{} Platinum, {} Silver, and {} Copper",
"{} platinum, {} silver, and {} copper",
Strings::Commify(std::to_string(platinum)),
Strings::Commify(std::to_string(silver)),
Strings::Commify(std::to_string(copper))
@@ -393,7 +415,7 @@ std::string Strings::Money(uint64 platinum, uint64 gold, uint64 silver, uint64 c
}
else if (copper && silver && gold && !platinum) { // CSG
money_string = fmt::format(
"{} Gold, {} Silver, and {} Copper",
"{} gold, {} silver, and {} copper",
Strings::Commify(std::to_string(gold)),
Strings::Commify(std::to_string(silver)),
Strings::Commify(std::to_string(copper))
@@ -401,21 +423,21 @@ std::string Strings::Money(uint64 platinum, uint64 gold, uint64 silver, uint64 c
}
else if (copper && !silver && !gold && platinum) { // CP
money_string = fmt::format(
"{} Platinum and {} Copper",
"{} platinum and {} copper",
Strings::Commify(std::to_string(platinum)),
Strings::Commify(std::to_string(copper))
);
}
else if (copper && silver && !gold && !platinum) { // CS
money_string = fmt::format(
"{} Silver and {} Copper",
"{} silver and {} copper",
Strings::Commify(std::to_string(silver)),
Strings::Commify(std::to_string(copper))
);
}
else if (!copper && silver && gold && platinum) { // SGP
money_string = fmt::format(
"{} Platinum, {} Gold, and {} Silver",
"{} platinum, {} gold, and {} silver",
Strings::Commify(std::to_string(platinum)),
Strings::Commify(std::to_string(gold)),
Strings::Commify(std::to_string(silver))
@@ -423,21 +445,21 @@ std::string Strings::Money(uint64 platinum, uint64 gold, uint64 silver, uint64 c
}
else if (!copper && silver && !gold && platinum) { // SP
money_string = fmt::format(
"{} Platinum and {} Silver",
"{} platinum and {} silver",
Strings::Commify(std::to_string(platinum)),
Strings::Commify(std::to_string(silver))
);
}
else if (!copper && silver && gold && !platinum) { // SG
money_string = fmt::format(
"{} Gold and {} Silver",
"{} gold and {} silver",
Strings::Commify(std::to_string(gold)),
Strings::Commify(std::to_string(silver))
);
}
else if (copper && !silver && gold && platinum) { // CGP
money_string = fmt::format(
"{} Platinum, {} Gold, and {} Copper",
"{} platinum, {} gold, and {} copper",
Strings::Commify(std::to_string(platinum)),
Strings::Commify(std::to_string(gold)),
Strings::Commify(std::to_string(copper))
@@ -445,39 +467,39 @@ std::string Strings::Money(uint64 platinum, uint64 gold, uint64 silver, uint64 c
}
else if (copper && !silver && gold && !platinum) { // CG
money_string = fmt::format(
"{} Gold and {} Copper",
"{} gold and {} copper",
Strings::Commify(std::to_string(gold)),
Strings::Commify(std::to_string(copper))
);
}
else if (!copper && !silver && gold && platinum) { // GP
money_string = fmt::format(
"{} Platinum and {} Gold",
"{} platinum and {} gold",
Strings::Commify(std::to_string(platinum)),
Strings::Commify(std::to_string(gold))
);
}
else if (!copper && !silver && !gold && platinum) { // P
money_string = fmt::format(
"{} Platinum",
"{} platinum",
Strings::Commify(std::to_string(platinum))
);
}
else if (!copper && !silver && gold && !platinum) { // G
money_string = fmt::format(
"{} Gold",
"{} gold",
Strings::Commify(std::to_string(gold))
);
}
else if (!copper && silver && !gold && !platinum) { // S
money_string = fmt::format(
"{} Silver",
"{} silver",
Strings::Commify(std::to_string(silver))
);
}
else if (copper && !silver && !gold && !platinum) { // C
money_string = fmt::format(
"{} Copper",
"{} copper",
Strings::Commify(std::to_string(copper))
);
}
@@ -783,21 +805,6 @@ bool Strings::ToBool(const std::string& bool_string)
return false;
}
// returns a random string of specified length
std::string Strings::Random(size_t length)
{
auto randchar = []() -> char {
const char charset[] = "0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
const size_t max_index = (sizeof(charset) - 1);
return charset[static_cast<size_t>(std::rand()) % max_index];
};
std::string str(length, 0);
std::generate_n(str.begin(), length, randchar);
return str;
}
// a wrapper for stoi which will return a fallback if the string
// fails to cast to a number
int Strings::ToInt(const std::string &s, int fallback)
@@ -882,3 +889,17 @@ std::string Strings::RemoveNumbers(std::string s)
return s.substr(0, current);
}
std::string Strings::ZoneTime(const uint8 hours, const uint8 minutes)
{
return fmt::format(
"{:02}:{:02} {}",
(
(hours % 12) == 0 ?
12 :
(hours % 12)
),
minutes,
hours >= 13 ? "PM" : "AM"
);
}
+1 -1
View File
@@ -130,6 +130,7 @@ public:
static std::string Random(size_t length);
static bool BeginsWith(const std::string& subject, const std::string& search);
static bool EndsWith(const std::string& subject, const std::string& search);
static std::string ZoneTime(const uint8 hours, const uint8 minutes);
template<typename T>
static std::string
@@ -184,7 +185,6 @@ public:
value = strtod(tmp_str.data(), nullptr);
return res;
}
};
const std::string StringFormat(const char *format, ...);
+3 -3
View File
@@ -25,7 +25,7 @@
// Build variables
// these get injected during the build pipeline
#define CURRENT_VERSION "22.18.0-dev" // always append -dev to the current version for custom-builds
#define CURRENT_VERSION "22.35.0-dev" // always append -dev to the current version for custom-builds
#define LOGIN_VERSION "0.8.0"
#define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__
@@ -42,9 +42,9 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9229
#define CURRENT_BINARY_DATABASE_VERSION 9246
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9039
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9040
#endif
+10 -28
View File
@@ -121,43 +121,25 @@ bool Database::GetLoginTokenDataFromToken(
std::string &user
)
{
auto query = fmt::format(
"SELECT tbllogintokens.Id, tbllogintokens.IpAddress, tbllogintokenclaims.Name, tbllogintokenclaims.Value FROM tbllogintokens "
"JOIN tbllogintokenclaims ON tbllogintokens.Id = tbllogintokenclaims.TokenId WHERE tbllogintokens.Expires > NOW() "
"AND tbllogintokens.Id='{0}' AND tbllogintokens.IpAddress='{1}'",
auto query = fmt::format("SELECT login_server, username, account_id FROM login_tickets WHERE expires > NOW()"
" AND id='{0}' AND ip_address='{1}' LIMIT 1",
Strings::Escape(token),
Strings::Escape(ip)
);
Strings::Escape(ip));
auto results = QueryDatabase(query);
if (results.RowCount() == 0 || !results.Success()) {
return false;
}
bool found_username = false;
bool found_login_id = false;
bool found_login_server_name = false;
for (auto row = results.begin(); row != results.end(); ++row) {
if (strcmp(row[2], "username") == 0) {
user = row[3];
found_username = true;
continue;
}
if (strcmp(row[2], "login_server_id") == 0) {
db_account_id = Strings::ToUnsignedInt(row[3]);
found_login_id = true;
continue;
}
if (strcmp(row[2], "login_server_name") == 0) {
db_loginserver = row[3];
found_login_server_name = true;
continue;
}
for (auto row = results.begin(); row != results.end(); ++row) {
db_loginserver = row[0];
user = row[1];
db_account_id = Strings::ToUnsignedInt(row[2]);
return true;
}
return found_username && found_login_id && found_login_server_name;
return false;
}
/**
+11
View File
@@ -0,0 +1,11 @@
DROP TABLE IF EXISTS `login_tickets`;
CREATE TABLE `login_tickets` (
`id` VARCHAR(128) NOT NULL,
`login_server` TEXT NOT NULL,
`username` TEXT NOT NULL,
`account_id` INT(10) UNSIGNED NOT NULL,
`ip_address` VARCHAR(45) NOT NULL,
`expires` DATETIME NOT NULL,
PRIMARY KEY (`id`) USING BTREE
)
ENGINE=InnoDB;
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "eqemu-server",
"version": "22.18.0",
"version": "22.35.0",
"repository": {
"type": "git",
"url": "https://github.com/EQEmu/Server.git"
+5
View File
@@ -156,6 +156,11 @@ bool UCSDatabase::VerifyMailKey(const std::string& characterName, int IPAddress,
return false;
}
if (results.RowCount() == 0) {
LogInfo("No mailkeys found for [{}].", characterName.c_str());
return false;
}
auto row = results.begin();
// The key is the client's IP address (expressed as 8 hex digits) and an 8 hex digit random string generated
+4 -2
View File
@@ -301,9 +301,7 @@ OP_LeadershipExpUpdate=0x2797
OP_PurchaseLeadershipAA=0x6c55
OP_UpdateLeadershipAA=0x0026
OP_MarkNPC=0x1fb5
OP_MarkRaidNPC=0x5a58 #unimplemented
OP_ClearNPCMarks=0x2003
OP_ClearRaidNPCMarks=0x20d3 #unimplemented
OP_DelegateAbility=0x76b8
OP_SetGroupTarget=0x2814
OP_Charm=0x5d92
@@ -372,6 +370,7 @@ OP_AggroMeterTargetInfo=0x16bc
OP_AggroMeterUpdate=0x1781
OP_UnderWorld=0x2eb3 # clients sends up when they detect an underworld issue, might be useful for cheat detection
OP_KickPlayers=0x6770
OP_BookButton=0x6146
# Expeditions
OP_DzQuit=0xb2e3
@@ -544,6 +543,9 @@ OP_LFGResponse=0x0000
OP_RaidInvite=0x55ac
OP_RaidUpdate=0x3973
OP_RaidJoin=0x0000
OP_RaidDelegateAbility=0x2b33
OP_MarkRaidNPC=0x5a58
OP_RaidClearNPCMarks=0x20d3
# Button-push commands
OP_Taunt=0x2703
+1
View File
@@ -360,6 +360,7 @@ OP_Marquee=0x7dc9
OP_Fling=0x2b88
OP_CancelSneakHide=0x7705
OP_UnderWorld=0x51ae # clients sends up when they detect an underworld issue, might be useful for cheat detection
OP_BookButton=0x4348
# Expedition
OP_DzQuit=0x054e
+1
View File
@@ -341,6 +341,7 @@ OP_Marquee=0x2f75
OP_Untargetable=0x3e36
OP_CancelSneakHide=0x5335
OP_UnderWorld=0x7580 # clients sends up when they detect an underworld issue, might be useful for cheat detection
OP_BookButton=0x4eee
#expedition
OP_DzQuit=0x20d6
+2
View File
@@ -423,6 +423,8 @@ OP_CancelInvite=0x0000
OP_RaidJoin=0x1f21 # ShowEQ 10/27/05
OP_RaidInvite=0x5891 # ShowEQ 10/27/05
OP_RaidUpdate=0x1f21 # EQEmu 06/29/05
OP_RaidDelegateAbility=0x56eb
OP_RaidClearNPCMarks=0x1794
OP_InspectBuffs=0x4FB6
+3
View File
@@ -371,6 +371,7 @@ OP_Marquee=0x3675
OP_Fling=0x51b1
OP_CancelSneakHide=0x7686
OP_UnderWorld=0x2d9d # clients sends up when they detect an underworld issue, might be useful for cheat detection
OP_BookButton=0x018e
OP_DzQuit=0x1539
OP_DzListTimers=0x21e9
@@ -533,6 +534,8 @@ OP_LFGResponse=0x0000 #
OP_RaidInvite=0x60b5 # C
OP_RaidUpdate=0x4d8b # C
OP_RaidJoin=0x0000 #
OP_RaidDelegateAbility=0x0297
OP_RaidClearNPCMarks=0x2af4
# Button-push commands
OP_Taunt=0x30e2 # C
+12 -2
View File
@@ -1,6 +1,6 @@
#!/bin/bash
set -x
set -ex
sudo chown eqemu:eqemu /drone/src/ * -R
sudo chown eqemu:eqemu /home/eqemu/.ccache/ * -R
@@ -9,7 +9,17 @@ git submodule init && git submodule update
perl utils/scripts/build/tag-version.pl
mkdir -p build && cd build && cmake -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_STATIC=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_LUA=ON -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING="-Os" -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -G 'Unix Makefiles' .. && make -j$((`nproc`-4))
mkdir -p build && cd build && \
cmake -DEQEMU_BUILD_TESTS=ON \
-DEQEMU_BUILD_STATIC=ON \
-DEQEMU_BUILD_LOGIN=ON \
-DEQEMU_BUILD_LUA=ON \
-DEQEMU_BUILD_PERL=ON \
-DCMAKE_CXX_FLAGS:STRING="-O1 -g" \
-DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING="-O1 -g" \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-G 'Unix Makefiles' \
.. && make -j$((`nproc`-4))
curl https://raw.githubusercontent.com/Akkadius/eqemu-install-v2/master/eqemu_config.json --output eqemu_config.json
./bin/tests
+2 -2
View File
@@ -10,7 +10,7 @@ require (
require (
github.com/golang/protobuf v1.3.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/net v0.17.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
)
+4 -4
View File
@@ -10,12 +10,12 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -112,6 +112,7 @@ if ($requested_table_to_generate ne "all") {
}
my @cereal_enabled_tables = (
"data_buckets",
"player_event_logs"
);
+259 -222
View File
@@ -1,255 +1,292 @@
#! /usr/bin/perl
#!/usr/bin/perl
########################################################################
#::: 13th floor import script
#::: Current Source: http://items.sodeq.org/download.php
#::: Authors: (Natedog, Akkadius)
#::: Items Source: http://items.sodeq.org/download.php
#::: How To:
#::: 1. Place this script with your server eqemu_config.json
#::: 2. Download the items.txt file and place with this script
#::: 3. Run this script with Perl
#::: 4. Review new and updated items in the items_new table
#::: 5. Make any desired changes and replace the items table contents
########################################################################
use DBI;
use DBD::mysql;
my $database_name = "";
my $db_host = "";
my $db_port = "";
my $db_name = "";
my $db_user = "";
my $db_pass = "";
my $total_items = 0;
my $read_items_file = "items.txt"; #default
my $dbh = LoadMysql();
my $keep_temp_items_table = 0; #keeps the imported items table
read_eqemu_config_json();
my $dbh = DBI->connect("DBI:mysql:database=$db_name;host=$db_host;port=$db_port", $db_user, $db_pass) or die "Cannot connect to MySql.";
read_items_file_from_13th_floor_text();
update_items_table();
sub LoadMysql{
#::: Config Variables
my $confile = "eqemu_config.xml";
open(F, "<$confile") or die "Unable to open config: $confile\n";
my $indb = 0;
while(<F>) {
s/\r//g;
if(/<database>/i) { $indb = 1; }
next unless($indb == 1);
if(/<\/database>/i) { $indb = 0; last; }
if(/<host>(.*)<\/host>/i) { $host = $1; }
elsif(/<username>(.*)<\/username>/i) { $user = $1; }
elsif(/<password>(.*)<\/password>/i) { $pass = $1; }
elsif(/<db>(.*)<\/db>/i) { $db = $1; }
}
$database_name = $db;
#::: DATA SOURCE NAME
$dsn = "dbi:mysql:$db:localhost:3306";
#::: PERL DBI CONNECT
$connect = DBI->connect($dsn, $user, $pass);
return $connect;
print "\n\nImport complete! Review items_new table before replacing into items table.\n\n";
sub read_eqemu_config_json {
use JSON;
my $json = new JSON();
my $config;
my $config_file = "eqemu_config.json";
my $content;
open(my $fh, '<', $config_file) or die "cannot open file $config_file"; {
local $/;
$content = <$fh>;
}
close($fh);
$config = $json->decode($content);
$db_host = $config->{"server"}{"database"}{"host"};
$db_port = $config->{"server"}{"database"}{"port"};
$db_name = $config->{"server"}{"database"}{"db"};
$db_user = $config->{"server"}{"database"}{"username"};
$db_pass = $config->{"server"}{"database"}{"password"};
}
sub read_items_file_from_13th_floor_text {
#::: Read from file and place into array
open(F, "<" . $read_items_file) or die "Unable to open itemfile: " . $read_items_file . "\n";
my @item_file_lines = <F>;
close(F);
#::: Read from file and place into array
open(F, "<" . $read_items_file) or die "Unable to open itemfile: " . $read_items_file . "\n";
my @item_file_lines = <F>;
close(F);
#::: Chomp this array...
my @newitem_file_lines;
chomp($item_file_lines[0]);
@fields = split("(?<!\\\\)\\|", $item_file_lines[0]);
my $sth = $dbh->prepare("SHOW TABLES LIKE 'items_floor'");
$sth->execute();
my $has_items_floor = $sth->fetchrow_array();
#::: If we have items_floor
if ($has_items_floor eq '') {
$dbh->do("CREATE TABLE `items_floor` (`" . join("` VARCHAR(64) NOT NULL DEFAULT '', `", @fields). "` VARCHAR(64) NOT NULL DEFAULT '', UNIQUE INDEX `ID` (`id`)) COLLATE='latin1_swedish_ci' ENGINE=MyISAM");
$dbh->do("ALTER TABLE `items_floor` CHANGE `id` `id` INT(11) NOT NULL DEFAULT '0'");
printf "Database items_floor created\n";
}
#::: Create REPLACE INTO header and define worker variables...
$master_insert = "REPLACE INTO `items_floor` (" . join(",", @fields) . ") VALUES ";
$query_insert_ph = ""; #::: Used for building placeholder values in query Ex: (?, ?, ?)
@field_values = (); #::: Used for stuffing mysql field values
$query_count = 0; #::: Used for chunking query updates
$print_cycle = 0; #::: Counter for console updates
$start_time = time(); #::: Start time for import
$total_items_file = scalar(grep $_, @item_file_lines) - 1; #::: Total items in text file
#::: Chomp this array...
my @newitem_file_lines;
chomp($item_file_lines[0]);
@fields = split("(?<!\\\\)\\|", $item_file_lines[0]);
#::: Iterate through each item in items.txt
for (1 .. $#item_file_lines) {
@f = split("(?<!\\\\)\\|", $item_file_lines[$_]);
my $sth = $dbh->prepare("SHOW TABLES LIKE 'items_floor'");
$sth->execute();
my $has_items_floor = $sth->fetchrow_array();
#::: Build our individual prepared statement (?, ?) values in the insert_ph
#::: ?, ? placeholders will be resolved via @field_values in the execute
$query_insert_ph .= " (";
foreach (@f) {
push (@field_values, trim($_));
$query_insert_ph .= "?, ";
}
$query_insert_ph = substr($query_insert_ph, 0, -2);
$query_insert_ph .= "), ";
#::: If we don't have items_floor table
if ($has_items_floor eq '') {
$dbh->do("CREATE TABLE `items_floor` (`" . join("` VARCHAR(64) NOT NULL DEFAULT '', `", @fields). "` VARCHAR(64) NOT NULL DEFAULT '', UNIQUE INDEX `ID` (`id`)) COLLATE='latin1_swedish_ci' ENGINE=MyISAM");
$dbh->do("ALTER TABLE `items_floor` CHANGE `id` `id` INT(11) NOT NULL DEFAULT '0'");
printf "Database items_floor created\n";
}
#::: Let's chunk our updates so we can break up the amount of individual queries
if($query_count > 500){
$query_insert_ph = substr($query_insert_ph, 0, -2);
$dbh->prepare($master_insert . " " . $query_insert_ph)->execute(@field_values);
$query_count = 0;
$query_insert_ph = "";
@field_values = ();
}
#::: Print updates to console
if($print_cycle > 25){
print "Processing (" . $read_items_file . ") :: (Items: " . $total_items . "/" . $total_items_file . ") \r";
$print_cycle = 0;
}
#::: Create REPLACE INTO header and define worker variables...
$master_insert = "REPLACE INTO `items_floor` (" . join(",", @fields) . ") VALUES ";
$query_insert_ph = ""; #::: Used for building placeholder values in query Ex: (?, ?, ?)
@field_values = (); #::: Used for stuffing mysql field values
$query_count = 0; #::: Used for chunking query updates
$print_cycle = 0; #::: Counter for console updates
$start_time = time(); #::: Start time for import
$total_items_file = scalar(grep $_, @item_file_lines) - 1; #::: Total items in text file
#::: Counters
$total_items++;
$query_count++;
$print_cycle++;
}
#::: One last processing print
print "Processing (" . $read_items_file . ") :: (Items: " . $total_items . "/" . $total_items_file . ") \r";
printf "\n" . $total_items . " items added to database... Took " . (time() - $start_time) . " second(s)... \n";
print "Flipping slots 21 and 22...";
$rows_affected = $dbh->prepare("
UPDATE `items_floor`
SET `slots` = (`slots` ^ 6291456)
WHERE (`slots` & 6291456)
IN (2097152, 4194304)")->execute();
print " Rows affected (" . $rows_affected . ")\n";
#::: Iterate through each item in items.txt
for (1 .. $#item_file_lines) {
@f = split("(?<!\\\\)\\|", $item_file_lines[$_]);
#::: Build our individual prepared statement (?, ?) values in the insert_ph
#::: ?, ? placeholders will be resolved via @field_values in the execute
$query_insert_ph .= " (";
foreach (@f) {
push (@field_values, trim($_));
$query_insert_ph .= "?, ";
}
$query_insert_ph = substr($query_insert_ph, 0, -2);
$query_insert_ph .= "), ";
#::: Let's chunk our updates so we can break up the amount of individual queries
if($query_count > 500){
$query_insert_ph = substr($query_insert_ph, 0, -2);
$dbh->prepare($master_insert . " " . $query_insert_ph)->execute(@field_values);
$query_count = 0;
$query_insert_ph = "";
@field_values = ();
}
#::: Print updates to console
if($print_cycle > 25){
print "Processing (" . $read_items_file . ") :: (Items: " . $total_items . "/" . $total_items_file . ") \r";
$print_cycle = 0;
}
#::: Counters
$total_items++;
$query_count++;
$print_cycle++;
}
#::: One last processing print
print "Processing (" . $read_items_file . ") :: (Items: " . $total_items . "/" . $total_items_file . ") \r";
printf "\n" . $total_items . " items imported... Took " . (time() - $start_time) . " second(s)... \n";
#::: Process slots 21, 22
print "Flipping slots 21 and 22...";
$rows_affected = $dbh->prepare("
UPDATE `items_floor`
SET `slots` = (`slots` ^ 6291456)
WHERE (`slots` & 6291456)
IN (2097152, 4194304)")->execute();
print " :: Rows affected (" . $rows_affected . ")\n";
#::: Update idfile entries
print "Updating idfile entries...";
$rows_affected = $dbh->prepare("
UPDATE `items_floor`
SET `idfile` = CONCAT('IT', `idfile`)")->execute();
print " :: Rows affected(" . $rows_affected . ")\n";
}
sub update_items_table {
#::: Keep Items table sane
$query_handle = $dbh->prepare("
ALTER TABLE `items`
MODIFY COLUMN `UNK132` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL;
");
$query_handle->execute();
my @matching_table;
my @missing_items_table;
my @missing_items_floor_table;
#::: Get columns from `items`
my $sth = $dbh->prepare("SHOW COLUMNS FROM `items`;");
$sth->execute();
my @items_table;
while (my @row = $sth->fetchrow_array()) {
push(@items_table, $row[0]);
}
#::: Get columns from `items_floor`
$sth2 = $dbh->prepare("SHOW COLUMNS FROM `items_floor`");
$sth2->execute();
my @items_floor_table;
while (my @row = $sth2->fetchrow_array()) {
push(@items_floor_table, $row[0]);
}
#::: Go through the original items table columns and line them up with what columns match on 13th floor
#::: This is so we can use the matching columns to update and insert item data into `items` table
foreach $value (@items_table) {
if ( grep( /^$value$/i, @items_floor_table ) ) {
push(@matching_table, $value);
} else {
#::: What values are we missing from EMU items table..
push(@missing_items_table, $value);
}
}
#::: What values are we missing from.. 13thFloor
foreach $value (@items_floor_table) {
if ( grep( /^$value$/i, @items_table ) ) {
#DO NOTHING...
} else {
push(@missing_items_floor_table, $value);
}
}
#::: Establish items_new table
print "Setting up new items table...\n";
$dbh->do("DROP TABLE IF EXISTS items_new");
$dbh->do("CREATE TABLE items_new AS SELECT * FROM items");
#::: Go through the matched columns and build our query strings...
my $items_field_list = ""; #::: Build the field list for the INSERT (field1, field2)
my $items_floor_field_list = ""; #::: What fields we will select from items_floor table to insert into items (matched columns)
my $update_fields = ""; #::: To update an existing item entry if it exists...
print "Updating new items table...\n";
foreach $match (@matching_table) {
$match = lc($match);
$update_fields .= "`" . $match . "` = fi.`" . $match . "`, ";
$items_field_list .= "`" . $match . "`, ";
$items_floor_field_list .= "fi.`" . $match . "`, ";
}
#::: Trim ', ' off the ends
$update_fields = substr($update_fields, 0, -2);
$items_field_list = substr($items_field_list, 0, -2);
$items_floor_field_list = substr($items_floor_field_list, 0, -2);
#::: Mixed up fields...
$items_floor_field_list =~ s/booktype/booklang/g; #our booktype is mixed with theirs...
$update_fields =~ s/`booktype` = fi.`booktype`/`booktype` = fi.`booklang`/g;
my @matching_table;
my @missing_items_table;
my @missing_items_floor_table;
#::: FIELDS THAT DO NOT MATCH GO HERE
my @items_add = (
"casttime_", "endur", "range", "attuneable", "evolvinglevel", "herosforgemodel", "scrolltype",
"scriptfileid", "powersourcecapacity", "augslot1unk2", "augslot2unk2", "augslot3unk2", "augslot4unk2",
"augslot5unk2", "augslot6unk2", "recskill", "book"
);
my @items_floor_add = (
"foodduration", "endurance", "therange", "attunable", "evolvl", "heroforge1", "scrolleffecttype",
"rightclickscriptid", "powersourcecap", "augslot1unk", "augslot2unk", "augslot3unk", "augslot4unk",
"augslot5unk", "augslot6unk", "reqskill", "booktype"
);
#::: Match the mis-matched fields...
my $spot = 0;
foreach $value (@items_add) {
$items_field_list .= ", `" . $value . "`";
$update_fields .= ", `" . $value . "` = fi.`" . $items_floor_add[$spot] . "`";
$spot++;
@missing_items_table = grep {$_ ne $value} @missing_items_table;
}
foreach $value (@items_floor_add) {
$items_floor_field_list .= ", fi.`" . $value . "`";
@missing_items_floor_table = grep {$_ ne $value} @missing_items_floor_table;
}
my $update_query = "
INSERT INTO items (" . $items_field_list . ")
SELECT " . $items_floor_field_list . "
FROM items_floor fi
ON DUPLICATE KEY UPDATE " . $update_fields;
#::: Print missing fields to file
my $write_file = "missing_item_fields.txt";
open(F, ">$write_file") or die "Unable to open questfile: $write_file\n";
print F "$update_query \n\n";
print F "EQEMU items Table missing fields\n";
foreach $value (@missing_items_table) {
print F "$value\n";
}
print F "\n\n13thFloor items Table missing fields\n";
foreach $value (@missing_items_floor_table) {
print F "$value\n";
}
close(F);
#::: Number of rows affected by query
$rows = $dbh->do($update_query);
#::: Update stackables
$dbh->do("UPDATE items i SET i.stackable = 1 WHERE i.stacksize > 1");
print "Added all new items to Items table (" . $rows . ")!\n";
print "Comparing table structure...\n";
#::: Get columns from `items`
my $sth = $dbh->prepare("SHOW COLUMNS FROM `items_new`;");
$sth->execute();
my @items_table;
while (my @row = $sth->fetchrow_array()) {
push(@items_table, $row[0]);
}
#::: Get columns from `items_floor`
$sth2 = $dbh->prepare("SHOW COLUMNS FROM `items_floor`");
$sth2->execute();
my @items_floor_table;
while (my @row = $sth2->fetchrow_array()) {
push(@items_floor_table, $row[0]);
}
#::: Go through the original items table columns and line them up with what columns match on 13th floor
#::: This is so we can use the matching columns to update and insert item data into `items` table
foreach $value (@items_table) {
if ( grep( /^$value$/i, @items_floor_table ) ) {
push(@matching_table, $value);
} else {
#::: What values are we missing from EMU items table..
push(@missing_items_table, $value);
}
}
#::: What values are we missing from.. 13thFloor
foreach $value (@items_floor_table) {
if ( grep( /^$value$/i, @items_table ) ) {
#DO NOTHING...
} else {
push(@missing_items_floor_table, $value);
}
}
#::: Go through the matched columns and build our query strings...
my $items_field_list = ""; #::: Build the field list for the INSERT (field1, field2)
my $items_floor_field_list = ""; #::: What fields we will select from items_floor table to insert into items (matched columns)
my $update_fields = ""; #::: To update an existing item entry if it exists...
foreach $match (@matching_table) {
$match = lc($match);
$update_fields .= "`" . $match . "` = fi.`" . $match . "`, ";
$items_field_list .= "`" . $match . "`, ";
$items_floor_field_list .= "fi.`" . $match . "`, ";
}
#::: Trim ', ' off the ends
$update_fields = substr($update_fields, 0, -2);
$items_field_list = substr($items_field_list, 0, -2);
$items_floor_field_list = substr($items_floor_field_list, 0, -2);
#::: Mixed up fields...
$items_floor_field_list =~ s/booktype/booklang/g; #our booktype is mixed with theirs...
$update_fields =~ s/`booktype` = fi.`booktype`/`booktype` = fi.`booklang`/g;
#::: FIELDS THAT DO NOT MATCH GO HERE
my @items_add = (
"casttime_", "endur", "range", "attuneable", "evolvinglevel", "herosforgemodel", "scrolltype",
"scriptfileid", "powersourcecapacity", "augslot1unk2", "augslot2unk2", "augslot3unk2", "augslot4unk2",
"augslot5unk2", "augslot6unk2", "recskill", "book", "procunk1"
);
my @items_floor_add = (
"foodduration", "endurance", "therange", "attunable", "evolvl", "heroforge1", "scrolleffecttype",
"rightclickscriptid", "powersourcecap", "augslot1unk", "augslot2unk", "augslot3unk", "augslot4unk",
"augslot5unk", "augslot6unk", "reqskill", "booktype", "prockunk1"
);
#::: Match the mis-matched fields...
print "Matching fields...\n";
my $spot = 0;
foreach $value (@items_add) {
$items_field_list .= ", `" . $value . "`";
$update_fields .= ", `" . $value . "` = fi.`" . $items_floor_add[$spot] . "`";
$spot++;
@missing_items_table = grep {$_ ne $value} @missing_items_table;
}
foreach $value (@items_floor_add) {
$items_floor_field_list .= ", fi.`" . $value . "`";
@missing_items_floor_table = grep {$_ ne $value} @missing_items_floor_table;
}
my $update_query = "
INSERT INTO items_new (" . $items_field_list . ")
SELECT " . $items_floor_field_list . "
FROM items_floor fi
ON DUPLICATE KEY UPDATE " . $update_fields;
#::: Print missing fields to file
print "Writing query and discrepencies to file...\n";
my $write_file = "missing_item_fields.txt";
open(F, ">$write_file") or die "Unable to open file: $write_file\n";
print F "$update_query \n\n";
print F "EQEMU items table extra fields:\n";
foreach $value (@missing_items_table) {
print F "$value\n";
}
print F "\n\n13thFloor items table extra fields:\n";
foreach $value (@missing_items_floor_table) {
print F "$value\n";
}
close(F);
#::: Number of rows affected by query
$rows = $dbh->do($update_query);
print "Added or updated " . $rows . " entries.\n";
#::: Update stackables
print "Updating stackable field...\n";
$dbh->do("UPDATE items_new i SET i.stackable = 1 WHERE i.stacksize > 1");
#::: Update legacy research tome bagtypes
print "Updating legacy research tomes...\n";
$dbh->do("UPDATE items_new i SET i.bagtype = 24 WHERE i.id IN (17655, 17903)"); #RESEARCHWIZ
$dbh->do("UPDATE items_new i SET i.bagtype = 25 WHERE i.id IN (17502, 17653)"); #RESEARCHMAG
$dbh->do("UPDATE items_new i SET i.bagtype = 26 WHERE i.id IN (17501, 17654)"); #RESEARCHNEC
$dbh->do("UPDATE items_new i SET i.bagtype = 27 WHERE i.id IN (17500, 17652)"); #RESEARCHENC
#::: Remove temp table
if (!$keep_temp_items_table) {
print "Cleaning up temp items table...\n";
$dbh->do("DROP TABLE items_floor");
}
}
sub trim($) {
my $string = shift;
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return $string;
}
my $string = shift;
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return $string;
}
+1 -1
View File
@@ -44,7 +44,7 @@ echo "Generating [create_*] table exports..."
bash -c "${world_bin} database:dump --login-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_login.sql"
bash -c "${world_bin} database:dump --player-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_player.sql"
bash -c "${world_bin} database:dump --state-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_state.sql"
echo 'REPLACE INTO `instance_list` VALUES (1,25,1,1,0,0,1),(2,25,2,1,0,0,1),(3,151,1,1,0,0,1),(4,114,1,1,0,0,1),(5,344,1,1,0,0,1),(6,202,0,1,0,0,1);' >> "${dump_path}create_tables_state.sql"
bash -c "${world_bin} database:dump --static-instance-data --dump-output-to-console >> ${dump_path}create_tables_state.sql"
bash -c "${world_bin} database:dump --query-serv-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_queryserv.sql"
# with content
+2
View File
@@ -15,6 +15,7 @@ void WorldserverCLI::DatabaseDump(int argc, char **argv, argh::parser &cmd, std:
"--state-tables",
"--system-tables",
"--query-serv-tables",
"--static-instance-data",
"--table-structure-only",
"--table-lock",
"--dump-path=",
@@ -51,6 +52,7 @@ void WorldserverCLI::DatabaseDump(int argc, char **argv, argh::parser &cmd, std:
s->SetDumpWithCompression(cmd[{"--compress"}]);
s->SetDumpOutputToConsole(cmd[{"--dump-output-to-console"}]);
s->SetDumpDropTableSyntaxOnly(cmd[{"--drop-table-syntax-only"}]);
s->SetDumpStaticInstanceData(cmd[{"--static-instance-data"}]);
s->DatabaseDump();
}

Some files were not shown because too many files have changed in this diff Show More