Compare commits

...

377 Commits

Author SHA1 Message Date
Akkadius 332a1dcab1 Update windows-build.ps1 2023-01-21 00:51:26 -06:00
Akkadius 8dd8caff63 Update windows-build.ps1 2023-01-21 00:41:20 -06:00
Akkadius fc24385fd6 Update windows-build.ps1 2023-01-21 00:30:52 -06:00
Akkadius c9d8c45b39 Update windows-build.ps1 2023-01-21 00:22:52 -06:00
Akkadius 191746975c Trim windows assets 2023-01-21 00:15:11 -06:00
Akkadius 965bf0e684 Update CMakeLists.txt 2023-01-21 00:00:09 -06:00
Akkadius 4ed820039c Update linux-build.sh 2023-01-20 21:16:55 -06:00
Akkadius c931b1051e Update linux-build.sh 2023-01-20 20:25:39 -06:00
Akkadius 5375603b81 Another release test 2023-01-20 19:30:16 -06:00
Akkadius 77ad1c6f9c Update linux-build.sh 2023-01-20 17:37:02 -06:00
Akkadius 3771da84c4 Pop cache back in 2023-01-20 17:26:25 -06:00
Akkadius 77cbe4b9d4 Run it 2023-01-20 17:17:41 -06:00
Akkadius c7dcf52b82 Consolidate 2023-01-20 17:06:20 -06:00
Akkadius a942b65553 Update windows-build.ps1 2023-01-20 17:01:08 -06:00
Akkadius 62546b6f2f F 2023-01-20 16:54:10 -06:00
Akkadius 4ac0bfd69e Update windows-build.ps1 2023-01-20 16:51:43 -06:00
Akkadius 9cde2f7405 Update windows-build.ps1 2023-01-20 16:50:45 -06:00
Akkadius c17ab5a848 Update windows-build.ps1 2023-01-20 16:48:05 -06:00
Akkadius 158dd3ac97 Take #45354 2023-01-20 16:32:11 -06:00
Akkadius f5de63b1d7 Shuffle 2023-01-20 16:22:41 -06:00
Akkadius bf157eab7f Update build-release.bat 2023-01-20 16:16:09 -06:00
Akkadius 11fc66c490 Update build-release.bat 2023-01-20 16:11:14 -06:00
Akkadius f654fa6f58 Bump 2023-01-20 16:07:08 -06:00
Akkadius c75f731a82 Update CHANGELOG.md 2023-01-20 16:06:18 -06:00
Akkadius f29421a7d6 Test pipeline 2023-01-20 16:04:08 -06:00
Akkadius 0a6212f9a8 Update build-release.bat 2023-01-20 16:01:46 -06:00
Akkadius 84415b146b Update build-release.bat 2023-01-20 16:01:02 -06:00
Akkadius e4fe36088b Update .drone.yml 2023-01-20 15:59:56 -06:00
Akkadius 5aea91e680 Update .drone.yml 2023-01-20 15:58:29 -06:00
Akkadius 8d7cef6237 Update .drone.yml 2023-01-20 15:57:23 -06:00
Akkadius f65ab8d372 Update build-release.bat 2023-01-20 15:56:03 -06:00
Akkadius 217ea71bd7 Test 2023-01-20 15:54:17 -06:00
Akkadius d5f2669cab Update .drone.yml 2023-01-20 15:25:25 -06:00
Akkadius c49548c090 Update .drone.yml 2023-01-20 15:23:42 -06:00
Akkadius b615b4d474 Add version checks 2023-01-20 15:23:10 -06:00
Akkadius f151e5fbe3 Update .drone.yml 2023-01-20 14:24:25 -06:00
Akkadius 2835f79a9f Update .drone.yml 2023-01-20 14:21:00 -06:00
Akkadius 9fbdf1e7c0 exit 78 2023-01-20 14:19:21 -06:00
Akkadius 1c074ec84c Update .drone.yml 2023-01-20 14:14:52 -06:00
Akkadius aa953731ad Update .drone.yml 2023-01-20 14:02:15 -06:00
Akkadius 23ef6b9c8c Check if release 2023-01-20 13:59:10 -06:00
Akkadius 3655b1a350 Release bot test #2 2023-01-20 13:29:35 -06:00
Akkadius 9ff2d03d01 Bots release 22.0.5 (Test) 2023-01-20 13:28:54 -06:00
Akkadius eedba3949d Test 2023-01-20 13:28:54 -06:00
Akkadius 241e6e6823 Update .drone.yml 2023-01-20 13:28:54 -06:00
Akkadius d00ab2233a Filter pipeline stage 2023-01-20 13:28:54 -06:00
Akkadius af03ac7df2 Update .drone.yml 2023-01-20 13:28:54 -06:00
Akkadius 45c1a60684 Remove debug 2023-01-20 13:28:54 -06:00
Akkadius f3407f5972 Test pipeline 2023-01-20 13:28:54 -06:00
Akkadius e7b43b9e2f Update .drone.yml 2023-01-20 13:28:54 -06:00
Akkadius cf6b97c745 Update .drone.yml 2023-01-20 13:28:54 -06:00
Akkadius 26116ec808 Release without bots 2023-01-20 13:28:54 -06:00
Akkadius a6438b833c Yolo 2023-01-20 13:28:54 -06:00
Akkadius e840eeb931 Copy 2023-01-20 13:28:54 -06:00
Akkadius 6cd2cb20b5 Update .drone.yml 2023-01-20 13:28:54 -06:00
Akkadius 440eb64328 Update .drone.yml 2023-01-20 13:28:54 -06:00
Akkadius af0e64cef8 Yolo 2023-01-20 13:28:54 -06:00
Akkadius 2db28a7e42 Yolo 2023-01-20 13:28:54 -06:00
Akkadius 4bbad8678c Update .drone.yml 2023-01-20 13:28:54 -06:00
Akkadius b6e5ef5521 Update .drone.yml 2023-01-20 13:28:54 -06:00
Akkadius b22b281312 Update .drone.yml 2023-01-20 13:28:54 -06:00
Akkadius b66c65fc02 Test upload 2023-01-20 13:28:54 -06:00
Akkadius 1c7dedb12d Naming 2023-01-20 13:28:54 -06:00
Akkadius e6dc06c0c6 Update .drone.yml 2023-01-20 13:28:54 -06:00
Akkadius c445f7bed6 Test 2023-01-20 13:28:54 -06:00
Akkadius 4e0b762244 Update .drone.yml 2023-01-20 13:28:53 -06:00
Akkadius 4f3c97ff24 Update .drone.yml 2023-01-20 13:28:53 -06:00
Akkadius c5d5bf6503 Update .drone.yml 2023-01-20 13:28:53 -06:00
Akkadius a76204bd38 Update .drone.yml 2023-01-20 13:28:53 -06:00
Akkadius d828c72176 Linux 2023-01-20 13:28:53 -06:00
Akkadius 60962005d1 Remove 7z from build scripts 2023-01-20 13:28:53 -06:00
Akkadius 2a81314d49 Split 2023-01-20 13:28:53 -06:00
Akkadius 9edad8fa3b Kill excessive warnings 2023-01-20 13:28:53 -06:00
Akkadius 74f8629884 Update windows-build.ps1 2023-01-20 13:28:53 -06:00
Akkadius 6f8fc85a92 Update windows-build.ps1 2023-01-20 13:28:53 -06:00
Akkadius 87af11374c Update windows-build.ps1 2023-01-20 13:28:53 -06:00
Akkadius 90366302bd Test 2023-01-20 13:28:53 -06:00
Akkadius 92df505c6e Test 2023-01-20 13:28:53 -06:00
Chris Miles 5c095ab87a [Bots] Post pre-processor fixes (#2770)
* Fixes

* Update main.cpp
2023-01-20 13:28:39 -06:00
Akkadius e8ca3f6942 [eqemu_server.pl Swap out binary source 2023-01-20 12:56:37 -06:00
Akkadius 706a06efb6 [Appveyor] Remove bots preprocessor 2023-01-20 12:42:35 -06:00
Alex King 3335cacac1 [Bots] Cleanup and remove preprocessors. (#2757)
* [Bots] Cleanup and remove preprocessors.

- Removes every `#ifdef BOTS` we have and locks bots behind `Bots:AllowBots` rule.
- Bot updates are now done by default similar to regular database updates.
- Modify `CMakeLists.txt`, `.drone.yml`, and `BUILD.md` to match the removal of `EQEMU_ENABLE_BOTS`.

* Cleanup

- Add SQL for enabling bots for servers with bots.
- Add message that tells players/operators bots are disabled.

* Suggested changes.

* Bot injection stuff

* Change SQL to bot SQL.

* Tweaks

* Remove `is_bot`

* Update version.h

* Update main.cpp

* Update database.cpp

* Fix name availability crash

* Remove bots from update script

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-01-20 12:35:33 -06:00
Akkadius 1f0b2a8991 [Hotfix] Make sure we have a proper split size before assuming we can split it 2023-01-20 12:25:49 -06:00
Aeadoin a16f21d6fe [Bots] Add Support for AA bonuses that were missing. (#2764)
* [Bots] Add Support for AA bonuses that were missing.

* Fix GetFocusEffect, add virtual override to Bot to prevent using NPC
2023-01-19 22:45:09 -06:00
Chris Miles 900837f633 [Logging] Improvements to GM Say Logging (#2765) 2023-01-19 22:24:57 -06:00
Chris Miles d3e756287e [Logging] Remove function prefixes (#2766) 2023-01-19 22:24:50 -06:00
Vayle 7d0dd13d17 [Bug Fix] Add omitted function call in UCS (#2768) 2023-01-19 22:24:39 -06:00
Vayle ba5b901c16 [Optimization] Handle channel name filter checks in memory (#2767)
* Handle channel name filter checks in memory

With this commit, name filters are loaded into memory when the server loads and new channels are compared against these memory values VS hitting the database each time.

* Minor formatting tweaks
2023-01-19 21:23:11 -06:00
Akkadius 3424ae2dde [Hotfix] Fix door click crash issue if destination zone doesn't exist 2023-01-19 19:06:58 -06:00
Chris Miles 9aad8ae54c [Logging] Force crash logs to always be on regardless of setting (#2762) 2023-01-19 18:21:44 -06:00
JJ 7cd6b4b8ab [SQL] Update 2023_01_15_merc_data.sql (#2763)
Odd spacing. Someone fell asleep on the keyboard.
2023-01-19 18:20:46 -06:00
Aeadoin 090019cf83 [Bot] Restrict Bot Groups from spawning while Feigned. (#2761) 2023-01-19 16:52:20 -06:00
Chris Miles d93ea9ed86 [Zone Flags] Use database connection, not content connection (#2759) 2023-01-19 15:11:40 -06:00
Chris Miles a7b35594f8 [Fix] Zone Flags Regression (#2760) 2023-01-19 15:11:32 -06:00
Vayle 29473aa7f5 [Rules] Add rule to allow players to permanently save chat channels to database, up to a limit. (#2706)
* Initial code

* Tweak

* Rule description tweak

* More channel work

* More adjustments

* Auto-join saved permanent player channels

* Fix UCS crash if player has no channels to load from table.

* Implemented channel blocking feature

* Update database when player channel's owner or password change

* First round of requested changes.

* Logic tweak to ensure player channels are sets to permanent when appropraite

* name_filter table integration and some refactoring

* Use new `reserved_channel_names` table to block specific channel names.

* Remove some legacy channel block code

* Setup required SQL update to create  `reserved_channel_names`  table.

* Update db_update_manifest.txt

* Update db_update_manifest.txt

* Update chatchannel.cpp

* Code review

* Database to UCSDatabase

* Repository SaveChatChannel

* CurrentPlayerChannelCount repository

* Cleanup name filter

* CreateChannel

* Update websocketpp

* Increment CURRENT_BINARY_DATABASE_VERSION

Set to 9216

* Minor tweaks to blocked channel name checks & other related areas.

- Enforce blocked channel names on channel creation.
- Also enforce blocked channel names on channel join.
- Add channel status check to Debug logging.
- Minor formatting adjustments.
- Add single quotes to column name value in query.

* Minor log change

* Increment DB Version

* Formatting Tweaks

- Made formatting adjustments consistent with KinglyKrab's recommended changes.
- This compiles successfully with these changes, but unable to test the changes until this weekend.

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-01-18 22:42:09 -06:00
Aeadoin 03a27b02ff [Hotfix] Login Server failing to compile on Windows. (#2758) 2023-01-18 21:21:36 -05:00
Akkadius f9ea7ddb62 [Logging] Reset stream so we don't bold the whole line 2023-01-17 21:39:18 -06:00
Chris Miles 40d1c33351 [Logging] Logging Improvements (#2755)
* Console logging improvements

* stderr handling

* Add origination information

* Formatting

* Update zoneserver.cpp

* Update eqemu_logsys.cpp

* Remove semicolon from MySQLQuery log output

* Remove IsRfc5424LogCategory

* Remove no longer used functions

* Remove definition BUILD_LOGGING

* Deprecate categories UCSServer & WorldServer

* Deprecate UCS / World Server / Zone Server categories

* Deprecate Status, QSServer, Normal

* Update login_server.cpp

* Deprecate Emergency, Alert, Critical, Notice

* Deprecate Alert

* Fix terminal color resetting

* Deprecate headless client

* Move LogAIModerate to Detail

* Deprecate moderate logging level for detail

* Update logs.cpp

* Logs list simplify

* Update logs.cpp

* Add discord to log command

* Remove unused headers

* Windows fix

* Error in world when zones fail to load

* Show warning color properly

* Keep loginserver thread log from colliding with other logs during startup

* Deprecate Loginserver category
2023-01-17 21:18:40 -06:00
Michael Cook (mackal) ee2079ec35 [C++20] Arithmetic on different enums is deprecated (#2752)
Just do some casts and add some constants to make life easier
2023-01-17 15:21:01 -06:00
Xackery a90c760186 [Code] Removed vscode setting (#2753) 2023-01-17 15:20:36 -06:00
Alex King fbb36a3e75 [Mercs] Add Mercenary Support (#2745)
* [Mercs] Add Mercenary Support

# Notes
- Adds `--merc-tables` support to database dumper.
- Adds Mercenary-based repositories.
- Adds required SQL `2023_01_15_merc_data.sql` to insert the tables for those who don't already have them.
- Adds optional SQL `2023_01_15_merc_liaisons.sql` to change NPCs to the Mercenary Liaison class optionally.

* Inline.

* Trim tables_to_dump output

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-01-17 16:19:55 -05:00
Aeadoin bd29f1c5bb [Bug Fix] Handle_OP_AugmentItem could cause Zone crash (#2750) 2023-01-17 14:34:28 -05:00
Natedog2012 a99e0a4b2c [Bug Fix] Move EVENT_SPAWN for adding NPCs back to original spot, also add NPCs… (#2749)
* Move EVENT_SPAWN for adding NPCs back to original spot, also add NPCs to npc/mob list before parsing

* Adjust bots EVENT_SPAWN before spawn packet
2023-01-16 22:32:19 -05:00
Aeadoin be03628aa9 [Bug Fix] Fix Group XP not working. (#2748) 2023-01-16 19:10:19 -05:00
Aeadoin f1a6006ee1 [Hotfix] Resolve Zone Crashing when grouped with Bots. (#2747)
* [Hotfix] Resolve Zone Crashing when grouped with Bots.

* Fixed SpawnBotGroupByName as well.

* rename variables
2023-01-16 16:50:38 -05:00
Aeadoin dd40f2a0e6 [Bug Fix] Fix ST_TargetsTarget Spells with Restrictions (#2746) 2023-01-15 17:55:34 -05:00
Aeadoin 7fa421d848 [Bug Fix] HasPet() Zone Crashes (#2744)
* [Bug Fixes] Fix for HasPet() Zone Crashes

* HasPets const

* Remove checking This

* formatting
2023-01-15 17:16:17 -05:00
Alex King 00658632de [Cleanup] Make use of std::abs where possible. (#2739)
# Notes
- Resolves https://github.com/EQEmu/Server/issues/338
2023-01-15 17:02:13 -05:00
Alex King eed45e5250 [Quest API] Add SendPath() to Perl/Lua. (#2740)
* [Quest API] Add SendPath() to Perl/Lua.

# Perl
- Add `$client->SendPath(target)`.

# Lua
- Add `client:SendPath(target)`.

# Notes
- Allows operators to send a path to a target arbitrarily with a script.

* Update client.cpp
2023-01-15 17:02:06 -05:00
Alex King 64c62c4f0a [Feature] Add Rule to Disable Group EXP Modifier. (#2741)
# Notes
- Adds `Character:EnableGroupEXPModifier`, defaults to `true`.
- Adds `Character:GroupMemberEXPModifier`, defaults to `0.2`.
- Adds `Character:FullGroupEXPModifier`, defaults to `2.16`.
- Allows operators to enable or disable the group experience modifier based on number of members.
- Allows operators to change the modifier per member in the group between `2` and `5`.
- Allows operators to change the full group experience modifier.
2023-01-15 17:01:59 -05:00
Paul Coene ca0ae3cb98 [Rule] Add rule for NPC Level Based Buff Restrictions. (#2708)
* [Rule] Add rule for NPC Level Based Buff Restrictions.

* Erroneous whitespace

* Change prefix on log message

* Added log message when GM casts
2023-01-15 15:30:42 -06:00
Chris Miles 9e3539295b [QS] Database class name change (#2743) 2023-01-15 14:37:39 -06:00
Chris Miles 7aa25f17f6 [UCS] Database class name change (#2742) 2023-01-15 14:16:23 -06:00
Chris Miles e1c1d55ca5 [Websocket] Fix cpp20/gcc11 compile failure (#2737) 2023-01-15 11:00:24 -06:00
Aeadoin 403c54362e [Bot/Merc] Cleanup methods, and virtual overrides. (#2734)
* [Bot] Cleanup methods, and virtual overrides.

* Remove Bot::CheckAggroAmount & Bot::CheckHealAggroAmount

* formatting
2023-01-14 23:32:19 -05:00
Alex King a422484307 [Quest API] Add Client Augment Events to Perl/Lua. (#2735)
* [Quest API] Add Client Augment Events to Perl/Lua.

# Perl
- Add `EVENT_AUGMENT_INSERT_CLIENT`.
- Add `EVENT_AUGMENT_REMOVE_CLIENT`.

# Lua
- Add `event_augment_insert_client`.
- Add `event_augment_remove_client`.

# Notes
- Allows operators to use augment insert and augment remove events outside of an item script.
2023-01-14 23:23:48 -05:00
Alex King c41f375129 [Bug Fix] Fix issue with Bot::LoadAndSpawnAllZonedBots. (#2733)
* [Bug Fix] Fix issue with Bot:;LoadAndSpawnAllZonedBots.

# Notes
- Bots could spawn beyond class/global limits due to being stuck in group limbo and spawning when you enter a zone properly.

* Debug messages.

* Remove unspawned bots from group.

* Update bot.cpp

* Update bot.cpp

* Update bot.cpp

* Update bot.cpp

* >= 0
2023-01-14 23:15:26 -05:00
Alex King bd3e8b2afc [Quest API] Add Bot Methods to Lua. (#2731)
# Perl
- Minor cleanup of variable types.

 # Lua
- Add `bot:GetAugmentAt(slot_id, augment_index)`.
- Add `bot:GetItemAt(slot_id)`.
- Add `bot:SendSpellAnim(target_id, spell_id)`.
- Properly implemented `bot:GetItemIDAt(slot_id)`.

# Notes
- `bot:GetItemIDAt` existed in Lua, but didn't have a bind definition, so was non-functional.
- This makes Perl/Lua bot methods 1:1 as Perl had 75 and Lua had 72, they now both have 75.
2023-01-14 09:16:11 -06:00
Alex King f5523b40d2 [Quest API] Add CampAllBots() to Perl/Lua. (#2732)
# Perl
- Add `$client->CampAllBots()`.
- Add `$client->CampAllBots(class_id)`.

# Lua
- Add `client:CampAllBots()`.
- Add `client:CampAllBots(class_id)`.

# Notes
- Adds constants for `NO_CLASS` which is class `0` and uses `RACE_DOUG_0` for any spots that use race ID `0`.
- Cleans up magic number usage of race/class of `0`.
2023-01-14 09:14:50 -06:00
Alex King 095f4fb56c [Quest API] Add SignalAllBotsByOwnerName() to Perl/Lua. (#2730)
# Perl
- Add `$entity_list->SignalAllBotsByOwnerName(owner_name)`.

# Lua
- Add `eq.get_entity_list():SignalAllBotsByOwnerName(owner_name)`.

# Notes
- Adds a way to signal all bots by owner name instead of only character ID.
2023-01-13 04:54:20 -06:00
Alex King f8afadf0a9 [Cleanup] Remove unused basic_functions.h (#2729)
# Notes
- This file is unused and not included in any other files.
2023-01-13 04:52:32 -06:00
Alex King 9c23882d67 [Cleanup] Remove unused maxskill.h. (#2728)
# Notes
- This file is unused, noticed it when looking through source. Nothing calls this method or includes this file.
2023-01-13 04:52:08 -06:00
Aeadoin 3510ba2493 [Bug Fix] Fix Aug Clicks where item has no click effect. (#2725) 2023-01-12 12:46:42 -05:00
Chris Miles db7ab7a3ef [Diawind] Plus sign markdown fix (#2727) 2023-01-12 10:39:59 -06:00
Cole-SoD 6d13f46c40 [Bug Fix] Fix luamod GetExperienceForKill return value 2023-01-12 08:34:49 -05:00
Alex King 2f90f26351 [Quest API] Add Door Methods to Perl/Lua. (#2724)
# Perl
- Add `$door->ForceClose(sender)`.
- Add `$door->ForceClose(sender, alt_mode)`.
- Add `$door->ForceOpen(sender)`.
- Add `$door->ForceOpen(sender, alt_mode)`.
- Add `$door->GetDisableTimer()`.
- Add `$door->SetDisableTimer(disable_timer)`.

# Lua
- Add `door:GetID()`.

# Notes
- Makes Perl/Lua Door scripting capabilities 1:1.
2023-01-11 19:10:38 -05:00
Natedog2012 3341c0b7ab [Luamod] Add CalcSpellEffectValue_formula to luamods (#2721)
* [Luamod] Add CalcSpellEffectValue_formula to luamods with example code in utils/mods/spell_formula.lua

* Fix typo

* Change formula down to uint32, fix format issues and remove debug on lua file
2023-01-11 17:49:35 -06:00
Aeadoin 2587a7fed5 out of bound (#2723) 2023-01-11 17:54:42 -05:00
Aeadoin 46fa2e589e [Bug Fix] Add Complete Heal Spell back to IsCompleteHealSpell Method (#2722)
* [Bug Fix] Add Complete Heal Spell back to IsCompleteHealSpell Method

* Typo
2023-01-11 12:02:46 -05:00
Chris Miles fc020b7580 [API] Reload API (#2716)
* [API] Reload API

* Update eqemu_api_world_data_service.cpp

* Add api get_reload_types

* Update eqemu_api_world_data_service.cpp
2023-01-11 07:45:48 -06:00
Alex King 933293098b [Bug Fix] Fix Bot "Failed to Load" Messages. (#2719)
* [Bug Fix] Fix Bot "Failed to Load" Messages.

# Notes
- Bots were producing error messages for "failing to load" spells and inventory when the bot had no spells, like a Warrior, or when the bot was naked, like a newly created bot.

* Update botspellsai.cpp
2023-01-10 21:45:04 -05:00
Alex King 4df9fa89bc [Quest API] Add Bot::Camp() to Perl/Lua. (#2718)
# Perl
- Add `$bot->Camp()`.
- Add `$bot->Camp(save_to_database)`.

# Lua
- Add `bot:Camp()`.
- Add `bot:Camp(save_to_database)`.

# Notes
- Saves to database by default, overload is for edge case where a user may not want bot to save to database.
2023-01-10 21:44:55 -05:00
Alex King 09d1dc6a24 [Lua Bind] Fix INT64 Support for Windows. (#2717)
# Notes
- Temporary fix for `int64` and `uint64` support in Lua on Windows.
2023-01-10 21:28:45 -05:00
Aeadoin 8fe02b5ed1 [Bot] Add GetBotOwnerByBotID Method (#2715)
* [Bot] Add GetBotOwnerByBotID Method

* Cleanup.

* Remove EVENT_DESPAWN exports in Lua.

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2023-01-10 21:14:42 -05:00
Alex King 0d23ffe5e5 [Zones] Add Max Level Check to Zones. (#2714)
* [Zones] Add Max Level Check to Zones.

# Perl
- Add `$client->CanEnterZone(zone_short_name)`.
- Add `$client->CanEnterZone(zone_short_name, instance_version)`.

# Lua
- Add `client:CanEnterZone(zone_short_name)`.
- Add `client:CanEnterZone(zone_short_name, instance_version)`.

# Notes
- Allows operators to limit zones to a maximum level.
- Allows operators to see if a player can enter a zone before sending them.
- Keeps players from entering via `#peqzone` and `#zone` as well if they do not meet the requirements or are not high enough status to bypass the requirements.

* Cleanup.
2023-01-10 20:47:37 -05:00
Alex King 4c8b65ecc6 [Quest API] Add EVENT_BOT_CREATE to Perl/Lua (#2713)
* [Quest API] Add EVENT_BOT_CREATE to Perl/Lua

# Perl
- Add `EVENT_BOT_CREATE`.
- Exports `$bot_id`, `$bot_name`, `$bot_class`, `$bot_race`, and `$bot_gender`.

# Lua
- Add `event_bot_create`.
- Exports `e.bot_id`, `e.bot_name`, `e.bot_class`, `e.bot_race`, and `e.bot_gender`.
2023-01-08 21:46:40 -05:00
Alex King 0c105a2b91 [Bug Fix] Fix NPC Reference in EVENT_SPAWN (#2712)
* [Bug Fix] Fix NPC Reference in EVENT_SPAWN

# Notes
- Event parsing was too early and memory wasn't fully allocated, meaning that sometimes you could use the NPC reference and other times you couldn't.
- Most people worked around this by setting timers in `EVENT_SPAWN` then using `EVENT_TIMER` to handle the stuff they wanted to do on spawn.

# Example Code in Perl
```pl
sub EVENT_SPAWN {
	quest::shout($npc->GetCleanName() . " just spawned with an ID of " . $npc->GetID() . " and an NPC Type ID of " . $npc->GetNPCTypeID() . ".");
}```

* Update bot.cpp
2023-01-08 11:27:17 -05:00
Aeadoin 2253e43d2c [AI] Add Support to Heals to allow Trigger based spells (#2709) 2023-01-07 19:04:41 -05:00
Aeadoin 5f244c2dd2 [Bots] Fix Bot Spell Type "In Combat Buffs" (#2711) 2023-01-07 19:04:29 -05:00
Paul Coene 9e5a530f0f [Bug Fix] #npcstats command displaying incorrect faction (#2710) 2023-01-07 19:02:19 -05:00
Vayle ebf69e9b6e [Bug Fix] Resolve XP Calculation Bug introduced w/ recent Rule addition (#2703)
* [Bug Fix] Resolve XP Calculation Bug introduced w/ recent Rule addition

* Camel case.

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2023-01-07 12:04:52 -05:00
Alex King c1ad086eaf [Quest API] Add Despawn Events to Perl/Lua. (#2707)
# Perl
- Add `$bot->GetBotID()`.
- Add `EVENT_DESPAWN`.
- Add `EVENT_DESPAWN_ZONE`.

# Lua
- Add `bot:GetBotID()`.
- Add `event_despawn`.
- Add `event_despawn_zone`.

# Notes
- Allows operators to determine when a Bot or an NPC has been despawned via Depop.
- Bots call NPC::Depop on ^camp so we just put the code there.
- Adds the ability to get a bot's ID using their reference in case you're looping a list and need that value.
- Moves `DispatchZoneControllerEvent` from NPC to Mob so it can be used by any type.
2023-01-07 12:04:33 -05:00
Aeadoin 143c4fe6aa [Quest API] Add option to Ignore Mods to CalcEXP (#2704)
# Perl
- Add `$client->CalcEXP(consider_level, ignore_modifiers)`.

# Lua
- Add `client:CalcEXP(consider_level)`.
- Add `client:CalcEXP(consider_level, ignore_modifiers)`.

# Notes
- Allows operators to calculate experience based on consider level as well as ignore modifiers to get a baseline of experience that should be expected when killing a mob.
2023-01-05 20:38:08 -05:00
Alex King d9f437d90f [Commands] Cleanup #guild Command (#2693)
# Commands
- Adds `#guild search [Search Criteria]` sub command.

# Notes
- Allows operators to search for a guild instead of listing all guilds at once.
- Adds a method for sending guild sub commands to make code drier.
2023-01-04 16:20:43 -05:00
Aeadoin b15e73e1b2 [Bug Fix] AltCurrencySelectItemReply_Struct was not handled correctly. (#2702) 2023-01-04 14:49:43 -05:00
Vayle 6e1c4b768f [Quest API] Add GetLeader() and GetLeaderName() to Perl/Lua. (#2701)
* [Quest API] Add $raid->GetLeader() and $raid->GetLeaderName()

* Remove semicolon

* Tweaks

* Remove inline

* Add LUA compatibility

* Add GetLeaderName() to LUA

* Cast leadername to string

* Fix GetLeaderName return type

* Tweak
2023-01-03 20:17:19 -05:00
Alex King a80a6de59f [Commands] Add #findcharacter Command. (#2692)
# Commands
- Add `#findcharacter [Search Criteria]`.

# Notes
- Allows operators to search for characters by ID or a portion of their name to easily get ID/Name.
2023-01-03 14:32:21 -05:00
Alex King af4ee9f8d8 [Rules] Add LDoN Loot Count Modifier Rule (#2694)
# Notes
- Adds a rule for LDoN Adventure Loot.
2023-01-03 14:32:13 -05:00
Alex King c7dde7832d [Commands] Add #setanon Command (#2690)
* [Commands] Add #setanon Command.

# Commands
- Adds `#setanon [Anonymous Flag]`.

# Notes
- Allows operators to turn on/off a player's anonymous flag so they can view their Magelo.

* Update eq_constants.h

* Add character ID support.

* Update setanon.cpp
2023-01-03 12:06:20 -05:00
Vayle 8c939ad8da [Bug Fix] Fixed message on promote/demote permissions check. (#2700)
* [Bug Fix] Fixed message on demote permissions check.

* Included promote fix

* Formatting consistency, grammar, use constants

* Further use of constants/consistency of error/failure message colors
2023-01-02 13:08:47 -05:00
Alex King f322e85d4e [Bug Fix] Fix #door Save (#2699)
* [Bug Fix] Fix #door Create

# Notes
- Using `#door create` then `#door save` was overwriting doors instead of using the next highest ID.
- Remove the following unused commands.
```cpp
uint32 GetGuildEQID(uint32 guilddbid);
void UpdateDoorGuildID(int doorid, int guild_id);
int32 GetDoorsCount(uint32* oMaxID, const char *zone_name, int16 version);```

* Update doors.cpp

* Update doors.cpp

* Update doors.cpp
2023-01-01 22:53:34 -05:00
Alex King 7e13d07108 [Bug Fix] EVENT_ENTER_AREA/EVENT_LEAVE_AREA. (#2698)
Should be EventPlayer, not EventNPC.
2023-01-01 19:43:42 -06:00
Alex King 3e4231c662 [Quest API] Cleanup Proximity Events (#2697)
* [Quest API] Cleanup Proximity Events

# Perl
- Add `$area_id` export to EVENT_ENTER_AREA.
- Add `$area_type` export to EVENT_ENTER_AREA.
- Add `$area_id` export to EVENT_LEAVE_AREA.
- Add `$area_type` export to EVENT_LEAVE_AREA.

# Notes
- This is so Spire will parse these events properly.

* Update entity.cpp

* Update entity.cpp

* Update entity.cpp

* Update entity.cpp
2023-01-01 18:07:14 -06:00
Alex King 039d4f09e3 [Hotfix] Lua Parser Needs Lua_ItemInst (#2696) 2023-01-01 16:00:58 -06:00
Alex King c544221838 [Bug Fix] Fix #zone 0. (#2691)
# Notes
- `#zone 0` was used to send you to safe coordinates, this has been broken for a while now.
2023-01-01 13:55:17 -05:00
Alex King 16103b510d [Hotfix] Blocks are nested too deeply. (#2689) 2023-01-01 12:40:31 -05:00
Alex King 0b8b363c13 [Quest API] Add DoesAugmentFit() to Perl/Lua. (#2688)
# Perl
- Add `quest::does_augment_fit(item, augment_id)`.

# Lua
- Add `eq.does_augment_fit(item, augment_id)`.

# Notes
- Returns the augment slot index where the augment fits within the item instance provided, returns `-1` if it doesn't fit or has no open slot to fit in.
2023-01-01 12:20:07 -05:00
Alex King 1531650b3a [Quest API] Add Augment Slot Type/Visible to GetItemStat (#2686)
* [Quest API] Add Augment Slot Type/Visible to GetItemStat

# Notes
- Adds the ability to get an item's augment slot types and augment slot visibility information.

* const
2023-01-01 11:35:15 -05:00
Alex King 3a4ba6f422 [Quest API] Add DoAugmentSlotsMatch() to Perl/Lua. (#2687)
# Perl
- Add `quest::do_augment_slots_match(item_one, item_two)`.

# Lua
- Add `eq.do_augment_slots_match(item_one, item_two)`.

# Notes
- Allows operators to see if augments slots across two items match for something like moving augments from one item to another.
2023-01-01 11:25:37 -05:00
Alex King 501ea4b736 [Quest API] Add Charges/Augment/Attuned Support to Varlink. (#2685)
# Perl
- Add `quest::varlink(item_id, charges)`.
- Add `quest::varlink(item_id, charges, aug1)`.
- Add `quest::varlink(item_id, charges, aug1, aug2)`.
- Add `quest::varlink(item_id, charges, aug1, aug2, aug3)`.
- Add `quest::varlink(item_id, charges, aug1, aug2, aug3, aug4)`.
- Add `quest::varlink(item_id, charges, aug1, aug2, aug3, aug4, aug5)`.
- Add `quest::varlink(item_id, charges, aug1, aug2, aug3, aug4, aug5, aug6)`.
- Add `quest::varlink(item_id, charges, aug1, aug2, aug3, aug4, aug5, aug6, attuned)`.

# Lua
- Add `eq.item_link(item_id, charges)`.
- Add `eq.item_link(item_id, charges, aug1)`.
- Add `eq.item_link(item_id, charges, aug1, aug2)`.
- Add `eq.item_link(item_id, charges, aug1, aug2, aug3)`.
- Add `eq.item_link(item_id, charges, aug1, aug2, aug3, aug4)`.
- Add `eq.item_link(item_id, charges, aug1, aug2, aug3, aug4, aug5)`.
- Add `eq.item_link(item_id, charges, aug1, aug2, aug3, aug4, aug5, aug6)`.
- Add `eq.item_link(item_id, charges, aug1, aug2, aug3, aug4, aug5, aug6, attuned)`.

# Notes
- Allows operators to link items with specific charges, augments, and attuned flag.
- Gives much more versatility to the varlink/item_link methods.
2023-01-01 10:49:07 -05:00
Aeadoin aeda7127ec [Git] Add Clangd Generated Files to .gitignore (#2684) 2022-12-31 12:24:13 -05:00
Aeadoin 9c3c5b5230 [Experience] Change Exp Calculations to be 64 bit where needed. (#2677)
* [Experience] Change Exp Calculations to be 64 bit where needed.

* Fix lua values

* Formatting
2022-12-30 22:03:30 -05:00
Aeadoin f962466573 [Hotfix] Corrected misnamed Database Query file for Experience Toggle (#2683)
* [Hotfix] Correct misnamed DB script

* [Hotfix] Fix misnamed DB file
2022-12-30 21:50:35 -05:00
Alex King a6fa6084fa [Feature] Add Experience Gain Toggle. (#2676)
* [Feature] Add Experience Gain Toggle.

# Perl
- Add `$client->IsEXPEnabled()`.
- Add `$client->SetEXPEnabled(is_exp_enabled)`.

# Lua
- Add `client:IsEXPEnabled()`.
- Add `client:SetEXPEnabled(is_exp_enabled)`.

# Commands
- Add `#exptoggle [Toggle] - Toggle your or your target's experience gain.`.

# Notes
- Allows operators to turn on/off a player's experience gain individually without changing their rule values.
- The command allows operators to give players access to the command to disable their own experience gain.
2022-12-30 17:30:23 -05:00
Aeadoin 0c9c78fbab [Bot Commands] Toggle Enforce Spell Settings (#2682)
* [Bot Commands] Toggle enforcespellsettings

* Cleanup

* Update bot_command.cpp

Co-authored-by: Alex King <89047260+Kinglykrab@users.noreply.github.com>
2022-12-30 17:18:05 -05:00
Aeadoin 8fc665a3c1 [Bug Fix] NPC Constructor was passing hp_regen_per_second out of order to Mob(). (#2681) 2022-12-29 15:29:52 -05:00
Alex King 7e7485be77 [Quest API] Add BuffCount() Overloads to Perl/Lua. (#2679)
# Perl
- Add `$mob->BuffCount(is_beneficial)`.
- Add `$mob->BuffCount(is_beneficial, is_detrimental)`.

# Lua
- Add `mob:BuffCount(is_beneficial)`.
- Add `mob:BuffCount(is_beneficial, is_detrimental)`.

 # Notes
- Allows operators to count only beneficial or detrimental buffs a mob has instead of always counting all buffs.
2022-12-29 11:58:38 -05:00
Alex King a590ea1d52 [Feature] Add "Keeps Sold Items" Flag to NPCs (#2671)
# Perl
- Add `$npc->GetKeepsSoldItems()`.
- Add `$npc->SetKeepsSoldItems(keeps_sold_items)`.

# Lua
- Add `npc:GetKeepsSoldItems()`.
- Add `npc:SetKeepsSoldItems(keeps_sold_items)`.

# Notes
- Allows operators to keep specific NPCs from keeping items sold to them.
- Keeps NPCs from being cluttered with stuff like Cloth Caps, Bone Chips, etc.
2022-12-25 16:36:20 -05:00
Alex King 2ed73199bf [Quest API] Add IsAttackAllowed() to Perl/Lua. (#2672)
# Perl
- Add `$mob->IsAttackAllowed(target)`.
- Add `$mob->IsAttackAllowed(target, is_spell_attack)`.

# Lua
- Add `mob:IsAttackAllowed(target)`.

# Notes
- Lua had `mob:IsAttackAllowed(target, is_spell_attack)` but not the other overload.
- Perl had neither.
2022-12-25 16:18:00 -05:00
Alex King d1430f6834 [Quest API] Add IsAttackAllowed() to Perl/Lua. (#2672)
# Perl
- Add `$mob->IsAttackAllowed(target)`.
- Add `$mob->IsAttackAllowed(target, is_spell_attack)`.

# Lua
- Add `mob:IsAttackAllowed(target)`.

# Notes
- Lua had `mob:IsAttackAllowed(target, is_spell_attack)` but not the other overload.
- Perl had neither.
2022-12-25 16:17:46 -05:00
Aeadoin 860b545fe3 [Rules] Change TradeskillUp Rules to be Floats (#2674)
* [Rules] Change TradeskillUp Rules to be Floats

* update rule values so it's obvious they are floats.
2022-12-25 16:09:16 -05:00
Vayle 8219cc9ea0 [Rules] Rule to allow cap on % XP gain per kill (#2667)
* [Rules] Add rule to limit single kill xp gain

Adds a rule to allow server operators to restrict XP gain/kill to a specified % of their current level.

* Logic correction

* Commenting

* Logic tweaks

* Rule description update

* Logic adjustment

Changed to allow xp cap > 100% and -1 = disabled

* Formatting

* Removed extra space

* Formatting

Renamed rule to be more clear.
Updated rule description.
Minor formatting tweaks.
Implemented use of descriptive bools.

* Data type adjustment

* Removed Bools

* Update exp.cpp

* Update exp.cpp

* Update exp.cpp

* Update exp.cpp

Co-authored-by: Alex King <89047260+Kinglykrab@users.noreply.github.com>
2022-12-25 15:59:05 -05:00
Alex King d7ae3d5c6d [Quest API] Add GetAugmentIDsBySlotID() to Perl/Lua. (#2673)
* [Quest API] Add GetAugmentIDsBySlotID() to Perl/Lua.

# Perl
- Add `$client->GetAugmentIDsBySlotID(slot_id)`.
- Add `$inventory->GetAugmentIDsBySlotID(slot_id)`.

# Lua
- Add `client:GetAugmentIDsBySlotID(slot_id)`.
- Add `inventory:GetAugmentIDsBySlotID(slot_id)`.

# Notes
- Allows operators to get a list of augments from a specific slot instead of having to build a plugin or something to do it.
- Fix issue with Lua tables starting at index `1` versus index `0`, so you lost the first value of the table due to this.

* Update inventory_profile.cpp
2022-12-25 15:14:54 -05:00
Aeadoin 6229852331 [Commands] #reload level_mods could cause Non-Booted zones to crash. (#2670) 2022-12-24 12:50:04 -05:00
Aeadoin 5bb27dd4c0 [Commands] Fix Flymode Command Help Prompt (#2669) 2022-12-22 19:37:54 -05:00
Aeadoin 2f9a6daab5 [Client] Remove unimplemented Client Insight Method. (#2663)
* [Cleanup] Remove unused Insight Method, and cleanup Magic Numbers

* change emu->NPC back to 0, not Doug
2022-12-21 18:41:56 -05:00
Vayle d5aecb228a [Rules] Add Backstab Rules (#2666)
* [Rules] Add backstab rules

Add rules to disable elemental and bane damage on backstab.

* Update special_attacks.cpp

Co-authored-by: Alex King <89047260+Kinglykrab@users.noreply.github.com>
2022-12-21 18:41:25 -05:00
Aeadoin e811cb1e85 [Hotfox] Compiling fails on FMT 9.1 with Bots (#2665) 2022-12-21 16:20:47 -05:00
Chris Miles c236c57a2c [C++20] Enable C++20 + Fixes + FMT 9.1 (#2664)
* [CPP] Enable and build compliance with cpp20

* Windows build fix

* bump fmt version

* Updated fmt to 9.1, updated cmake minimum and verified preprocessor stuff works.

* Missing :

* Fix warning: top-level comma expression in array subscript is deprecated

* Fix warning: top-level comma expression in array subscript is deprecated

Co-authored-by: KimLS <KimLS@peqtgc.com>
2022-12-20 21:52:36 -06:00
Chris Miles db12c069ef [Luabind] Silence deprecation warning (#2657)
* [Luabind] Silence deprecation warning

* [libuv] Bump to v1.44.2 from v1.26.0

* Revert "[libuv] Bump to v1.44.2 from v1.26.0"

This reverts commit c794735d16.

* Update libuv
2022-12-20 13:13:04 -06:00
Chris Miles 4ea38bf896 [libuv] Bump to v1.44.2 from v1.26.0 (#2658) 2022-12-20 13:12:55 -06:00
Chris Miles 0d1fa9e96e [Repositories] Add Cereal support to repository generator (#2660)
* [Repositories] Add Cereal support to repository generator

* Update base_repository.template
2022-12-20 13:12:44 -06:00
Chris Miles 51c62d3b3e [Cereal] Bump to v1.3.2 from v1.2.2 (#2654) 2022-12-20 13:12:35 -06:00
Aeadoin 900e1aecf6 [Cleanup] Cleanup magic numbers (#2662)
* [Cleanup] Cleanup magic numbers

* renamed RACE_NODE
2022-12-20 11:31:42 -05:00
Aeadoin ed6194ad19 [Aggro] Cleanup Mob::CombatRange (#2652)
* [Aggro] Cleanup Mob::CombatRange

* Change to Race_ constants
2022-12-19 21:08:50 -06:00
Michael e6f58382de [Rule] Add ManaOnDeath and EndurOnDeath (#2661)
* [Rule] Add ManaOnDeath and EndurOnDeath
This rule allows death to fully fill Mana or Endurance.

* Updates rules to live-like

* Adjust rule names to be more descriptive of their intent, remove else cases

Co-authored-by: Akkadius <akkadius1@gmail.com>
2022-12-19 21:04:03 -06:00
Aeadoin 083d44d4fe [Bug Fix] Resolve Warning due to Virtual Mob Method GetInv() (#2650) 2022-12-19 16:51:05 -05:00
Aeadoin f12090d109 [Bots] Cleanup various Bot Spell Focus methods (#2649)
* [Bots] Cleanup GetFocusEffect & GetActSpellDamage

* Remove unused CalcBotFocusEffect

* Cleanup unneeded derived class methods

* compile error
2022-12-16 17:21:37 -05:00
Paul Coene f188c1394a Add ground spawns to discovered items feature. (#2648)
* Add ground spawns to discovered items feature.

* Add {}
2022-12-16 16:11:58 -05:00
Chris Miles d9e5056657 [Repositories] Migrate LoadPerlEventExportSettings to use repositories (#2637)
* [Repositories] Migrate LoadPerlEventExportSettings to use repositories

* Update quest_parser_collection.cpp
2022-12-14 22:26:14 -06:00
Chris Miles dce5f03e74 [Commands] Nested Command Aliases (#2636) 2022-12-14 22:26:05 -06:00
Chris Miles 6ddd5db480 [Quests] Improve Quest Error Handling - Add back in process based syntax validation (#2646) 2022-12-14 23:20:00 -05:00
nytmyr 1338d21823 [Bug Fix] Fix trading with bots when in an illusion. (#2645)
Trade check was not checking GetBaseRace and would fail if the bot's illusion couldn't equip the item.

Co-authored-by: toxin06 <53322305+toxin06@users.noreply.github.com>
2022-12-14 21:32:34 -05:00
Aeadoin 0fd4d82553 [Bots] Resolve incorrect values on Bot Creation (#2644) 2022-12-14 18:03:56 -05:00
Alex King bca04b969f [Bug Fix] Remove Unnecessary Attack Log (#2643)
# Notes
- This log fires every time for no reason.
2022-12-14 17:31:28 -05:00
Alex King 89ba1270d9 [Bug Fix] Remove unnecessary log messages. (#2642) 2022-12-14 17:31:21 -05:00
Alex King 337dc54eb9 [Bug Fix] Allow High Level Spells to be Unmemorized. (#2641)
* [Bug Fix] Allow High Level Spells to be Unmemorized.

# Notes
- If you deleveled below a spell's level, you couldn't unmemorize it, this fixes that.

* Update client_process.cpp
2022-12-14 17:18:51 -05:00
nytmyr bc277ac296 [Commands] Add max_hp back to #modifynpcstat command. (#2638)
Restores max_hp back to the #modifynpcstat command to adjust the target's HPs.

Co-authored-by: toxin06 <53322305+toxin06@users.noreply.github.com>
2022-12-13 11:41:10 -05:00
nytmyr 7189bab848 [Bots] Fix Gender not saving as GetBaseGender on BotSave (#2639)
Bots were not saving their Base Gender when saving. This could result in bots with illusions saving as gender 2 and becoming a male human model upon illusion fade.

Co-authored-by: toxin06 <53322305+toxin06@users.noreply.github.com>
2022-12-13 11:40:59 -05:00
Chris Miles c3cb0b8cdf [Quests] Improve Quest Error Handling (#2635)
* Improve Quest Error handling

* Update embperl.cpp

* Bench test (temp)

* Swap log category for benchmark

* Swap external process invocation for native Perl eval throw
2022-12-12 19:21:33 -06:00
Aeadoin ae4908b40c [Bots] Add Quest API Methods (#2631)
* [Bots] Add Quest API Methods

* Cleanup unneeded methods.
2022-12-12 17:25:36 -06:00
Aeadoin 13a3afbfac [Bots] Add Event_Trade Support for ^inventorygive Command (#2628) 2022-12-11 16:25:47 -05:00
Chris Miles f5126222c2 [Process] Process Execution Refactor (#2632)
* Swap execute output method

* Create "Process" class and move random string to Strings

* test

* Tweaks
2022-12-11 14:08:55 -05:00
Alex King 70719852d6 [Quest API] Fix Lua Door/Object Create Methods. (#2633)
# Notes
- Lua door/object create methods were `void` type instead of `uint16`, so you couldn't get the entity ID of the door you created.
- Converted Perl's door/object create methods to return `uint16` instead of `int` as well.
2022-12-11 14:08:43 -05:00
Alex King 46f993ef71 [Quest API] Add EVENT_GM_COMMAND to Perl/Lua. (#2634)
# Perl
- Add `EVENT_GM_COMMAND`, exports `$message`.

# Lua
- Add `event_gm_command`, exports `e.message`.

# Notes
- Only parses with real GM commands such as `#reload quest`.
2022-12-11 14:08:38 -05:00
Alex King 20efa83f73 [Bug Fix] Fix possible crash in ProcessSpecialAbilities. (#2630)
* [Bug Fix] Fix possible crash in ProcessSpecialAbilities.

# Notes
- Passing an invalid special ability along such as `4,1,,-1,100` currently causes a crash since every `,` assumes it's followed by a number.
- Fixed by making sure first and second parameters are numbers and then when looping additional parameters we also check if they are numbers.

* Update mob.cpp
2022-12-11 09:07:06 -05:00
Alex King d3fac8a0cb [Quest API] Add EVENT_LEVEL_DOWN to Perl/Lua. (#2620)
* [Quest API] Add EVENT_LEVEL_DOWN to Perl/Lua.

# Perl
- Add `EVENT_LEVEL_DOWN`, exports `$levels_lost`.
- Add `$levels_gained` export to `EVENT_LEVEL_UP`.

# Lua
- Add `event_level_down`, exports `e.levels_lost`.
- Add `e.levels_gained` export to `event_level_up`.

# Notes
- Allows operators to perform actions on level down.
- Allows operators to tell how many levels were lost or gained in case people are gaining/losing multiple levels and they want to keep track or use this as a mechanic in their code somewhere.

* Update exp.cpp

* Update embparser.cpp
2022-12-10 19:22:31 -05:00
Alex King 8c707f9fe5 [Commands] Add #suspendmulti Command. (#2619)
* [Commands] Add #suspendmulti Command.

# Notes
- Allows operators to suspend multiple people at once in case they have  a player who is boxing and want to suspend them all at once.

* To lower.

* Update command.cpp

* Update suspendmulti.cpp

* Create suspendmulti.cpp
2022-12-10 18:07:33 -06:00
Aeadoin c8218574cc [Logging] More AI Logging Cleanup (#2616)
* [Logging] Additional AI Cleanup

* More cleanup/formatting fixes

* Typo
2022-12-10 17:36:40 -06:00
Chris Miles 3dfeda9cea [Tasks] Crash fix with data input sanitization (#2629) 2022-12-10 18:31:18 -05:00
Alex King 1d06a4117a [Quest API] Add DoAnim Overloads to Perl/Lua. (#2627)
# Perl
- Add `$mob->DoAnim(animation_id, animation_speed, ackreq)`.
- Add `$mob->DoAnim(animation_id, animation_speed, ackreq, filter)`.
- Add `quest::doanim(animation_id, animation_speed)`.
- Add `quest::doanim(animation_id, animation_speed, ackreq)`.
- Add `quest::doanim(animation_id, animation_speed, ackreq, filter)`.

# Lua
- Add `eq.do_anim(animation_id)`.
- Add `eq.do_anim(animation_id, animation_speed)`.
- Add `eq.do_anim(animation_id, animation_speed, ackreq)`.
- Add `eq.do_anim(animation_id, animation_speed, ackreq, filter)`.

# Notes
- Adds overloads and cleans up spots where `animation_speed` was named `type` erroneously.
2022-12-10 17:30:40 -06:00
Alex King b1c4e7c23f [Commands] Cleanup #rules Command. (#2593)
* [Commands] Cleanup #rules Command.

- Cleanup messages and logic.
- Rewrite all rules logic to use `std::string` and repositories.

* References

* Update rules.cpp

* Strings::Equal and Strings::EqualFold.

* Cleanup.

* Update rulesys.cpp

* Update rulesys.cpp

Co-authored-by: Akkadius <akkadius1@gmail.com>
2022-12-10 18:08:55 -05:00
Michael 3872555332 [Rules] Rule Gate Pet Zoning (#2625)
Allows preventing pet zoning from happening for more classic servers.
2022-12-07 18:50:02 -05:00
Aeadoin 86af0f0759 [Bots] Cleanup Fast Rest Regen (#2626) 2022-12-07 17:21:50 -05:00
Alex King 88e8b25fa1 [Bug Fix] Data Bucket Permanent Duration String (#2624)
# Notes
- "F" or "f" weren't handled in this method, so they weren't working properly.
- Most people don't provide this parameter when setting a permanent data bucket, so wasn't noticed in testing.
2022-12-06 09:28:38 -05:00
Alex King f7fb1c9fe1 [Quest API] Add MaxSkills() to Perl/Lua. (#2621)
* [Quest API] Add MaxSkills() to Perl/Lua.

# Perl
- Add `$client->MaxSkills()`.

# Lua
- Add `client:MaxSkills()`.

# Notes
- Allows operators an easy short hand for maxing a player's skills for their level without needing to do all the looping and stuff on their own.

* Cleanup.

* Only set if it's higher than skill level player has.

* Add constant.
2022-12-06 08:46:21 -05:00
Alex King 91ea6462f2 [Quest API] Add CopyHateList() to Perl/Lua. (#2623)
* [Quest API] Add CopyHateList() to Perl/Lua.

# Perl
- Add `$mob->CopyHateList(to_mob)`.

# Lua
- Add `mob:CopyHateList(to_mob)`.

# Notes
- Allows operators to easily copy and entire hatelist from one mob to another.

* Update mob.cpp
2022-12-06 08:38:51 -05:00
Alex King 3774dc50d9 [Quest API] Add Fling Overloads to Perl/Lua. (#2622)
* [Quest API] Add Fling Overload to Perl/Lua.

# Perl
- Add `$client->Fling(target_x, target_y, target_z)`.
- Add `$client->Fling(target_x, target_y, target_z, ignore_los)`.
- Add `$client->Fling(target_x, target_y, target_z, ignore_los, clipping)`.

# Lua
- Add `client:Fling(target_x, target_y, target_z)`.
- Add `client:Fling(target_x, target_y, target_z, ignore_los)`.
- Add `client:Fling(target_x, target_y, target_z, ignore_los, clipping)`.

# Notes
- These overloads calculate the speed based on the distance automatically.

* Update client.cpp

* Update client.cpp

* Update client.cpp

* clip_through_walls
2022-12-06 08:38:33 -05:00
Alex King 0455868f66 [Commands] Cleanup #scale Command. (#2591)
* [Commands] Cleanup #scale Command.

- Cleanup messages and logic.

* One line message.
2022-12-04 23:17:56 -06:00
Alex King ef42e00df8 [Bug Fix] Fix case-sensitivity in #suspend Command. (#2613)
* [Bug Fix] Fix case-sensitivity in #suspend Command.

# Notes
- This command required you to properly send the name as it appears in the database otherwise it wouldn't kick the player.
- Solution is to `Strings::ToLower` then `Strings::UcFirst`.

* To lower.
2022-12-04 23:17:17 -06:00
Alex King a9c161011e [Hot Fix] Fix Bot Data Repository (#2618)
* [Hot Fix] Fix Bot Data Repository

Query was in wrong order.

* Update base_repository.template
2022-12-04 22:35:17 -05:00
Alex King 423e6ae751 [Bots] Convert Load, Save, SaveNew, and Delete to Repositories. (#2614)
* [Bots] Convert Load, Save, SaveNew, and Delete to Repositories.

# Notes
- General code cleanup, as manually adding to these queries doesn't scale very well.

* FindOne.

* Update base_bot_data_repository.h

* Update template.
2022-12-04 18:22:35 -05:00
Alex King 9a35cacf27 [Quest API] Add EVENT_PAYLOAD to Perl/Lua. (#2611)
* [Quest API] Add EVENT_PAYLOAD to Perl/Lua.

# Perl
- Add `$bot->SendPayload(payload_id)`.
- Add `$bot->SendPayload(payload_id, payload_value)`.
- Add `$client->SendPayload(payload_id)`.
- Add `$client->SendPayload(payload_id, payload_value)`.
- Add `$mob->SendPayload(payload_id)`.
- Add `$mob->SendPayload(payload_id, payload_value)`.
- Add `$npc->SendPayload(payload_id)`.
- Add `$npc->SendPayload(payload_id, payload_value)`.

# Lua
- Add `bot:SendPayload(payload_id)`.
- Add `bot:SendPayload(payload_id, payload_value)`.
- Add `client:SendPayload(payload_id)`.
- Add `client:SendPayload(payload_id, payload_value)`.
- Add `mob:SendPayload(payload_id)`.
- Add `mob:SendPayload(payload_id, payload_value)`.
- Add `npc:SendPayload(payload_id)`.
- Add `npc:SendPayload(payload_id, payload_value)`.

# Notes
- Allows operators to send payload IDs with a payload value, the value can be a comma separated value, JSON, etc.
- The idea is to allow a more configurable event for operators to send information to/from entities.

* Cleanup parser events.
2022-12-04 17:47:49 -05:00
Alex King e1d5274bd5 [Quest API] Cleanup Signal Methods in Perl/Lua. (#2604)
# Perl
- Add `$client->Signal(signal_id)`.

# Notes
- Some places still had signal as `uint32` versus `int`.
- Rename `signal` to `signal_id` where valid so we don't have conflicts.
2022-12-04 17:40:48 -05:00
Aeadoin ede3ed4df3 [HotFix] Resolve issue with Bot Casting after zoning. (#2617) 2022-12-04 15:43:38 -06:00
Aeadoin 318e487515 [Logging] Cleanup AI Logging Events (#2615) 2022-12-04 14:22:53 -05:00
Aeadoin 7e0fe93039 [Bots] Save Bot Toggle Archer Setting between Loads. (#2612)
* [Bots] Save Bot Toggle Archer Setting between Loads.

* [Bots] Save Bot Toggle Archer Setting between Loads.

* Typo
2022-12-04 13:23:25 -05:00
Alex King 7abc084cd1 [Quest API] Add Entity Variable Methods to Perl/Lua. (#2609)
* [Quest API] Add Entity Variable Methods to Perl/Lua.

# Perl
- Add `$mob->ClearEntityVariables()`.
- Add `$mob->DeleteEntityVariable(variable_name)`.
- Add `$object->ClearEntityVariables()`.
- Add `$object->DeleteEntityVariable(variable_name)`.

# Lua
- Add `mob:ClearEntityVariables()`.
- Add `mob:DeleteEntityVariable(variable_name)`.
- Add `object:ClearEntityVariables()`.
- Add `object:DeleteEntityVariable(variable_name)`.

# Notes
- Allows operators to clear all entity variables or delete one by name, previously you just had to set to an empty value to clear after being set.

* Cleanup.
2022-12-04 12:18:27 -05:00
Alex King 5d5c2a4194 [Quest API] Add GetGuildPublicNote() to Perl/Lua. (#2608)
# Perl
- Add `$client->GetGuildPublicNote()`.

# Lua
- Add `client:GetGuildPublicNote()`.

# Notes
- Allows operators to grab a player's public note in there guild if they wanted to.
2022-12-04 12:18:18 -05:00
Aeadoin 80fffb57b1 [Bots] Cleanup Spell Settings Commands (#2607)
* [Bots] Cleanup Spell Settings Commands

* Update Bot DB version

* typo
2022-12-03 19:49:45 -05:00
Aeadoin 61b91d92c3 [Bots] Expanded Bot Spell Settings List. (#2606)
* [Bots] Expanded Bot Spell List Settings

* [Bots] Expanded Bot Spell List Settings

* Fixes/formatting

* typo

* Formatting & update SpellInfo Command

* Spelling

* Typo
2022-12-03 12:15:57 -05:00
Aeadoin 35d22913b9 [Bug Fix] Fix Bot ^spellsettingsadd command (#2603) 2022-12-01 14:25:23 -05:00
Alex King dbba22b153 [Bug Fix] Add SE_MakeDrunk to avoid error message. (#2601)
* [Bug Fix] Add SE_MakeDrunk to avoid error message.

Currently sends error message about unknown spell effect ID.

* Message types cleanup.

* Update spdat.cpp
2022-11-30 22:09:59 -05:00
JJ de7a632d67 [SQL] Bugs Table Migration (#2559) (#2602)
Copies bugs from `bugs` to `bug_reports`
2022-11-30 22:09:49 -05:00
Alex King 85ae36ede5 [Bug Fix] Fix Instance Repository (#2598)
Instance code used to use a `REPLACE INTO`, add an extended repository method to do this so we're not getting `DUPLICATE` errors.
2022-11-30 21:31:39 -05:00
Alex King ecc34940b4 [Bug Fix] Fix IDFile Crash with spaces or invalid data. (#2597)
* [Bug Fix] Fix IDFile Crash with spaces or invalid data.

* Update mob_appearance.cpp
2022-11-30 21:31:28 -05:00
Alex King a9cfacf54b [Quest API] Add WearChange Overloads to Perl/Lua. (#2600)
* [Quest API] Add WearChange Overloads to Perl/Lua.

# Perl
- Add `$mob->WearChange(slot, texture)`.

# Lua
- Add `mob:WearChange(slot, texture)`.
- Add `mob:WearChange(slot, texture, color, heros_forge_model)`.

# Notes
- These overloads allow you to not have to send color.
- Lua didn't have an overload with Hero's Forge Model.

* Fix variable types.
2022-11-30 21:31:22 -05:00
Aeadoin e7704f00f3 [Bots] Melee Bot Support for Spell Settings Commands (#2599) 2022-11-30 19:35:17 -05:00
Aeadoin 639f8e184a [Fix] Clamp Item Ldon Sell Back Rates. (#2592)
* [Fix] Clamp ldonsellbackrates to prevent abuse.

* Change cast to uint32

* Fix issues with Clamp not functioning correctly.

* Fix missed clamp

* change price is unsigned int to prevent potential overflow

* Formatting

* Formatting fix

* Update client_packet.cpp

* Update client_packet.cpp

Co-authored-by: Alex King <89047260+Kinglykrab@users.noreply.github.com>
2022-11-30 18:02:36 -05:00
Michael 1d302f512e [Quest API] Adjustment to depop_all function. (#2595)
* [Quest API] Adjustment to depop_all function.

Adjustment to depop_all function to no longer require an owner under all conditions (allows use inside encounters)

* More simplification

* Update questmgr.cpp

Co-authored-by: Alex King <89047260+Kinglykrab@users.noreply.github.com>
2022-11-29 23:57:19 -05:00
Michael 02c0a8fa7f [Command] Adding movespeed to #showstats output (#2596) 2022-11-29 23:51:33 -05:00
Aeadoin e928754df3 [Bot] Add Buff support for Bards under AI_IdleCastChecks (#2590)
* [Bot] Add Buff support for Bards under AI_IdleCastChecks

* Add InCombatBuffSong to Idle Bard cast Logic

* Fixes a number of Buffs that would fail to land on the Bot, causing casting loops

* Accidently removed If Statement added back.

* Update bot.cpp

Co-authored-by: Alex King <89047260+Kinglykrab@users.noreply.github.com>
2022-11-28 16:35:51 -05:00
Alex King 200c6cccaf [Bots] Optimize inventory loading. (#2588)
* [Bots] Optimize inventory loading.

# Notes
- Bots previously were running 23 individual queries to load their inventory versus grabbing their inventory all at once and referencing it in memory.

* Typo.

* Update bot_database.cpp

* Update bot_database.cpp

* Update bot.cpp
2022-11-27 19:07:24 -05:00
Alex King d6db35b84e [Commands] Cleanup #gearup Command. (#2589)
# Notes
- Cleanup messages and logic.
- Add support for gearing up target client (with #gm on) and/or target bots.
2022-11-27 18:56:40 -05:00
Alex King d0e7e8c4c4 [Quest API] Add Group/Raid Overloads to Perl/Lua. (#2587)
# Perl
- Add `$group->IsGroupMember(name)`.
- Add `$group->IsLeader(name)`.
- Add `$raid->IsRaidMember(c)`.
- Add `$raid->IsGroupLeader(c)`.

# Lua
- Add `group:IsGroupMember(name)`.
- Add `group:IsLeader(name)`.
- Add `raid:IsGroupLeader(client)`.
- Add `raid:IsLeader(client)`.
- Add `raid:IsRaidMember(client)`.

# Notes
- Adds overloads to these methods allowing operators to get by name or reference.
2022-11-27 15:57:01 -05:00
Aeadoin 29247a0f45 [Bot] Add Support for Bots to receive Auras, and other AoE Buffs. (#2586) 2022-11-27 15:49:38 -05:00
Alex King 2d364e2fd1 [Bots] Add Bot-specific Spell Settings. (#2553)
* [Bots] Add Bot-specific Spell Settings.

# Notes
- Allows players to set `priority`, `min_level`, `max_level`, `min_hp`, `max_hp`, and `is_enabled` settings per spell based on targeted bot.
- Lets players disable spells they don't want their bots casting or change the criteria they cast them at if they want.

* Update botspellsai.cpp

* Update 2022_11_19_bot_spell_settings.sql

* Typo.

* Update botspellsai.cpp

* Cleanup and add Reload Methods to Perl/Lua.
2022-11-27 14:46:36 -05:00
Aeadoin f6c5560e9c [Bot] Update Bot Logic to ignore ST_TargetsTarget when buffing (#2584)
* [Bot] Update Bot Logic to ignore ST_TargetsTarget when buffing

* Fix Not Operator

* Update botspellsai.cpp

Co-authored-by: Alex King <89047260+Kinglykrab@users.noreply.github.com>
2022-11-27 14:39:34 -05:00
Alex King fb4d4e1382 [Quest API] Fix Perl EVENT_HP double parsing in Spire. (#2585)
This condition caused the variables to show twice due to the way Sprie parses the source code, and the condition itself is unnecessary since we can just use an inline ternary in this case.
2022-11-27 14:27:27 -05:00
Aeadoin 9a7770377d [Bots] Move Bot Spell Loading process to constructor from calcbotstats() (#2583) 2022-11-27 11:41:10 -05:00
Alex King 15b2baa663 [Commands] Cleanup #npcedit Command. (#2582)
* [Commands] Cleanup #npcedit Command.

- Make use of repositories and cleanup logic.

* Remove accidental change.
2022-11-27 11:37:22 -05:00
Alex King 253f4c07e0 [Commands] Cleanup #chat Command. (#2581)
- Cleanup messages and logic.
2022-11-26 19:28:28 -05:00
Alex King f7ae5850f0 [Quest API] Add Time String to Seconds Method to Perl/Lua. (#2580)
* [Quest API] Add Time String to Seconds Method to Perl/Lua.

# Perl
- Add `quest::timetoseconds(time_string)`.

# Lua
- Add `eq.time_to_seconds(time_string)`.

# Notes
- Allows operators to use this method in place of hardcoded values like `3600`.

* Remove unused method.
2022-11-26 19:28:21 -05:00
Aeadoin ea9a02bec4 [Bots] Add Rule Allowing Bots to Equip Any Race Items (#2578)
* [Bots] Add Rule AllowBotEquipAnyRaceGear

* Fix formatting

* Update item_instance.cpp

* Update bot.cpp

* Update item_data.h

Co-authored-by: Alex King <89047260+Kinglykrab@users.noreply.github.com>
2022-11-26 17:39:31 -05:00
Alex King 31d57342e1 [Quest API] Add Entity Variable Methods to Perl/Lua. (#2579)
* [Quest API] Add Entity Variable Methods to Perl/Lua.

# Perl
- Add `$mob->GetEntityVariables()`.
- Add `$object->GetEntityVariables()`.

# Lua
- Add `mob:GetEntityVariables()`.
- Add `object:GetEntityVariables()`.

# Notes
- Convert all overloads and methods to use `std::string` for entity variables.
- Allows operators to get a list of a Mob's entity variables.

* Update loottables.cpp
2022-11-26 16:24:01 -05:00
Alex King 290ebf3b26 [Quest API] Add GetBotListByClientName() Class Overload to Perl/Lua. (#2577)
# Perl
- Add `$entity_list->GetBotListByClientName(client_name, class_id)`.

# Lua
- Add `eq.get_entity_list():GetBotListByClientName(client_name, class_id)`.

# Notes
- Adds overload to get bots by client name and class ID.
2022-11-26 15:47:45 -05:00
Alex King 25f8ee2084 [Hotfix] Instances Repository Fix (#2576)
Need to use `this` pointer.
2022-11-26 12:31:51 -05:00
Alex King 1002a5659b [Hot Fix] Fix non-Bot Compile. (#2575)
#ifdef BOTS is needed for non-Bots compile.
2022-11-26 11:13:57 -05:00
Alex King dced08cf97 [Quest API] Add Zone Flag Methods to Perl/Lua. (#2574)
* [Quest API] Add Zone Flag Methods to Perl/Lua.

# Perl
- Add `$client->GetPEQZoneFlags()`.
- Add `$client->GetZoneFlags()`.

# Lua
- Add `client:GetPEQZoneFlags()`.
- Add `client:GetZoneFlags()`.

# Notes
- Allows operators to get a list of all PEQ/zone flags to be looped through or listed out easily without having to have a list of individual zone IDs to check or otherwise.

* Update zoning.cpp

* Repositories and cleanup.
2022-11-26 11:13:46 -05:00
Alex King b91d879662 [Quest API] Add Instance Methods to Perl/Lua. (#2573)
* [Quest API] Add Instance Methods to Perl/Lua.

# Perl
- Add `quest::GetInstanceIDs(zone_name)`.
- Add `quest::GetInstanceIDsByCharID(zone_name, character_id)`.
- Add `quest::GetInstanceVersionByID(instance_id)`.
- Add `quest::GetInstanceZoneIDByID(instance_id)`.

# Lua
- Add `eq.get_instance_ids(zone_name)`.
- Add `eq.get_instance_ids_by_char_id(zone_name, character_id)`.
- Add `eq.get_instance_version_by_id(instance_id)`.
- Add `eq.get_instance_zone_id_by_id(instance_id)`.

# Notes
- The instance IDs methods return arrays of IDs for looping so you can check on mass the instances a player has for a zone.
- Keeps operators from having to guess which possible versions of a zone a player has an instance for or loop through them all to find out.
- Cleanup `common/database_instances.cpp` to mostly use repositories where possible.

* Update database.h

* Update character_corpses_repository.h
2022-11-26 10:43:29 -05:00
Alex King 1d1ffc66fe [Quest API] Add Proximity Range Methods to Perl/Lua. (#2572)
# Perl
- Add `quest::set_proximity_range(x_range, y_range)`.
- Add `quest::set_proximity_range(x_range, y_range, z_range)`.
- Add `quest::set_proximity_range(x_range, y_range, z_range, enable_say)`.

# Lua
- Add `eq.set_proximity_range(x_range, y_range)`.
- Add `eq.set_proximity_range(x_range, y_range, z_range)`.
- Add `eq.set_proximity_range(x_range, y_range, z_range, enable_say)`.

# Notes
- Allows a shorthand for setting proximities.
- Automatically uses NPC's current location versus having to provide it.
2022-11-26 10:11:40 -05:00
Aeadoin 4423a9f160 [Bots] Add Melee Support for Casting, Cleanup Bot Casting Logic (#2571)
* [Bots] Add Melee Support for Casting, Cleanup Logic

* Formatting

* More Logic Changes

* formatting
2022-11-25 16:23:00 -05:00
Aeadoin 217a6b6344 [Merchant] LDoNSellBackRate support for Rule Merchant:EnableAltCurrencySell (#2570) 2022-11-25 16:16:59 -05:00
Aeadoin 99052aec8b [Bot] Add EVENT_TRADE Support to Bots. (#2560)
* [Bot] Add EVENT_TRADE Support to Bots.

* Fixed issue with duplicate items after Event Trade

* Update logic

* Add CalcBotStats call after Bot Trade Event

* Fix Lua EVENT_TRADE.

* Formatting.

* More formatting.

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2022-11-25 15:09:08 -05:00
Aeadoin 45c4fe55f0 [Quest API] Add HasBotSpellEntry() to Perl/Lua. (#2563)
* [Bots] Quest API Check Spell in Bot_Spell_Entries

* Add to luabind and packages

* Change Method to be HasBotSpellEntry, change SpellID to uint16

* Ordering, and removed unused logging
2022-11-24 22:29:38 -05:00
Kinglykrab 52e1bc943a [Commands] Add #bugs Command. (#2559)
* [Commands] Add #bugs Command.

- Adds a #bugs command for viewing bug reports.
- Remove unused bug related rules in favor of hard-coding the new system.

* Cleanup.

* Typo.

* Push.

* Lower status so it fits with message.
2022-11-22 17:32:26 -05:00
Kinglykrab dd3c76e9d2 [Bug Fix] Fix EntityList::GetBotListByCharacterID() (#2569)
- Class ID wasn't being checked, must've been left out of commit.
2022-11-22 17:03:43 -05:00
Kinglykrab 5e6741cf17 [Quest API] Add Overloads to MoveZone Methods in Perl/Lua. (#2551)
# Perl
- Add `$client->MoveZone(zone_name, x, y, z)`.
- Add `$client->MoveZone(zone_name, x, y, z, h)`.
- Add `$client->MoveZoneGroup(zone_name, x, y, z)`.
- Add `$client->MoveZoneGroup(zone_name, x, y, z, h)`.
- Add `$client->MoveZoneRaid(zone_name, x, y, z)`.
- Add `$client->MoveZoneRaid(zone_name, x, y, z, h)`.
- Add `$client->MoveZoneInstance(instance_id, x, y, z)`.
- Add `$client->MoveZoneInstance(instance_id, x, y, z, h)`.
- Add `$client->MoveZoneInstanceGroup(instance_id, x, y, z)`.
- Add `$client->MoveZoneInstanceGroup(instance_id, x, y, z, h)`.
- Add `$client->MoveZoneInstanceRaid(instance_id, x, y, z)`.
- Add `$client->MoveZoneInstanceRaid(instance_id, x, y, z, h)`.

# Lua
- Add `client:MoveZone(zone_name, x, y, z)`.
- Add `client:MoveZone(zone_name, x, y, z, h)`.
- Add `client:MoveZoneGroup(zone_name, x, y, z)`.
- Add `client:MoveZoneGroup(zone_name, x, y, z, h)`.
- Add `client:MoveZoneRaid(zone_name, x, y, z)`.
- Add `client:MoveZoneRaid(zone_name, x, y, z, h)`.
- Add `client:MoveZoneInstance(instance_id, x, y, z)`.
- Add `client:MoveZoneInstance(instance_id, x, y, z, h)`.
- Add `client:MoveZoneInstanceGroup(instance_id, x, y, z)`.
- Add `client:MoveZoneInstanceGroup(instance_id, x, y, z, h)`.
- Add `client:MoveZoneInstanceRaid(instance_id, x, y, z)`.
- Add `client:MoveZoneInstanceRaid(instance_id, x, y, z, h)`.

# Notes
- Adds XYZ/XYZH overloads to these methods so it no longer assumes safe coordinates unless position isn't specified.
2022-11-22 16:48:05 -05:00
Kinglykrab 8373dd1cb9 [Commands] Cleanup #timers Command. (#2562)
- Cleanup popup window and add a message for if there are no recast timers.
2022-11-22 09:17:09 -05:00
Kinglykrab 9f65159cb2 [Commands] Cleanup #serverinfo Command. (#2568)
- Cleanup messages.
- Use new dialogue window methods.
2022-11-22 09:14:22 -05:00
Kinglykrab f143d0a75f [Commands] Cleanup #delacct Command. (#2567)
- Cleanup messages and logic.
- Use repositories.
2022-11-22 09:14:15 -05:00
Kinglykrab 19e7f0a6b1 [Commands] Cleanup #heromodel Command. (#2566)
- Cleanup messages and logic.
2022-11-22 09:14:08 -05:00
Kinglykrab 3c361be739 [Commands] Remove #iteminfo Command. (#2565)
- Command is unused and doesn't have most of the item data anyway, seems like a command for back when items weren't fully working.
2022-11-22 09:13:59 -05:00
Kinglykrab 3424fe78f5 [Commands] Cleanup #suspend Command. (#2564)
- Cleanup messages and logic.
- Use repositories.
2022-11-22 09:13:37 -05:00
Kinglykrab 0dfa067974 [Quest API] Add Hotzone Methods to Perl/Lua. (#2558)
# Perl
- Add `quest::ishotzone()`.
- Add `quest::sethotzone(is_hotzone)`.

# Lua
- Add `eq.is_hotzone()`.
- Add `quest::set_hotzone(is_hotzone)`.

# Notes
- Allows operators to toggle hotzone flags within a script dynamically, for stuff like making an instance a hotzone, but not necessarily all versions of the zone.
2022-11-22 09:11:53 -05:00
Kinglykrab 0c56586f3b [Quest API] Add Client Spell Methods to Perl/Lua. (#2550)
* [Quest API] Add Client Spell Methods to Perl/Lua.

# Perl
- Add `$client->ApplySpell(spell_id)`.
- Add `$client->ApplySpell(spell_id, duration)`.
- Add `$client->ApplySpell(spell_id, duration, allow_pets)`.
- Add `$client->ApplySpell(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `$client->ApplySpell(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.
- Add `$client->ApplySpellGroup(spell_id)`.
- Add `$client->ApplySpellGroup(spell_id, duration)`.
- Add `$client->ApplySpellGroup(spell_id, duration, allow_pets)`.
- Add `$client->ApplySpellGroup(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `$client->ApplySpellGroup(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.
- Add `$client->ApplySpellRaid(spell_id)`.
- Add `$client->ApplySpellRaid(spell_id, duration)`.
- Add `$client->ApplySpellRaid(spell_id, duration, allow_pets)`.
- Add `$client->ApplySpellRaid(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `$client->ApplySpellRaid(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.
- Add `$client->SetSpellDuration(spell_id)`.
- Add `$client->SetSpellDuration(spell_id, duration)`.
- Add `$client->SetSpellDuration(spell_id, duration, allow_pets)`.
- Add `$client->SetSpellDuration(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `$client->SetSpellDuration(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.
- Add `$client->SetSpellDurationGroup(spell_id)`.
- Add `$client->SetSpellDurationGroup(spell_id, duration)`.
- Add `$client->SetSpellDurationGroup(spell_id, duration, allow_pets)`.
- Add `$client->SetSpellDurationGroup(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `$client->SetSpellDurationGroup(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.
- Add `$client->SetSpellDurationRaid(spell_id)`.
- Add `$client->SetSpellDurationRaid(spell_id, duration)`.
- Add `$client->SetSpellDurationRaid(spell_id, duration, allow_pets)`.
- Add `$client->SetSpellDurationRaid(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `$client->SetSpellDurationRaid(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.

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

# Notes
- Allows operators extremely easy shorthands to cast on entire groups and raid groups and optionally include their bots and pets.
- Default functionality for Raid is that it only casts on your group, set `is_raid_group_only` to `false` to cast on the entire Raid.

* Cleanup.

* Remove Raid parameter from Solo/Group methods.
2022-11-22 09:11:36 -05:00
Kinglykrab 37af643b61 [Bots] Cleanup Say Event Parse. (#2557) 2022-11-20 14:28:46 -06:00
Kinglykrab f67767f28e [Cleanup] Extra Space in NPC::AISpellsList(). (#2555) 2022-11-20 09:59:59 -05:00
Kinglykrab e2dfbeb116 [Bug Fix] Fix Flag Updating with SetGMStatus() in Lua. (#2554)
# Notes
- Perl was sending `UpdateAdmin()` after `SetGMStatus()`, Lua wasn't, so only Perl was updating properly.
- Fix is to just put `UpdateAdmin()` inside `SetGMStatus()`.
2022-11-19 22:05:01 -05:00
Aeadoin 5173a9179b [Hotfix] Fix issue with Bot Loading with 0 Health causing buffs to be lost. (#2552) 2022-11-18 17:27:59 -05:00
Kinglykrab 0003f6f863 [Quest API] Add Area Damage Methods to Perl/Lua. (#2549)
* [Quest API] Add Area Damage Methods to Perl/Lua.

# Perl
- Add `$mob->DamageArea(damage)`.
- Add `$mob->DamageArea(damage, distance)`.
- Add `$mob->DamageAreaBots(damage)`.
- Add `$mob->DamageAreaBots(damage, distance)`.
- Add `$mob->DamageAreaClients(damage)`.
- Add `$mob->DamageAreaClients(damage, distance)`.
- Add `$mob->DamageAreaNPCs(damage)`.
- Add `$mob->DamageAreaNPCs(damage, distance)`.
- Add `$mob->DamageAreaPercentage(damage)`.
- Add `$mob->DamageAreaPercentage(damage, distance)`.
- Add `$mob->DamageAreaBotsPercentage(damage)`.
- Add `$mob->DamageAreaBotsPercentage(damage, distance)`.
- Add `$mob->DamageAreaClientsPercentage(damage)`.
- Add `$mob->DamageAreaClientsPercentage(damage, distance)`.
- Add `$mob->DamageAreaNPCsPercentage(damage)`.
- Add `$mob->DamageAreaNPCsPercentage(damage, distance)`.

# Lua
- Add `mob:DamageArea(damage)`.
- Add `mob:DamageArea(damage, distance)`.
- Add `mob:DamageAreaBots(damage)`.
- Add `mob:DamageAreaBots(damage, distance)`.
- Add `mob:DamageAreaClients(damage)`.
- Add `mob:DamageAreaClients(damage, distance)`.
- Add `mob:DamageAreaNPCs(damage)`.
- Add `mob:DamageAreaNPCs(damage, distance)`.
- Add `mob:DamageAreaPercentage(damage)`.
- Add `mob:DamageAreaPercentage(damage, distance)`.
- Add `mob:DamageAreaBotsPercentage(damage)`.
- Add `mob:DamageAreaBotsPercentage(damage, distance)`.
- Add `mob:DamageAreaClientsPercentage(damage)`.
- Add `mob:DamageAreaClientsPercentage(damage, distance)`.
- Add `mob:DamageAreaNPCsPercentage(damage)`.
- Add `mob:DamageAreaNPCsPercentage(damage, distance)`.

# Notes
- Cleanup parameter order of damage methods.
- These methods allow you to damage all Bots, Clients, Mobs, or NPCs in a zone or by distance from the Mob.
- Fix math with percentage damage.

* Update entity.cpp
2022-11-16 21:11:01 -06:00
Kinglykrab 856aa51cb8 [Bots] Add support for Bot scripting. (#2515)
* [Bots] Add support for Bot scripting.

# Perl
- Add support for `zone/bot.pl` and `zone/bot_v#.pl`.
- Add support for `global/global_bot.pl`.
- Add `$bot->SignalBot(signal_id)` to Perl.
- Add `$bot->OwnerMessage(message)` to Perl.
- Add `$entity_list->SignalAllBotsByOwnerCharacterID(character_id, signal_id)` to Perl.
- Add `$entity_list->SignalBotByBotID(bot_id, signal_id)` to Perl.
- Add `$entity_list->SignalBotByBotName(bot_name, signal_id)` to Perl.
- Add `EVENT_SPELL_EFFECT_BOT` to Perl.
- Add `EVENT_SPELL_EFFECT_BUFF_TIC_BOT` to Perl.

# Lua
- Add support for `zone/bot.lua` and `zone/bot_v#.lua`.
- Add support for `global/global_bot.lua`.
- Add `bot:SignalBot(signal_id)` to Lua.
- Add `bot:OwnerMessage(message)` to Lua.
- Add `entity_list:SignalAllBotsByOwnerCharacterID(character_id, signal_id)` to Lua.
- Add `entity_list:SignalBotByBotID(bot_id, signal_id)` to Lua.
- Add `entity_list:SignalBotByBotName(bot_name, signal_id)` to Lua.
- Add `EVENT_SPELL_EFFECT_BOT` to Lua.
- Add `EVENT_SPELL_EFFECT_BUFF_TIC_BOT` to Lua.

# Supported Bot Events
1. `EVENT_CAST`
2. `EVENT_CAST_BEGIN`
3. `EVENT_CAST_ON`
4. `EVENT_COMBAT`
5. `EVENT_DEATH`
6. `EVENT_DEATH_COMPLETE`
7. `EVENT_SAY`
8. `EVENT_SIGNAL`
9. `EVENT_SLAY`
10. `EVENT_SLAY_NPC`
11. `EVENT_SPAWN`
12. `EVENT_TARGET_CHANGE`
13. `EVENT_TIMER`
14. `EVENT_USE_SKILL`

# Common
- Convert NPC pointers in common events to Mob pointers so bots are supported.
- Convert signal IDs to `int` where it wasn't already, allowing negative signals to be sent properly.

* Add EVENT_POPUP_RESPONSE.

* Cleanup and fix EVENT_COMBAT/EVENT_SLAY/EVENT_NPC_SLAY.

* Fix DoNPCEmote calls.

* Update attack.cpp

* Update event_codes.h

* Update bot_command.cpp
2022-11-16 21:02:16 -06:00
Kinglykrab 7ea77ee027 [Bots] Add Quest API Support for Limits. (#2522)
* [Bots] Add Quest API Support for Limits.

# Perl
- Add `$client->GetBotCreationLimit()` to Perl.
- Add `$client->GetBotCreationLimit(class_id)` to Perl.
- Add `$client->GetBotRequiredLevel()` to Perl.
- Add `$client->GetBotRequiredLevel(class_id)` to Perl.
- Add `$client->GetBotSpawnLimit()` to Perl.
- Add `$client->GetBotSpawnLimit(class_id)` to Perl.
- Add `$client->SetBotCreationLimit(creation_limit)` to Perl.
- Add `$client->SetBotCreationLimit(creation_limit, class_id)` to Perl.
- Add `$client->SetBotRequiredLevel(required_level)` to Perl.
- Add `$client->SetBotRequiredLevel(required_level, class_id)` to Perl.
- Add `$client->SetBotSpawnLimit(spawn_limit)` to Perl.
- Add `$client->SetBotSpawnLimit(spawn_limit, class_id)` to Perl.
- Add `$entity_list->GetBotListByCharacterID(character_id, class_id)` to Perl.

# Lua
- Add `client:GetBotCreationLimit()` to Lua.
- Add `client:GetBotCreationLimit(class_id)` to Lua.
- Add `client:GetBotRequiredLevel()` to Lua.
- Add `client:GetBotRequiredLevel(class_id)` to Lua.
- Add `client:GetBotSpawnLimit()` to Lua.
- Add `client:GetBotSpawnLimit(class_id)` to Lua.
- Add `client:SetBotCreationLimit(creation_limit)` to Lua.
- Add `client:SetBotCreationLimit(creation_limit, class_id)` to Lua.
- Add `client:SetBotRequiredLevel(required_level)` to Lua.
- Add `client:SetBotRequiredLevel(required_level, class_id)` to Lua.
- Add `client:SetBotSpawnLimit(spawn_limit)` to Lua.
- Add `client:SetBotSpawnLimit(spawn_limit, class_id)` to Lua.
- Add `entity_list:GetBotListByCharacterID(character_id, class_id)` to Lua.

# Notes
- Allows operators to set creation and spawn limits based on class, as well as required level.
- Using the class-inspecific methods sets the global limit or required level.
- Global limits are checked prior to class-specific limits and if they are not met, creation or spawn is disallowed.
- Modified preexisting Quest API to make use of this new stuff under the hood.

* Update bot_command.cpp

* Add client bot file.
2022-11-16 19:51:13 -05:00
Kinglykrab ce4d96dc91 [Commands] Cleanup #xtargets Command. (#2545)
* [Commands] Cleanup #xtargets Command.

- Cleanup messages and logic.

* Update client.cpp

* Update client.cpp
2022-11-16 19:11:35 -05:00
Kinglykrab bd95daa1f3 [Quest API] Add GetRandomBot() to Perl/Lua (#2543)
* [Quest API] Add GetRandomBot() to Perl/lua.

# Perl
- Add `$entity_list->GetRandomBot()` to Perl.
- Add `$entity_list->GetRandomBot(x, y, z, distance)` to Perl.
- Add `$entity_list->GetRandomBot(x, y, z, distance, exclude_bot)` to Perl.

# Lua
- Add `eq.get_entity_list():GetRandomBot()` to Lua.
- Add `eq.get_entity_list():GetRandomBot(x, y, z, distance)` to Lua.
- Add `eq.get_entity_list():GetRandomBot(x, y, z, distance, exclude_bot)` to Lua.

# Notes
- Allows operators to grab a random Bot from entity list similar to Client, Mob, and NPC.

* Cleanup and fix Perl distance.

- Perl distance was sending as already squared, Lua was not.
- Send as non-squared and square in the method so that both work the same.

* Update entity.cpp

* Update entity.cpp
2022-11-16 18:54:15 -05:00
Kinglykrab 93d8471487 [Commands] Cleanup #opcode Command. (#2547)
* [Commands] Cleanup #opcode Command.

- Cleanup logic.

* Update command.cpp
2022-11-16 08:30:35 -06:00
Kinglykrab 730cd3f28a [Bots] Add Expansion Bitmask Quest APIs. (#2523)
* [Bots] Add Expansion Bitmask Quest APIs.

- Add `$bot->GetExpansionBitmask()` to Perl.
- Add `$bot->SetExpansionBitmask(expansion_bitmask)` to Perl.

- Add `bot:GetExpansionBitmask()` to Lua.
- Add `bot:SetExpansionBitmask(expansion_bitmask)` to Lua.

- Adds `expansion_bitmask` column to `bot_data` table.
- Allows server operators to limit expansion settings on a bot-by-bot basis.
- Allows limiting or allowing of AAs in `Bot::LoadAAs()` based on expansion bitmask.
- Default value is `-1` which just defaults to the `Bots:BotExpansionSettings` rule value.
- Setting bitmask saves to database and reloads AAs so bots automatically recalculate bonuses.

* Add save parameter.

* Typo.
2022-11-16 07:29:50 -06:00
Kinglykrab bb58a9cd20 [Quest API] Add Marquee methods to Perl/Lua. (#2544)
* [Quest API] Add zonemarquee to Perl/Lua.

# Perl
- Add `quest::zonemarquee(type, priority, fade_in, fade_out, duration, message)` to Perl.

# Lua
- Add `eq.zone_marquee(type, priority, fade_in, fade_out, duration, message)` to Lua.

# Notes
- Allows operators to easily send a zone-wide marquee, similar to `quest::ze`/`eq.zone_emote`.

* Update lua_general.cpp

* Add other methods.

* Add entity list marquee

* Update client.cpp

* Add more shorthands.
2022-11-16 07:23:39 -06:00
Kinglykrab 8c994fef97 [Quest API] Add Mob Hate Methods to Perl/Lua. (#2548)
* [Quest API] Add Mob Hate Methods to Perl/Lua.

# Perl
- Add `$mob->DamageHateList(damage)` to Perl.
- Add `$mob->DamageHateList(damage, distance)` to Perl.
- Add `$mob->DamageHateListPercentage(damage)` to Perl.
- Add `$mob->DamageHateListPercentage(damage, distance)` to Perl.
- Add `$mob->DamageHateListBots(damage)` to Perl.
- Add `$mob->DamageHateListBots(damage, distance)` to Perl.
- Add `$mob->DamageHateListBotsPercentage(damage)` to Perl.
- Add `$mob->DamageHateListBotsPercentage(damage, distance)` to Perl.
- Add `$mob->DamageHateListClients(damage)` to Perl.
- Add `$mob->DamageHateListClients(damage, distance)` to Perl.
- Add `$mob->DamageHateListClientsPercentage(damage)` to Perl.
- Add `$mob->DamageHateListClientsPercentage(damage, distance)` to Perl.
- Add `$mob->DamageHateListNPCs(damage)` to Perl.
- Add `$mob->DamageHateListNPCs(damage, distance)` to Perl.
- Add `$mob->DamageHateListNPCsPercentage(damage)` to Perl.
- Add `$mob->DamageHateListNPCsPercentage(damage, distance)` to Perl.
- Add `$mob->GetHateListBots()` to Perl.
- Add `$mob->GetHateListBots(distance)` to Perl.
- Add `$mob->GetHateListClients()` to Perl.
- Add `$mob->GetHateListClients(distance)` to Perl.
- Add `$mob->GetHateListNPCs()` to Perl.
- Add `$mob->GetHateListNPCs(distance)` to Perl.

# Lua
- Add `mob:DamageHateList(damage)` to Lua.
- Add `mob:DamageHateList(damage, distance)` to Lua.
- Add `mob:DamageHateListPercentage(damage)` to Lua.
- Add `mob:DamageHateListPercentage(damage, distance)` to Lua.
- Add `mob:DamageHateListBots(damage)` to Lua.
- Add `mob:DamageHateListBots(damage, distance)` to Lua.
- Add `mob:DamageHateListBotsPercentage(damage)` to Lua.
- Add `mob:DamageHateListBotsPercentage(damage, distance)` to Lua.
- Add `mob:DamageHateListClients(damage)` to Lua.
- Add `mob:DamageHateListClients(damage, distance)` to Lua.
- Add `mob:DamageHateListClientsPercentage(damage)` to Lua.
- Add `mob:DamageHateListClientsPercentage(damage, distance)` to Lua.
- Add `mob:DamageHateListNPCs(damage)` to Lua.
- Add `mob:DamageHateListNPCs(damage, distance)` to Lua.
- Add `mob:DamageHateListNPCsPercentage(damage)` to Lua.
- Add `mob:DamageHateListNPCsPercentage(damage, distance)` to Lua.
- Add `mob:GetHateListBots()` to Lua.
- Add `mob:GetHateListBots(distance)` to Lua.
- Add `mob:GetHateListClients()` to Lua.
- Add `mob:GetHateListClients(distance)` to Lua.
- Add `mob:GetHateListNPCs()` to Lua.
- Add `mob:GetHateListNPCs(distance)` to Lua.

# Notes
- Offers an extreme amount of short hands when grabbing hate list entities by a specific type or damaging a specific type of entity on an NPC's hatelist.
- Should save operators having to use `GetHateList()` then loop it to get the entries they want to do something.

* Cleanup.
2022-11-16 07:16:47 -06:00
Kinglykrab 6ff52f94c4 [Repositories] Add Bot Repositories. (#2529)
* [Repositories] Add Bot Repositories.

* Remove unnecessary table.

* Add back table.
2022-11-16 07:15:48 -06:00
Kinglykrab b5035d7e03 [Commands] Remove #profiledump and #profilereset Commands. (#2546)
- These commands don't seem to be used anymore.
2022-11-16 07:15:03 -06:00
Kinglykrab 8f1b87c5e4 [Quest API] Add Owner methods to Perl/Lua. (#2542)
* [Quest API] Add Owner methods to Perl/Lua.

# Perl
- Add `$mob->GetOwner()` to Perl.

# Lua
- Add `mob:GetOwnerID()` to Lua.

# Notes
- `GetOwner()` exists in Lua, but not Perl.
- `GetOwnerID()` exists in Perl, but not Lua.

* Update lua_mob.cpp
2022-11-14 18:03:26 -05:00
Kinglykrab e72ec4ae56 [Quest API] Add RandomizeFeature() overloads to Perl/Lua. (#2532)
# Perl
- Add `$mob->RandomizeFeatures()` to Perl.
- Add `$mob->RandomizeFeatures(send_illusion)` to Perl.
- Add `$mob->RandomizeFeatures(send_illusion, set_variables)` to Perl.

# Lua
- Add `mob:RandomizeFeatures()` to Lua.
- Add `mob:RandomizeFeatures(send_illusion)` to Lua.
- Add `mob:RandomizeFeatures(send_illusion, set_variables)` to Lua.

# Notes
- Previous overload required `send_illusion` and `set_variables` despite both default values being `true`, this will allow you to just send nothing if you want both to be `true`.
- Change `RandomizeFeatures()` type to `bool` from `void` to match source method, returns `false` when used on a race that has no features to randomize.
- This allows operators to do something different if the NPC can't use this method.
2022-11-14 16:59:17 -05:00
Kinglykrab fd2fc76706 [Commands] Cleanup #depopzone Command. (#2537)
* [Commands] Cleanup #depopzone Command.

- Cleanup messages and logic.
- Add optional `start_spawn_timers` parameter to start spawn timers of NPCs when depopped.

* Update depopzone.cpp
2022-11-14 16:47:20 -05:00
Kinglykrab f668949c24 [Quest API] Add SendGMCommand() to Perl/Lua. (#2527)
* [Quest API] Add SendGMCommand() to Perl/Lua.

# Perl
- Add `$client->SendGMCommand(message)` to Perl.
- Add `$client->SendGMCommand(message, ignore_status)` to Perl.

# Lua
- Add `client:SendGMCommand(message)` to Lua.
- Add `client:SendGMCommand(message, ignore_status)` to Lua.

# Notes
- `ignore_status` allows you to have players use GM commands that they are not the required status level for through the Quest API.
- `ignore_status` is default false, so if you don't send it, it checks and makes sure the player can use the command you're sending before allowing it.

* Typo.

* Formatting.
2022-11-14 16:47:02 -05:00
Kinglykrab 36887203d3 [Commands] Cleanup #doanim Command. (#2540)
* [Commands] Cleanup #doanim Command.

- Cleanup messages and logic.
- Allow you to use animation names or IDs, could possibly extend this to quest API in the future.

* Update dialogue_window.h
2022-11-14 16:38:05 -05:00
Kinglykrab e5ad9264d0 [Quest API] Add GetRandomClient(), GetRandomMob() and GetRandomNPC() overloads to Perl/Lua. (#2541)
* [Quest API] Add GetRandomClient(), GetRandomMob() and GetRandomNPC() overloads to Perl/Lua.

# Perl
- Add `$entity_list->GetRandomClient()` to Perl.
- Add `$entity_list->GetRandomMob()` to Perl.
- Add `$entity_list->GetRandomNPC()` to Perl.

# Lua
- Add `eq.get_entity_list():GetRandomClient()` to Lua.
- Add `eq.get_entity_list():GetRandomMob()` to Lua.
- Add `eq.get_entity_list():GetRandomNPC()` to Lua.

# Notes
- We didn't have overloads before without XYZ, so was harder to do a zone-wide random.

* Update lua_entity_list.cpp
2022-11-14 14:08:02 -05:00
Kinglykrab df57138a61 [Commands] Cleanup #devtools Command. (#2538)
* [Commands] Cleanup #devtools Command.

- Cleanup messages and logic.

* Update client.cpp
2022-11-14 14:06:36 -05:00
Kinglykrab aa506110e1 [Commands] Cleanup #depop Command. (#2536)
* [Commands] Cleanup #depop Command.

- Cleanup messages and logic.
- Add optional `start_spawn_timer` parameter to start spawn timer of NPC when depopped.

* Update command.cpp
2022-11-14 14:05:48 -05:00
Kinglykrab 2c656c4110 [Commands] Cleanup #emote Command. (#2535)
* [Commands] Cleanup #emote Command.

- Cleanup messages and logic.
- Allow `^` separator to send multiple messages by name, world, or zone.

* Update emote.cpp
2022-11-14 14:05:40 -05:00
Kinglykrab 8d184fc6c0 [Commands] Cleanup #scribespell and #scribespells Commands. (#2534)
- Cleanup messages and logic.
2022-11-14 14:05:34 -05:00
Kinglykrab 9c967c24b8 [Quest API] Add Popup methods to Perl/Lua. (#2533)
* [Quest API] Add Popup methods to Perl/Lua.

# Perl
- Add `quest::popupcentermessage(message)` to Perl.
- Add `quest::popupcolormessage(color, message)` to Perl.
- Add `quest::popupindent()` to Perl.
- Add `quest::popuplink(link)` to Perl.
- Add `quest::popuplink(link, message)` to Perl.

# Lua
- Add `eq.popup(title, message)` to Lua.
- Add `eq.popup(title, message, popup_id)` to Lua.
- Add `eq.popup(title, message, popup_id, buttons)` to Lua.
- Add `eq.popup_center_message(message)` to Lua.
- Add `eq.popup_color_message(color, message)` to Lua.
- Add `eq.popup_indent()` to Lua.
- Add `eq.popup_link(link)` to Lua.
- Add `eq.popup_link(link, message)` to Lua.

# Notes
- Adds the Perl plugins like PWAutoCenter, PWIndent, and PWHyperlink.
- Parses out HTML `<>` tags automatically in `popupautocenter` to properly center stuff like colored messages. (Doesn't work with links)
- This lets Lua users have similar functionality to Perl users.

* Add tables and break.

* Add indent_count to indent method.

* Move to Dialogue Window.
2022-11-14 14:05:24 -05:00
Kinglykrab 31e5622dad [Quest API] Add CloneAppearance() to Perl/Lua. (#2531)
* [Quest API] Add CloneAppearance() to Perl/Lua.

# Perl
- Add `$client->CloneAppearance(other)` to Perl.
- Add `$client->CloneAppearance(other, clone_name)` to Perl.

# Lua
- Add `client:CloneAppearance(other)` to Lua.
- Add `client:CloneAppearance(other, clone_name)` to Lua.

# Notes
- Allows operators to easily clone appearance between mobs in a script without relying on a plugin or module.

* Update mob_appearance.cpp

* Update mob.cpp
2022-11-14 14:05:05 -05:00
Kinglykrab 8a449b0152 [Repositories] Update Character EXP Modifiers Repository (#2530) 2022-11-14 14:04:55 -05:00
Kinglykrab 5f4a8d17f5 [Quest API] Add SplitMoney() with Client splitter to Perl. (#2525)
# Perl
- Add `$group->SplitMoney(copper, silver, gold, platinum, splitter)` to Perl.
- Add `$raid->SplitMoney(group_id, copper, silver, gold, platinum, splitter)` to Perl.
2022-11-14 14:04:44 -05:00
Kinglykrab c5c57b7541 [Quest API] Add Group/Raid overloads to Perl/Lua. (#2526)
# Perl
- Add `$raid->GetGroup(client)` to Perl.
- Add `$raid->GetGroupMember(member_index)` to Perl.
- Add `$raid->IsLeader(client)` to Perl.

# Lua
- Add `group:GroupMessage(sender, message)` to Lua.
2022-11-14 14:04:38 -05:00
Kinglykrab 3cb13969ff [Quest API] Add GetAverageLevel() to Perl/Lua. (#2524)
# Perl
- Add `$group->GetAverageLevel()` to Perl.

# Lua
- Add `group:GetAverageLevel()` to Lua.
- Convert `group:GetHighestLevel()` from `int` to `uint32` in Lua.
- Convert `group:GetLowestLevel()` from `int` to `uint32` in Lua.
2022-11-14 14:04:14 -05:00
Kinglykrab fca99bb274 [Bots] Hotfix for possible crash. (#2539)
* [Bots] Hotfix for possible crash.

Possible crash due to 4 nullable columns in `bot_spells_entries` table.

* Update 2022_11_13_bot_spells_entries.sql
2022-11-13 20:44:07 -05:00
Kinglykrab 815593b9bc [Cleanup] Remove unusued Max Item ID Constant (#2528) 2022-11-08 14:59:24 -05:00
Aeadoin 33b95c42c2 [Feature] Change #scribespells to be aware of spellgroups & ranks (#2501)
* Change #scribespells to be aware of spellgroups & ranks

* Formatting

* Fix Formatting, and change stored return  data type to match function return type.

* Compact If Statements

* Implemented SQL Query to reduce number of iterations required.

* Cleaned up Query, and improved performance

* Cleaned up SQL Queries

* Formatting

* Indenting fix.

* Update client.cpp

* Fix Formatting in spells.cpp

* Fix ValueWithin.

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
Co-authored-by: Kinglykrab <89047260+Kinglykrab@users.noreply.github.com>
2022-11-06 18:01:58 -05:00
hg e01ac39887 [Quest API] Send delivered task items in trade events (#2518)
This restores sending items to EVENT_TRADE that are updated by source
controlled delivery tasks which was removed in 7cf96ca2d8.

That patch filtered out items consumed by task updates to fix a few bugs
with items being returned despite incrementing a task:

  - If an npc without a quest trade event handler was the target of a
    delivery task for a NoDrop/non-Quest item, the npc would auto return
    it due to the `ReturnNonQuestNoDropItems` rule.

  - If an npc without a quest trade event handler was the target of a
    delivery task for a non-NoDrop item, the item would be added to the
    npc's loot.

  - If an npc with an EVENT_ITEM/EVENT_TRADE quest handler used the Lua
    or Perl trade plugins, the plugins would return task items unless
    specific checks for the turned in slots existed.

The quest plugin item returns are problematic for this since they just
summon to return items not handled by the script

  e.g. For a task to deliver N Large Fruit Bat Wings (item id 19616),
  if a player turned in 1 Wing in slot 1 and a stack of 20 Wings in slot
  2, the task would be incremented 21 times and the following Lua trade
  handler would return the stack of 20 from the 2nd trade slot:

  ```lua
    function event_trade(e)
      local item_lib = require("items")
      if item_lib.check_turn_in(e.trade, { item1 = 19616 }) then
        eq.debug("Lua consumed 1 slot and will return other slots")
      end
      item_lib.return_items(e.self, e.other, e.trade)
    end
  ```

  This also occured with the perl plugin though slightly differently
  since that plugin returns all slots unless the exact handin slot count
  matches (requiring check_handin conditions for all slots):

  ```perl
    sub EVENT_ITEM {
      if (plugin::check_handin(\%itemcount, 19616 => 1)) {
        # No issue if only one slot used for trade (item not returned)
      }
      # Perl fails handin check if multiple slots not checked and returns all
      plugin::return_items(\%itemcount);
    }
  ```

While that patch solved the issue, it's inconvenient and wrong to not
receive items in trade events used in a source task update. It breaks
existing trade scripts for tasks that aren't quest controlled and it
forces tasks to be changed to quest controlled and manually updated to
script any extra behavior.

This patch stores the task update count on the item instance before
dispatching it to quests. The burden is now on quests and plugins to
use that value in order to prevent returning items consumed by tasks.

`ItemInstance::RemoveTaskDeliveredItems` has been added to simplify
handling this in plugins which is also used for non-quest item returns.
2022-11-06 17:10:30 -05:00
Aeadoin 7e7358e9b6 [Bots] Add Data Bucket support to Bot Spell Entries. (#2505)
* [Bots] Add Data Bucket support to Bot Spell Entries.

* Cleanup Formatting and Functions

* Consolidated "CheckDataBucket" Functions

* Remove unneeded CastToClient

* Add choice to format data buckets as either "character-id" or "bot-id" to Bot spells

* Fix Formatting

* Clean up.

* Update npc.h

* Fix Bot Casting issues

* Formatting

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
Co-authored-by: Kinglykrab <89047260+Kinglykrab@users.noreply.github.com>
2022-11-06 17:06:01 -05:00
hg de63eaa4b2 [Quest API] Add apis to end shared tasks (#2521)
This required some minor shared task refactoring

- Shared task expiration handling was moved to world. Previously this
  was handled by zone and had clients self remove when a shared task
  expired. This resulted in wrong messages when a task ended.

- FailTask is now implemented for shared tasks which previously only
  made the client quit the shared task. It now fails the task for all
  members by ending the shared task.

The `Client::EndSharedTask` api will end the client's current shared
task (removing all members). This is similiar to the `FailTask` api
except it doesn't require a `task_id` and the red task fail banner is
optional (live doesn't use it for shared tasks).

The global `end_dz_task` api was added for when a client context isn't
available. This will end a shared task if the current zone is a dynamic
zone for a shared task mission. Currently only shared tasks use dynamic
zones but this api can be expanded if support is added for tasks/quests.

The global `get_dz_task_id` was added to conveniently get the task id
for the current dynamic zone if it's used for a mission. Note this is
a database hit since that information is not available at zone level.
2022-11-06 11:04:39 -05:00
hg 3d7c43e92f [Quest API] Add ResetDecayTimer() to Perl/Lua. (#2520) 2022-11-06 10:48:10 -05:00
hg 69e90c1739 [Quest API] Export corpse in EVENT_DEATH_COMPLETE (#2519)
It wasn't possible to easily obtain the corpse from post-death events
because the killed entity id is assigned to the corpse and reset to 0
on the entity before the events are dispatched.

This exposes the killed entity's corpse to EVENT_DEATH_COMPLETE and
EVENT_DEATH_ZONE. Lua exports a Corpse object and perl exports a corpse
entity id.

The purpose of this is to make it easier to add items dynamically on
death. Ideally this would be done in EVENT_DEATH before the corpse is
made, but there's currently some combat system bugs that make that event
unusable since it can be dispatched multiple times.

A follow up will provide an api to reset corpse decay times since adding
items after corpse creation will require quests to manually reset the
decay timer in case the corpse had zero items.
2022-11-06 10:36:57 -05:00
Kinglykrab 13b2af1a91 [Quest API] Add Instance ID/Version exports to EVENT_ZONE. (#2502)
# Perl
- Add `$from_instance_id` to EVENT_ZONE in Perl.
- Add `$from_instance_version` to EVENT_ZONE in Perl.
- Add `$target_instance_id` to EVENT_ZONE in Perl.
- Add `$target_instance_version` to EVENT_ZONE in Perl.

# Lua
- Add `e.from_instance_id` to EVENT_ZONE in Lua.
- Add `e.from_instance_version` to EVENT_ZONE in Lua.
- Add `e.instance_id` to EVENT_ZONE in Lua.
- Add `e.instance_version` to EVENT_ZONE in Lua.

# Notes
- This will allow Operators to prevent people from entering zones by Instance ID or Instance Version.
2022-11-05 11:38:03 -04:00
hg 9c7dd70b5f [Quest API] Add Lua handlers for zone controller events (#2514)
This cleans up some of the NPC::Death event dispatch code.

Adds handlers for EVENT_SPAWN_ZONE and EVENT_DEATH_ZONE used by zone
controller and fixes the death handler exports which were incorrect.
2022-11-05 11:13:39 -04:00
hg 070bf64d6a [Tasks] Only update loot tasks for NPC corpses (#2513)
This fixes a bug that allowed looting items from a player's corpse to
increment a task if it didn't have an npc target defined. It looks
like this bug existed before the changes in 7482cfc0.

This also now passes count for task loot updates to handle item stacks.

Also fixes incorrectly casting Corpse to NPC on loot update
2022-11-05 11:13:02 -04:00
Kinglykrab f6dbdf5db8 [Quest API] Add EVENT_AA_BUY and EVENT_AA_GAIN to Perl/Lua. (#2504)
# Perl
- Add EVENT_AA_BUY to Perl.
  - Exports `$aa_cost`, `$aa_id`, `$aa_previous_id`, and `$aa_next_id`
- Add EVENT_AA_GAIN to Perl.
  - Exports `$aa_gained`
- Add quest::getaaname(aa_id) to Perl.

# Lua
- Add event_aa_buy to Lua.
  - Exports `e.aa_cost`, `e.aa_id`, `e.aa_previous_id`, and `e.aa_next_id`
- Add event_aa_gain to Lua.
  - Exports `e.aa_gained`
- Add eq.get_aa_name(aa_id) to Lua.
2022-11-05 11:09:47 -04:00
Kinglykrab a3928ec504 [Quest API] Add GetUltimateOwner() to Perl/Lua. (#2516)
# Perl
- Add `$mob->GetUltimateOwner()` to Perl.

# Lua
- Add `mob:GetUltimateOwner()` to Lua.

# Notes
- Allows operators to get ultimate owner of something like a pet's pet or a pet's swarm pet.
2022-11-05 08:35:14 -04:00
Kinglykrab 8d1dd52db3 [Quest API] Add GetLowestLevel() to Perl. (#2517)
# Perl
- Add `$group->GetLowestLevel()` to Perl.

# Notes
- This exists in Lua, but not Perl.
2022-11-05 08:34:29 -04:00
Kinglykrab 2218f46b5b [Commands] Cleanup #dbspawn2 Command. (#2493)
* [Commands] Cleanup #dbspawn2 Command.

Add some descriptive messages so that you get some feedback from the command.

* Update dbspawn2.cpp
2022-10-29 21:22:24 -04:00
Kinglykrab 53dcd14534 [Commands] Cleanup #emotesearch and #emoteview Command. (#2494)
* [Commands] Cleanup #emoteview Command.

Cleanup command messages and logic.

Add constants for Emote Events and Emote Types and replace all the old constants with the new constants.

* Update emoteview.cpp

* Cleanup #emotesearch Command.
2022-10-29 21:22:17 -04:00
Kinglykrab dcbc9a358f [Commands] Cleanup #modifynpcstat Command. (#2499)
* [Commands] Cleanup #modifynpcstat Command.

Cleanup messages and logic,

Add map and loop through it to display all stats, can add to this in the future if we add more stuff modifiable by this command.

* Delete settings.json

* Update modifynpcstat.cpp

* Update modifynpcstat.cpp

* Update questmgr.h
2022-10-29 21:22:07 -04:00
Kinglykrab b512447448 [Bots] Add give/remove saylinks to ^itemuse. (#2503)
Adds shortcut saylinks for giving items to bots or removing items from them.
2022-10-29 21:22:01 -04:00
hg 444a4f6744 [Tasks] Add pre-task update event (#2512)
This adds the player EVENT_TASK_BEFORE_UPDATE event which will allow
quests to prevent a source controlled task update by returning non-zero.
2022-10-29 20:46:08 -04:00
hg 43ec9dc815 [Tasks] Let task completion event block task rewards (#2511)
Returning non-zero from EVENT_TASK_COMPLETE will prevent task rewards
and completion emote. This is necessary for a DoN mission which scripts
a mission failure but still gives the lockout.
2022-10-29 20:46:00 -04:00
hg 9e836a9780 [Feature] Add player /inspect quest event (#2508)
Returning non-zero from EVENT_INSPECT will prevent default message
2022-10-29 19:49:48 -04:00
hg 3bc5d4b125 [Quest API] Add ResetAlternateAdvancementRank() to Perl/Lua. (#2510)
Exports Client::ResetAlternateAdvancementRank
2022-10-29 19:49:23 -04:00
hg 9f033df196 [Cleanup] Send eqstr message in AddAAPoints (#2507)
This api is only used by quests
2022-10-29 19:48:27 -04:00
hg 16ee25224d [Feature] Add special ability to block /open (#2506)
This adds the IMMUNE_OPEN (53) special ability to prevent /open on
LDON_TREASURE classes.
2022-10-29 19:48:14 -04:00
hg 56510e6383 [Quest API] Add Corpse::AddItem overloads for Lua (#2509)
Perl already has these
2022-10-29 19:48:03 -04:00
Aeadoin bf43bda1e2 [Bots] Cleanup Bot Spell Functions, reduce reliance on NPC Functions/Attributes (#2495)
* [Bots] Initial Cleanup of Functions, moved Bot Casting out of mob_ai.cpp

* Moved Bots off NPC AI_Spells Struct, and AI_Spells private attribute.

* Formatting Fixes, fixed LogAI entries, Added LogAIModerate Alias

* Add Constants.

* Added Bot DB Struct, fixed some potential casting issues

* Formatting

* Formatting
2022-10-29 16:38:15 -04:00
hg 5708164511 [Tasks] Add method to filter shared task offers (#2497) 2022-10-29 16:38:04 -04:00
Kinglykrab 7abb02655d [Rules] Add Toggle for Warrior Shielding (#2496)
This adds a toggle to disable the Warrior shielding ability. This will not stop the client-side message from sending when you do not have a target, but it will keep the ability from doing anything.
2022-10-22 14:59:52 -05:00
Akkadius cb08c02537 [Hotfix] Fix path load ordering for CLI commands 2022-10-15 22:26:12 -05:00
Chris Miles dea94ce63d [Zoning] Revert #2424 (#2492) 2022-10-15 20:48:15 -05:00
Chris Miles bd302b8394 [Logs] Have #reload logs also reload UCS logging (#2491) 2022-10-15 17:06:36 -05:00
Coreidan 221140c3c5 [Doors] Fix Neriak PoK Stone (#2486)
* [Doors] Fix Neriak PoK Stone

This augments the recent zone version heading changes where the doors for Neriak need to be corrected. The client version mask was incorrect and the locations were incorrect for the client.  Tested in my sandbox.

* [Doors] Change Misty PoK Stone Destination To Old Zone

Code fix #2482 changed Misty PoK Stone destination to the new misty zone.  This needed to be changed back to the old zone.  Zone destination was modified along with destination coordinates.

Co-authored-by: chrisjezorek <chris@jezoreksolutions.com>
2022-10-15 15:18:12 -05:00
Chris Miles 7092183103 [Crash] Stability Fixes (#2489)
* Input sanitation for #zone

* Update zone.cpp

* Update clientlist.cpp

* Test

* Test

* Remove logging, revert /who all code

* Remove log

* Update clientlist.cpp
2022-10-15 15:17:50 -05:00
Chris Miles bbbebdd346 [Crash] Pointer validation in mob iteration loops (#2490) 2022-10-15 15:10:11 -05:00
Akkadius 05723ad1e8 [Hotfix] Return weather_type_map 2022-10-14 17:57:55 -05:00
Chris Miles 4c7a625d7c [Doors] Fix Misty PoK Stone (#2482) 2022-10-13 21:03:15 -05:00
Aeadoin 1b82e6b283 [Feature] Add Hate Override for Heals (#2485)
* [Feature] Add Hate Override for Heals

* Formatting

Co-authored-by: Akkadius <akkadius1@gmail.com>
2022-10-13 21:02:59 -05:00
Kinglykrab 0240a9cc76 [Quest API] Add IsRaining() and IsSnowing() to Perl/Lua. (#2477)
* [Quest API] Add IsRaining() and IsSnowing() to Perl/Lua.

- Add quest::IsRaining() to Perl.
- Add quest::IsSnowing() to Perl.
- Add eq.is_raining() to Lua.
- Add eq.is_snowing() to Lua.

This will allow server operators to tell if a zone is currently raining, snowing, or neither.

* Remove unnecessary quest manager stuff.

* Added constants and cleaned up #weather command

* Revert "Added constants and cleaned up #weather command"

This reverts commit 2ec85304b7.

* Revert "Revert "Added constants and cleaned up #weather command""

This reverts commit 76f4e411b6.

* Delete settings.json

* Update zone.cpp
2022-10-13 20:59:55 -05:00
Aeadoin eb02525d36 [Feature] Add Support for "Show Mine Only" Filters (#2484)
* [Feature] Add Support for "Show Mine Only" Filters

* Added "Show Mine Only" support for HoTs

* remove this-> as it's implied.
2022-10-12 20:39:53 -05:00
Michael d7097e84ff [Feature] AA Cap Limit (#2423)
* [Feature] AA Cap Limit

Will force unused AA points to the cap if they exceed the cap. Will also force AA Percentage to 0%. NOTE: The variable, UnusedAAPointCap, should NOT be lowered once implemented without first checking the DB for how many Unused AAs people have.  The next time they gain any EXP, it WILL drop them to cap.  Also, PCs should be given warning prior to this patch going to Live, to ensure they have a chance to spend any AAs above the cap, else they will lose them.

* Fix formatting on strings

* Fixes

* Change ConvertArray to fmt

* Fix formating and >= 0 aa_cap per review
2022-10-12 20:14:44 -05:00
Aeadoin 3de65d46b4 [Bug Fix] Fixed Spell Logic for Bot Nukes (#2481) 2022-10-12 20:14:14 -05:00
Kinglykrab 303b35a755 [Commands] Cleanup #setlanguage Command. (#2464)
* [Commands] Cleanup #setlanguage Command.

Cleanup #setlanguage command and remove unnecessary variables.

* Tabs not spaces.

* newline
2022-10-12 20:13:25 -05:00
Aeadoin a9e218acfa [Feature] Soft Delete Bots on Character Soft Delete (#2467)
* [Feature] Soft Delete Bots on Character SoftDelete

* Moved Bot Soft Delete logic to be inline with SoftDeletes rule.

* Update from feedback

Co-authored-by: Akkadius <akkadius1@gmail.com>
2022-10-12 20:12:29 -05:00
Aeadoin 0f2da56b04 [Feature] Spell Ranks will now work with AllowSpellMemorizeFromItem Rule (#2475)
* Figured out Popup Windows

* SendPopupToClient, and response works

* Added Popup logic

* Didn't use WriteSpellInfoSection function

* Misc fixes, DB String ID 11004  now referenced as a constant

* Remove use of "this"

* Added "else" statement to return if "AllowSpellMemorizeFromItem" rule is not used
2022-10-12 19:53:21 -05:00
Kinglykrab f3f8a50d3c [Bug Fix] Allow Songs to be scribed from scrolls (#2460)
* [Bug Fix] Allow Songs to be scribed from scrolls

Songs weren't capable of being scribed from scrolls because we didn't check for `Song: ` in the name.

Converted old logic to substrings, can probably do it cleaner, but it's better than it was.

Removed extraneous `initiator->IsClient()` calls as `initiator` is **always** a client.

* Fix substr logic.
2022-10-11 21:29:54 -05:00
Chris Miles bc72641eef [Zoning] Fix zone race condition (#2479)
* Testing

* Separate auto shutdown fix

* Revert for PR

* Invalidate lock in places where zoning is cancelled
2022-10-11 20:23:27 -05:00
Chris Miles 18bfee5616 [Zone Shutdown] Fix for resetting shutdown timer (#2480) 2022-10-11 20:23:12 -05:00
Chris Miles 6c8930eacd [Logging] Fix zoning log typo (#2478) 2022-10-11 18:01:24 -04:00
Chris Miles e18d4a81c5 [Zoning] Possible zoning under world fix (#2424) 2022-10-10 22:55:49 -05:00
Alex 77c3841a49 [Process Management] Change all executables to use the default event loop run (#2471)
* Loginserver change to event loop run.

* eqlaunch, loginserver, queryserv, world
2022-10-10 22:55:39 -05:00
Michael Cook (mackal) 832bffa811 Fix Client::QuestReward overload SummonItem call (#2472)
The overload that took the packet struct wasn't calling SummonItem with
-1 charges, resulting it chargeless items if they had any
2022-10-05 16:23:03 -04:00
Aeadoin 267472fc91 [Bug Fix] Touch Of Vinitras was ignoring pet DT rule (#2469) 2022-10-03 19:35:52 -04:00
Chris Miles 44f760d177 [Crash] Fix reload crashes (#2462) 2022-09-30 07:54:05 -05:00
Michael Cook (mackal) 50fc4d68aa eqlaunch wasn't loading paths (#2461) 2022-09-29 14:23:20 -04:00
Akkadius ee167bbc64 [Hotfix] Fix lua mod load path 2022-09-29 12:06:01 -05:00
Chris Miles b20d0b84f6 [Logging] Remove loginserver unhandled error (#2458) 2022-09-28 22:20:20 -05:00
Kinglykrab 267d73ca27 [Tasks] Use zone currencies instead of hard-coded enum. (#2459) 2022-09-28 22:20:07 -05:00
Chris Miles c1626da40d [Crash] Websocket Crash fix race when fetching log categories (#2456)
* [Crash] Websocket crash fix race

* Refine check
2022-09-28 21:29:04 -05:00
Aeadoin 554b41d424 [Feature] Change Lifetap Emotes to be filterable. (#2454) 2022-09-28 21:03:26 -05:00
Chris Miles 714fb032e9 [Crash] Fix spawn race condition shown by #repop (#2455)
* Troubleshooting

* Debugging

* Debugging

* Debugging

* Debugging

* Remove debug line

* Revert back to GetRawNPCTypeName
2022-09-28 21:03:05 -05:00
Chris Miles 74dfc1ae3c [Database] Add fallback migration for logsys columns (#2457) 2022-09-28 21:02:51 -05:00
Akkadius 6b1e3d94f8 [Hotfix] Force collation on conversion script 2022-09-28 14:15:16 -05:00
Chris Miles f357361474 [Logging] Add stack trace in code paths that shouldn't occur (#2453)
* [Logging] Add stack trace in code paths that shouldn't occur

* Update zone_store.cpp

* Windows workaround
2022-09-28 13:32:39 -05:00
Chris Miles f8e7576ae7 [File Paths] Implement Path Manager (#2440)
* Push up branch for testing

* Path manager

* Tweaks

* Changes

* More path work

* Update paths for eqemu_server.pl

* More path work

* Import and export client files

* Path remove

* More path work

* Update eqemu_config.h

* Fix tests

* Tests disable temp

* Update eqemu_config.h

* Update .drone.yml

* Hook tests back up

* Update main.cpp

* Platform tests

* Fix include

* Use std::filesystem on windows

* Fix IPCMutex name on windows

* std::filesystem changes

* Update path_manager.cpp

* Explicit string cast

* Explicit string cast

* Update path_manager.cpp

* Windows fixes

* Mapped files

* Relative fixes

* Use relative paths off of cwd

* Update Debian image to Debian 11 (updates GCC)

Co-authored-by: hg <4683435+hgtw@users.noreply.github.com>
2022-09-28 04:08:59 -05:00
Chris Miles 19791195e5 [Logging] Netcode Logging Unify (#2443)
* [Logging] Unify netcode logging

* More tweaks, generator

* Exclude OP_SpecialMesg at callback level

* Consolidate packet loggers

* Log at EQStream level instead of proxy

* Fix C->S

* Server to server logging

* C-S for Loginserver

* Hook UCS for C->S

* Update eqemu_logsys.h

* World C->S logging

* Translate opcodes through patch system for client to server

* Additional logging requests

* Add detailed opcode translation logging

* vStringFormat resiliency

* Translate loginserver C->S

* Simplify out message string (reduce copies) and ignore legacy formats

* Update eqemu_logsys.cpp

* Log file format

* Handle deprecated categories
2022-09-28 03:42:09 -05:00
Chris Miles 9d766bf5dc [World CLI] Refactor world CLI to be easier to reason about (#2441) 2022-09-28 03:04:09 -05:00
Chris Miles 7ac8fe17e5 [Library] Bump httplib to 0.11.2 (#2442) 2022-09-28 03:03:23 -05:00
Kinglykrab 959a17daea [Quest API] Add GetGMStatus() to Perl/Lua. (#2448)
* [Quest API] Add GetGMStatus() to Perl/Lua.

- Add $client->GetGMStatus() to Perl.
- Add client:GetGMStatus() to Lua.
- Fix client:Admin() using Lua_Safe_Call_Bool().

This is just a more descriptive form of $client->Admin() in Perl and client:Admin() in Lua.

* Update lua_client.cpp

* Update perl_client.cpp
2022-09-28 03:03:07 -05:00
Kinglykrab 90406e0328 [Quest API] Add Merchant Events to Perl/Lua. (#2452)
- Add EVENT_ALT_CURRENCY_MERCHANT_BUY to Perl/Lua.
- Add EVENT_ALT_CURRENCY_MERCHANT_SELL to Perl/Lua.
- Add EVENT_MERCHANT_BUY to Perl/Lua.
- Add EVENT_MERCHANT_SELL to Perl/Lua.

This will allow server operators to track or do specific stuff based on if a person buys X item from Y NPC or whatever.
2022-09-28 03:02:42 -05:00
hg e883703b2f [Tasks] Schema simplification (#2449)
* Combine task_activity item and npc fields

This will make tooling easier.

While denormalizing goallists may not be ideal, it decouples tasks from
rewards which share the table and removes a redundant column in favor
of a using the delimited string which better matches live packet data.

* [Tasks] Deprecate goallists table, migrate reward goal lists, simplify logic

* Update 2022_09_25_task_concat_matchlists.sql

* Update 2022_09_25_task_concat_matchlists.sql

* Tweaks

* Fix reward column name in conversion script

* Task reward stacking

* Update task_client_state.cpp

* Implement stack counts

* Fix reward item instance memory leak

* Validate reward item instance

* Fix item reward message

* Fix findtask

Co-authored-by: Akkadius <akkadius1@gmail.com>
2022-09-28 02:31:05 -05:00
514 changed files with 64588 additions and 24984 deletions
-21
View File
@@ -1,21 +0,0 @@
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.101.1/containers/ubuntu-18.04-git
{
"name": "Ubuntu 18.04 EQEMU",
// Moved from dockerfile to image so it builds faster
"image": "eqemu/devcontainer:0.0.2",
// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],
// Add the IDs of extensions you want installed when the container is created.
"extensions": ["ms-vscode.cpptools", "ms-azuretools.vscode-docker"],
"mounts": ["source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"],
"remoteEnv": {
"HOST_PROJECT_PATH": "${localWorkspaceFolder}"
}
}
+75 -10
View File
@@ -1,7 +1,11 @@
---
kind: pipeline
type: docker
name: EQEmulator Server Linux CI
name: Build Linux
clone:
depth: 1
# Limits how many of these builds can run on the drone runner at a time, this isn't about cores
concurrency:
@@ -10,18 +14,79 @@ concurrency:
volumes:
- name: cache
host:
path: /var/lib/cache
path: /var/lib/cache-release
steps:
- name: server-build
# Source build script https://github.com/Akkadius/akk-stack/blob/master/containers/eqemu-server/Dockerfile#L20
image: akkadius/eqemu-server:latest
- name: Build Linux X64
image: akkadius/eqemu-server:v11
environment:
GITHUB_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
RCLONE_CONFIG_REMOTE_TYPE: ftp
RCLONE_FTP_HOST: drone.akkadius.com
RCLONE_FTP_USER: artifacts
RCLONE_FTP_PASS:
from_secret: RCLONE_FTP_PASS
commands:
- sudo chown eqemu:eqemu /drone/src/ * -R
- sudo chown eqemu:eqemu /home/eqemu/.ccache/ * -R
- git submodule init && git submodule update && mkdir -p build && cd build && cmake -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LUA=ON -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING="-O0 -g -DNDEBUG" -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
- ./utils/scripts/build/linux-build.sh
volumes:
- name: cache
path: /home/eqemu/.ccache/
---
kind: pipeline
type: exec
name: Build Windows
clone:
depth: 1
platform:
os: windows
arch: amd64
steps:
- name: Build Windows X64
environment:
RCLONE_CONFIG_REMOTE_TYPE: ftp
RCLONE_FTP_HOST: drone.akkadius.com
RCLONE_FTP_USER: artifacts
RCLONE_FTP_PASS:
from_secret: RCLONE_FTP_PASS
GITHUB_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
commands:
- .\utils\scripts\build\windows-build.ps1
---
kind: pipeline
type: docker
name: Publish Artifacts to Github
steps:
- name: Upload Artifacts
image: akkadius/eqemu-build-releaser:v3
environment:
RCLONE_CONFIG_REMOTE_TYPE: ftp
RCLONE_FTP_HOST: drone.akkadius.com
RCLONE_FTP_USER: artifacts
RCLONE_FTP_PASS:
from_secret: RCLONE_FTP_PASS
GH_RELEASE_GITHUB_API_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
GITHUB_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
commands:
- ./utils/scripts/build/should-release/should-release
- rclone config create remote ftp env_auth true > /dev/null
- |
rclone copy remote: --include "eqemu-server*.zip" .
- gh-release --assets=eqemu-server-linux-x64.zip,eqemu-server-windows-x64.zip -y
- |
rclone delete remote: --include "eqemu-server*.zip"
depends_on:
- Build Windows
- Build Linux
+12
View File
@@ -56,3 +56,15 @@ bin/
/client_files/**/CMakeFiles/
.idea
# Clangd Generated Files.
compile_flags.txt
.cache/
# vscode generated settings
.vscode/
# Build pipeline
!utils/scripts/build/
!utils/scripts/build/should-release/should-release
!utils/scripts/build/should-release/should-release.exe
-16
View File
@@ -1,16 +0,0 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/include/mysql"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c11",
"cppStandard": "c++17"
}
],
"version": 4
}
-164
View File
@@ -1,164 +0,0 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "make",
"type": "shell",
"command": "cd bin && make",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "make clean",
"type": "shell",
"command": "cd bin && make clean",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "cmake",
"type": "shell",
"command": "mkdir -p bin && cd bin && rm CMakeCache.txt && cmake -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_LUA=ON -G 'Unix Makefiles' ..",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher":{
"owner": "cpp",
"fileLocation": "relative",
"pattern":[
{
"regexp": "([\\w+|\\\\]*\\.\\w+)\\((\\d+)\\)\\: (warning|error) (.*)$",
"file": 1,
"location": 2,
"severity": 3,
"message": 4
}
]
}
},
{
"label": "download maps",
"type": "shell",
"command": "mkdir -p bin && cd bin && wget https://codeload.github.com/Akkadius/EQEmuMaps/zip/master -O maps.zip && unzip -o maps.zip && rm ./maps -rf && mv EQEmuMaps-master maps && rm maps.zip",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "download quests",
"type": "shell",
"command": "mkdir -p bin && cd bin && cd server && git -C ./quests pull 2> /dev/null || git clone https://github.com/ProjectEQ/projecteqquests.git quests",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "download eqemu_config",
"type": "shell",
"command": "mkdir -p bin && cd bin && wget --no-check-certificate https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/eqemu_config_docker.json -O eqemu_config.json",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "rebuild database (mariadb must be started)",
"type": "shell",
"command": "mkdir -p bin && cd bin && docker run -i --rm --privileged -v ${HOST_PROJECT_PATH}/bin:/src --network=eqemu -it eqemu/server:0.0.3 bash -c './eqemu_server.pl source_peq_db && ./eqemu_server.pl check_db_updates && ./eqemu_server.pl linux_login_server_setup'",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "zone 7000",
"type": "shell",
"command": "docker stop zone7000 | true && docker network create eqemu | true && docker run -i --rm --name zone7000 --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --privileged -v ${HOST_PROJECT_PATH}/bin:/src --ulimit core=10000000 --network=eqemu -p 7000:7000/udp -e LD_LIBRARY_PATH=/src/ eqemu/server:0.0.3 gdb -ex run --args ./zone dynamic_zone7000:7000",
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "zone 7001",
"type": "shell",
"command": "docker stop zone7001 | true && docker network create eqemu | true && docker run -i --rm --name zone7001 --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --privileged -v ${HOST_PROJECT_PATH}/bin:/src --ulimit core=10000000 --network=eqemu -p 7001:7001/udp -e LD_LIBRARY_PATH=/src/ eqemu/server:0.0.3 gdb -ex run --args ./zone dynamic_zone7001:7001",
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "loginserver",
"type": "shell",
"command": "docker stop loginserver | true && docker network create eqemu | true && docker run -i --rm --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --privileged -v ${HOST_PROJECT_PATH}/bin:/src --ulimit core=10000000 --network=eqemu --name loginserver -p 5999:5999/udp -p 5998:5998/udp -e LD_LIBRARY_PATH=/src/ eqemu/server:0.0.3 gdb -ex run --args ./loginserver",
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "shared_memory, world",
"type": "shell",
"command": "docker stop sharedmemory | true && docker stop world | true && docker network create eqemu | true && docker run --rm -v ${HOST_PROJECT_PATH}/bin:/src --network=eqemu --name sharedmemory eqemu/server:0.0.3 ./shared_memory && docker run --rm -v ${HOST_PROJECT_PATH}/bin:/src --ulimit core=10000000 -e LD_LIBRARY_PATH=/src/ --network=eqemu --name world -p 9000:9000 -p 9000:9000/udp -p 9001:9001 -p 9080:9080 eqemu/server:0.0.3 gdb -ex run ./world",
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "queryserv",
"type": "shell",
"command": "docker stop queryserv | true && docker run --rm -v ${HOST_PROJECT_PATH}/bin:/src --ulimit core=10000000 -e LD_LIBRARY_PATH=/src/ --network=eqemu --name queryserv eqemu/server:0.0.3 gdb -ex run ./queryserv",
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "mariadb",
"type": "shell",
"command": "docker stop mariadb | true && cd bin && docker network create eqemu | true && docker run --rm -v ${HOST_PROJECT_PATH}/bin/db:/bitnami/mariadb -p 3306:3306 -e MARIADB_DATABASE=peq -e MARIADB_USER=eqemu -e MARIADB_PASSWORD=eqemupass -e ALLOW_EMPTY_PASSWORD=yes --name mariadb --network=eqemu bitnami/mariadb:latest",
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "ucs",
"type": "shell",
"command": "docker stop ucs | true && cd bin && docker network create eqemu | true && docker run --rm -v ${HOST_PROJECT_PATH}/bin:/src -p 7778:7778 --name ucs --network=eqemu eqemu/server:0.0.3 gdb -ex run ./ucs",
"group": {
"kind": "test",
"isDefault": true
}
}
]
}
+2 -2
View File
@@ -40,14 +40,14 @@ Assuming it is starting in c:/projects/eqemu and the x64 dependencies were extra
mkdir build
cd build
cmake -G "Visual Studio 15 2017 Win64" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_ZLIB=ON -DEQEMU_ENABLE_BOTS=ON -DCMAKE_TOOLCHAIN_FILE="c:/projects/eqemu/vcpkg/vcpkg-export-20180828-145455/scripts/buildsystems/vcpkg.cmake" ..
cmake -G "Visual Studio 15 2017 Win64" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_ZLIB=ON -DCMAKE_TOOLCHAIN_FILE="c:/projects/eqemu/vcpkg/vcpkg-export-20180828-145455/scripts/buildsystems/vcpkg.cmake" ..
##### Linux
Similarly to Windows running CMake on Linux is simple it just omits the toolchain file and uses a different generator.
mkdir build
cd build
cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LOGIN=ON ..
cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON ..
### Building
+47
View File
@@ -0,0 +1,47 @@
## [22.0.8]
### Release Test
Another release test (We're almost there!)
## [22.0.7]
### Release Test
Release test
## [22.0.6]
### Release Test
Release test with bots #2
## [22.0.5]
### Release Test
Release test with bots
## [22.0.4]
### Release Test
Release test with smaller Linux bins
## [22.0.3]
### Release Test
Testing Linux build in release
## [22.0.2]
### Release Without Bots
Testing release without bots
## [22.0.1]
### Stable Releases
- Testing stable releases
+6 -12
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.7)
CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH})
@@ -12,7 +12,7 @@ IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_CXX_STANDARD 17)
SET(CMAKE_CXX_STANDARD 20)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_EXTENSIONS OFF)
@@ -21,8 +21,9 @@ IF(MSVC)
ADD_DEFINITIONS(-DNOMINMAX)
ADD_DEFINITIONS(-DCRASH_LOGGING)
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")
ELSE(MSVC)
ADD_DEFINITIONS(-DHAS_UNION_SEMUN)
ENDIF(MSVC)
@@ -122,7 +123,6 @@ ENDIF()
MESSAGE(STATUS "**************************************************")
#options
OPTION(EQEMU_ENABLE_BOTS "Enable Bots" OFF)
OPTION(EQEMU_COMMANDS_LOGGING "Enable GM Command logs" ON)
OPTION(EQEMU_BUILD_SERVER "Build the game server." ON)
OPTION(EQEMU_BUILD_LOGIN "Build the login server." ON)
@@ -176,10 +176,6 @@ IF(EQEMU_COMMANDS_LOGGING)
ADD_DEFINITIONS(-DCOMMANDS_LOGGING)
ENDIF(EQEMU_COMMANDS_LOGGING)
IF(EQEMU_ENABLE_BOTS)
ADD_DEFINITIONS(-DBOTS)
ENDIF(EQEMU_ENABLE_BOTS)
#database
IF(MySQL_FOUND AND MariaDB_FOUND)
SET(DATABASE_LIBRARY_SELECTION MariaDB CACHE STRING "Database library to use:
@@ -340,10 +336,8 @@ INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigat
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Recast/Include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/websocketpp")
OPTION(EQEMU_BUILD_LOGGING "Build Logging (To speed up compilation)" ON)
IF(EQEMU_BUILD_LOGGING)
ADD_DEFINITIONS(-DBUILD_LOGGING)
ENDIF()
# silence obnoxious deprecation message
ADD_DEFINITIONS(-DBOOST_BIND_GLOBAL_PLACEHOLDERS)
IF(TLS_LIBRARY_ENABLED)
SET(SERVER_LIBS ${SERVER_LIBS} ${TLS_LIBRARY_LIBS})
+1 -1
View File
@@ -9,7 +9,7 @@ init:
- ps: git config --global core.autocrlf input
cache: c:\tools\vcpkg\installed\
before_build:
- ps: "$wc = New-Object System.Net.WebClient\n$wc.DownloadFile(\"http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip\", \"c:\\projects\\eqemu\\strawberry-perl-5.26.2.1-64bit-portable.zip\")\ncd c:\\projects\\eqemu\n7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y\n(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h\nvcpkg install boost-geometry:x64-windows boost-dynamic-bitset:x64-windows luajit:x64-windows libsodium:x64-windows libmysql:x64-windows openssl:x64-windows zlib:x64-windows \nmkdir build\ncd build\ncmake -G \"Visual Studio 15 2017 Win64\" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -EQEMU_ENABLE_BOTS=ON -DPERL_EXECUTABLE=\"C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe\" -DPERL_INCLUDE_PATH=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE\" -DPERL_LIBRARY=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a\" -DCMAKE_TOOLCHAIN_FILE=\"c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake\" .."
- ps: "$wc = New-Object System.Net.WebClient\n$wc.DownloadFile(\"http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip\", \"c:\\projects\\eqemu\\strawberry-perl-5.26.2.1-64bit-portable.zip\")\ncd c:\\projects\\eqemu\n7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y\n(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h\nvcpkg install boost-geometry:x64-windows boost-dynamic-bitset:x64-windows luajit:x64-windows libsodium:x64-windows libmysql:x64-windows openssl:x64-windows zlib:x64-windows \nmkdir build\ncd build\ncmake -G \"Visual Studio 15 2017 Win64\" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DPERL_EXECUTABLE=\"C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe\" -DPERL_INCLUDE_PATH=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE\" -DPERL_LIBRARY=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a\" -DCMAKE_TOOLCHAIN_FILE=\"c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake\" .."
build:
project: C:\projects\eqemu\build\EQEmu.sln
parallel: true
+1 -1
View File
@@ -9,7 +9,7 @@ init:
- ps: git config --global core.autocrlf input
cache: c:\tools\vcpkg\installed\
before_build:
- ps: "$wc = New-Object System.Net.WebClient\n$wc.DownloadFile(\"http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip\", \"c:\\projects\\eqemu\\strawberry-perl-5.26.2.1-64bit-portable.zip\")\ncd c:\\projects\\eqemu\n7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y\n(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h\nvcpkg install boost-geometry:x64-windows boost-dynamic-bitset:x64-windows luajit:x64-windows libsodium:x64-windows libmysql:x64-windows openssl:x64-windows zlib:x64-windows \nmkdir build\ncd build\ncmake -G \"Visual Studio 15 2017 Win64\" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -EQEMU_ENABLE_BOTS=OFF -DPERL_EXECUTABLE=\"C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe\" -DPERL_INCLUDE_PATH=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE\" -DPERL_LIBRARY=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a\" -DCMAKE_TOOLCHAIN_FILE=\"c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake\" .."
- ps: "$wc = New-Object System.Net.WebClient\n$wc.DownloadFile(\"http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip\", \"c:\\projects\\eqemu\\strawberry-perl-5.26.2.1-64bit-portable.zip\")\ncd c:\\projects\\eqemu\n7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y\n(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h\nvcpkg install boost-geometry:x64-windows boost-dynamic-bitset:x64-windows luajit:x64-windows libsodium:x64-windows libmysql:x64-windows openssl:x64-windows zlib:x64-windows \nmkdir build\ncd build\ncmake -G \"Visual Studio 15 2017 Win64\" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DPERL_EXECUTABLE=\"C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe\" -DPERL_INCLUDE_PATH=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE\" -DPERL_LIBRARY=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a\" -DCMAKE_TOOLCHAIN_FILE=\"c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake\" .."
build:
project: C:\projects\eqemu\build\EQEmu.sln
parallel: true
+1 -1
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
SET(export_sources
main.cpp
+13 -4
View File
@@ -28,10 +28,12 @@
#include "../../common/strings.h"
#include "../../common/content/world_content_service.h"
#include "../../common/zone_store.h"
#include "../../common/path_manager.h"
EQEmuLogSys LogSys;
WorldContentService content_service;
ZoneStore zone_store;
PathManager path;
void ExportSpells(SharedDatabase *db);
void ExportSkillCaps(SharedDatabase *db);
@@ -44,6 +46,8 @@ int main(int argc, char **argv)
LogSys.LoadLogSettingsDefaults();
set_exception_handler();
path.LoadPaths();
LogInfo("Client Files Export Utility");
if (!EQEmuConfig::LoadConfig()) {
LogError("Unable to load configuration file");
@@ -86,6 +90,7 @@ int main(int argc, char **argv)
}
LogSys.SetDatabase(&database)
->SetLogPath(path.GetLogPath())
->LoadLogDatabaseSettings()
->StartFileLogs();
@@ -126,7 +131,8 @@ void ExportSpells(SharedDatabase *db)
{
LogInfo("Exporting Spells");
FILE *f = fopen("export/spells_us.txt", "w");
std::string file = fmt::format("{}/export/spells_us.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "w");
if (!f) {
LogError("Unable to open export/spells_us.txt to write, skipping.");
return;
@@ -208,7 +214,8 @@ void ExportSkillCaps(SharedDatabase *db)
{
LogInfo("Exporting Skill Caps");
FILE *f = fopen("export/SkillCaps.txt", "w");
std::string file = fmt::format("{}/export/SkillCaps.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "w");
if (!f) {
LogError("Unable to open export/SkillCaps.txt to write, skipping.");
return;
@@ -238,7 +245,8 @@ void ExportBaseData(SharedDatabase *db)
{
LogInfo("Exporting Base Data");
FILE *f = fopen("export/BaseData.txt", "w");
std::string file = fmt::format("{}/export/BaseData.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "w");
if (!f) {
LogError("Unable to open export/BaseData.txt to write, skipping.");
return;
@@ -271,7 +279,8 @@ void ExportDBStrings(SharedDatabase *db)
{
LogInfo("Exporting DB Strings");
FILE *f = fopen("export/dbstr_us.txt", "w");
std::string file = fmt::format("{}/export/dbstr_us.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "w");
if (!f) {
LogError("Unable to open export/dbstr_us.txt to write, skipping.");
return;
+1 -1
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
SET(import_sources
main.cpp
+17 -8
View File
@@ -26,10 +26,12 @@
#include "../../common/strings.h"
#include "../../common/content/world_content_service.h"
#include "../../common/zone_store.h"
#include "../../common/path_manager.h"
EQEmuLogSys LogSys;
WorldContentService content_service;
ZoneStore zone_store;
PathManager path;
void ImportSpells(SharedDatabase *db);
void ImportSkillCaps(SharedDatabase *db);
@@ -41,6 +43,8 @@ int main(int argc, char **argv) {
LogSys.LoadLogSettingsDefaults();
set_exception_handler();
path.LoadPaths();
LogInfo("Client Files Import Utility");
if(!EQEmuConfig::LoadConfig()) {
LogError("Unable to load configuration file.");
@@ -83,6 +87,7 @@ int main(int argc, char **argv) {
}
LogSys.SetDatabase(&database)
->SetLogPath(path.GetLogPath())
->LoadLogDatabaseSettings()
->StartFileLogs();
@@ -127,9 +132,10 @@ bool IsStringField(int i) {
void ImportSpells(SharedDatabase *db) {
LogInfo("Importing Spells");
FILE *f = fopen("import/spells_us.txt", "r");
std::string file = fmt::format("{}/import/spells_us.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "r");
if(!f) {
LogError("Unable to open import/spells_us.txt to read, skipping.");
LogError("Unable to open {} to read, skipping.", file);
return;
}
@@ -216,9 +222,10 @@ void ImportSpells(SharedDatabase *db) {
void ImportSkillCaps(SharedDatabase *db) {
LogInfo("Importing Skill Caps");
FILE *f = fopen("import/SkillCaps.txt", "r");
std::string file = fmt::format("{}/import/SkillCaps.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "r");
if(!f) {
LogError("Unable to open import/SkillCaps.txt to read, skipping.");
LogError("Unable to open {} to read, skipping.", file);
return;
}
@@ -251,9 +258,10 @@ void ImportSkillCaps(SharedDatabase *db) {
void ImportBaseData(SharedDatabase *db) {
LogInfo("Importing Base Data");
FILE *f = fopen("import/BaseData.txt", "r");
std::string file = fmt::format("{}/import/BaseData.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "r");
if(!f) {
LogError("Unable to open import/BaseData.txt to read, skipping.");
LogError("Unable to open {} to read, skipping.", file);
return;
}
@@ -296,9 +304,10 @@ void ImportBaseData(SharedDatabase *db) {
void ImportDBStrings(SharedDatabase *db) {
LogInfo("Importing DB Strings");
FILE *f = fopen("import/dbstr_us.txt", "r");
std::string file = fmt::format("{}/import/dbstr_us.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "r");
if(!f) {
LogError("Unable to open import/dbstr_us.txt to read, skipping.");
LogError("Unable to open {} to read, skipping.", file);
return;
}
+13 -5
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
SET(common_sources
base_packet.cpp
@@ -37,7 +37,7 @@ SET(common_sources
extprofile.cpp
discord_manager.cpp
faction.cpp
file_util.cpp
file.cpp
guild_base.cpp
guilds.cpp
inventory_profile.cpp
@@ -61,8 +61,10 @@ SET(common_sources
packet_dump.cpp
packet_dump_file.cpp
packet_functions.cpp
path_manager.cpp
perl_eqdb.cpp
perl_eqdb_res.cpp
process/process.cpp
proc_launcher.cpp
profanity_manager.cpp
ptimer.cpp
@@ -180,6 +182,8 @@ SET(repositories
repositories/base/base_char_create_combinations_repository.h
repositories/base/base_char_create_point_allocations_repository.h
repositories/base/base_char_recipe_list_repository.h
repositories/base/base_chatchannels_repository.h
repositories/base/base_chatchannel_reserved_names_repository.h
repositories/base/base_completed_shared_tasks_repository.h
repositories/base/base_completed_shared_task_activity_state_repository.h
repositories/base/base_completed_shared_task_members_repository.h
@@ -207,7 +211,6 @@ SET(repositories
repositories/base/base_friends_repository.h
repositories/base/base_global_loot_repository.h
repositories/base/base_gm_ips_repository.h
repositories/base/base_goallists_repository.h
repositories/base/base_graveyard_repository.h
repositories/base/base_ground_spawns_repository.h
repositories/base/base_group_id_repository.h
@@ -357,6 +360,8 @@ SET(repositories
repositories/char_create_combinations_repository.h
repositories/char_create_point_allocations_repository.h
repositories/char_recipe_list_repository.h
repositories/chatchannels_repository.h
repositories/chatchannel_reserved_names_repository.h
repositories/completed_shared_tasks_repository.h
repositories/completed_shared_task_activity_state_repository.h
repositories/completed_shared_task_members_repository.h
@@ -384,7 +389,6 @@ SET(repositories
repositories/friends_repository.h
repositories/global_loot_repository.h
repositories/gm_ips_repository.h
repositories/goallists_repository.h
repositories/graveyard_repository.h
repositories/ground_spawns_repository.h
repositories/group_id_repository.h
@@ -531,7 +535,7 @@ SET(common_headers
expedition_lockout_timer.h
extprofile.h
faction.h
file_util.h
file.h
features.h
fixed_memory_hash_set.h
fixed_memory_variable_hash_set.h
@@ -567,7 +571,9 @@ SET(common_headers
packet_dump.h
packet_dump_file.h
packet_functions.h
path_manager.cpp
platform.h
process/process.h
proc_launcher.h
profanity_manager.h
profiler.h
@@ -650,6 +656,8 @@ SET(common_headers
patches/uf_limits.h
patches/uf_ops.h
patches/uf_structs.h
termcolor/rang.hpp
stacktrace/backward.hpp
StackWalker/StackWalker.h
util/memory_stream.h
util/directory.h
+1
View File
@@ -20,6 +20,7 @@
#include "../common/types.h"
#define NO_CLASS 0
#define WARRIOR 1
#define CLERIC 2
#define PALADIN 3
+10 -43
View File
@@ -1,48 +1,15 @@
#include "global_define.h"
#include "eqemu_logsys.h"
#include "crash.h"
#include "strings.h"
#include "process/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;
}
#include <cstdio>
std::string execute(const std::string &cmd, bool return_result = true)
{
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());
#if WINDOWS
#define popen _popen
#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;
}
#if defined(_WINDOWS) && defined(CRASH_LOGGING)
#include "StackWalker.h"
@@ -167,7 +134,7 @@ void set_exception_handler() {
void print_trace()
{
bool does_gdb_exist = execute("gdb -v").find("GNU") != std::string::npos;
bool does_gdb_exist = Strings::Contains(Process::execute("gdb -v"), "GNU");
if (!does_gdb_exist) {
LogCrash(
"[Error] GDB is not installed, if you want crash dumps on Linux to work properly you will need GDB installed"
@@ -176,12 +143,12 @@ void print_trace()
}
auto uid = geteuid();
std::string temp_output_file = "/tmp/dump-output";
std::string temp_output_file = fmt::format("/tmp/dump-output-{}", Strings::Random(10));
// check for passwordless sudo if not root
if (uid != 0) {
bool has_passwordless_sudo = execute("sudo -n true").find("a password is required") == std::string::npos;
if (!has_passwordless_sudo) {
bool sudo_password_required = Strings::Contains(Process::execute("sudo -n true"), "a password is required");
if (sudo_password_required) {
LogCrash(
"[Error] Current user does not have passwordless sudo installed. It is required to automatically process crash dumps with GDB as non-root."
);
@@ -210,7 +177,7 @@ void print_trace()
abort(); /* If gdb failed to start */
}
else {
waitpid(child_pid, NULL, 0);
waitpid(child_pid, nullptr, 0);
}
std::ifstream input(temp_output_file);
+39 -21
View File
@@ -71,11 +71,11 @@ bool Database::Connect(const char* host, const char* user, const char* passwd, c
uint32 errnum= 0;
char errbuf[MYSQL_ERRMSG_SIZE];
if (!Open(host, user, passwd, database, port, &errnum, errbuf)) {
LogError("[MySQL] Connection [{}] Failed to connect to database: Error [{}]", connection_label, errbuf);
LogError("Connection [{}] Failed to connect to database Error [{}]", connection_label, errbuf);
return false;
}
else {
LogInfo("[MySQL] Connection [{}] database [{}] at [{}]:[{}]", connection_label, database, host,port);
LogInfo("Connected to database [{}] [{}] @ [{}:{}]", connection_label, database, host,port);
return true;
}
}
@@ -376,9 +376,10 @@ bool Database::ReserveName(uint32 account_id, char* name) {
* @param character_name
* @return
*/
bool Database::DeleteCharacter(char *character_name) {
bool Database::DeleteCharacter(char *character_name)
{
uint32 character_id = 0;
if(!character_name || !strlen(character_name)) {
if (!character_name || !strlen(character_name)) {
LogInfo("DeleteCharacter: request to delete without a name (empty char slot)");
return false;
}
@@ -390,45 +391,60 @@ bool Database::DeleteCharacter(char *character_name) {
}
if (character_id <= 0) {
LogError("DeleteCharacter | Invalid Character ID [{}]", character_name);
LogError("Invalid Character ID [{}]", character_name);
return false;
}
std::string delete_type = "hard-deleted";
if (RuleB(Character, SoftDeletes)) {
delete_type = "soft-deleted";
std::string query = fmt::format(
delete_type = "soft-deleted";
query = fmt::format(
SQL(
UPDATE
character_data
character_data
SET
name = SUBSTRING(CONCAT(name, '-deleted-', UNIX_TIMESTAMP()), 1, 64),
name = SUBSTRING(CONCAT(name, '-deleted-', UNIX_TIMESTAMP()), 1, 64),
deleted_at = NOW()
WHERE
id = '{}'
WHERE
id = '{}'
),
character_id
);
QueryDatabase(query);
if (RuleB(Bots, Enabled)) {
query = fmt::format(
SQL(
UPDATE
bot_data
SET
name = SUBSTRING(CONCAT(name, '-deleted-', UNIX_TIMESTAMP()), 1, 64)
WHERE
owner_id = '{}'
),
character_id
);
QueryDatabase(query);
LogInfo(
"[DeleteCharacter] character_name [{}] ({}) bots are being [{}]",
character_name,
character_id,
delete_type
);
}
return true;
}
LogInfo("DeleteCharacter | Character [{}] ({}) is being [{}]", character_name, character_id, delete_type);
for (const auto& iter : DatabaseSchema::GetCharacterTables()) {
for (const auto &iter: DatabaseSchema::GetCharacterTables()) {
std::string table_name = iter.first;
std::string character_id_column_name = iter.second;
QueryDatabase(fmt::format("DELETE FROM {} WHERE {} = {}", table_name, character_id_column_name, character_id));
}
#ifdef BOTS
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", character_id); // note: only use of GetMobTypeById()
QueryDatabase(query);
#endif
LogInfo("character_name [{}] ({}) is being [{}]", character_name, character_id, delete_type);
return true;
}
@@ -959,6 +975,8 @@ bool Database::LoadVariables() {
varcache.Add(key, value);
}
LogInfo("Loaded [{}] variable(s)", Strings::Commify(std::to_string(results.RowCount())));
return true;
}
@@ -2338,7 +2356,7 @@ void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string ur
uri request_uri(url);
LogHTTP(
"[SourceDatabaseTableFromUrl] parsing url [{}] path [{}] host [{}] query_string [{}] protocol [{}] port [{}]",
"parsing url [{}] path [{}] host [{}] query_string [{}] protocol [{}] port [{}]",
url,
request_uri.get_path(),
request_uri.get_host(),
@@ -2392,7 +2410,7 @@ void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string ur
}
catch (std::invalid_argument iae) {
LogError("[SourceDatabaseTableFromUrl] URI parser error [{}]", iae.what());
LogError("URI parser error [{}]", iae.what());
}
}
+10 -11
View File
@@ -145,31 +145,30 @@ public:
/* Instancing */
bool AddClientToInstance(uint16 instance_id, uint32 char_id);
bool CharacterInInstanceGroup(uint16 instance_id, uint32 char_id);
bool AddClientToInstance(uint16 instance_id, uint32 character_id);
bool CheckInstanceByCharID(uint16 instance_id, uint32 character_id);
bool CheckInstanceExists(uint16 instance_id);
bool CheckInstanceExpired(uint16 instance_id);
bool CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration);
bool GetUnusedInstanceID(uint16 &instance_id);
bool GlobalInstance(uint16 instance_id);
bool IsGlobalInstance(uint16 instance_id);
bool RemoveClientFromInstance(uint16 instance_id, uint32 char_id);
bool RemoveClientsFromInstance(uint16 instance_id);
bool VerifyInstanceAlive(uint16 instance_id, uint32 char_id);
bool VerifyInstanceAlive(uint16 instance_id, uint32 character_id);
bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id);
uint16 GetInstanceID(uint32 zone, uint32 charid, int16 version);
uint16 GetInstanceVersion(uint16 instance_id);
std::vector<uint16> GetInstanceIDs(uint32 zone_id, uint32 character_id);
uint8_t GetInstanceVersion(uint16 instance_id);
uint32 GetTimeRemainingInstance(uint16 instance_id, bool &is_perma);
uint32 VersionFromInstanceID(uint16 instance_id);
uint32 ZoneIDFromInstanceID(uint16 instance_id);
uint32 GetInstanceZoneID(uint16 instance_id);
void AssignGroupToInstance(uint32 gid, uint32 instance_id);
void AssignRaidToInstance(uint32 rid, uint32 instance_id);
void BuryCorpsesInInstance(uint16 instance_id);
void DeleteInstance(uint16 instance_id);
void FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid);
void FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid);
void GetCharactersInInstance(uint16 instance_id, std::list<uint32> &charid_list);
void FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 charid, uint32 group_id);
void FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 charid, uint32 raid_id);
void GetCharactersInInstance(uint16 instance_id, std::list<uint32> &character_ids);
void PurgeExpiredInstances();
void SetInstanceDuration(uint16 instance_id, uint32 new_duration);
+47 -119
View File
@@ -26,7 +26,8 @@
#include "../strings.h"
#include "../eqemu_config.h"
#include "../database_schema.h"
#include "../file_util.h"
#include "../file.h"
#include "../process/process.h"
#include <ctime>
@@ -40,38 +41,6 @@
#define DATABASE_DUMP_PATH "backups/"
/**
* @param cmd
* @param return_result
* @return
*/
std::string DatabaseDumpService::execute(const std::string &cmd, bool return_result = true)
{
const char *file_name = "db-exec-result.txt";
if (return_result) {
#ifdef _WINDOWS
std::system((cmd + " > " + file_name + " 2>&1").c_str());
#else
std::system((cmd + " > " + file_name).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;
}
/**
* @return bool
*/
@@ -88,7 +57,7 @@ bool DatabaseDumpService::IsMySQLInstalled()
*/
bool DatabaseDumpService::IsTarAvailable()
{
std::string version_output = execute("tar --version");
std::string version_output = Process::execute("tar --version");
return version_output.find("GNU tar") != std::string::npos;
}
@@ -99,7 +68,7 @@ bool DatabaseDumpService::IsTarAvailable()
*/
bool DatabaseDumpService::Is7ZipAvailable()
{
std::string version_output = execute("7z --help");
std::string version_output = Process::execute("7z --help");
return version_output.find("7-Zip") != std::string::npos;
}
@@ -117,7 +86,7 @@ bool DatabaseDumpService::HasCompressionBinary()
*/
std::string DatabaseDumpService::GetMySQLVersion()
{
std::string version_output = execute("mysql --version");
std::string version_output = Process::execute("mysql --version");
return Strings::Trim(version_output);
}
@@ -149,109 +118,53 @@ std::string DatabaseDumpService::GetBaseMySQLDumpCommand()
);
}
/**
* @return
*/
std::string DatabaseDumpService::GetPlayerTablesList()
{
std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetPlayerTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return Strings::Trim(tables_list);
return Strings::Join(DatabaseSchema::GetPlayerTables(), " ");
}
/**
* @return
*/
std::string DatabaseDumpService::GetBotTablesList()
{
std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetBotTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return Strings::Trim(tables_list);
return Strings::Join(DatabaseSchema::GetBotTables(), " ");
}
std::string DatabaseDumpService::GetMercTablesList()
{
return Strings::Join(DatabaseSchema::GetMercTables(), " ");
}
/**
* @return
*/
std::string DatabaseDumpService::GetLoginTableList()
{
std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetLoginTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return Strings::Trim(tables_list);
return Strings::Join(DatabaseSchema::GetLoginTables(), " ");
}
/**
* @return
*/
std::string DatabaseDumpService::GetQueryServTables()
{
std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetQueryServerTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return Strings::Trim(tables_list);
return Strings::Join(DatabaseSchema::GetQueryServerTables(), " ");
}
/**
* @return
*/
std::string DatabaseDumpService::GetSystemTablesList()
{
std::string tables_list;
auto system_tables = DatabaseSchema::GetServerTables();
auto version_tables = DatabaseSchema::GetVersionTables();
std::vector<std::string> tables = DatabaseSchema::GetServerTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
system_tables.insert(
std::end(system_tables),
std::begin(version_tables),
std::end(version_tables)
);
tables = DatabaseSchema::GetVersionTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return Strings::Trim(tables_list);
return Strings::Join(system_tables, " ");
}
/**
* @return
*/
std::string DatabaseDumpService::GetStateTablesList()
{
std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetStateTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return Strings::Trim(tables_list);
return Strings::Join(DatabaseSchema::GetStateTables(), " ");
}
/**
* @return
*/
std::string DatabaseDumpService::GetContentTablesList()
{
std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetContentTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return Strings::Trim(tables_list);
return Strings::Join(DatabaseSchema::GetContentTables(), " ");
}
/**
@@ -337,6 +250,11 @@ void DatabaseDumpService::Dump()
dump_descriptor += "-bots";
}
if (IsDumpMercTables()) {
tables_to_dump += GetMercTablesList() + " ";
dump_descriptor += "-mercs";
}
if (IsDumpSystemTables()) {
tables_to_dump += GetSystemTablesList() + " ";
dump_descriptor += "-system";
@@ -383,8 +301,8 @@ void DatabaseDumpService::Dump()
pipe_file
);
if (!FileUtil::exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) {
FileUtil::mkdir(GetSetDumpPath());
if (!File::Exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) {
File::Makedir(GetSetDumpPath());
}
if (IsDumpDropTableSyntaxOnly()) {
@@ -399,14 +317,14 @@ void DatabaseDumpService::Dump()
}
}
else {
std::string execution_result = execute(execute_command, IsDumpOutputToConsole());
if (!execution_result.empty()) {
std::string execution_result = Process::execute(execute_command);
if (!execution_result.empty() && IsDumpOutputToConsole()) {
std::cout << execution_result;
}
}
if (!tables_to_dump.empty()) {
LogInfo("Dumping Tables [{}]", tables_to_dump);
LogInfo("Dumping Tables [{}]", Strings::Trim(tables_to_dump));
}
LogInfo("Database dump created at [{}.sql]", GetDumpFileNameWithPath());
@@ -416,7 +334,7 @@ void DatabaseDumpService::Dump()
LogInfo("Compression requested... Compressing dump [{}.sql]", GetDumpFileNameWithPath());
if (IsTarAvailable()) {
execute(
Process::execute(
fmt::format(
"tar -zcvf {}.tar.gz -C {} {}.sql",
GetDumpFileNameWithPath(),
@@ -427,7 +345,7 @@ void DatabaseDumpService::Dump()
LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath());
}
else if (Is7ZipAvailable()) {
execute(
Process::execute(
fmt::format(
"7z a -t7z {}.zip {}.sql",
GetDumpFileNameWithPath(),
@@ -607,3 +525,13 @@ void DatabaseDumpService::SetDumpBotTables(bool dump_bot_tables)
{
DatabaseDumpService::dump_bot_tables = dump_bot_tables;
}
bool DatabaseDumpService::IsDumpMercTables() const
{
return dump_merc_tables;
}
void DatabaseDumpService::SetDumpMercTables(bool dump_merc_tables)
{
DatabaseDumpService::dump_merc_tables = dump_merc_tables;
}
+4 -1
View File
@@ -55,6 +55,8 @@ public:
void SetDumpStateTables(bool dump_state_tables);
bool IsDumpBotTables() const;
void SetDumpBotTables(bool dump_bot_tables);
bool IsDumpMercTables() const;
void SetDumpMercTables(bool dump_bot_tables);
private:
bool dump_all_tables = false;
@@ -70,15 +72,16 @@ private:
bool dump_output_to_console = false;
bool dump_drop_table_syntax_only = false;
bool dump_bot_tables = false;
bool dump_merc_tables = false;
std::string dump_path;
std::string dump_file_name;
std::string execute(const std::string &cmd, bool return_result);
bool IsMySQLInstalled();
std::string GetMySQLVersion();
std::string GetBaseMySQLDumpCommand();
std::string GetPlayerTablesList();
std::string GetBotTablesList();
std::string GetMercTablesList();
std::string GetSystemTablesList();
std::string GetStateTablesList();
std::string GetContentTablesList();
+10 -1
View File
@@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "database.h"
#include "extprofile.h"
#include "path_manager.h"
#include <iomanip>
#include <iostream>
@@ -475,8 +476,16 @@ bool Database::CheckDatabaseConversions() {
CheckDatabaseConvertPPDeblob();
CheckDatabaseConvertCorpseDeblob();
RuleManager::Instance()->LoadRules(this, "default", false);
if (!RuleB(Bots, Enabled) && DoesTableExist("bot_data")) {
LogInfo("Bot tables found but rule not enabled, enabling");
RuleManager::Instance()->SetRule("Bots:Enabled", "true", this, true, true);
}
/* Run EQEmu Server script (Checks for database updates) */
system("perl eqemu_server.pl ran_from_world");
const std::string file = fmt::format("{}/eqemu_server.pl", path.GetServerPath());
system(fmt::format("perl {} ran_from_world", file).c_str());
return true;
}
+228 -289
View File
@@ -20,8 +20,16 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/rulesys.h"
#include "../common/strings.h"
#include "../common/timer.h"
#include "../common/repositories/character_corpses_repository.h"
#include "../common/repositories/dynamic_zone_members_repository.h"
#include "../common/repositories/dynamic_zones_repository.h"
#include "../common/repositories/group_id_repository.h"
#include "../common/repositories/instance_list_repository.h"
#include "../common/repositories/instance_list_player_repository.h"
#include "../common/repositories/raid_members_repository.h"
#include "../common/repositories/respawn_times_repository.h"
#include "../common/repositories/spawn_condition_values_repository.h"
#include "database.h"
@@ -41,115 +49,83 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include <sys/time.h>
#endif
/**
* @param instance_id
* @param char_id
* @return
*/
bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id)
bool Database::AddClientToInstance(uint16 instance_id, uint32 character_id)
{
std::string query = StringFormat(
"REPLACE INTO `instance_list_player` (id, charid) "
"VALUES "
"(%lu, %lu)",
(unsigned long) instance_id,
(unsigned long) char_id
);
auto e = InstanceListPlayerRepository::NewEntity();
auto results = QueryDatabase(query);
e.id = instance_id;
e.charid = character_id;
return results.Success();
return InstanceListPlayerRepository::ReplaceOne(*this, e);
}
bool Database::CharacterInInstanceGroup(uint16 instance_id, uint32 char_id)
bool Database::CheckInstanceByCharID(uint16 instance_id, uint32 character_id)
{
std::string query = StringFormat("SELECT charid FROM instance_list_player where id=%u AND charid=%u", instance_id, char_id);
auto results = QueryDatabase(query);
if (!results.Success())
if (!instance_id) {
return false;
}
if (results.RowCount() != 1)
auto l = InstanceListPlayerRepository::GetWhere(
*this,
fmt::format(
"id = {} AND charid = {}",
instance_id,
character_id
)
);
if (l.empty()) {
return false;
}
return true;
}
bool Database::CheckInstanceExists(uint16 instance_id) {
std::string query = StringFormat(
"SELECT "
"`id` "
"FROM "
"`instance_list` "
"WHERE "
"`id` = %u",
instance_id
);
auto results = QueryDatabase(query);
if (!results.Success())
bool Database::CheckInstanceExists(uint16 instance_id)
{
if (!instance_id) {
return false;
}
if (results.RowCount() == 0)
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
return false;
}
return true;
}
bool Database::CheckInstanceExpired(uint16 instance_id)
{
int32 start_time = 0;
int32 duration = 0;
uint32 never_expires = 0;
std::string query = StringFormat(
"SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u",
instance_id
);
auto results = QueryDatabase(query);
if (!results.Success()) {
if (!instance_id) {
return true;
}
if (results.RowCount() == 0) {
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
return true;
}
auto row = results.begin();
start_time = atoi(row[0]);
duration = atoi(row[1]);
never_expires = atoi(row[2]);
if (never_expires == 1) {
if (i.never_expires) {
return false;
}
timeval tv{};
gettimeofday(&tv, nullptr);
return (start_time + duration) <= tv.tv_sec;
return (i.start_time + i.duration) <= tv.tv_sec;
}
bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration)
{
std::string query = StringFormat(
"INSERT INTO instance_list (id, zone, version, start_time, duration)"
" values (%u, %u, %u, UNIX_TIMESTAMP(), %u)",
instance_id,
zone_id,
version,
duration
);
auto e = InstanceListRepository::NewEntity();
auto results = QueryDatabase(query);
e.id = instance_id;
e.zone = zone_id;
e.version = version;
e.start_time = std::time(nullptr);
e.duration = duration;
return results.Success();
return InstanceListRepository::InsertOne(*this, e).id;
}
bool Database::GetUnusedInstanceID(uint16 &instance_id)
@@ -157,8 +133,8 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id)
uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances);
uint32 max = 32000;
std::string query = StringFormat(
"SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u",
auto query = fmt::format(
"SELECT IFNULL(MAX(id), {}) + 1 FROM instance_list WHERE id > {}",
max_reserved_instance_id,
max_reserved_instance_id
);
@@ -202,7 +178,7 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id)
return true;
}
query = StringFormat("SELECT id FROM instance_list where id > %u ORDER BY id", max_reserved_instance_id);
query = fmt::format("SELECT id FROM instance_list where id > {} ORDER BY id", max_reserved_instance_id);
results = QueryDatabase(query);
if (!results.Success()) {
@@ -216,8 +192,9 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id)
}
max_reserved_instance_id++;
for (auto row = results.begin(); row != results.end(); ++row) {
if (max_reserved_instance_id < atoi(row[0])) {
for (auto row : results) {
if (max_reserved_instance_id < std::stoul(row[0])) {
instance_id = max_reserved_instance_id;
return true;
}
@@ -235,57 +212,45 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id)
return true;
}
bool Database::GlobalInstance(uint16 instance_id)
bool Database::IsGlobalInstance(uint16 instance_id)
{
std::string query = StringFormat(
"SELECT "
"is_global "
"FROM "
"instance_list "
"WHERE "
"id = %u "
"LIMIT 1 ",
instance_id
);
auto results = QueryDatabase(query);
if (!results.Success())
if (!instance_id) {
return false;
}
if (results.RowCount() == 0)
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
return false;
}
auto row = results.begin();
return (atoi(row[0]) == 1) ? true : false;
return i.is_global;
}
bool Database::RemoveClientFromInstance(uint16 instance_id, uint32 char_id)
{
std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu AND charid=%lu",
(unsigned long)instance_id, (unsigned long)char_id);
auto results = QueryDatabase(query);
return results.Success();
return InstanceListPlayerRepository::DeleteWhere(
*this,
fmt::format(
"id = {} AND charid = {}",
instance_id,
char_id
)
);
}
bool Database::RemoveClientsFromInstance(uint16 instance_id)
{
std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu", (unsigned long)instance_id);
auto results = QueryDatabase(query);
return results.Success();
return InstanceListPlayerRepository::DeleteOne(*this, instance_id);
}
bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 char_id)
bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 character_id)
{
//we are not saved to this instance so set our instance to 0
if (!GlobalInstance(instance_id) && !CharacterInInstanceGroup(instance_id, char_id))
if (!IsGlobalInstance(instance_id) && !CheckInstanceByCharID(instance_id, character_id)) {
return false;
}
if (CheckInstanceExpired(instance_id))
{
if (CheckInstanceExpired(instance_id)) {
DeleteInstance(instance_id);
return false;
}
@@ -295,99 +260,102 @@ bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 char_id)
bool Database::VerifyZoneInstance(uint32 zone_id, uint16 instance_id)
{
std::string query = StringFormat("SELECT id FROM instance_list where id=%u AND zone=%u", instance_id, zone_id);
auto results = QueryDatabase(query);
if (!results.Success())
return false;
if (results.RowCount() == 0)
auto l = InstanceListRepository::GetWhere(
*this,
fmt::format(
"id = {} AND zone = {}",
instance_id,
zone_id
)
);
if (l.empty()) {
return false;
}
return true;
}
uint16 Database::GetInstanceID(uint32 zone, uint32 character_id, int16 version)
uint16 Database::GetInstanceID(uint32 zone_id, uint32 character_id, int16 version)
{
if (!zone)
if (!zone_id) {
return 0;
}
std::string query = StringFormat(
"SELECT "
"instance_list.id "
"FROM "
"instance_list, "
"instance_list_player "
"WHERE "
"instance_list.zone = %u "
"AND instance_list.version = %u "
"AND instance_list.id = instance_list_player.id "
"AND instance_list_player.charid = %u "
"LIMIT 1; ",
zone,
const auto query = fmt::format(
"SELECT instance_list.id FROM "
"instance_list, instance_list_player WHERE "
"instance_list.zone = {} AND "
"instance_list.version = {} AND "
"instance_list.id = instance_list_player.id AND "
"instance_list_player.charid = {} "
"LIMIT 1;",
zone_id,
version,
character_id
);
);
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if (results.RowCount() == 0)
if (!results.Success() || !results.RowCount()) {
return 0;
}
auto row = results.begin();
return atoi(row[0]);
return static_cast<uint16>(std::stoul(row[0]));
}
uint16 Database::GetInstanceVersion(uint16 instance_id) {
if (instance_id == 0)
return 0;
std::vector<uint16> Database::GetInstanceIDs(uint32 zone_id, uint32 character_id)
{
std::vector<uint16> l;
std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id);
if (!zone_id) {
return l;
}
const auto query = fmt::format(
"SELECT instance_list.id FROM "
"instance_list, instance_list_player WHERE "
"instance_list.zone = {} AND "
"instance_list.id = instance_list_player.id AND "
"instance_list_player.charid = {}",
zone_id,
character_id
);
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if (!results.Success() || !results.RowCount()) {
return l;
}
if (results.RowCount() == 0)
return 0;
for (auto row : results) {
l.push_back(static_cast<uint16>(std::stoul(row[0])));
}
auto row = results.begin();
return atoi(row[0]);
return l;
}
uint8_t Database::GetInstanceVersion(uint16 instance_id) {
if (!instance_id) {
return 0;
}
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
return 0;
}
return i.version;
}
uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma)
{
uint32 start_time = 0;
uint32 duration = 0;
uint32 never_expires = 0;
std::string query = StringFormat("SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id);
auto results = QueryDatabase(query);
if (!results.Success())
{
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
is_perma = false;
return 0;
}
if (results.RowCount() == 0)
{
is_perma = false;
return 0;
}
auto row = results.begin();
start_time = atoi(row[0]);
duration = atoi(row[1]);
never_expires = atoi(row[2]);
if (never_expires == 1)
{
if (i.never_expires) {
is_perma = true;
return 0;
}
@@ -396,204 +364,175 @@ uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma)
timeval tv;
gettimeofday(&tv, nullptr);
return ((start_time + duration) - tv.tv_sec);
return ((i.start_time + i.duration) - tv.tv_sec);
}
uint32 Database::VersionFromInstanceID(uint16 instance_id)
uint32 Database::GetInstanceZoneID(uint16 instance_id)
{
std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id);
auto results = QueryDatabase(query);
if (!results.Success())
if (!instance_id) {
return 0;
}
if (results.RowCount() == 0)
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
return 0;
}
auto row = results.begin();
return atoi(row[0]);
}
uint32 Database::ZoneIDFromInstanceID(uint16 instance_id)
{
std::string query = StringFormat("SELECT zone FROM instance_list where id=%u", instance_id);
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
return i.zone;
}
void Database::AssignGroupToInstance(uint32 group_id, uint32 instance_id)
{
auto zone_id = GetInstanceZoneID(instance_id);
auto version = GetInstanceVersion(instance_id);
uint32 zone_id = ZoneIDFromInstanceID(instance_id);
uint16 version = VersionFromInstanceID(instance_id);
std::string query = StringFormat("SELECT `charid` FROM `group_id` WHERE `groupid` = %u", group_id);
auto results = QueryDatabase(query);
if (!results.Success())
auto l = GroupIdRepository::GetWhere(
*this,
fmt::format(
"groupid = {}",
group_id
)
);
if (l.empty()) {
return;
}
for (auto row = results.begin(); row != results.end(); ++row)
{
uint32 charid = atoi(row[0]);
if (GetInstanceID(zone_id, charid, version) == 0)
AddClientToInstance(instance_id, charid);
for (const auto& e : l) {
if (!GetInstanceID(zone_id, e.charid, version)) {
AddClientToInstance(instance_id, e.charid);
}
}
}
void Database::AssignRaidToInstance(uint32 raid_id, uint32 instance_id)
{
auto zone_id = GetInstanceZoneID(instance_id);
auto version = GetInstanceVersion(instance_id);
uint32 zone_id = ZoneIDFromInstanceID(instance_id);
uint16 version = VersionFromInstanceID(instance_id);
std::string query = StringFormat("SELECT `charid` FROM `raid_members` WHERE `raidid` = %u", raid_id);
auto results = QueryDatabase(query);
if (!results.Success())
return;
for (auto row = results.begin(); row != results.end(); ++row)
{
uint32 charid = atoi(row[0]);
if (GetInstanceID(zone_id, charid, version) == 0)
AddClientToInstance(instance_id, charid);
}
}
void Database::BuryCorpsesInInstance(uint16 instance_id) {
QueryDatabase(
auto l = GroupIdRepository::GetWhere(
*this,
fmt::format(
"UPDATE character_corpses SET is_buried = 1, instance_id = 0 WHERE instance_id = {}",
instance_id
"raidid = {}",
raid_id
)
);
if (l.empty()) {
return;
}
for (const auto& e : l) {
if (!GetInstanceID(zone_id, e.charid, version)) {
AddClientToInstance(instance_id, e.charid);
}
}
}
void Database::DeleteInstance(uint16 instance_id)
{
std::string query;
query = StringFormat("DELETE FROM instance_list_player WHERE id=%u", instance_id);
QueryDatabase(query);
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id = {}", instance_id));
query = StringFormat("DELETE FROM respawn_times WHERE instance_id=%u", instance_id);
QueryDatabase(query);
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
query = StringFormat("DELETE FROM spawn_condition_values WHERE instance_id=%u", instance_id);
QueryDatabase(query);
SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
DynamicZoneMembersRepository::DeleteByInstance(*this, instance_id);
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
BuryCorpsesInInstance(instance_id);
CharacterCorpsesRepository::BuryInstance(*this, instance_id);
}
void Database::FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid)
void Database::FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 group_id)
{
uint16 id = GetInstanceID(zone, charid, version);
if (id != 0)
auto instance_id = GetInstanceID(zone_id, character_id, version);
if (instance_id) {
return;
}
char ln[128];
memset(ln, 0, 128);
GetGroupLeadershipInfo(gid, ln);
uint32 l_charid = GetCharacterID((const char*)ln);
uint16 l_id = GetInstanceID(zone, l_charid, version);
GetGroupLeadershipInfo(group_id, ln);
if (l_id == 0)
auto group_leader_id = GetCharacterID((const char*)ln);
auto group_leader_instance_id = GetInstanceID(zone_id, group_leader_id, version);
if (!group_leader_instance_id) {
return;
}
AddClientToInstance(l_id, charid);
AddClientToInstance(group_leader_instance_id, character_id);
}
void Database::FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid)
void Database::FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 raid_id)
{
uint16 id = GetInstanceID(zone, charid, version);
if (id != 0)
uint16 instance_id = GetInstanceID(zone_id, character_id, version);
if (instance_id) {
return;
}
uint32 l_charid = GetCharacterID(GetRaidLeaderName(rid));
uint16 l_id = GetInstanceID(zone, l_charid, version);
auto raid_leader_id = GetCharacterID(GetRaidLeaderName(raid_id));
auto raid_leader_instance_id = GetInstanceID(zone_id, raid_leader_id, version);
if (l_id == 0)
if (!raid_leader_instance_id) {
return;
}
AddClientToInstance(l_id, charid);
AddClientToInstance(raid_leader_instance_id, character_id);
}
void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &charid_list) {
std::string query = StringFormat("SELECT `charid` FROM `instance_list_player` WHERE `id` = %u", instance_id);
auto results = QueryDatabase(query);
if (!results.Success())
void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &character_ids)
{
auto l = InstanceListPlayerRepository::GetWhere(*this, fmt::format("id = {}", instance_id));
if (l.empty()) {
return;
}
for (auto row = results.begin(); row != results.end(); ++row)
charid_list.push_back(atoi(row[0]));
for (const auto& e : l) {
character_ids.push_back(e.charid);
}
}
void Database::PurgeExpiredInstances()
{
/**
* Delay purging by a day so that we can continue using adjacent free instance id's
* from the table without risking the chance we immediately re-allocate a zone that freshly expired but
* has not been fully de-allocated
*/
std::string query =
SQL(
SELECT
id
FROM
instance_list
where
(start_time + duration) <= (UNIX_TIMESTAMP() - 86400)
and never_expires = 0
);
auto results = QueryDatabase(query);
if (!results.Success()) {
return;
}
if (results.RowCount() == 0) {
auto l = InstanceListRepository::GetWhere(
*this,
"(start_time + duration) <= (UNIX_TIMESTAMP() - 86400) AND never_expires = 0"
);
if (l.empty()) {
return;
}
std::vector<std::string> instance_ids;
for (auto row = results.begin(); row != results.end(); ++row) {
instance_ids.emplace_back(row[0]);
for (const auto& e : l) {
instance_ids.emplace_back(std::to_string(e.id));
}
std::string imploded_instance_ids = Strings::Implode(",", instance_ids);
const auto imploded_instance_ids = Strings::Implode(",", instance_ids);
QueryDatabase(fmt::format("DELETE FROM instance_list WHERE id IN ({})", imploded_instance_ids));
QueryDatabase(fmt::format("DELETE FROM instance_list_player WHERE id IN ({})", imploded_instance_ids));
QueryDatabase(fmt::format("DELETE FROM respawn_times WHERE instance_id IN ({})", imploded_instance_ids));
QueryDatabase(fmt::format("DELETE FROM spawn_condition_values WHERE instance_id IN ({})", imploded_instance_ids));
QueryDatabase(fmt::format("UPDATE character_corpses SET is_buried = 1, instance_id = 0 WHERE instance_id IN ({})", imploded_instance_ids));
InstanceListRepository::DeleteWhere(*this, fmt::format("id IN ({})", imploded_instance_ids));
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id IN ({})", imploded_instance_ids));
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
CharacterCorpsesRepository::BuryInstances(*this, imploded_instance_ids);
DynamicZoneMembersRepository::DeleteByManyInstances(*this, imploded_instance_ids);
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
}
void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
{
std::string query = StringFormat("UPDATE `instance_list` SET start_time=UNIX_TIMESTAMP(), "
"duration=%u WHERE id=%u", new_duration, instance_id);
auto results = QueryDatabase(query);
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
return;
}
i.start_time = std::time(nullptr);
i.duration = new_duration;
InstanceListRepository::UpdateOne(*this, i);
}
+25 -4
View File
@@ -197,7 +197,6 @@ namespace DatabaseSchema {
"fishing",
"forage",
"global_loot",
"goallists",
"graveyard",
"grid",
"grid_entries",
@@ -333,7 +332,9 @@ namespace DatabaseSchema {
"ip_exemptions",
"item_tick",
"lfguild",
"merc_buffs",
"merchantlist_temp",
"mercs",
"object_contents",
"raid_details",
"raid_leaders",
@@ -404,11 +405,31 @@ namespace DatabaseSchema {
"bot_pet_inventories",
"bot_pets",
"bot_spell_casting_chances",
"bot_spell_settings",
"bot_spells_entries",
"bot_stances",
"bot_timers",
"vw_bot_character_mobs",
"vw_bot_groups"
"bot_timers"
};
}
static std::vector<std::string> GetMercTables()
{
return {
"merc_armorinfo",
"merc_inventory",
"merc_merchant_entries",
"merc_merchant_template_entries",
"merc_merchant_templates",
"merc_name_types",
"merc_npc_types",
"merc_spell_list_entries",
"merc_spell_lists",
"merc_stance_entries",
"merc_stats",
"merc_subtypes",
"merc_templates",
"merc_types",
"merc_weaponinfo"
};
}
+2 -2
View File
@@ -167,7 +167,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) {
if ((strncasecmp(query, "select", 6) == 0)) {
LogMySQLQuery(
"{0}; -- ({1} row{2} returned) ({3}s)",
"{0} -- ({1} row{2} returned) ({3}s)",
query,
requestResult.RowCount(),
requestResult.RowCount() == 1 ? "" : "s",
@@ -176,7 +176,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
}
else {
LogMySQLQuery(
"{0}; -- ({1} row{2} affected) ({3}s)",
"{0} -- ({1} row{2} affected) ({3}s)",
query,
requestResult.RowsAffected(),
requestResult.RowsAffected() == 1 ? "" : "s",
+1 -1
View File
@@ -48,7 +48,7 @@ void Discord::SendWebhookMessage(const std::string &message, const std::string &
while (retry) {
if (auto res = cli.Post(endpoint.c_str(), payload.str(), "application/json")) {
if (res->status != 200 && res->status != 204) {
LogError("[Discord Client] Code [{}] Error [{}]", res->status, res->body);
LogError("Code [{}] Error [{}]", res->status, res->body);
}
if (res->status == 429) {
if (!res->body.empty()) {
+66
View File
@@ -513,3 +513,69 @@ std::string EQ::constants::GetObjectTypeName(int object_type)
return std::string();
}
const std::map<uint8, std::string> &EQ::constants::GetWeatherTypeMap()
{
static const std::map<uint8, std::string> weather_type_map = {
{WeatherTypes::None, "None"},
{WeatherTypes::Raining, "Raining"},
{WeatherTypes::Snowing, "Snowing"}
};
return weather_type_map;
}
std::string EQ::constants::GetWeatherTypeName(uint8 weather_type)
{
if (EQ::ValueWithin(weather_type, WeatherTypes::None, WeatherTypes::Snowing)) {
return EQ::constants::GetWeatherTypeMap().find(weather_type)->second;
}
return std::string();
}
const std::map<uint8, std::string> &EQ::constants::GetEmoteEventTypeMap()
{
static const std::map<uint8, std::string> emote_event_type_map = {
{ EmoteEventTypes::LeaveCombat, "Leave Combat" },
{ EmoteEventTypes::EnterCombat, "Enter Combat" },
{ EmoteEventTypes::OnDeath, "On Death" },
{ EmoteEventTypes::AfterDeath, "After Death" },
{ EmoteEventTypes::Hailed, "Hailed" },
{ EmoteEventTypes::KilledPC, "Killed PC" },
{ EmoteEventTypes::KilledNPC, "Killed NPC" },
{ EmoteEventTypes::OnSpawn, "On Spawn" },
{ EmoteEventTypes::OnDespawn, "On Despawn" }
};
return emote_event_type_map;
}
std::string EQ::constants::GetEmoteEventTypeName(uint8 emote_event_type)
{
if (EQ::ValueWithin(emote_event_type, EmoteEventTypes::LeaveCombat, EmoteEventTypes::OnDespawn)) {
return EQ::constants::GetEmoteEventTypeMap().find(emote_event_type)->second;
}
return std::string();
}
const std::map<uint8, std::string> &EQ::constants::GetEmoteTypeMap()
{
static const std::map<uint8, std::string> emote_type_map = {
{ EmoteTypes::Emote, "Emote" },
{ EmoteTypes::Shout, "Shout" },
{ EmoteTypes::Proximity, "Proximity" }
};
return emote_type_map;
}
std::string EQ::constants::GetEmoteTypeName(uint8 emote_type)
{
if (EQ::ValueWithin(emote_type, EmoteTypes::Emote, EmoteTypes::Proximity)) {
return EQ::constants::GetEmoteTypeMap().find(emote_type)->second;
}
return std::string();
}
+66 -1
View File
@@ -217,6 +217,25 @@ namespace EQ
stanceBurnAE
};
enum BotSpellIDs : int {
Warrior = 3001,
Cleric,
Paladin,
Ranger,
Shadowknight,
Druid,
Monk,
Bard,
Rogue,
Shaman,
Necromancer,
Wizard,
Magician,
Enchanter,
Beastlord,
Berserker
};
enum GravityBehavior : int8 {
Ground,
Flying,
@@ -312,6 +331,30 @@ namespace EQ
NoDeposit
};
enum WeatherTypes : uint8 {
None,
Raining,
Snowing
};
enum EmoteEventTypes : uint8 {
LeaveCombat,
EnterCombat,
OnDeath,
AfterDeath,
Hailed,
KilledPC,
KilledNPC,
OnSpawn,
OnDespawn
};
enum EmoteTypes : uint8 {
Emote,
Shout,
Proximity
};
const char *GetStanceName(StanceType stance_type);
int ConvertStanceTypeToIndex(StanceType stance_type);
@@ -345,6 +388,15 @@ namespace EQ
extern const std::map<int, std::string>& GetObjectTypeMap();
std::string GetObjectTypeName(int object_type);
extern const std::map<uint8, std::string>& GetWeatherTypeMap();
std::string GetWeatherTypeName(uint8 weather_type);
extern const std::map<uint8, std::string>& GetEmoteEventTypeMap();
std::string GetEmoteEventTypeName(uint8 emote_event_type);
extern const std::map<uint8, std::string>& GetEmoteTypeMap();
std::string GetEmoteTypeName(uint8 emote_type);
const int STANCE_TYPE_FIRST = stancePassive;
const int STANCE_TYPE_LAST = stanceBurnAE;
const int STANCE_TYPE_COUNT = stanceBurnAE;
@@ -515,7 +567,7 @@ enum ReloadWorld : uint8 {
ForceRepop
};
enum MerchantBucketComparison : uint8 {
enum BucketComparison : uint8 {
BucketEqualTo = 0,
BucketNotEqualTo,
BucketGreaterThanOrEqualTo,
@@ -528,4 +580,17 @@ enum MerchantBucketComparison : uint8 {
BucketIsNotBetween
};
enum class EntityFilterType {
All,
Bots,
Clients,
NPCs
};
enum class ApplySpellType {
Solo,
Group,
Raid
};
#endif /*COMMON_EMU_CONSTANTS_H*/
+1 -1
View File
@@ -35,7 +35,7 @@ N(OP_AltCurrencyMerchantRequest),
N(OP_AltCurrencyPurchase),
N(OP_AltCurrencyReclaim),
N(OP_AltCurrencySell),
N(OP_AltCurrencySellSelection),
N(OP_AltCurrencySellSelection), // Used by eqstr_us.txt 8066, 8068, 8069
N(OP_Animation),
N(OP_AnnoyingZoneUnknown),
N(OP_ApplyPoison),
+19 -9
View File
@@ -684,14 +684,6 @@ namespace Zones {
constexpr uint16 APPRENTICE = 999; // Designer Apprentice
}
//ZoneChange_Struct->success values
#define ZONE_ERROR_NOMSG 0
#define ZONE_ERROR_NOTREADY -1
#define ZONE_ERROR_VALIDPC -2
#define ZONE_ERROR_STORYZONE -3
#define ZONE_ERROR_NOEXPANSION -6
#define ZONE_ERROR_NOEXPERIENCE -7
typedef enum {
FilterNone = 0,
@@ -718,7 +710,7 @@ typedef enum {
FilterPetMisses = 21, //0=show, 1=hide
FilterFocusEffects = 22, //0=show, 1=hide
FilterPetSpells = 23, //0=show, 1=hide
FilterHealOverTime = 24, //0=show, 1=hide
FilterHealOverTime = 24, //0=show, 1=mine only, 2=hide
FilterUnknown25 = 25,
FilterUnknown26 = 26,
FilterUnknown27 = 27,
@@ -1016,4 +1008,22 @@ enum FVNoDropFlagRule
AdminOnly = 2
};
enum Anonymity : uint8
{
NotAnonymous,
Anonymous,
Roleplaying
};
enum ZoningMessage : int8
{
ZoneNoMessage = 0,
ZoneSuccess = 1,
ZoneNotReady = -1,
ZoneValidPC = -2,
ZoneStoryZone = -3,
ZoneNoExpansion = -6,
ZoneNoExperience = -7
};
#endif /*COMMON_EQ_CONSTANTS_H*/
+4 -4
View File
@@ -5163,10 +5163,10 @@ struct AltCurrencySelectItemReply_Struct {
/*000*/ uint32 unknown000;
/*004*/ uint8 unknown004; //0xff
/*005*/ uint8 unknown005; //0xff
/*006*/ uint8 unknown006; //0xff
/*007*/ uint8 unknown007; //0xff
/*008*/ char item_name[64];
/*072*/ uint32 unknown074;
/*006*/ uint16 unknown006; //0xffff
/*008*/ uint16 unknown008; //0xffff
/*010*/ char item_name[64];
/*074*/ uint16 unknown074;
/*076*/ uint32 cost;
/*080*/ uint32 unknown080;
/*084*/ uint32 unknown084;
+11 -6
View File
@@ -218,13 +218,13 @@ class EQStream : public EQStreamInterface {
void init(bool resetSession=true);
public:
EQStream() { init(); remote_ip = 0; remote_port = 0; State = UNESTABLISHED;
StreamType = UnknownStream; compressed = true; encoded = false; app_opcode_size = 2;
bytes_sent = 0; bytes_recv = 0; create_time = Timer::GetTimeSeconds(); sessionAttempts = 0;
EQStream() { init(); remote_ip = 0; remote_port = 0; State = UNESTABLISHED;
StreamType = UnknownStream; compressed = true; encoded = false; app_opcode_size = 2;
bytes_sent = 0; bytes_recv = 0; create_time = Timer::GetTimeSeconds(); sessionAttempts = 0;
streamactive = false; }
EQStream(sockaddr_in addr) { init(); remote_ip = addr.sin_addr.s_addr;
remote_port = addr.sin_port; State = UNESTABLISHED; StreamType = UnknownStream;
compressed = true; encoded = false; app_opcode_size = 2; bytes_sent = 0; bytes_recv = 0;
EQStream(sockaddr_in addr) { init(); remote_ip = addr.sin_addr.s_addr;
remote_port = addr.sin_port; State = UNESTABLISHED; StreamType = UnknownStream;
compressed = true; encoded = false; app_opcode_size = 2; bytes_sent = 0; bytes_recv = 0;
create_time = Timer::GetTimeSeconds(); }
virtual ~EQStream() { RemoveData(); SetState(CLOSED); }
void SetMaxLen(uint32 length) { MaxLen=length; }
@@ -243,6 +243,11 @@ class EQStream : public EQStreamInterface {
virtual void SetOpcodeManager(OpcodeManager **opm) { OpMgr = opm; }
virtual OpcodeManager* GetOpcodeManager() const
{
return (*OpMgr);
};
void CheckTimeout(uint32 now, uint32 timeout=30);
bool HasOutgoingData();
void Process(const unsigned char *data, const uint32 length);
+2 -1
View File
@@ -30,7 +30,7 @@ struct EQStreamManagerInterfaceOptions
//World seems to support both compression and xor zone supports one or the others.
//Enforce one or the other in the convienence construct
//Login I had trouble getting to recognize compression at all
//Login I had trouble getting to recognize compression at all
//but that might be because it was still a bit buggy when i was testing that.
if (compressed) {
daybreak_options.encode_passes[0] = EQ::Net::EncodeCompression;
@@ -100,6 +100,7 @@ public:
virtual MatchState CheckSignature(const Signature *sig) { return MatchFailed; }
virtual EQStreamState GetState() = 0;
virtual void SetOpcodeManager(OpcodeManager **opm) = 0;
virtual OpcodeManager* GetOpcodeManager() const = 0;
virtual const EQ::versions::ClientVersion ClientVersion() const { return EQ::versions::ClientVersion::Unknown; }
virtual Stats GetStats() const = 0;
virtual void ResetStats() = 0;
+6 -5
View File
@@ -38,12 +38,8 @@ void EQStreamProxy::SetOpcodeManager(OpcodeManager **opm)
}
void EQStreamProxy::QueuePacket(const EQApplicationPacket *p, bool ack_req) {
if(p == nullptr)
if (p == nullptr) {
return;
if (p->GetOpcode() != OP_SpecialMesg) {
Log(Logs::General, Logs::PacketServerClient, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size());
Log(Logs::General, Logs::PacketServerClientWithDump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size(), DumpPacketToString(p).c_str());
}
EQApplicationPacket *newp = p->Copy();
@@ -112,3 +108,8 @@ bool EQStreamProxy::CheckState(EQStreamState state) {
return false;
}
OpcodeManager *EQStreamProxy::GetOpcodeManager() const
{
return (*m_opcodes);
}
+3 -1
View File
@@ -34,13 +34,15 @@ public:
virtual Stats GetStats() const;
virtual void ResetStats();
virtual EQStreamManagerInterface* GetManager() const;
virtual OpcodeManager* GetOpcodeManager() const;
protected:
std::shared_ptr<EQStreamInterface> const m_stream; //we own this stream object.
const StructStrategy *const m_structs; //we do not own this object.
//this is a pointer to a pointer to make it less likely that a packet will
//reference an invalid opcode manager when they are being reloaded.
OpcodeManager **const m_opcodes; //we do not own this object.
OpcodeManager **const m_opcodes;
//we do not own this object.
};
#endif /*EQSTREAMPROXY_H_*/
+15 -5
View File
@@ -20,7 +20,9 @@
#include "json/json.h"
#include "linked_list.h"
#include "path_manager.h"
#include <fstream>
#include <fmt/format.h>
struct LoginConfig {
std::string LoginHost;
@@ -152,23 +154,31 @@ class EQEmuConfig
}
// Load the config
static bool LoadConfig()
static bool LoadConfig(const std::string& path = "")
{
if (_config != nullptr) {
return true;
}
_config = new EQEmuConfig;
return parseFile();
return parseFile(path);
}
// Load config file and parse data
static bool parseFile() {
static bool parseFile(const std::string& file_path = ".")
{
if (_config == nullptr) {
return LoadConfig();
return LoadConfig(file_path);
}
std::ifstream fconfig(EQEmuConfig::ConfigFile, std::ifstream::binary);
std::string file = fmt::format(
"{}/{}",
(file_path.empty() ? path.GetServerPath() : file_path),
EQEmuConfig::ConfigFile
);
std::ifstream fconfig(file, std::ifstream::binary);
try {
fconfig >> _config->_root;
_config->parse_config();
+263 -253
View File
@@ -22,21 +22,19 @@
#include "rulesys.h"
#include "platform.h"
#include "strings.h"
#include "misc.h"
#include "discord/discord.h"
#include "repositories/discord_webhooks_repository.h"
#include "repositories/logsys_categories_repository.h"
#include "termcolor/rang.hpp"
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <time.h>
#include <sys/stat.h>
#include <algorithm>
std::ofstream process_log;
#include <filesystem>
#ifdef _WINDOWS
#include <direct.h>
#include <conio.h>
@@ -52,46 +50,12 @@ std::ofstream process_log;
#endif
/**
* Linux ANSI console color defines
*/
#define LC_RESET "\033[0m"
#define LC_BLACK "\033[30m" /* Black */
#define LC_RED "\033[31m" /* Red */
#define LC_GREEN "\033[32m" /* Green */
#define LC_YELLOW "\033[33m" /* Yellow */
#define LC_BLUE "\033[34m" /* Blue */
#define LC_MAGENTA "\033[35m" /* Magenta */
#define LC_CYAN "\033[36m" /* Cyan */
#define LC_WHITE "\033[37m" /* White */
namespace Console {
enum Color {
Black = 0,
Blue = 1,
Green = 2,
Cyan = 3,
Red = 4,
Magenta = 5,
Brown = 6,
LightGray = 7,
DarkGray = 8,
LightBlue = 9,
LightGreen = 10,
LightCyan = 11,
LightRed = 12,
LightMagenta = 13,
Yellow = 14,
White = 15
};
}
/**
* EQEmuLogSys Constructor
*/
EQEmuLogSys::EQEmuLogSys()
{
m_on_log_gmsay_hook = [](uint16 log_type, const std::string &) {};
m_on_log_gmsay_hook = [](uint16 log_type, const char *func, const std::string &) {};
m_on_log_console_hook = [](uint16 log_type, const std::string &) {};
}
@@ -120,14 +84,8 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
/**
* Set Defaults
*/
log_settings[Logs::WorldServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::ZoneServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::QSServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::UCSServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::MySQLError].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Loginserver].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HeadlessClient].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_console = static_cast<uint8>(Logs::General);
@@ -140,16 +98,14 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
log_settings[Logs::ChecksumVerification].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::CombatRecord].log_to_gmsay = static_cast<uint8>(Logs::General);
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);
/**
* RFC 5424
*/
log_settings[Logs::Emergency].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Alert].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Critical].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Error].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Warning].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Notice].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Info].log_to_console = static_cast<uint8>(Logs::General);
/**
@@ -194,39 +150,6 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
return this;
}
/**
* @param log_category
* @return
*/
bool EQEmuLogSys::IsRfc5424LogCategory(uint16 log_category)
{
return (
log_category == Logs::Emergency ||
log_category == Logs::Alert ||
log_category == Logs::Critical ||
log_category == Logs::Error ||
log_category == Logs::Warning ||
log_category == Logs::Notice ||
log_category == Logs::Info ||
log_category == Logs::Debug
);
}
/**
* @param log_category
* @param in_message
* @return
*/
std::string EQEmuLogSys::FormatOutMessageString(
uint16 log_category,
const std::string &in_message
)
{
std::string return_string = "[" + GetPlatformName() + "] ";
return return_string + "[" + Logs::LogCategoryName[log_category] + "] " + in_message;
}
/**
* @param debug_level
* @param log_category
@@ -257,64 +180,6 @@ void EQEmuLogSys::ProcessLogWrite(
}
}
/**
* @param log_category
* @return
*/
uint16 EQEmuLogSys::GetWindowsConsoleColorFromCategory(uint16 log_category)
{
switch (log_category) {
case Logs::Status:
case Logs::Normal:
return Console::Color::Yellow;
case Logs::MySQLError:
case Logs::Error:
return Console::Color::LightRed;
case Logs::MySQLQuery:
case Logs::Debug:
return Console::Color::LightGreen;
case Logs::Quests:
return Console::Color::LightCyan;
case Logs::Commands:
case Logs::Mercenaries:
return Console::Color::LightMagenta;
case Logs::Crash:
return Console::Color::LightRed;
default:
return Console::Color::Yellow;
}
}
/**
* @param log_category
* @return
*/
std::string EQEmuLogSys::GetLinuxConsoleColorFromCategory(uint16 log_category)
{
switch (log_category) {
case Logs::Status:
case Logs::Normal:
return LC_YELLOW;
case Logs::MySQLError:
case Logs::Warning:
case Logs::Critical:
case Logs::Error:
return LC_RED;
case Logs::MySQLQuery:
case Logs::Debug:
return LC_GREEN;
case Logs::Quests:
return LC_CYAN;
case Logs::Commands:
case Logs::Mercenaries:
return LC_MAGENTA;
case Logs::Crash:
return LC_RED;
default:
return LC_YELLOW;
}
}
/**
* @param log_category
* @return
@@ -322,10 +187,8 @@ std::string EQEmuLogSys::GetLinuxConsoleColorFromCategory(uint16 log_category)
uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
{
switch (log_category) {
case Logs::Status:
case Logs::Normal:
return Chat::Yellow;
case Logs::MySQLError:
case Logs::QuestErrors:
case Logs::Error:
return Chat::Red;
case Logs::MySQLQuery:
@@ -343,28 +206,144 @@ uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
}
}
/**
* @param debug_level
* @param log_category
* @param message
*/
void EQEmuLogSys::ProcessConsoleMessage(uint16 log_category, const std::string &message)
void EQEmuLogSys::ProcessConsoleMessage(
uint16 log_category,
const std::string &message,
const char *file,
const char *func,
int line
)
{
#ifdef _WINDOWS
HANDLE console_handle;
console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_FONT_INFOEX info = { 0 };
info.cbSize = sizeof(info);
info.dwFontSize.Y = 12; // leave X as zero
info.FontWeight = FW_NORMAL;
wcscpy(info.FaceName, L"Lucida Console");
SetCurrentConsoleFontEx(console_handle, NULL, &info);
SetConsoleTextAttribute(console_handle, EQEmuLogSys::GetWindowsConsoleColorFromCategory(log_category));
std::cout << message << "\n";
SetConsoleTextAttribute(console_handle, Console::Color::White);
#else
std::cout << EQEmuLogSys::GetLinuxConsoleColorFromCategory(log_category) << message << LC_RESET << std::endl;
#endif
bool is_error = (
log_category == Logs::LogCategory::Error ||
log_category == Logs::LogCategory::MySQLError ||
log_category == Logs::LogCategory::Crash ||
log_category == Logs::LogCategory::QuestErrors
);
bool is_warning = (
log_category == Logs::LogCategory::Warning
);
(!is_error ? std::cout : std::cerr)
<< ""
<< rang::fgB::black
<< rang::style::bold
<< fmt::format("{:>6}", GetPlatformName().substr(0, 6))
<< rang::style::reset
<< rang::fgB::gray
<< " | "
<< ((is_error || is_warning) ? rang::fgB::red : rang::fgB::gray)
<< rang::style::bold
<< fmt::format("{:^10}", fmt::format("{}", Logs::LogCategoryName[log_category]).substr(0, 10))
<< rang::style::reset
<< rang::fgB::gray
<< " | "
<< rang::fgB::gray
<< rang::style::bold
<< fmt::format("{}", func)
<< rang::style::reset
<< rang::fgB::gray
<< " ";
if (RuleB(Logging, PrintFileFunctionAndLine)) {
(!is_error ? std::cout : std::cerr)
<< ""
<< rang::fgB::green
<< rang::style::bold
<< fmt::format("{:}", fmt::format("{}:{}:{}", std::filesystem::path(file).filename().string(), func, line))
<< rang::style::reset
<< " | ";
}
if (log_category == Logs::LogCategory::MySQLQuery) {
auto s = Strings::Split(message, "--");
if (s.size() > 1) {
std::string query = Strings::Trim(s[0]);
std::string meta = Strings::Trim(s[1]);
std::cout <<
rang::fgB::green
<<
query
<<
rang::style::reset;
std::cout <<
rang::fgB::black
<<
" -- "
<<
meta
<<
rang::style::reset;
}
}
else if (Strings::Contains(message, "[")) {
for (auto &e: Strings::Split(message, " ")) {
if (Strings::Contains(e, "[") && Strings::Contains(e, "]")) {
e = Strings::Replace(e, "[", "");
e = Strings::Replace(e, "]", "");
bool is_upper = false;
for (int i = 0; i < strlen(e.c_str()); i++) {
if (isupper(e[i])) {
is_upper = true;
}
}
if (!is_upper) {
(!is_error ? std::cout : std::cerr)
<< rang::fgB::gray
<< "["
<< rang::style::bold
<< rang::fgB::yellow
<< e
<< rang::fgB::gray
<< "] "
;
}
else {
(!is_error ? std::cout : std::cerr) << rang::fgB::gray << "[" << e << "] ";
}
}
else {
(!is_error ? std::cout : std::cerr)
<< (is_error ? rang::fgB::red : rang::fgB::gray)
<< e
<< " ";
}
}
}
else {
(!is_error ? std::cout : std::cerr)
<< (is_error ? rang::fgB::red : rang::fgB::gray)
<< message
<< " ";
}
if (!origination_info.zone_short_name.empty()) {
(!is_error ? std::cout : std::cerr)
<<
rang::fgB::black
<<
"-- "
<<
fmt::format(
"[{}] ({}) inst_id [{}]",
origination_info.zone_short_name,
origination_info.zone_long_name,
origination_info.instance_id
);
}
(!is_error ? std::cout : std::cerr) << rang::style::reset << std::endl;
m_on_log_console_hook(log_category, message);
}
@@ -378,33 +357,6 @@ constexpr const char *str_end(const char *str)
return *str ? str_end(str + 1) : str;
}
/**
* @param str
* @return
*/
constexpr bool str_slant(const char *str)
{
return *str == '/' ? true : (*str ? str_slant(str + 1) : false);
}
/**
* @param str
* @return
*/
constexpr const char *r_slant(const char *str)
{
return *str == '/' ? (str + 1) : r_slant(str - 1);
}
/**
* @param str
* @return
*/
constexpr const char *base_file_name(const char *str)
{
return str_slant(str) ? r_slant(str_end(str)) : str;
}
/**
* Core logging function
*
@@ -423,49 +375,54 @@ void EQEmuLogSys::Out(
...
)
{
bool log_to_console = log_settings[log_category].log_to_console > 0 &&
log_settings[log_category].log_to_console >= debug_level;
bool log_to_file = log_settings[log_category].log_to_file > 0 &&
log_settings[log_category].log_to_file >= debug_level;
bool log_to_gmsay = log_settings[log_category].log_to_gmsay > 0 &&
log_settings[log_category].log_to_gmsay >= debug_level &&
log_category != Logs::LogCategory::Netcode &&
(EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone ||
EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformWorld);
bool log_to_discord = EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone &&
log_settings[log_category].log_to_discord > 0 &&
log_settings[log_category].log_to_discord >= debug_level &&
log_settings[log_category].discord_webhook_id > 0 &&
log_settings[log_category].discord_webhook_id < MAX_DISCORD_WEBHOOK_ID;
auto l = GetLogsEnabled(debug_level, log_category);
// bail out if nothing to log
const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay && !log_to_discord;
if (nothing_to_log) {
if (!l.log_enabled) {
return;
}
std::string prefix;
if (RuleB(Logging, PrintFileFunctionAndLine)) {
prefix = fmt::format("[{0}::{1}:{2}] ", base_file_name(file), func, line);
prefix = fmt::format("[{0}::{1}:{2}] ", std::filesystem::path(file).filename().string(), func, line);
}
va_list args;
va_start(args, message);
std::string output_message = vStringFormat(message, args);
va_end(args);
// remove this when we remove all legacy logs
bool ignore_log_legacy_format = (
log_category == Logs::Netcode ||
log_category == Logs::PacketServerClient ||
log_category == Logs::PacketClientServer ||
log_category == Logs::PacketServerToServer
);
std::string output_debug_message = EQEmuLogSys::FormatOutMessageString(log_category, prefix + output_message);
// remove this when we remove all legacy logs
std::string output_message = message;
if (!ignore_log_legacy_format) {
va_list args;
va_start(args, message);
output_message = vStringFormat(message, args);
va_end(args);
}
if (log_to_console) {
EQEmuLogSys::ProcessConsoleMessage(log_category, output_debug_message);
if (l.log_to_console_enabled) {
EQEmuLogSys::ProcessConsoleMessage(
log_category,
output_message,
file,
func,
line
);
}
if (log_to_gmsay) {
m_on_log_gmsay_hook(log_category, output_message);
if (l.log_to_gmsay_enabled) {
m_on_log_gmsay_hook(log_category, func, output_message);
}
if (log_to_file) {
EQEmuLogSys::ProcessLogWrite(log_category, output_debug_message);
if (l.log_to_file_enabled) {
EQEmuLogSys::ProcessLogWrite(
log_category,
fmt::format("[{}] [{}] {}", GetPlatformName(), Logs::LogCategoryName[log_category], prefix + output_message)
);
}
if (log_to_discord && m_on_log_discord_hook) {
if (l.log_to_discord_enabled && m_on_log_discord_hook) {
m_on_log_discord_hook(log_category, log_settings[log_category].discord_webhook_id, output_message);
}
}
@@ -479,7 +436,7 @@ void EQEmuLogSys::SetCurrentTimeStamp(char *time_stamp)
struct tm *time_info;
time(&raw_time);
time_info = localtime(&raw_time);
strftime(time_stamp, 80, "[%m-%d-%Y :: %H:%M:%S]", time_info);
strftime(time_stamp, 80, "[%m-%d-%Y %H:%M:%S]", time_info);
}
/**
@@ -534,37 +491,29 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name)
return;
}
LogInfo("Starting File Log [logs/{}_{}.log]", m_platform_file_name.c_str(), getpid());
LogInfo("Starting File Log [{}/zone/{}_{}.log]", GetLogPath(), m_platform_file_name.c_str(), getpid());
/**
* Make directory if not exists
*/
EQEmuLogSys::MakeDirectory("logs/zone");
// Make directory if not exists
EQEmuLogSys::MakeDirectory(fmt::format("{}/zone", GetLogPath()));
/**
* Open file pointer
*/
// Open file pointer
process_log.open(
StringFormat("logs/zone/%s_%i.log", m_platform_file_name.c_str(), getpid()),
fmt::format("{}/zone/{}_{}.log", GetLogPath(), m_platform_file_name, getpid()),
std::ios_base::app | std::ios_base::out
);
}
else {
/**
* All other processes
*/
// All other processes
if (m_platform_file_name.empty()) {
return;
}
LogInfo("Starting File Log [logs/{}_{}.log]", m_platform_file_name.c_str(), getpid());
LogInfo("Starting File Log [{}/{}_{}.log]", GetLogPath(), m_platform_file_name.c_str(), getpid());
/**
* Open file pointer
*/
// Open file pointer
process_log.open(
StringFormat("logs/%s_%i.log", m_platform_file_name.c_str(), getpid()),
fmt::format("{}/{}_{}.log", GetLogPath(), m_platform_file_name.c_str(), getpid()),
std::ios_base::app | std::ios_base::out
);
}
@@ -579,6 +528,8 @@ void EQEmuLogSys::SilenceConsoleLogging()
log_settings[log_index].log_to_console = 0;
log_settings[log_index].is_category_enabled = 0;
}
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
}
/**
@@ -642,10 +593,23 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
// Auto inject categories that don't exist in the database...
for (int i = Logs::AA; i != Logs::MaxCategoryID; i++) {
if (std::find(db_categories.begin(), db_categories.end(), i) == db_categories.end()) {
bool is_missing_in_database = std::find(db_categories.begin(), db_categories.end(), i) == db_categories.end();
bool is_deprecated_category = Strings::Contains(fmt::format("{}", Logs::LogCategoryName[i]), "Deprecated");
if (!is_missing_in_database && is_deprecated_category) {
LogInfo(
"Automatically adding new log category [{0}]",
Logs::LogCategoryName[i]
"Logging category [{}] ({}) is now deprecated, deleting from database",
Logs::LogCategoryName[i],
i
);
LogsysCategoriesRepository::DeleteOne(*m_database, i);
}
if (is_missing_in_database && !is_deprecated_category) {
LogInfo(
"Automatically adding new log category [{}] ({})",
Logs::LogCategoryName[i],
i
);
auto new_category = LogsysCategoriesRepository::NewEntity();
@@ -670,6 +634,11 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
LogInfo("Loaded [{}] Discord webhooks", webhooks.size());
}
// force override this setting
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_file = static_cast<uint8>(Logs::General);
return this;
}
@@ -696,13 +665,13 @@ void EQEmuLogSys::InjectTablesIfNotExist()
CREATE TABLE discord_webhooks
(
id INT auto_increment primary key NULL,
webhook_name varchar(100) NULL,
webhook_url varchar(255) NULL,
created_at DATETIME NULL,
deleted_at DATETIME NULL
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_general_ci;
webhook_name varchar(100) NULL,
webhook_url varchar(255) NULL,
created_at DATETIME NULL,
deleted_at DATETIME NULL
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_general_ci;
)
);
}
@@ -713,15 +682,15 @@ void EQEmuLogSys::InjectTablesIfNotExist()
m_database->QueryDatabase(
SQL(
CREATE TABLE `logsys_categories` (
`log_category_id` int(11) NOT NULL,
`log_category_description` varchar(150) DEFAULT NULL,
`log_to_console` smallint(11) DEFAULT 0,
`log_to_file` smallint(11) DEFAULT 0,
`log_to_gmsay` smallint(11) DEFAULT 0,
`log_to_discord` smallint(11) DEFAULT 0,
`discord_webhook_id` int(11) DEFAULT 0,
PRIMARY KEY (`log_category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
`log_category_id` int(11) NOT NULL,
`log_category_description` varchar(150) DEFAULT NULL,
`log_to_console` smallint(11) DEFAULT 0,
`log_to_file` smallint(11) DEFAULT 0,
`log_to_gmsay` smallint(11) DEFAULT 0,
`log_to_discord` smallint(11) DEFAULT 0,
`discord_webhook_id` int(11) DEFAULT 0,
PRIMARY KEY (`log_category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
)
);
}
@@ -732,3 +701,44 @@ const EQEmuLogSys::DiscordWebhooks *EQEmuLogSys::GetDiscordWebhooks() const
return m_discord_webhooks;
}
EQEmuLogSys::LogEnabled EQEmuLogSys::GetLogsEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category)
{
auto e = LogEnabled{};
e.log_to_console_enabled = log_settings[log_category].log_to_console > 0 &&
log_settings[log_category].log_to_console >= debug_level;
e.log_to_file_enabled = log_settings[log_category].log_to_file > 0 &&
log_settings[log_category].log_to_file >= debug_level;
e.log_to_gmsay_enabled = log_settings[log_category].log_to_gmsay > 0 &&
log_settings[log_category].log_to_gmsay >= debug_level &&
log_category != Logs::LogCategory::Netcode &&
(EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone ||
EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformWorld);
e.log_to_discord_enabled = EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone &&
log_settings[log_category].log_to_discord > 0 &&
log_settings[log_category].log_to_discord >= debug_level &&
log_settings[log_category].discord_webhook_id > 0 &&
log_settings[log_category].discord_webhook_id < MAX_DISCORD_WEBHOOK_ID;
e.log_enabled =
e.log_to_console_enabled || e.log_to_file_enabled || e.log_to_gmsay_enabled || e.log_to_discord_enabled;
return e;
}
bool EQEmuLogSys::IsLogEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category)
{
return GetLogsEnabled(debug_level, log_category).log_enabled;
}
const std::string &EQEmuLogSys::GetLogPath() const
{
return m_log_path;
}
EQEmuLogSys *EQEmuLogSys::SetLogPath(const std::string &log_path)
{
EQEmuLogSys::m_log_path = log_path;
return this;
}
+85 -60
View File
@@ -39,8 +39,7 @@
namespace Logs {
enum DebugLevel {
General = 1, // 1 - Low-Level general debugging, useful info on single line
Moderate, // 2 - Informational based, used in functions, when particular things load
Detail // 3 - Use this for extreme detail in logging, usually in extreme debugging in the stack or interprocess communication
Detail // 2 - Use this for very chatty logging you want to leave in but don't want on by default
};
/**
@@ -54,7 +53,7 @@ namespace Logs {
AI,
Aggro,
Attack,
PacketClientServer,
DeprecatedCS, // deprecated
Combat,
Commands,
Crash,
@@ -65,36 +64,36 @@ namespace Logs {
Inventory,
Launcher,
Netcode,
Normal,
Normal, // deprecated
Object,
Pathing,
QSServer,
QSServer, // deprecated
Quests,
Rules,
Skills,
Spawns,
Spells,
Status,
Status, // deprecated
TCPConnection,
Tasks,
Tradeskills,
Trading,
Tribute,
UCSServer,
WebInterfaceServer,
WorldServer,
ZoneServer,
UCSServer, // deprecated
WebInterfaceServer, // deprecated
WorldServer, // deprecated
ZoneServer, // deprecated
MySQLError,
MySQLQuery,
Mercenaries,
QuestDebug,
PacketServerClient,
PacketClientServerUnhandled,
PacketServerClientWithDump,
PacketClientServerWithDump,
Loginserver,
DeprecatedSC, // deprecated
DeprecatedCSU, // deprecated
DeprecatedSCD, // deprecated
DeprecatedCSD, // deprecated
Loginserver, // deprecated
ClientLogin,
HeadlessClient,
HeadlessClient, // deprecated
HPUpdate,
FixZ,
Food,
@@ -104,10 +103,10 @@ namespace Logs {
MobAppearance,
Info,
Warning,
Critical,
Emergency,
Alert,
Notice,
Critical, // deprecated
Emergency, // deprecated
Alert, // deprecated
Notice, // deprecated
AIScanClose,
AIYellForHelp,
AICastBeneficialClose,
@@ -132,6 +131,11 @@ namespace Logs {
Hate,
Discord,
Faction,
PacketServerClient,
PacketClientServer,
PacketServerToServer,
Bugs,
QuestErrors,
MaxCategoryID /* Don't Remove this */
};
@@ -144,7 +148,7 @@ namespace Logs {
"AI",
"Aggro",
"Attack",
"Packet :: Client -> Server",
"Deprecated",
"Combat",
"Commands",
"Crash",
@@ -155,52 +159,52 @@ namespace Logs {
"Inventory",
"Launcher",
"Netcode",
"Normal",
"Normal (Deprecated)",
"Object",
"Pathing",
"QS Server",
"QS Server (Deprecated)",
"Quests",
"Rules",
"Skills",
"Spawns",
"Spells",
"Status",
"Status (Deprecated)",
"TCP Connection",
"Tasks",
"Tradeskills",
"Trading",
"Tribute",
"UCS Server",
"WebInterface Server",
"World Server",
"Zone Server",
"MySQL Error",
"MySQL Query",
"UCS Server (Deprecated)",
"Web Interface (Deprecated)",
"World Server (Deprecated)",
"Zone Server (Deprecated)",
"QueryErr",
"Query",
"Mercenaries",
"Quest Debug",
"Packet :: Server -> Client",
"Packet :: Client -> Server Unhandled",
"Packet :: Server -> Client (Dump)",
"Packet :: Client -> Server (Dump)",
"Login Server",
"Legacy Packet Logging (Deprecated)",
"Legacy Packet Logging (Deprecated)",
"Legacy Packet Logging (Deprecated)",
"Legacy Packet Logging (Deprecated)",
"Login Server (Deprecated)",
"Client Login",
"Headless Client",
"Headless Client (Deprecated)",
"HP Update",
"FixZ",
"Food",
"Traps",
"NPC Roam Box",
"NPC Scaling",
"Mob Appearance",
"MobAppearance",
"Info",
"Warning",
"Critical",
"Emergency",
"Alert",
"Notice",
"AI Scan Close",
"AI Yell For Help",
"AI Cast Beneficial Close",
"Critical (Deprecated)",
"Emergency (Deprecated)",
"Alert (Deprecated)",
"Notice (Deprecated)",
"AI Scan",
"AI Yell",
"AI CastBeneficial",
"AOE Cast",
"Entity Management",
"Flee",
@@ -217,11 +221,16 @@ namespace Logs {
"DialogueWindow",
"HTTP",
"Saylink",
"ChecksumVerification",
"ChecksumVer",
"CombatRecord",
"Hate",
"Discord",
"Faction",
"Packet S->C",
"Packet C->S",
"Packet S->S",
"Bugs",
"QuestErrors"
};
}
@@ -313,6 +322,17 @@ public:
*/
LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{};
struct LogEnabled {
bool log_to_file_enabled;
bool log_to_console_enabled;
bool log_to_gmsay_enabled;
bool log_to_discord_enabled;
bool log_enabled;
};
LogEnabled GetLogsEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category);
bool IsLogEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category);
struct DiscordWebhooks {
int id;
std::string webhook_name;
@@ -324,7 +344,7 @@ public:
// gmsay
uint16 GetGMSayColorFromCategory(uint16 log_category);
EQEmuLogSys *SetGMSayHandler(std::function<void(uint16 log_type, const std::string &)> f)
EQEmuLogSys *SetGMSayHandler(const std::function<void(uint16 log_type, const char *func, const std::string &)>& f)
{
m_on_log_gmsay_hook = f;
return this;
@@ -349,25 +369,30 @@ public:
// database
EQEmuLogSys *SetDatabase(Database *db);
[[nodiscard]] const std::string &GetLogPath() const;
EQEmuLogSys * SetLogPath(const std::string &log_path);
private:
// reference to database
Database *m_database;
std::function<void(uint16 log_category, const std::string &)> m_on_log_gmsay_hook;
std::function<void(uint16 log_category, int webhook_id, const std::string &)> m_on_log_discord_hook;
std::function<void(uint16 log_category, const std::string &)> m_on_log_console_hook;
DiscordWebhooks m_discord_webhooks[MAX_DISCORD_WEBHOOK_ID]{};
bool m_file_logs_enabled = false;
int m_log_platform = 0;
std::string m_platform_file_name;
Database *m_database;
std::function<void(uint16 log_category, const char *func, const std::string &)> m_on_log_gmsay_hook;
std::function<void(uint16 log_category, int webhook_id, const std::string &)> m_on_log_discord_hook;
std::function<void(uint16 log_category, const std::string &)> m_on_log_console_hook;
DiscordWebhooks m_discord_webhooks[MAX_DISCORD_WEBHOOK_ID]{};
bool m_file_logs_enabled = false;
int m_log_platform = 0;
std::string m_platform_file_name;
std::string m_log_path;
std::string FormatOutMessageString(uint16 log_category, const std::string &in_message);
std::string GetLinuxConsoleColorFromCategory(uint16 log_category);
uint16 GetWindowsConsoleColorFromCategory(uint16 log_category);
void ProcessConsoleMessage(uint16 log_category, const std::string &message);
void ProcessConsoleMessage(
uint16 log_category,
const std::string &message,
const char *file,
const char *func,
int line
);
void ProcessLogWrite(uint16 log_category, const std::string &message);
bool IsRfc5424LogCategory(uint16 log_category);
void InjectTablesIfNotExist();
};
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -96,12 +96,12 @@ bool IsOfEqualRace(int r1, int r2)
// TODO: add more values
switch (r1) {
case DARK_ELF:
if (r2 == 77) {
if (r2 == RACE_NERIAK_CITIZEN_77) {
return true;
}
break;
case BARBARIAN:
if (r2 == 90) {
if (r2 == RACE_HALAS_CITIZEN_90) {
return true;
}
}
+30 -20
View File
@@ -19,7 +19,7 @@
*/
#include <fstream>
#include "file_util.h"
#include "file.h"
#ifdef _WINDOWS
#include <direct.h>
@@ -35,38 +35,48 @@
#endif
#include <fmt/format.h>
#include <filesystem>
namespace fs = std::filesystem;
/**
* @param name
* @return
*/
bool FileUtil::exists(const std::string &name)
bool File::Exists(const std::string &name)
{
std::ifstream f(name.c_str());
return f.good();
return fs::exists(fs::path{name});
}
/**
* @param directory_name
*/
void FileUtil::mkdir(const std::string& directory_name)
void File::Makedir(const std::string &directory_name)
{
fs::create_directory(directory_name);
fs::permissions(directory_name, fs::perms::owner_all);
}
#ifdef _WINDOWS
struct _stat st;
if (_stat(directory_name.c_str(), &st) == 0) // exists
return;
_mkdir(directory_name.c_str());
#else
struct stat st{};
if (stat(directory_name.c_str(), &st) == 0) { // exists
return;
std::string File::FindEqemuConfigPath()
{
if (File::Exists(fs::path{File::GetCwd() + "/eqemu_config.json"}.string())) {
return File::GetCwd();
}
::mkdir(directory_name.c_str(), 0755);
#endif
else if (File::Exists(fs::path{File::GetCwd() + "/../eqemu_config.json"}.string())) {
return canonical(fs::path{File::GetCwd() + "/../"}).string();
}
else if (File::Exists(fs::path{File::GetCwd() + "/login.json"}.string())) {
return File::GetCwd();
}
else if (File::Exists(fs::path{File::GetCwd() + "/../login.json"}.string())) {
return canonical(fs::path{File::GetCwd() + "/../"}).string();
}
return {};
}
bool file_exists(const std::string& name) {
std::ifstream f(name.c_str());
return f.good();
std::string File::GetCwd()
{
return fs::current_path().string();
}
+12 -7
View File
@@ -18,16 +18,21 @@
*
*/
#ifndef EQEMU_FILE_UTIL_H
#define EQEMU_FILE_UTIL_H
#ifndef EQEMU_FILE_H
#define EQEMU_FILE_H
#include <filesystem>
class FileUtil {
namespace fs = std::filesystem;
class File {
public:
static bool exists(const std::string &name);
static void mkdir(const std::string& directory_name);
static bool Exists(const std::string &name);
static void Makedir(const std::string& directory_name);
static std::string FindEqemuConfigPath();
static std::string GetCwd();
};
bool file_exists(const std::string& name);
bool Exists(const std::string& name);
#endif //EQEMU_FILE_UTIL_H
#endif //EQEMU_FILE_H
+5 -17
View File
@@ -63,7 +63,9 @@ bool BaseGuildManager::LoadGuilds() {
for (auto row=results.begin();row!=results.end();++row)
_CreateGuild(atoi(row[0]), row[1], atoi(row[2]), atoi(row[3]), row[4], row[5], row[6], row[7]);
query = "SELECT guild_id,`rank`,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace FROM guild_ranks";
LogInfo("Loaded [{}] Guilds", Strings::Commify(std::to_string(results.RowCount())));
query = "SELECT guild_id,`rank`,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace FROM guild_ranks";
results = m_db->QueryDatabase(query);
if (!results.Success())
@@ -864,20 +866,11 @@ bool BaseGuildManager::QueryWithLogging(std::string query, const char *errmsg) {
return(true);
}
//factored out so I dont have to copy this crap.
#ifdef BOTS
#define GuildMemberBaseQuery \
"SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \
" g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \
" g.`banker`, g.`public_note`, g.`alt`" \
" FROM `vw_bot_character_mobs` AS c LEFT JOIN `vw_guild_members` AS g ON c.`id` = g.`char_id` AND c.`mob_type` = g.`mob_type` "
#else
#define GuildMemberBaseQuery \
"SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \
" g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \
" g.`banker`, g.`public_note`, g.`alt` " \
" FROM `character_data` AS c LEFT JOIN `guild_members` AS g ON c.`id` = g.`char_id` "
#endif
static void ProcessGuildMember(MySQLRequestRow row, CharGuildInfo &into) {
//fields from `characer_`
into.char_id = atoi(row[0]);
@@ -967,13 +960,8 @@ bool BaseGuildManager::GetCharInfo(uint32 char_id, CharGuildInfo &into) {
}
//load up the rank info for each guild.
std::string query;
#ifdef BOTS
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mob_type = 'C' AND c.deleted_at IS NULL", char_id);
#else
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.deleted_at IS NULL", char_id);
#endif
auto results = m_db->QueryDatabase(query);
std::string query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.deleted_at IS NULL", char_id);
auto results = m_db->QueryDatabase(query);
if (!results.Success()) {
return false;
}
+2836 -2113
View File
File diff suppressed because it is too large Load Diff
+14
View File
@@ -1718,3 +1718,17 @@ int16 EQ::InventoryProfile::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 lo
return EQ::invslot::SLOT_INVALID;
}
std::vector<uint32> EQ::InventoryProfile::GetAugmentIDsBySlotID(int16 slot_id)
{
std::vector<uint32> augments;
const auto* item = GetItem(slot_id);
if (item) {
for (uint8 i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; i++) {
augments.push_back(item->GetAugment(i) ? item->GetAugmentItemID(i) : 0);
}
}
return augments;
}
+8 -2
View File
@@ -26,8 +26,11 @@
#include "item_instance.h"
#include "classes.h"
#include "races.h"
#include <list>
#include <vector>
//FatherNitwit: location bits for searching specific
@@ -129,7 +132,7 @@ namespace EQ
// Swap items in inventory
enum SwapItemFailState : int8 { swapInvalid = -1, swapPass = 0, swapNotAllowed, swapNullData, swapRaceClass, swapDeity, swapLevel };
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = 0, uint8 class_id = 0, uint16 deity_id = 0, uint8 level = 0);
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = RACE_DOUG_0, uint8 class_id = NO_CLASS, uint16 deity_id = deity::DeityType::DeityUnknown, uint8 level = 0);
// Remove item from inventory
bool DeleteItem(int16 slot_id, int16 quantity = 0);
@@ -152,6 +155,9 @@ namespace EQ
// Check how many of a specific augment the player has equipped by Item ID
int CountAugmentEquippedByID(uint32 item_id);
// Get a list of augments from a specific slot ID
std::vector<uint32> GetAugmentIDsBySlotID(int16 slot_id);
// Check whether there is space for the specified number of the specified item.
bool HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity);
@@ -202,7 +208,7 @@ namespace EQ
void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value);
void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value);
std::string GetCustomItemData(int16 slot_id, std::string identifier);
static int GetItemStatValue(uint32 item_id, const char* identifier);
static const int GetItemStatValue(uint32 item_id, std::string identifier);
protected:
///////////////////////////////
// Protected Methods
+1 -1
View File
@@ -198,7 +198,7 @@ std::string IpUtil::DNSLookupSync(const std::string &addr, int port)
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
if (std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() > 1500) {
LogInfo(
"[DNSLookupSync] Deadline exceeded [{}]",
"Deadline exceeded [{}]",
1500
);
running = false;
+4 -6
View File
@@ -30,6 +30,7 @@
#include "types.h"
#include "eqemu_exception.h"
#include "eqemu_config.h"
#include "path_manager.h"
namespace EQ {
struct IPCMutex::Implementation {
@@ -40,12 +41,11 @@ namespace EQ {
#endif
};
IPCMutex::IPCMutex(std::string name) : locked_(false) {
IPCMutex::IPCMutex(const std::string& name) : locked_(false) {
imp_ = new Implementation;
#ifdef _WINDOWS
auto Config = EQEmuConfig::get();
std::string final_name = Config->SharedMemDir + "EQEmuMutex_";
final_name += name;
std::string final_name = fmt::format("{}/EQEmuMutex_{}", Config->SharedMemDir, name);
imp_->mut_ = CreateMutex(nullptr,
FALSE,
@@ -55,9 +55,7 @@ namespace EQ {
EQ_EXCEPT("IPC Mutex", "Could not create mutex.");
}
#else
auto Config = EQEmuConfig::get();
std::string final_name = Config->SharedMemDir + name;
final_name += ".lock";
std::string final_name = fmt::format("{}/{}.lock", path.GetSharedMemoryPath(), name);
#ifdef __DARWIN
#if __DARWIN_C_LEVEL < 200809L
+1 -1
View File
@@ -37,7 +37,7 @@ namespace EQ {
Creates a named binary semaphore, basically a semaphore that is init S <- 1
\param name The name of this mutex.
*/
IPCMutex(std::string name);
IPCMutex(const std::string& name);
//! Destructor
~IPCMutex();
+24 -2
View File
@@ -169,11 +169,33 @@ uint8 EQ::item::ConvertAugTypeBitToAugType(uint32 aug_type_bit)
bool EQ::ItemData::IsEquipable(uint16 race_id, uint16 class_id) const
{
if (!(Races & GetPlayerRaceBit(race_id)))
if (!(Races & GetPlayerRaceBit(race_id))) {
return false;
}
if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id))))
if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id)))) {
return false;
}
return true;
}
bool EQ::ItemData::IsClassEquipable(uint16 class_id) const
{
if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id)))) {
return false;
}
return true;
}
bool EQ::ItemData::IsRaceEquipable(uint16 race_id) const
{
if (!(Races & GetPlayerRaceBit(race_id))) {
return false;
}
return true;
}
+2
View File
@@ -533,6 +533,8 @@ namespace EQ
//BardName
bool IsEquipable(uint16 Race, uint16 Class) const;
bool IsClassEquipable(uint16 Class) const;
bool IsRaceEquipable(uint16 Race) const;
bool IsClassCommon() const;
bool IsClassBag() const;
bool IsClassBook() const;
+67 -19
View File
@@ -263,20 +263,43 @@ bool EQ::ItemInstance::IsCharged() const
// Can item be equipped?
bool EQ::ItemInstance::IsEquipable(uint16 race, uint16 class_) const
{
if (!m_item || (m_item->Slots == 0))
if (!m_item || !m_item->Slots) {
return false;
}
return m_item->IsEquipable(race, class_);
}
// Can item be equipped by Class?
bool EQ::ItemInstance::IsClassEquipable(uint16 class_) const
{
if (!m_item || !m_item->Slots) {
return false;
}
return m_item->IsClassEquipable(class_);
}
// Can item be equipped by Race?
bool EQ::ItemInstance::IsRaceEquipable(uint16 race) const
{
if (!m_item || !m_item->Slots) {
return false;
}
return m_item->IsRaceEquipable(race);
}
// Can equip at this slot?
bool EQ::ItemInstance::IsEquipable(int16 slot_id) const
{
if (!m_item)
if (!m_item || !m_item->Slots) {
return false;
}
if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END)
if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END) {
return false;
}
return ((m_item->Slots & (1 << slot_id)) != 0);
}
@@ -309,19 +332,30 @@ bool EQ::ItemInstance::AvailableWearSlot(uint32 aug_wear_slots) const {
return (index <= EQ::invslot::EQUIPMENT_END);
}
int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augtype) const
int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augment_type) const
{
if (!m_item || !m_item->IsClassCommon())
if (!m_item || !m_item->IsClassCommon()) {
return INVALID_INDEX;
int index = invaug::SOCKET_BEGIN;
for (; index <= invaug::SOCKET_END; ++index) {
if (GetItem(index)) { continue; }
if (augtype == -1 || (m_item->AugSlotType[index] && ((1 << (m_item->AugSlotType[index] - 1)) & augtype)))
break;
}
return (index <= invaug::SOCKET_END) ? index : INVALID_INDEX;
auto i = invaug::SOCKET_BEGIN;
for (; i <= invaug::SOCKET_END; ++i) {
if (GetItem(i)) {
continue;
}
if (
augment_type == -1 ||
(
m_item->AugSlotType[i] &&
((1 << (m_item->AugSlotType[i] - 1)) & augment_type)
)
) {
break;
}
}
return (i <= invaug::SOCKET_END) ? i : INVALID_INDEX;
}
bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const
@@ -500,10 +534,11 @@ bool EQ::ItemInstance::IsNoneEmptyContainer()
}
// Retrieve augment inside item
EQ::ItemInstance* EQ::ItemInstance::GetAugment(uint8 slot) const
EQ::ItemInstance* EQ::ItemInstance::GetAugment(uint8 augment_index) const
{
if (m_item && m_item->IsClassCommon())
return GetItem(slot);
if (m_item && m_item->IsClassCommon()) {
return GetItem(augment_index);
}
return nullptr;
}
@@ -629,12 +664,13 @@ bool EQ::ItemInstance::CanTransform(const ItemData *ItemToTry, const ItemData *C
return false;
}
uint32 EQ::ItemInstance::GetAugmentItemID(uint8 slot) const
uint32 EQ::ItemInstance::GetAugmentItemID(uint8 augment_index) const
{
if (!m_item || !m_item->IsClassCommon())
if (!m_item || !m_item->IsClassCommon()) {
return 0;
}
return GetItemID(slot);
return GetItemID(augment_index);
}
// Add an augment to the item
@@ -1215,7 +1251,7 @@ int EQ::ItemInstance::GetItemBaneDamageBody(bool augments) const
int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const
{
int race = 0;
int race = RACE_DOUG_0;
const auto item = GetItem();
if (item) {
race = item->BaneDmgRace;
@@ -1721,6 +1757,18 @@ int EQ::ItemInstance::GetItemHaste(bool augments) const
return total;
}
int EQ::ItemInstance::RemoveTaskDeliveredItems()
{
int count = IsStackable() ? GetCharges() : 1;
count -= GetTaskDeliveredCount();
if (IsStackable())
{
SetCharges(count);
}
SetTaskDeliveredCount(0);
return count;
}
//
// class EvolveInfo
//
+14 -2
View File
@@ -92,6 +92,8 @@ namespace EQ
// Can item be equipped by/at?
bool IsEquipable(uint16 race, uint16 class_) const;
bool IsClassEquipable(uint16 class_) const;
bool IsRaceEquipable(uint16 race) const;
bool IsEquipable(int16 slot_id) const;
//
@@ -125,8 +127,8 @@ namespace EQ
//
// Augments
//
ItemInstance* GetAugment(uint8 slot) const;
uint32 GetAugmentItemID(uint8 slot) const;
ItemInstance* GetAugment(uint8 augment_index) const;
uint32 GetAugmentItemID(uint8 augment_index) const;
void PutAugment(uint8 slot, const ItemInstance& inst);
void PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id);
void DeleteAugment(uint8 slot);
@@ -148,6 +150,8 @@ namespace EQ
const ItemData* GetItem() const;
const ItemData* GetUnscaledItem() const;
const uint8 GetItemType() const { return m_item ? m_item->ItemType : 255; } // Return 255 so you know there's no valid item
int16 GetCharges() const { return m_charges; }
void SetCharges(int16 charges) { m_charges = charges; }
@@ -229,6 +233,13 @@ namespace EQ
void StopTimer(std::string name);
void ClearTimers();
int GetTaskDeliveredCount() const { return m_task_delivered_count; }
void SetTaskDeliveredCount(int count) { m_task_delivered_count = count; }
// This function should only be used by trade return apis
// Removes delivered task items from stack count and returns remaining count
// Return value should be used to determine if an item still exists (for stackable and non-stackable)
int RemoveTaskDeliveredItems();
// Get a total of a stat, including augs
// These functions should be used in place of other code manually totaling
// to centralize where it is done to make future changes easier (ex. whenever powersources come around)
@@ -313,6 +324,7 @@ namespace EQ
uint32 m_new_id_file;
uint32 m_ornament_hero_model;
uint32 m_recast_timestamp;
int m_task_delivered_count = 0;
//
// Items inside of this item (augs or contents);
+7 -7
View File
@@ -1,5 +1,5 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
@@ -41,7 +41,7 @@ namespace EQ
MemoryBuffer& operator+=(const MemoryBuffer &rhs);
friend MemoryBuffer operator+(MemoryBuffer lhs, const MemoryBuffer& rhs) { return lhs += rhs; }
~MemoryBuffer();
uchar& operator[](size_t pos);
const uchar& operator[](size_t pos) const;
@@ -64,20 +64,20 @@ namespace EQ
size_t Size() const;
size_t Capacity();
size_t Capacity() const;
void Resize(size_t sz);
void Clear();
void Zero();
template<typename T>
void Write(T val) {
static_assert(std::is_pod<T>::value, "MemoryBuffer::Write<T>(T val) only works on pod and string types.");
static_assert(std::is_standard_layout<T>::value, "MemoryBuffer::Write<T>(T val) only works on pod and string types.");
Write((const char*)&val, sizeof(T));
}
template<typename T>
T Read() {
static_assert(std::is_pod<T>::value, "MemoryBuffer::Read<T>() only works on pod and string types.");
static_assert(std::is_standard_layout<T>::value, "MemoryBuffer::Read<T>() only works on pod and string types.");
T temp;
Read((uchar*)&temp, sizeof(T));
return temp;
@@ -102,7 +102,7 @@ namespace EQ
read_pos_ += len + 1;
return ret;
}
void Write(const char *val, size_t len);
void Read(uchar *buf, size_t len);
void Read(char *str);
@@ -113,7 +113,7 @@ namespace EQ
inline size_t GetReadPosition() { return read_pos_; }
inline void SetReadPosition(size_t rp) { read_pos_ = rp; }
inline void ReadSkipBytes(size_t skip) { read_pos_ += skip; }
private:
uchar *buffer_;
size_t size_;
+3
View File
@@ -33,6 +33,9 @@
#include <sys/stat.h>
#endif
#include <filesystem>
namespace fs = std::filesystem;
namespace EQ {
struct MemoryMappedFile::Implementation {
+23 -5
View File
@@ -3,6 +3,7 @@
#include "../event/task.h"
#include "../data_verification.h"
#include "crc32.h"
#include "../eqemu_logsys.h"
#include <zlib.h>
#include <fmt/format.h>
#include <sstream>
@@ -308,6 +309,8 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner
m_combined[1] = OP_Combined;
m_last_session_stats = Clock::now();
m_outgoing_budget = owner->m_options.outgoing_data_rate;
LogNetcode("New session [{}] with encode key [{}]", m_connect_code, HostToNetwork(m_encode_key));
}
//new connection made as client
@@ -466,7 +469,7 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
for (int i = 1; i >= 0; --i) {
switch (m_encode_passes[i]) {
case EncodeXOR:
if (temp.GetInt8(0) == 0)
if (temp.GetInt8(0) == 0)
Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
else
Decode(temp, 1, temp.Length() - 1);
@@ -630,6 +633,8 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
DynamicPacket p;
p.PutSerialize(0, reply);
InternalSend(p);
LogNetcode("[OP_SessionRequest] Session [{}] started with encode key [{}]", m_connect_code, HostToNetwork(m_encode_key));
}
break;
@@ -647,6 +652,12 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
m_encode_passes[1] = (DaybreakEncodeType)reply.encode_pass2;
m_max_packet_size = reply.max_packet_size;
ChangeStatus(StatusConnected);
LogNetcode(
"[OP_SessionResponse] Session [{}] refresh with encode key [{}]",
m_connect_code,
HostToNetwork(m_encode_key)
);
}
}
break;
@@ -771,6 +782,12 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
SendDisconnect();
}
LogNetcode(
"[OP_SessionDisconnect] Session [{}] disconnect with encode key [{}]",
m_connect_code,
HostToNetwork(m_encode_key)
);
ChangeStatus(StatusDisconnecting);
break;
}
@@ -835,6 +852,7 @@ bool EQ::Net::DaybreakConnection::ValidateCRC(Packet &p)
}
if (p.Length() < (size_t)m_crc_bytes) {
LogNetcode("Session [{}] ignored packet (crc bytes invalid on session)", m_connect_code);
return false;
}
@@ -1078,7 +1096,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
if (m_status == DbProtocolStatus::StatusDisconnected) {
return;
}
auto resends = 0;
auto now = Clock::now();
auto s = &m_streams[stream];
@@ -1113,7 +1131,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
Close();
return;
}
if ((size_t)time_since_last_send.count() > entry.second.resend_delay) {
auto &p = entry.second.packet;
if (p.Length() >= DaybreakHeader::size()) {
@@ -1406,8 +1424,8 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
sent.first_sent = Clock::now();
sent.times_resent = 0;
sent.resend_delay = EQ::Clamp(
static_cast<size_t>((m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms),
m_owner->m_options.resend_delay_min,
static_cast<size_t>((m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms),
m_owner->m_options.resend_delay_min,
m_owner->m_options.resend_delay_max);
stream->sent_packets.insert(std::make_pair(stream->sequence_out, sent));
stream->sequence_out++;
+9
View File
@@ -65,6 +65,15 @@ EQ::Net::EQStream::~EQStream()
}
void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req) {
LogPacketServerClient(
"[{}] [{:#06x}] Size [{}] {}",
OpcodeManager::EmuToName(p->GetOpcode()),
(*m_opcode_manager)->EmuToEQ(p->GetOpcode()),
p->Size(),
(LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerClient) ? DumpPacketToString(p) : "")
);
if (m_opcode_manager && *m_opcode_manager) {
uint16 opcode = 0;
if (p->GetOpcodeBypass() != 0) {
+4
View File
@@ -57,6 +57,10 @@ namespace EQ
virtual void SetOpcodeManager(OpcodeManager **opm) {
m_opcode_manager = opm;
}
virtual OpcodeManager * GetOpcodeManager() const
{
return (*m_opcode_manager);
};
virtual Stats GetStats() const;
virtual void ResetStats();
+11 -1
View File
@@ -135,7 +135,7 @@ void EQ::Net::ServertalkServerConnection::ProcessReadBuffer()
auto leg_opcode = *(uint16_t*)&m_buffer[current];
auto leg_size = *(uint16_t*)&m_buffer[current + 2] - 4;
//this creates a small edge case where the exact size of a
//this creates a small edge case where the exact size of a
//packet from the modern protocol can't be "43061256"
//so in send we pad it one byte if that's the case
if (leg_opcode == ServerOP_NewLSInfo && leg_size == sizeof(ServerNewLSInfo_Struct)) {
@@ -319,6 +319,16 @@ void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p)
size_t message_len = length;
EQ::Net::StaticPacket packet(&data[0], message_len);
const auto is_detail_enabled = LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerToServer);
if (opcode != ServerOP_KeepAlive || is_detail_enabled) {
LogPacketServerToServer(
"[{:#06x}] Size [{}] {}",
opcode,
packet.Length(),
(is_detail_enabled ? "\n" + packet.ToString() : "")
);
}
auto cb = m_message_callbacks.find(opcode);
if (cb != m_message_callbacks.end()) {
cb->second(opcode, packet);
+3
View File
@@ -184,6 +184,9 @@ uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
MOpcodes.lock();
res = emu_to_eq[emu_op];
MOpcodes.unlock();
LogNetcodeDetail("[Opcode Manager] Translate emu [{}] ({:#06x}) eq [{:#06x}]", OpcodeNames[emu_op], emu_op, res);
#ifdef DEBUG_TRANSLATE
fprintf(stderr, "M Translate Emu %s (%d) to EQ 0x%.4x\n", OpcodeNames[emu_op], emu_op, res);
#endif
+16 -19
View File
@@ -32,6 +32,8 @@
#include "../inventory_profile.h"
#include "rof_structs.h"
#include "../rulesys.h"
#include "../path_manager.h"
#include "../races.h"
#include <iostream>
#include <sstream>
@@ -75,12 +77,8 @@ namespace RoF
{
//create our opcode manager if we havent already
if (opcodes == nullptr) {
//TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
//load up the opcode manager.
//TODO: figure out how to support shared memory with multiple patches...
opcodes = new RegularOpcodeManager();
@@ -118,12 +116,7 @@ namespace RoF
//we need to go to every stream and replace it's manager.
if (opcodes != nullptr) {
//TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
return;
@@ -672,7 +665,7 @@ namespace RoF
ENCODE(OP_DeleteCharge)
{
Log(Logs::Moderate, Logs::Netcode, "RoF::ENCODE(OP_DeleteCharge)");
Log(Logs::Detail, Logs::Netcode, "RoF::ENCODE(OP_DeleteCharge)");
ENCODE_FORWARD(OP_MoveItem);
}
@@ -1600,7 +1593,7 @@ namespace RoF
ENCODE_LENGTH_EXACT(LootingItem_Struct);
SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "RoF::ENCODE(OP_LootItem)");
Log(Logs::Detail, Logs::Netcode, "RoF::ENCODE(OP_LootItem)");
OUT(lootee);
OUT(looter);
@@ -1758,7 +1751,7 @@ namespace RoF
ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "RoF::ENCODE(OP_MoveItem)");
Log(Logs::Detail, Logs::Netcode, "RoF::ENCODE(OP_MoveItem)");
eq->from_slot = ServerToRoFSlot(emu->from_slot);
eq->to_slot = ServerToRoFSlot(emu->to_slot);
@@ -3838,7 +3831,9 @@ namespace RoF
}
float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)))
if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
)
{
PacketSize += 60;
@@ -3970,7 +3965,9 @@ namespace RoF
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown18
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown19
if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
)
{
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
{
@@ -4825,7 +4822,7 @@ namespace RoF
DECODE_LENGTH_EXACT(structs::LootingItem_Struct);
SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "RoF::DECODE(OP_LootItem)");
Log(Logs::Detail, Logs::Netcode, "RoF::DECODE(OP_LootItem)");
IN(lootee);
IN(looter);
@@ -4840,7 +4837,7 @@ namespace RoF
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "RoF::DECODE(OP_MoveItem)");
Log(Logs::Detail, Logs::Netcode, "RoF::DECODE(OP_MoveItem)");
emu->from_slot = RoFToServerSlot(eq->from_slot);
emu->to_slot = RoFToServerSlot(eq->to_slot);
+29 -28
View File
@@ -32,6 +32,9 @@
#include "../inventory_profile.h"
#include "rof2_structs.h"
#include "../rulesys.h"
#include "../path_manager.h"
#include "../classes.h"
#include "../races.h"
#include <iostream>
#include <sstream>
@@ -76,12 +79,9 @@ namespace RoF2
{
//create our opcode manager if we havent already
if (opcodes == nullptr) {
//TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
//load up the opcode manager.
//TODO: figure out how to support shared memory with multiple patches...
opcodes = new RegularOpcodeManager();
@@ -122,12 +122,7 @@ namespace RoF2
//we need to go to every stream and replace it's manager.
if (opcodes != nullptr) {
//TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
return;
@@ -721,7 +716,7 @@ namespace RoF2
ENCODE(OP_DeleteCharge)
{
Log(Logs::Moderate, Logs::Netcode, "RoF2::ENCODE(OP_DeleteCharge)");
Log(Logs::Detail, Logs::Netcode, "RoF2::ENCODE(OP_DeleteCharge)");
ENCODE_FORWARD(OP_MoveItem);
}
@@ -1649,7 +1644,7 @@ namespace RoF2
ENCODE_LENGTH_EXACT(LootingItem_Struct);
SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "RoF2::ENCODE(OP_LootItem)");
Log(Logs::Detail, Logs::Netcode, "RoF2::ENCODE(OP_LootItem)");
OUT(lootee);
OUT(looter);
@@ -1807,7 +1802,7 @@ namespace RoF2
ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "RoF2::ENCODE(OP_MoveItem)");
Log(Logs::Detail, Logs::Netcode, "RoF2::ENCODE(OP_MoveItem)");
eq->from_slot = ServerToRoF2Slot(emu->from_slot);
eq->to_slot = ServerToRoF2Slot(emu->to_slot);
@@ -3951,7 +3946,7 @@ namespace RoF2
if (strlen(emu->suffix))
PacketSize += strlen(emu->suffix) + 1;
if (emu->DestructibleObject || emu->class_ == 62)
if (emu->DestructibleObject || emu->class_ == LDON_TREASURE)
{
if (emu->DestructibleObject)
PacketSize = PacketSize - 4; // No bodytype
@@ -3972,7 +3967,9 @@ namespace RoF2
}
float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)))
if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
)
{
PacketSize += 60;
@@ -4039,17 +4036,19 @@ namespace RoF2
// actually part of bitfields
uint8 OtherData = 0;
if (emu->class_ == 62) //LDoN Chest
if (emu->class_ == LDON_TREASURE) //LDoN Chest
{
OtherData = OtherData | 0x04;
if (strlen(emu->title))
}
if (strlen(emu->title)) {
OtherData = OtherData | 16;
if (strlen(emu->suffix))
}
if (strlen(emu->suffix)) {
OtherData = OtherData | 32;
if (emu->DestructibleObject)
}
if (emu->DestructibleObject) {
OtherData = OtherData | 0xe1; // Live has 0xe1 for OtherData
}
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData);
// float EmitterScalingRadius
@@ -4065,7 +4064,7 @@ namespace RoF2
// int DefaultEmitterID
VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4
if (emu->DestructibleObject || emu->class_ == 62)
if (emu->DestructibleObject || emu->class_ == LDON_TREASURE)
{
VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleModel);
VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleName2);
@@ -4173,7 +4172,9 @@ namespace RoF2
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // These do something with OP_WeaponEquip1
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // ^
if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
)
{
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
{
@@ -5022,7 +5023,7 @@ namespace RoF2
DECODE_LENGTH_EXACT(structs::LootingItem_Struct);
SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "RoF2::DECODE(OP_LootItem)");
Log(Logs::Detail, Logs::Netcode, "RoF2::DECODE(OP_LootItem)");
IN(lootee);
IN(looter);
@@ -5037,7 +5038,7 @@ namespace RoF2
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "RoF2::DECODE(OP_MoveItem)");
Log(Logs::Detail, Logs::Netcode, "RoF2::DECODE(OP_MoveItem)");
emu->from_slot = RoF2ToServerSlot(eq->from_slot);
emu->to_slot = RoF2ToServerSlot(eq->to_slot);
+18 -20
View File
@@ -32,6 +32,8 @@
#include "../item_instance.h"
#include "sod_structs.h"
#include "../rulesys.h"
#include "../path_manager.h"
#include "../races.h"
#include <iostream>
#include <sstream>
@@ -69,12 +71,7 @@ namespace SoD
{
//create our opcode manager if we havent already
if (opcodes == nullptr) {
//TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
//load up the opcode manager.
//TODO: figure out how to support shared memory with multiple patches...
opcodes = new RegularOpcodeManager();
@@ -115,12 +112,7 @@ namespace SoD
//we need to go to every stream and replace it's manager.
if (opcodes != nullptr) {
//TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
return;
@@ -466,7 +458,7 @@ namespace SoD
ENCODE(OP_DeleteCharge)
{
Log(Logs::Moderate, Logs::Netcode, "SoD::ENCODE(OP_DeleteCharge)");
Log(Logs::Detail, Logs::Netcode, "SoD::ENCODE(OP_DeleteCharge)");
ENCODE_FORWARD(OP_MoveItem);
}
@@ -1136,7 +1128,7 @@ namespace SoD
ENCODE_LENGTH_EXACT(LootingItem_Struct);
SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "SoD::ENCODE(OP_LootItem)");
Log(Logs::Detail, Logs::Netcode, "SoD::ENCODE(OP_LootItem)");
OUT(lootee);
OUT(looter);
@@ -1285,7 +1277,7 @@ namespace SoD
ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "SoD::ENCODE(OP_MoveItem)");
Log(Logs::Detail, Logs::Netcode, "SoD::ENCODE(OP_MoveItem)");
eq->from_slot = ServerToSoDSlot(emu->from_slot);
eq->to_slot = ServerToSoDSlot(emu->to_slot);
@@ -2475,7 +2467,9 @@ namespace SoD
}
float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)))
if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
)
{
PacketSize -= (sizeof(structs::Texture_Struct) * EQ::textures::materialCount);
@@ -2672,7 +2666,9 @@ namespace SoD
Buffer += sizeof(structs::Spawn_Struct_Position);
if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
)
{
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
{
@@ -2697,7 +2693,9 @@ namespace SoD
}
if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
)
{
structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer;
@@ -3228,7 +3226,7 @@ namespace SoD
DECODE_LENGTH_EXACT(structs::LootingItem_Struct);
SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "SoD::DECODE(OP_LootItem)");
Log(Logs::Detail, Logs::Netcode, "SoD::DECODE(OP_LootItem)");
IN(lootee);
IN(looter);
@@ -3243,7 +3241,7 @@ namespace SoD
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "SoD::DECODE(OP_MoveItem)");
Log(Logs::Detail, Logs::Netcode, "SoD::DECODE(OP_MoveItem)");
emu->from_slot = SoDToServerSlot(eq->from_slot);
emu->to_slot = SoDToServerSlot(eq->to_slot);
+8 -17
View File
@@ -32,6 +32,7 @@
#include "../item_instance.h"
#include "sof_structs.h"
#include "../rulesys.h"
#include "../path_manager.h"
#include <iostream>
#include <sstream>
@@ -69,12 +70,7 @@ namespace SoF
{
//create our opcode manager if we havent already
if (opcodes == nullptr) {
//TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
//load up the opcode manager.
//TODO: figure out how to support shared memory with multiple patches...
opcodes = new RegularOpcodeManager();
@@ -113,12 +109,7 @@ namespace SoF
//we need to go to every stream and replace it's manager.
if (opcodes != nullptr) {
//TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
return;
@@ -445,7 +436,7 @@ namespace SoF
ENCODE(OP_DeleteCharge)
{
Log(Logs::Moderate, Logs::Netcode, "SoF::ENCODE(OP_DeleteCharge)");
Log(Logs::Detail, Logs::Netcode, "SoF::ENCODE(OP_DeleteCharge)");
ENCODE_FORWARD(OP_MoveItem);
}
@@ -932,7 +923,7 @@ namespace SoF
ENCODE_LENGTH_EXACT(LootingItem_Struct);
SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "SoF::ENCODE(OP_LootItem)");
Log(Logs::Detail, Logs::Netcode, "SoF::ENCODE(OP_LootItem)");
OUT(lootee);
OUT(looter);
@@ -963,7 +954,7 @@ namespace SoF
ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "SoF::ENCODE(OP_MoveItem)");
Log(Logs::Detail, Logs::Netcode, "SoF::ENCODE(OP_MoveItem)");
eq->from_slot = ServerToSoFSlot(emu->from_slot);
eq->to_slot = ServerToSoFSlot(emu->to_slot);
@@ -2640,7 +2631,7 @@ namespace SoF
DECODE_LENGTH_EXACT(structs::LootingItem_Struct);
SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "SoF::DECODE(OP_LootItem)");
Log(Logs::Detail, Logs::Netcode, "SoF::DECODE(OP_LootItem)");
IN(lootee);
IN(looter);
@@ -2655,7 +2646,7 @@ namespace SoF
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "SoF::DECODE(OP_MoveItem)");
Log(Logs::Detail, Logs::Netcode, "SoF::DECODE(OP_MoveItem)");
emu->from_slot = SoFToServerSlot(eq->from_slot);
emu->to_slot = SoFToServerSlot(eq->to_slot);
+8 -16
View File
@@ -32,6 +32,7 @@
#include "../strings.h"
#include "../item_instance.h"
#include "titanium_structs.h"
#include "../path_manager.h"
#include <sstream>
@@ -69,11 +70,7 @@ namespace Titanium
auto Config = EQEmuConfig::get();
//create our opcode manager if we havent already
if (opcodes == nullptr) {
//TODO: get this file name from the config file
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
//load up the opcode manager.
//TODO: figure out how to support shared memory with multiple patches...
opcodes = new RegularOpcodeManager();
@@ -114,12 +111,7 @@ namespace Titanium
//we need to go to every stream and replace it's manager.
if (opcodes != nullptr) {
//TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
return;
@@ -388,7 +380,7 @@ namespace Titanium
ENCODE(OP_DeleteCharge)
{
Log(Logs::Moderate, Logs::Netcode, "Titanium::ENCODE(OP_DeleteCharge)");
Log(Logs::Detail, Logs::Netcode, "Titanium::ENCODE(OP_DeleteCharge)");
ENCODE_FORWARD(OP_MoveItem);
}
@@ -898,7 +890,7 @@ namespace Titanium
ENCODE_LENGTH_EXACT(LootingItem_Struct);
SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "Titanium::ENCODE(OP_LootItem)");
Log(Logs::Detail, Logs::Netcode, "Titanium::ENCODE(OP_LootItem)");
OUT(lootee);
OUT(looter);
@@ -942,7 +934,7 @@ namespace Titanium
ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "Titanium::ENCODE(OP_MoveItem)");
Log(Logs::Detail, Logs::Netcode, "Titanium::ENCODE(OP_MoveItem)");
eq->from_slot = ServerToTitaniumSlot(emu->from_slot);
eq->to_slot = ServerToTitaniumSlot(emu->to_slot);
@@ -2186,7 +2178,7 @@ namespace Titanium
DECODE_LENGTH_EXACT(structs::LootingItem_Struct);
SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "Titanium::DECODE(OP_LootItem)");
Log(Logs::Detail, Logs::Netcode, "Titanium::DECODE(OP_LootItem)");
IN(lootee);
IN(looter);
@@ -2201,7 +2193,7 @@ namespace Titanium
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "Titanium::DECODE(OP_MoveItem)");
Log(Logs::Detail, Logs::Netcode, "Titanium::DECODE(OP_MoveItem)");
emu->from_slot = TitaniumToServerSlot(eq->from_slot);
emu->to_slot = TitaniumToServerSlot(eq->to_slot);
+30 -29
View File
@@ -32,6 +32,9 @@
#include "../item_instance.h"
#include "uf_structs.h"
#include "../rulesys.h"
#include "../path_manager.h"
#include "../classes.h"
#include "../races.h"
#include <iostream>
#include <sstream>
@@ -69,12 +72,7 @@ namespace UF
{
//create our opcode manager if we havent already
if (opcodes == nullptr) {
//TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
//load up the opcode manager.
//TODO: figure out how to support shared memory with multiple patches...
opcodes = new RegularOpcodeManager();
@@ -115,12 +113,7 @@ namespace UF
//we need to go to every stream and replace it's manager.
if (opcodes != nullptr) {
//TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
return;
@@ -586,7 +579,7 @@ namespace UF
ENCODE(OP_DeleteCharge)
{
Log(Logs::Moderate, Logs::Netcode, "UF::ENCODE(OP_DeleteCharge)");
Log(Logs::Detail, Logs::Netcode, "UF::ENCODE(OP_DeleteCharge)");
ENCODE_FORWARD(OP_MoveItem);
}
@@ -1356,7 +1349,7 @@ namespace UF
ENCODE_LENGTH_EXACT(LootingItem_Struct);
SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "UF::ENCODE(OP_LootItem)");
Log(Logs::Detail, Logs::Netcode, "UF::ENCODE(OP_LootItem)");
OUT(lootee);
OUT(looter);
@@ -1509,7 +1502,7 @@ namespace UF
ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "UF::ENCODE(OP_MoveItem)");
Log(Logs::Detail, Logs::Netcode, "UF::ENCODE(OP_MoveItem)");
eq->from_slot = ServerToUFSlot(emu->from_slot);
eq->to_slot = ServerToUFSlot(emu->to_slot);
@@ -2725,7 +2718,7 @@ namespace UF
if (strlen(emu->suffix))
PacketSize += strlen(emu->suffix) + 1;
if (emu->DestructibleObject || emu->class_ == 62)
if (emu->DestructibleObject || emu->class_ == LDON_TREASURE)
{
if (emu->DestructibleObject)
PacketSize = PacketSize - 4; // No bodytype
@@ -2746,7 +2739,9 @@ namespace UF
}
float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)))
if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
)
{
PacketSize -= (sizeof(structs::Texture_Struct) * EQ::textures::materialCount);
@@ -2812,18 +2807,20 @@ namespace UF
uint8 OtherData = 0;
if (emu->class_ == 62) //Ldon chest
if (emu->class_ == LDON_TREASURE) //Ldon chest
{
OtherData = OtherData | 0x01;
}
if (strlen(emu->title))
if (strlen(emu->title)) {
OtherData = OtherData | 0x04;
if (strlen(emu->suffix))
}
if (strlen(emu->suffix)) {
OtherData = OtherData | 0x08;
if (emu->DestructibleObject)
}
if (emu->DestructibleObject) {
OtherData = OtherData | 0xd1; // Live has 0xe1 for OtherData
}
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData);
if (emu->DestructibleObject)
@@ -2836,7 +2833,7 @@ namespace UF
}
VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4
if (emu->DestructibleObject || emu->class_ == 62)
if (emu->DestructibleObject || emu->class_ == LDON_TREASURE)
{
VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleModel);
VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleName2);
@@ -2945,7 +2942,9 @@ namespace UF
Buffer += sizeof(structs::Spawn_Struct_Position);
if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
)
{
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
{
@@ -2979,7 +2978,9 @@ namespace UF
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
}
if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
)
{
structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer;
@@ -3583,7 +3584,7 @@ namespace UF
DECODE_LENGTH_EXACT(structs::LootingItem_Struct);
SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "UF::DECODE(OP_LootItem)");
Log(Logs::Detail, Logs::Netcode, "UF::DECODE(OP_LootItem)");
IN(lootee);
IN(looter);
@@ -3598,7 +3599,7 @@ namespace UF
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "UF::DECODE(OP_MoveItem)");
Log(Logs::Detail, Logs::Netcode, "UF::DECODE(OP_MoveItem)");
emu->from_slot = UFToServerSlot(eq->from_slot);
emu->to_slot = UFToServerSlot(eq->to_slot);
+140
View File
@@ -0,0 +1,140 @@
#include "path_manager.h"
#include "file.h"
#include "eqemu_logsys.h"
#include "eqemu_config.h"
#include "strings.h"
#include <filesystem>
namespace fs = std::filesystem;
inline std::string striptrailingslash(const std::string &file_path)
{
if (file_path.back() == '/' || file_path.back() == '\\') {
return file_path.substr(0, file_path.length() - 1);
}
return file_path;
}
void PathManager::LoadPaths()
{
m_server_path = File::FindEqemuConfigPath();
if (!m_server_path.empty()) {
std::filesystem::current_path(m_server_path);
}
if (m_server_path.empty()) {
LogInfo("Failed to load server path");
return;
}
LogInfo("server [{}]", m_server_path);
if (!EQEmuConfig::LoadConfig()) {
LogError("Failed to load eqemu config");
return;
}
const auto c = EQEmuConfig::get();
// maps
if (File::Exists(fs::path{m_server_path + "/" + c->MapDir}.string())) {
m_maps_path = fs::relative(fs::path{m_server_path + "/" + c->MapDir}).string();
}
else if (File::Exists(fs::path{m_server_path + "/maps"}.string())) {
m_maps_path = fs::relative(fs::path{m_server_path + "/maps"}).string();
}
else if (File::Exists(fs::path{m_server_path + "/Maps"}.string())) {
m_maps_path = fs::relative(fs::path{m_server_path + "/Maps"}).string();
}
// quests
if (File::Exists(fs::path{m_server_path + "/" + c->QuestDir}.string())) {
m_quests_path = fs::relative(fs::path{m_server_path + "/" + c->QuestDir}).string();
}
// plugins
if (File::Exists(fs::path{m_server_path + "/" + c->PluginDir}.string())) {
m_plugins_path = fs::relative(fs::path{m_server_path + "/" + c->PluginDir}).string();
}
// lua_modules
if (File::Exists(fs::path{m_server_path + "/" + c->LuaModuleDir}.string())) {
m_lua_modules_path = fs::relative(fs::path{m_server_path + "/" + c->LuaModuleDir}).string();
}
// lua mods
if (File::Exists(fs::path{ m_server_path + "/mods" }.string())) {
m_lua_mods_path = fs::relative(fs::path{ m_server_path + "/mods" }).string();
}
// patches
if (File::Exists(fs::path{m_server_path + "/" + c->PatchDir}.string())) {
m_patch_path = fs::relative(fs::path{m_server_path + "/" + c->PatchDir}).string();
}
// shared_memory_path
if (File::Exists(fs::path{m_server_path + "/" + c->SharedMemDir}.string())) {
m_shared_memory_path = fs::relative(fs::path{ m_server_path + "/" + c->SharedMemDir }).string();
}
// logging path
if (File::Exists(fs::path{m_server_path + "/" + c->LogDir}.string())) {
m_log_path = fs::relative(fs::path{m_server_path + "/" + c->LogDir}).string();
}
LogInfo("logs path [{}]", m_log_path);
LogInfo("lua mods path [{}]", m_lua_mods_path);
LogInfo("lua_modules path [{}]", m_lua_modules_path);
LogInfo("maps path [{}]", m_maps_path);
LogInfo("patches path [{}]", m_patch_path);
LogInfo("plugins path [{}]", m_plugins_path);
LogInfo("quests path [{}]", m_quests_path);
LogInfo("shared_memory path [{}]", m_shared_memory_path);
}
const std::string &PathManager::GetServerPath() const
{
return m_server_path;
}
const std::string &PathManager::GetMapsPath() const
{
return m_maps_path;
}
const std::string &PathManager::GetQuestsPath() const
{
return m_quests_path;
}
const std::string &PathManager::GetPluginsPath() const
{
return m_plugins_path;
}
const std::string &PathManager::GetSharedMemoryPath() const
{
return m_shared_memory_path;
}
const std::string &PathManager::GetLogPath() const
{
return m_log_path;
}
const std::string &PathManager::GetPatchPath() const
{
return m_patch_path;
}
const std::string &PathManager::GetLuaModulesPath() const
{
return m_lua_modules_path;
}
const std::string &PathManager::GetLuaModsPath() const
{
return m_lua_mods_path;
}
+35
View File
@@ -0,0 +1,35 @@
#ifndef EQEMU_PATH_MANAGER_H
#define EQEMU_PATH_MANAGER_H
#include <string>
class PathManager {
public:
void LoadPaths();
[[nodiscard]] const std::string &GetLogPath() const;
[[nodiscard]] const std::string &GetLuaModsPath() const;
[[nodiscard]] const std::string &GetLuaModulesPath() const;
[[nodiscard]] const std::string &GetMapsPath() const;
[[nodiscard]] const std::string &GetPatchPath() const;
[[nodiscard]] const std::string &GetPluginsPath() const;
[[nodiscard]] const std::string &GetQuestsPath() const;
[[nodiscard]] const std::string &GetServerPath() const;
[[nodiscard]] const std::string &GetSharedMemoryPath() const;
private:
std::string m_log_path;
std::string m_lua_mods_path;
std::string m_lua_modules_path;
std::string m_maps_path;
std::string m_patch_path;
std::string m_plugins_path;
std::string m_quests_path;
std::string m_server_path;
std::string m_shared_memory_path;
};
extern PathManager path;
#endif //EQEMU_PATH_MANAGER_H
+5 -5
View File
@@ -55,18 +55,18 @@ std::string GetPlatformName()
return "UCS";
case EQEmuExePlatform::ExePlatformLogin:
return "Login";
case EQEmuExePlatform::ExePlatformSocket_Server:
return "SocketServer";
case EQEmuExePlatform::ExePlatformSharedMemory:
return "SharedMemory";
return "SharedMem";
case EQEmuExePlatform::ExePlatformClientImport:
return "ClientImport";
return "Import";
case EQEmuExePlatform::ExePlatformClientExport:
return "ClientExport";
return "Export";
case EQEmuExePlatform::ExePlatformLaunch:
return "Launch";
case EQEmuExePlatform::ExePlatformHC:
return "HC";
case EQEmuExePlatform::ExePlatformTests:
return "Tests";
default:
return "";
}
+2 -1
View File
@@ -36,7 +36,8 @@ enum EQEmuExePlatform
ExePlatformSharedMemory,
ExePlatformClientImport,
ExePlatformClientExport,
ExePlatformHC
ExePlatformHC,
ExePlatformTests
};
void RegisterExecutablePlatform(EQEmuExePlatform p);
+18
View File
@@ -0,0 +1,18 @@
#include <string>
#include <memory>
#include "process.h"
std::string Process::execute(const std::string &cmd)
{
std::shared_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);
if (!pipe) { return "ERROR"; }
char buffer[128];
std::string result;
while (!feof(pipe.get())) {
if (fgets(buffer, 128, pipe.get()) != nullptr) {
result += buffer;
}
}
return result;
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef EQEMU_PROCESS_H
#define EQEMU_PROCESS_H
#include "../strings.h"
#include <cstdio>
#if _WIN32
#define popen _popen
#define pclose _pclose
#endif
class Process {
public:
static std::string execute(const std::string &cmd);
};
#endif //EQEMU_PROCESS_H
+3
View File
@@ -18,6 +18,7 @@
*/
#include "profanity_manager.h"
#include "eqemu_logsys.h"
#include "dbcore.h"
#include "strings.h"
@@ -235,6 +236,8 @@ bool EQ::ProfanityManager::load_database_entries(DBcore *db) {
}
}
LogInfo("Loaded [{}] profanity entries", Strings::Commify(profanity_list.size()));
return true;
}
+1
View File
@@ -1612,6 +1612,7 @@ namespace PlayerAppearance
#define RACE_LUCLIN_731 731
#define RACE_PEGASUS_732 732
#define RACE_INTERACTIVE_OBJECT_2250 2250
#define RACE_NODE_2254 2254
#endif
@@ -0,0 +1,512 @@
/**
* 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_BUFFS_REPOSITORY_H
#define EQEMU_BASE_BOT_BUFFS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotBuffsRepository {
public:
struct BotBuffs {
uint32_t buffs_index;
uint32_t bot_id;
uint32_t spell_id;
uint8_t caster_level;
uint32_t duration_formula;
uint32_t tics_remaining;
uint32_t poison_counters;
uint32_t disease_counters;
uint32_t curse_counters;
uint32_t corruption_counters;
uint32_t numhits;
uint32_t melee_rune;
uint32_t magic_rune;
uint32_t dot_rune;
int8_t persistent;
int32_t caston_x;
int32_t caston_y;
int32_t caston_z;
uint32_t extra_di_chance;
int32_t instrument_mod;
};
static std::string PrimaryKey()
{
return std::string("buffs_index");
}
static std::vector<std::string> Columns()
{
return {
"buffs_index",
"bot_id",
"spell_id",
"caster_level",
"duration_formula",
"tics_remaining",
"poison_counters",
"disease_counters",
"curse_counters",
"corruption_counters",
"numhits",
"melee_rune",
"magic_rune",
"dot_rune",
"persistent",
"caston_x",
"caston_y",
"caston_z",
"extra_di_chance",
"instrument_mod",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"buffs_index",
"bot_id",
"spell_id",
"caster_level",
"duration_formula",
"tics_remaining",
"poison_counters",
"disease_counters",
"curse_counters",
"corruption_counters",
"numhits",
"melee_rune",
"magic_rune",
"dot_rune",
"persistent",
"caston_x",
"caston_y",
"caston_z",
"extra_di_chance",
"instrument_mod",
};
}
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_buffs");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotBuffs NewEntity()
{
BotBuffs e{};
e.buffs_index = 0;
e.bot_id = 0;
e.spell_id = 0;
e.caster_level = 0;
e.duration_formula = 0;
e.tics_remaining = 0;
e.poison_counters = 0;
e.disease_counters = 0;
e.curse_counters = 0;
e.corruption_counters = 0;
e.numhits = 0;
e.melee_rune = 0;
e.magic_rune = 0;
e.dot_rune = 0;
e.persistent = 0;
e.caston_x = 0;
e.caston_y = 0;
e.caston_z = 0;
e.extra_di_chance = 0;
e.instrument_mod = 10;
return e;
}
static BotBuffs GetBotBuffs(
const std::vector<BotBuffs> &bot_buffss,
int bot_buffs_id
)
{
for (auto &bot_buffs : bot_buffss) {
if (bot_buffs.buffs_index == bot_buffs_id) {
return bot_buffs;
}
}
return NewEntity();
}
static BotBuffs FindOne(
Database& db,
int bot_buffs_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_buffs_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotBuffs e{};
e.buffs_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.spell_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.caster_level = static_cast<uint8_t>(strtoul(row[3], nullptr, 10));
e.duration_formula = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.tics_remaining = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.poison_counters = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.disease_counters = static_cast<uint32_t>(strtoul(row[7], nullptr, 10));
e.curse_counters = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
e.corruption_counters = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
e.numhits = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
e.melee_rune = static_cast<uint32_t>(strtoul(row[11], nullptr, 10));
e.magic_rune = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.dot_rune = static_cast<uint32_t>(strtoul(row[13], nullptr, 10));
e.persistent = static_cast<int8_t>(atoi(row[14]));
e.caston_x = static_cast<int32_t>(atoi(row[15]));
e.caston_y = static_cast<int32_t>(atoi(row[16]));
e.caston_z = static_cast<int32_t>(atoi(row[17]));
e.extra_di_chance = static_cast<uint32_t>(strtoul(row[18], nullptr, 10));
e.instrument_mod = static_cast<int32_t>(atoi(row[19]));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_buffs_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_buffs_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotBuffs &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.bot_id));
v.push_back(columns[2] + " = " + std::to_string(e.spell_id));
v.push_back(columns[3] + " = " + std::to_string(e.caster_level));
v.push_back(columns[4] + " = " + std::to_string(e.duration_formula));
v.push_back(columns[5] + " = " + std::to_string(e.tics_remaining));
v.push_back(columns[6] + " = " + std::to_string(e.poison_counters));
v.push_back(columns[7] + " = " + std::to_string(e.disease_counters));
v.push_back(columns[8] + " = " + std::to_string(e.curse_counters));
v.push_back(columns[9] + " = " + std::to_string(e.corruption_counters));
v.push_back(columns[10] + " = " + std::to_string(e.numhits));
v.push_back(columns[11] + " = " + std::to_string(e.melee_rune));
v.push_back(columns[12] + " = " + std::to_string(e.magic_rune));
v.push_back(columns[13] + " = " + std::to_string(e.dot_rune));
v.push_back(columns[14] + " = " + std::to_string(e.persistent));
v.push_back(columns[15] + " = " + std::to_string(e.caston_x));
v.push_back(columns[16] + " = " + std::to_string(e.caston_y));
v.push_back(columns[17] + " = " + std::to_string(e.caston_z));
v.push_back(columns[18] + " = " + std::to_string(e.extra_di_chance));
v.push_back(columns[19] + " = " + std::to_string(e.instrument_mod));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.buffs_index
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotBuffs InsertOne(
Database& db,
BotBuffs e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.buffs_index));
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.caster_level));
v.push_back(std::to_string(e.duration_formula));
v.push_back(std::to_string(e.tics_remaining));
v.push_back(std::to_string(e.poison_counters));
v.push_back(std::to_string(e.disease_counters));
v.push_back(std::to_string(e.curse_counters));
v.push_back(std::to_string(e.corruption_counters));
v.push_back(std::to_string(e.numhits));
v.push_back(std::to_string(e.melee_rune));
v.push_back(std::to_string(e.magic_rune));
v.push_back(std::to_string(e.dot_rune));
v.push_back(std::to_string(e.persistent));
v.push_back(std::to_string(e.caston_x));
v.push_back(std::to_string(e.caston_y));
v.push_back(std::to_string(e.caston_z));
v.push_back(std::to_string(e.extra_di_chance));
v.push_back(std::to_string(e.instrument_mod));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.buffs_index = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotBuffs> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.buffs_index));
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.caster_level));
v.push_back(std::to_string(e.duration_formula));
v.push_back(std::to_string(e.tics_remaining));
v.push_back(std::to_string(e.poison_counters));
v.push_back(std::to_string(e.disease_counters));
v.push_back(std::to_string(e.curse_counters));
v.push_back(std::to_string(e.corruption_counters));
v.push_back(std::to_string(e.numhits));
v.push_back(std::to_string(e.melee_rune));
v.push_back(std::to_string(e.magic_rune));
v.push_back(std::to_string(e.dot_rune));
v.push_back(std::to_string(e.persistent));
v.push_back(std::to_string(e.caston_x));
v.push_back(std::to_string(e.caston_y));
v.push_back(std::to_string(e.caston_z));
v.push_back(std::to_string(e.extra_di_chance));
v.push_back(std::to_string(e.instrument_mod));
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<BotBuffs> All(Database& db)
{
std::vector<BotBuffs> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotBuffs e{};
e.buffs_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.spell_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.caster_level = static_cast<uint8_t>(strtoul(row[3], nullptr, 10));
e.duration_formula = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.tics_remaining = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.poison_counters = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.disease_counters = static_cast<uint32_t>(strtoul(row[7], nullptr, 10));
e.curse_counters = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
e.corruption_counters = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
e.numhits = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
e.melee_rune = static_cast<uint32_t>(strtoul(row[11], nullptr, 10));
e.magic_rune = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.dot_rune = static_cast<uint32_t>(strtoul(row[13], nullptr, 10));
e.persistent = static_cast<int8_t>(atoi(row[14]));
e.caston_x = static_cast<int32_t>(atoi(row[15]));
e.caston_y = static_cast<int32_t>(atoi(row[16]));
e.caston_z = static_cast<int32_t>(atoi(row[17]));
e.extra_di_chance = static_cast<uint32_t>(strtoul(row[18], nullptr, 10));
e.instrument_mod = static_cast<int32_t>(atoi(row[19]));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotBuffs> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotBuffs> 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) {
BotBuffs e{};
e.buffs_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.spell_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.caster_level = static_cast<uint8_t>(strtoul(row[3], nullptr, 10));
e.duration_formula = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.tics_remaining = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.poison_counters = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.disease_counters = static_cast<uint32_t>(strtoul(row[7], nullptr, 10));
e.curse_counters = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
e.corruption_counters = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
e.numhits = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
e.melee_rune = static_cast<uint32_t>(strtoul(row[11], nullptr, 10));
e.magic_rune = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.dot_rune = static_cast<uint32_t>(strtoul(row[13], nullptr, 10));
e.persistent = static_cast<int8_t>(atoi(row[14]));
e.caston_x = static_cast<int32_t>(atoi(row[15]));
e.caston_y = static_cast<int32_t>(atoi(row[16]));
e.caston_z = static_cast<int32_t>(atoi(row[17]));
e.extra_di_chance = static_cast<uint32_t>(strtoul(row[18], nullptr, 10));
e.instrument_mod = static_cast<int32_t>(atoi(row[19]));
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_BUFFS_REPOSITORY_H
@@ -0,0 +1,333 @@
/**
* 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_CREATE_COMBINATIONS_REPOSITORY_H
#define EQEMU_BASE_BOT_CREATE_COMBINATIONS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotCreateCombinationsRepository {
public:
struct BotCreateCombinations {
uint32_t race;
uint32_t classes;
};
static std::string PrimaryKey()
{
return std::string("race");
}
static std::vector<std::string> Columns()
{
return {
"race",
"classes",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"race",
"classes",
};
}
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_create_combinations");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotCreateCombinations NewEntity()
{
BotCreateCombinations e{};
e.race = 0;
e.classes = 0;
return e;
}
static BotCreateCombinations GetBotCreateCombinations(
const std::vector<BotCreateCombinations> &bot_create_combinationss,
int bot_create_combinations_id
)
{
for (auto &bot_create_combinations : bot_create_combinationss) {
if (bot_create_combinations.race == bot_create_combinations_id) {
return bot_create_combinations;
}
}
return NewEntity();
}
static BotCreateCombinations FindOne(
Database& db,
int bot_create_combinations_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_create_combinations_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotCreateCombinations e{};
e.race = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.classes = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_create_combinations_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_create_combinations_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotCreateCombinations &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[0] + " = " + std::to_string(e.race));
v.push_back(columns[1] + " = " + std::to_string(e.classes));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.race
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotCreateCombinations InsertOne(
Database& db,
BotCreateCombinations e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.race));
v.push_back(std::to_string(e.classes));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.race = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotCreateCombinations> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.race));
v.push_back(std::to_string(e.classes));
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<BotCreateCombinations> All(Database& db)
{
std::vector<BotCreateCombinations> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotCreateCombinations e{};
e.race = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.classes = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotCreateCombinations> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotCreateCombinations> 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) {
BotCreateCombinations e{};
e.race = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.classes = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_BOT_CREATE_COMBINATIONS_REPOSITORY_H
@@ -0,0 +1,813 @@
/**
* 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_DATA_REPOSITORY_H
#define EQEMU_BASE_BOT_DATA_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotDataRepository {
public:
struct BotData {
uint32_t bot_id;
uint32_t owner_id;
uint32_t spells_id;
std::string name;
std::string last_name;
std::string title;
std::string suffix;
int16_t zone_id;
int8_t gender;
int16_t race;
int8_t class_;
uint8_t level;
uint32_t deity;
uint32_t creation_day;
uint32_t last_spawn;
uint32_t time_spawned;
float size;
int32_t face;
int32_t hair_color;
int32_t hair_style;
int32_t beard;
int32_t beard_color;
int32_t eye_color_1;
int32_t eye_color_2;
int32_t drakkin_heritage;
int32_t drakkin_tattoo;
int32_t drakkin_details;
int16_t ac;
int32_t atk;
int32_t hp;
int32_t mana;
int32_t str;
int32_t sta;
int32_t cha;
int32_t dex;
int32_t int_;
int32_t agi;
int32_t wis;
int16_t fire;
int16_t cold;
int16_t magic;
int16_t poison;
int16_t disease;
int16_t corruption;
uint32_t show_helm;
uint32_t follow_distance;
uint8_t stop_melee_level;
int32_t expansion_bitmask;
uint8_t enforce_spell_settings;
uint8_t archery_setting;
};
static std::string PrimaryKey()
{
return std::string("bot_id");
}
static std::vector<std::string> Columns()
{
return {
"bot_id",
"owner_id",
"spells_id",
"name",
"last_name",
"title",
"suffix",
"zone_id",
"gender",
"race",
"`class`",
"level",
"deity",
"creation_day",
"last_spawn",
"time_spawned",
"size",
"face",
"hair_color",
"hair_style",
"beard",
"beard_color",
"eye_color_1",
"eye_color_2",
"drakkin_heritage",
"drakkin_tattoo",
"drakkin_details",
"ac",
"atk",
"hp",
"mana",
"str",
"sta",
"cha",
"dex",
"`int`",
"agi",
"wis",
"fire",
"cold",
"magic",
"poison",
"disease",
"corruption",
"show_helm",
"follow_distance",
"stop_melee_level",
"expansion_bitmask",
"enforce_spell_settings",
"archery_setting",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"bot_id",
"owner_id",
"spells_id",
"name",
"last_name",
"title",
"suffix",
"zone_id",
"gender",
"race",
"`class`",
"level",
"deity",
"creation_day",
"last_spawn",
"time_spawned",
"size",
"face",
"hair_color",
"hair_style",
"beard",
"beard_color",
"eye_color_1",
"eye_color_2",
"drakkin_heritage",
"drakkin_tattoo",
"drakkin_details",
"ac",
"atk",
"hp",
"mana",
"str",
"sta",
"cha",
"dex",
"`int`",
"agi",
"wis",
"fire",
"cold",
"magic",
"poison",
"disease",
"corruption",
"show_helm",
"follow_distance",
"stop_melee_level",
"expansion_bitmask",
"enforce_spell_settings",
"archery_setting",
};
}
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_data");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotData NewEntity()
{
BotData e{};
e.bot_id = 0;
e.owner_id = 0;
e.spells_id = 0;
e.name = "";
e.last_name = "";
e.title = "";
e.suffix = "";
e.zone_id = 0;
e.gender = 0;
e.race = 0;
e.class_ = 0;
e.level = 0;
e.deity = 0;
e.creation_day = 0;
e.last_spawn = 0;
e.time_spawned = 0;
e.size = 0;
e.face = 1;
e.hair_color = 1;
e.hair_style = 1;
e.beard = 0;
e.beard_color = 1;
e.eye_color_1 = 1;
e.eye_color_2 = 1;
e.drakkin_heritage = 0;
e.drakkin_tattoo = 0;
e.drakkin_details = 0;
e.ac = 0;
e.atk = 0;
e.hp = 0;
e.mana = 0;
e.str = 75;
e.sta = 75;
e.cha = 75;
e.dex = 75;
e.int_ = 75;
e.agi = 75;
e.wis = 75;
e.fire = 0;
e.cold = 0;
e.magic = 0;
e.poison = 0;
e.disease = 0;
e.corruption = 0;
e.show_helm = 0;
e.follow_distance = 200;
e.stop_melee_level = 255;
e.expansion_bitmask = -1;
e.enforce_spell_settings = 0;
e.archery_setting = 0;
return e;
}
static BotData GetBotData(
const std::vector<BotData> &bot_datas,
int bot_data_id
)
{
for (auto &bot_data : bot_datas) {
if (bot_data.bot_id == bot_data_id) {
return bot_data;
}
}
return NewEntity();
}
static BotData FindOne(
Database& db,
int bot_data_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
bot_data_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotData e{};
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.owner_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.spells_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.name = row[3] ? row[3] : "";
e.last_name = row[4] ? row[4] : "";
e.title = row[5] ? row[5] : "";
e.suffix = row[6] ? row[6] : "";
e.zone_id = static_cast<int16_t>(atoi(row[7]));
e.gender = static_cast<int8_t>(atoi(row[8]));
e.race = static_cast<int16_t>(atoi(row[9]));
e.class_ = static_cast<int8_t>(atoi(row[10]));
e.level = static_cast<uint8_t>(strtoul(row[11], nullptr, 10));
e.deity = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.creation_day = static_cast<uint32_t>(strtoul(row[13], nullptr, 10));
e.last_spawn = static_cast<uint32_t>(strtoul(row[14], nullptr, 10));
e.time_spawned = static_cast<uint32_t>(strtoul(row[15], nullptr, 10));
e.size = strtof(row[16], nullptr);
e.face = static_cast<int32_t>(atoi(row[17]));
e.hair_color = static_cast<int32_t>(atoi(row[18]));
e.hair_style = static_cast<int32_t>(atoi(row[19]));
e.beard = static_cast<int32_t>(atoi(row[20]));
e.beard_color = static_cast<int32_t>(atoi(row[21]));
e.eye_color_1 = static_cast<int32_t>(atoi(row[22]));
e.eye_color_2 = static_cast<int32_t>(atoi(row[23]));
e.drakkin_heritage = static_cast<int32_t>(atoi(row[24]));
e.drakkin_tattoo = static_cast<int32_t>(atoi(row[25]));
e.drakkin_details = static_cast<int32_t>(atoi(row[26]));
e.ac = static_cast<int16_t>(atoi(row[27]));
e.atk = static_cast<int32_t>(atoi(row[28]));
e.hp = static_cast<int32_t>(atoi(row[29]));
e.mana = static_cast<int32_t>(atoi(row[30]));
e.str = static_cast<int32_t>(atoi(row[31]));
e.sta = static_cast<int32_t>(atoi(row[32]));
e.cha = static_cast<int32_t>(atoi(row[33]));
e.dex = static_cast<int32_t>(atoi(row[34]));
e.int_ = static_cast<int32_t>(atoi(row[35]));
e.agi = static_cast<int32_t>(atoi(row[36]));
e.wis = static_cast<int32_t>(atoi(row[37]));
e.fire = static_cast<int16_t>(atoi(row[38]));
e.cold = static_cast<int16_t>(atoi(row[39]));
e.magic = static_cast<int16_t>(atoi(row[40]));
e.poison = static_cast<int16_t>(atoi(row[41]));
e.disease = static_cast<int16_t>(atoi(row[42]));
e.corruption = static_cast<int16_t>(atoi(row[43]));
e.show_helm = static_cast<uint32_t>(strtoul(row[44], nullptr, 10));
e.follow_distance = static_cast<uint32_t>(strtoul(row[45], nullptr, 10));
e.stop_melee_level = static_cast<uint8_t>(strtoul(row[46], nullptr, 10));
e.expansion_bitmask = static_cast<int32_t>(atoi(row[47]));
e.enforce_spell_settings = static_cast<uint8_t>(strtoul(row[48], nullptr, 10));
e.archery_setting = static_cast<uint8_t>(strtoul(row[49], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_data_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_data_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotData &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.owner_id));
v.push_back(columns[2] + " = " + std::to_string(e.spells_id));
v.push_back(columns[3] + " = '" + Strings::Escape(e.name) + "'");
v.push_back(columns[4] + " = '" + Strings::Escape(e.last_name) + "'");
v.push_back(columns[5] + " = '" + Strings::Escape(e.title) + "'");
v.push_back(columns[6] + " = '" + Strings::Escape(e.suffix) + "'");
v.push_back(columns[7] + " = " + std::to_string(e.zone_id));
v.push_back(columns[8] + " = " + std::to_string(e.gender));
v.push_back(columns[9] + " = " + std::to_string(e.race));
v.push_back(columns[10] + " = " + std::to_string(e.class_));
v.push_back(columns[11] + " = " + std::to_string(e.level));
v.push_back(columns[12] + " = " + std::to_string(e.deity));
v.push_back(columns[13] + " = " + std::to_string(e.creation_day));
v.push_back(columns[14] + " = " + std::to_string(e.last_spawn));
v.push_back(columns[15] + " = " + std::to_string(e.time_spawned));
v.push_back(columns[16] + " = " + std::to_string(e.size));
v.push_back(columns[17] + " = " + std::to_string(e.face));
v.push_back(columns[18] + " = " + std::to_string(e.hair_color));
v.push_back(columns[19] + " = " + std::to_string(e.hair_style));
v.push_back(columns[20] + " = " + std::to_string(e.beard));
v.push_back(columns[21] + " = " + std::to_string(e.beard_color));
v.push_back(columns[22] + " = " + std::to_string(e.eye_color_1));
v.push_back(columns[23] + " = " + std::to_string(e.eye_color_2));
v.push_back(columns[24] + " = " + std::to_string(e.drakkin_heritage));
v.push_back(columns[25] + " = " + std::to_string(e.drakkin_tattoo));
v.push_back(columns[26] + " = " + std::to_string(e.drakkin_details));
v.push_back(columns[27] + " = " + std::to_string(e.ac));
v.push_back(columns[28] + " = " + std::to_string(e.atk));
v.push_back(columns[29] + " = " + std::to_string(e.hp));
v.push_back(columns[30] + " = " + std::to_string(e.mana));
v.push_back(columns[31] + " = " + std::to_string(e.str));
v.push_back(columns[32] + " = " + std::to_string(e.sta));
v.push_back(columns[33] + " = " + std::to_string(e.cha));
v.push_back(columns[34] + " = " + std::to_string(e.dex));
v.push_back(columns[35] + " = " + std::to_string(e.int_));
v.push_back(columns[36] + " = " + std::to_string(e.agi));
v.push_back(columns[37] + " = " + std::to_string(e.wis));
v.push_back(columns[38] + " = " + std::to_string(e.fire));
v.push_back(columns[39] + " = " + std::to_string(e.cold));
v.push_back(columns[40] + " = " + std::to_string(e.magic));
v.push_back(columns[41] + " = " + std::to_string(e.poison));
v.push_back(columns[42] + " = " + std::to_string(e.disease));
v.push_back(columns[43] + " = " + std::to_string(e.corruption));
v.push_back(columns[44] + " = " + std::to_string(e.show_helm));
v.push_back(columns[45] + " = " + std::to_string(e.follow_distance));
v.push_back(columns[46] + " = " + std::to_string(e.stop_melee_level));
v.push_back(columns[47] + " = " + std::to_string(e.expansion_bitmask));
v.push_back(columns[48] + " = " + std::to_string(e.enforce_spell_settings));
v.push_back(columns[49] + " = " + std::to_string(e.archery_setting));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.bot_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotData InsertOne(
Database& db,
BotData e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.owner_id));
v.push_back(std::to_string(e.spells_id));
v.push_back("'" + Strings::Escape(e.name) + "'");
v.push_back("'" + Strings::Escape(e.last_name) + "'");
v.push_back("'" + Strings::Escape(e.title) + "'");
v.push_back("'" + Strings::Escape(e.suffix) + "'");
v.push_back(std::to_string(e.zone_id));
v.push_back(std::to_string(e.gender));
v.push_back(std::to_string(e.race));
v.push_back(std::to_string(e.class_));
v.push_back(std::to_string(e.level));
v.push_back(std::to_string(e.deity));
v.push_back(std::to_string(e.creation_day));
v.push_back(std::to_string(e.last_spawn));
v.push_back(std::to_string(e.time_spawned));
v.push_back(std::to_string(e.size));
v.push_back(std::to_string(e.face));
v.push_back(std::to_string(e.hair_color));
v.push_back(std::to_string(e.hair_style));
v.push_back(std::to_string(e.beard));
v.push_back(std::to_string(e.beard_color));
v.push_back(std::to_string(e.eye_color_1));
v.push_back(std::to_string(e.eye_color_2));
v.push_back(std::to_string(e.drakkin_heritage));
v.push_back(std::to_string(e.drakkin_tattoo));
v.push_back(std::to_string(e.drakkin_details));
v.push_back(std::to_string(e.ac));
v.push_back(std::to_string(e.atk));
v.push_back(std::to_string(e.hp));
v.push_back(std::to_string(e.mana));
v.push_back(std::to_string(e.str));
v.push_back(std::to_string(e.sta));
v.push_back(std::to_string(e.cha));
v.push_back(std::to_string(e.dex));
v.push_back(std::to_string(e.int_));
v.push_back(std::to_string(e.agi));
v.push_back(std::to_string(e.wis));
v.push_back(std::to_string(e.fire));
v.push_back(std::to_string(e.cold));
v.push_back(std::to_string(e.magic));
v.push_back(std::to_string(e.poison));
v.push_back(std::to_string(e.disease));
v.push_back(std::to_string(e.corruption));
v.push_back(std::to_string(e.show_helm));
v.push_back(std::to_string(e.follow_distance));
v.push_back(std::to_string(e.stop_melee_level));
v.push_back(std::to_string(e.expansion_bitmask));
v.push_back(std::to_string(e.enforce_spell_settings));
v.push_back(std::to_string(e.archery_setting));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.bot_id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotData> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.owner_id));
v.push_back(std::to_string(e.spells_id));
v.push_back("'" + Strings::Escape(e.name) + "'");
v.push_back("'" + Strings::Escape(e.last_name) + "'");
v.push_back("'" + Strings::Escape(e.title) + "'");
v.push_back("'" + Strings::Escape(e.suffix) + "'");
v.push_back(std::to_string(e.zone_id));
v.push_back(std::to_string(e.gender));
v.push_back(std::to_string(e.race));
v.push_back(std::to_string(e.class_));
v.push_back(std::to_string(e.level));
v.push_back(std::to_string(e.deity));
v.push_back(std::to_string(e.creation_day));
v.push_back(std::to_string(e.last_spawn));
v.push_back(std::to_string(e.time_spawned));
v.push_back(std::to_string(e.size));
v.push_back(std::to_string(e.face));
v.push_back(std::to_string(e.hair_color));
v.push_back(std::to_string(e.hair_style));
v.push_back(std::to_string(e.beard));
v.push_back(std::to_string(e.beard_color));
v.push_back(std::to_string(e.eye_color_1));
v.push_back(std::to_string(e.eye_color_2));
v.push_back(std::to_string(e.drakkin_heritage));
v.push_back(std::to_string(e.drakkin_tattoo));
v.push_back(std::to_string(e.drakkin_details));
v.push_back(std::to_string(e.ac));
v.push_back(std::to_string(e.atk));
v.push_back(std::to_string(e.hp));
v.push_back(std::to_string(e.mana));
v.push_back(std::to_string(e.str));
v.push_back(std::to_string(e.sta));
v.push_back(std::to_string(e.cha));
v.push_back(std::to_string(e.dex));
v.push_back(std::to_string(e.int_));
v.push_back(std::to_string(e.agi));
v.push_back(std::to_string(e.wis));
v.push_back(std::to_string(e.fire));
v.push_back(std::to_string(e.cold));
v.push_back(std::to_string(e.magic));
v.push_back(std::to_string(e.poison));
v.push_back(std::to_string(e.disease));
v.push_back(std::to_string(e.corruption));
v.push_back(std::to_string(e.show_helm));
v.push_back(std::to_string(e.follow_distance));
v.push_back(std::to_string(e.stop_melee_level));
v.push_back(std::to_string(e.expansion_bitmask));
v.push_back(std::to_string(e.enforce_spell_settings));
v.push_back(std::to_string(e.archery_setting));
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<BotData> All(Database& db)
{
std::vector<BotData> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotData e{};
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.owner_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.spells_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.name = row[3] ? row[3] : "";
e.last_name = row[4] ? row[4] : "";
e.title = row[5] ? row[5] : "";
e.suffix = row[6] ? row[6] : "";
e.zone_id = static_cast<int16_t>(atoi(row[7]));
e.gender = static_cast<int8_t>(atoi(row[8]));
e.race = static_cast<int16_t>(atoi(row[9]));
e.class_ = static_cast<int8_t>(atoi(row[10]));
e.level = static_cast<uint8_t>(strtoul(row[11], nullptr, 10));
e.deity = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.creation_day = static_cast<uint32_t>(strtoul(row[13], nullptr, 10));
e.last_spawn = static_cast<uint32_t>(strtoul(row[14], nullptr, 10));
e.time_spawned = static_cast<uint32_t>(strtoul(row[15], nullptr, 10));
e.size = strtof(row[16], nullptr);
e.face = static_cast<int32_t>(atoi(row[17]));
e.hair_color = static_cast<int32_t>(atoi(row[18]));
e.hair_style = static_cast<int32_t>(atoi(row[19]));
e.beard = static_cast<int32_t>(atoi(row[20]));
e.beard_color = static_cast<int32_t>(atoi(row[21]));
e.eye_color_1 = static_cast<int32_t>(atoi(row[22]));
e.eye_color_2 = static_cast<int32_t>(atoi(row[23]));
e.drakkin_heritage = static_cast<int32_t>(atoi(row[24]));
e.drakkin_tattoo = static_cast<int32_t>(atoi(row[25]));
e.drakkin_details = static_cast<int32_t>(atoi(row[26]));
e.ac = static_cast<int16_t>(atoi(row[27]));
e.atk = static_cast<int32_t>(atoi(row[28]));
e.hp = static_cast<int32_t>(atoi(row[29]));
e.mana = static_cast<int32_t>(atoi(row[30]));
e.str = static_cast<int32_t>(atoi(row[31]));
e.sta = static_cast<int32_t>(atoi(row[32]));
e.cha = static_cast<int32_t>(atoi(row[33]));
e.dex = static_cast<int32_t>(atoi(row[34]));
e.int_ = static_cast<int32_t>(atoi(row[35]));
e.agi = static_cast<int32_t>(atoi(row[36]));
e.wis = static_cast<int32_t>(atoi(row[37]));
e.fire = static_cast<int16_t>(atoi(row[38]));
e.cold = static_cast<int16_t>(atoi(row[39]));
e.magic = static_cast<int16_t>(atoi(row[40]));
e.poison = static_cast<int16_t>(atoi(row[41]));
e.disease = static_cast<int16_t>(atoi(row[42]));
e.corruption = static_cast<int16_t>(atoi(row[43]));
e.show_helm = static_cast<uint32_t>(strtoul(row[44], nullptr, 10));
e.follow_distance = static_cast<uint32_t>(strtoul(row[45], nullptr, 10));
e.stop_melee_level = static_cast<uint8_t>(strtoul(row[46], nullptr, 10));
e.expansion_bitmask = static_cast<int32_t>(atoi(row[47]));
e.enforce_spell_settings = static_cast<uint8_t>(strtoul(row[48], nullptr, 10));
e.archery_setting = static_cast<uint8_t>(strtoul(row[49], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotData> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotData> 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) {
BotData e{};
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.owner_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.spells_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.name = row[3] ? row[3] : "";
e.last_name = row[4] ? row[4] : "";
e.title = row[5] ? row[5] : "";
e.suffix = row[6] ? row[6] : "";
e.zone_id = static_cast<int16_t>(atoi(row[7]));
e.gender = static_cast<int8_t>(atoi(row[8]));
e.race = static_cast<int16_t>(atoi(row[9]));
e.class_ = static_cast<int8_t>(atoi(row[10]));
e.level = static_cast<uint8_t>(strtoul(row[11], nullptr, 10));
e.deity = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.creation_day = static_cast<uint32_t>(strtoul(row[13], nullptr, 10));
e.last_spawn = static_cast<uint32_t>(strtoul(row[14], nullptr, 10));
e.time_spawned = static_cast<uint32_t>(strtoul(row[15], nullptr, 10));
e.size = strtof(row[16], nullptr);
e.face = static_cast<int32_t>(atoi(row[17]));
e.hair_color = static_cast<int32_t>(atoi(row[18]));
e.hair_style = static_cast<int32_t>(atoi(row[19]));
e.beard = static_cast<int32_t>(atoi(row[20]));
e.beard_color = static_cast<int32_t>(atoi(row[21]));
e.eye_color_1 = static_cast<int32_t>(atoi(row[22]));
e.eye_color_2 = static_cast<int32_t>(atoi(row[23]));
e.drakkin_heritage = static_cast<int32_t>(atoi(row[24]));
e.drakkin_tattoo = static_cast<int32_t>(atoi(row[25]));
e.drakkin_details = static_cast<int32_t>(atoi(row[26]));
e.ac = static_cast<int16_t>(atoi(row[27]));
e.atk = static_cast<int32_t>(atoi(row[28]));
e.hp = static_cast<int32_t>(atoi(row[29]));
e.mana = static_cast<int32_t>(atoi(row[30]));
e.str = static_cast<int32_t>(atoi(row[31]));
e.sta = static_cast<int32_t>(atoi(row[32]));
e.cha = static_cast<int32_t>(atoi(row[33]));
e.dex = static_cast<int32_t>(atoi(row[34]));
e.int_ = static_cast<int32_t>(atoi(row[35]));
e.agi = static_cast<int32_t>(atoi(row[36]));
e.wis = static_cast<int32_t>(atoi(row[37]));
e.fire = static_cast<int16_t>(atoi(row[38]));
e.cold = static_cast<int16_t>(atoi(row[39]));
e.magic = static_cast<int16_t>(atoi(row[40]));
e.poison = static_cast<int16_t>(atoi(row[41]));
e.disease = static_cast<int16_t>(atoi(row[42]));
e.corruption = static_cast<int16_t>(atoi(row[43]));
e.show_helm = static_cast<uint32_t>(strtoul(row[44], nullptr, 10));
e.follow_distance = static_cast<uint32_t>(strtoul(row[45], nullptr, 10));
e.stop_melee_level = static_cast<uint8_t>(strtoul(row[46], nullptr, 10));
e.expansion_bitmask = static_cast<int32_t>(atoi(row[47]));
e.enforce_spell_settings = static_cast<uint8_t>(strtoul(row[48], nullptr, 10));
e.archery_setting = static_cast<uint8_t>(strtoul(row[49], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_BOT_DATA_REPOSITORY_H
@@ -0,0 +1,342 @@
/**
* 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_GROUP_MEMBERS_REPOSITORY_H
#define EQEMU_BASE_BOT_GROUP_MEMBERS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotGroupMembersRepository {
public:
struct BotGroupMembers {
uint32_t group_members_index;
uint32_t groups_index;
uint32_t bot_id;
};
static std::string PrimaryKey()
{
return std::string("group_members_index");
}
static std::vector<std::string> Columns()
{
return {
"group_members_index",
"groups_index",
"bot_id",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"group_members_index",
"groups_index",
"bot_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("bot_group_members");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotGroupMembers NewEntity()
{
BotGroupMembers e{};
e.group_members_index = 0;
e.groups_index = 0;
e.bot_id = 0;
return e;
}
static BotGroupMembers GetBotGroupMembers(
const std::vector<BotGroupMembers> &bot_group_memberss,
int bot_group_members_id
)
{
for (auto &bot_group_members : bot_group_memberss) {
if (bot_group_members.group_members_index == bot_group_members_id) {
return bot_group_members;
}
}
return NewEntity();
}
static BotGroupMembers FindOne(
Database& db,
int bot_group_members_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_group_members_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotGroupMembers e{};
e.group_members_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.groups_index = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_group_members_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_group_members_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotGroupMembers &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.groups_index));
v.push_back(columns[2] + " = " + std::to_string(e.bot_id));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.group_members_index
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotGroupMembers InsertOne(
Database& db,
BotGroupMembers e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.group_members_index));
v.push_back(std::to_string(e.groups_index));
v.push_back(std::to_string(e.bot_id));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.group_members_index = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotGroupMembers> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.group_members_index));
v.push_back(std::to_string(e.groups_index));
v.push_back(std::to_string(e.bot_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<BotGroupMembers> All(Database& db)
{
std::vector<BotGroupMembers> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotGroupMembers e{};
e.group_members_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.groups_index = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotGroupMembers> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotGroupMembers> 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) {
BotGroupMembers e{};
e.group_members_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.groups_index = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_BOT_GROUP_MEMBERS_REPOSITORY_H
@@ -0,0 +1,352 @@
/**
* 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_GROUPS_REPOSITORY_H
#define EQEMU_BASE_BOT_GROUPS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotGroupsRepository {
public:
struct BotGroups {
uint32_t groups_index;
uint32_t group_leader_id;
std::string group_name;
uint8_t auto_spawn;
};
static std::string PrimaryKey()
{
return std::string("groups_index");
}
static std::vector<std::string> Columns()
{
return {
"groups_index",
"group_leader_id",
"group_name",
"auto_spawn",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"groups_index",
"group_leader_id",
"group_name",
"auto_spawn",
};
}
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_groups");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotGroups NewEntity()
{
BotGroups e{};
e.groups_index = 0;
e.group_leader_id = 0;
e.group_name = "";
e.auto_spawn = 0;
return e;
}
static BotGroups GetBotGroups(
const std::vector<BotGroups> &bot_groupss,
int bot_groups_id
)
{
for (auto &bot_groups : bot_groupss) {
if (bot_groups.groups_index == bot_groups_id) {
return bot_groups;
}
}
return NewEntity();
}
static BotGroups FindOne(
Database& db,
int bot_groups_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_groups_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotGroups e{};
e.groups_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.group_leader_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.group_name = row[2] ? row[2] : "";
e.auto_spawn = static_cast<uint8_t>(strtoul(row[3], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_groups_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_groups_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotGroups &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.group_leader_id));
v.push_back(columns[2] + " = '" + Strings::Escape(e.group_name) + "'");
v.push_back(columns[3] + " = " + std::to_string(e.auto_spawn));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.groups_index
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotGroups InsertOne(
Database& db,
BotGroups e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.groups_index));
v.push_back(std::to_string(e.group_leader_id));
v.push_back("'" + Strings::Escape(e.group_name) + "'");
v.push_back(std::to_string(e.auto_spawn));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.groups_index = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotGroups> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.groups_index));
v.push_back(std::to_string(e.group_leader_id));
v.push_back("'" + Strings::Escape(e.group_name) + "'");
v.push_back(std::to_string(e.auto_spawn));
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<BotGroups> All(Database& db)
{
std::vector<BotGroups> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotGroups e{};
e.groups_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.group_leader_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.group_name = row[2] ? row[2] : "";
e.auto_spawn = static_cast<uint8_t>(strtoul(row[3], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotGroups> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotGroups> 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) {
BotGroups e{};
e.groups_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.group_leader_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.group_name = row[2] ? row[2] : "";
e.auto_spawn = static_cast<uint8_t>(strtoul(row[3], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_BOT_GROUPS_REPOSITORY_H
@@ -0,0 +1,403 @@
/**
* 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_GUILD_MEMBERS_REPOSITORY_H
#define EQEMU_BASE_BOT_GUILD_MEMBERS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotGuildMembersRepository {
public:
struct BotGuildMembers {
int32_t bot_id;
uint32_t guild_id;
uint8_t rank;
uint8_t tribute_enable;
uint32_t total_tribute;
uint32_t last_tribute;
uint8_t banker;
std::string public_note;
uint8_t alt;
};
static std::string PrimaryKey()
{
return std::string("bot_id");
}
static std::vector<std::string> Columns()
{
return {
"bot_id",
"guild_id",
"rank",
"tribute_enable",
"total_tribute",
"last_tribute",
"banker",
"public_note",
"alt",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"bot_id",
"guild_id",
"rank",
"tribute_enable",
"total_tribute",
"last_tribute",
"banker",
"public_note",
"alt",
};
}
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_guild_members");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotGuildMembers NewEntity()
{
BotGuildMembers e{};
e.bot_id = 0;
e.guild_id = 0;
e.rank = 0;
e.tribute_enable = 0;
e.total_tribute = 0;
e.last_tribute = 0;
e.banker = 0;
e.public_note = "";
e.alt = 0;
return e;
}
static BotGuildMembers GetBotGuildMembers(
const std::vector<BotGuildMembers> &bot_guild_memberss,
int bot_guild_members_id
)
{
for (auto &bot_guild_members : bot_guild_memberss) {
if (bot_guild_members.bot_id == bot_guild_members_id) {
return bot_guild_members;
}
}
return NewEntity();
}
static BotGuildMembers FindOne(
Database& db,
int bot_guild_members_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_guild_members_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotGuildMembers e{};
e.bot_id = static_cast<int32_t>(atoi(row[0]));
e.guild_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.rank = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
e.tribute_enable = static_cast<uint8_t>(strtoul(row[3], nullptr, 10));
e.total_tribute = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.last_tribute = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.banker = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.public_note = row[7] ? row[7] : "";
e.alt = static_cast<uint8_t>(strtoul(row[8], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_guild_members_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_guild_members_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotGuildMembers &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[0] + " = " + std::to_string(e.bot_id));
v.push_back(columns[1] + " = " + std::to_string(e.guild_id));
v.push_back(columns[2] + " = " + std::to_string(e.rank));
v.push_back(columns[3] + " = " + std::to_string(e.tribute_enable));
v.push_back(columns[4] + " = " + std::to_string(e.total_tribute));
v.push_back(columns[5] + " = " + std::to_string(e.last_tribute));
v.push_back(columns[6] + " = " + std::to_string(e.banker));
v.push_back(columns[7] + " = '" + Strings::Escape(e.public_note) + "'");
v.push_back(columns[8] + " = " + std::to_string(e.alt));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.bot_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotGuildMembers InsertOne(
Database& db,
BotGuildMembers e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.tribute_enable));
v.push_back(std::to_string(e.total_tribute));
v.push_back(std::to_string(e.last_tribute));
v.push_back(std::to_string(e.banker));
v.push_back("'" + Strings::Escape(e.public_note) + "'");
v.push_back(std::to_string(e.alt));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.bot_id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotGuildMembers> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.tribute_enable));
v.push_back(std::to_string(e.total_tribute));
v.push_back(std::to_string(e.last_tribute));
v.push_back(std::to_string(e.banker));
v.push_back("'" + Strings::Escape(e.public_note) + "'");
v.push_back(std::to_string(e.alt));
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<BotGuildMembers> All(Database& db)
{
std::vector<BotGuildMembers> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotGuildMembers e{};
e.bot_id = static_cast<int32_t>(atoi(row[0]));
e.guild_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.rank = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
e.tribute_enable = static_cast<uint8_t>(strtoul(row[3], nullptr, 10));
e.total_tribute = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.last_tribute = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.banker = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.public_note = row[7] ? row[7] : "";
e.alt = static_cast<uint8_t>(strtoul(row[8], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotGuildMembers> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotGuildMembers> 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) {
BotGuildMembers e{};
e.bot_id = static_cast<int32_t>(atoi(row[0]));
e.guild_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.rank = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
e.tribute_enable = static_cast<uint8_t>(strtoul(row[3], nullptr, 10));
e.total_tribute = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.last_tribute = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.banker = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.public_note = row[7] ? row[7] : "";
e.alt = static_cast<uint8_t>(strtoul(row[8], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_BOT_GUILD_MEMBERS_REPOSITORY_H
@@ -0,0 +1,342 @@
/**
* 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_HEAL_ROTATION_MEMBERS_REPOSITORY_H
#define EQEMU_BASE_BOT_HEAL_ROTATION_MEMBERS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotHealRotationMembersRepository {
public:
struct BotHealRotationMembers {
uint32_t member_index;
uint32_t heal_rotation_index;
uint32_t bot_id;
};
static std::string PrimaryKey()
{
return std::string("member_index");
}
static std::vector<std::string> Columns()
{
return {
"member_index",
"heal_rotation_index",
"bot_id",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"member_index",
"heal_rotation_index",
"bot_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("bot_heal_rotation_members");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotHealRotationMembers NewEntity()
{
BotHealRotationMembers e{};
e.member_index = 0;
e.heal_rotation_index = 0;
e.bot_id = 0;
return e;
}
static BotHealRotationMembers GetBotHealRotationMembers(
const std::vector<BotHealRotationMembers> &bot_heal_rotation_memberss,
int bot_heal_rotation_members_id
)
{
for (auto &bot_heal_rotation_members : bot_heal_rotation_memberss) {
if (bot_heal_rotation_members.member_index == bot_heal_rotation_members_id) {
return bot_heal_rotation_members;
}
}
return NewEntity();
}
static BotHealRotationMembers FindOne(
Database& db,
int bot_heal_rotation_members_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_heal_rotation_members_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotHealRotationMembers e{};
e.member_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.heal_rotation_index = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_heal_rotation_members_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_heal_rotation_members_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotHealRotationMembers &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.heal_rotation_index));
v.push_back(columns[2] + " = " + std::to_string(e.bot_id));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.member_index
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotHealRotationMembers InsertOne(
Database& db,
BotHealRotationMembers e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.member_index));
v.push_back(std::to_string(e.heal_rotation_index));
v.push_back(std::to_string(e.bot_id));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.member_index = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotHealRotationMembers> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.member_index));
v.push_back(std::to_string(e.heal_rotation_index));
v.push_back(std::to_string(e.bot_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<BotHealRotationMembers> All(Database& db)
{
std::vector<BotHealRotationMembers> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotHealRotationMembers e{};
e.member_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.heal_rotation_index = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotHealRotationMembers> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotHealRotationMembers> 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) {
BotHealRotationMembers e{};
e.member_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.heal_rotation_index = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_BOT_HEAL_ROTATION_MEMBERS_REPOSITORY_H
@@ -0,0 +1,342 @@
/**
* 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_HEAL_ROTATION_TARGETS_REPOSITORY_H
#define EQEMU_BASE_BOT_HEAL_ROTATION_TARGETS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotHealRotationTargetsRepository {
public:
struct BotHealRotationTargets {
uint32_t target_index;
uint32_t heal_rotation_index;
std::string target_name;
};
static std::string PrimaryKey()
{
return std::string("target_index");
}
static std::vector<std::string> Columns()
{
return {
"target_index",
"heal_rotation_index",
"target_name",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"target_index",
"heal_rotation_index",
"target_name",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("bot_heal_rotation_targets");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotHealRotationTargets NewEntity()
{
BotHealRotationTargets e{};
e.target_index = 0;
e.heal_rotation_index = 0;
e.target_name = "";
return e;
}
static BotHealRotationTargets GetBotHealRotationTargets(
const std::vector<BotHealRotationTargets> &bot_heal_rotation_targetss,
int bot_heal_rotation_targets_id
)
{
for (auto &bot_heal_rotation_targets : bot_heal_rotation_targetss) {
if (bot_heal_rotation_targets.target_index == bot_heal_rotation_targets_id) {
return bot_heal_rotation_targets;
}
}
return NewEntity();
}
static BotHealRotationTargets FindOne(
Database& db,
int bot_heal_rotation_targets_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_heal_rotation_targets_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotHealRotationTargets e{};
e.target_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.heal_rotation_index = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.target_name = row[2] ? row[2] : "";
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_heal_rotation_targets_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_heal_rotation_targets_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotHealRotationTargets &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.heal_rotation_index));
v.push_back(columns[2] + " = '" + Strings::Escape(e.target_name) + "'");
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.target_index
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotHealRotationTargets InsertOne(
Database& db,
BotHealRotationTargets e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.target_index));
v.push_back(std::to_string(e.heal_rotation_index));
v.push_back("'" + Strings::Escape(e.target_name) + "'");
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.target_index = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotHealRotationTargets> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.target_index));
v.push_back(std::to_string(e.heal_rotation_index));
v.push_back("'" + Strings::Escape(e.target_name) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<BotHealRotationTargets> All(Database& db)
{
std::vector<BotHealRotationTargets> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotHealRotationTargets e{};
e.target_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.heal_rotation_index = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.target_name = row[2] ? row[2] : "";
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotHealRotationTargets> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotHealRotationTargets> 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) {
BotHealRotationTargets e{};
e.target_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.heal_rotation_index = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.target_name = row[2] ? 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_BOT_HEAL_ROTATION_TARGETS_REPOSITORY_H
@@ -0,0 +1,442 @@
/**
* 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_HEAL_ROTATIONS_REPOSITORY_H
#define EQEMU_BASE_BOT_HEAL_ROTATIONS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotHealRotationsRepository {
public:
struct BotHealRotations {
uint32_t heal_rotation_index;
uint32_t bot_id;
uint32_t interval;
uint32_t fast_heals;
uint32_t adaptive_targeting;
uint32_t casting_override;
std::string safe_hp_base;
std::string safe_hp_cloth;
std::string safe_hp_leather;
std::string safe_hp_chain;
std::string safe_hp_plate;
std::string critical_hp_base;
std::string critical_hp_cloth;
std::string critical_hp_leather;
std::string critical_hp_chain;
std::string critical_hp_plate;
};
static std::string PrimaryKey()
{
return std::string("heal_rotation_index");
}
static std::vector<std::string> Columns()
{
return {
"heal_rotation_index",
"bot_id",
"interval",
"fast_heals",
"adaptive_targeting",
"casting_override",
"safe_hp_base",
"safe_hp_cloth",
"safe_hp_leather",
"safe_hp_chain",
"safe_hp_plate",
"critical_hp_base",
"critical_hp_cloth",
"critical_hp_leather",
"critical_hp_chain",
"critical_hp_plate",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"heal_rotation_index",
"bot_id",
"interval",
"fast_heals",
"adaptive_targeting",
"casting_override",
"safe_hp_base",
"safe_hp_cloth",
"safe_hp_leather",
"safe_hp_chain",
"safe_hp_plate",
"critical_hp_base",
"critical_hp_cloth",
"critical_hp_leather",
"critical_hp_chain",
"critical_hp_plate",
};
}
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_heal_rotations");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotHealRotations NewEntity()
{
BotHealRotations e{};
e.heal_rotation_index = 0;
e.bot_id = 0;
e.interval = 0;
e.fast_heals = 0;
e.adaptive_targeting = 0;
e.casting_override = 0;
e.safe_hp_base = 0;
e.safe_hp_cloth = 0;
e.safe_hp_leather = 0;
e.safe_hp_chain = 0;
e.safe_hp_plate = 0;
e.critical_hp_base = 0;
e.critical_hp_cloth = 0;
e.critical_hp_leather = 0;
e.critical_hp_chain = 0;
e.critical_hp_plate = 0;
return e;
}
static BotHealRotations GetBotHealRotations(
const std::vector<BotHealRotations> &bot_heal_rotationss,
int bot_heal_rotations_id
)
{
for (auto &bot_heal_rotations : bot_heal_rotationss) {
if (bot_heal_rotations.heal_rotation_index == bot_heal_rotations_id) {
return bot_heal_rotations;
}
}
return NewEntity();
}
static BotHealRotations FindOne(
Database& db,
int bot_heal_rotations_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_heal_rotations_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotHealRotations e{};
e.heal_rotation_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.interval = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.fast_heals = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.adaptive_targeting = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.casting_override = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_heal_rotations_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_heal_rotations_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotHealRotations &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.bot_id));
v.push_back(columns[2] + " = " + std::to_string(e.interval));
v.push_back(columns[3] + " = " + std::to_string(e.fast_heals));
v.push_back(columns[4] + " = " + std::to_string(e.adaptive_targeting));
v.push_back(columns[5] + " = " + std::to_string(e.casting_override));
v.push_back(columns[6] + " = " + std::to_string(e.safe_hp_base));
v.push_back(columns[7] + " = " + std::to_string(e.safe_hp_cloth));
v.push_back(columns[8] + " = " + std::to_string(e.safe_hp_leather));
v.push_back(columns[9] + " = " + std::to_string(e.safe_hp_chain));
v.push_back(columns[10] + " = " + std::to_string(e.safe_hp_plate));
v.push_back(columns[11] + " = " + std::to_string(e.critical_hp_base));
v.push_back(columns[12] + " = " + std::to_string(e.critical_hp_cloth));
v.push_back(columns[13] + " = " + std::to_string(e.critical_hp_leather));
v.push_back(columns[14] + " = " + std::to_string(e.critical_hp_chain));
v.push_back(columns[15] + " = " + std::to_string(e.critical_hp_plate));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.heal_rotation_index
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotHealRotations InsertOne(
Database& db,
BotHealRotations e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.heal_rotation_index));
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.interval));
v.push_back(std::to_string(e.fast_heals));
v.push_back(std::to_string(e.adaptive_targeting));
v.push_back(std::to_string(e.casting_override));
v.push_back(std::to_string(e.safe_hp_base));
v.push_back(std::to_string(e.safe_hp_cloth));
v.push_back(std::to_string(e.safe_hp_leather));
v.push_back(std::to_string(e.safe_hp_chain));
v.push_back(std::to_string(e.safe_hp_plate));
v.push_back(std::to_string(e.critical_hp_base));
v.push_back(std::to_string(e.critical_hp_cloth));
v.push_back(std::to_string(e.critical_hp_leather));
v.push_back(std::to_string(e.critical_hp_chain));
v.push_back(std::to_string(e.critical_hp_plate));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.heal_rotation_index = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotHealRotations> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.heal_rotation_index));
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.interval));
v.push_back(std::to_string(e.fast_heals));
v.push_back(std::to_string(e.adaptive_targeting));
v.push_back(std::to_string(e.casting_override));
v.push_back(std::to_string(e.safe_hp_base));
v.push_back(std::to_string(e.safe_hp_cloth));
v.push_back(std::to_string(e.safe_hp_leather));
v.push_back(std::to_string(e.safe_hp_chain));
v.push_back(std::to_string(e.safe_hp_plate));
v.push_back(std::to_string(e.critical_hp_base));
v.push_back(std::to_string(e.critical_hp_cloth));
v.push_back(std::to_string(e.critical_hp_leather));
v.push_back(std::to_string(e.critical_hp_chain));
v.push_back(std::to_string(e.critical_hp_plate));
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<BotHealRotations> All(Database& db)
{
std::vector<BotHealRotations> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotHealRotations e{};
e.heal_rotation_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.interval = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.fast_heals = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.adaptive_targeting = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.casting_override = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotHealRotations> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotHealRotations> 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) {
BotHealRotations e{};
e.heal_rotation_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.interval = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.fast_heals = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.adaptive_targeting = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.casting_override = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_BOT_HEAL_ROTATIONS_REPOSITORY_H
@@ -0,0 +1,333 @@
/**
* 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_INSPECT_MESSAGES_REPOSITORY_H
#define EQEMU_BASE_BOT_INSPECT_MESSAGES_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotInspectMessagesRepository {
public:
struct BotInspectMessages {
uint32_t bot_id;
std::string inspect_message;
};
static std::string PrimaryKey()
{
return std::string("bot_id");
}
static std::vector<std::string> Columns()
{
return {
"bot_id",
"inspect_message",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"bot_id",
"inspect_message",
};
}
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_inspect_messages");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotInspectMessages NewEntity()
{
BotInspectMessages e{};
e.bot_id = 0;
e.inspect_message = "";
return e;
}
static BotInspectMessages GetBotInspectMessages(
const std::vector<BotInspectMessages> &bot_inspect_messagess,
int bot_inspect_messages_id
)
{
for (auto &bot_inspect_messages : bot_inspect_messagess) {
if (bot_inspect_messages.bot_id == bot_inspect_messages_id) {
return bot_inspect_messages;
}
}
return NewEntity();
}
static BotInspectMessages FindOne(
Database& db,
int bot_inspect_messages_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_inspect_messages_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotInspectMessages e{};
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.inspect_message = row[1] ? row[1] : "";
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_inspect_messages_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_inspect_messages_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotInspectMessages &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[0] + " = " + std::to_string(e.bot_id));
v.push_back(columns[1] + " = '" + Strings::Escape(e.inspect_message) + "'");
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.bot_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotInspectMessages InsertOne(
Database& db,
BotInspectMessages e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.bot_id));
v.push_back("'" + Strings::Escape(e.inspect_message) + "'");
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.bot_id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotInspectMessages> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.bot_id));
v.push_back("'" + Strings::Escape(e.inspect_message) + "'");
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<BotInspectMessages> All(Database& db)
{
std::vector<BotInspectMessages> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotInspectMessages e{};
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.inspect_message = row[1] ? row[1] : "";
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotInspectMessages> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotInspectMessages> 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) {
BotInspectMessages e{};
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.inspect_message = row[1] ? row[1] : "";
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_INSPECT_MESSAGES_REPOSITORY_H
@@ -0,0 +1,482 @@
/**
* 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_INVENTORIES_REPOSITORY_H
#define EQEMU_BASE_BOT_INVENTORIES_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotInventoriesRepository {
public:
struct BotInventories {
uint32_t inventories_index;
uint32_t bot_id;
uint32_t slot_id;
uint32_t item_id;
uint16_t inst_charges;
uint32_t inst_color;
uint8_t inst_no_drop;
std::string inst_custom_data;
uint32_t ornament_icon;
uint32_t ornament_id_file;
int32_t ornament_hero_model;
uint32_t augment_1;
uint32_t augment_2;
uint32_t augment_3;
uint32_t augment_4;
uint32_t augment_5;
uint32_t augment_6;
};
static std::string PrimaryKey()
{
return std::string("inventories_index");
}
static std::vector<std::string> Columns()
{
return {
"inventories_index",
"bot_id",
"slot_id",
"item_id",
"inst_charges",
"inst_color",
"inst_no_drop",
"inst_custom_data",
"ornament_icon",
"ornament_id_file",
"ornament_hero_model",
"augment_1",
"augment_2",
"augment_3",
"augment_4",
"augment_5",
"augment_6",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"inventories_index",
"bot_id",
"slot_id",
"item_id",
"inst_charges",
"inst_color",
"inst_no_drop",
"inst_custom_data",
"ornament_icon",
"ornament_id_file",
"ornament_hero_model",
"augment_1",
"augment_2",
"augment_3",
"augment_4",
"augment_5",
"augment_6",
};
}
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_inventories");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotInventories NewEntity()
{
BotInventories e{};
e.inventories_index = 0;
e.bot_id = 0;
e.slot_id = 0;
e.item_id = 0;
e.inst_charges = 0;
e.inst_color = 0;
e.inst_no_drop = 0;
e.inst_custom_data = "";
e.ornament_icon = 0;
e.ornament_id_file = 0;
e.ornament_hero_model = 0;
e.augment_1 = 0;
e.augment_2 = 0;
e.augment_3 = 0;
e.augment_4 = 0;
e.augment_5 = 0;
e.augment_6 = 0;
return e;
}
static BotInventories GetBotInventories(
const std::vector<BotInventories> &bot_inventoriess,
int bot_inventories_id
)
{
for (auto &bot_inventories : bot_inventoriess) {
if (bot_inventories.inventories_index == bot_inventories_id) {
return bot_inventories;
}
}
return NewEntity();
}
static BotInventories FindOne(
Database& db,
int bot_inventories_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_inventories_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotInventories e{};
e.inventories_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.slot_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.item_id = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.inst_charges = static_cast<uint16_t>(strtoul(row[4], nullptr, 10));
e.inst_color = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.inst_no_drop = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.inst_custom_data = row[7] ? row[7] : "";
e.ornament_icon = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
e.ornament_id_file = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
e.ornament_hero_model = static_cast<int32_t>(atoi(row[10]));
e.augment_1 = static_cast<uint32_t>(strtoul(row[11], nullptr, 10));
e.augment_2 = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.augment_3 = static_cast<uint32_t>(strtoul(row[13], nullptr, 10));
e.augment_4 = static_cast<uint32_t>(strtoul(row[14], nullptr, 10));
e.augment_5 = static_cast<uint32_t>(strtoul(row[15], nullptr, 10));
e.augment_6 = static_cast<uint32_t>(strtoul(row[16], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_inventories_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_inventories_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotInventories &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.bot_id));
v.push_back(columns[2] + " = " + std::to_string(e.slot_id));
v.push_back(columns[3] + " = " + std::to_string(e.item_id));
v.push_back(columns[4] + " = " + std::to_string(e.inst_charges));
v.push_back(columns[5] + " = " + std::to_string(e.inst_color));
v.push_back(columns[6] + " = " + std::to_string(e.inst_no_drop));
v.push_back(columns[7] + " = '" + Strings::Escape(e.inst_custom_data) + "'");
v.push_back(columns[8] + " = " + std::to_string(e.ornament_icon));
v.push_back(columns[9] + " = " + std::to_string(e.ornament_id_file));
v.push_back(columns[10] + " = " + std::to_string(e.ornament_hero_model));
v.push_back(columns[11] + " = " + std::to_string(e.augment_1));
v.push_back(columns[12] + " = " + std::to_string(e.augment_2));
v.push_back(columns[13] + " = " + std::to_string(e.augment_3));
v.push_back(columns[14] + " = " + std::to_string(e.augment_4));
v.push_back(columns[15] + " = " + std::to_string(e.augment_5));
v.push_back(columns[16] + " = " + std::to_string(e.augment_6));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.inventories_index
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotInventories InsertOne(
Database& db,
BotInventories e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.inventories_index));
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.inst_charges));
v.push_back(std::to_string(e.inst_color));
v.push_back(std::to_string(e.inst_no_drop));
v.push_back("'" + Strings::Escape(e.inst_custom_data) + "'");
v.push_back(std::to_string(e.ornament_icon));
v.push_back(std::to_string(e.ornament_id_file));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.augment_1));
v.push_back(std::to_string(e.augment_2));
v.push_back(std::to_string(e.augment_3));
v.push_back(std::to_string(e.augment_4));
v.push_back(std::to_string(e.augment_5));
v.push_back(std::to_string(e.augment_6));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.inventories_index = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotInventories> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.inventories_index));
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.inst_charges));
v.push_back(std::to_string(e.inst_color));
v.push_back(std::to_string(e.inst_no_drop));
v.push_back("'" + Strings::Escape(e.inst_custom_data) + "'");
v.push_back(std::to_string(e.ornament_icon));
v.push_back(std::to_string(e.ornament_id_file));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.augment_1));
v.push_back(std::to_string(e.augment_2));
v.push_back(std::to_string(e.augment_3));
v.push_back(std::to_string(e.augment_4));
v.push_back(std::to_string(e.augment_5));
v.push_back(std::to_string(e.augment_6));
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<BotInventories> All(Database& db)
{
std::vector<BotInventories> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotInventories e{};
e.inventories_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.slot_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.item_id = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.inst_charges = static_cast<uint16_t>(strtoul(row[4], nullptr, 10));
e.inst_color = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.inst_no_drop = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.inst_custom_data = row[7] ? row[7] : "";
e.ornament_icon = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
e.ornament_id_file = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
e.ornament_hero_model = static_cast<int32_t>(atoi(row[10]));
e.augment_1 = static_cast<uint32_t>(strtoul(row[11], nullptr, 10));
e.augment_2 = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.augment_3 = static_cast<uint32_t>(strtoul(row[13], nullptr, 10));
e.augment_4 = static_cast<uint32_t>(strtoul(row[14], nullptr, 10));
e.augment_5 = static_cast<uint32_t>(strtoul(row[15], nullptr, 10));
e.augment_6 = static_cast<uint32_t>(strtoul(row[16], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotInventories> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotInventories> 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) {
BotInventories e{};
e.inventories_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.slot_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.item_id = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.inst_charges = static_cast<uint16_t>(strtoul(row[4], nullptr, 10));
e.inst_color = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.inst_no_drop = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.inst_custom_data = row[7] ? row[7] : "";
e.ornament_icon = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
e.ornament_id_file = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
e.ornament_hero_model = static_cast<int32_t>(atoi(row[10]));
e.augment_1 = static_cast<uint32_t>(strtoul(row[11], nullptr, 10));
e.augment_2 = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.augment_3 = static_cast<uint32_t>(strtoul(row[13], nullptr, 10));
e.augment_4 = static_cast<uint32_t>(strtoul(row[14], nullptr, 10));
e.augment_5 = static_cast<uint32_t>(strtoul(row[15], nullptr, 10));
e.augment_6 = static_cast<uint32_t>(strtoul(row[16], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_BOT_INVENTORIES_REPOSITORY_H
@@ -0,0 +1,343 @@
/**
* 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_OWNER_OPTIONS_REPOSITORY_H
#define EQEMU_BASE_BOT_OWNER_OPTIONS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotOwnerOptionsRepository {
public:
struct BotOwnerOptions {
uint32_t owner_id;
uint16_t option_type;
uint16_t option_value;
};
static std::string PrimaryKey()
{
return std::string("owner_id");
}
static std::vector<std::string> Columns()
{
return {
"owner_id",
"option_type",
"option_value",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"owner_id",
"option_type",
"option_value",
};
}
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_owner_options");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotOwnerOptions NewEntity()
{
BotOwnerOptions e{};
e.owner_id = 0;
e.option_type = 0;
e.option_value = 0;
return e;
}
static BotOwnerOptions GetBotOwnerOptions(
const std::vector<BotOwnerOptions> &bot_owner_optionss,
int bot_owner_options_id
)
{
for (auto &bot_owner_options : bot_owner_optionss) {
if (bot_owner_options.owner_id == bot_owner_options_id) {
return bot_owner_options;
}
}
return NewEntity();
}
static BotOwnerOptions FindOne(
Database& db,
int bot_owner_options_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_owner_options_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotOwnerOptions e{};
e.owner_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.option_type = static_cast<uint16_t>(strtoul(row[1], nullptr, 10));
e.option_value = static_cast<uint16_t>(strtoul(row[2], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_owner_options_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_owner_options_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotOwnerOptions &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[0] + " = " + std::to_string(e.owner_id));
v.push_back(columns[1] + " = " + std::to_string(e.option_type));
v.push_back(columns[2] + " = " + std::to_string(e.option_value));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.owner_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotOwnerOptions InsertOne(
Database& db,
BotOwnerOptions e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.owner_id));
v.push_back(std::to_string(e.option_type));
v.push_back(std::to_string(e.option_value));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.owner_id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotOwnerOptions> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.owner_id));
v.push_back(std::to_string(e.option_type));
v.push_back(std::to_string(e.option_value));
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<BotOwnerOptions> All(Database& db)
{
std::vector<BotOwnerOptions> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotOwnerOptions e{};
e.owner_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.option_type = static_cast<uint16_t>(strtoul(row[1], nullptr, 10));
e.option_value = static_cast<uint16_t>(strtoul(row[2], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotOwnerOptions> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotOwnerOptions> 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) {
BotOwnerOptions e{};
e.owner_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.option_type = static_cast<uint16_t>(strtoul(row[1], nullptr, 10));
e.option_value = static_cast<uint16_t>(strtoul(row[2], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_BOT_OWNER_OPTIONS_REPOSITORY_H
@@ -0,0 +1,362 @@
/**
* 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_PET_BUFFS_REPOSITORY_H
#define EQEMU_BASE_BOT_PET_BUFFS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotPetBuffsRepository {
public:
struct BotPetBuffs {
uint32_t pet_buffs_index;
uint32_t pets_index;
uint32_t spell_id;
uint32_t caster_level;
uint32_t duration;
};
static std::string PrimaryKey()
{
return std::string("pet_buffs_index");
}
static std::vector<std::string> Columns()
{
return {
"pet_buffs_index",
"pets_index",
"spell_id",
"caster_level",
"duration",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"pet_buffs_index",
"pets_index",
"spell_id",
"caster_level",
"duration",
};
}
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_pet_buffs");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotPetBuffs NewEntity()
{
BotPetBuffs e{};
e.pet_buffs_index = 0;
e.pets_index = 0;
e.spell_id = 0;
e.caster_level = 0;
e.duration = 0;
return e;
}
static BotPetBuffs GetBotPetBuffs(
const std::vector<BotPetBuffs> &bot_pet_buffss,
int bot_pet_buffs_id
)
{
for (auto &bot_pet_buffs : bot_pet_buffss) {
if (bot_pet_buffs.pet_buffs_index == bot_pet_buffs_id) {
return bot_pet_buffs;
}
}
return NewEntity();
}
static BotPetBuffs FindOne(
Database& db,
int bot_pet_buffs_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_pet_buffs_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotPetBuffs e{};
e.pet_buffs_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.pets_index = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.spell_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.caster_level = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.duration = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_pet_buffs_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_pet_buffs_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotPetBuffs &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.pets_index));
v.push_back(columns[2] + " = " + std::to_string(e.spell_id));
v.push_back(columns[3] + " = " + std::to_string(e.caster_level));
v.push_back(columns[4] + " = " + std::to_string(e.duration));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.pet_buffs_index
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotPetBuffs InsertOne(
Database& db,
BotPetBuffs e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.pet_buffs_index));
v.push_back(std::to_string(e.pets_index));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.caster_level));
v.push_back(std::to_string(e.duration));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.pet_buffs_index = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotPetBuffs> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.pet_buffs_index));
v.push_back(std::to_string(e.pets_index));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.caster_level));
v.push_back(std::to_string(e.duration));
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<BotPetBuffs> All(Database& db)
{
std::vector<BotPetBuffs> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotPetBuffs e{};
e.pet_buffs_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.pets_index = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.spell_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.caster_level = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.duration = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotPetBuffs> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotPetBuffs> 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) {
BotPetBuffs e{};
e.pet_buffs_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.pets_index = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.spell_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.caster_level = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.duration = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_BOT_PET_BUFFS_REPOSITORY_H
@@ -0,0 +1,342 @@
/**
* 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_PET_INVENTORIES_REPOSITORY_H
#define EQEMU_BASE_BOT_PET_INVENTORIES_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotPetInventoriesRepository {
public:
struct BotPetInventories {
uint32_t pet_inventories_index;
uint32_t pets_index;
uint32_t item_id;
};
static std::string PrimaryKey()
{
return std::string("pet_inventories_index");
}
static std::vector<std::string> Columns()
{
return {
"pet_inventories_index",
"pets_index",
"item_id",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"pet_inventories_index",
"pets_index",
"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("bot_pet_inventories");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotPetInventories NewEntity()
{
BotPetInventories e{};
e.pet_inventories_index = 0;
e.pets_index = 0;
e.item_id = 0;
return e;
}
static BotPetInventories GetBotPetInventories(
const std::vector<BotPetInventories> &bot_pet_inventoriess,
int bot_pet_inventories_id
)
{
for (auto &bot_pet_inventories : bot_pet_inventoriess) {
if (bot_pet_inventories.pet_inventories_index == bot_pet_inventories_id) {
return bot_pet_inventories;
}
}
return NewEntity();
}
static BotPetInventories FindOne(
Database& db,
int bot_pet_inventories_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_pet_inventories_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotPetInventories e{};
e.pet_inventories_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.pets_index = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.item_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_pet_inventories_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_pet_inventories_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotPetInventories &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.pets_index));
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.pet_inventories_index
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotPetInventories InsertOne(
Database& db,
BotPetInventories e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.pet_inventories_index));
v.push_back(std::to_string(e.pets_index));
v.push_back(std::to_string(e.item_id));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.pet_inventories_index = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotPetInventories> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.pet_inventories_index));
v.push_back(std::to_string(e.pets_index));
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<BotPetInventories> All(Database& db)
{
std::vector<BotPetInventories> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotPetInventories e{};
e.pet_inventories_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.pets_index = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.item_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotPetInventories> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotPetInventories> 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) {
BotPetInventories e{};
e.pet_inventories_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.pets_index = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.item_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_BOT_PET_INVENTORIES_REPOSITORY_H
@@ -0,0 +1,372 @@
/**
* 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_PETS_REPOSITORY_H
#define EQEMU_BASE_BOT_PETS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotPetsRepository {
public:
struct BotPets {
uint32_t pets_index;
uint32_t spell_id;
uint32_t bot_id;
std::string name;
int32_t mana;
int32_t hp;
};
static std::string PrimaryKey()
{
return std::string("pets_index");
}
static std::vector<std::string> Columns()
{
return {
"pets_index",
"spell_id",
"bot_id",
"name",
"mana",
"hp",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"pets_index",
"spell_id",
"bot_id",
"name",
"mana",
"hp",
};
}
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_pets");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotPets NewEntity()
{
BotPets e{};
e.pets_index = 0;
e.spell_id = 0;
e.bot_id = 0;
e.name = "";
e.mana = 0;
e.hp = 0;
return e;
}
static BotPets GetBotPets(
const std::vector<BotPets> &bot_petss,
int bot_pets_id
)
{
for (auto &bot_pets : bot_petss) {
if (bot_pets.pets_index == bot_pets_id) {
return bot_pets;
}
}
return NewEntity();
}
static BotPets FindOne(
Database& db,
int bot_pets_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_pets_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotPets e{};
e.pets_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.spell_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.name = row[3] ? row[3] : "";
e.mana = static_cast<int32_t>(atoi(row[4]));
e.hp = static_cast<int32_t>(atoi(row[5]));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_pets_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_pets_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotPets &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.spell_id));
v.push_back(columns[2] + " = " + std::to_string(e.bot_id));
v.push_back(columns[3] + " = '" + Strings::Escape(e.name) + "'");
v.push_back(columns[4] + " = " + std::to_string(e.mana));
v.push_back(columns[5] + " = " + std::to_string(e.hp));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.pets_index
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotPets InsertOne(
Database& db,
BotPets e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.pets_index));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.bot_id));
v.push_back("'" + Strings::Escape(e.name) + "'");
v.push_back(std::to_string(e.mana));
v.push_back(std::to_string(e.hp));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.pets_index = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotPets> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.pets_index));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.bot_id));
v.push_back("'" + Strings::Escape(e.name) + "'");
v.push_back(std::to_string(e.mana));
v.push_back(std::to_string(e.hp));
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<BotPets> All(Database& db)
{
std::vector<BotPets> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotPets e{};
e.pets_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.spell_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.name = row[3] ? row[3] : "";
e.mana = static_cast<int32_t>(atoi(row[4]));
e.hp = static_cast<int32_t>(atoi(row[5]));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotPets> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotPets> 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) {
BotPets e{};
e.pets_index = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.spell_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.name = row[3] ? row[3] : "";
e.mana = static_cast<int32_t>(atoi(row[4]));
e.hp = static_cast<int32_t>(atoi(row[5]));
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_PETS_REPOSITORY_H
@@ -0,0 +1,512 @@
/**
* 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_SPELL_CASTING_CHANCES_REPOSITORY_H
#define EQEMU_BASE_BOT_SPELL_CASTING_CHANCES_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotSpellCastingChancesRepository {
public:
struct BotSpellCastingChances {
int32_t id;
uint8_t spell_type_index;
uint8_t class_id;
uint8_t stance_index;
uint8_t nHSND_value;
uint8_t pH_value;
uint8_t pS_value;
uint8_t pHS_value;
uint8_t pN_value;
uint8_t pHN_value;
uint8_t pSN_value;
uint8_t pHSN_value;
uint8_t pD_value;
uint8_t pHD_value;
uint8_t pSD_value;
uint8_t pHSD_value;
uint8_t pND_value;
uint8_t pHND_value;
uint8_t pSND_value;
uint8_t pHSND_value;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"spell_type_index",
"class_id",
"stance_index",
"nHSND_value",
"pH_value",
"pS_value",
"pHS_value",
"pN_value",
"pHN_value",
"pSN_value",
"pHSN_value",
"pD_value",
"pHD_value",
"pSD_value",
"pHSD_value",
"pND_value",
"pHND_value",
"pSND_value",
"pHSND_value",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"spell_type_index",
"class_id",
"stance_index",
"nHSND_value",
"pH_value",
"pS_value",
"pHS_value",
"pN_value",
"pHN_value",
"pSN_value",
"pHSN_value",
"pD_value",
"pHD_value",
"pSD_value",
"pHSD_value",
"pND_value",
"pHND_value",
"pSND_value",
"pHSND_value",
};
}
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_spell_casting_chances");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotSpellCastingChances NewEntity()
{
BotSpellCastingChances e{};
e.id = 0;
e.spell_type_index = 0;
e.class_id = 0;
e.stance_index = 0;
e.nHSND_value = 0;
e.pH_value = 0;
e.pS_value = 0;
e.pHS_value = 0;
e.pN_value = 0;
e.pHN_value = 0;
e.pSN_value = 0;
e.pHSN_value = 0;
e.pD_value = 0;
e.pHD_value = 0;
e.pSD_value = 0;
e.pHSD_value = 0;
e.pND_value = 0;
e.pHND_value = 0;
e.pSND_value = 0;
e.pHSND_value = 0;
return e;
}
static BotSpellCastingChances GetBotSpellCastingChances(
const std::vector<BotSpellCastingChances> &bot_spell_casting_chancess,
int bot_spell_casting_chances_id
)
{
for (auto &bot_spell_casting_chances : bot_spell_casting_chancess) {
if (bot_spell_casting_chances.id == bot_spell_casting_chances_id) {
return bot_spell_casting_chances;
}
}
return NewEntity();
}
static BotSpellCastingChances FindOne(
Database& db,
int bot_spell_casting_chances_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_spell_casting_chances_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotSpellCastingChances e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.spell_type_index = static_cast<uint8_t>(strtoul(row[1], nullptr, 10));
e.class_id = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
e.stance_index = static_cast<uint8_t>(strtoul(row[3], nullptr, 10));
e.nHSND_value = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.pH_value = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
e.pS_value = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.pHS_value = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.pN_value = static_cast<uint8_t>(strtoul(row[8], nullptr, 10));
e.pHN_value = static_cast<uint8_t>(strtoul(row[9], nullptr, 10));
e.pSN_value = static_cast<uint8_t>(strtoul(row[10], nullptr, 10));
e.pHSN_value = static_cast<uint8_t>(strtoul(row[11], nullptr, 10));
e.pD_value = static_cast<uint8_t>(strtoul(row[12], nullptr, 10));
e.pHD_value = static_cast<uint8_t>(strtoul(row[13], nullptr, 10));
e.pSD_value = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
e.pHSD_value = static_cast<uint8_t>(strtoul(row[15], nullptr, 10));
e.pND_value = static_cast<uint8_t>(strtoul(row[16], nullptr, 10));
e.pHND_value = static_cast<uint8_t>(strtoul(row[17], nullptr, 10));
e.pSND_value = static_cast<uint8_t>(strtoul(row[18], nullptr, 10));
e.pHSND_value = static_cast<uint8_t>(strtoul(row[19], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_spell_casting_chances_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_spell_casting_chances_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotSpellCastingChances &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.spell_type_index));
v.push_back(columns[2] + " = " + std::to_string(e.class_id));
v.push_back(columns[3] + " = " + std::to_string(e.stance_index));
v.push_back(columns[4] + " = " + std::to_string(e.nHSND_value));
v.push_back(columns[5] + " = " + std::to_string(e.pH_value));
v.push_back(columns[6] + " = " + std::to_string(e.pS_value));
v.push_back(columns[7] + " = " + std::to_string(e.pHS_value));
v.push_back(columns[8] + " = " + std::to_string(e.pN_value));
v.push_back(columns[9] + " = " + std::to_string(e.pHN_value));
v.push_back(columns[10] + " = " + std::to_string(e.pSN_value));
v.push_back(columns[11] + " = " + std::to_string(e.pHSN_value));
v.push_back(columns[12] + " = " + std::to_string(e.pD_value));
v.push_back(columns[13] + " = " + std::to_string(e.pHD_value));
v.push_back(columns[14] + " = " + std::to_string(e.pSD_value));
v.push_back(columns[15] + " = " + std::to_string(e.pHSD_value));
v.push_back(columns[16] + " = " + std::to_string(e.pND_value));
v.push_back(columns[17] + " = " + std::to_string(e.pHND_value));
v.push_back(columns[18] + " = " + std::to_string(e.pSND_value));
v.push_back(columns[19] + " = " + std::to_string(e.pHSND_value));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotSpellCastingChances InsertOne(
Database& db,
BotSpellCastingChances e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.spell_type_index));
v.push_back(std::to_string(e.class_id));
v.push_back(std::to_string(e.stance_index));
v.push_back(std::to_string(e.nHSND_value));
v.push_back(std::to_string(e.pH_value));
v.push_back(std::to_string(e.pS_value));
v.push_back(std::to_string(e.pHS_value));
v.push_back(std::to_string(e.pN_value));
v.push_back(std::to_string(e.pHN_value));
v.push_back(std::to_string(e.pSN_value));
v.push_back(std::to_string(e.pHSN_value));
v.push_back(std::to_string(e.pD_value));
v.push_back(std::to_string(e.pHD_value));
v.push_back(std::to_string(e.pSD_value));
v.push_back(std::to_string(e.pHSD_value));
v.push_back(std::to_string(e.pND_value));
v.push_back(std::to_string(e.pHND_value));
v.push_back(std::to_string(e.pSND_value));
v.push_back(std::to_string(e.pHSND_value));
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<BotSpellCastingChances> &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.spell_type_index));
v.push_back(std::to_string(e.class_id));
v.push_back(std::to_string(e.stance_index));
v.push_back(std::to_string(e.nHSND_value));
v.push_back(std::to_string(e.pH_value));
v.push_back(std::to_string(e.pS_value));
v.push_back(std::to_string(e.pHS_value));
v.push_back(std::to_string(e.pN_value));
v.push_back(std::to_string(e.pHN_value));
v.push_back(std::to_string(e.pSN_value));
v.push_back(std::to_string(e.pHSN_value));
v.push_back(std::to_string(e.pD_value));
v.push_back(std::to_string(e.pHD_value));
v.push_back(std::to_string(e.pSD_value));
v.push_back(std::to_string(e.pHSD_value));
v.push_back(std::to_string(e.pND_value));
v.push_back(std::to_string(e.pHND_value));
v.push_back(std::to_string(e.pSND_value));
v.push_back(std::to_string(e.pHSND_value));
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<BotSpellCastingChances> All(Database& db)
{
std::vector<BotSpellCastingChances> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotSpellCastingChances e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.spell_type_index = static_cast<uint8_t>(strtoul(row[1], nullptr, 10));
e.class_id = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
e.stance_index = static_cast<uint8_t>(strtoul(row[3], nullptr, 10));
e.nHSND_value = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.pH_value = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
e.pS_value = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.pHS_value = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.pN_value = static_cast<uint8_t>(strtoul(row[8], nullptr, 10));
e.pHN_value = static_cast<uint8_t>(strtoul(row[9], nullptr, 10));
e.pSN_value = static_cast<uint8_t>(strtoul(row[10], nullptr, 10));
e.pHSN_value = static_cast<uint8_t>(strtoul(row[11], nullptr, 10));
e.pD_value = static_cast<uint8_t>(strtoul(row[12], nullptr, 10));
e.pHD_value = static_cast<uint8_t>(strtoul(row[13], nullptr, 10));
e.pSD_value = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
e.pHSD_value = static_cast<uint8_t>(strtoul(row[15], nullptr, 10));
e.pND_value = static_cast<uint8_t>(strtoul(row[16], nullptr, 10));
e.pHND_value = static_cast<uint8_t>(strtoul(row[17], nullptr, 10));
e.pSND_value = static_cast<uint8_t>(strtoul(row[18], nullptr, 10));
e.pHSND_value = static_cast<uint8_t>(strtoul(row[19], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotSpellCastingChances> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotSpellCastingChances> 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) {
BotSpellCastingChances e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.spell_type_index = static_cast<uint8_t>(strtoul(row[1], nullptr, 10));
e.class_id = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
e.stance_index = static_cast<uint8_t>(strtoul(row[3], nullptr, 10));
e.nHSND_value = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.pH_value = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
e.pS_value = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.pHS_value = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.pN_value = static_cast<uint8_t>(strtoul(row[8], nullptr, 10));
e.pHN_value = static_cast<uint8_t>(strtoul(row[9], nullptr, 10));
e.pSN_value = static_cast<uint8_t>(strtoul(row[10], nullptr, 10));
e.pHSN_value = static_cast<uint8_t>(strtoul(row[11], nullptr, 10));
e.pD_value = static_cast<uint8_t>(strtoul(row[12], nullptr, 10));
e.pHD_value = static_cast<uint8_t>(strtoul(row[13], nullptr, 10));
e.pSD_value = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
e.pHSD_value = static_cast<uint8_t>(strtoul(row[15], nullptr, 10));
e.pND_value = static_cast<uint8_t>(strtoul(row[16], nullptr, 10));
e.pHND_value = static_cast<uint8_t>(strtoul(row[17], nullptr, 10));
e.pSND_value = static_cast<uint8_t>(strtoul(row[18], nullptr, 10));
e.pHSND_value = static_cast<uint8_t>(strtoul(row[19], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_BOT_SPELL_CASTING_CHANCES_REPOSITORY_H
@@ -0,0 +1,382 @@
/**
* 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_SPELL_SETTINGS_REPOSITORY_H
#define EQEMU_BASE_BOT_SPELL_SETTINGS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotSpellSettingsRepository {
public:
struct BotSpellSettings {
uint32_t id;
int32_t bot_id;
int16_t spell_id;
int16_t priority;
int16_t min_hp;
int16_t max_hp;
uint8_t is_enabled;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"bot_id",
"spell_id",
"priority",
"min_hp",
"max_hp",
"is_enabled",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"bot_id",
"spell_id",
"priority",
"min_hp",
"max_hp",
"is_enabled",
};
}
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_spell_settings");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotSpellSettings NewEntity()
{
BotSpellSettings e{};
e.id = 0;
e.bot_id = 0;
e.spell_id = 0;
e.priority = 0;
e.min_hp = 0;
e.max_hp = 0;
e.is_enabled = 1;
return e;
}
static BotSpellSettings GetBotSpellSettings(
const std::vector<BotSpellSettings> &bot_spell_settingss,
int bot_spell_settings_id
)
{
for (auto &bot_spell_settings : bot_spell_settingss) {
if (bot_spell_settings.id == bot_spell_settings_id) {
return bot_spell_settings;
}
}
return NewEntity();
}
static BotSpellSettings FindOne(
Database& db,
int bot_spell_settings_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_spell_settings_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotSpellSettings e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.bot_id = static_cast<int32_t>(atoi(row[1]));
e.spell_id = static_cast<int16_t>(atoi(row[2]));
e.priority = static_cast<int16_t>(atoi(row[3]));
e.min_hp = static_cast<int16_t>(atoi(row[4]));
e.max_hp = static_cast<int16_t>(atoi(row[5]));
e.is_enabled = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_spell_settings_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_spell_settings_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotSpellSettings &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.bot_id));
v.push_back(columns[2] + " = " + std::to_string(e.spell_id));
v.push_back(columns[3] + " = " + std::to_string(e.priority));
v.push_back(columns[4] + " = " + std::to_string(e.min_hp));
v.push_back(columns[5] + " = " + std::to_string(e.max_hp));
v.push_back(columns[6] + " = " + std::to_string(e.is_enabled));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotSpellSettings InsertOne(
Database& db,
BotSpellSettings e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.priority));
v.push_back(std::to_string(e.min_hp));
v.push_back(std::to_string(e.max_hp));
v.push_back(std::to_string(e.is_enabled));
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<BotSpellSettings> &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.bot_id));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.priority));
v.push_back(std::to_string(e.min_hp));
v.push_back(std::to_string(e.max_hp));
v.push_back(std::to_string(e.is_enabled));
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<BotSpellSettings> All(Database& db)
{
std::vector<BotSpellSettings> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotSpellSettings e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.bot_id = static_cast<int32_t>(atoi(row[1]));
e.spell_id = static_cast<int16_t>(atoi(row[2]));
e.priority = static_cast<int16_t>(atoi(row[3]));
e.min_hp = static_cast<int16_t>(atoi(row[4]));
e.max_hp = static_cast<int16_t>(atoi(row[5]));
e.is_enabled = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotSpellSettings> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotSpellSettings> 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) {
BotSpellSettings e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.bot_id = static_cast<int32_t>(atoi(row[1]));
e.spell_id = static_cast<int16_t>(atoi(row[2]));
e.priority = static_cast<int16_t>(atoi(row[3]));
e.min_hp = static_cast<int16_t>(atoi(row[4]));
e.max_hp = static_cast<int16_t>(atoi(row[5]));
e.is_enabled = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_BOT_SPELL_SETTINGS_REPOSITORY_H
@@ -0,0 +1,462 @@
/**
* 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_SPELLS_ENTRIES_REPOSITORY_H
#define EQEMU_BASE_BOT_SPELLS_ENTRIES_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotSpellsEntriesRepository {
public:
struct BotSpellsEntries {
uint32_t id;
int32_t npc_spells_id;
int16_t spellid;
uint32_t type;
uint8_t minlevel;
uint8_t maxlevel;
int16_t manacost;
int32_t recast_delay;
int16_t priority;
int32_t resist_adjust;
int16_t min_hp;
int16_t max_hp;
std::string bucket_name;
std::string bucket_value;
uint8_t bucket_comparison;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"npc_spells_id",
"spellid",
"type",
"minlevel",
"maxlevel",
"manacost",
"recast_delay",
"priority",
"resist_adjust",
"min_hp",
"max_hp",
"bucket_name",
"bucket_value",
"bucket_comparison",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"npc_spells_id",
"spellid",
"type",
"minlevel",
"maxlevel",
"manacost",
"recast_delay",
"priority",
"resist_adjust",
"min_hp",
"max_hp",
"bucket_name",
"bucket_value",
"bucket_comparison",
};
}
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_spells_entries");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotSpellsEntries NewEntity()
{
BotSpellsEntries e{};
e.id = 0;
e.npc_spells_id = 0;
e.spellid = 0;
e.type = 0;
e.minlevel = 0;
e.maxlevel = 255;
e.manacost = -1;
e.recast_delay = -1;
e.priority = 0;
e.resist_adjust = 0;
e.min_hp = 0;
e.max_hp = 0;
e.bucket_name = "";
e.bucket_value = "";
e.bucket_comparison = 0;
return e;
}
static BotSpellsEntries GetBotSpellsEntries(
const std::vector<BotSpellsEntries> &bot_spells_entriess,
int bot_spells_entries_id
)
{
for (auto &bot_spells_entries : bot_spells_entriess) {
if (bot_spells_entries.id == bot_spells_entries_id) {
return bot_spells_entries;
}
}
return NewEntity();
}
static BotSpellsEntries FindOne(
Database& db,
int bot_spells_entries_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_spells_entries_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotSpellsEntries e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.npc_spells_id = static_cast<int32_t>(atoi(row[1]));
e.spellid = static_cast<int16_t>(atoi(row[2]));
e.type = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.minlevel = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.maxlevel = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
e.manacost = static_cast<int16_t>(atoi(row[6]));
e.recast_delay = static_cast<int32_t>(atoi(row[7]));
e.priority = static_cast<int16_t>(atoi(row[8]));
e.resist_adjust = static_cast<int32_t>(atoi(row[9]));
e.min_hp = static_cast<int16_t>(atoi(row[10]));
e.max_hp = static_cast<int16_t>(atoi(row[11]));
e.bucket_name = row[12] ? row[12] : "";
e.bucket_value = row[13] ? row[13] : "";
e.bucket_comparison = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_spells_entries_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_spells_entries_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotSpellsEntries &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.npc_spells_id));
v.push_back(columns[2] + " = " + std::to_string(e.spellid));
v.push_back(columns[3] + " = " + std::to_string(e.type));
v.push_back(columns[4] + " = " + std::to_string(e.minlevel));
v.push_back(columns[5] + " = " + std::to_string(e.maxlevel));
v.push_back(columns[6] + " = " + std::to_string(e.manacost));
v.push_back(columns[7] + " = " + std::to_string(e.recast_delay));
v.push_back(columns[8] + " = " + std::to_string(e.priority));
v.push_back(columns[9] + " = " + std::to_string(e.resist_adjust));
v.push_back(columns[10] + " = " + std::to_string(e.min_hp));
v.push_back(columns[11] + " = " + std::to_string(e.max_hp));
v.push_back(columns[12] + " = '" + Strings::Escape(e.bucket_name) + "'");
v.push_back(columns[13] + " = '" + Strings::Escape(e.bucket_value) + "'");
v.push_back(columns[14] + " = " + std::to_string(e.bucket_comparison));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotSpellsEntries InsertOne(
Database& db,
BotSpellsEntries e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.npc_spells_id));
v.push_back(std::to_string(e.spellid));
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.minlevel));
v.push_back(std::to_string(e.maxlevel));
v.push_back(std::to_string(e.manacost));
v.push_back(std::to_string(e.recast_delay));
v.push_back(std::to_string(e.priority));
v.push_back(std::to_string(e.resist_adjust));
v.push_back(std::to_string(e.min_hp));
v.push_back(std::to_string(e.max_hp));
v.push_back("'" + Strings::Escape(e.bucket_name) + "'");
v.push_back("'" + Strings::Escape(e.bucket_value) + "'");
v.push_back(std::to_string(e.bucket_comparison));
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<BotSpellsEntries> &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.npc_spells_id));
v.push_back(std::to_string(e.spellid));
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.minlevel));
v.push_back(std::to_string(e.maxlevel));
v.push_back(std::to_string(e.manacost));
v.push_back(std::to_string(e.recast_delay));
v.push_back(std::to_string(e.priority));
v.push_back(std::to_string(e.resist_adjust));
v.push_back(std::to_string(e.min_hp));
v.push_back(std::to_string(e.max_hp));
v.push_back("'" + Strings::Escape(e.bucket_name) + "'");
v.push_back("'" + Strings::Escape(e.bucket_value) + "'");
v.push_back(std::to_string(e.bucket_comparison));
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<BotSpellsEntries> All(Database& db)
{
std::vector<BotSpellsEntries> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotSpellsEntries e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.npc_spells_id = static_cast<int32_t>(atoi(row[1]));
e.spellid = static_cast<int16_t>(atoi(row[2]));
e.type = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.minlevel = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.maxlevel = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
e.manacost = static_cast<int16_t>(atoi(row[6]));
e.recast_delay = static_cast<int32_t>(atoi(row[7]));
e.priority = static_cast<int16_t>(atoi(row[8]));
e.resist_adjust = static_cast<int32_t>(atoi(row[9]));
e.min_hp = static_cast<int16_t>(atoi(row[10]));
e.max_hp = static_cast<int16_t>(atoi(row[11]));
e.bucket_name = row[12] ? row[12] : "";
e.bucket_value = row[13] ? row[13] : "";
e.bucket_comparison = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotSpellsEntries> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotSpellsEntries> 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) {
BotSpellsEntries e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.npc_spells_id = static_cast<int32_t>(atoi(row[1]));
e.spellid = static_cast<int16_t>(atoi(row[2]));
e.type = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.minlevel = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.maxlevel = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
e.manacost = static_cast<int16_t>(atoi(row[6]));
e.recast_delay = static_cast<int32_t>(atoi(row[7]));
e.priority = static_cast<int16_t>(atoi(row[8]));
e.resist_adjust = static_cast<int32_t>(atoi(row[9]));
e.min_hp = static_cast<int16_t>(atoi(row[10]));
e.max_hp = static_cast<int16_t>(atoi(row[11]));
e.bucket_name = row[12] ? row[12] : "";
e.bucket_value = row[13] ? row[13] : "";
e.bucket_comparison = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_BOT_SPELLS_ENTRIES_REPOSITORY_H
@@ -9,38 +9,38 @@
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
*/
#ifndef EQEMU_BASE_GOALLISTS_REPOSITORY_H
#define EQEMU_BASE_GOALLISTS_REPOSITORY_H
#ifndef EQEMU_BASE_BOT_STANCES_REPOSITORY_H
#define EQEMU_BASE_BOT_STANCES_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseGoallistsRepository {
class BaseBotStancesRepository {
public:
struct Goallists {
uint32_t listid;
uint32_t entry;
struct BotStances {
uint32_t bot_id;
uint8_t stance_id;
};
static std::string PrimaryKey()
{
return std::string("listid");
return std::string("bot_id");
}
static std::vector<std::string> Columns()
{
return {
"listid",
"entry",
"bot_id",
"stance_id",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"listid",
"entry",
"bot_id",
"stance_id",
};
}
@@ -56,7 +56,7 @@ public:
static std::string TableName()
{
return std::string("goallists");
return std::string("bot_stances");
}
static std::string BaseSelect()
@@ -77,49 +77,49 @@ public:
);
}
static Goallists NewEntity()
static BotStances NewEntity()
{
Goallists e{};
BotStances e{};
e.listid = 0;
e.entry = 0;
e.bot_id = 0;
e.stance_id = 0;
return e;
}
static Goallists GetGoallists(
const std::vector<Goallists> &goallistss,
int goallists_id
static BotStances GetBotStances(
const std::vector<BotStances> &bot_stancess,
int bot_stances_id
)
{
for (auto &goallists : goallistss) {
if (goallists.listid == goallists_id) {
return goallists;
for (auto &bot_stances : bot_stancess) {
if (bot_stances.bot_id == bot_stances_id) {
return bot_stances;
}
}
return NewEntity();
}
static Goallists FindOne(
static BotStances FindOne(
Database& db,
int goallists_id
int bot_stances_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
goallists_id
bot_stances_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
Goallists e{};
BotStances e{};
e.listid = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.entry = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.stance_id = static_cast<uint8_t>(strtoul(row[1], nullptr, 10));
return e;
}
@@ -129,7 +129,7 @@ public:
static int DeleteOne(
Database& db,
int goallists_id
int bot_stances_id
)
{
auto results = db.QueryDatabase(
@@ -137,7 +137,7 @@ public:
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
goallists_id
bot_stances_id
)
);
@@ -146,15 +146,15 @@ public:
static int UpdateOne(
Database& db,
const Goallists &e
const BotStances &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[0] + " = " + std::to_string(e.listid));
v.push_back(columns[1] + " = " + std::to_string(e.entry));
v.push_back(columns[0] + " = " + std::to_string(e.bot_id));
v.push_back(columns[1] + " = " + std::to_string(e.stance_id));
auto results = db.QueryDatabase(
fmt::format(
@@ -162,22 +162,22 @@ public:
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.listid
e.bot_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static Goallists InsertOne(
static BotStances InsertOne(
Database& db,
Goallists e
BotStances e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.listid));
v.push_back(std::to_string(e.entry));
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.stance_id));
auto results = db.QueryDatabase(
fmt::format(
@@ -188,7 +188,7 @@ public:
);
if (results.Success()) {
e.listid = results.LastInsertedID();
e.bot_id = results.LastInsertedID();
return e;
}
@@ -199,7 +199,7 @@ public:
static int InsertMany(
Database& db,
const std::vector<Goallists> &entries
const std::vector<BotStances> &entries
)
{
std::vector<std::string> insert_chunks;
@@ -207,8 +207,8 @@ public:
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.listid));
v.push_back(std::to_string(e.entry));
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.stance_id));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -226,9 +226,9 @@ public:
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<Goallists> All(Database& db)
static std::vector<BotStances> All(Database& db)
{
std::vector<Goallists> all_entries;
std::vector<BotStances> all_entries;
auto results = db.QueryDatabase(
fmt::format(
@@ -240,10 +240,10 @@ public:
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
Goallists e{};
BotStances e{};
e.listid = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.entry = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.stance_id = static_cast<uint8_t>(strtoul(row[1], nullptr, 10));
all_entries.push_back(e);
}
@@ -251,9 +251,9 @@ public:
return all_entries;
}
static std::vector<Goallists> GetWhere(Database& db, const std::string &where_filter)
static std::vector<BotStances> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<Goallists> all_entries;
std::vector<BotStances> all_entries;
auto results = db.QueryDatabase(
fmt::format(
@@ -266,10 +266,10 @@ public:
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
Goallists e{};
BotStances e{};
e.listid = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.entry = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.stance_id = static_cast<uint8_t>(strtoul(row[1], nullptr, 10));
all_entries.push_back(e);
}
@@ -330,4 +330,4 @@ public:
};
#endif //EQEMU_BASE_GOALLISTS_REPOSITORY_H
#endif //EQEMU_BASE_BOT_STANCES_REPOSITORY_H
@@ -0,0 +1,343 @@
/**
* 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_TIMERS_REPOSITORY_H
#define EQEMU_BASE_BOT_TIMERS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotTimersRepository {
public:
struct BotTimers {
uint32_t bot_id;
uint32_t timer_id;
uint32_t timer_value;
};
static std::string PrimaryKey()
{
return std::string("bot_id");
}
static std::vector<std::string> Columns()
{
return {
"bot_id",
"timer_id",
"timer_value",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"bot_id",
"timer_id",
"timer_value",
};
}
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_timers");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotTimers NewEntity()
{
BotTimers e{};
e.bot_id = 0;
e.timer_id = 0;
e.timer_value = 0;
return e;
}
static BotTimers GetBotTimers(
const std::vector<BotTimers> &bot_timerss,
int bot_timers_id
)
{
for (auto &bot_timers : bot_timerss) {
if (bot_timers.bot_id == bot_timers_id) {
return bot_timers;
}
}
return NewEntity();
}
static BotTimers FindOne(
Database& db,
int bot_timers_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
bot_timers_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotTimers e{};
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.timer_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.timer_value = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_timers_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_timers_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotTimers &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[0] + " = " + std::to_string(e.bot_id));
v.push_back(columns[1] + " = " + std::to_string(e.timer_id));
v.push_back(columns[2] + " = " + std::to_string(e.timer_value));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.bot_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotTimers InsertOne(
Database& db,
BotTimers e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.timer_id));
v.push_back(std::to_string(e.timer_value));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.bot_id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotTimers> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.timer_id));
v.push_back(std::to_string(e.timer_value));
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<BotTimers> All(Database& db)
{
std::vector<BotTimers> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotTimers e{};
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.timer_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.timer_value = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotTimers> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotTimers> 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) {
BotTimers e{};
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.timer_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.timer_value = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_BOT_TIMERS_REPOSITORY_H
@@ -16,6 +16,7 @@
#include "../../strings.h"
#include <ctime>
class BaseCharacterDataRepository {
public:
struct CharacterData {
@@ -57,6 +58,7 @@ public:
uint8_t ability_time_minutes;
uint8_t ability_time_hours;
uint32_t exp;
uint8_t exp_enabled;
uint32_t aa_points_spent;
uint32_t aa_exp;
uint32_t aa_points;
@@ -169,6 +171,7 @@ public:
"ability_time_minutes",
"ability_time_hours",
"exp",
"exp_enabled",
"aa_points_spent",
"aa_exp",
"aa_points",
@@ -277,6 +280,7 @@ public:
"ability_time_minutes",
"ability_time_hours",
"exp",
"exp_enabled",
"aa_points_spent",
"aa_exp",
"aa_points",
@@ -419,6 +423,7 @@ public:
e.ability_time_minutes = 0;
e.ability_time_hours = 0;
e.exp = 0;
e.exp_enabled = 1;
e.aa_points_spent = 0;
e.aa_exp = 0;
e.aa_points = 0;
@@ -508,8 +513,9 @@ public:
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
character_data_id
)
);
@@ -556,70 +562,71 @@ public:
e.ability_time_minutes = static_cast<uint8_t>(strtoul(row[35], nullptr, 10));
e.ability_time_hours = static_cast<uint8_t>(strtoul(row[36], nullptr, 10));
e.exp = static_cast<uint32_t>(strtoul(row[37], nullptr, 10));
e.aa_points_spent = static_cast<uint32_t>(strtoul(row[38], nullptr, 10));
e.aa_exp = static_cast<uint32_t>(strtoul(row[39], nullptr, 10));
e.aa_points = static_cast<uint32_t>(strtoul(row[40], nullptr, 10));
e.group_leadership_exp = static_cast<uint32_t>(strtoul(row[41], nullptr, 10));
e.raid_leadership_exp = static_cast<uint32_t>(strtoul(row[42], nullptr, 10));
e.group_leadership_points = static_cast<uint32_t>(strtoul(row[43], nullptr, 10));
e.raid_leadership_points = static_cast<uint32_t>(strtoul(row[44], nullptr, 10));
e.points = static_cast<uint32_t>(strtoul(row[45], nullptr, 10));
e.cur_hp = static_cast<uint32_t>(strtoul(row[46], nullptr, 10));
e.mana = static_cast<uint32_t>(strtoul(row[47], nullptr, 10));
e.endurance = static_cast<uint32_t>(strtoul(row[48], nullptr, 10));
e.intoxication = static_cast<uint32_t>(strtoul(row[49], nullptr, 10));
e.str = static_cast<uint32_t>(strtoul(row[50], nullptr, 10));
e.sta = static_cast<uint32_t>(strtoul(row[51], nullptr, 10));
e.cha = static_cast<uint32_t>(strtoul(row[52], nullptr, 10));
e.dex = static_cast<uint32_t>(strtoul(row[53], nullptr, 10));
e.int_ = static_cast<uint32_t>(strtoul(row[54], nullptr, 10));
e.agi = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
e.wis = static_cast<uint32_t>(strtoul(row[56], nullptr, 10));
e.zone_change_count = static_cast<uint32_t>(strtoul(row[57], nullptr, 10));
e.toxicity = static_cast<uint32_t>(strtoul(row[58], nullptr, 10));
e.hunger_level = static_cast<uint32_t>(strtoul(row[59], nullptr, 10));
e.thirst_level = static_cast<uint32_t>(strtoul(row[60], nullptr, 10));
e.ability_up = static_cast<uint32_t>(strtoul(row[61], nullptr, 10));
e.ldon_points_guk = static_cast<uint32_t>(strtoul(row[62], nullptr, 10));
e.ldon_points_mir = static_cast<uint32_t>(strtoul(row[63], nullptr, 10));
e.ldon_points_mmc = static_cast<uint32_t>(strtoul(row[64], nullptr, 10));
e.ldon_points_ruj = static_cast<uint32_t>(strtoul(row[65], nullptr, 10));
e.ldon_points_tak = static_cast<uint32_t>(strtoul(row[66], nullptr, 10));
e.ldon_points_available = static_cast<uint32_t>(strtoul(row[67], nullptr, 10));
e.tribute_time_remaining = static_cast<uint32_t>(strtoul(row[68], nullptr, 10));
e.career_tribute_points = static_cast<uint32_t>(strtoul(row[69], nullptr, 10));
e.tribute_points = static_cast<uint32_t>(strtoul(row[70], nullptr, 10));
e.tribute_active = static_cast<uint32_t>(strtoul(row[71], nullptr, 10));
e.pvp_status = static_cast<uint8_t>(strtoul(row[72], nullptr, 10));
e.pvp_kills = static_cast<uint32_t>(strtoul(row[73], nullptr, 10));
e.pvp_deaths = static_cast<uint32_t>(strtoul(row[74], nullptr, 10));
e.pvp_current_points = static_cast<uint32_t>(strtoul(row[75], nullptr, 10));
e.pvp_career_points = static_cast<uint32_t>(strtoul(row[76], nullptr, 10));
e.pvp_best_kill_streak = static_cast<uint32_t>(strtoul(row[77], nullptr, 10));
e.pvp_worst_death_streak = static_cast<uint32_t>(strtoul(row[78], nullptr, 10));
e.pvp_current_kill_streak = static_cast<uint32_t>(strtoul(row[79], nullptr, 10));
e.pvp2 = static_cast<uint32_t>(strtoul(row[80], nullptr, 10));
e.pvp_type = static_cast<uint32_t>(strtoul(row[81], nullptr, 10));
e.show_helm = static_cast<uint32_t>(strtoul(row[82], nullptr, 10));
e.group_auto_consent = static_cast<uint8_t>(strtoul(row[83], nullptr, 10));
e.raid_auto_consent = static_cast<uint8_t>(strtoul(row[84], nullptr, 10));
e.guild_auto_consent = static_cast<uint8_t>(strtoul(row[85], nullptr, 10));
e.leadership_exp_on = static_cast<uint8_t>(strtoul(row[86], nullptr, 10));
e.RestTimer = static_cast<uint32_t>(strtoul(row[87], nullptr, 10));
e.air_remaining = static_cast<uint32_t>(strtoul(row[88], nullptr, 10));
e.autosplit_enabled = static_cast<uint32_t>(strtoul(row[89], nullptr, 10));
e.lfp = static_cast<uint8_t>(strtoul(row[90], nullptr, 10));
e.lfg = static_cast<uint8_t>(strtoul(row[91], nullptr, 10));
e.mailkey = row[92] ? row[92] : "";
e.xtargets = static_cast<uint8_t>(strtoul(row[93], nullptr, 10));
e.firstlogon = static_cast<int8_t>(atoi(row[94]));
e.e_aa_effects = static_cast<uint32_t>(strtoul(row[95], nullptr, 10));
e.e_percent_to_aa = static_cast<uint32_t>(strtoul(row[96], nullptr, 10));
e.e_expended_aa_spent = static_cast<uint32_t>(strtoul(row[97], nullptr, 10));
e.aa_points_spent_old = static_cast<uint32_t>(strtoul(row[98], nullptr, 10));
e.aa_points_old = static_cast<uint32_t>(strtoul(row[99], nullptr, 10));
e.e_last_invsnapshot = static_cast<uint32_t>(strtoul(row[100], nullptr, 10));
e.deleted_at = strtoll(row[101] ? row[101] : "-1", nullptr, 10);
e.exp_enabled = static_cast<uint8_t>(strtoul(row[38], nullptr, 10));
e.aa_points_spent = static_cast<uint32_t>(strtoul(row[39], nullptr, 10));
e.aa_exp = static_cast<uint32_t>(strtoul(row[40], nullptr, 10));
e.aa_points = static_cast<uint32_t>(strtoul(row[41], nullptr, 10));
e.group_leadership_exp = static_cast<uint32_t>(strtoul(row[42], nullptr, 10));
e.raid_leadership_exp = static_cast<uint32_t>(strtoul(row[43], nullptr, 10));
e.group_leadership_points = static_cast<uint32_t>(strtoul(row[44], nullptr, 10));
e.raid_leadership_points = static_cast<uint32_t>(strtoul(row[45], nullptr, 10));
e.points = static_cast<uint32_t>(strtoul(row[46], nullptr, 10));
e.cur_hp = static_cast<uint32_t>(strtoul(row[47], nullptr, 10));
e.mana = static_cast<uint32_t>(strtoul(row[48], nullptr, 10));
e.endurance = static_cast<uint32_t>(strtoul(row[49], nullptr, 10));
e.intoxication = static_cast<uint32_t>(strtoul(row[50], nullptr, 10));
e.str = static_cast<uint32_t>(strtoul(row[51], nullptr, 10));
e.sta = static_cast<uint32_t>(strtoul(row[52], nullptr, 10));
e.cha = static_cast<uint32_t>(strtoul(row[53], nullptr, 10));
e.dex = static_cast<uint32_t>(strtoul(row[54], nullptr, 10));
e.int_ = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
e.agi = static_cast<uint32_t>(strtoul(row[56], nullptr, 10));
e.wis = static_cast<uint32_t>(strtoul(row[57], nullptr, 10));
e.zone_change_count = static_cast<uint32_t>(strtoul(row[58], nullptr, 10));
e.toxicity = static_cast<uint32_t>(strtoul(row[59], nullptr, 10));
e.hunger_level = static_cast<uint32_t>(strtoul(row[60], nullptr, 10));
e.thirst_level = static_cast<uint32_t>(strtoul(row[61], nullptr, 10));
e.ability_up = static_cast<uint32_t>(strtoul(row[62], nullptr, 10));
e.ldon_points_guk = static_cast<uint32_t>(strtoul(row[63], nullptr, 10));
e.ldon_points_mir = static_cast<uint32_t>(strtoul(row[64], nullptr, 10));
e.ldon_points_mmc = static_cast<uint32_t>(strtoul(row[65], nullptr, 10));
e.ldon_points_ruj = static_cast<uint32_t>(strtoul(row[66], nullptr, 10));
e.ldon_points_tak = static_cast<uint32_t>(strtoul(row[67], nullptr, 10));
e.ldon_points_available = static_cast<uint32_t>(strtoul(row[68], nullptr, 10));
e.tribute_time_remaining = static_cast<uint32_t>(strtoul(row[69], nullptr, 10));
e.career_tribute_points = static_cast<uint32_t>(strtoul(row[70], nullptr, 10));
e.tribute_points = static_cast<uint32_t>(strtoul(row[71], nullptr, 10));
e.tribute_active = static_cast<uint32_t>(strtoul(row[72], nullptr, 10));
e.pvp_status = static_cast<uint8_t>(strtoul(row[73], nullptr, 10));
e.pvp_kills = static_cast<uint32_t>(strtoul(row[74], nullptr, 10));
e.pvp_deaths = static_cast<uint32_t>(strtoul(row[75], nullptr, 10));
e.pvp_current_points = static_cast<uint32_t>(strtoul(row[76], nullptr, 10));
e.pvp_career_points = static_cast<uint32_t>(strtoul(row[77], nullptr, 10));
e.pvp_best_kill_streak = static_cast<uint32_t>(strtoul(row[78], nullptr, 10));
e.pvp_worst_death_streak = static_cast<uint32_t>(strtoul(row[79], nullptr, 10));
e.pvp_current_kill_streak = static_cast<uint32_t>(strtoul(row[80], nullptr, 10));
e.pvp2 = static_cast<uint32_t>(strtoul(row[81], nullptr, 10));
e.pvp_type = static_cast<uint32_t>(strtoul(row[82], nullptr, 10));
e.show_helm = static_cast<uint32_t>(strtoul(row[83], nullptr, 10));
e.group_auto_consent = static_cast<uint8_t>(strtoul(row[84], nullptr, 10));
e.raid_auto_consent = static_cast<uint8_t>(strtoul(row[85], nullptr, 10));
e.guild_auto_consent = static_cast<uint8_t>(strtoul(row[86], nullptr, 10));
e.leadership_exp_on = static_cast<uint8_t>(strtoul(row[87], nullptr, 10));
e.RestTimer = static_cast<uint32_t>(strtoul(row[88], nullptr, 10));
e.air_remaining = static_cast<uint32_t>(strtoul(row[89], nullptr, 10));
e.autosplit_enabled = static_cast<uint32_t>(strtoul(row[90], nullptr, 10));
e.lfp = static_cast<uint8_t>(strtoul(row[91], nullptr, 10));
e.lfg = static_cast<uint8_t>(strtoul(row[92], nullptr, 10));
e.mailkey = row[93] ? row[93] : "";
e.xtargets = static_cast<uint8_t>(strtoul(row[94], nullptr, 10));
e.firstlogon = static_cast<int8_t>(atoi(row[95]));
e.e_aa_effects = static_cast<uint32_t>(strtoul(row[96], nullptr, 10));
e.e_percent_to_aa = static_cast<uint32_t>(strtoul(row[97], nullptr, 10));
e.e_expended_aa_spent = static_cast<uint32_t>(strtoul(row[98], nullptr, 10));
e.aa_points_spent_old = static_cast<uint32_t>(strtoul(row[99], nullptr, 10));
e.aa_points_old = static_cast<uint32_t>(strtoul(row[100], nullptr, 10));
e.e_last_invsnapshot = static_cast<uint32_t>(strtoul(row[101], nullptr, 10));
e.deleted_at = strtoll(row[102] ? row[102] : "-1", nullptr, 10);
return e;
}
@@ -690,70 +697,71 @@ public:
v.push_back(columns[35] + " = " + std::to_string(e.ability_time_minutes));
v.push_back(columns[36] + " = " + std::to_string(e.ability_time_hours));
v.push_back(columns[37] + " = " + std::to_string(e.exp));
v.push_back(columns[38] + " = " + std::to_string(e.aa_points_spent));
v.push_back(columns[39] + " = " + std::to_string(e.aa_exp));
v.push_back(columns[40] + " = " + std::to_string(e.aa_points));
v.push_back(columns[41] + " = " + std::to_string(e.group_leadership_exp));
v.push_back(columns[42] + " = " + std::to_string(e.raid_leadership_exp));
v.push_back(columns[43] + " = " + std::to_string(e.group_leadership_points));
v.push_back(columns[44] + " = " + std::to_string(e.raid_leadership_points));
v.push_back(columns[45] + " = " + std::to_string(e.points));
v.push_back(columns[46] + " = " + std::to_string(e.cur_hp));
v.push_back(columns[47] + " = " + std::to_string(e.mana));
v.push_back(columns[48] + " = " + std::to_string(e.endurance));
v.push_back(columns[49] + " = " + std::to_string(e.intoxication));
v.push_back(columns[50] + " = " + std::to_string(e.str));
v.push_back(columns[51] + " = " + std::to_string(e.sta));
v.push_back(columns[52] + " = " + std::to_string(e.cha));
v.push_back(columns[53] + " = " + std::to_string(e.dex));
v.push_back(columns[54] + " = " + std::to_string(e.int_));
v.push_back(columns[55] + " = " + std::to_string(e.agi));
v.push_back(columns[56] + " = " + std::to_string(e.wis));
v.push_back(columns[57] + " = " + std::to_string(e.zone_change_count));
v.push_back(columns[58] + " = " + std::to_string(e.toxicity));
v.push_back(columns[59] + " = " + std::to_string(e.hunger_level));
v.push_back(columns[60] + " = " + std::to_string(e.thirst_level));
v.push_back(columns[61] + " = " + std::to_string(e.ability_up));
v.push_back(columns[62] + " = " + std::to_string(e.ldon_points_guk));
v.push_back(columns[63] + " = " + std::to_string(e.ldon_points_mir));
v.push_back(columns[64] + " = " + std::to_string(e.ldon_points_mmc));
v.push_back(columns[65] + " = " + std::to_string(e.ldon_points_ruj));
v.push_back(columns[66] + " = " + std::to_string(e.ldon_points_tak));
v.push_back(columns[67] + " = " + std::to_string(e.ldon_points_available));
v.push_back(columns[68] + " = " + std::to_string(e.tribute_time_remaining));
v.push_back(columns[69] + " = " + std::to_string(e.career_tribute_points));
v.push_back(columns[70] + " = " + std::to_string(e.tribute_points));
v.push_back(columns[71] + " = " + std::to_string(e.tribute_active));
v.push_back(columns[72] + " = " + std::to_string(e.pvp_status));
v.push_back(columns[73] + " = " + std::to_string(e.pvp_kills));
v.push_back(columns[74] + " = " + std::to_string(e.pvp_deaths));
v.push_back(columns[75] + " = " + std::to_string(e.pvp_current_points));
v.push_back(columns[76] + " = " + std::to_string(e.pvp_career_points));
v.push_back(columns[77] + " = " + std::to_string(e.pvp_best_kill_streak));
v.push_back(columns[78] + " = " + std::to_string(e.pvp_worst_death_streak));
v.push_back(columns[79] + " = " + std::to_string(e.pvp_current_kill_streak));
v.push_back(columns[80] + " = " + std::to_string(e.pvp2));
v.push_back(columns[81] + " = " + std::to_string(e.pvp_type));
v.push_back(columns[82] + " = " + std::to_string(e.show_helm));
v.push_back(columns[83] + " = " + std::to_string(e.group_auto_consent));
v.push_back(columns[84] + " = " + std::to_string(e.raid_auto_consent));
v.push_back(columns[85] + " = " + std::to_string(e.guild_auto_consent));
v.push_back(columns[86] + " = " + std::to_string(e.leadership_exp_on));
v.push_back(columns[87] + " = " + std::to_string(e.RestTimer));
v.push_back(columns[88] + " = " + std::to_string(e.air_remaining));
v.push_back(columns[89] + " = " + std::to_string(e.autosplit_enabled));
v.push_back(columns[90] + " = " + std::to_string(e.lfp));
v.push_back(columns[91] + " = " + std::to_string(e.lfg));
v.push_back(columns[92] + " = '" + Strings::Escape(e.mailkey) + "'");
v.push_back(columns[93] + " = " + std::to_string(e.xtargets));
v.push_back(columns[94] + " = " + std::to_string(e.firstlogon));
v.push_back(columns[95] + " = " + std::to_string(e.e_aa_effects));
v.push_back(columns[96] + " = " + std::to_string(e.e_percent_to_aa));
v.push_back(columns[97] + " = " + std::to_string(e.e_expended_aa_spent));
v.push_back(columns[98] + " = " + std::to_string(e.aa_points_spent_old));
v.push_back(columns[99] + " = " + std::to_string(e.aa_points_old));
v.push_back(columns[100] + " = " + std::to_string(e.e_last_invsnapshot));
v.push_back(columns[101] + " = FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")");
v.push_back(columns[38] + " = " + std::to_string(e.exp_enabled));
v.push_back(columns[39] + " = " + std::to_string(e.aa_points_spent));
v.push_back(columns[40] + " = " + std::to_string(e.aa_exp));
v.push_back(columns[41] + " = " + std::to_string(e.aa_points));
v.push_back(columns[42] + " = " + std::to_string(e.group_leadership_exp));
v.push_back(columns[43] + " = " + std::to_string(e.raid_leadership_exp));
v.push_back(columns[44] + " = " + std::to_string(e.group_leadership_points));
v.push_back(columns[45] + " = " + std::to_string(e.raid_leadership_points));
v.push_back(columns[46] + " = " + std::to_string(e.points));
v.push_back(columns[47] + " = " + std::to_string(e.cur_hp));
v.push_back(columns[48] + " = " + std::to_string(e.mana));
v.push_back(columns[49] + " = " + std::to_string(e.endurance));
v.push_back(columns[50] + " = " + std::to_string(e.intoxication));
v.push_back(columns[51] + " = " + std::to_string(e.str));
v.push_back(columns[52] + " = " + std::to_string(e.sta));
v.push_back(columns[53] + " = " + std::to_string(e.cha));
v.push_back(columns[54] + " = " + std::to_string(e.dex));
v.push_back(columns[55] + " = " + std::to_string(e.int_));
v.push_back(columns[56] + " = " + std::to_string(e.agi));
v.push_back(columns[57] + " = " + std::to_string(e.wis));
v.push_back(columns[58] + " = " + std::to_string(e.zone_change_count));
v.push_back(columns[59] + " = " + std::to_string(e.toxicity));
v.push_back(columns[60] + " = " + std::to_string(e.hunger_level));
v.push_back(columns[61] + " = " + std::to_string(e.thirst_level));
v.push_back(columns[62] + " = " + std::to_string(e.ability_up));
v.push_back(columns[63] + " = " + std::to_string(e.ldon_points_guk));
v.push_back(columns[64] + " = " + std::to_string(e.ldon_points_mir));
v.push_back(columns[65] + " = " + std::to_string(e.ldon_points_mmc));
v.push_back(columns[66] + " = " + std::to_string(e.ldon_points_ruj));
v.push_back(columns[67] + " = " + std::to_string(e.ldon_points_tak));
v.push_back(columns[68] + " = " + std::to_string(e.ldon_points_available));
v.push_back(columns[69] + " = " + std::to_string(e.tribute_time_remaining));
v.push_back(columns[70] + " = " + std::to_string(e.career_tribute_points));
v.push_back(columns[71] + " = " + std::to_string(e.tribute_points));
v.push_back(columns[72] + " = " + std::to_string(e.tribute_active));
v.push_back(columns[73] + " = " + std::to_string(e.pvp_status));
v.push_back(columns[74] + " = " + std::to_string(e.pvp_kills));
v.push_back(columns[75] + " = " + std::to_string(e.pvp_deaths));
v.push_back(columns[76] + " = " + std::to_string(e.pvp_current_points));
v.push_back(columns[77] + " = " + std::to_string(e.pvp_career_points));
v.push_back(columns[78] + " = " + std::to_string(e.pvp_best_kill_streak));
v.push_back(columns[79] + " = " + std::to_string(e.pvp_worst_death_streak));
v.push_back(columns[80] + " = " + std::to_string(e.pvp_current_kill_streak));
v.push_back(columns[81] + " = " + std::to_string(e.pvp2));
v.push_back(columns[82] + " = " + std::to_string(e.pvp_type));
v.push_back(columns[83] + " = " + std::to_string(e.show_helm));
v.push_back(columns[84] + " = " + std::to_string(e.group_auto_consent));
v.push_back(columns[85] + " = " + std::to_string(e.raid_auto_consent));
v.push_back(columns[86] + " = " + std::to_string(e.guild_auto_consent));
v.push_back(columns[87] + " = " + std::to_string(e.leadership_exp_on));
v.push_back(columns[88] + " = " + std::to_string(e.RestTimer));
v.push_back(columns[89] + " = " + std::to_string(e.air_remaining));
v.push_back(columns[90] + " = " + std::to_string(e.autosplit_enabled));
v.push_back(columns[91] + " = " + std::to_string(e.lfp));
v.push_back(columns[92] + " = " + std::to_string(e.lfg));
v.push_back(columns[93] + " = '" + Strings::Escape(e.mailkey) + "'");
v.push_back(columns[94] + " = " + std::to_string(e.xtargets));
v.push_back(columns[95] + " = " + std::to_string(e.firstlogon));
v.push_back(columns[96] + " = " + std::to_string(e.e_aa_effects));
v.push_back(columns[97] + " = " + std::to_string(e.e_percent_to_aa));
v.push_back(columns[98] + " = " + std::to_string(e.e_expended_aa_spent));
v.push_back(columns[99] + " = " + std::to_string(e.aa_points_spent_old));
v.push_back(columns[100] + " = " + std::to_string(e.aa_points_old));
v.push_back(columns[101] + " = " + std::to_string(e.e_last_invsnapshot));
v.push_back(columns[102] + " = FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")");
auto results = db.QueryDatabase(
fmt::format(
@@ -813,6 +821,7 @@ public:
v.push_back(std::to_string(e.ability_time_minutes));
v.push_back(std::to_string(e.ability_time_hours));
v.push_back(std::to_string(e.exp));
v.push_back(std::to_string(e.exp_enabled));
v.push_back(std::to_string(e.aa_points_spent));
v.push_back(std::to_string(e.aa_exp));
v.push_back(std::to_string(e.aa_points));
@@ -944,6 +953,7 @@ public:
v.push_back(std::to_string(e.ability_time_minutes));
v.push_back(std::to_string(e.ability_time_hours));
v.push_back(std::to_string(e.exp));
v.push_back(std::to_string(e.exp_enabled));
v.push_back(std::to_string(e.aa_points_spent));
v.push_back(std::to_string(e.aa_exp));
v.push_back(std::to_string(e.aa_points));
@@ -1079,70 +1089,71 @@ public:
e.ability_time_minutes = static_cast<uint8_t>(strtoul(row[35], nullptr, 10));
e.ability_time_hours = static_cast<uint8_t>(strtoul(row[36], nullptr, 10));
e.exp = static_cast<uint32_t>(strtoul(row[37], nullptr, 10));
e.aa_points_spent = static_cast<uint32_t>(strtoul(row[38], nullptr, 10));
e.aa_exp = static_cast<uint32_t>(strtoul(row[39], nullptr, 10));
e.aa_points = static_cast<uint32_t>(strtoul(row[40], nullptr, 10));
e.group_leadership_exp = static_cast<uint32_t>(strtoul(row[41], nullptr, 10));
e.raid_leadership_exp = static_cast<uint32_t>(strtoul(row[42], nullptr, 10));
e.group_leadership_points = static_cast<uint32_t>(strtoul(row[43], nullptr, 10));
e.raid_leadership_points = static_cast<uint32_t>(strtoul(row[44], nullptr, 10));
e.points = static_cast<uint32_t>(strtoul(row[45], nullptr, 10));
e.cur_hp = static_cast<uint32_t>(strtoul(row[46], nullptr, 10));
e.mana = static_cast<uint32_t>(strtoul(row[47], nullptr, 10));
e.endurance = static_cast<uint32_t>(strtoul(row[48], nullptr, 10));
e.intoxication = static_cast<uint32_t>(strtoul(row[49], nullptr, 10));
e.str = static_cast<uint32_t>(strtoul(row[50], nullptr, 10));
e.sta = static_cast<uint32_t>(strtoul(row[51], nullptr, 10));
e.cha = static_cast<uint32_t>(strtoul(row[52], nullptr, 10));
e.dex = static_cast<uint32_t>(strtoul(row[53], nullptr, 10));
e.int_ = static_cast<uint32_t>(strtoul(row[54], nullptr, 10));
e.agi = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
e.wis = static_cast<uint32_t>(strtoul(row[56], nullptr, 10));
e.zone_change_count = static_cast<uint32_t>(strtoul(row[57], nullptr, 10));
e.toxicity = static_cast<uint32_t>(strtoul(row[58], nullptr, 10));
e.hunger_level = static_cast<uint32_t>(strtoul(row[59], nullptr, 10));
e.thirst_level = static_cast<uint32_t>(strtoul(row[60], nullptr, 10));
e.ability_up = static_cast<uint32_t>(strtoul(row[61], nullptr, 10));
e.ldon_points_guk = static_cast<uint32_t>(strtoul(row[62], nullptr, 10));
e.ldon_points_mir = static_cast<uint32_t>(strtoul(row[63], nullptr, 10));
e.ldon_points_mmc = static_cast<uint32_t>(strtoul(row[64], nullptr, 10));
e.ldon_points_ruj = static_cast<uint32_t>(strtoul(row[65], nullptr, 10));
e.ldon_points_tak = static_cast<uint32_t>(strtoul(row[66], nullptr, 10));
e.ldon_points_available = static_cast<uint32_t>(strtoul(row[67], nullptr, 10));
e.tribute_time_remaining = static_cast<uint32_t>(strtoul(row[68], nullptr, 10));
e.career_tribute_points = static_cast<uint32_t>(strtoul(row[69], nullptr, 10));
e.tribute_points = static_cast<uint32_t>(strtoul(row[70], nullptr, 10));
e.tribute_active = static_cast<uint32_t>(strtoul(row[71], nullptr, 10));
e.pvp_status = static_cast<uint8_t>(strtoul(row[72], nullptr, 10));
e.pvp_kills = static_cast<uint32_t>(strtoul(row[73], nullptr, 10));
e.pvp_deaths = static_cast<uint32_t>(strtoul(row[74], nullptr, 10));
e.pvp_current_points = static_cast<uint32_t>(strtoul(row[75], nullptr, 10));
e.pvp_career_points = static_cast<uint32_t>(strtoul(row[76], nullptr, 10));
e.pvp_best_kill_streak = static_cast<uint32_t>(strtoul(row[77], nullptr, 10));
e.pvp_worst_death_streak = static_cast<uint32_t>(strtoul(row[78], nullptr, 10));
e.pvp_current_kill_streak = static_cast<uint32_t>(strtoul(row[79], nullptr, 10));
e.pvp2 = static_cast<uint32_t>(strtoul(row[80], nullptr, 10));
e.pvp_type = static_cast<uint32_t>(strtoul(row[81], nullptr, 10));
e.show_helm = static_cast<uint32_t>(strtoul(row[82], nullptr, 10));
e.group_auto_consent = static_cast<uint8_t>(strtoul(row[83], nullptr, 10));
e.raid_auto_consent = static_cast<uint8_t>(strtoul(row[84], nullptr, 10));
e.guild_auto_consent = static_cast<uint8_t>(strtoul(row[85], nullptr, 10));
e.leadership_exp_on = static_cast<uint8_t>(strtoul(row[86], nullptr, 10));
e.RestTimer = static_cast<uint32_t>(strtoul(row[87], nullptr, 10));
e.air_remaining = static_cast<uint32_t>(strtoul(row[88], nullptr, 10));
e.autosplit_enabled = static_cast<uint32_t>(strtoul(row[89], nullptr, 10));
e.lfp = static_cast<uint8_t>(strtoul(row[90], nullptr, 10));
e.lfg = static_cast<uint8_t>(strtoul(row[91], nullptr, 10));
e.mailkey = row[92] ? row[92] : "";
e.xtargets = static_cast<uint8_t>(strtoul(row[93], nullptr, 10));
e.firstlogon = static_cast<int8_t>(atoi(row[94]));
e.e_aa_effects = static_cast<uint32_t>(strtoul(row[95], nullptr, 10));
e.e_percent_to_aa = static_cast<uint32_t>(strtoul(row[96], nullptr, 10));
e.e_expended_aa_spent = static_cast<uint32_t>(strtoul(row[97], nullptr, 10));
e.aa_points_spent_old = static_cast<uint32_t>(strtoul(row[98], nullptr, 10));
e.aa_points_old = static_cast<uint32_t>(strtoul(row[99], nullptr, 10));
e.e_last_invsnapshot = static_cast<uint32_t>(strtoul(row[100], nullptr, 10));
e.deleted_at = strtoll(row[101] ? row[101] : "-1", nullptr, 10);
e.exp_enabled = static_cast<uint8_t>(strtoul(row[38], nullptr, 10));
e.aa_points_spent = static_cast<uint32_t>(strtoul(row[39], nullptr, 10));
e.aa_exp = static_cast<uint32_t>(strtoul(row[40], nullptr, 10));
e.aa_points = static_cast<uint32_t>(strtoul(row[41], nullptr, 10));
e.group_leadership_exp = static_cast<uint32_t>(strtoul(row[42], nullptr, 10));
e.raid_leadership_exp = static_cast<uint32_t>(strtoul(row[43], nullptr, 10));
e.group_leadership_points = static_cast<uint32_t>(strtoul(row[44], nullptr, 10));
e.raid_leadership_points = static_cast<uint32_t>(strtoul(row[45], nullptr, 10));
e.points = static_cast<uint32_t>(strtoul(row[46], nullptr, 10));
e.cur_hp = static_cast<uint32_t>(strtoul(row[47], nullptr, 10));
e.mana = static_cast<uint32_t>(strtoul(row[48], nullptr, 10));
e.endurance = static_cast<uint32_t>(strtoul(row[49], nullptr, 10));
e.intoxication = static_cast<uint32_t>(strtoul(row[50], nullptr, 10));
e.str = static_cast<uint32_t>(strtoul(row[51], nullptr, 10));
e.sta = static_cast<uint32_t>(strtoul(row[52], nullptr, 10));
e.cha = static_cast<uint32_t>(strtoul(row[53], nullptr, 10));
e.dex = static_cast<uint32_t>(strtoul(row[54], nullptr, 10));
e.int_ = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
e.agi = static_cast<uint32_t>(strtoul(row[56], nullptr, 10));
e.wis = static_cast<uint32_t>(strtoul(row[57], nullptr, 10));
e.zone_change_count = static_cast<uint32_t>(strtoul(row[58], nullptr, 10));
e.toxicity = static_cast<uint32_t>(strtoul(row[59], nullptr, 10));
e.hunger_level = static_cast<uint32_t>(strtoul(row[60], nullptr, 10));
e.thirst_level = static_cast<uint32_t>(strtoul(row[61], nullptr, 10));
e.ability_up = static_cast<uint32_t>(strtoul(row[62], nullptr, 10));
e.ldon_points_guk = static_cast<uint32_t>(strtoul(row[63], nullptr, 10));
e.ldon_points_mir = static_cast<uint32_t>(strtoul(row[64], nullptr, 10));
e.ldon_points_mmc = static_cast<uint32_t>(strtoul(row[65], nullptr, 10));
e.ldon_points_ruj = static_cast<uint32_t>(strtoul(row[66], nullptr, 10));
e.ldon_points_tak = static_cast<uint32_t>(strtoul(row[67], nullptr, 10));
e.ldon_points_available = static_cast<uint32_t>(strtoul(row[68], nullptr, 10));
e.tribute_time_remaining = static_cast<uint32_t>(strtoul(row[69], nullptr, 10));
e.career_tribute_points = static_cast<uint32_t>(strtoul(row[70], nullptr, 10));
e.tribute_points = static_cast<uint32_t>(strtoul(row[71], nullptr, 10));
e.tribute_active = static_cast<uint32_t>(strtoul(row[72], nullptr, 10));
e.pvp_status = static_cast<uint8_t>(strtoul(row[73], nullptr, 10));
e.pvp_kills = static_cast<uint32_t>(strtoul(row[74], nullptr, 10));
e.pvp_deaths = static_cast<uint32_t>(strtoul(row[75], nullptr, 10));
e.pvp_current_points = static_cast<uint32_t>(strtoul(row[76], nullptr, 10));
e.pvp_career_points = static_cast<uint32_t>(strtoul(row[77], nullptr, 10));
e.pvp_best_kill_streak = static_cast<uint32_t>(strtoul(row[78], nullptr, 10));
e.pvp_worst_death_streak = static_cast<uint32_t>(strtoul(row[79], nullptr, 10));
e.pvp_current_kill_streak = static_cast<uint32_t>(strtoul(row[80], nullptr, 10));
e.pvp2 = static_cast<uint32_t>(strtoul(row[81], nullptr, 10));
e.pvp_type = static_cast<uint32_t>(strtoul(row[82], nullptr, 10));
e.show_helm = static_cast<uint32_t>(strtoul(row[83], nullptr, 10));
e.group_auto_consent = static_cast<uint8_t>(strtoul(row[84], nullptr, 10));
e.raid_auto_consent = static_cast<uint8_t>(strtoul(row[85], nullptr, 10));
e.guild_auto_consent = static_cast<uint8_t>(strtoul(row[86], nullptr, 10));
e.leadership_exp_on = static_cast<uint8_t>(strtoul(row[87], nullptr, 10));
e.RestTimer = static_cast<uint32_t>(strtoul(row[88], nullptr, 10));
e.air_remaining = static_cast<uint32_t>(strtoul(row[89], nullptr, 10));
e.autosplit_enabled = static_cast<uint32_t>(strtoul(row[90], nullptr, 10));
e.lfp = static_cast<uint8_t>(strtoul(row[91], nullptr, 10));
e.lfg = static_cast<uint8_t>(strtoul(row[92], nullptr, 10));
e.mailkey = row[93] ? row[93] : "";
e.xtargets = static_cast<uint8_t>(strtoul(row[94], nullptr, 10));
e.firstlogon = static_cast<int8_t>(atoi(row[95]));
e.e_aa_effects = static_cast<uint32_t>(strtoul(row[96], nullptr, 10));
e.e_percent_to_aa = static_cast<uint32_t>(strtoul(row[97], nullptr, 10));
e.e_expended_aa_spent = static_cast<uint32_t>(strtoul(row[98], nullptr, 10));
e.aa_points_spent_old = static_cast<uint32_t>(strtoul(row[99], nullptr, 10));
e.aa_points_old = static_cast<uint32_t>(strtoul(row[100], nullptr, 10));
e.e_last_invsnapshot = static_cast<uint32_t>(strtoul(row[101], nullptr, 10));
e.deleted_at = strtoll(row[102] ? row[102] : "-1", nullptr, 10);
all_entries.push_back(e);
}
@@ -1205,70 +1216,71 @@ public:
e.ability_time_minutes = static_cast<uint8_t>(strtoul(row[35], nullptr, 10));
e.ability_time_hours = static_cast<uint8_t>(strtoul(row[36], nullptr, 10));
e.exp = static_cast<uint32_t>(strtoul(row[37], nullptr, 10));
e.aa_points_spent = static_cast<uint32_t>(strtoul(row[38], nullptr, 10));
e.aa_exp = static_cast<uint32_t>(strtoul(row[39], nullptr, 10));
e.aa_points = static_cast<uint32_t>(strtoul(row[40], nullptr, 10));
e.group_leadership_exp = static_cast<uint32_t>(strtoul(row[41], nullptr, 10));
e.raid_leadership_exp = static_cast<uint32_t>(strtoul(row[42], nullptr, 10));
e.group_leadership_points = static_cast<uint32_t>(strtoul(row[43], nullptr, 10));
e.raid_leadership_points = static_cast<uint32_t>(strtoul(row[44], nullptr, 10));
e.points = static_cast<uint32_t>(strtoul(row[45], nullptr, 10));
e.cur_hp = static_cast<uint32_t>(strtoul(row[46], nullptr, 10));
e.mana = static_cast<uint32_t>(strtoul(row[47], nullptr, 10));
e.endurance = static_cast<uint32_t>(strtoul(row[48], nullptr, 10));
e.intoxication = static_cast<uint32_t>(strtoul(row[49], nullptr, 10));
e.str = static_cast<uint32_t>(strtoul(row[50], nullptr, 10));
e.sta = static_cast<uint32_t>(strtoul(row[51], nullptr, 10));
e.cha = static_cast<uint32_t>(strtoul(row[52], nullptr, 10));
e.dex = static_cast<uint32_t>(strtoul(row[53], nullptr, 10));
e.int_ = static_cast<uint32_t>(strtoul(row[54], nullptr, 10));
e.agi = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
e.wis = static_cast<uint32_t>(strtoul(row[56], nullptr, 10));
e.zone_change_count = static_cast<uint32_t>(strtoul(row[57], nullptr, 10));
e.toxicity = static_cast<uint32_t>(strtoul(row[58], nullptr, 10));
e.hunger_level = static_cast<uint32_t>(strtoul(row[59], nullptr, 10));
e.thirst_level = static_cast<uint32_t>(strtoul(row[60], nullptr, 10));
e.ability_up = static_cast<uint32_t>(strtoul(row[61], nullptr, 10));
e.ldon_points_guk = static_cast<uint32_t>(strtoul(row[62], nullptr, 10));
e.ldon_points_mir = static_cast<uint32_t>(strtoul(row[63], nullptr, 10));
e.ldon_points_mmc = static_cast<uint32_t>(strtoul(row[64], nullptr, 10));
e.ldon_points_ruj = static_cast<uint32_t>(strtoul(row[65], nullptr, 10));
e.ldon_points_tak = static_cast<uint32_t>(strtoul(row[66], nullptr, 10));
e.ldon_points_available = static_cast<uint32_t>(strtoul(row[67], nullptr, 10));
e.tribute_time_remaining = static_cast<uint32_t>(strtoul(row[68], nullptr, 10));
e.career_tribute_points = static_cast<uint32_t>(strtoul(row[69], nullptr, 10));
e.tribute_points = static_cast<uint32_t>(strtoul(row[70], nullptr, 10));
e.tribute_active = static_cast<uint32_t>(strtoul(row[71], nullptr, 10));
e.pvp_status = static_cast<uint8_t>(strtoul(row[72], nullptr, 10));
e.pvp_kills = static_cast<uint32_t>(strtoul(row[73], nullptr, 10));
e.pvp_deaths = static_cast<uint32_t>(strtoul(row[74], nullptr, 10));
e.pvp_current_points = static_cast<uint32_t>(strtoul(row[75], nullptr, 10));
e.pvp_career_points = static_cast<uint32_t>(strtoul(row[76], nullptr, 10));
e.pvp_best_kill_streak = static_cast<uint32_t>(strtoul(row[77], nullptr, 10));
e.pvp_worst_death_streak = static_cast<uint32_t>(strtoul(row[78], nullptr, 10));
e.pvp_current_kill_streak = static_cast<uint32_t>(strtoul(row[79], nullptr, 10));
e.pvp2 = static_cast<uint32_t>(strtoul(row[80], nullptr, 10));
e.pvp_type = static_cast<uint32_t>(strtoul(row[81], nullptr, 10));
e.show_helm = static_cast<uint32_t>(strtoul(row[82], nullptr, 10));
e.group_auto_consent = static_cast<uint8_t>(strtoul(row[83], nullptr, 10));
e.raid_auto_consent = static_cast<uint8_t>(strtoul(row[84], nullptr, 10));
e.guild_auto_consent = static_cast<uint8_t>(strtoul(row[85], nullptr, 10));
e.leadership_exp_on = static_cast<uint8_t>(strtoul(row[86], nullptr, 10));
e.RestTimer = static_cast<uint32_t>(strtoul(row[87], nullptr, 10));
e.air_remaining = static_cast<uint32_t>(strtoul(row[88], nullptr, 10));
e.autosplit_enabled = static_cast<uint32_t>(strtoul(row[89], nullptr, 10));
e.lfp = static_cast<uint8_t>(strtoul(row[90], nullptr, 10));
e.lfg = static_cast<uint8_t>(strtoul(row[91], nullptr, 10));
e.mailkey = row[92] ? row[92] : "";
e.xtargets = static_cast<uint8_t>(strtoul(row[93], nullptr, 10));
e.firstlogon = static_cast<int8_t>(atoi(row[94]));
e.e_aa_effects = static_cast<uint32_t>(strtoul(row[95], nullptr, 10));
e.e_percent_to_aa = static_cast<uint32_t>(strtoul(row[96], nullptr, 10));
e.e_expended_aa_spent = static_cast<uint32_t>(strtoul(row[97], nullptr, 10));
e.aa_points_spent_old = static_cast<uint32_t>(strtoul(row[98], nullptr, 10));
e.aa_points_old = static_cast<uint32_t>(strtoul(row[99], nullptr, 10));
e.e_last_invsnapshot = static_cast<uint32_t>(strtoul(row[100], nullptr, 10));
e.deleted_at = strtoll(row[101] ? row[101] : "-1", nullptr, 10);
e.exp_enabled = static_cast<uint8_t>(strtoul(row[38], nullptr, 10));
e.aa_points_spent = static_cast<uint32_t>(strtoul(row[39], nullptr, 10));
e.aa_exp = static_cast<uint32_t>(strtoul(row[40], nullptr, 10));
e.aa_points = static_cast<uint32_t>(strtoul(row[41], nullptr, 10));
e.group_leadership_exp = static_cast<uint32_t>(strtoul(row[42], nullptr, 10));
e.raid_leadership_exp = static_cast<uint32_t>(strtoul(row[43], nullptr, 10));
e.group_leadership_points = static_cast<uint32_t>(strtoul(row[44], nullptr, 10));
e.raid_leadership_points = static_cast<uint32_t>(strtoul(row[45], nullptr, 10));
e.points = static_cast<uint32_t>(strtoul(row[46], nullptr, 10));
e.cur_hp = static_cast<uint32_t>(strtoul(row[47], nullptr, 10));
e.mana = static_cast<uint32_t>(strtoul(row[48], nullptr, 10));
e.endurance = static_cast<uint32_t>(strtoul(row[49], nullptr, 10));
e.intoxication = static_cast<uint32_t>(strtoul(row[50], nullptr, 10));
e.str = static_cast<uint32_t>(strtoul(row[51], nullptr, 10));
e.sta = static_cast<uint32_t>(strtoul(row[52], nullptr, 10));
e.cha = static_cast<uint32_t>(strtoul(row[53], nullptr, 10));
e.dex = static_cast<uint32_t>(strtoul(row[54], nullptr, 10));
e.int_ = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
e.agi = static_cast<uint32_t>(strtoul(row[56], nullptr, 10));
e.wis = static_cast<uint32_t>(strtoul(row[57], nullptr, 10));
e.zone_change_count = static_cast<uint32_t>(strtoul(row[58], nullptr, 10));
e.toxicity = static_cast<uint32_t>(strtoul(row[59], nullptr, 10));
e.hunger_level = static_cast<uint32_t>(strtoul(row[60], nullptr, 10));
e.thirst_level = static_cast<uint32_t>(strtoul(row[61], nullptr, 10));
e.ability_up = static_cast<uint32_t>(strtoul(row[62], nullptr, 10));
e.ldon_points_guk = static_cast<uint32_t>(strtoul(row[63], nullptr, 10));
e.ldon_points_mir = static_cast<uint32_t>(strtoul(row[64], nullptr, 10));
e.ldon_points_mmc = static_cast<uint32_t>(strtoul(row[65], nullptr, 10));
e.ldon_points_ruj = static_cast<uint32_t>(strtoul(row[66], nullptr, 10));
e.ldon_points_tak = static_cast<uint32_t>(strtoul(row[67], nullptr, 10));
e.ldon_points_available = static_cast<uint32_t>(strtoul(row[68], nullptr, 10));
e.tribute_time_remaining = static_cast<uint32_t>(strtoul(row[69], nullptr, 10));
e.career_tribute_points = static_cast<uint32_t>(strtoul(row[70], nullptr, 10));
e.tribute_points = static_cast<uint32_t>(strtoul(row[71], nullptr, 10));
e.tribute_active = static_cast<uint32_t>(strtoul(row[72], nullptr, 10));
e.pvp_status = static_cast<uint8_t>(strtoul(row[73], nullptr, 10));
e.pvp_kills = static_cast<uint32_t>(strtoul(row[74], nullptr, 10));
e.pvp_deaths = static_cast<uint32_t>(strtoul(row[75], nullptr, 10));
e.pvp_current_points = static_cast<uint32_t>(strtoul(row[76], nullptr, 10));
e.pvp_career_points = static_cast<uint32_t>(strtoul(row[77], nullptr, 10));
e.pvp_best_kill_streak = static_cast<uint32_t>(strtoul(row[78], nullptr, 10));
e.pvp_worst_death_streak = static_cast<uint32_t>(strtoul(row[79], nullptr, 10));
e.pvp_current_kill_streak = static_cast<uint32_t>(strtoul(row[80], nullptr, 10));
e.pvp2 = static_cast<uint32_t>(strtoul(row[81], nullptr, 10));
e.pvp_type = static_cast<uint32_t>(strtoul(row[82], nullptr, 10));
e.show_helm = static_cast<uint32_t>(strtoul(row[83], nullptr, 10));
e.group_auto_consent = static_cast<uint8_t>(strtoul(row[84], nullptr, 10));
e.raid_auto_consent = static_cast<uint8_t>(strtoul(row[85], nullptr, 10));
e.guild_auto_consent = static_cast<uint8_t>(strtoul(row[86], nullptr, 10));
e.leadership_exp_on = static_cast<uint8_t>(strtoul(row[87], nullptr, 10));
e.RestTimer = static_cast<uint32_t>(strtoul(row[88], nullptr, 10));
e.air_remaining = static_cast<uint32_t>(strtoul(row[89], nullptr, 10));
e.autosplit_enabled = static_cast<uint32_t>(strtoul(row[90], nullptr, 10));
e.lfp = static_cast<uint8_t>(strtoul(row[91], nullptr, 10));
e.lfg = static_cast<uint8_t>(strtoul(row[92], nullptr, 10));
e.mailkey = row[93] ? row[93] : "";
e.xtargets = static_cast<uint8_t>(strtoul(row[94], nullptr, 10));
e.firstlogon = static_cast<int8_t>(atoi(row[95]));
e.e_aa_effects = static_cast<uint32_t>(strtoul(row[96], nullptr, 10));
e.e_percent_to_aa = static_cast<uint32_t>(strtoul(row[97], nullptr, 10));
e.e_expended_aa_spent = static_cast<uint32_t>(strtoul(row[98], nullptr, 10));
e.aa_points_spent_old = static_cast<uint32_t>(strtoul(row[99], nullptr, 10));
e.aa_points_old = static_cast<uint32_t>(strtoul(row[100], nullptr, 10));
e.e_last_invsnapshot = static_cast<uint32_t>(strtoul(row[101], nullptr, 10));
e.deleted_at = strtoll(row[102] ? row[102] : "-1", nullptr, 10);
all_entries.push_back(e);
}
@@ -21,6 +21,7 @@ public:
struct CharacterExpModifiers {
int32_t character_id;
int32_t zone_id;
int32_t instance_version;
float aa_modifier;
float exp_modifier;
};
@@ -35,6 +36,7 @@ public:
return {
"character_id",
"zone_id",
"instance_version",
"aa_modifier",
"exp_modifier",
};
@@ -45,6 +47,7 @@ public:
return {
"character_id",
"zone_id",
"instance_version",
"aa_modifier",
"exp_modifier",
};
@@ -87,10 +90,11 @@ public:
{
CharacterExpModifiers e{};
e.character_id = 0;
e.zone_id = 0;
e.aa_modifier = 0;
e.exp_modifier = 0;
e.character_id = 0;
e.zone_id = 0;
e.instance_version = -1;
e.aa_modifier = 0;
e.exp_modifier = 0;
return e;
}
@@ -126,10 +130,11 @@ public:
if (results.RowCount() == 1) {
CharacterExpModifiers e{};
e.character_id = static_cast<int32_t>(atoi(row[0]));
e.zone_id = static_cast<int32_t>(atoi(row[1]));
e.aa_modifier = strtof(row[2], nullptr);
e.exp_modifier = strtof(row[3], nullptr);
e.character_id = static_cast<int32_t>(atoi(row[0]));
e.zone_id = static_cast<int32_t>(atoi(row[1]));
e.instance_version = static_cast<int32_t>(atoi(row[2]));
e.aa_modifier = strtof(row[3], nullptr);
e.exp_modifier = strtof(row[4], nullptr);
return e;
}
@@ -165,8 +170,9 @@ public:
v.push_back(columns[0] + " = " + std::to_string(e.character_id));
v.push_back(columns[1] + " = " + std::to_string(e.zone_id));
v.push_back(columns[2] + " = " + std::to_string(e.aa_modifier));
v.push_back(columns[3] + " = " + std::to_string(e.exp_modifier));
v.push_back(columns[2] + " = " + std::to_string(e.instance_version));
v.push_back(columns[3] + " = " + std::to_string(e.aa_modifier));
v.push_back(columns[4] + " = " + std::to_string(e.exp_modifier));
auto results = db.QueryDatabase(
fmt::format(
@@ -190,6 +196,7 @@ public:
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.zone_id));
v.push_back(std::to_string(e.instance_version));
v.push_back(std::to_string(e.aa_modifier));
v.push_back(std::to_string(e.exp_modifier));
@@ -223,6 +230,7 @@ public:
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.zone_id));
v.push_back(std::to_string(e.instance_version));
v.push_back(std::to_string(e.aa_modifier));
v.push_back(std::to_string(e.exp_modifier));
@@ -258,10 +266,11 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
CharacterExpModifiers e{};
e.character_id = static_cast<int32_t>(atoi(row[0]));
e.zone_id = static_cast<int32_t>(atoi(row[1]));
e.aa_modifier = strtof(row[2], nullptr);
e.exp_modifier = strtof(row[3], nullptr);
e.character_id = static_cast<int32_t>(atoi(row[0]));
e.zone_id = static_cast<int32_t>(atoi(row[1]));
e.instance_version = static_cast<int32_t>(atoi(row[2]));
e.aa_modifier = strtof(row[3], nullptr);
e.exp_modifier = strtof(row[4], nullptr);
all_entries.push_back(e);
}
@@ -286,10 +295,11 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
CharacterExpModifiers e{};
e.character_id = static_cast<int32_t>(atoi(row[0]));
e.zone_id = static_cast<int32_t>(atoi(row[1]));
e.aa_modifier = strtof(row[2], nullptr);
e.exp_modifier = strtof(row[3], nullptr);
e.character_id = static_cast<int32_t>(atoi(row[0]));
e.zone_id = static_cast<int32_t>(atoi(row[1]));
e.instance_version = static_cast<int32_t>(atoi(row[2]));
e.aa_modifier = strtof(row[3], nullptr);
e.exp_modifier = strtof(row[4], nullptr);
all_entries.push_back(e);
}
@@ -0,0 +1,334 @@
/**
* 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_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H
#define EQEMU_BASE_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseChatchannelReservedNamesRepository {
public:
struct ChatchannelReservedNames {
int32_t id;
std::string name;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"name",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"name",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("chatchannel_reserved_names");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static ChatchannelReservedNames NewEntity()
{
ChatchannelReservedNames e{};
e.id = 0;
e.name = "";
return e;
}
static ChatchannelReservedNames GetChatchannelReservedNames(
const std::vector<ChatchannelReservedNames> &chatchannel_reserved_namess,
int chatchannel_reserved_names_id
)
{
for (auto &chatchannel_reserved_names : chatchannel_reserved_namess) {
if (chatchannel_reserved_names.id == chatchannel_reserved_names_id) {
return chatchannel_reserved_names;
}
}
return NewEntity();
}
static ChatchannelReservedNames FindOne(
Database& db,
int chatchannel_reserved_names_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
chatchannel_reserved_names_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
ChatchannelReservedNames e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.name = row[1] ? row[1] : "";
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int chatchannel_reserved_names_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
chatchannel_reserved_names_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const ChatchannelReservedNames &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'");
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static ChatchannelReservedNames InsertOne(
Database& db,
ChatchannelReservedNames e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.name) + "'");
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<ChatchannelReservedNames> &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.name) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<ChatchannelReservedNames> All(Database& db)
{
std::vector<ChatchannelReservedNames> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
ChatchannelReservedNames e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.name = row[1] ? row[1] : "";
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<ChatchannelReservedNames> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<ChatchannelReservedNames> 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) {
ChatchannelReservedNames e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.name = row[1] ? row[1] : "";
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_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H
@@ -0,0 +1,364 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
*/
#ifndef EQEMU_BASE_CHATCHANNELS_REPOSITORY_H
#define EQEMU_BASE_CHATCHANNELS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseChatchannelsRepository {
public:
struct Chatchannels {
int32_t id;
std::string name;
std::string owner;
std::string password;
int32_t minstatus;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"name",
"owner",
"password",
"minstatus",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"name",
"owner",
"password",
"minstatus",
};
}
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("chatchannels");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static Chatchannels NewEntity()
{
Chatchannels e{};
e.id = 0;
e.name = "";
e.owner = "";
e.password = "";
e.minstatus = 0;
return e;
}
static Chatchannels GetChatchannels(
const std::vector<Chatchannels> &chatchannelss,
int chatchannels_id
)
{
for (auto &chatchannels : chatchannelss) {
if (chatchannels.id == chatchannels_id) {
return chatchannels;
}
}
return NewEntity();
}
static Chatchannels FindOne(
Database& db,
int chatchannels_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
chatchannels_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
Chatchannels e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.name = row[1] ? row[1] : "";
e.owner = row[2] ? row[2] : "";
e.password = row[3] ? row[3] : "";
e.minstatus = static_cast<int32_t>(atoi(row[4]));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int chatchannels_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
chatchannels_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const Chatchannels &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'");
v.push_back(columns[2] + " = '" + Strings::Escape(e.owner) + "'");
v.push_back(columns[3] + " = '" + Strings::Escape(e.password) + "'");
v.push_back(columns[4] + " = " + std::to_string(e.minstatus));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static Chatchannels InsertOne(
Database& db,
Chatchannels e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.name) + "'");
v.push_back("'" + Strings::Escape(e.owner) + "'");
v.push_back("'" + Strings::Escape(e.password) + "'");
v.push_back(std::to_string(e.minstatus));
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<Chatchannels> &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.name) + "'");
v.push_back("'" + Strings::Escape(e.owner) + "'");
v.push_back("'" + Strings::Escape(e.password) + "'");
v.push_back(std::to_string(e.minstatus));
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<Chatchannels> All(Database& db)
{
std::vector<Chatchannels> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
Chatchannels e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.name = row[1] ? row[1] : "";
e.owner = row[2] ? row[2] : "";
e.password = row[3] ? row[3] : "";
e.minstatus = static_cast<int32_t>(atoi(row[4]));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<Chatchannels> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<Chatchannels> 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) {
Chatchannels e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.name = row[1] ? row[1] : "";
e.owner = row[2] ? row[2] : "";
e.password = row[3] ? row[3] : "";
e.minstatus = static_cast<int32_t>(atoi(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_CHATCHANNELS_REPOSITORY_H
@@ -0,0 +1,414 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
*/
#ifndef EQEMU_BASE_MERC_ARMORINFO_REPOSITORY_H
#define EQEMU_BASE_MERC_ARMORINFO_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseMercArmorinfoRepository {
public:
struct MercArmorinfo {
int32_t id;
uint32_t merc_npc_type_id;
uint8_t minlevel;
uint8_t maxlevel;
uint8_t texture;
uint8_t helmtexture;
uint32_t armortint_id;
uint8_t armortint_red;
uint8_t armortint_green;
uint8_t armortint_blue;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"merc_npc_type_id",
"minlevel",
"maxlevel",
"texture",
"helmtexture",
"armortint_id",
"armortint_red",
"armortint_green",
"armortint_blue",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"merc_npc_type_id",
"minlevel",
"maxlevel",
"texture",
"helmtexture",
"armortint_id",
"armortint_red",
"armortint_green",
"armortint_blue",
};
}
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("merc_armorinfo");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static MercArmorinfo NewEntity()
{
MercArmorinfo e{};
e.id = 0;
e.merc_npc_type_id = 0;
e.minlevel = 1;
e.maxlevel = 255;
e.texture = 0;
e.helmtexture = 0;
e.armortint_id = 0;
e.armortint_red = 0;
e.armortint_green = 0;
e.armortint_blue = 0;
return e;
}
static MercArmorinfo GetMercArmorinfo(
const std::vector<MercArmorinfo> &merc_armorinfos,
int merc_armorinfo_id
)
{
for (auto &merc_armorinfo : merc_armorinfos) {
if (merc_armorinfo.id == merc_armorinfo_id) {
return merc_armorinfo;
}
}
return NewEntity();
}
static MercArmorinfo FindOne(
Database& db,
int merc_armorinfo_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
merc_armorinfo_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
MercArmorinfo e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.merc_npc_type_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.minlevel = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
e.maxlevel = static_cast<uint8_t>(strtoul(row[3], nullptr, 10));
e.texture = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.helmtexture = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
e.armortint_id = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.armortint_red = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.armortint_green = static_cast<uint8_t>(strtoul(row[8], nullptr, 10));
e.armortint_blue = static_cast<uint8_t>(strtoul(row[9], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int merc_armorinfo_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
merc_armorinfo_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const MercArmorinfo &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.merc_npc_type_id));
v.push_back(columns[2] + " = " + std::to_string(e.minlevel));
v.push_back(columns[3] + " = " + std::to_string(e.maxlevel));
v.push_back(columns[4] + " = " + std::to_string(e.texture));
v.push_back(columns[5] + " = " + std::to_string(e.helmtexture));
v.push_back(columns[6] + " = " + std::to_string(e.armortint_id));
v.push_back(columns[7] + " = " + std::to_string(e.armortint_red));
v.push_back(columns[8] + " = " + std::to_string(e.armortint_green));
v.push_back(columns[9] + " = " + std::to_string(e.armortint_blue));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static MercArmorinfo InsertOne(
Database& db,
MercArmorinfo e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.merc_npc_type_id));
v.push_back(std::to_string(e.minlevel));
v.push_back(std::to_string(e.maxlevel));
v.push_back(std::to_string(e.texture));
v.push_back(std::to_string(e.helmtexture));
v.push_back(std::to_string(e.armortint_id));
v.push_back(std::to_string(e.armortint_red));
v.push_back(std::to_string(e.armortint_green));
v.push_back(std::to_string(e.armortint_blue));
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<MercArmorinfo> &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.merc_npc_type_id));
v.push_back(std::to_string(e.minlevel));
v.push_back(std::to_string(e.maxlevel));
v.push_back(std::to_string(e.texture));
v.push_back(std::to_string(e.helmtexture));
v.push_back(std::to_string(e.armortint_id));
v.push_back(std::to_string(e.armortint_red));
v.push_back(std::to_string(e.armortint_green));
v.push_back(std::to_string(e.armortint_blue));
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<MercArmorinfo> All(Database& db)
{
std::vector<MercArmorinfo> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
MercArmorinfo e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.merc_npc_type_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.minlevel = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
e.maxlevel = static_cast<uint8_t>(strtoul(row[3], nullptr, 10));
e.texture = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.helmtexture = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
e.armortint_id = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.armortint_red = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.armortint_green = static_cast<uint8_t>(strtoul(row[8], nullptr, 10));
e.armortint_blue = static_cast<uint8_t>(strtoul(row[9], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<MercArmorinfo> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<MercArmorinfo> 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) {
MercArmorinfo e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.merc_npc_type_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.minlevel = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
e.maxlevel = static_cast<uint8_t>(strtoul(row[3], nullptr, 10));
e.texture = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.helmtexture = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
e.armortint_id = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.armortint_red = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.armortint_green = static_cast<uint8_t>(strtoul(row[8], nullptr, 10));
e.armortint_blue = static_cast<uint8_t>(strtoul(row[9], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_MERC_ARMORINFO_REPOSITORY_H
@@ -0,0 +1,504 @@
/**
* 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_MERC_BUFFS_REPOSITORY_H
#define EQEMU_BASE_MERC_BUFFS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseMercBuffsRepository {
public:
struct MercBuffs {
uint32_t MercBuffId;
uint32_t MercId;
uint32_t SpellId;
uint32_t CasterLevel;
uint32_t DurationFormula;
int32_t TicsRemaining;
uint32_t PoisonCounters;
uint32_t DiseaseCounters;
uint32_t CurseCounters;
uint32_t CorruptionCounters;
uint32_t HitCount;
uint32_t MeleeRune;
uint32_t MagicRune;
int32_t dot_rune;
int32_t caston_x;
int8_t Persistent;
int32_t caston_y;
int32_t caston_z;
int32_t ExtraDIChance;
};
static std::string PrimaryKey()
{
return std::string("MercBuffId");
}
static std::vector<std::string> Columns()
{
return {
"MercBuffId",
"MercId",
"SpellId",
"CasterLevel",
"DurationFormula",
"TicsRemaining",
"PoisonCounters",
"DiseaseCounters",
"CurseCounters",
"CorruptionCounters",
"HitCount",
"MeleeRune",
"MagicRune",
"dot_rune",
"caston_x",
"Persistent",
"caston_y",
"caston_z",
"ExtraDIChance",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"MercBuffId",
"MercId",
"SpellId",
"CasterLevel",
"DurationFormula",
"TicsRemaining",
"PoisonCounters",
"DiseaseCounters",
"CurseCounters",
"CorruptionCounters",
"HitCount",
"MeleeRune",
"MagicRune",
"dot_rune",
"caston_x",
"Persistent",
"caston_y",
"caston_z",
"ExtraDIChance",
};
}
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("merc_buffs");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static MercBuffs NewEntity()
{
MercBuffs e{};
e.MercBuffId = 0;
e.MercId = 0;
e.SpellId = 0;
e.CasterLevel = 0;
e.DurationFormula = 0;
e.TicsRemaining = 0;
e.PoisonCounters = 0;
e.DiseaseCounters = 0;
e.CurseCounters = 0;
e.CorruptionCounters = 0;
e.HitCount = 0;
e.MeleeRune = 0;
e.MagicRune = 0;
e.dot_rune = 0;
e.caston_x = 0;
e.Persistent = 0;
e.caston_y = 0;
e.caston_z = 0;
e.ExtraDIChance = 0;
return e;
}
static MercBuffs GetMercBuffs(
const std::vector<MercBuffs> &merc_buffss,
int merc_buffs_id
)
{
for (auto &merc_buffs : merc_buffss) {
if (merc_buffs.MercBuffId == merc_buffs_id) {
return merc_buffs;
}
}
return NewEntity();
}
static MercBuffs FindOne(
Database& db,
int merc_buffs_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
merc_buffs_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
MercBuffs e{};
e.MercBuffId = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.MercId = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.SpellId = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.CasterLevel = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.DurationFormula = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.TicsRemaining = static_cast<int32_t>(atoi(row[5]));
e.PoisonCounters = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.DiseaseCounters = static_cast<uint32_t>(strtoul(row[7], nullptr, 10));
e.CurseCounters = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
e.CorruptionCounters = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
e.HitCount = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
e.MeleeRune = static_cast<uint32_t>(strtoul(row[11], nullptr, 10));
e.MagicRune = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.dot_rune = static_cast<int32_t>(atoi(row[13]));
e.caston_x = static_cast<int32_t>(atoi(row[14]));
e.Persistent = static_cast<int8_t>(atoi(row[15]));
e.caston_y = static_cast<int32_t>(atoi(row[16]));
e.caston_z = static_cast<int32_t>(atoi(row[17]));
e.ExtraDIChance = static_cast<int32_t>(atoi(row[18]));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int merc_buffs_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
merc_buffs_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const MercBuffs &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.MercId));
v.push_back(columns[2] + " = " + std::to_string(e.SpellId));
v.push_back(columns[3] + " = " + std::to_string(e.CasterLevel));
v.push_back(columns[4] + " = " + std::to_string(e.DurationFormula));
v.push_back(columns[5] + " = " + std::to_string(e.TicsRemaining));
v.push_back(columns[6] + " = " + std::to_string(e.PoisonCounters));
v.push_back(columns[7] + " = " + std::to_string(e.DiseaseCounters));
v.push_back(columns[8] + " = " + std::to_string(e.CurseCounters));
v.push_back(columns[9] + " = " + std::to_string(e.CorruptionCounters));
v.push_back(columns[10] + " = " + std::to_string(e.HitCount));
v.push_back(columns[11] + " = " + std::to_string(e.MeleeRune));
v.push_back(columns[12] + " = " + std::to_string(e.MagicRune));
v.push_back(columns[13] + " = " + std::to_string(e.dot_rune));
v.push_back(columns[14] + " = " + std::to_string(e.caston_x));
v.push_back(columns[15] + " = " + std::to_string(e.Persistent));
v.push_back(columns[16] + " = " + std::to_string(e.caston_y));
v.push_back(columns[17] + " = " + std::to_string(e.caston_z));
v.push_back(columns[18] + " = " + std::to_string(e.ExtraDIChance));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.MercBuffId
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static MercBuffs InsertOne(
Database& db,
MercBuffs e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.MercBuffId));
v.push_back(std::to_string(e.MercId));
v.push_back(std::to_string(e.SpellId));
v.push_back(std::to_string(e.CasterLevel));
v.push_back(std::to_string(e.DurationFormula));
v.push_back(std::to_string(e.TicsRemaining));
v.push_back(std::to_string(e.PoisonCounters));
v.push_back(std::to_string(e.DiseaseCounters));
v.push_back(std::to_string(e.CurseCounters));
v.push_back(std::to_string(e.CorruptionCounters));
v.push_back(std::to_string(e.HitCount));
v.push_back(std::to_string(e.MeleeRune));
v.push_back(std::to_string(e.MagicRune));
v.push_back(std::to_string(e.dot_rune));
v.push_back(std::to_string(e.caston_x));
v.push_back(std::to_string(e.Persistent));
v.push_back(std::to_string(e.caston_y));
v.push_back(std::to_string(e.caston_z));
v.push_back(std::to_string(e.ExtraDIChance));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.MercBuffId = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<MercBuffs> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.MercBuffId));
v.push_back(std::to_string(e.MercId));
v.push_back(std::to_string(e.SpellId));
v.push_back(std::to_string(e.CasterLevel));
v.push_back(std::to_string(e.DurationFormula));
v.push_back(std::to_string(e.TicsRemaining));
v.push_back(std::to_string(e.PoisonCounters));
v.push_back(std::to_string(e.DiseaseCounters));
v.push_back(std::to_string(e.CurseCounters));
v.push_back(std::to_string(e.CorruptionCounters));
v.push_back(std::to_string(e.HitCount));
v.push_back(std::to_string(e.MeleeRune));
v.push_back(std::to_string(e.MagicRune));
v.push_back(std::to_string(e.dot_rune));
v.push_back(std::to_string(e.caston_x));
v.push_back(std::to_string(e.Persistent));
v.push_back(std::to_string(e.caston_y));
v.push_back(std::to_string(e.caston_z));
v.push_back(std::to_string(e.ExtraDIChance));
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<MercBuffs> All(Database& db)
{
std::vector<MercBuffs> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
MercBuffs e{};
e.MercBuffId = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.MercId = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.SpellId = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.CasterLevel = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.DurationFormula = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.TicsRemaining = static_cast<int32_t>(atoi(row[5]));
e.PoisonCounters = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.DiseaseCounters = static_cast<uint32_t>(strtoul(row[7], nullptr, 10));
e.CurseCounters = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
e.CorruptionCounters = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
e.HitCount = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
e.MeleeRune = static_cast<uint32_t>(strtoul(row[11], nullptr, 10));
e.MagicRune = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.dot_rune = static_cast<int32_t>(atoi(row[13]));
e.caston_x = static_cast<int32_t>(atoi(row[14]));
e.Persistent = static_cast<int8_t>(atoi(row[15]));
e.caston_y = static_cast<int32_t>(atoi(row[16]));
e.caston_z = static_cast<int32_t>(atoi(row[17]));
e.ExtraDIChance = static_cast<int32_t>(atoi(row[18]));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<MercBuffs> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<MercBuffs> 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) {
MercBuffs e{};
e.MercBuffId = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.MercId = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.SpellId = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.CasterLevel = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.DurationFormula = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.TicsRemaining = static_cast<int32_t>(atoi(row[5]));
e.PoisonCounters = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.DiseaseCounters = static_cast<uint32_t>(strtoul(row[7], nullptr, 10));
e.CurseCounters = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
e.CorruptionCounters = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
e.HitCount = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
e.MeleeRune = static_cast<uint32_t>(strtoul(row[11], nullptr, 10));
e.MagicRune = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.dot_rune = static_cast<int32_t>(atoi(row[13]));
e.caston_x = static_cast<int32_t>(atoi(row[14]));
e.Persistent = static_cast<int8_t>(atoi(row[15]));
e.caston_y = static_cast<int32_t>(atoi(row[16]));
e.caston_z = static_cast<int32_t>(atoi(row[17]));
e.ExtraDIChance = static_cast<int32_t>(atoi(row[18]));
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_MERC_BUFFS_REPOSITORY_H

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