Compare commits

..

787 Commits

Author SHA1 Message Date
Akkadius dc64561b3c [Release] 22.2.0 2023-01-27 01:13:38 -06:00
Akkadius cb2aee2713 [Release] 22.2.0 2023-01-27 01:12:30 -06:00
Chris Miles 0730b6b588 [Crash] Fix crash issue with log formatting during character creation (#2798) 2023-01-26 20:40:58 -06:00
Aeadoin 826550acac [Bots] Add EVENT_UNEQUIP_ITEM_BOT & EVENT_EQUIP_ITEM_BOT (#2796)
* Initial Commit, need to test.

* Add unequip events.

* const auto
2023-01-26 19:49:20 -05:00
Alex King b71b3f5be0 [Bots] ^create and ^viewcombos popup messages fix. (#2797)
# Notes
- These messages were showing weirdly and inconsistently, cleaned them up to show at max 4 per line.
- `^viewcombos` now shows class name and ID in the popup title.
- `^create help` now shows proper class names and IDs instead of `{}`.
2023-01-26 18:44:21 -05:00
Natedog2012 1fe79f430c [Feature] ResetItemCooldown added to lua/perl and fix item re-cast times to show properly (#2793)
* Testing.

* Add ResetItemCooldown and port it over to perl

* This flag needs to be set for updating shared item cooldowns

* Properly set item recast for all item types, on corpses, on looting

* SummonItem properly sets recast timers of summoned items

* Rename variable to avoid confusion and change manifest to be more specific

* Sanity check item_d

* Recast -1 added as RECAST_TYPE_UNLINKED_ITEM
ResetItemCooldown will still remove cooldown of item that we don't have so when we acquire it the cooldown is reset

* change magic numbers

* more magic numbers

* More constants yay

* Remove unneeded export DeleteItemRecastTimer

* Remove duplicate message, this is handled by the client in this part of the code

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2023-01-25 20:09:08 -06:00
Alex King e5dabe0afc [Git] Add CMake Files to .gitignore (#2792)
* [Git] Add CMake Files to GitIgnore

* Update .drone.yml
2023-01-24 18:37:14 -06:00
Alex King 5720ffbcb6 [Release] 22.1.2 (#2791) 2023-01-24 17:18:42 -06:00
Alex King 2b0c778ad1 [Bug Fix] Fix nullptr spell in BCSpells::Load() (#2790)
* [Bug Fix] Fix nullptr spell in BCSpells::Load()

# Notes
- Fix possible `nullptr` where we didn't check if spell was valid before using it.

* Cleanup.
2023-01-24 17:57:12 -05:00
Alex King bf39a0540c [Cleanup] Cleanup #door Command. (#2783)
* [Cleanup] Cleanup #door Command.

# Notes
- Resolves an issue with `.1` versus `0.1`.
- Resolves an issue with updating a pre-existing door.
- Adds `heading` to the update/insert.

* Update doors.cpp
2023-01-24 16:37:21 -06:00
Chris Miles 08c8393988 [CI/CD] Build / Release Pipeline Changes (#2788)
* Test

* Test

* Update windows-build.ps1

* Update windows-build.ps1

* Update windows-build.ps1

* Kill excessive warnings

* Split

* Remove 7z from build scripts

* Linux

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Test

* Update .drone.yml

* Naming

* Test upload

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Yolo

* Yolo

* Update .drone.yml

* Update .drone.yml

* Copy

* Yolo

* Release without bots

* Update .drone.yml

* Update .drone.yml

* Test pipeline

* Remove debug

* Update .drone.yml

* Filter pipeline stage

* Update .drone.yml

* Test

* Bots release 22.0.5 (Test)

* Release bot test #2

* Check if release

* Update .drone.yml

* Update .drone.yml

* exit 78

* Update .drone.yml

* Update .drone.yml

* Add version checks

* Update .drone.yml

* Update .drone.yml

* Test

* Update build-release.bat

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Update build-release.bat

* Update build-release.bat

* Test pipeline

* Update CHANGELOG.md

* Bump

* Update build-release.bat

* Update build-release.bat

* Shuffle

* Take #45354

* Update windows-build.ps1

* Update windows-build.ps1

* Update windows-build.ps1

* F

* Update windows-build.ps1

* Consolidate

* Run it

* Pop cache back in

* Update linux-build.sh

* Another release test

* Update linux-build.sh

* Update linux-build.sh

* Update CMakeLists.txt

* Trim windows assets

* Update windows-build.ps1

* Update windows-build.ps1

* Update windows-build.ps1

* Update windows-build.ps1

* [22.1.0] Release

* Crash reporting

* Add version tag injection in the build pipeline

* Update windows-build.ps1

* Test

* Test

* Update windows-build.ps1

* Update windows-build.ps1

* Update windows-build.ps1

* Kill excessive warnings

* Split

* Remove 7z from build scripts

* Linux

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Test

* Update .drone.yml

* Naming

* Test upload

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Yolo

* Yolo

* Update .drone.yml

* Update .drone.yml

* Copy

* Yolo

* Release without bots

* Update .drone.yml

* Update .drone.yml

* Test pipeline

* Remove debug

* Update .drone.yml

* Filter pipeline stage

* Update .drone.yml

* Test

* Bots release 22.0.5 (Test)

* Release bot test #2

* Check if release

* Update .drone.yml

* Update .drone.yml

* exit 78

* Update .drone.yml

* Update .drone.yml

* Add version checks

* Update .drone.yml

* Update .drone.yml

* Test

* Update build-release.bat

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Update build-release.bat

* Update build-release.bat

* Test pipeline

* Update CHANGELOG.md

* Bump

* Update build-release.bat

* Update build-release.bat

* Shuffle

* Take #45354

* Update windows-build.ps1

* Update windows-build.ps1

* Update windows-build.ps1

* F

* Update windows-build.ps1

* Consolidate

* Run it

* Pop cache back in

* Update linux-build.sh

* Another release test

* Update linux-build.sh

* Update linux-build.sh

* Update CMakeLists.txt

* Trim windows assets

* Update windows-build.ps1

* Update windows-build.ps1

* Update windows-build.ps1

* Update windows-build.ps1

* [22.1.0] Release

* Crash reporting

* Add version tag injection in the build pipeline

* Update windows-build.ps1

* Full crash report on windows.

* Update endpoint

* [22.1.1] Release

* [skip ci] update .drone.yml

* Filter

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Update CHANGELOG.md

Co-authored-by: KimLS <KimLS@peqtgc.com>
2023-01-24 16:37:04 -06:00
Alex King 8c12f7b431 [Bug Fix] Remove duplicate logic in GetActSpellHealing reducing HOT criticals (#2786)
# Notes
- Removes duplicate critical chance roll in `Mob::GetActSpellHealing`.
- Not sure if this was Live-like or an oversight, but it seems to drastically reduce the possibility of a HOT getting a critical.
- A 1% chance becomes a 0.01% chance being we have to roll twice.
2023-01-24 12:39:46 -06:00
Chris Miles 037be84f38 [Crash] Fix rarer world crash issue where scheduler database was not available (#2789) 2023-01-24 12:38:26 -06:00
Aeadoin 4d355afe9d [Bug Fix] Fix scenario where dereferenced object could be null. (#2784) 2023-01-23 18:40:23 -05:00
Aeadoin 93eddf603b [Bug Fix] Fix botgrouplist to display unique entries. (#2785) 2023-01-23 18:39:55 -05:00
Aeadoin 293f79268d [Bots] Fix Slow Query in QueryNameAvailablity (#2781) 2023-01-22 18:26:57 -05:00
Chris Miles 7e35d5aa79 [AA] Fix AA tables dump (#2769) 2023-01-22 12:57:08 -05:00
Alex King f7e4fba584 [Bug Fix] Fix bots equipping augments. (#2772)
# Notes
- Bots didn't check if the item was an augment before equipping, this stops them from equipping them.
2023-01-22 12:57:00 -05:00
Alex King 01a0f906e1 [Bots] Add Bot Command Reloading (#2773)
# Notes
- Adds `bot_command_init` to `#reload commands` so that operators can reload bot commands if they enable/disable bots while the server is running.
2023-01-22 12:56:55 -05:00
Alex King 0a11eaa092 [Bug Fix] Fix #findaa and GetAAName(). (#2774)
# Notes
- These were not properly checking every possible AA ID.
2023-01-22 12:56:49 -05:00
Alex King d0edb93d62 [Commands] Remove #guildapprove, #guildcreate, and #guildlist Commands (#2775)
# Notes
- Removes `#guildapprove`, `#guildcreate`, and `#guildlist`.
- Removes associated functions, classes, etc. that were only used in these commands.
- These commands are unused and/or covered by the general `#guild` command.
- Approvals don't really seem to be a thing anymore and the variable itself doesn't exist in stock PEQ database anyway.
2023-01-22 12:56:42 -05:00
Alex King 35c3778baf [Commands] Remove #undyeme Command. (#2776)
# Notes
- Removes redundant `#undyeme` command.
- Adds `GetGM()` check to `#undye` so players can't undye other players.
2023-01-22 12:56:36 -05:00
Alex King abb41840f8 [Commands] Cleanup #appearanceeffects Command. (#2777)
# Notes
- Cleanup messages and logic.
2023-01-22 12:56:26 -05:00
Aeadoin cd63047e60 [Bug Fix] Fix Bot Group Loading (#2780)
* [Bots] Fix Bot Groups

* unsigned.
2023-01-22 12:06:13 -05:00
Paul Coene 4fe5522212 [Bug Fix] #scribespells triggered error on mysql keyword rank (#2779) 2023-01-21 18:02:27 -05:00
Akkadius 0ccb18d017 [Hotfix] Remove appveyor fetch bots 2023-01-20 20:56:19 -06:00
Aeadoin e010e41a83 [Bots] Add Virtual Override for Bot::Attack (#2771) 2023-01-20 17:13:40 -05:00
Aeadoin 886f80117c [Cleanup] Merge Client::Attack and Bot::Attack into Mob::Attack (#2756)
* [Cleanup] Merge Client::Attack and Bot::Attack into Mob::Attack (#11)

* Remove #ifdef Bots to go along with KK fix

* Remove method in logging

* remove method from logging

* Fixes

* Rename
2023-01-20 15:52:45 -05: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
JJ d22fca7593 [Database Updates] Typo in manifest 9207 (#2451) 2022-09-27 20:21:09 -05:00
Aeadoin 2b203c0ebe [Bug Fix] Fix Swarm Pet Flurry/Rampages Messages (#2444)
* Fix Swarm Pet Flurry/Rampages Messages

* Fixed formatting
2022-09-25 13:00:43 -04:00
Chris Miles c826d3b4e9 [eqemu_server.pl] Remove non-working fetch_latest_windows_binaries() (#2445) 2022-09-25 13:00:33 -04:00
Chris Miles 78a9de124e [Command] Fix #copycharacter command crash (#2446) 2022-09-25 13:00:25 -04:00
Aeadoin 1ce272a1c3 [Feature] Allow Focus Effects to be Filtered out. (#2447) 2022-09-25 13:00:19 -04:00
Michael Cook (mackal) 678a4e30f5 Define is _WINDOWS not WINDOWS (#2439) 2022-09-21 12:43:38 -04:00
hg dbf8440a32 [Quest API] Let HasQuestSub check encounters (#2435)
This fixes an edge case where trading would not detect the npc had a
quest handler if it was registered inside a Lua encounter.
2022-09-20 13:21:48 -04:00
Aeadoin b2a73dc572 [Feature] Add Type 49545 to Spell Resistrictions (#2436) 2022-09-20 09:06:23 -04:00
Aeadoin 406ea039d7 [Bug Fix] Fix Spellinfo Command to work with SpellIDs above int16 (#2437)
* Fix Spellinfo Command SpellIDs to work above int16

* Updated to use int32_t
2022-09-20 09:06:01 -04:00
hg b4e46c1f7e [Tasks] Let task reward find free bag slots (#2431) 2022-09-18 10:45:34 -04:00
Chris Miles 5502ab8765 [Pathing] Fix pathing z-correctness for certain models (#2430)
* [Pathing] Fix pathing z-correctness for certain models

* Update npc.cpp

* Update npc.cpp

* Update npc.cpp
2022-09-11 13:05:20 -04:00
Aeadoin 7dc9b40ee1 [Feature] Update HateMod used by SPA 114 to Int32. (#2428) 2022-09-08 07:49:13 -04:00
hg 2c9fe4f2b8 [Tasks] Add rule to update multiple task elements (#2427)
On live if a task update would affect multiple elements, only the first
one gets updated. This was added as part of the changes in 7482cfc0.

Setting `UpdateOneElementPerTask` to false will restore the old behavior
that increments all active elements matching the task update criteria.
2022-09-06 12:42:45 -04:00
hg 78223b7ebf [Commands] Make #damage require a target (#2426)
Fixes annoying issue where it affected the client if no target
2022-09-05 12:12:46 -05:00
Michael Cook (mackal) 73f310d098 I guess we'll go plural (#2425) 2022-09-05 10:54:33 -04:00
Akkadius f22d90f6e2 [Hotfix] Add Bazaar portal discs to SQL 2022-09-05 04:30:49 -05:00
Chris Miles 78d4bd464e [Zone Points] Fix zone point heading data (#2415)
* [Zone Points] Fix zone point heading data

* Update 2022_09_03_fix_zone_point_heading_data.sql

* Augment #showzonepoints with saylinks

* Add more heading fixes to zone points

* Account for 999 target_heading

* Add zone safe headings
2022-09-05 04:08:34 -05:00
Chris Miles 186c2fe2ae [Doors] Fix door target zone heading data (#2414)
* [Doors] Fix door target zone heading

* Fix even more doors that were wrong to be accurate to live

* Update version.h
2022-09-05 04:06:39 -05:00
Chris Miles 5250b819fa [Character Starting Points] Fix headings data (#2413)
* [Character Starting Points] Fix headings

* Update version.h

Co-authored-by: Michael Cook (mackal) <277429+mackal@users.noreply.github.com>
2022-09-05 04:02:47 -05:00
Akkadius da4bcbf736 [Hotfix] Faction associations file naming / lock consistency 2022-09-05 00:10:21 -05:00
Michael Cook (mackal) d8134df679 Clang was complaining about these (#2421)
Checking if first char is null should be faster than strlen
2022-09-03 17:36:45 -04:00
hg 89382d5e4a [Tasks] Only allow shared task completion once (#2422)
This prevents re-triggering completion when a shared task contains
optional elements
2022-09-03 16:25:18 -05:00
hg aa3c72c1de [Tasks] Make Task Selector Cooldown Optional (#2420)
Some live npcs ignore the request cooldown timer (tutorialb)

A separate function had to be used for perl because the apis use an
array instead of array reference which won't allow a bool overload

This also replaces the fixed array and count args with a vector
2022-09-03 13:20:03 -04:00
Michael Cook (mackal) 5e9a9e8afe [Bug Fix] Shared Memory Faction Association Typo (#2419) 2022-09-03 12:08:40 -04:00
Michael Cook (mackal) ba53b4144e [Cleanup] Rework Lua QuestReward to not use try/catch blocks (#2417)
Quest system will catch any errors and result it in being reported where
these weren't
2022-09-03 12:07:46 -04:00
Kinglykrab 5134a0e43b [NPC Scaling] Recalculate Skills and Reload Spells on Level Change (#2416)
* [NPC Scaling] Recalculate Skills and Reload Spells on Level Change

- Add $npc->ReloadSpells() to Perl.
- Add npc:ReloadSpells() to Lua.

Previously, you would you have to manually call RecalculateSkills() after you scale the NPC, now the call is built in to the scaling.

Spells did not reload when NPCs were scaled, causing them to continue to use their low/high level spells depending upon which way their level had been scaled, this has been adding to the scaling method. This will make NPCs properly use their level-based spells.

RecalculateSkills() and ReloadSpells() can still be used manually if people scale using something other than the source scaling method. Having this functionality built in to the scaling itself just makes more sense to me. Open to any  ideas or thoughts.

* Reload spell effects, too.
2022-09-03 12:06:33 -04:00
Michael Cook (mackal) 402d742def Unsure how this seding messed up (#2418) 2022-09-03 11:53:43 -04:00
Michael Cook (mackal) 2b4e555eae [Feature] Faction Association (#2408)
* Add faction logging category

Probably should use this for more things

* Add FactionAssociation struct

This is simply just a struct that contains an array of faction ids and
multiplier. This can hold a maximum of 10 entries (Seru hit is 8, so 2
extra) this can be raised if need be.

* Add database changes and other data point changes

This is all the database changes and loading changes

Included is an optional SQL that will be used as a starting point, there
is likely errors or typos, but we will fix those as they are discovered.

* Add Client::RewardFaction function

This just takes the faction ID and the magnitude of the primary faction
hit and calculates the rest.

The minimum change will be either 1 or -1. We stop processing after we
see an ID of 0 and assume there will be no later entries.

The primary faction ID will always receive a hit even if there is no
faction association entries

* Add users of RewardFaction to NPC death, tasks, and QuestRewards

This will only use the new system if the magnitude is set, otherwise we
will just use the old system still

* Add quest system calls and lua QuestReward support

* Add #factionassociation command

This just calls RewardFaction, mostly useful for debugging
2022-09-03 10:57:55 -04:00
hg efe1879115 [Tasks] Change zone task data container (#2410)
This allows removal of the task id limit (MAXTASKS)

There's some suspect places task data isn't verified but left unchanged

If memory use becomes too high once more live data is added tasks can be
stored in shared memory instead
2022-09-03 03:33:49 -05:00
Chris Miles ec857cefae [Zoning] Fix zoning logic issues (#2412)
* [Zoning] Fix various zoning issues, flag logic, #zone etc

* Enforce character restrictions later in the connection process so we don't end up in a loop race condition in world
2022-09-03 00:57:57 -05:00
hg 034667f03b [Bug Fix] Avoid erase in discord queue range loop (#2411)
Erasing from the map inside the range loop invalidated the iterator used
internally by the loop. This caused ucs access violations under msvc
debug builds when a discord logging category was enabled.
2022-09-02 21:49:14 -05:00
hg d12145c449 [Bug Fix] Fix memory leak in ucs (#2409) 2022-09-02 21:48:33 -05:00
hg ce12481021 [Tasks] Tweak task update messages (#2406)
Excludes GiveCash since it uses copper amount for increments
2022-09-01 23:10:05 -05:00
hg 7cf96ca2d8 [Tasks] Remove delivered task items from trades (#2405) 2022-09-01 23:09:13 -05:00
hg e011864ed5 [Zone] Add missing safe_heading assignment (#2407)
Regression from 89fdd842e1
2022-09-01 23:04:35 -05:00
hg 7482cfc066 [Tasks] Replace task goals with explicit fields (#2402)
The task goal system made implementing tasks a little confusing since
the goal could be ambiguous depending on type. This also didn't support
filtering on multiple goals (e.g. looting items from matching npc names
inside an area). Deliver types could specify an npc id in `delivertonpc`
but the database may have multiple npcs with the same name or a task
might want to match partial npc names.

This replaces goalids with explicit fields for npcs, items, proximity
areas, and touch switch ids. These changes make managing task data
easier without needing to update multiple tables and allows filtering
task updates by multiple criteria. To mitigate any performance impact
from merging task proximities, only clients with explore tasks in the
current zone are checked during client movement updates.

Items and npcs still support goallists but it would be possible to
denormalize entries into delimited strings to combine with the match
lists. This would also decouple task goals from reward lists.

The client task update functions were refactored to run through a single
filtering function which significantly reduces duplicated code from the
legacy task system. This will also make it easier to later implement
any unhandled types.

Since the new fields will handle filtering single entries and lists
based on having values set, `goalmethod` now only distinguishes quest
controlled from source controlled.

This is a breaking api change, `taskexploredarea` has been removed
since explore ids no longer exist.
2022-09-01 19:18:21 -05:00
Michael Cook (mackal) 8851b410d2 [Bug Fix] Resolve logic error in Raid::QueueClients (#2404)
We're checking if they're groupless here, so this should be correct now
2022-09-01 18:48:47 -05:00
Chris Miles 89fdd842e1 [Code Cleanup] Zone Data Loading Refactor (#2388)
* [Code Cleanup] Zone data loading refactor

* Update client_packet.cpp

* strcpy adjustments

* Ensure safe points get reloaded properly

* Simplify GetPEQZone and getZoneShutDownDelay

* Bring in zone_store where needed

* Update client.cpp

* Signature

* Signature

* Convert helpers to using pointers

* PR comment

* Update worlddb.cpp

* Fix loading for instances

* Fix zoning with fallback as well

* Another place for instance fallback
2022-09-01 18:48:28 -05:00
Michael Cook (mackal) c613dbb2f7 Fix issues with Client::SetHideMe (#2403)
Arg was shadowing the member variable and we weren't updating the member
variable
2022-09-01 11:48:23 -04:00
Michael Cook (mackal) 6f7fa98996 [Repositories] Add more precise types to repository generator (#2391)
* Make utils/scripts/generators/repository-generator.pl aware of more
datatypes

This adds support for unsigned and more integer types. It also avoids
using parsing functions that require casting (still needed in some
cases)

Having the data types in the Repository structs better map to the types
in the database will allow us to avoid casting when we pull data out of
them. And as a benefit, assume something is wrong if we do :)

Hopefully clean up some warnings due to casting too.

Co-authored-by: Akkadius <akkadius1@gmail.com>
2022-08-31 00:04:27 -05:00
Kinglykrab fcf01f6d87 [Commands] Add #findrecipe and #viewrecipe Commands. (#2401)
* [Commands] Add #findrecipe and #viewrecipe Commands.

- Add #findrecipe [Search Critieria] command.
- Add #viewrecipe [Recipe ID] command.
- #findrecipe will show #viewrecipe saylinks if the user has access to that command.
- #viewrecipe will show #summonitem saylinks if the user has access to that command.

* Cleanup

* Lexicon change.

* Remove unnecessary .c_str() and
2022-08-30 23:32:17 -05:00
Michael 3228d6edf6 [Bug] Loot Drop Randomization adjustment (#2368)
* [Bug] Loot Drop Randomization adjustment

Loot Table currently favors the first item in the loot drop. This should help remove that condition.

Code by Ailia.

* snake_case

Co-authored-by: Akkadius <akkadius1@gmail.com>
2022-08-30 23:31:07 -05:00
Aeadoin 149fa54cfa [Feature] Implement Heroic Strikethrough to NPCs (#2395)
* [Feature] Implement Heroic Strikethrough to NPCs

* Removed virtual from inline int32 GetHeroicStrikethrough()

* Fix formatting

* Removed unnecessary function
2022-08-30 23:29:41 -05:00
Michael Cook (mackal) edda5ef811 [Utility] Add std::string_view overloads for std::from_chars (#2392)
* Add std::string_view overloads for std::from_chars

std::from_chars floating point support is still pour, so we provide some
fall backs. These fall backs currently lack error handling.

(since GCC 11 and MSVC 2019 16.4 FP support is added, clang with libc++
still doesn't support FP)

GCC's floating point support is still rather pour (performance) and
probably shouldn't be used, but we have support to if people want to
now.

Probably need more test cases ...

* Fix issue with std::chars_format define lacking

My test case for lacking FP support was clang with libc++ which defined
this enum anyways.
2022-08-30 23:13:59 -05:00
Chris Miles 786a7e2169 [Zone] Fix and simplify zone shutdown logic (#2390)
* Fix and simplify zone shutdown logic

* Add ResetShutdownTimer
2022-08-30 23:08:24 -05:00
Michael Cook (mackal) 59584a8d94 Use macro to generate correct format specifier (#2400)
Windows and Linux use different data models on 64 bit systems so "%lld"
isn't the same on them.
2022-08-28 14:38:26 -04:00
hg 94ac04b360 [Bug Fix] Fix loading world shared task state (#2398)
The default for this field is -1 not 0, so on world restarts this was
marking all elements completed
2022-08-28 13:16:35 -04:00
Kinglykrab 3e703769a4 [Quest API] Allow CreateInstance to be used without a Client initiator. (#2399)
* [Quest API] Allow CreateInstance to be used without a Client initiator.

Currently, you have to create the instance with a client initiator, whether that's in an NPC's EVENT_SAY /EVENT_ITEM or in a player script.

This will allow you to create instances without needing a client, but if there is one and there are errors, the messages will be sent to the client.

* Update questmgr.h

* Instance version.
2022-08-28 13:10:19 -04:00
Kinglykrab 57b3255fad [Quest API] Add Recipe Methods (#2393)
- Add $client->GetRecipeMadeCount(recipe_id) to Perl.
- Add $client->HasRecipeLearned(recipe_id) to Perl.
- Add quest::getrecipemadecount(recipe_id) to Perl.
- Add quest::getrecipename(recipe_id) to Perl.
- Add quest::hasrecipelearned(recipe_id) to Perl.
- Add client:GetRecipeMadeCount(recipe_id) to Lua.
- Add client:HasRecipeLearned(recipe_id) to Lua.
- Add eq.get_recipe_made_count(recipe_id) to Lua.
- Add eq.get_recipe_name(recipe_id) to Lua.
- Add eq.has_recipe_learned(recipe_id) to Lua.
2022-08-23 13:23:33 -05:00
Michael Cook (mackal) 10fd26ebbf [Manifest] Its not_empty not notempty (#2394) 2022-08-22 22:26:24 -05:00
Kinglykrab b9d8a13c76 [Bug Fix] Fix Silent Saylinks Sending Message to Others. (#2389)
* [Bug Fix] Fix Silent Saylinks Sending Message to Others.
Silent saylinks wouldn't send to sender, but to everyone else, so they could see what your saylinks were.

Added an optional `is_silent` bool to ChannelMessageReceived to account for this where necessary.

* Nullptr fix.
2022-08-21 23:26:25 -04:00
Chris Miles c0d4dd4176 [Expansions] Zone expansion consistency changes (#2380)
* [Expansions] Zone expansion consistency changes

* Add expansion check exclusions

* Update 2022_08_19_zone_expansion_consistency.sql
2022-08-21 20:36:21 -05:00
Kinglykrab 6637e2c59f [Feature] Add Guild Chat to Console. (#2387)
Adds guild chat to console.
2022-08-21 20:55:26 -04:00
hg e65b61a95f [Tasks] Implement task activity prerequisites (#2374)
Some live tasks make new elements available without requiring all
currently active ones to be completed first.

This adds the `req_activity_id` field to task activities which will mark
an element active if its required activity id is completed. If a valid
value is set then it's used instead of checking the current step.

The `step` field may still be set on rows with a valid `req_activity_id`
to specify its logical step and prevent later steps from becoming active
until completed. It's only ignored when deciding if the current element
is active.

The legacy task logic for unlocking activities was completely refactored
for this. A common method has been added so both zone and world can make
use of it to determine which elements are currently active. The previous
step system should remain unchanged.

The world logic for locking shared tasks when an element became active
did not account for "sequential" mode (all steps 0), unordered steps, or
gaps in step numbers. This also resolves that issue.
2022-08-21 19:55:19 -05:00
Kinglykrab c954685239 [Bug Fix] Fix Duplicate Silent Saylink Messages (#2386)
Clicking silent saylinks was sending the message twice if you had an NPC targeted due to duplicate code within ChannelMessageReceived.
2022-08-21 20:54:40 -04:00
Chris Miles 893d53425a [Repository] Modernize character recipe list (#2385) 2022-08-21 19:06:57 -05:00
Chris Miles 295ec0e1b4 [Tasks] Data validation for zone_version (#2381)
* [Tasks] Data validation for zone_version

* Update task_manager.cpp

* Update task_manager.cpp

* Update task_manager.cpp

* Update task_manager.cpp
2022-08-21 14:45:06 -05:00
Aeadoin 1d8dc4c8a8 [Feature] Change Mana Costs to use Signed Int (#2384) 2022-08-21 15:38:21 -04:00
Kinglykrab b108828502 [Bug Fix] Fix Strings::Money Missing Conditions. (#2383)
Noudess pointed out we were missing CSP, CP, and SP options in these conditions.
2022-08-21 15:00:02 -04:00
Michael Cook (mackal) 3f9df40c3c Update CURRENT_BINARY_DATABASE_VERSION (#2382)
PR #2376 didn't update it
2022-08-20 17:20:37 -04:00
Kinglykrab 3e8d34825a [Quest API] Add Goto Player Teleport Methods. (#2379)
* [Quest API] Add Player Teleport Methods.

These methods will allow server operators to teleport players directly to other players via the quest API using the #goto command's functionality.
- Add $client->TeleportToPlayerByCharID(character_id) to Perl.
- Add $client->TeleportToPlayerByName(player_name) to Perl.
- Add $client->TeleportGroupToPlayerByCharID(character_id) to Perl.
- Add $client->TeleportGroupToPlayerByName(player_name) to Perl.
- Add $client->TeleportRaidToPlayerByCharID(character_id) to Perl.
- Add $client->TeleportRaidToPlayerByName(player_name) to Perl.
- Add client:TeleportToPlayerByCharID(character_id) to Lua.
- Add client:TeleportToPlayerByName(player_name) to Lua.
- Add client:TeleportGroupToPlayerByCharID(character_id) to Lua.
- Add client:TeleportGroupToPlayerByName(player_name) to Lua.
- Add client:TeleportRaidToPlayerByCharID(character_id) to Lua.
- Add client:TeleportRaidToPlayerByName(player_name) to Lua.

* Simplify by using repositories

* Simplify

Co-authored-by: Akkadius <akkadius1@gmail.com>
2022-08-20 10:23:41 -04:00
Kinglykrab 59691f39d7 [Commands] Command Status Reload and Helper Method (#2377)
* [Commands] Command Status Reloading

Currently command status changes require a server restart to take effect, this will allow them to be changed and use `#reload commands` without needing a restart.

Added a helper method called GetCommandStatus() for future reference when sending command saylinks to people and making sure if they're high enough status for the command before sending the link.

* Update client.cpp

* Update command.h

* Saylink cleanup.

* Remove unnecessary packet sending.

* Revert "Remove unnecessary packet sending."

This reverts commit e7e77b83af.
2022-08-20 10:23:26 -04:00
Kinglykrab 8e3ad529dc [Feature] Instance Version Specific Experience Modifiers (#2376)
* [Feature] Add Instance Version Support to Experience Modifiers.

Allows Operators to set experience modifiers to be instance version specific so that you can have different versions of the same zone have different modifiers. If there is not one found, it defaults to zone_id 0 for global and instance_veresion -1 for global.

* Update zonedb.cpp

* Typo.
2022-08-20 03:16:58 -05:00
Chris Miles 607871a7ac [Loot] Add #lootsim (Loot Simulator) command (#2375)
* [Loot] Add #lootsim (Loot Simulator) command

* Validation

* Add global loot
2022-08-20 03:16:09 -05:00
Kinglykrab 6232a64cdb [Bug Fix] Fix Bot Group Loading (#2366)
* [Bug Fix] Fix Bot Group Loading

There were some weird cases where this code would falsely say a bot group did not exist and this would disallow summoning this botgroup as well as deleting it.

* Typo.
2022-08-20 03:15:58 -05:00
Michael Cook (mackal) 25c6b055a4 Fix issue with trap auras casting on caster (#2378)
Unsure if something changed or I just failed to test correctly
2022-08-18 12:34:37 -04:00
Kinglykrab 216b6ef426 [Saylinks] Convert all GM Command Saylinks to Silent Saylinks. (#2373)
* [Saylinks] Convert all GM Command Saylinks to Silent Saylinks.
- This cleans up all non-silent GM Command Saylinks that we had before due to the way they worked before. All saylinks like this should be silent now.
- Add source short hand capability for say links with same link as text.

* Defaults to r anyway.

* Spacing.
2022-08-13 20:40:22 -04:00
Chris Miles 597b041d92 [Saylinks] Add Silent helper (#2372)
* [Saylinks] Add Silent helper

* Swap out usage in door manipulation for silent saylink helper
2022-08-13 19:44:53 -04:00
Michael f6889d20e9 [Bug] UINT32 EmoteID (#2369)
emoteid packet structure is UINT32 but a number of references are in UINT16.
2022-08-13 18:41:14 -05:00
Chris Miles 79285b1002 [Repositories] Add GetMaxId, Count (#2371)
* [Repositories] Add GetMaxId, Count

* Update cmake with repositories, regenerate extended repos

* Remove license from files

* Simplify receivers

* Receiver simplify remaining

* Simplify receivers final

* Pass params by const reference

* Modernize grid tables

* Remove guild members since it doesn't conform as a generatable table

* PR comment
2022-08-13 18:40:56 -05:00
Chris Miles b79e1947f1 [Doors] Improvements to door manipulation (#2370) 2022-08-13 18:16:55 -05:00
Kinglykrab aa2b7f8947 [Quest API] Add GetSkillDmgAmt() to Perl. (#2365)
- Add $mob->GetSkillDmgAmt(skill_id) to Perl.
- This already exists in Lua, but not Perl.
2022-08-10 13:39:51 -04:00
Aeadoin 1d5a3a82a8 [Feature] Change GetSkillDmgAmt to int32 (#2364) 2022-08-09 21:24:15 -04:00
Kinglykrab 8ee7759dec [Rules] Add Rule to Enable Tells with #hideme (#2358)
With the recent changes to #hideme as of #2328, tells are disabled to hidden GMs, meaning a GM must show themselves in order to receive tells.
2022-08-04 16:41:36 -04:00
Chris Miles 5ec18709a6 [Hotfix] Remove expansion field from account for those who have it (#2357) 2022-08-01 15:07:36 -05:00
hg 7c27c4350d [Tasks] Add task accept packet validation (#2354)
This makes it so clients can only accept tasks that have been offered
2022-07-31 17:54:42 -05:00
hg 6068085de4 [Quest API] Fix lua task selector count when over max (#2353)
This was leaving the task count at 0 if called with more than the max
number of tasks (40)
2022-07-31 17:52:18 -05:00
Kinglykrab e1f515ba4b [Typo] Remove CanTradeFVNoDropItem() Duplicate (#2352) 2022-07-31 13:57:48 -05:00
hg c7a3e88b81 [Tasks] Make #task reloadall not quit shared tasks (#2351)
This was causing #task reloadall to desync state for shared tasks.
Characters were removed from the shared task but remained in the
character_tasks table. This CancelTask is cosmetic only to reload
the client window.
2022-07-31 13:57:33 -05:00
Kinglykrab b0da836f5a [Quest API] Add GetBotItem() and GetBotItemIDBySlot() to Perl/Lua. (#2350)
- Add $bot->GetBotItem() to Perl.
- Add $bot->GetBotItemIDBySlot() to Perl.
- Add bot:GetBotItem() to Lua.
- Add bot:GetBotItemIDBySlot() to Lua.
2022-07-31 13:45:17 -05:00
Michael Cook (mackal) a24a6f1160 [Code Cleanup] Resolve some warnings in loginserver/world_server.cpp (#2347) 2022-07-31 13:25:09 -05:00
hg be1e558b3b [Shared Tasks] Fix shared task message target (#2349)
Small regression from refactoring
2022-07-31 13:24:36 -05:00
hg c4a99aabd0 [Shared Tasks] Avoid erasing shared tasks while iterating (#2348)
This wasn't safe since the erase would invalidate iterators used
internally by the range loops.

Shared tasks with no members are now also cleaned up

Make GetMembers return reference instead of copy (this is used a lot)

Add rule for shared task terminate time for easier debugging
2022-07-31 13:24:21 -05:00
Akkadius 0dfc6eaa15 [Hotfix] Fix potential race for crash dumps (Linux) 2022-07-31 04:10:09 -05:00
Akkadius 3cccb183a2 [Hotfix] SQL Update 2022-07-31 03:00:24 -05:00
Michael Cook (mackal) c6cfcc3ea9 [Bug Fix] Limit merchant temp item list to zone and instance (#2346)
This prevents issues with a merchant being in more than one zone as well
as guild hall merchants sharing a list of temp items
2022-07-30 22:22:09 -05:00
hg 53b599518a [Dynamic Zones] Implement dz templates (#2345)
This allows shared tasks to create dz instances automatically through
the `dz_template_id` field instead of using quest scripts. Quest apis
were also added to create expeditions from template ids.
2022-07-30 21:25:43 -05:00
hg 5e7e255d72 [Tasks] Use dz switch id for task touch events (#2344)
This changes task touch elements to use the dz_switch_id as the goal id
instead of checking if a player zoned. It will remove the need to script
door clicks or modify task element zone field since task packet data can
just be imported.
2022-07-30 21:14:22 -05:00
hg 676467cbdc [Dynamic Zones] Implement dz switch id (#2343)
This adds the `dz_switch_id` field to doors and dynamic_zones. It will
allow for compasses to be automatically added to dz entrances and will
support moving clients to the dz on use without needing to script it.
These can be imported for switches/doors from live packet dumps.

Also removes compass packet encoders (same struct in all clients)
2022-07-30 21:00:11 -05:00
hg 1351f147f4 [Shared Tasks] Enforce task reqs on player removal (#2342)
This verifies a shared task's minimum players requirement is still met
when a member is removed and schedules it for termination if not
2022-07-30 20:49:57 -05:00
hg d243cbf8a3 [Shared Tasks] Cleanup shared task request and remove (#2341)
Functionally nothing should change in this patch. This refactors a lot
of formatting and code duplication in requests and member removals.

The long SharedTaskMessage namespace and its constants were contributing
to a lot of formatting that was difficult to read. These were shortened
since they're not all shared task specific anyway (though they should
probably just be moved to string_ids.h with other eqstrs now)

Shared task requests were refactored a little to remove an unnecessary
function that filled potential members. The separate functions used for
/taskquit and /taskremove were also combined into a single function to
remove a member while preserving live message differences.
2022-07-30 20:36:04 -05:00
hg 8a962e09f6 [Shared Tasks] Implement task timer groups (#2340)
This adds task replay and request timer groups (an arbitrary id) which
allows for different tasks to share lockouts
2022-07-30 20:18:19 -05:00
hg f64d072af7 [Shared Tasks] Implement Activity Locking (#2339)
* Add shared task element locking

This adds the `lock_activity_id` field to the tasks table which will
automatically lock a shared task when that element becomes active.

A method was added to world analogous to zone's UnlockActivities to
determine when an activity is active with respect to task steps.

Also adds quest apis to manually lock or unlock a client's shared task

* Add comment
2022-07-30 19:57:57 -05:00
Michael ea878ed27f [Feature] GM State Change Persistance (#2328)
* [Feature] GM State Change Persistance

- Flymode and Invulnerable will now persist over zoning.

- Appended GMSpeed, Flymode and Invulnerable to the hideme message GMs see when they first login.

- Added #godmode [on/off] command to turn on or off hideme, flymode, gmspeed and invulnerable all in one shot.

- /becomenpc will now disable tells to the target player. It will also automatically disable GM States that interfere with its functionality.

- GM Command /toggle will not properly turn tells on/off

- GMs will now be notified if they are ignoring tells when they first zone-in, provided their GM flag is up.

- Added TellsOff variable to the output to #showstats

* [Bug] Fix tells when gmhideme is turned off.

* [Cleanup] Cleanup function and rename for consistancy.

Remove un-needed this->

* Tweaks

* Tweaks

* Update db_update_manifest.txt

* Move string building logic to a vector and use strings join

* Update client_packet.cpp

* Update 2022_07_28_gm_state_changes.sql

* PR comment tweaks

Co-authored-by: Akkadius <akkadius1@gmail.com>
2022-07-30 19:29:24 -05:00
hg 793d4bc3a4 [Quest API] Use Floating Point for CameraEffect Intensity (#2337)
This was implemented in a very odd way. The intensity is just a float.

This is a breaking api change but low-impact (intensity will be
different).

To convert old values to new values with same intensity:

  0: 0.03125
  1: 0.05625
  2: 0.1
  3: 0.175
  4: 0.3
  5: 0.5
  6: 0.9
  7: 1.6
  8: 2.8
  9: 4.8
 10: 8.0
2022-07-30 19:18:20 -05:00
hg 4592c15dd6 [Tasks] Send Client Message for All Solo Task Updates (#2336)
Live sends the task updated message for every solo quest and task
increment (not just goal completed).

Also changed color to what live uses now. There are some other color
changes with shared task messages but they correspond with colors
changed in client generated messages but probably not worth chasing
down and causing inconsistency.
2022-07-30 19:17:24 -05:00
hg 4cf6db79aa [Saylinks] Inject Saylinks in MessageClose API (#2335) 2022-07-30 19:16:25 -05:00
Kinglykrab 576e7b0f91 [Quest API] Add IsRareSpawn() to Perl/Lua. (#2338)
- Add $npc->IsRareSpawn() to Perl.
- Add npc:IsRareSpawn() to Lua.
2022-07-30 19:40:51 -04:00
Paul Coene 113846c48c [Roambox] Improve Path Finding (#2324) 2022-07-30 14:52:28 -05:00
Michael Cook (mackal) dd71420a0e [Feature] NPCs with bows and arrows do ranged attacks (#2322)
* NPCs with bows and arrows do ranged attacks

Who knew!!

* PR comments

Co-authored-by: Akkadius <akkadius1@gmail.com>
2022-07-30 14:28:06 -05:00
Michael 0f9427098d [Rules] Add adjustment for zone forage. (#2330)
* [Rules] Add adjustment for zone forage.

- Added rule to allow the adjustment of zone foraging %

* Cleanup if formating
2022-07-30 13:39:12 -05:00
Aeadoin 25705878d8 [Feature] Change mana_used to int32 (#2321)
* Changed mana_used to use int32,
to match int32 mana_cost
This will allow higher mana costs to function

* Corrected DoHPToManaCovert to Int32

* Removed unused uint16 GetMana function call from Server/zone/questmgr.h

* Change GetSkillDmgAmt from Int16 to Int32 (SkillDamageAmount2 which uses function is Int32)

* Delete mob.cpp

* Revert "Delete mob.cpp"

This reverts commit 3db8bf04d1.

* Revert "Change GetSkillDmgAmt from Int16 to Int32 (SkillDamageAmount2 which uses function is Int32)"

This reverts commit cf5dbc9ce8.

Co-authored-by: dmcintosh-BCT <dan@blackcreektechnologies.com>
2022-07-30 13:36:48 -05:00
hg 6e2d11a283 [Tasks] Support Raw NPC Names in Task Goal List (#2333) 2022-07-30 13:33:53 -05:00
hg 2ccf692167 [Tasks] Use CashReward for Tasks (#2332)
Also removes the sound which does not occur
2022-07-30 13:33:05 -05:00
Trent 5e50c4181f [Rules] Add Keep Level on Death (#2319)
* add keep level on death rule

* add keep level on death rule

* add sql rule

* add rule db update

* remove unnecessary manifest entry

* remove unnecessary sql migration

* fix casing
2022-07-30 13:32:21 -05:00
hg eaeb583048 [Tasks] Add Task Reward Points Field (#2317)
* Add task reward points field

This replaces the separate DoN crystal reward fields with points and
point_type fields. This will make it easier to import data from
packet/client captures and possibly better support any future clients
or tasks that don't reward through the newer reward window.

* Fix manifest column check
2022-07-30 13:31:34 -05:00
Quintinon c68ff9bc5a [Rules] Update logic checks everywhere for FVNoDropFlag. (#2179)
* Update logic checks everywhere for FVNoDropFlag.

FVNoDropFlag == 0 is disabled
FVNoDropFlag == 1 is enabled for everyone
FVNoDropFlag == 2 is enabled for Admin() >= Character:MinStatusForNoDropExemptions

* Adding extra parenthesis to reduce ambiquity of order of operations for FVNoDropFlag checks

* Move FVNoDropFlag checks into a helper function in emu_constants.cpp and make an enum for the possible values.
Added console warning if setting is outside of allowed values.

* Move to client scoped helper method

Co-authored-by: Akkadius <akkadius1@gmail.com>
2022-07-30 13:16:47 -05:00
Kinglykrab 3bda8251b9 [Rules] Add Rule to allow Assassinate on non-Humanoid body types. (#2331) 2022-07-29 19:23:20 -04:00
Kinglykrab cadd29e5d1 [Rules] Add Rule to allow Headshots on non-Humanoid body types. (#2329)
* [Rules] Add Rule to allow Headshots on non-Humanoid body types.

* Formatting.
2022-07-29 18:38:30 -04:00
Akkadius 4002d6a083 [Hotfix] Shared Memory Protection Fixes 2022-07-27 17:37:20 -05:00
Michael Cook (mackal) 5331f4d841 [CPP] Update C++ standard to C++17 (#2308)
* Update C++ standard to C++17

* Nuke EQ::Any in favor of std::any

* Remove std::iterator due to deprecation

* Replace result_of with invoke_result due to deprecation
2022-07-27 09:00:09 -05:00
Quintinon f4f5728195 [Memory Leak] This mem leak was missed due to merge issues in the previous PRs. (#2314)
https://github.com/EQEmu/Server/commit/b5c4357de2e14a1c97abbab26c60eee8ff308331#r77584958
2022-07-27 08:54:40 -05:00
hg ed64c82a2f [Quest API] Allow scripts to prevent door click (#2327)
Returning non-zero from EVENT_CLICK_DOOR will prevent the default
handler.

This should have been implemented when expeditions were put in to
allow scripts to prevent zoning out of vxed and tipt without flags.
Some upcoming changes may need this to allow scripts to prevent
automatic dz entry.
2022-07-27 08:53:38 -05:00
hg c847e3da86 [Netcode] Adjust first packet for compress flag (#2326)
When a packet was over max_raw_size and zlib failed to compress the
first packet chunk then the final output would be 513 bytes which
exceeded m_max_packet_size of 512.

This occured because the first packet chunk used sublen without
adjusting for the new_length + 1 compression flag added in Compress().
When the packet failed to compress then it was already at its max.
After the first packet, chunk sizes are calculated using max_raw_size
which already accounted for the compress flag. (From #979)

This should fix #2325
2022-07-27 08:52:25 -05:00
Chris Miles 7d2f88325a [Client] Fix IsMoving for Client (#2318)
* [Client] Fix IsMoving for client

* Consolidate member vars

* Update client_process.cpp
2022-07-27 08:51:51 -05:00
hg 1089f8139b [Saylinks] Refactor saylink injection (#2315)
If a message was longer than 50 characters with "00000" somewhere in the
message (such as messages with hex numbers) then the saylink injection
method was sending a blank message to the chat window.

This refactors the saylink injection method using a crude state machine
to build the output. It should function the same:

  - Inner-most brackets generate saylinks when nested
  - Saylinks are not generated in brackets that already have a saylink
  - Existing saylinks are preserved
  - Existing saylinks that contain text with brackets do not attempt to
    generate saylinks
  - Saylinks are not generated if brackets contains leading or trailing
    spaces (e.g. [ spaces ])
2022-07-27 08:50:00 -05:00
Chris Miles f07e3f4d3b [CI] Hook tests back up (#2316)
* [CI] Hook tests back up

* Pull in config file

* Delete .travis.yml
2022-07-27 08:49:04 -05:00
Chris Miles 9f8f838265 [Content Filter] Fix Runtime Filtering When Set to -1 (All) (#2313) 2022-07-27 08:48:50 -05:00
Paul Coene 5af1620e50 Fix bestz to work on client or target. (#2323) 2022-07-23 13:03:20 -04:00
hg 20c639c872 [Tasks] Reward clients on shared task completion sync (#2306)
If a member is offline (or possibly during a race while zoning?) when
the shared task is completed they will not receive the reward. On live
the character receives their reward (with an updated replay timer) if
they enter back into game while the shared task is still active. They
keep the original replay timer if the shared task is no longer active
and do not receive a reward.

This makes it so clients are issued rewards (and a task completed
event is dispatch) if the client's task state was out of sync with a
completed shared task. To prevent characters being rewarded more than
once in case of bad sync checks, a 'was_rewarded' field has been added
to the character_tasks table and updated when rewards are assigned.

This fixes a couple bugs so the character_activities table is correctly
updated with shared task states to better detect when out of sync:

- The character_activities table is now flagged to update after syncing
  shared task states. This table was not being updated if a client was
  offline or inaccessible for a shared task element update.

- The character_activities table is now updated when a task element is
  completed. This was only being updated for activity increments and on
  completing the entire task. SaveClientState is now called at the end
  of ClientTaskState::IncrementDoneCount to cover all cases.

This also has a cosmetic change to show replay timers before rewards
like live, though this will not work for shared tasks until refactoring
world code
2022-07-16 15:26:48 -05:00
Akkadius 635b7b5e86 [Hotfix] fix manifest 2022-07-16 14:58:11 -05:00
Michael Cook (mackal) 139845f971 [Feature] Implement OP_CashReward (#2307)
* Implement OP_CashReward

Tit opcode needs verifying still, I think it's correct.

Added Perl and lua client CashReward functions

* Forgot AddMoneyToPP call somehow

* Switch QuestManager::givecash to CashReward packet

* Fix extra comma
2022-07-14 21:17:44 -05:00
KimLS ce74ac9913 Merge branch 'master' of https://github.com/EQEmu/Server 2022-07-14 18:56:08 -07:00
KimLS 1db2dffa57 Fix windows build for strings.cpp 2022-07-14 18:56:00 -07:00
Chris Miles 59f8d54491 [Expansions] Expansion Deprecation Revert (#2312)
* [Expansions] Expansion Deprecation Revert

* Add blank SQL for deprecate

* Update version.h

* Adjustments
2022-07-14 20:48:26 -05:00
Michael Cook (mackal) 9488ee1e8c [Bug Fix] Remove StringUtilTest::EscapeStringMemoryTest (#2310)
This was testing the old std::string EscapeString(const char *src,
size_t sz) which was removed since it's not used anywhere else.
2022-07-14 19:47:58 -05:00
Chris Miles ffe4d528e7 [Tasks] Zone Version Matching (#2303) 2022-07-14 02:57:23 -05:00
Chris Miles ddb5794462 [Zone] Deprecate Zone expansion Field (#2297) 2022-07-14 02:49:35 -05:00
Chris Miles c8b3ca53fe [World] World Bootup Consolidation (#2294) 2022-07-14 02:39:01 -05:00
Akkadius fb2df0e570 [Hotfix] Fix merge issue 2022-07-14 02:32:35 -05:00
Paul Coene 6b5e4afd2d [DoT Messages] Add DoT messages for mob->PC casts, fixed others to use correct str. (#2289) 2022-07-14 02:23:13 -05:00
neckkola 3b409def2c [Login] Added OP_ExpansionPacketData for RoF2 and update payload for Titanium (#2186)
* Fix for GENERIC_9_STRINGS

* Update .gitignore

* OP_ExpansionPacketData for Titanium and RoF2

* Update for login_opcodes_sod.conf

* Add OP_LoginExpansionPacketData for Titanium and RoF2

* Few expansion fixes

* Update client.h

* Update client.h

* l

* Updates based on PR feedback.
Moved configuration to login.json
Set Titanium limits to constants

* Update login.json

Added the two configurations to login.json
display_expansions - true/false to display on the server select screen
max_expansions - the bitmask of expansions enabled (http://spire.akkadius.com/calculators#expansions-bitmask-calculator)

* Further cleanup based on feedback.

* Further cleanup and refactor max_expansions to max_expansions_mask to better reflect its purpose

* Missed rename of max_expansions corrected.
2022-07-14 02:22:50 -05:00
hg 1488c3685c [Tasks] Apply full duration mission replay timers (#2299)
Shared task replay timers used to be based on the task start time
(reducing the final lockout timer by elapsed task time).

Live changed this in the 2022 April 20 patch:
"Replay timers will now apply their full duration upon completion of
their associated task/quest."

Solo tasks and quests already did this

This also fixes a small bug where request timers were being
deleted when replacing replay timers for shared tasks
2022-07-14 02:19:27 -05:00
Chris Miles 71966c85ca [Logs] #logs list Improvements (#2302) 2022-07-14 02:19:00 -05:00
Chris Miles 6cbfecd5a1 [Code Cleanup] Remove Unused EQEMU_DEPOP_INVALIDATES_CACHE (#2292) 2022-07-14 02:18:13 -05:00
Chris Miles 73d4e90275 [World] Add more descriptive LS auth erroring (#2293) 2022-07-14 02:17:51 -05:00
Chris Miles f7923457fd [Crash] Linux Crash Dump Improvements (#2296)
* [Crash] Linux Crash Dump Improvements

* Change LogError  for LogCrash
2022-07-14 02:17:18 -05:00
hg f381453dbd [Tasks] Place task item rewards in free slots (#2300)
Live places item rewards into the first free inventory slot and only
places it on the cursor if inventory is full
2022-07-14 02:16:43 -05:00
hg 792ea1608a [Tasks] Fix #task command crash on bad input (#2301) 2022-07-14 02:16:31 -05:00
Chris Miles 230d115195 [Code Cleanup] Remove use of bzero since it is deprecated for memset (#2295) 2022-07-14 02:11:30 -05:00
Chris Miles dda1712bb8 [Logs] Fix GMSay Log Regression (#2298) 2022-07-14 02:11:18 -05:00
Kinglykrab 849f4e18a5 [Validation] Add Size Validation to #hotfix. (#2304)
* [Validation] Add Size Validation to #hotfix.
- Validates size of shared memory pool versus current count of database so people don't accidentally #hotfix and mess something up.

* Typo.

* Message change.
2022-07-14 02:11:04 -05:00
Chris Miles dfd8f84cac [Strings] Refactor Strings Usage (#2305)
* Initial commit checkpoint

* More functions converted

* Commify

* More functions

* Fin

* Sort declarations

* Split functions between files

* Bots

* Update strings.h

* Split

* Revert find replaces

* Repository template

* Money

* Misc function

* Update CMakeLists.txt

* Saylink

* Update strings.cpp

* Swap Strings::Saylink for Saylink::Create since saylink is coupled to zone database

* API casings
2022-07-14 02:10:52 -05:00
hg 44c85a0dd7 [Quest API] Fix missing arg in perl set_proximity (#2291) 2022-07-08 19:05:33 -05:00
Michael Cook (mackal) 8d6fcf2a84 Fix string comparison issues in Client::SendZoneFlagInfo (#2290)
clang complained about these
2022-07-08 00:07:07 -04:00
Akkadius c59ec59e85 [Hotfix] Windows compile fix take 3 (final) 2022-07-06 23:14:52 -05:00
Akkadius a2e531d7e4 [Hotfix] Possible windows compile fix take 2 2022-07-06 22:58:22 -05:00
Akkadius 8ab3ec4fb0 [Hotfix] Possible windows compile fix 2022-07-06 22:40:34 -05:00
Chris Miles 19b751257b [Server Maintenance Script] Improvements to Downloading - Empty File Detection (#2282)
* Change how the utility script gets downloaded

* Adjust timeouts and order
2022-07-06 22:13:42 -05:00
Chris Miles f4904d00d2 [Backups] Use World CLI for Database Backups (#2286)
* Use world backup utility instead of db_dumper.pl

* Delete database_dumper.pl

* Delete db_dumper.pl

* Tweak script
2022-07-06 22:02:28 -05:00
Chris Miles 67f5759e47 [Server] Configuration Issues Checker (LAN Detection) (#2283)
* LAN detect

* Add more checks, consolidate logic

* Tweaks

* Tweaks

* Update world_config.cpp

* Tweak logic

* Add DNS resolution

* Delete task runner after being used

* JSON path notation adjust
2022-07-06 22:01:58 -05:00
Chris Miles eca4eed996 [Logging] Table Injection - Member Variable Cleanup (#2281)
* Logsys member variable cleanup, table injection

* Private member adjustments, OOB checks

* continue
2022-07-06 22:01:47 -05:00
Paul Coene 5c105d7408 [Bug Fix] NPCs were getting weapon proc added twice (#2277) 2022-07-06 21:59:46 -05:00
Kinglykrab a444857b46 [Quest API] Perl Doors Fix. (#2288) 2022-07-05 16:17:55 -05:00
Kinglykrab 4025b84891 [Quest API] Add missing methods/package.adds to Perl API. (#2287) 2022-07-05 16:07:41 -05:00
Kinglykrab 6d56b5b730 [Bug Fix] Fix Spell Bucket and Spell Global Logic Checks. (#2285)
- Default to true and set to false if they fail the proper check.
2022-07-04 23:28:21 -04:00
Michael 0f13a92b73 Merge pull request #2284 from hgtw/fix/missing-overload 2022-07-04 11:29:56 -04:00
hg 44dc9967a3 Add perl SpellFinished overload 2022-07-04 11:19:44 -04:00
hg 7e8a24fcec [Quest API] Use binding library for perl apis (#2216)
* Add perlbind library

* Convert perl apis to perlbind
2022-07-03 21:33:45 -05:00
Michael 2829d21057 [Cleanup] Update to EQEmu #2253 to clean up message strings (#2279)
Added message string 1393 // You have been summoned!
2022-07-03 18:57:33 -04:00
Akkadius 66d6d523cf [Hotfix] Move discord_webhooks to state tables because we don't want webhooks being exported 2022-07-03 12:16:19 -05:00
Akkadius 1a02017737 [Hotfix] Add discord_webhooks to server tables 2022-07-03 12:08:00 -05:00
Quintinon b5c4357de2 [Bug Fix] Fix miscellaneous memory leaks related to EQApplicationPacket and it's pBuffer (#2262)
* Delete EQApplicationPacket after use

* Correct issue where Creating EQApplicationPackets in zone/mob.cpp may not free pBuffer[]

* Handle freeing pBuffer[] if exists in zone/mob.cpp Create*Packet functions

* Handle freeing pBuffer[] in zone/object.cpp Create*Packet methods

* Delete leaked outapp variables in zone/trading.cpp

* Make CreateHorseSpawnPacket() safer by freeing pBuffer[] before replacing with new[]

* Prevent initial new ServerPacket from being leaked in command_reload

* Free pack after sending in command_setlsinfo

* Delete new NPC in command_viewnpctype after printing stats

* Fix compile error

* Delete EQApplicationPacket after sending in command_kick

* Remove unneeded safe_delete(outapp) after FastQueuePacket and fix minor whitespace issue

* Delete packet after sending in WorldServer::SendReloadTasks

* Cleanup logic and free leaked NPCType in Client::Doppelganger

* Free RespawnOption in Client::HandleRespawnFromHover in 'unexpected rez from hover request' branch

* Free EQApplicationPacket after sending in Bot::ProcessBotInspectionRequest

* Free Bot when returning from failed Bot::Save() in helper_bot_create()

* Initialize variable to nullptr to prevent garbage initial value

* Undo change in other PR
2022-07-02 22:10:51 -05:00
Paul Coene 5c60913583 [Feature] Add humanoid and non-wielded restrictions to pick pocket (#2276)
* Add humanoid and non-wielded restructions to pick pocket

* Use constants for message string and char color

* Fixed more magic #s

* Fix to include valie bodytypes

* Fix incorrect scope of final else

* My extra message was not needed.  Client handles based on packet reply

* Removed string ID I added - issued by client

* Use existing pick pocket reply function / clean up
2022-07-02 22:02:43 -05:00
Quintinon 30f35a920b [Bug Fix] Handle memory leaks from return value of Client::GetTraderItems() (#2266)
* Move delete of ItemInstance to avoid edge case leaking in ZoneDatabase::LoadWorldContainer()

* Delete ItemInstance after use in Client::Handle_OP_AdventureMerchantPurchase()

* Delete ItemInstance after use in NPC::GetEquipmentMaterial()

* Delete ItemInstance after use in Bot::AddBotItem()

* Delete GetItems_Struct in edge case when !TradeItemsValid in Client::Handle_OP_Trader()

* Move delete GetItems_Struct to handle edge case when Customer is not valid in Client::Trader_EndTrader()
2022-07-02 22:01:42 -05:00
Quintinon 445c94bf4a [Cleanup] Fix unintended copies in zone/zonedb.cpp by changing auto to auto& (#2271) 2022-07-02 21:57:17 -05:00
Michael 221d173c59 [Feature] Bind Wound and Forage while mounted. (#2257)
During some point in the eras you were not able to Bind Wound or Forage when mounted. I am not sure if Live is still like this, so I added a rule with it disabled by default.
2022-07-02 21:53:15 -05:00
Michael 68d28bcd3e [Bug Fix] Add required distance to CoTH before aggro wipe (#2253)
* Add required distance to CoTH before aggro wipe

This should fix eqemu/master#2205

* Remove implied this->

* Adjustments to rules per PR discussion.
2022-07-02 21:51:57 -05:00
Kinglykrab d107226ced [Telnet] Add guildsay to console commands and Guild Channel to QueueMessage. (#2263)
* [Telnet] Add guildsay to console commands and Guild Channel to QueueMessage.
- Will allow you to send guild-specific messages from things like Discord EQ.
- Add Guild support in `EQ::Net::ConsoleServerConnection::SendChannelMessage` so guild ID can be parsed out.

* Fix auction ChannelMessage by adding to condition.

* Update console.cpp

* Update console.cpp
2022-07-02 21:51:03 -05:00
Quintinon 2c0716f654 [Cleanup] Cleanup code smells and compiler warnings in common/shareddb (#2270)
* Apply refactoring for modernize-use-default-equals

* Apply refactoring for const local variable

* Replace c-style cast with static_cast<>

* Explicit cast double to float to remove compiler warning

* Make member functions const when possible

* Correct [lnt-accidental-copy] by changing auto to auto&

* Use static_cast instead of reinterpret_cast when appropriate

* Remove unneeded initial values when assigned in all paths and joined delcaration and assignment when possible

* Remove unused include

* Make member function in header const
2022-07-02 21:49:42 -05:00
Kinglykrab 0c01872608 [Bots] Cleanup ^inventoryremove, ^inventorylist, and ^list Commands and bot groups. (#2273)
* [Bots] Cleanup ^inventoryremove, ^inventorylist, and ^list Commands.

* Bot group cleanup, bot group auto spawning.

* Compile fix.

* Require SQL.
2022-07-02 21:46:00 -05:00
Paul Coene 3936b2b882 [Fix] Boats should never get FixZ'd (#2246)
* Boats should never get FixZ'd

* Use member variable to avoid repetitive checks

* Resolve comments from review

* Fix return type
2022-07-02 13:49:45 -05:00
Kinglykrab 15113f4056 [Quest API] Add TrackNPC to Perl/Lua. (#2272)
* [Quest API] Add TrackNPC to Perl/Lua.
- Add quest::tracknpc(entity_id) to Perl.
- Add eq.track_npc(entity_id) to Lua.
- This will allow server operators to arbitrarily Track NPCs for clients with scripts.
- Modified tracking to auto turn off and tell you that you discovered your target if within 10 units, this is to allow scripted Tracking to turn off without the need for the Tracking skill.

* Remove unnecessary DoTracking() call.

* Update client.cpp
2022-06-29 15:29:02 -04:00
hg 16b31c5a3a [Bug Fix] Fix empty spawned merchants (#2275)
Regression from 763fc823
2022-06-28 09:23:08 -04:00
Kinglykrab 28b07d635a [Spells] Target's Target Combat Range Rule (#2274) 2022-06-24 19:04:52 -04:00
Quintinon 059a4b7568 [Bug Fix] Delete NpcType Struct returned by Bot::CreateDefaultNPCTypeStructForBot() when unused (#2267) 2022-06-18 16:45:38 -04:00
Quintinon b9ceba1b1c [Bug Fix] Free return value of ZoneDatabase::LoadTraderItemWithCharges() (#2264) 2022-06-18 16:44:23 -04:00
Quintinon cb95251c68 [Bug Fix] Correct type signed/unsigned int when reading item from database in shareddb (#2269)
* Correct database reads from unsigned to signed integer for item regen, manaregen, endur, and enduranceregen

* Correct item database read for Click.Effect from unsigned to signed int
2022-06-15 12:16:58 -04:00
Kinglykrab be00aa1b60 [Loot] Remove unnecessary loot error messages. (#2261)
* [Loot] Remove unnecessary loot error messages.
These messages are only sent when you loot a corpse that is mid-decay (i.e. no items and you go to loot it immediately) or if you try to loot a non-corpse entity.
The ent != 0 shows up a lot if you're trying to loot too quickly and really isn't an error, the server just hasn't caught up to decay the corpse before you try to loot.

* Use preexisting struct.

* Remove newline.

* Update client_packet.cpp
2022-06-12 18:44:16 -04:00
Akkadius b2658a6cbc [Hotfix] Correct database call to point to the content_db connection 2022-06-12 17:34:51 -05:00
Michael 026133f32a [Bug Fix] Tradeskill Item 0 Error (#2256)
When trying to fully script a combine so the tradeskill itself does not return an item (Item 0) and handling all items through quests, the source will provide an error regardless that "Item 0 does not exist". This change will move the item summon after the validity check thus preventing the error to the client.
2022-06-10 13:53:30 -04:00
Michael 6d4f22a1c0 [Bug Fix] Tradeskill Autocombine MinSkill (#2260)
* [Bug] Tradeskill Autocombine MinSkill

Require min tradeskill or above for autocombine.

* Syntax fixes
2022-06-10 13:52:31 -04:00
Michael e75f87a535 [Quest API] Expand SaveGuardSpot (#2258)
* Expand SaveGuardSpot

- Adds
-- mob:saveguardspot()
-- mob:saveguardspot(true)

* Perl Support
Thanks to KinglyKrab for the perl implementation.
2022-06-10 13:52:22 -04:00
Kinglykrab 83e066bffc [Bug Fix] Stop skill ups on Charmed NPCs. (#2249)
- Clients were capable of leveling up their melee skills on Charmed Mobs according to: https://github.com/EQEmu/Server/issues/2182
2022-06-09 21:08:50 -04:00
Chris Miles 4639405fdf [Discord Integration] Native Discord Integration (#2140)
* Start of discord integration work

* more testing

* Discord client work

* More discord work

* Cleanup

* Handle retry timer response and max retries

* Update base retry timer

* Move Discord queue handler to UCS, add queuer to own thread

* Post merge

* Send up Zone::SendDiscordMessage

* Start of discord integration work

* more testing

* Discord client work

* More discord work

* Cleanup

* Move Discord queue handler to UCS, add queuer to own thread

* Post merge

* Push up tables

* Quest API stuff.

* Update 2022_05_07_discord_webhooks.sql

* Post merge fixes

* Push up manifest

* Flip logging signs in logic from copy / paste of inverse logic before

* Make sure we add new line to quest api sourced messages

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2022-06-09 17:22:23 -05:00
hg 8ef3e87370 [Bug Fix] Fix stack leaks in Lua events #2254
EventItem was leaving the package table on the stack in successful
(non-encounter) calls and only popping the return. All events were
also leaking the full stack on lua_pcall errors. Lua mod callbacks
were popping error returns but leaking the table.
2022-06-09 17:20:35 -05:00
Akkadius bec28769aa [Hotfix] Flipped positive / negative values for legacy_combat.lua 2022-06-09 17:19:00 -05:00
Kinglykrab 8586cdc47e [Messages] Convert messages from Spells to FocusEffect where necessary. (#2243)
* [Messages] Convert messages from Spells to FocusEffect where necessary.
https://github.com/EQEmu/Server/issues/837 from 2019 notes a couple places that should use Focus Effect chat type instead of Spells chat type.

* Add rule for item cast messages.
2022-06-08 19:09:33 -04:00
Michael Cook (mackal) 63ba5dc3ab Fix memory leaks found by Quint (#2248) 2022-06-07 23:41:13 -04:00
Michael fcc7725ca3 [Bug Fix] Bazaar Search MYSQL Error (#2252)
Corrected fields that the bazaar search function is using to prevent mysql error due to non-existant field items.spellid.
2022-06-07 21:21:02 -04:00
Michael 5df6a61c96 [Bug Fix] Hacker_Str was causing sql errors - Non Escaped (#2251)
Processing the hacker_str through EscapeString().
2022-06-07 21:19:24 -04:00
Kinglykrab fc5105eed7 [Rules] Add Frontal Stun Immunity Rules. (#2217)
* [Rules] Add Frontal Stun Immunity Rules.
- Add Combat:FrontalStunImmunityClasses rule for determining Frontal Stun Immunity by class bitmasks
- Add Combat:FrontalStunImmunityRaces rule for determining Frontal Stun Immunity by race bitmasks
- Add Combat:NPCsUseFrontalStunImmunityClasses rule for determining if NPCs use Frontal Stun Immunity by class bitmasks
- Add Combat:NPCsUseFrontalStunImmunityRaces rule for determining if NPCs uses Frontal Stun Immunity by race bitmasks
- Cleanup GetDefaultGender() as best as possible with the globalload I have.
- Combat:NPCsUseFrontalStunImmunityRaces defaults to true as NPCs currently use Frontal Stun Immunity.
- Added **all** Ogre races to the check for Frontal Stun Immunity.

* Remove other Ogre races.
2022-06-06 22:29:06 -05:00
Quintinon 243fb781e8 [Bug Fix] Fix two invalid data accesses in zone/client.cpp (#2238)
* Correct potential read out of bounds on array in Client::Doppelganger

* Correct potential read out of bounds in Client::ChannelMessageSend

* Corrected logic to not read out of bounds on the lower end.
2022-06-06 22:26:36 -05:00
Kinglykrab ec4d228dd5 [Bug Fix] Fix issue where #advnpcspawn addspawn does not add spawn sometimes. (#2247)
* [Bug Fix] Fix issue where #advnpcspawn addspawn does not add spawn sometimes.
- Cleanup where std::stoi should be std::stoul.
- Cleanup ShowStats message to show NPC stats at bottom as well.

* Update advnpcspawn.cpp
2022-06-06 22:24:45 -05:00
Michael Cook (mackal) 2910073373 [Memory Leak] Fix leak of CommandRecords in commandlist (#2244)
* Fix leak of CommandRecords in commandlist

Quicker than porting to std::unique_ptr since we do fun stuff with
commandlist ...

* Fix leak so it won't double free

This is fine enough until we rewrite it to be better
2022-06-06 15:21:35 -04:00
Kinglykrab b4d5e807e3 [Commands] Add BestZ and Region Data to #loc (#2245) 2022-06-05 15:38:51 -04:00
Kinglykrab 8f729fe948 [Rules] Add Rule to Disable NPC Last Names. (#2227)
* [Rules] Add Rule to Disable NPC Last Names.
- Add NPC:DisableLastNames to disable NPC Last Names.
- Fix #npcedit lastname to allow you to use an empty string.

* Cleanup of classes in naming.

* Duplicate.

* Update classes.cpp
2022-06-04 14:01:00 -04:00
Kinglykrab 7160aa651e [Cleanup] Cleanup Haste references and Lua API calls for unsigned to signed. (#2240) 2022-06-04 14:00:21 -04:00
Kinglykrab 8414ce02e3 [Cleanup] Add Validation to varchar number item fields. (#2241)
- combateffects and charmfileid were varchar and have no default value, so if you passed '' shared memory would fail, default these to 0 to prevent this.
2022-06-04 14:00:16 -04:00
Kinglykrab 17034a6e47 [Commands] Cleanup #spawneditmass Command. (#2229)
* [Commands] Cleanup #spawneditmass Command.
- Cleanup messages and logic.
- Split command into its own file.

* Save querying database if they're not using the only supported option.

* Condense to one message.
2022-06-04 12:59:46 -05:00
Quintinon be1772d464 [Bug Fix] Correct (probably) unintended bitwise AND instead of logical AND (#2239) 2022-06-01 21:17:39 -04:00
Quintinon a00f086bb8 [Combat] Fix shield calculation (#2234)
* Fix max mitigation calculation

* Fix shield ability not receiving correct arguments from perl script.

* Correct shielder having wrong mitigation set.
2022-06-01 17:17:14 -04:00
Quintinon de830e5535 [Code Cleanup] Resharper Warnings (#2235)
* Remove unused local variable

* Remove another unused variable

* Correct typos and remove unused initialization

* Cleanup some code in OPCharCreate

* Remove unused function in client.cpp and undefined declaration.
Also the function potentially had a null pointer dereference according to Visual Studio.
2022-06-01 17:16:49 -04:00
Kinglykrab d1404a2d95 [Rules] Add Rules to disable various item functionalities and cleanup data types. (#2225)
- Noticed some data types were unsigned when they should be signed based on Live items having these stats as negatives.
- Loregroup was uint32 and should be int32 for Loregroup -1, fixed any references to -1 as 0xFFFFFFFF.
- Attack was uint32 and should be int32.
- DamageShield was uint32 and should be int32.
- DotShielding was uint32 and should be int32.
- Endurance was uint32 and should be int32.
- EnduranceRegen was uint32 and should be int32.
- Haste was uint32 and should be int32.
- ManaRegen was uint32 and should be int32.
- Regen was uint32 and should be int32.
- RULE_BOOL(Items, DisableAttuneable, false, "Enable this to disable Attuneable Items")
- RULE_BOOL(Items, DisableBardFocusEffects, false, "Enable this to disable Bard Focus Effects on Items")
- RULE_BOOL(Items, DisableLore, false, "Enable this to disable Lore Items")
- RULE_BOOL(Items, DisableNoDrop, false, "Enable this to disable No Drop Items")
- RULE_BOOL(Items, DisableNoPet, false, "Enable this to disable No Pet Items")
- RULE_BOOL(Items, DisableNoRent, false, "Enable this to disable No Rent Items")
- RULE_BOOL(Items, DisableNoTransfer, false, "Enable this to disable No Transfer Items")
- RULE_BOOL(Items, DisablePotionBelt, false, "Enable this to disable Potion Belt Items")
- RULE_BOOL(Items, DisableSpellFocusEffects, false, "Enable this to disable Spell Focus Effects on Items")
2022-06-01 17:12:31 -04:00
Kinglykrab 38da37755d [Bug Fix] Fix MovePC in #zone and #zoneinstance Commands. (#2236)
* [Bug Fix] Fix MovePC in #zone and #zoneinstance COmmands.

* #zone 0 Optional Functionality.
2022-06-01 17:05:43 -04:00
Kinglykrab 57ac46d090 [Commands] Cleanup #date Command. (#2228)
* [Commands] Cleanup #date Command.
- Cleanup messages and logic.

* Cleanup.
2022-06-01 15:31:31 -04:00
Chris Miles 59f32b8d34 [Loading] Zone Version Loading Fixes (#2233)
* Zone version loading fixes

* Remove errant code
2022-05-31 22:15:05 -05:00
Chris Miles a45117cd04 [Bug Fix] Adjustment for nullptr crash (#2232) 2022-05-31 22:24:12 -04:00
Chris Miles 291aaea581 [Bug Fix] Fix null pointer crash on zones that have not booted a zone yet with #reload commands or anything that calls GetZoneDescription (#2231) 2022-05-31 21:55:00 -04:00
Chris Miles 162d34e1d9 [Tasks] Fix validation loading (#2230) 2022-05-31 21:47:01 -04:00
titanium-forever 86c9be410d [Database Backup] Enable database dump of bot data (#2221)
* Add option to dump bot data

* Add player_bot_table dump suppor to command handler

* Add tableList getter to the dump_service

* Fix declaration in header file

* Include missed bot tables

* Rename player-bot to bot to be more descriptive

* Fix missed reference to player-bots

Co-authored-by: Kieren Hinch <khinch-github@nylonmoon.com>
2022-05-31 18:25:10 -05:00
Kinglykrab 30e34c67b4 [Quest API] Fix parameters in some Perl worldwide methods. (#2224) 2022-05-31 15:46:14 -04:00
Kinglykrab ce8b8da0d6 [Bug Fix] Fix Legacy Combat Lua Script (#2226) 2022-05-30 22:43:03 -04:00
Kinglykrab 02e8b125a4 [Hot Fix] Fix Linux compile due to missing include. (#2223)
- Not sure how Windows compiles, but Linux fails.
2022-05-30 22:10:49 -04:00
Kinglykrab 11369247b1 [INT64] Further int64 cleanup in Perl SetHP() and GetSpellHPBonuses() in Perl/Lua. (#2222) 2022-05-29 16:36:32 -05:00
Kinglykrab d493a6627b [Commands] Cleanup #nudge Command. (#2220)
* [Commands] Cleanup #nudge Command.
- Cleanup messages and logic.

* Update nudge.cpp

* Update nudge.cpp
2022-05-29 14:33:40 -04:00
Kinglykrab b07945f0be [Commands] Cleanup #emptyinventory Command. (#2219)
- Cleanup messages and logic.
- Breakout #emptyinventory into its own command file.
2022-05-29 14:33:35 -04:00
Kinglykrab 8f3ac74196 [INT64] Fix int64 for OOC Regen and GetHP(), GetMaxHP(), GetItemHPBonuses() in Perl/Lua. (#2218)
* [INT64] Fix int64 for OOC Regen and GetHP(), GetMaxHP(), GetItemHPBonuses() in Perl/Lua.
- These all had int64 values and were overflowing, returning garbage data.

* Update npc.cpp
2022-05-29 14:33:30 -04:00
Kinglykrab bcf7ccefcd [Money Messages] Cleanup quest::givecash(), split, and task reward messages. (#2205)
* [Money Messages] Cleanup quest::givecash(), split, and task reward messages.
- Cleans up all the money messages using ConvertMoneyToString().
- Allows quest::givecash() to have optional parameters other than copper.

* Commification.

* Corpse messages.

* String IDs and cleanup.
2022-05-29 14:33:18 -04:00
Kinglykrab 9e9ef6809b [Cleanup] Cleanup spell and max level bucket logic. (#2181)
* [Cleanup] Cleanup spell and max level bucket logic.
- Spell buckets will now allow new mob->SetBucket() buckets since most people use these now.
- Max level bucket will now allow new mob->SetBucket() bucket since most people use these now.
- Clean up GetScribeableSpells() and GetLearnableDisciplines() logic and magic numbers.
- Make GetClientMaxLevel() uint8 instead of int since it can only be 0-255.

* Fix typo from other commit.

* Lua setter.

* Update client.cpp
2022-05-28 14:35:17 -04:00
Kinglykrab c8f6dbb86d [Commands] Cleanup #npcedit, #lastname, #title, and #titlesuffix Commands. (#2215)
* [Commands] Cleanup #lastname, #npcedit, #title, and #titlesuffix Commands.
- Cleanup messages and logic.

* Update emu_constants.h

* Update command.cpp

* Update command.cpp

* Cleanup of GetXName methods to not define map unnecessarily.

* Update emu_constants.cpp

* Update npcedit.cpp
2022-05-28 14:35:05 -04:00
Kinglykrab 7de50d0e60 [Bug Fix] Fix IP Exemptions. (#2189)
* [Bug Fix] Fix IP Exemptions.
- IP Exemptions were broken due to GetAccountID() returning 0 in logic somehow, resolved this by setting a variable to GetAccountID() at the beginning of the method.
- Fixed weird IP messages where the long form of IP was displayed instead of the string form.
- Fixes edge case where IP rule may be set to -1 and this will make anyone get instantly kicked if IP Exemptions were enabled as their IP Count would always be greater than -1.

* Update client.cpp

* Update client.cpp

* Update clientlist.cpp

* Update clientlist.cpp
2022-05-27 23:57:55 -04:00
Paul Coene aaaee6c6a4 [Bug Fix] IsDamage test for lifetap was not complete. (#2213)
* [Bug Fix] IsDamage test for lifetap was not complete.

* Fix magic # and formatting as per Kingly

* Added #define
2022-05-27 15:30:38 -04:00
Kinglykrab d7f38361f2 [Commands] Cleanup #findaliases and #help Commands. (#2204)
- Cleanup messages and logic.
- Add saylinks to messages for ease of use when searching for commands as most have help messages when using them incorrectly or require no arguments and can be used immediately from the say link.
2022-05-27 15:28:36 -04:00
Kinglykrab 275995a374 [Commands] Cleanup #zone and #zoneinstance Commands. (#2202)
* [Commands] Cleanup #zone and #zoneinstance Commands.
- Cleanup messages and logic.
- Broke these commands out in to their own files.

* Update database.cpp

* Update database.cpp

* Update database.cpp
2022-05-27 15:26:30 -04:00
Kinglykrab 7072b5721b [Rules] Add Spells:BuffsFadeOnDeath. (#2200)
- Allows you to disable buffs fading on death.
2022-05-27 15:00:59 -04:00
Kinglykrab 123bc5f19a [Commands] Cleanup #findclass and #findrace Commands. (#2211)
- Cleanup messages and logic.
- Add bitmasks to player race messages.
2022-05-27 14:46:53 -04:00
Kinglykrab e6db71e31e [Commands] Cleanup #corpsefix Command. (#2197)
* [Commands] Cleanup #corpsefix Command.
- Cleanup messages and logic.

* Update entity.cpp
2022-05-27 14:46:26 -04:00
Kinglykrab 129a738072 [Commands] Cleanup #level Command. (#2203)
- Cleanup messages and logic.
- Breakout #level into its own command file.
2022-05-27 14:45:26 -04:00
Kinglykrab 0de90dc135 [Rules] Add Spells:IllusionsAlwaysPersist. (#2199)
- Allows illusions to always persist beyond death or zoning.
2022-05-27 14:39:35 -04:00
Kinglykrab 5bc4cff7a9 [Regen] Fix possible overflow in CalcHPRegenCap(). (#2185) 2022-05-27 14:39:25 -04:00
Kinglykrab f9191d4ef4 [Commands] Cleanup #oocmute Command. (#2191)
- Cleanup messages and logic.
- Add ServerOOCMute_Struct for cleanliness.
2022-05-27 14:38:40 -04:00
Michael Cook (mackal) 49d751b3d5 Revert "[Aggro] Rooted mobs will add other hated targets to Hate list (#2180)" (#2214)
This reverts commit 14f48fcc93.
2022-05-27 11:40:43 -04:00
Paul Coene 14f48fcc93 [Aggro] Rooted mobs will add other hated targets to Hate list (#2180) 2022-05-27 09:37:55 -04:00
titanium-forever 25addc3bd9 Create user directory during account creation to ensure default files are copied to profile from /etc/skel (#2176)
Co-authored-by: Kieren Hinch <khinch-github@nylonmoon.com>
2022-05-27 00:22:31 -05:00
Kinglykrab 7f12ad325a [Bug Fix] Fix bot compile locking client on server enter. (#2210) 2022-05-26 14:10:19 -04:00
Kinglykrab 6636c64c82 [Commands] Fix typos in #ban and #ipban Commands. (#2209) 2022-05-25 20:05:07 -04:00
Chris e2708af6f2 [Bug Fix] Blocked spells max spell id increased (#2207)
https://github.com/EQEmu/Server/pull/2073 broke blocking spells. There is another location in mob.h that needs to be updated to int32. Tested as fixed on my server.
2022-05-25 17:53:40 -04:00
Kinglykrab 1de0c27629 [Bug Fix] Fix HP Regen Per Second. (#2206)
`hp_regen_rate` was being used for `hp_regen_per_second` incorrectly.
2022-05-25 12:08:28 -05:00
Kinglykrab 9ccdb9eb84 [Bot Commands] Use Account Status Constants. (#2201)
- Convert bot_command_add calls to use constants instead of magic numbers.
2022-05-23 19:56:56 -04:00
Kinglykrab e69f7a6cf1 [Commands] Remove unused/broken #deletegraveyard and #setgraveyard Commands. (#2198)
- These commands don't function in their current state, and they probably haven't ever.
- Removing the commands and putting this in an editor makes more sense, as #setgraveyard uses the current zone XYZ coordinates of a target to set a graveyard for another zone. and they also only allow version 0 graveyards.
- Not sure of a better idea than just deleting, as setting data based on another zone using your current zone's data seems beyond the scope of a command.
2022-05-23 19:56:30 -04:00
Kinglykrab efd04f8324 [Commands] Cleanup #motd Command. (#2190) 2022-05-23 19:56:19 -04:00
Kinglykrab eeacc62a91 [Rules] Cleanup all unused rules. (#2184) 2022-05-23 19:56:03 -04:00
Kinglykrab a7a525ed0b [Commands] #bind Typo. (#2196) 2022-05-22 22:31:14 -04:00
Kinglykrab e43538cf73 [Commands] Cleanup #kill Command. (#2195)
- Cleanup messages and logic.
2022-05-22 22:31:08 -04:00
Kinglykrab 5b90d26a33 [Bug Fix] Fix bot guild removal. (#2194) 2022-05-22 22:31:03 -04:00
Kinglykrab 992e4ac59e [Commands] Consolidate #lock and #unlock Commands into #serverlock. (#2193)
- Convert the two commands into one command.
- Cleanup struct naming.
2022-05-22 22:30:56 -04:00
Chris Miles 6b85c914a5 Schema consistency fixes (#2192) 2022-05-21 23:44:04 -04:00
Kinglykrab 089246db53 [Cleanup] Move Client::Undye() to client.cpp from #path Command. (#2188)
- Client::Undye() was inside the #path command file.
2022-05-21 10:26:45 -04:00
Paul Coene f3e5423677 [Bug Fix] Fix duplicate and missing messages due to innate in spells (#2170)
* [Bug Fix] Fix duplicate and missing messages due to innate skill in spells.

* Seperate spell and melee damage range and skip

* Refine when innate messages are produced.

* Fix magic # (replace with constant)
2022-05-20 11:49:18 -04:00
Kinglykrab 0e96099b3d [Titles] Cleanup titles, title suffix, and last name methods. (#2174)
* [Titles] Cleanup titles, title suffix, and last name methods.
- Use strings instead of const chars*.
- Add optional parameter to SetAATitle in Lua so you can save to the database similar to Perl.
- Cleanup #lastname command.
- Cleanup #title command.
- Cleanup #titlesuffix command.

* Update npc.cpp
2022-05-19 20:15:44 -04:00
Kinglykrab 6398381c44 [Quest API] Add CheckNameFilter to Perl/Lua. (#2175)
- Add quest::checknamefilter(name) to Perl.
- Add eq.check_name_filter(name) to Lua.
- Allows operators to check strings against the name filter for stuff like setting custom pet names, titles, suffixes, etc in scripts.
2022-05-19 20:01:14 -04:00
Kinglykrab 7c1a139991 [Cleanup] Quest API push methods using invalid types. (#2172)
* [Cleanup] Quest API push methods using invalid types.
- Some push methods were pushing integers as unsigned integers or unsigned integer as integers, this fixes all of that.
- Also cleans up some lines that had multiple function calls on them.

* More cleanup of bools and one expansion name was wrong.
2022-05-15 22:14:16 -04:00
Kinglykrab 8554aab2ff [Cleanup] Remove unused methods. (#2171) 2022-05-15 19:12:33 -04:00
hg 77e72ba666 Save eyes in #npcedit featuresave (#2178) 2022-05-15 19:12:22 -04:00
Kinglykrab 8329760632 [Quest API] Add TaskSelector to Perl/Lua. (#2177)
- Add $client->TaskSelector(task_list) to Perl.
- Add client:TaskSelector({task_list}) to Lua.
- Allow $client->AssignTask(task_id) in Perl.
- Allow client:AssignTask(task_id) in Lua.
- Can now assign tasks in scripts without the NPC ID parameter.
2022-05-15 00:49:55 -04:00
hg d8aa8f7e7a [Opcode] Implement SetFace opcode (#2167)
* Implement SetFace opcode

This implements the opcode that's used to update zone clients when a
client updates their face

* Use SetFace in #feature command

Add check for valid number

This adds the #feature eyes command which isn't in the illusion struct
2022-05-11 19:57:20 -04:00
Kinglykrab 29cdd91ca0 [Quest API] Add GetHealAmount() and GetSpellDamage() to Perl/Lua. (#2165)
- Add $client->GetHealAmount() to Perl.
- Add $client->GetSpellDamage() to Perl.
- Add client:GetHealAmount() to Lua
- Add client:GetSpellDamage() to Lua.
2022-05-11 06:35:27 -04:00
Kinglykrab df99d97431 [Cleanup] Cleanup #kick message. (#2164) 2022-05-10 19:52:14 -04:00
Kinglykrab f314e05087 [Hot Fix] Off by on in Merchant Loading. (#2166) 2022-05-10 18:25:32 -04:00
Kinglykrab d120cf8a40 [Commands] #reload Command Overhaul. (#2162)
* [Commands] #reload Command Overhaul.
- Consolidated #reloadaa, #reloadallrules, #reloadcontentflags, #reloademote, #reloadlevelmods, #reloadmerchants, #reloadperlexportsettings, #reloadqst, #reloadstatic, #reloadtitles, #relaodtraps, #reloadworld, and #reloadzps in to one command.
- #reload has 15 different sub commands you may use, including Log Settings and Tasks reloading.
- All the reload commands are a part of the Developer Tools Menu messages now, as well as part of the documentation.
- Fixes the commands that weren't actually sending their packet to zone server to globally reload stuff.
- Added Variables table reloading to command.

* Consistency.

* Hot reload.

* Final big push.
2022-05-10 06:19:07 -04:00
Chris Miles 209b0eb273 [int64] Hate Fixes (#2163)
* Hate fixes

* Update perl_hateentry.cpp

* Update perl_hateentry.cpp
2022-05-09 20:49:43 -05:00
Kinglykrab 763fc82379 [Merchants] Add Merchant Data Bucket capability. (#2160)
* [Merchants] Add Merchant Data Bucket capability.
- Allows server operators to limit merchant items based on data bucket values and comparisons.
- Adds 3 columns, bucket_name, bucket_value, and bucket_comparison to merchantlist table.
- Bucket is checked based on GetBucketKey()-bucket_name.
- Buckets are mass loaded when using the merchant so it's not a database call per item, just a grouping of all their buckets from the start.
- This is a nearly year old pull request redone for master.
- bucket_comparison Values are as follows:
        - bucket_comparison 0: bucket_name == bucket_value
        - bucket_comparison 1: bucket_name != bucket_value
        - bucket_comparison 2: bucket_name >= bucket_value
        - bucket_comparison 3: bucket_name <= bucket_value
        - bucket_comparison 4: bucket_name > bucket_value
        - bucket_comparison 5: bucket_name < bucket_value
        - bucket_comparison 6: bucket_name is any of  pipe(|)-separated bucket_value
        - bucket_comparison 7: bucket_name is not any of  pipe(|)-separated bucket_value
        - bucket_comparison 8: bucket_name is between first and second value of pipe(|)-separated bucket_value
        - bucket_comparison 9: bucket_name is not between first and second value of pipe(|)-separated  bucket_value

* Revert query change.
2022-05-09 21:36:51 -04:00
Kinglykrab 6e0d101457 [Cleanup] Possible issues with variable/parameter name equality. (#2161) 2022-05-09 21:00:37 -04:00
Chris Miles a1a4f91ea6 [Hotfix] Fix regression caused by #2129 2022-05-09 01:18:10 -05:00
Michael Cook (mackal) 6cc845e05e Fix out of bounds issues with SPA 288 (#2157) 2022-05-08 18:18:24 -04:00
Kinglykrab 597e324319 [Bug FIx] Fix #repop Command. (#2159)
If you use no arguments, the command does not repop.
2022-05-08 17:01:50 -04:00
Kinglykrab f370a6048f [Bug Fix] Make Perl TakeMoneyFromPP int64 (#2158) 2022-05-08 13:17:46 -04:00
Kinglykrab 9d784d0d9b [Bug Fix] Fix possible issue where variables have the same name. (#2156)
* [Bug Fix] Fix possible issue where variables have the same name.

* Naming.
2022-05-08 01:43:28 -04:00
Chris Miles fd7b15abb1 [int64] Windows Compile Fixes (#2155)
* int64 windows aftermath

* Perl.

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2022-05-07 23:45:52 -05:00
Kinglykrab b27428a6d8 [Commands] Cleanup #cvs Command. (#2153)
* [Commands] Cleanup #cvs Command.
- Cleanup messages and logic.
- std::find was using .begin() in both comparisons, so it wasn't working and unique IPS always returned 1.

* Update cvs.cpp
2022-05-07 23:45:44 -04:00
Chris Miles f201d4c999 [int64] Support for HP / Mana / End / Damage / Hate (#2091)
* Initial int64 work

* Hate 64 bit

* Update special_attacks.cpp

* Aggro / Damage / Hate int64

* NPC edit adjustments

* Fix bot compile

* More int64 adjustments

* More int64 references

* npcedit references

* aggrozone

* More int64 changes

* More int64 changes for damage

* Many more damage int64 references

* More spell damage int64 conversions

* HealDamage

* Damage fully working

* Remove debug

* Add migration

* More int64 adjustments

* Much wow, many int64

* More int64

* PR adjustments
2022-05-07 22:32:02 -05:00
Kinglykrab d9c41526e8 [Commands] Cleanup #ban, #ipban, #flag, #kick, #setlsinfo, and #setpass Commands. (#2104)
* [Commands] Cleanup #ban, #ipban, #flag, and #kick Commands.
- Cleanup messages and logic.
- Add ServerFlagUpdate_Struct for flag updates.

* Add #setlsinfo and #setpass to cleanup.

* Update setlsinfo.cpp

* Update database.cpp

* Update database.cpp

* Update command.cpp
2022-05-07 23:28:45 -04:00
Chris Miles 07b46ed445 [UCS] Auto Client Reconnection (#2154) 2022-05-07 22:24:11 -05:00
Chris Miles 9f9eaed983 [Hotfix] Fix DB version merge 2022-05-07 21:19:21 -05:00
Chris Miles 862e1e33bf [Tasks] Implement Task Goal Match List (#2097)
* [Tasks] Implement Task Goal Match List

* Migration

* Add npc_type_id to match types for npc kill

* Flip str_tolower
2022-05-07 15:37:06 -05:00
Kinglykrab dca34cc2ff [Commands] Cleanup #time and #timezone Command. (#2147)
* [Commands] Cleanup #time and #timezone Command.
- Cleanup messages and logic.

* Cleanup.
2022-05-07 05:03:58 -05:00
Kinglykrab ccb316b11b [Bug Fix] NPC::GetNPCStat has no default return. (#2150)
```In member function 'float NPC::GetNPCStat(const char*)':
/drone/src/zone/npc.cpp:2810:1: warning: control reaches end of non-void function [-Wreturn-type]```
2022-05-07 05:01:36 -05:00
Kinglykrab 10ae4ea8f6 [Bug Fix] Lua GetBlockNextSpell() no return. (#2151)
- No return value.
2022-05-07 05:01:22 -05:00
Kinglykrab 7df9b2974b [Commands] Cleanup #reloadzps Command. (#2129)
* [Commands] Cleanup #reloadzps Command.
- Cleanup messages and logic.
- Make reloading of zone points global instead of zone specific.

* Further cleanup.
- Add zone->GetZoneDescription().
- Add mob->GetTargetDescription(mob).

* Final cleanup.

* Typo.
2022-05-07 03:23:15 -04:00
Kinglykrab 0b3065d7a9 [Commands] Cleanup #reloadtraps Command. (#2126)
* [Commands] Cleanup #reloadtraps Command.
- Cleanup messages and logic.
- Allow the option to reload/repop traps globally for this command.

* Typos.
2022-05-06 22:39:21 -04:00
Kinglykrab 7549fbbeea [Commands] Cleanup #reloadlevelmods Command. (#2122)
* [Commands] Cleanup #reloadlevelmods Command.
- Cleanup messages and logic.
- Make the reloading of modifiers global instead of zone-specific.

* Remove unnecessary message.

* Update worldserver.cpp

* Update worldserver.cpp

* Update worldserver.cpp
2022-05-06 22:31:17 -04:00
Kinglykrab e26eba8e03 [Commands] Cleanup #npctype_cache Command. (#2109)
* [Commands] Cleanup #npctype_cache Command.
- Cleanup messages and logic.
- Loop was returning as soon as it found first ID, so you couldn't use the spaced ID list functionality at all.

* Remove command.
2022-05-06 22:13:16 -04:00
Kinglykrab 02828a73b8 [Commands] Cleanup #npcspecialattk Command. (#2108)
* [Commands] Cleanup #npcspecialattk Command.
- Cleanup messages and logic.

* Remove command.
2022-05-06 22:06:12 -04:00
Kinglykrab 0e710fe5e7 [Commands] Cleanup #ucs Command. (#2149)
* [Commands] Cleanup #ucs Command.
- Cleanup messages and logic.

* Remove command.
2022-05-06 22:03:13 -04:00
Kinglykrab 86568e9292 [Commands] Cleanup #reloadaa Command. (#2120)
* [Commands] Cleanup #reloadaa Command.
- Cleanup messages.
- Remove unncessary file_exists command from file.
- Make reloading of Alternate Advancement data global instead of zone specific.

* Update worldserver.cpp

* Update worldserver.cpp
2022-05-06 21:57:19 -04:00
Kinglykrab bf1d05d639 [Commands] Cleanup #profanity Command. (#2113)
* [Commands] Cleanup #profanity Command.
- Cleanup messages and logic.

* Update profanity_manager.cpp

* Update profanity_manager.cpp

* Update profanity_manager.cpp

* Update profanity_manager.cpp
2022-05-06 21:36:23 -04:00
Kinglykrab 4eaf44fc33 [Commands] Remove unused #bestz and #pf Commands. (#2112)
- Remove unused commands.
2022-05-06 21:13:26 -04:00
Kinglykrab e62a283a79 [Commands] Cleanup #makepet Command. (#2105)
- Cleanup messages and logic.
2022-05-06 20:58:07 -04:00
Kinglykrab a847e461c1 [Commands] Cleanup #npcemote Command. (#2106)
* [Commands] Cleanup #npcemote Command.
- Cleanup messages and logic.

* Update npcemote.cpp
2022-05-06 20:58:01 -04:00
Kinglykrab 37fefad58e [Commands] Cleanup #npcsay and #npcshout Commands. (#2107)
* [Commands] Cleanup #npcsay and #npcshout Commands.
- Cleanup messages and logic.

* Update npcsay.cpp

* Update npcshout.cpp
2022-05-06 20:57:53 -04:00
Kinglykrab 26b26af8d7 [Commands] Cleanup #npctypespawn Command. (#2110)
- Cleanup messages and logic.
2022-05-06 20:50:02 -04:00
Kinglykrab ee86001132 [Commands] Cleanup #reloadmerchants Command. (#2123)
* [Commands] Cleanup #reloadmerchants Command.
- Cleanup messages and logic.
- Make the reloading of merchants global instead of zone specific.

* Update worldserver.cpp

* Update worldserver.cpp
2022-05-06 20:48:46 -04:00
Kinglykrab 7d89c05a48 [Commmands] Cleanup #questerrors Command. (#2116)
- Cleanup messages and logic.
2022-05-06 20:42:47 -04:00
Kinglykrab 6e15fae6a0 [Commands] Cleanup #randomizefeatures Command. (#2118)
- Cleanup messages and logic.
- Make #randomizefeatures function for Iksar and Vah Shir.
2022-05-06 20:42:34 -04:00
Kinglykrab 2f962c2c8a [Commands] Cleanup #refreshgroup Command. (#2119)
- Cleanup messages and logic.
2022-05-06 20:42:25 -04:00
Kinglykrab 6bbd1e94c3 [Commands] Cleanup #push Command. (#2114)
- Cleanup messages and logic.
2022-05-06 19:38:15 -05:00
Kinglykrab 78d44440eb [Commands] Cleanup #qglobal Command. (#2115)
- Cleanup messages and logic.
2022-05-06 19:37:45 -05:00
Kinglykrab 1e45ffa24d [Bug Fix] Resolve subroutine redefinition due to bot methods. (#2117)
* [Bug Fix] Resolve subroutine definition due to bot methods.

* Update perl_bot.cpp
2022-05-06 19:33:20 -05:00
Kinglykrab 37d5d96871 [Commands] Cleanup #resetaa_timer Command. (#2131)
* [Commands] Cleanup #resetaa_timer Command.
- Cleanup messages and logic.

* Typos.
2022-05-06 20:26:59 -04:00
Kinglykrab 90725f9fd9 [Commands] Cleanup #revoke Command. (#2134)
* [Commands] Cleanup #revoke Command.
- Cleanup messages and logic.

* Update revoke.cpp
2022-05-06 20:26:54 -04:00
Kinglykrab c1aa3e7056 [Commands] Cleanup #reloadallrules Command. (#2121)
* [Commands] Cleanup #reloadallrules Command.
- Cleanup messages.

* Typo.
2022-05-06 20:26:39 -04:00
Kinglykrab 1d59fff2bf [Commands] Cleanup #reloadperlexportsettings Command. (#2124)
* [Commands] Cleanup #reloadperlexportsettings Command.
- Cleanup messages and logic.
- Make reloading of Perl event export settings global instead of zone specific.

* Update worldserver.cpp
2022-05-06 20:22:58 -04:00
Kinglykrab 6beb220e93 [Commands] Cleanup #reloadtitles Command. (#2125)
* [Commands] Cleanup #reloadtitles Command.
- Cleanup messages;

* Update worldserver.cpp
2022-05-06 20:20:42 -04:00
Kinglykrab 3091a84540 [Commands] Cleanup #reloadworld and #repop Command. (#2127)
* [Commands] Cleanup #reloadworld Command.
- Cleanup messages and logic.

* [Commands] Cleanup #reloadworld and #repop Command.
- Cleanup messages and logic.
- Add #reloadworld 2 option to forcefully repop all mobs globally as well as reset quest timers and reload quests.
- Remove delay argument from #repop as it isn't used for anything.

* Typos.
2022-05-06 20:06:51 -04:00
Kinglykrab 9fbab76d40 [Commands] Cleanup #summonburiedplayercorpse Command. (#2146)
* [Commands] Cleanup #summonburiedplayercorpse Command.
- Cleanup messages and logic.

* Update summonburiedplayercorpse.cpp
2022-05-06 20:06:04 -04:00
Kinglykrab b03d47b9cd [Commands] Cleanup #trapinfo Command. (#2148)
* [Commands] Cleanup #trapinfo Command.
- Cleanup messages.
- Does not modify the command file, as it's only one line that calls the method in zones/trap.cpp.

* Cleanup.

* Update trap.cpp

* Update trap.cpp
2022-05-06 20:05:55 -04:00
Kinglykrab b583d95f09 [Commands] Cleanup #reloadrulesworld Command. (#2128)
- Cleanup messages and logic.
2022-05-06 20:05:40 -04:00
Kinglykrab 6846deb9c8 [Commands] Cleanup #reloadstatic Command. (#2130)
- Cleanup messages and logic.
- Make reloading of static zone data global instead of zone specific.
2022-05-06 20:03:22 -04:00
Kinglykrab adfec15893 [Commands] Cleanup #resetaa Command. (#2132)
* [Commands] Cleanup #resetaa Command.
- Cleanup messages and logic.

* Update resetaa.cpp
2022-05-06 20:02:32 -04:00
Kinglykrab 132c936c90 [Commands] Cleanup #sensetrap Command. (#2137)
* [Commands] Cleanup #sensetrap Command.
- Cleanup messages and logic.

* Update sensetrap.cpp
2022-05-06 20:01:29 -04:00
Kinglykrab a0ed0d57c5 [Commands] Cleanup #serverinfo Command. (#2138)
* [Commands] Cleanup #serverinfo Command.
- Cleanup message and logic.
- Use popup instead of messages.

* Update serverinfo.cpp
2022-05-06 20:01:21 -04:00
Kinglykrab 128e8ce08d [Commands] Cleanup #resetdisc_timer Command. (#2133)
- Cleanup messages and logic.
2022-05-06 19:50:58 -04:00
Kinglykrab 55629ce396 [Commands] Cleanup #roambox Command. (#2135)
- Cleanup messages and logic.
2022-05-06 19:50:26 -04:00
Kinglykrab bf7c1252f8 [Commands] Cleanup #save Command. (#2136)
- Cleanup messages and logic.
2022-05-06 19:50:19 -04:00
Kinglykrab e2bfa44df0 [Commands] Cleanup #serverrules Command. (#2139)
- Cleanup messages and logic.
- Change separator from new line to pipe separator, as new line was non-functional.
2022-05-06 19:50:09 -04:00
Kinglykrab e5acc7c322 [Commands] Cleanup #shownpcgloballoot and #showzonegloballoot Command. (#2141)
- Cleanup messages and logic.
2022-05-06 19:50:03 -04:00
Kinglykrab 5aaaaed6f1 [Commands] Add #feature Command. (#2142)
* [Commands] Add #feature Command.
- Removes #beard, #beardcolor, #details, #face, #hair, #haircolor, #helm, #heritage, #size, and #tattoo commands.
- Cleanup messages and logic.
- Consolidate 13 different feature settings to this one command.
- Unique commands including #gender, #race, and #texture were not removed.

* Add missing feature.cpp.

* Update feature.cpp
2022-05-06 19:49:56 -04:00
Kinglykrab 6d31786456 [Commands] Cleanup #spawnfix Command. (#2143)
- Cleanup messages and logic.
2022-05-06 19:49:51 -04:00
Kinglykrab 0aeab11408 [Commands] Cleanup #summon Command. (#2145)
* [Commands] Cleanup #summon Command.
- Cleanup messages and logic.
- Add glm::vec4 overload for GMMove.
- Remove unused parameter from GMMove.
- Remove unnecessary Lua GMMove now that parameter is gone.

* Update summon.cpp

* Cleanup.
2022-05-06 18:45:12 -05:00
Kinglykrab fc484d0b1c [Commands] Cleanup #gassign Command. (#2101)
* [Commands] Cleanup #gassign Command.
- Cleanup messages and logic.

* Update gassign.cpp

* Update gassign.cpp
2022-05-06 19:13:28 -04:00
Kinglykrab 8dcc810b43 [Commands] Cleanup #spawnstatus Command. (#2144)
* [Commands] Cleanup #spawnstatus Command.
- Cleanup messages and logic.

* Further cleanup and consolidation, add inline GetTimer() as timer is protected.
2022-05-06 18:12:29 -05:00
Kinglykrab 04f3d6286c [Commands] Cleanup #attack Command. (#2103)
- Cleanup messages and logic.
2022-05-03 23:05:16 -04:00
Kinglykrab 35044becc1 [Commands] Cleanup #freeze and #unfreeze Commands. (#2102)
- Cleanup messages and logic.
- Remove the ability to #freeze yourself.
2022-05-03 23:05:09 -04:00
Kinglykrab e08afb1234 [Commands] Cleanup #getvariable Command. (#2100)
- Cleanup messages and logic.
2022-05-03 23:05:02 -04:00
Kinglykrab b2b87ea4e0 [Quest API] Expand Bot quest API functionality. (#2096)
* [Quest API] Expand Bot quest API functionality.
- Add $bot->AddItem(slot_id, item_id, charges, attuned, augment_one, augment_two, augment_three, augment_four, augment_five, augment_six) to Perl.
- Add $bot->CountItem(item_id) to Perl.
- Add $bot->HasItem(item_id) to Perl.
- Add $bot->RemoveItem(item_id) to Perl.
- Add bot:AddItem(slot_id, item_id, charges, attuned, augment_one, augment_two, augment_three, augment_four, augment_five, augment_six) to Lua.
- Add bot:CountItem(item_id) to Lua.
- Add bot:GetOwner() to Lua.
- Add bot:HasItem(item_id) to Lua.
- Add bot:RemoveItem(item_id) to Lua.

* Fix possible crash.
2022-05-03 23:04:54 -04:00
Kinglykrab 837c0a4385 [Quest API] Perl Money Fixes. (#2098)
- Fixes `$client->GetAllMoney()` to use `uint64` and not overflow int value.
- Fixes `$client->GetCarriedMoney()` to use `uint64` and not overflow int value.
2022-05-03 22:55:56 -04:00
Kinglykrab 9b075c28b6 [Quest API] Add commify to Perl/Lua. (#2099)
- Add quest::commify(number) to Perl.
- Add eq.commify(number) to Lua.
2022-05-03 19:44:22 -04:00
Paul Coene c4f05c3864 [Combat] Fix Frenzy vs opponents immune to non-magic (#2095)
* [Combat] Fix Frenzy vs opponents immune to non-magic

* Fix naming.

* Use snake case for variable
2022-05-02 23:08:08 -04:00
hg 0c12ca8370 [Repository] Cast floats to avoid grid repository warnings (#2094)
This is in the custom repository method file so the generator doesn't
need modified for it
2022-05-01 21:53:37 -05:00
Chris Miles a450779c91 [Drone] Speed up drone builds (#2092)
* Speed up drone builds

* Add chown for ccache

* Add the cmake compiler launcher flag for ccache

* Update .drone.yml

* Don't optimize

* Don't optimize take 2
2022-05-01 20:17:43 -05:00
hg dc004c2a9d Remove already defined method (#2093)
CastRestrictedSpell is already defined in common/spdat

MSVC Debug builds caught this as an ODR violation, though Release
builds still allowed it (maybe because the methods were identical)
2022-05-01 20:54:50 -04:00
Kinglykrab d59dcb68ca [Commands] Add additional #peqzone functionality. (#2085)
* [Commands] Add additional #peqzone functionality.
- Add #peqzone flagging capabilities so operators don't have to blanket allow #peqzone access to zones.
- Allows you to set a zone's `peqzone` column to `2` and disallow use of `#peqzone` until they have been given the appropriate flag.
- Add #peqzone_flags command to list your #peqzone flags similar to #flags command.
- Add `character_peqzone_flags` table to database and database_schema.h.
- Required SQL update to add the new table.
- Add client:ClearPEQZoneFlag(zone_id) to Lua.
- Add client:HasPEQZoneFlag(zone_id) to Lua.
- Add client:LoadPEQZoneFlags() to Lua.
- Add client:LoadZoneFlags() to Lua.
- Add client:SendPEQZoneFlagInfo(client) to Lua.
- Add client:SetPEQZoneFlag(zone_id) to Lua.
- Add $client->ClearPEQZoneFlag(zone_id) to Perl.
- Add $client->HasPEQZoneFlag(zone_id) to Perl.
- Add $client->LoadPEQZoneFlags() to Perl.
- Add $client->SendPEQZoneFlagInfo(client) to Perl.
- Add $client->SetPEQZoneFlag(zone_id) to Perl.

* Fixes.
2022-05-01 19:39:52 -04:00
Chris Miles c7dbdfae58 [Combat] Basic Combat Recording (#2090)
* Basic combat recording

* Update combat_record.h
2022-05-01 18:08:12 -05:00
Kinglykrab 759f9bd007 [Bots] Bot::PerformTradeWithClient Cleanup. (#2084)
* [Bots] Bot::PerformTradeWithClient Cleanup.
- Cleanups message and logic.
- Initial cleanup to eventually allow easy use with Perl/Lua quest API.

* Duplicated comment.
2022-05-01 19:05:12 -04:00
Chris Miles 8f0b80097e [Refactor] Simplify NPC Loading (#2087)
* Refactor / simplify NPC loading

* Update spacing [skip ci]

* Update base_npc_types_repository.h
2022-05-01 17:04:38 -05:00
Chris Miles 71ae03d5bc [Compile] Decrease build times using unity build strategy (#2089) 2022-05-01 15:53:21 -05:00
KayenEQ 34dc081306 [Spells] Update to target types Beam and Cone to ignore invalid targets. (#2080) 2022-05-01 16:50:55 -04:00
Chris Miles 35b35f85cf [Logging] Update BUILD_LOGGING=false Blank Aliases (#2083) 2022-05-01 14:54:46 -05:00
Chris Miles 90da136b7a [Regen] Implement Per Second HP Regen for NPCs (#2086)
* Implement NPC per second regen

* Add hp_regen_per_second to ModifyNPCStat

* Take per second regen the rest of the way

* Add #npcedit hp_regen_per_second

* Add db migration
2022-05-01 10:26:16 -04:00
Chris Miles 5b4aeaa457 [Code Cleanup] Remove this-> in code where its implied (#2088) 2022-05-01 10:22:09 -04:00
Kinglykrab b02008ec53 [Bots] Remove unused methods. (#2082)
- Remove Bot::BotTradeSwapItem().
- Remove Bot::ApplySpecialAttackMod().
2022-04-30 18:13:34 -04:00
Kinglykrab c709a6aa8e [Quest API] Add multiple inventory method short hands to client. (#2078)
- Allows you to just directly use Client instead of having to grab reference to inventory.
- Add $client->CountAugmentEquippedByID(item_id) to Perl.
- Add $client->HasAugmentEquippedByID(item_id) to Perl.
- Add $client->CountItemEquippedByID(item_id) to Perl.
- Add $client->HasItemEquippedByID(item_id) to Perl.
- Add client:CountAugmentEquippedByID(item_id) to Lua.
- Add client:HasAugmentEquippedByID(item_id) to Lua
- Add client:CountItemEquippedByID(item_id) to Lua.
- Add client:HasItemEquippedByID(item_id) to Lua.
2022-04-30 11:47:05 -04:00
Kinglykrab 9113508269 [Bots] Fix ^dyearmor command math. (#2081)
* [Bots] Fix ^dyearmor command math.

* Typo.
2022-04-30 10:57:22 -04:00
Kinglykrab 1b7c12297d [Quest API] Add AddPlatinum(), GetCarriedPlatinum() and TakePlatinum() to Perl/Lua. (#2079)
* [Quest API] Add AddPlatinum(), GetCarriedPlatinum() and TakePlatinum() to Perl/Lua.
- Allows for easier NPC interactions.
- GetCarriedPlatinum() adds together all currencies in inventory based on conversion amounts so it works easily with removals/checks.
- Add $client->AddPlatinum(platinum, update_client) to Perl.
- Add $client->GetCarriedPlatinum() to Perl.
- Add $client->TakePlatinum(platinum, update_client) to Perl.
- Add client:AddPlatinum(platinum, update_client) to Lua.
- Add client:GetCarriedPlatinum() to Lua.
- Add client:TakePlatinum(platinum, update_client) to Lua.

* Formatting.
2022-04-30 10:57:05 -04:00
nytmyr b1311780a7 [Quest API] Add EVENT_SKILL_UP & EVENT_LANGUAGE_SKILL_UP to Perl/Lua (#2076)
Added EVENT_SKILL_UP to Perl/Lua

Adds sub EVENT_SKILL_UP output for use.
Exports:
$skill_id - ID of the skill being exported. Will export skill or language as the same so check below.
$skill_value - New skill level
$skill_max - Maximum value of skill
$is_tradeskill - 0 for non-tradeskill, 1 for tradeskill

Example usage:
sub EVENT_SKILL_UP {
if($is_tradeskill == 0) {
		quest::shout("Skill Increase! " . $client->GetCleanName() . " has increased their " . quest::getskillname($skill_id) . " to " . $skill_value . " of " . $skill_max . "!"); #deleteme
	}
	if ($is_tradeskill == 1) {
		quest::shout("Tradeskill Increase! " . $client->GetCleanName() . " has increased their " . quest::getskillname($skill_id) . " to " . $skill_value . " of " . $skill_max . "!"); #deleteme
	}
}

Adds sub EVENT_LANGUAGE_SKILL_UP output for use.
Exports:
$skill_id - ID of the skill being exported. Will export skill or language as the same so check below.
$skill_value - New skill level
$skill_max - Maximum value of skill

Example usage:
sub EVENT_LANGUAGE_SKILL_UP  {
		quest::shout("Language Increase! " . $client->GetCleanName() . " has increased their " . quest::getlanguagename($skill_id) . " to " . $skill_value . " of " . $skill_max . "!"); #deleteme
}

Co-authored-by: toxin06 <53322305+toxin06@users.noreply.github.com>
2022-04-25 11:18:52 -05:00
cybernine186 0d734a0837 Bug Fix for WorldServer::HandleMessage, CZUpdateType_NPC (#2074) 2022-04-21 08:17:29 -04:00
Paul Coene ee54a7eb5f [Bug Fix] Restore missing messages for lifetap and dmg spells. (#2057)
* [Bug Fix] Restore missing messages for lifetap and dmg spells.

* Fix unintended duplicate message for DD on clients.

* Improve performance and accuracy of IsDamageSpell()
2022-04-13 23:11:26 -04:00
Kinglykrab a6814d46de [Commands] Cleanup #task Command. (#2071)
* [Commands] Cleanup #task Command.
- Cleanup messages.
- Add #task uncomplete [Task ID] to uncomplete a completed task without having to go in the database manually.

* Message cleanup.
2022-04-13 23:11:20 -04:00
KayenEQ 9dba6a6680 [Bug Fix] Blocked spells max spell id increased (#2073)
Blocked spell id should be checking int32 not int16
2022-04-13 11:54:11 -04:00
KayenEQ bc875ae554 [API] Methods for getting more information on quest timers. (#2060)
* hastimer

* [API] Check quest timer duration, timer remaining and if timer exists.

* [API] Methods for getting more information on quest timers.

* [API] Methods for getting more information on quest timers.

* [API] Methods for getting more information on quest timers.
2022-04-13 11:20:03 -04:00
KayenEQ bb897b755f [Bug Fix] Instrument Mods should not affect spells that change model size. (#2072)
Instrument Mods should not affect spells that change model size.
2022-04-13 11:02:21 -04:00
Kinglykrab a39a825045 [Quest API] Add GetBotListByCharacterID() to Perl/Lua. (#2069) 2022-04-02 17:51:26 -04:00
Paul Coene ccd0713b33 [Bug Fix] Fix recipient sound (vtell) on non-player races (#2066)
* [Bug Fix] Fix recipient sound (vtell) on non-player races

* Fix to use BaseRace as intended
2022-04-02 11:18:10 -04:00
Kinglykrab 5d94c9844a [Bug Fix] Clear title/suffix bug fix. (#2068)
- Clearing uses title ID 0, so need to make sure title ID is valid when setting and based on that, either check and set, or just clear.
2022-04-02 11:09:48 -04:00
KayenEQ bbe2db7c0f [Bug Fix] Bard Invisible causing display issues. (#2067)
* [Bug Fix] Bard Invisible causing display issues.

Error occurring due to bard modifiers being applied to invisible spell effect value.

* [Bug Fix] Bard Invisible causing display issues.
2022-04-02 00:01:38 +02:00
Kinglykrab 5dc76e595b [Quest API] Add GetBotListByClientName(client_name) to Perl/Lua. (#2064)
* [Quest API] Add GetBotListByClientName(client_name) to Perl/Lua.
- Add $entity_list->GetBotListByClientName(client_name) to Perl.
- Add eq.get_entity_list():GetBotListByClientName(client_name) to Lua.
- Allows you to get a bot list comprised solely of a specific character's bots.

* Update lua_entity_list.cpp
2022-03-23 08:47:47 -04:00
Natedog2012 b6b662f1c7 [Bug Fix] #peqzone no longer bypass Handle_OP_ZoneChange (#2063)
* [Bug Fix] #peqzone no longer bypass Handle_OP_ZoneChange

* Force other quest functions to trigger EVENT_ZONE properly

* call MovePC

* Use MoveZone to keep things uniform
2022-03-19 19:25:14 -04:00
Paul Coene 5275201713 [Bug Fix] Fix for being able to skill up on corspe. (#2058)
* [Bug Fix] Fix for being able to skill up on corspe.

* Fix whitespace
2022-03-19 13:21:54 -05:00
Paul Coene 1e86e0c02f [Bug Fix] manifest for db version 9176 had incorrect field name(#2062)
Field name in version 9176 doesn't match field created.
2022-03-19 13:13:56 -05:00
Natedog2012 25c0416f1e [Bug Fix] Force NPCs to respect special ability 24 and 50 when set on player pets (#2059)
* Force NPCs to respect special ability 24 and 50 when set on player pets

* Fix error in logic

* Remove this
2022-03-15 19:28:36 -05:00
Paul Coene 326dba6aeb [Logging] Fix log messages to final damage values (#2056) 2022-03-14 12:05:39 -04:00
Kinglykrab b75741ff4e [Bug Fix] Fix possible crash with zone name methods. (#2055)
- ZoneLongName and ZoneName were returning nullptr in places that were then attempting to use that nullptr value, causing zone crashes.
2022-03-13 15:59:57 -04:00
Kinglykrab 8e62383997 [Quest API] Add AddItem() to Perl/Lua. (#2054)
- Add $client->AddItem(item_data) to Perl.
- Add client:AddItem(item_table) to Lua.
- This will allow server operators to add items without needless parameters.

Perl Example:
```pl
my %item_data = (
	"item_id" => 1200,
	"charges" => 1,
	"augment_one" => 49656,
	"augment_two" => 49656,
	"augment_three" => 49656,
	"augment_four" => 49656,
	"augment_five" => 49656,
	"augment_six" => 49656,
	"attuned" => 1,
	"slot_id" => quest::getinventoryslotid("general1")
);
$client->AddItem(\%item_data);
```
Lua Example:
```lua
local item_data = {
	item_id = 1200,
	charges = 1,
	augment_one = 49656,
	augment_two = 49656,
	augment_three = 49656,
	augment_four = 49656,
	augment_five = 49656,
	augment_six = 49656,
	attuned = true,
	slot_id = Slot.General1
};
e.self:AddItem(item_data);
```
2022-03-13 15:59:48 -04:00
KayenEQ 4296e2e39e [API] GetNPCStat default better naming (#2053) 2022-03-12 20:01:25 -05:00
Kinglykrab e5f924d1d5 [Quest API] Allow EVENT_ZONE to be parsed as non-zero to prevent zoning. (#2052)
- This will allow server operators to prevent zoning to or from a specific zone based on whatever criteria they want.
2022-03-12 16:11:27 -05:00
Kinglykrab fb2aee1827 [Quest API] Add EVENT_CAST_ON exports to EVENT_CAST and EVENT_CAST_BEGIN. (#2051)
- Export $caster_id and $caster_level to EVENT_CAST and EVENT_CAST_BEGIN in Perl.
- Export e.caster_id and e.caster_level to EVENT_CAST and EVENT_CAST_BEGIN in Lua.
2022-03-12 14:33:00 -05:00
Kinglykrab 791d8b329d [Quest API] Export killed XYZH to EVENT_DEATH_ZONE in Perl. (#2050)
- Export $killed_x, $killed_y, $killed_z, and $killed_h to EVENT_DEATH_ZONE in Perl.
- Cleanup export strings and unnecessary .c_str() calls on event exports.
2022-03-12 13:44:01 -05:00
catapultam-habeo abcf8cbce1 [Bots] Update Bot Heal & Damage methods to more closely match Clients + Bugfixes (#2045)
* - Fixed Bots Spell Damage being negative under some circumstances (heal target)
- Allow Bots to send non-melee damage reports in the same manner as Clients
- Refactor\Update Bots Spell Damage & Heal calculations to match current state of Clients.
- Allow Bots to actually utilize Spell Damage and Heal Amount stats

* Don't send packets to bots

* remove random tab

* align text lol
2022-03-11 18:28:00 -05:00
Chris Miles 3ed6663c4c [Repositories] Update repositories (#2040) 2022-03-11 18:27:36 -05:00
Chris Miles f22608a43a [Bug FIx] Saylink Collation Database Edge Case (#2039) 2022-03-11 18:27:15 -05:00
KayenEQ 0e5d578d71 [Bug Fix] #tune command various fixes (#2046)
* tune fixes

* [Bug Fix] #tune command various fixes

accuracy tune fix
2022-03-11 10:13:51 -05:00
KayenEQ 8107ed52e1 [API] GetNPCStat can now return default stat values. (#2048)
* [API] GetNPCStat return default stat values.

* [API] GetNPCStat can now return default stat values.
2022-03-11 09:10:52 -05:00
Kinglykrab d904db0e52 [Quest API] Add caster_id and caster_level export to EVENT_CAST_ON in Perl/Lua. (#2049)
- Add $caster_id and $caster_level to EVENT_CAST_ON in Perl.
- Add e.caster_id and e.caster_level to EVENT_CAST_ON in Perl.
2022-03-10 21:46:27 -05:00
Kinglykrab e6c8a38ffa [Bug Fix] Spell Buckets/Globals did not allow string-based values. (#2043) 2022-03-09 14:18:24 -05:00
KayenEQ dbe0591b09 [API] Perl functions to set invulnerable to and modify environmental damage. (#2044)
* invulnerable

* modifier

* fix

* fix

* fix

* [API] Perl functions to set invulnerable to and modify environmental damage.

* [API] Perl and Lua functions to set invulnerable to and modify environmental damage.

credit to kinglykrab for lua
2022-03-08 19:50:46 -05:00
KayenEQ 5b6f1d38be [Bug Fix] Invisible will display as dropped now on air pets when they attack. (#2042)
invisible display issue on pets
2022-03-07 16:41:43 -05:00
JJ ce85c70a07 [Database] Update 2022_01_10_checksum_verification.sql (#2041) 2022-03-07 14:30:24 -06:00
KayenEQ f814b5bec5 [Bug Fix] PR 2032 would lock client on casting fail as written (#2038) 2022-03-06 22:03:19 -06:00
Chris Miles 4e40d7eacc [Command] Fix #killallnpcs from crashing (#2037) 2022-03-06 22:03:10 -06:00
Randy Girard 31ad0da811 [Content Filtering] Updates contents flags to be checked at runtime. (#1940)
* Updates contents flags to be checked at runtime.

* Fix formatting

* Add expansion flags

* Tweaks to logic

* Logic tweaks

* Update world_content_service.cpp

* Inverse DoesPassContentFiltering logic

* Update world_content_service.cpp

* Update world_content_service.cpp

Co-authored-by: Akkadius <akkadius1@gmail.com>
2022-03-06 22:02:57 -06:00
Chris Miles 25a19a13dc [Database] Add Primary ID Keys to Tables (#2036) 2022-03-06 22:02:33 -06:00
Paul Coene 2a5ddde78a [Feature] Client Checksum Verification (Resubmit old 1678) (#1922)
* [Feature] Client Checksum Verification (Resubmit old 1678)

* Updated db version

* Add new updatechecksum to CmakeLists.txt

* Removed magic number and used constant

* Fix new command to have access to worldserver

* spacing, more venbose desc and remove unneeded check

* Cleanup, refactoring

Co-authored-by: Akkadius <akkadius1@gmail.com>
2022-03-06 20:26:29 -06:00
catapultam-habeo eca2ed0321 [Feature] EQ2-style implied targeting for spells. (#2032)
* Implemented EQ2-style implied targeting for spells.

* Fixed nullptr w\ target that has no target
2022-03-06 20:25:40 -06:00
Paul Coene afc32afb02 [AI] Spell Type (1024) InCombatBuff were spam casting (#2030) 2022-03-06 20:18:30 -06:00
catapultam-habeo 751db6fffb [Feature] Allow pets to zone with permanent (buffdurationformula 50) buffs to maintain them through zone transitions (#2035) 2022-03-06 20:17:25 -06:00
Paul Coene c4eb1f8439 [Bug Fix] Bandolier didn't recognize source weapon on cursor (#2026)
* [Bug Fix] Bandolier didn't recognize source weapon on cursor

* Add TODO comment
2022-03-06 20:15:22 -06:00
Paul Coene d6c03b54a1 [Bug Fix] Fixed several instances of incorrect comparision - & executes after == (#2025) 2022-03-06 18:42:23 -06:00
neckkola 261a9e6938 [Bots] Fix bot spawn when bot id = char_id (#1984)
* Fix for GENERIC_9_STRINGS

* Update .gitignore

* Fixed query for use case when char_id of owner equals a bot_id

* Update BotDatabase::LoadGroupedBotsByGroupID to not use a view though correct edge case where botid=charid
2022-03-06 18:41:53 -06:00
catapultam-habeo ac214f71d4 [Bots] Apply Spells:IgnoreSpellDmgLvlRestriction to bots (#2024)
* Correct bot spell damage and healing pathways to account for rule Spell:IgnoreSpellDmgLvlRestriction

* Corrected to be more consistent in regard to the 'spells[spell_id].no_heal_damage_item_mod' modifier. This modifier doesn't seem to actually exist on any content, and bots didn't use it to begin with.

This restriction is present on players - do we want it on bots also?
2022-03-06 18:40:21 -06:00
KayenEQ fd878e7b16 [Bug Fix] Missing break (#2031) 2022-03-04 18:35:59 -05:00
Michael Cook (mackal) 58cde58b45 Fix order of operations issues in worldshutdown command (#2029) 2022-03-04 12:24:13 -05:00
Kinglykrab cc2ef11158 [Bug Fix] Objects::GetTiltX() and Objects::GetTiltY() Perl Croak Typos. (#2028)
- Typo was causing GetIncline() to show three times on Spire and causing GetTiltX() and GetTiltY() not to show at all on Spire.
2022-03-03 22:06:25 -05:00
Kinglykrab 2dfb7614cc [Bug Fix] Doors::GetSize() Perl Croak Typo. (#2027)
- Typo was causing GetIncline() to show twice on Spire and causing GetSize() not to show at all on Spire.
2022-03-03 21:54:02 -05:00
KayenEQ 6dffeacc6e [Spells] Fixes for numhits type 7 counter incrementing incorrectly. (#2022)
* [Spells] Fix for numhits type 7 counter incrementing incorrectly.

* [Spells] Fixes for numhits type 7 counter incrementing incorrectly.

bot fix

* [Spells] Fixes for numhits type 7 counter incrementing incorrectly.

mercs

* [Spells] Fixes for numhits type 7 counter incrementing incorrectly.

remove old variable and related code.

* [Spells] Fixes for numhits type 7 counter incrementing incorrectly.

comments
2022-03-01 21:20:27 -05:00
Michael 2ec6dcbe24 Merge pull request #2023 from EQEmu/bug_fix/lua_argument_dispatch 2022-02-28 20:22:12 -05:00
Kinglykrab 39bc12b582 [Bug Fix] Removed Lua Event Argument Dispatch.
Fix accidentally removal of argument dispatch for EVENT_CONSIDER_CORPSE in https://github.com/EQEmu/Server/pull/2015
2022-02-28 19:59:34 -05:00
Kinglykrab 6d78f926c8 [Commands] Cleanup #worldwide command. (#2021)
- Cleanup messages and logic.
- Command usages would not display when using commands improperly, this will fix that.
2022-02-28 19:46:56 -05:00
catapultam-habeo 00af2903c3 Rule to apply Spell Dmg and Heal Amount stats as a percentage instead of flat value. (#2017)
* Apply Spell Dmg and Heal Amt stats as a percentage increase (1 SD\HA = 1% increase to spell effectiveness) instead of a flat addition.

* Corrected logic to allow for coexistence of FlatItemExtraSpellAmt rule and this.

* Adjusted rule name to be less ambiguous.
2022-02-28 15:24:16 -05:00
Kinglykrab 58fafd0f9c [Bug Fix] quest::MovePCInstance() Arguments Fix. (#2020)
- Logic made the method return an "error" when not using last parameter.
2022-02-27 16:39:45 -05:00
Kinglykrab 9f0989ee2d [Bug Fix] Spell Buckets/Globals SQL Escape. (#2019) 2022-02-26 10:17:05 -05:00
KayenEQ 14648b96c4 [Spells] SPA 79 SE_CurrentHPOnce now will check for focus, critical and partial resist checks, except for buffs. (#2018)
* [Spells] SPA 79 SE_CurrentHPOnce check for focus and related effects.

SPA 79 SE_CurrentHPOnce should have the damage checks as SPA 0 for heal/damage

* Update spell_effects.cpp

* [Spells] SPA 79 SE_CurrentHPOnce now will check for focus, critical and partial resist checks.
2022-02-24 13:47:54 -05:00
Kinglykrab bfd1cf9379 [Quest API] Add EVENT_EQUIP_ITEM_CLIENT and EVENT_UNEQUIP_ITEM_CLIENT to Perl/Lua. (#2015)
- These events allow more customization beyond forcing operators to use a script file for each and every item they want to have some sort of functionality for these events.
- Perl event exports $item_id, $item_quantity, and $slot_id.
- Lua event exports item_id, item_quantity, slot_id, and item.
2022-02-22 20:04:08 -05:00
Chris Miles 3c35e9bbc8 [GM Command] Fix Crash Issue and Validation with #zclip (#2014)
* Fix crash issue and validation with zclip

* Formatting.

Co-authored-by: Kinglykrab <89047260+Kinglykrab@users.noreply.github.com>
2022-02-21 17:02:48 -05:00
Kinglykrab d86544ff60 [Bug Fix] Alleviate some lag with crosszone/worldwide spell casting. (#2016)
- Spell casting was using SpellFinished which casts the spell, and if the spell was a group spell each member of the group would cast it on all the other members, causing a chain reaction.
- This fix utilizes ApplySpellBuff(spell_id, duration) so that it only casts the spell on the target, as with the crosszone and worldwide methods you will be affecting your target based on identifiers regardless.
- This should alleviate some of the crosszone/worldwide casting crashes on larger servers such as Lazarus.
2022-02-20 21:59:46 -05:00
KayenEQ 70eed67e08 [Bug Fix] checking casting_spell_slot before its defined is bad (#2013) 2022-02-20 15:56:17 -05:00
KayenEQ 1c0524681e [API] perl added GetNPCStat(identifier) (#2012)
* [API] perl added GetNPCStat

Returns values of the modifiers from ModifyNPCStat

* https://github.com/EQEmu/Server/pull/2012
2022-02-20 14:00:28 -05:00
KayenEQ aa9320de3c [Spells] Bard songs from item clickies should not require components (#2011) 2022-02-18 09:37:09 -05:00
KayenEQ ad28f3c3f3 [Bug Fix] Fix for castspell command (#2010)
Fix for using castspell command with parameter 0
2022-02-17 20:44:11 -05:00
Kinglykrab 71dfa9acc0 [Commands] Bug fix for #logs command. (#2008)
* [Commands] Bug fix for #logs command.

* Update logs.cpp
2022-02-17 12:01:06 -05:00
KayenEQ 56d0478ab1 [API] Fix for SetBuffDuration function to check bard slots. (#2009) 2022-02-17 12:00:42 -05:00
Kinglykrab 0d02fadb60 [Quest API] Add GetRandomMob() and GetRandomNPC() to Perl/Lua. (#2006)
- Add $entity_list->GetRandomMob(x, y, z, distance, exclude_mob) to Perl.
- Add $entity_list->GetRandomNPC(x, y, z, distance, exclude_npc) to Perl.
- Add eq.get_entity_list():GetRandomMob(x, y, z, distance, exclude_mob) to Lua.
- Add eq.get_entity_list():GetRandomNPC(x, y, z, distance, exclude_npc) to Lua.
2022-02-17 08:57:02 -05:00
cybernine186 4de5a7b86d [Bug] Fixed trade items record log (#2003)
LogPlayerHandin was not recording the item details of the trade. It should be inserting the trade details into `qs_player_handin_record_entries` but it was not running the query because of missing QueryDatabase function.
2022-02-16 21:52:14 -06:00
KayenEQ ba3c19ad0b [Spells] AE Duration effect (Rains) will now work with Target Ring and PBAE spells. (#2000)
* done

* Update beacon.cpp

* [Spells] AE Duration effect (Rains) will now work with Target Ring and PBAE spells.

Mackals suggestions implemented.
2022-02-16 10:12:13 -05:00
Kinglykrab 8ec80644ee [Commands] Cleanup #unscribespell Command. (#1998)
* [Commands] Cleanup #unscribespell Command.
- Cleanup messages and logic.
- Add Client::UnscribeSpellBySpellID(spell_id, update_client).
- Add $client->UnscribeSpellBySpellID(spell_id, update_client) to Perl.
- Add client:UnscribeSpellBySpellID(spell_id, update_client) to Lua.

* Update unscribespell.cpp
2022-02-16 06:04:01 -05:00
Kinglykrab ed7e2b2652 [Commands] Cleanup #untraindisc Command. (#1996)
- Cleanup messages and logic.
2022-02-16 06:03:51 -05:00
KayenEQ a83ad7080a fix for meloday cast bar issue (#2005) 2022-02-15 14:01:01 -05:00
KayenEQ 677d595c9d invis updates (#2004) 2022-02-15 11:39:19 -05:00
KayenEQ 615f4a5304 [API] Apply spells with custom buff durations and adjust existing spell buff durations. (#1997)
* working

* Update spell_effects.cpp

* updates

* disable_buff_overwrite

* revert

* update

* working

* update

* updates

* Update spells.cpp

* getbuffstat done

* Update perl_mob.cpp

* [API] Apply spells with custom buff durations and adjust existing spell buff durations.

* [API] Apply spells with custom buff durations and adjust existing spell buff durations.

* [API] Apply spells with custom buff durations and adjust existing spell buff durations.

* [API] Apply spells with custom buff durations and adjust existing spell buff durations.

* https://github.com/EQEmu/Server/pull/1997

Lua added, thanks kinglykrab
2022-02-15 08:58:10 -05:00
KayenEQ 5fd62d82db Update bonuses.cpp (#2002) 2022-02-15 08:57:53 -05:00
KayenEQ b938e6223c [Spells] Invisibility updates and rework (#1991)
* updates pre merge

* update

* Update spell_effects.cpp

* Update mob.h

* test

* test

* updates

* updates

* save

* update

* working solid

* animal and undead start

* progress

* updates

* rename

* set invis appearance on bonus

* remove fade buff state check

* update IsViisble check

* optimizing

* don't break bots

* debug remover

* Update ruletypes.h

* perl adds

* Update client_packet.cpp

* update

* done

* remove debugs

* Update client_packet.cpp

* update

* [Spells] Invisibility updates and rework

lua support

* [Spells] Invisibility updates and rework

lua
2022-02-15 00:18:02 -05:00
KayenEQ 51c8771bd2 bug fix (#2001) 2022-02-15 00:17:23 -05:00
Kinglykrab cc9196bd65 [Commands] Cleanup #showskills Command. (#1994)
* [Commands] Cleanup #showskills Command.
- Utilize popup over messages.
- Usage: #showskills [Start Skill ID] [All] - shows skills starting from skill ID and if "all" is specified it will show skills the player does not have normally (no max/cannot have skill).

* Update showskills.cpp

* Update command.cpp
2022-02-14 19:49:14 -05:00
Kinglykrab 6303f129af [Commands] Cleanup #setskillall Command. (#1992)
- Cleanup messages and logic.
2022-02-14 19:02:27 -05:00
KayenEQ 3f0987ba55 [Combat] /shield command "too far away message" (#1999)
* live did something that makes sense

* [Combat] /shield command "too far away message

better chat

* [Combat] /shield command "too far away message

never mind that one was red.
2022-02-14 10:44:26 -05:00
KayenEQ 1d4438ae1f [Bug Fix] Edge case AA reset timer issue fixes (#1995)
* SendCastRestriction not displaying right on linux build

changed const char to string

* fail safe to prevent recast timer checks from triggered spells

* fixed

* Update spell_effects.cpp

* https://github.com/EQEmu/Server/pull/1995

better message code
2022-02-13 21:50:53 -05:00
KayenEQ 03adf20fe9 bot crash fix (#1993) 2022-02-13 12:09:32 -05:00
KimLS dd6cde68bb Small change to order of a couple of files in zone cmakefile, added the gm commands to their own source group so they are cleanly separated in any IDEs cmake supports 2022-02-12 23:31:51 -08:00
KimLS 95c8b60ec6 Extra extern c warning squash, XS macro expands to XS_EXTERNAL which under c++ expands to extern c 2022-02-12 22:04:30 -08:00
KimLS fa418172d6 What is this random semicoloned if, removed to silence warning 2022-02-12 22:04:30 -08:00
KimLS 7b106fc622 Handle default case of GetDynamicZoneTypeName to silence warning 2022-02-12 22:04:30 -08:00
KimLS 62a453f0d7 Remove obsolete register spec on int to silence warning 2022-02-12 22:04:30 -08:00
KayenEQ fa9314811e [Bug Fix] Fix for Bot command casting (#1990)
* missing return true in ApplyBardPulse

* Update bot.cpp

* [Bug Fix] Fix for Bot command casting

compile error

* [Bug Fix] Fix for Bot command casting

* Update bot.cpp
2022-02-12 15:12:35 -05:00
Kinglykrab d2d7b8108d [Commands] Cleanup #ai Command. (#1980)
- Cleanup messages and logic.
- Remove #ai start/#ai stop as they can crash zones and are mostly useless.
- Add EQ::constants::GetConsiderLevelMap() and EQ::constants::GetConsiderLevelName().
- Add quest::getconsiderlevelname(consider_level) to Perl.
- Add eq.get_consider_level_name(consider_level) to Lua.
2022-02-11 16:26:08 -05:00
KayenEQ 99793cab8b [Spells] Fix for AA recast timers not resetting properly (#1989)
* revert completed

Too many issues popping up that are difficult to track down. This was probably not best way to solve the problem.

* fixed for real

* Update aa.cpp

* Update aa.cpp

* Update aa.cpp

* should work

* remove spaces

* [Spells] Fix for AA recast timers not resetting properly
2022-02-11 16:25:59 -05:00
KayenEQ e2484997dd revert completed (#1988)
Too many issues popping up that are difficult to track down. This was probably not best way to solve the problem.
2022-02-11 10:58:43 -05:00
KimLS 66935fe21b Fix for passing std::string to vsprintf 2022-02-11 01:15:02 -08:00
KayenEQ db988e4261 group message (#1987) 2022-02-10 23:55:59 -05:00
Kinglykrab fdd260d5fa [Commands] Cleanup #npcloot Command. (#1974)
- Cleanup messages and logic.
- Utilize item links where helpful.
- Implement #npcloot remove all to remove all loot from an NPC using GetLootList().
- #npcloot money now supports 0 to 65,535 for the money types, clamped using EQ::Clamp.
2022-02-10 20:05:36 -05:00
Kinglykrab 9110bc863e [Commands] Cleanup #logs Command. (#1969)
- Cleanup messages and logic.
- Utilize popup for list and applying settings.
2022-02-10 16:52:15 -05:00
Kinglykrab 4a41583805 [Commands] Cleanup #flagedit Command. (#1968)
- Cleanup and fix messages and logic.
- Utilized popup for listing zones that have required flags.
2022-02-10 16:17:52 -05:00
Kinglykrab 5396c0c88b [Commands] Cleanup #name Command. (#1977)
- Cleanup messages and logic.
2022-02-10 16:14:40 -05:00
Kinglykrab 968ae26c99 [Commands] Cleanup #hatelist Command. (#1976)
- Cleanup messages and logic.
2022-02-10 16:14:17 -05:00
Kinglykrab 7bf466cf3f [Commands] Cleanup #netstats Command. (#1970)
- Utilize popup over chat messages.
2022-02-10 16:10:31 -05:00
Kinglykrab 49d7eb1402 [Commands] Cleanup #version Command. (#1967)
- Utilize popup over chat message.
2022-02-10 16:10:23 -05:00
Kinglykrab d83ced6f76 [Commands] Cleanup #undye and #undyeme Commands. (#1966)
- Fix #undye command as its method was not being used in command.cpp.
- Cleanup messages and logic for both #undye and #undyeme.
2022-02-10 16:10:16 -05:00
Kinglykrab 1ea8888607 [Commands] Cleanup #timers Command. (#1965)
- Cleanup message and logic.
- Utilize popup instead of chat messages.
- Utilize ConvertSecondsToTime() helper method.
2022-02-10 16:10:06 -05:00
Kinglykrab f9eb4603a3 [Quest API] Add GetEnvironmentalDamageName() to Perl/Lua. (#1964)
- Add EQ::constants::GetEnvironmentalDamageMap() and EQ::constants::GetEnvironmentalDamageName().
- Add quest::getenvironmentaldamagename(damage_type) to Perl.
- Add eq.get_environmental_damage_name(damage_type) to Lua.
- Cleanup GM messages for avoiding environmental damage.
2022-02-10 16:09:56 -05:00
KayenEQ d656be6be4 [Bug Fix] Fix for PR1954 target restriction with npcpc_only_flag from groupbuffs (#1986)
* Update spells.cpp

* Update spells.cpp

* [Bug Fix] Fix for PR1954 target restriction with npcpc_only_flag from groupbuffs

disc failure log

* [Bug Fix] Fix for PR1954 target restriction with npcpc_only_flag from groupbuffs

improved HasItemRecastTimer check
2022-02-10 14:58:28 -05:00
KayenEQ fbbbd3b09d [Bug Fix] PR 1982 (#1985)
* Update spells.cpp

* [Bug Fix] PR 1982
2022-02-09 23:24:18 -05:00
KayenEQ a6d1652f44 fixed (#1983) 2022-02-09 18:02:45 -05:00
KayenEQ f0bf285836 [Spells] Support for SPA 194 SE_FadingMemories to use max level checks on aggroed mobs (#1979)
* escape fix for different target types

* implemented max level for fade

* test

* update

* update

* support modern limits

* Update ruletypes.h

* update

* [Spells] Support for SPA 194 SE_FadingMemories to use max level checks on aggroed mobs

not sure why this code got removed, maybe merge error.
2022-02-09 15:12:39 -05:00
KayenEQ 1f560529da [Bug Fix] Bard update fixes 1 (#1982)
* fix for bard item charge consumables

* [Bug Fix] Bards not consuming item click charges on instant cast items.

* [Bug Fix] Bard update fixes 1

bards not respecting deity/race/class restrictions on instant cast items
2022-02-09 15:07:38 -05:00
Kinglykrab f65a6d2761 [Quest API] Add AddAISpellEffect(spell_effect_id, base_value, limit_value, max_value) and RemoveAISpellEffect(spell_effect_id) to Lua. (#1981)
- Add npc:AddAISpellEffect(spell_effect_id, base_value, limit_value, max_value) to Lua.
- Add npc:RemoveAISpellEffect(spell_effect_id) to Lua.
2022-02-08 20:46:59 -05:00
KayenEQ 79f250da2d [API] Perl functions added to apply spell effects directly to NPCs without requiring buffs. (#1975)
* script functions working

* Update perl_npc.cpp

* [API] Perl functions added to apply spell effects directly to NPCs without requiring buffs.
2022-02-08 18:32:13 -05:00
KayenEQ 752e6c89f3 [Spells] Allow damage spells to heal if quest based spell mitigation is over 100 pct. (#1978)
* heal from nuke

* Update mob.cpp
2022-02-08 09:03:31 -05:00
KayenEQ e962ad3a35 procs silence (#1973) 2022-02-08 07:36:20 -05:00
KayenEQ 872d494bb6 [Bug Fix] Summon Companion causing pets to warps away. (#1972)
* Update spell_effects.cpp

* Update spell_effects.cpp
2022-02-08 07:36:04 -05:00
KayenEQ 8a48473dbc [Spells] Fix for AA and Discipline recast timers being set on spell casting failure. (#1971)
* recast timer updates

* reworked

* removed unneeded param

* fix expendible AA

* fixed

* Update spells.cpp

* [Spells] Fix for AA and Discipline recast timers being set on spell casting failure.

don't check recasts from triggered spells.
2022-02-08 07:35:47 -05:00
KayenEQ a208801d1f [Spells] Major update to Bard song pulsing, Bard item clicks while singing, and spell casting restriction logic. (#1954)
* test

* complete

* Update effects.cpp

* Update spells.cpp

* Update effects.cpp

* [Spells] Support for bards using Disciplines while casting or /melody.

Support for spell field 'cast not standing' not allow casting from divine aura

* [Spells] Support for bards using Disciplines while casting or /melody.

DA bypass logic for spells with field 'cast_not_standing'

* updates

* stun and mez bypass

* Update spdat.cpp

* Update spdat.cpp

* Update spells.cpp

* clean

* requirement messages

* update

* pct

* save work

* Reform code 1_22_22

* updated

* update id to pointer

* Update spells.cpp

* rework 2

* update 1_23_22

* Update spells.cpp

* updates

* msg string works

* fix disc timers not be set

* more optimization

* update 1_23_22 PM

moved stop casting out
charm and harmony moved in

* update 1_25_22

rework of functions

* updates 1_26_22

* remove old checks

* gm override added for some

* update bard AA casting checks

* updates

* addbuff exception for bard

* debugs

* charm working

* update

* moved skill check here

* cast from item while singing

* lets not attack mounts

* instant cast items click

* aug clicks working

* aug tests

Bug? Cast time not display on aug clicks for bards

* aug recast from items semi ok

* added item timer function

* unified setting item recast timer

* clean up time

* update

* bard AA cast updates

* debugs removed

* debugs removed

* clean up

* clean up

* better placement of bindsight and numhits fix

* move and rename function

* Update spells.cpp

* add logs

* delete old DoCastingChecks

* Removed old bard pulse functions

* remove AEBardPulse and GroupPulse

* removed Raid::GroupBardPulse

* Pulse Restriction: Divine Aura

* Pulse Restrictions : Fear behavior

* Update spells.cpp

* Update spells.cpp

* [Spells] Major update to Bard song pulsing, Bard item clicks while singing, and spell casting restriction logic.

bots...

* [Spells] Major update to Bard song pulsing, Bard item clicks while singing, and spell casting restriction logic.

added recommended isvalidspell check

* [Spells] Major update to Bard song pulsing, Bard item clicks while singing, and spell casting restriction logic.

merged

* [Spells] Major update to Bard song pulsing, Bard item clicks while singing, and spell casting restriction logic.

removed defines since we have them as constants
2022-02-07 07:48:52 -05:00
1261 changed files with 154478 additions and 125628 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}"
}
}
+88 -6
View File
@@ -1,16 +1,98 @@
---
kind: pipeline
type: docker
name: EQEmulator Server Linux CI
name: Build Linux
# Limits how many of these builds can run on the drone runner at a time, this isn't about cores
concurrency:
limit: 1
volumes:
- name: cache
host:
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
- git submodule init && git submodule update && mkdir -p build && cd build && cmake -DEQEMU_BUILD_LOGIN=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LUA=ON -G 'Unix Makefiles' .. && make -j$((`nproc`-4))
- ./utils/scripts/build/linux-build.sh
volumes:
- name: cache
path: /home/eqemu/.ccache/
---
kind: pipeline
type: exec
name: Build Windows
# Limits how many of these builds can run on the drone runner at a time, this isn't about cores
concurrency:
limit: 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"
trigger:
branch:
- master
event:
- push
depends_on:
- Build Windows
- Build Linux
+15
View File
@@ -56,3 +56,18 @@ 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
# CMake Files
cmake-build-relwithdebinfo/*
-19
View File
@@ -1,19 +0,0 @@
language: cpp
compiler: gcc
dist: bionic
addons:
apt:
packages:
- libmysqlclient-dev
- libperl-dev
- libboost-dev
- liblua5.1-0-dev
- zlib1g-dev
- uuid-dev
- libssl-dev
script:
- cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LOGIN=ON
- make -j2
- ./bin/tests
-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
+669
View File
@@ -0,0 +1,669 @@
## [22.2.0] - 01/27/2023
### Bots
* Add EVENT_UNEQUIP_ITEM_BOT & EVENT_EQUIP_ITEM_BOT ([#2796](https://github.com/EQEmu/Server/pull/2796)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-27
* ^create and ^viewcombos popup messages fix. ([#2797](https://github.com/EQEmu/Server/pull/2797)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-26
### Code Cleanup
* Cleanup #door Command. ([#2783](https://github.com/EQEmu/Server/pull/2783)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-24
### Crash
* Fix crash issue with log formatting during character creation ([#2798](https://github.com/EQEmu/Server/pull/2798)) ([Akkadius](https://github.com/Akkadius)) 2023-01-27
### Feature
* ResetItemCooldown added to lua/perl and fix item re-cast times to show properly ([#2793](https://github.com/EQEmu/Server/pull/2793)) ([Natedog2012](https://github.com/Natedog2012)) 2023-01-26
### Git
* Add CMake Files to .gitignore ([#2792](https://github.com/EQEmu/Server/pull/2792)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-25
## [22.1.2] - 01/24/2023
### CI/CD
* Build / Release Pipeline Changes ([#2788](https://github.com/EQEmu/Server/pull/2788)) ([Akkadius](https://github.com/Akkadius)) 2023-01-24
### Code Cleanup
* Cleanup #door Command. ([#2783](https://github.com/EQEmu/Server/pull/2783)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-24
### Crash
* Fix rarer world crash issue where scheduler database was not available ([#2789](https://github.com/EQEmu/Server/pull/2789)) ([Akkadius](https://github.com/Akkadius)) 2023-01-24
### Fixes
* Fix nullptr spell in BCSpells::Load() ([#2790](https://github.com/EQEmu/Server/pull/2790)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-24
* Remove duplicate logic in GetActSpellHealing reducing HOT criticals ([#2786](https://github.com/EQEmu/Server/pull/2786)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-24
## [22.1.1] - 01/23/2023
### Fixes
* Fix botgrouplist to display unique entries. ([#2785](https://github.com/EQEmu/Server/pull/2785)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-23
* Fix scenario where dereferenced object could be null. ([#2784](https://github.com/EQEmu/Server/pull/2784)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-23
## [22.1.0] - 01/22/2023
This is a first release using the new build system. Changelog entry representative of last year. Subsequent releases will consist of incremental changes since the last release.
### AA
* Fix AA tables dump ([#2769](https://github.com/EQEmu/Server/pull/2769)) ([Akkadius](https://github.com/Akkadius)) 2023-01-22
### Appveyor
* Remove bots preprocessor ([Akkadius](https://github.com/Akkadius)) 2023-01-20
### Bot/Merc
* Cleanup methods, and virtual overrides. ([#2734](https://github.com/EQEmu/Server/pull/2734)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-15
### Bots
* Add Bot Command Reloading ([#2773](https://github.com/EQEmu/Server/pull/2773)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22
* Add Bot-specific Spell Settings. ([#2553](https://github.com/EQEmu/Server/pull/2553)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27
* Add Buff support for Bards under AI_IdleCastChecks ([#2590](https://github.com/EQEmu/Server/pull/2590)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-28
* Add Data Bucket support to Bot Spell Entries. ([#2505](https://github.com/EQEmu/Server/pull/2505)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-06
* Add EVENT_TRADE Support to Bots. ([#2560](https://github.com/EQEmu/Server/pull/2560)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-25
* Add Event_Trade Support for ^inventorygive Command ([#2628](https://github.com/EQEmu/Server/pull/2628)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-11
* Add Expansion Bitmask Quest APIs. ([#2523](https://github.com/EQEmu/Server/pull/2523)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16
* Add GetBotOwnerByBotID Method ([#2715](https://github.com/EQEmu/Server/pull/2715)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-11
* Add Melee Support for Casting, Cleanup Bot Casting Logic ([#2571](https://github.com/EQEmu/Server/pull/2571)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-25
* Add Quest API Methods ([#2631](https://github.com/EQEmu/Server/pull/2631)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-12
* Add Quest API Support for Limits. ([#2522](https://github.com/EQEmu/Server/pull/2522)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-17
* Add Rule Allowing Bots to Equip Any Race Items ([#2578](https://github.com/EQEmu/Server/pull/2578)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-26
* Add Support for AA bonuses that were missing. ([#2764](https://github.com/EQEmu/Server/pull/2764)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-20
* Add Support for Bots to receive Auras, and other AoE Buffs. ([#2586](https://github.com/EQEmu/Server/pull/2586)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-27
* Add Virtual Override for Bot::Attack ([#2771](https://github.com/EQEmu/Server/pull/2771)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-20
* Add give/remove saylinks to ^itemuse. ([#2503](https://github.com/EQEmu/Server/pull/2503)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-30
* Add support for Bot scripting. ([#2515](https://github.com/EQEmu/Server/pull/2515)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-17
* Apply Spells:IgnoreSpellDmgLvlRestriction to bots ([#2024](https://github.com/EQEmu/Server/pull/2024)) ([catapultam-habeo](https://github.com/catapultam-habeo)) 2022-03-07
* Bot::PerformTradeWithClient Cleanup. ([#2084](https://github.com/EQEmu/Server/pull/2084)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-01
* Cleanup Bot Spell Functions, reduce reliance on NPC Functions/Attributes ([#2495](https://github.com/EQEmu/Server/pull/2495)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-29
* Cleanup Fast Rest Regen ([#2626](https://github.com/EQEmu/Server/pull/2626)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-07
* Cleanup Say Event Parse. ([#2557](https://github.com/EQEmu/Server/pull/2557)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-20
* Cleanup Spell Settings Commands ([#2607](https://github.com/EQEmu/Server/pull/2607)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-04
* Cleanup ^inventoryremove, ^inventorylist, and ^list Commands and bot groups. ([#2273](https://github.com/EQEmu/Server/pull/2273)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-03
* Cleanup and remove preprocessors. ([#2757](https://github.com/EQEmu/Server/pull/2757)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-20
* Cleanup various Bot Spell Focus methods ([#2649](https://github.com/EQEmu/Server/pull/2649)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-16
* Convert Load, Save, SaveNew, and Delete to Repositories. ([#2614](https://github.com/EQEmu/Server/pull/2614)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-04
* Expanded Bot Spell Settings List. ([#2606](https://github.com/EQEmu/Server/pull/2606)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-03
* Fix Bot Spell Type "In Combat Buffs" ([#2711](https://github.com/EQEmu/Server/pull/2711)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-08
* Fix Gender not saving as GetBaseGender on BotSave ([#2639](https://github.com/EQEmu/Server/pull/2639)) ([nytmyr](https://github.com/nytmyr)) 2022-12-13
* Fix Slow Query in QueryNameAvailablity ([#2781](https://github.com/EQEmu/Server/pull/2781)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-22
* Fix ^dyearmor command math. ([#2081](https://github.com/EQEmu/Server/pull/2081)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-30
* Fix bot spawn when bot id = char_id ([#1984](https://github.com/EQEmu/Server/pull/1984)) ([neckkola](https://github.com/neckkola)) 2022-03-07
* Hotfix for possible crash. ([#2539](https://github.com/EQEmu/Server/pull/2539)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Melee Bot Support for Spell Settings Commands ([#2599](https://github.com/EQEmu/Server/pull/2599)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-01
* Move Bot Spell Loading process to constructor from calcbotstats() ([#2583](https://github.com/EQEmu/Server/pull/2583)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-27
* Optimize inventory loading. ([#2588](https://github.com/EQEmu/Server/pull/2588)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-28
* Post pre-processor fixes ([#2770](https://github.com/EQEmu/Server/pull/2770)) ([Akkadius](https://github.com/Akkadius)) 2023-01-20
* Resolve incorrect values on Bot Creation ([#2644](https://github.com/EQEmu/Server/pull/2644)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-14
* Restrict Bot Groups from spawning while Feigned. ([#2761](https://github.com/EQEmu/Server/pull/2761)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-19
* Save Bot Toggle Archer Setting between Loads. ([#2612](https://github.com/EQEmu/Server/pull/2612)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-04
* Update Bot Heal & Damage methods to more closely match Clients + Bugfixes ([#2045](https://github.com/EQEmu/Server/pull/2045)) ([catapultam-habeo](https://github.com/catapultam-habeo)) 2022-03-11
* Update Bot Logic to ignore ST_TargetsTarget when buffing ([#2584](https://github.com/EQEmu/Server/pull/2584)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-27
### C++20
* Arithmetic on different enums is deprecated ([#2752](https://github.com/EQEmu/Server/pull/2752)) ([mackal](https://github.com/mackal)) 2023-01-17
* Enable C++20 + Fixes + FMT 9.1 ([#2664](https://github.com/EQEmu/Server/pull/2664)) ([Akkadius](https://github.com/Akkadius)) 2022-12-21
### Code
* Removed vscode setting ([#2753](https://github.com/EQEmu/Server/pull/2753)) ([xackery](https://github.com/xackery)) 2023-01-17
### Code Cleanup
* Add Validation to varchar number item fields. ([#2241](https://github.com/EQEmu/Server/pull/2241)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-04
* Cleanup #kick message. ([#2164](https://github.com/EQEmu/Server/pull/2164)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-10
* Cleanup Haste references and Lua API calls for unsigned to signed. ([#2240](https://github.com/EQEmu/Server/pull/2240)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-04
* Cleanup code smells and compiler warnings in common/shareddb ([#2270](https://github.com/EQEmu/Server/pull/2270)) ([Quintinon](https://github.com/Quintinon)) 2022-07-03
* Cleanup magic numbers ([#2662](https://github.com/EQEmu/Server/pull/2662)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-20
* Cleanup spell and max level bucket logic. ([#2181](https://github.com/EQEmu/Server/pull/2181)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-28
* Extra Space in NPC::AISpellsList(). ([#2555](https://github.com/EQEmu/Server/pull/2555)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-20
* Fix unintended copies in zone/zonedb.cpp by changing auto to auto& ([#2271](https://github.com/EQEmu/Server/pull/2271)) ([Quintinon](https://github.com/Quintinon)) 2022-07-03
* Make use of std::abs where possible. ([#2739](https://github.com/EQEmu/Server/pull/2739)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-15
* Merge Client::Attack and Bot::Attack into Mob::Attack ([#2756](https://github.com/EQEmu/Server/pull/2756)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-20
* Move Client::Undye() to client.cpp from #path Command. ([#2188](https://github.com/EQEmu/Server/pull/2188)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-21
* Possible issues with variable/parameter name equality. ([#2161](https://github.com/EQEmu/Server/pull/2161)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-10
* Quest API push methods using invalid types. ([#2172](https://github.com/EQEmu/Server/pull/2172)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-16
* Remove Unused EQEMU_DEPOP_INVALIDATES_CACHE ([#2292](https://github.com/EQEmu/Server/pull/2292)) ([Akkadius](https://github.com/Akkadius)) 2022-07-14
* Remove this-> in code where its implied ([#2088](https://github.com/EQEmu/Server/pull/2088)) ([Akkadius](https://github.com/Akkadius)) 2022-05-01
* Remove unused basic_functions.h ([#2729](https://github.com/EQEmu/Server/pull/2729)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-13
* Remove unused maxskill.h. ([#2728](https://github.com/EQEmu/Server/pull/2728)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-13
* Remove unused methods. ([#2171](https://github.com/EQEmu/Server/pull/2171)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-15
* Remove unusued Max Item ID Constant ([#2528](https://github.com/EQEmu/Server/pull/2528)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-08
* Remove use of bzero since it is deprecated for memset ([#2295](https://github.com/EQEmu/Server/pull/2295)) ([Akkadius](https://github.com/Akkadius)) 2022-07-14
* Resharper Warnings ([#2235](https://github.com/EQEmu/Server/pull/2235)) ([Quintinon](https://github.com/Quintinon)) 2022-06-01
* Resolve some warnings in loginserver/world_server.cpp ([#2347](https://github.com/EQEmu/Server/pull/2347)) ([mackal](https://github.com/mackal)) 2022-07-31
* Rework Lua QuestReward to not use try/catch blocks ([#2417](https://github.com/EQEmu/Server/pull/2417)) ([mackal](https://github.com/mackal)) 2022-09-03
* Send eqstr message in AddAAPoints ([#2507](https://github.com/EQEmu/Server/pull/2507)) ([hgtw](https://github.com/hgtw)) 2022-10-29
* Update to EQEmu #2253 to clean up message strings ([#2279](https://github.com/EQEmu/Server/pull/2279)) ([fryguy503](https://github.com/fryguy503)) 2022-07-03
* Zone Data Loading Refactor ([#2388](https://github.com/EQEmu/Server/pull/2388)) ([Akkadius](https://github.com/Akkadius)) 2022-09-01
### Commands
* #bind Typo. ([#2196](https://github.com/EQEmu/Server/pull/2196)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23
* #ginfo Cleanup. ([#1955](https://github.com/EQEmu/Server/pull/1955)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-03
* #reload Command Overhaul. ([#2162](https://github.com/EQEmu/Server/pull/2162)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-10
* #reload level_mods could cause Non-Booted zones to crash. ([#2670](https://github.com/EQEmu/Server/pull/2670)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-24
* Add #bugs Command. ([#2559](https://github.com/EQEmu/Server/pull/2559)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Add #feature Command. ([#2142](https://github.com/EQEmu/Server/pull/2142)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Add #findcharacter Command. ([#2692](https://github.com/EQEmu/Server/pull/2692)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-03
* Add #findrecipe and #viewrecipe Commands. ([#2401](https://github.com/EQEmu/Server/pull/2401)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-31
* Add #setanon Command ([#2690](https://github.com/EQEmu/Server/pull/2690)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-03
* Add #suspendmulti Command. ([#2619](https://github.com/EQEmu/Server/pull/2619)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-11
* Add BestZ and Region Data to #loc ([#2245](https://github.com/EQEmu/Server/pull/2245)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-05
* Add additional #peqzone functionality. ([#2085](https://github.com/EQEmu/Server/pull/2085)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-01
* Add max_hp back to #modifynpcstat command. ([#2638](https://github.com/EQEmu/Server/pull/2638)) ([nytmyr](https://github.com/nytmyr)) 2022-12-13
* Adding movespeed to #showstats output ([#2596](https://github.com/EQEmu/Server/pull/2596)) ([fryguy503](https://github.com/fryguy503)) 2022-11-30
* Bug fix for #logs command. ([#2008](https://github.com/EQEmu/Server/pull/2008)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-17
* Cleanup #ai Command. ([#1980](https://github.com/EQEmu/Server/pull/1980)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-11
* Cleanup #appearanceeffects Command. ([#2777](https://github.com/EQEmu/Server/pull/2777)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22
* Cleanup #attack Command. ([#2103](https://github.com/EQEmu/Server/pull/2103)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-04
* Cleanup #ban, #ipban, #flag, #kick, #setlsinfo, and #setpass Commands. ([#2104](https://github.com/EQEmu/Server/pull/2104)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-08
* Cleanup #chat Command. ([#2581](https://github.com/EQEmu/Server/pull/2581)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27
* Cleanup #corpsefix Command. ([#2197](https://github.com/EQEmu/Server/pull/2197)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27
* Cleanup #cvs Command. ([#2153](https://github.com/EQEmu/Server/pull/2153)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-08
* Cleanup #date Command. ([#2228](https://github.com/EQEmu/Server/pull/2228)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-01
* Cleanup #dbspawn2 Command. ([#2493](https://github.com/EQEmu/Server/pull/2493)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-30
* Cleanup #delacct Command. ([#2567](https://github.com/EQEmu/Server/pull/2567)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Cleanup #depop Command. ([#2536](https://github.com/EQEmu/Server/pull/2536)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Cleanup #depopzone Command. ([#2537](https://github.com/EQEmu/Server/pull/2537)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Cleanup #devtools Command. ([#2538](https://github.com/EQEmu/Server/pull/2538)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Cleanup #doanim Command. ([#2540](https://github.com/EQEmu/Server/pull/2540)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Cleanup #emote Command. ([#2535](https://github.com/EQEmu/Server/pull/2535)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Cleanup #emotesearch and #emoteview Command. ([#2494](https://github.com/EQEmu/Server/pull/2494)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-30
* Cleanup #emptyinventory Command. ([#2219](https://github.com/EQEmu/Server/pull/2219)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-29
* Cleanup #findaliases and #help Commands. ([#2204](https://github.com/EQEmu/Server/pull/2204)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27
* Cleanup #findclass and #findrace Commands. ([#2211](https://github.com/EQEmu/Server/pull/2211)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27
* Cleanup #flagedit Command. ([#1968](https://github.com/EQEmu/Server/pull/1968)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10
* Cleanup #freeze and #unfreeze Commands. ([#2102](https://github.com/EQEmu/Server/pull/2102)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-04
* Cleanup #gassign Command. ([#2101](https://github.com/EQEmu/Server/pull/2101)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #gearup Command. ([#2589](https://github.com/EQEmu/Server/pull/2589)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27
* Cleanup #getvariable Command. ([#2100](https://github.com/EQEmu/Server/pull/2100)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-04
* Cleanup #guild Command ([#2693](https://github.com/EQEmu/Server/pull/2693)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-04
* Cleanup #hatelist Command. ([#1976](https://github.com/EQEmu/Server/pull/1976)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10
* Cleanup #heromodel Command. ([#2566](https://github.com/EQEmu/Server/pull/2566)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Cleanup #kill Command. ([#2195](https://github.com/EQEmu/Server/pull/2195)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23
* Cleanup #level Command. ([#2203](https://github.com/EQEmu/Server/pull/2203)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27
* Cleanup #logs Command. ([#1969](https://github.com/EQEmu/Server/pull/1969)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10
* Cleanup #makepet Command. ([#2105](https://github.com/EQEmu/Server/pull/2105)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #modifynpcstat Command. ([#2499](https://github.com/EQEmu/Server/pull/2499)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-30
* Cleanup #motd Command. ([#2190](https://github.com/EQEmu/Server/pull/2190)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23
* Cleanup #name Command. ([#1977](https://github.com/EQEmu/Server/pull/1977)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10
* Cleanup #netstats Command. ([#1970](https://github.com/EQEmu/Server/pull/1970)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10
* Cleanup #npcedit Command. ([#2582](https://github.com/EQEmu/Server/pull/2582)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27
* Cleanup #npcedit, #lastname, #title, and #titlesuffix Commands. ([#2215](https://github.com/EQEmu/Server/pull/2215)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-28
* Cleanup #npceditmass command. ([#1957](https://github.com/EQEmu/Server/pull/1957)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-03
* Cleanup #npcemote Command. ([#2106](https://github.com/EQEmu/Server/pull/2106)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #npcloot Command. ([#1974](https://github.com/EQEmu/Server/pull/1974)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-11
* Cleanup #npcsay and #npcshout Commands. ([#2107](https://github.com/EQEmu/Server/pull/2107)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #npcspecialattk Command. ([#2108](https://github.com/EQEmu/Server/pull/2108)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #npctype_cache Command. ([#2109](https://github.com/EQEmu/Server/pull/2109)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #npctypespawn Command. ([#2110](https://github.com/EQEmu/Server/pull/2110)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #nudge Command. ([#2220](https://github.com/EQEmu/Server/pull/2220)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-29
* Cleanup #oocmute Command. ([#2191](https://github.com/EQEmu/Server/pull/2191)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27
* Cleanup #opcode Command. ([#2547](https://github.com/EQEmu/Server/pull/2547)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16
* Cleanup #profanity Command. ([#2113](https://github.com/EQEmu/Server/pull/2113)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #push Command. ([#2114](https://github.com/EQEmu/Server/pull/2114)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #qglobal Command. ([#2115](https://github.com/EQEmu/Server/pull/2115)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #randomizefeatures Command. ([#2118](https://github.com/EQEmu/Server/pull/2118)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #refreshgroup Command. ([#2119](https://github.com/EQEmu/Server/pull/2119)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadaa Command. ([#2120](https://github.com/EQEmu/Server/pull/2120)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadallrules Command. ([#2121](https://github.com/EQEmu/Server/pull/2121)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadlevelmods Command. ([#2122](https://github.com/EQEmu/Server/pull/2122)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadmerchants Command. ([#2123](https://github.com/EQEmu/Server/pull/2123)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadperlexportsettings Command. ([#2124](https://github.com/EQEmu/Server/pull/2124)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadrulesworld Command. ([#2128](https://github.com/EQEmu/Server/pull/2128)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadstatic Command. ([#2130](https://github.com/EQEmu/Server/pull/2130)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadtitles Command. ([#2125](https://github.com/EQEmu/Server/pull/2125)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadtraps Command. ([#2126](https://github.com/EQEmu/Server/pull/2126)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadworld and #repop Command. ([#2127](https://github.com/EQEmu/Server/pull/2127)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadzps Command. ([#2129](https://github.com/EQEmu/Server/pull/2129)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #resetaa Command. ([#2132](https://github.com/EQEmu/Server/pull/2132)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #resetaa_timer Command. ([#2131](https://github.com/EQEmu/Server/pull/2131)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #resetdisc_timer Command. ([#2133](https://github.com/EQEmu/Server/pull/2133)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #revoke Command. ([#2134](https://github.com/EQEmu/Server/pull/2134)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #roambox Command. ([#2135](https://github.com/EQEmu/Server/pull/2135)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #rules Command. ([#2593](https://github.com/EQEmu/Server/pull/2593)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-10
* Cleanup #save Command. ([#2136](https://github.com/EQEmu/Server/pull/2136)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #scale Command. ([#2591](https://github.com/EQEmu/Server/pull/2591)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-05
* Cleanup #scribespell and #scribespells Commands. ([#2534](https://github.com/EQEmu/Server/pull/2534)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Cleanup #sensetrap Command. ([#2137](https://github.com/EQEmu/Server/pull/2137)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #serverinfo Command. ([#2568](https://github.com/EQEmu/Server/pull/2568)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Cleanup #serverrules Command. ([#2139](https://github.com/EQEmu/Server/pull/2139)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #setlanguage Command. ([#2464](https://github.com/EQEmu/Server/pull/2464)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-13
* Cleanup #setskillall Command. ([#1992](https://github.com/EQEmu/Server/pull/1992)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-15
* Cleanup #shownpcgloballoot and #showzonegloballoot Command. ([#2141](https://github.com/EQEmu/Server/pull/2141)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #showskills Command. ([#1994](https://github.com/EQEmu/Server/pull/1994)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-15
* Cleanup #spawneditmass Command. ([#2229](https://github.com/EQEmu/Server/pull/2229)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-04
* Cleanup #spawnfix Command. ([#2143](https://github.com/EQEmu/Server/pull/2143)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #spawnstatus Command. ([#2144](https://github.com/EQEmu/Server/pull/2144)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #summon Command. ([#2145](https://github.com/EQEmu/Server/pull/2145)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #summonburiedplayercorpse Command. ([#2146](https://github.com/EQEmu/Server/pull/2146)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #suspend Command. ([#2564](https://github.com/EQEmu/Server/pull/2564)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Cleanup #task Command. ([#2071](https://github.com/EQEmu/Server/pull/2071)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-14
* Cleanup #time and #timezone Command. ([#2147](https://github.com/EQEmu/Server/pull/2147)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #timers Command. ([#2562](https://github.com/EQEmu/Server/pull/2562)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Cleanup #trapinfo Command. ([#2148](https://github.com/EQEmu/Server/pull/2148)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #ucs Command. ([#2149](https://github.com/EQEmu/Server/pull/2149)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #undye and #undyeme Commands. ([#1966](https://github.com/EQEmu/Server/pull/1966)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10
* Cleanup #unscribespell Command. ([#1998](https://github.com/EQEmu/Server/pull/1998)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-16
* Cleanup #untraindisc Command. ([#1996](https://github.com/EQEmu/Server/pull/1996)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-16
* Cleanup #version Command. ([#1967](https://github.com/EQEmu/Server/pull/1967)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10
* Cleanup #worldwide command. ([#2021](https://github.com/EQEmu/Server/pull/2021)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-01
* Cleanup #xtargets Command. ([#2545](https://github.com/EQEmu/Server/pull/2545)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-17
* Cleanup #zone and #zoneinstance Commands. ([#2202](https://github.com/EQEmu/Server/pull/2202)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27
* Command Status Reload and Helper Method ([#2377](https://github.com/EQEmu/Server/pull/2377)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-20
* Consolidate #lock and #unlock Commands into #serverlock. ([#2193](https://github.com/EQEmu/Server/pull/2193)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23
* Fix #copycharacter command crash ([#2446](https://github.com/EQEmu/Server/pull/2446)) ([Akkadius](https://github.com/Akkadius)) 2022-09-25
* Fix #killallnpcs from crashing ([#2037](https://github.com/EQEmu/Server/pull/2037)) ([Akkadius](https://github.com/Akkadius)) 2022-03-07
* Fix Flymode Command Help Prompt ([#2669](https://github.com/EQEmu/Server/pull/2669)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-23
* Fix typos in #ban and #ipban Commands. ([#2209](https://github.com/EQEmu/Server/pull/2209)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-26
* Make #damage require a target ([#2426](https://github.com/EQEmu/Server/pull/2426)) ([hgtw](https://github.com/hgtw)) 2022-09-05
* Nested Command Aliases ([#2636](https://github.com/EQEmu/Server/pull/2636)) ([Akkadius](https://github.com/Akkadius)) 2022-12-15
* Remove #guildapprove, #guildcreate, and #guildlist Commands ([#2775](https://github.com/EQEmu/Server/pull/2775)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22
* Remove #iteminfo Command. ([#2565](https://github.com/EQEmu/Server/pull/2565)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Remove #profiledump and #profilereset Commands. ([#2546](https://github.com/EQEmu/Server/pull/2546)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16
* Remove #undyeme Command. ([#2776](https://github.com/EQEmu/Server/pull/2776)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22
* Remove unused #bestz and #pf Commands. ([#2112](https://github.com/EQEmu/Server/pull/2112)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Remove unused/broken #deletegraveyard and #setgraveyard Commands. ([#2198](https://github.com/EQEmu/Server/pull/2198)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23
### Diawind
* Plus sign markdown fix ([#2727](https://github.com/EQEmu/Server/pull/2727)) ([Akkadius](https://github.com/Akkadius)) 2023-01-12
### Feature
* AA Cap Limit ([#2423](https://github.com/EQEmu/Server/pull/2423)) ([fryguy503](https://github.com/fryguy503)) 2022-10-13
* Add "Keeps Sold Items" Flag to NPCs ([#2671](https://github.com/EQEmu/Server/pull/2671)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-25
* Add Experience Gain Toggle. ([#2676](https://github.com/EQEmu/Server/pull/2676)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-30
* Add Guild Chat to Console. ([#2387](https://github.com/EQEmu/Server/pull/2387)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-22
* Add Hate Override for Heals ([#2485](https://github.com/EQEmu/Server/pull/2485)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-14
* Add Rule to Disable Group EXP Modifier. ([#2741](https://github.com/EQEmu/Server/pull/2741)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-15
* Add Support for "Show Mine Only" Filters ([#2484](https://github.com/EQEmu/Server/pull/2484)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-13
* Add Type 49545 to Spell Resistrictions ([#2436](https://github.com/EQEmu/Server/pull/2436)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-20
* Add humanoid and non-wielded restrictions to pick pocket ([#2276](https://github.com/EQEmu/Server/pull/2276)) ([noudess](https://github.com/noudess)) 2022-07-03
* Add player /inspect quest event ([#2508](https://github.com/EQEmu/Server/pull/2508)) ([hgtw](https://github.com/hgtw)) 2022-10-29
* Add special ability to block /open ([#2506](https://github.com/EQEmu/Server/pull/2506)) ([hgtw](https://github.com/hgtw)) 2022-10-29
* Allow Focus Effects to be Filtered out. ([#2447](https://github.com/EQEmu/Server/pull/2447)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-25
* Allow pets to zone with permanent (buffdurationformula 50) buffs to maintain them through zone transitions ([#2035](https://github.com/EQEmu/Server/pull/2035)) ([catapultam-habeo](https://github.com/catapultam-habeo)) 2022-03-07
* Bind Wound and Forage while mounted. ([#2257](https://github.com/EQEmu/Server/pull/2257)) ([fryguy503](https://github.com/fryguy503)) 2022-07-03
* Change #scribespells to be aware of spellgroups & ranks ([#2501](https://github.com/EQEmu/Server/pull/2501)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-06
* Change GetSkillDmgAmt to int32 ([#2364](https://github.com/EQEmu/Server/pull/2364)) ([Aeadoin](https://github.com/Aeadoin)) 2022-08-10
* Change Lifetap Emotes to be filterable. ([#2454](https://github.com/EQEmu/Server/pull/2454)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-29
* Change Mana Costs to use Signed Int ([#2384](https://github.com/EQEmu/Server/pull/2384)) ([Aeadoin](https://github.com/Aeadoin)) 2022-08-21
* Change mana_used to int32 ([#2321](https://github.com/EQEmu/Server/pull/2321)) ([Aeadoin](https://github.com/Aeadoin)) 2022-07-30
* Client Checksum Verification (Resubmit old 1678) ([#1922](https://github.com/EQEmu/Server/pull/1922)) ([noudess](https://github.com/noudess)) 2022-03-07
* EQ2-style implied targeting for spells. ([#2032](https://github.com/EQEmu/Server/pull/2032)) ([catapultam-habeo](https://github.com/catapultam-habeo)) 2022-03-07
* Faction Association ([#2408](https://github.com/EQEmu/Server/pull/2408)) ([mackal](https://github.com/mackal)) 2022-09-03
* GM State Change Persistance ([#2328](https://github.com/EQEmu/Server/pull/2328)) ([fryguy503](https://github.com/fryguy503)) 2022-07-31
* Implement Heroic Strikethrough to NPCs ([#2395](https://github.com/EQEmu/Server/pull/2395)) ([Aeadoin](https://github.com/Aeadoin)) 2022-08-31
* Implement OP_CashReward ([#2307](https://github.com/EQEmu/Server/pull/2307)) ([mackal](https://github.com/mackal)) 2022-07-15
* Instance Version Specific Experience Modifiers ([#2376](https://github.com/EQEmu/Server/pull/2376)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-20
* NPCs with bows and arrows do ranged attacks ([#2322](https://github.com/EQEmu/Server/pull/2322)) ([mackal](https://github.com/mackal)) 2022-07-30
* Soft Delete Bots on Character Soft Delete ([#2467](https://github.com/EQEmu/Server/pull/2467)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-13
* Spell Ranks will now work with AllowSpellMemorizeFromItem Rule ([#2475](https://github.com/EQEmu/Server/pull/2475)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-13
* Update HateMod used by SPA 114 to Int32. ([#2428](https://github.com/EQEmu/Server/pull/2428)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-08
### Fixes
* #npcstats command displaying incorrect faction ([#2710](https://github.com/EQEmu/Server/pull/2710)) ([noudess](https://github.com/noudess)) 2023-01-08
* #peqzone no longer bypass Handle_OP_ZoneChange ([#2063](https://github.com/EQEmu/Server/pull/2063)) ([Natedog2012](https://github.com/Natedog2012)) 2022-03-19
* #scribespells triggered error on mysql keyword rank ([#2779](https://github.com/EQEmu/Server/pull/2779)) ([noudess](https://github.com/noudess)) 2023-01-21
* #tune command various fixes ([#2046](https://github.com/EQEmu/Server/pull/2046)) ([KayenEQ](https://github.com/KayenEQ)) 2022-03-11
* Add Complete Heal Spell back to IsCompleteHealSpell Method ([#2722](https://github.com/EQEmu/Server/pull/2722)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-11
* Add SE_MakeDrunk to avoid error message. ([#2601](https://github.com/EQEmu/Server/pull/2601)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-01
* Add omitted function call in UCS ([#2768](https://github.com/EQEmu/Server/pull/2768)) ([Valorith](https://github.com/Valorith)) 2023-01-20
* Add required distance to CoTH before aggro wipe ([#2253](https://github.com/EQEmu/Server/pull/2253)) ([fryguy503](https://github.com/fryguy503)) 2022-07-03
* Adjustment for nullptr crash ([#2232](https://github.com/EQEmu/Server/pull/2232)) ([Akkadius](https://github.com/Akkadius)) 2022-06-01
* Alleviate some lag with crosszone/worldwide spell casting. ([#2016](https://github.com/EQEmu/Server/pull/2016)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-21
* Allow High Level Spells to be Unmemorized. ([#2641](https://github.com/EQEmu/Server/pull/2641)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-14
* Allow Songs to be scribed from scrolls ([#2460](https://github.com/EQEmu/Server/pull/2460)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-12
* AltCurrencySelectItemReply_Struct was not handled correctly. ([#2702](https://github.com/EQEmu/Server/pull/2702)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-04
* Any use of TempName left old clean_name. ([#1946](https://github.com/EQEmu/Server/pull/1946)) ([noudess](https://github.com/noudess)) 2022-01-26
* Avoid erase in discord queue range loop ([#2411](https://github.com/EQEmu/Server/pull/2411)) ([hgtw](https://github.com/hgtw)) 2022-09-03
* Bandolier didn't recognize source weapon on cursor ([#2026](https://github.com/EQEmu/Server/pull/2026)) ([noudess](https://github.com/noudess)) 2022-03-07
* Bard Invisible causing display issues. ([#2067](https://github.com/EQEmu/Server/pull/2067)) ([KayenEQ](https://github.com/KayenEQ)) 2022-04-01
* Bard update fixes 1 ([#1982](https://github.com/EQEmu/Server/pull/1982)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-09
* Bazaar Search MYSQL Error ([#2252](https://github.com/EQEmu/Server/pull/2252)) ([fryguy503](https://github.com/fryguy503)) 2022-06-08
* Blocked spells max spell id increased ([#2207](https://github.com/EQEmu/Server/pull/2207)) ([Isaaru](https://github.com/Isaaru)) 2022-05-25
* Boats should never get FixZ'd ([#2246](https://github.com/EQEmu/Server/pull/2246)) ([noudess](https://github.com/noudess)) 2022-07-02
* Clamp Item Ldon Sell Back Rates. ([#2592](https://github.com/EQEmu/Server/pull/2592)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-30
* Clear title/suffix bug fix. ([#2068](https://github.com/EQEmu/Server/pull/2068)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-02
* Correct (probably) unintended bitwise AND instead of logical AND ([#2239](https://github.com/EQEmu/Server/pull/2239)) ([Quintinon](https://github.com/Quintinon)) 2022-06-02
* Correct type signed/unsigned int when reading item from database in shareddb ([#2269](https://github.com/EQEmu/Server/pull/2269)) ([Quintinon](https://github.com/Quintinon)) 2022-06-15
* Data Bucket Permanent Duration String ([#2624](https://github.com/EQEmu/Server/pull/2624)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-06
* Delete NpcType Struct returned by Bot::CreateDefaultNPCTypeStructForBot() when unused ([#2267](https://github.com/EQEmu/Server/pull/2267)) ([Quintinon](https://github.com/Quintinon)) 2022-06-18
* Do not allow /open to be used on traps or auras, causes crash ([#1951](https://github.com/EQEmu/Server/pull/1951)) ([KayenEQ](https://github.com/KayenEQ)) 2022-01-30
* Doors::GetSize() Perl Croak Typo. ([#2027](https://github.com/EQEmu/Server/pull/2027)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-04
* EVENT_ENTER_AREA/EVENT_LEAVE_AREA. ([#2698](https://github.com/EQEmu/Server/pull/2698)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-02
* Edge case AA reset timer issue fixes ([#1995](https://github.com/EQEmu/Server/pull/1995)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-14
* Fix #door Save ([#2699](https://github.com/EQEmu/Server/pull/2699)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-02
* Fix #findaa and GetAAName(). ([#2774](https://github.com/EQEmu/Server/pull/2774)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22
* Fix #zone 0. ([#2691](https://github.com/EQEmu/Server/pull/2691)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01
* Fix Aug Clicks where item has no click effect. ([#2725](https://github.com/EQEmu/Server/pull/2725)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-12
* Fix Bot "Failed to Load" Messages. ([#2719](https://github.com/EQEmu/Server/pull/2719)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-11
* Fix Bot Group Loading ([#2780](https://github.com/EQEmu/Server/pull/2780)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-22
* Fix Bot ^spellsettingsadd command ([#2603](https://github.com/EQEmu/Server/pull/2603)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-01
* Fix Duplicate Silent Saylink Messages ([#2386](https://github.com/EQEmu/Server/pull/2386)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-22
* Fix EntityList::GetBotListByCharacterID() ([#2569](https://github.com/EQEmu/Server/pull/2569)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Fix Flag Updating with SetGMStatus() in Lua. ([#2554](https://github.com/EQEmu/Server/pull/2554)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-20
* Fix Group XP not working. ([#2748](https://github.com/EQEmu/Server/pull/2748)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-17
* Fix HP Regen Per Second. ([#2206](https://github.com/EQEmu/Server/pull/2206)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-25
* Fix IDFile Crash with spaces or invalid data. ([#2597](https://github.com/EQEmu/Server/pull/2597)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-01
* Fix IP Exemptions. ([#2189](https://github.com/EQEmu/Server/pull/2189)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-28
* Fix Instance Repository ([#2598](https://github.com/EQEmu/Server/pull/2598)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-01
* Fix Legacy Combat Lua Script ([#2226](https://github.com/EQEmu/Server/pull/2226)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-31
* Fix MovePC in #zone and #zoneinstance Commands. ([#2236](https://github.com/EQEmu/Server/pull/2236)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-01
* Fix NPC Reference in EVENT_SPAWN ([#2712](https://github.com/EQEmu/Server/pull/2712)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-08
* Fix ST_TargetsTarget Spells with Restrictions ([#2746](https://github.com/EQEmu/Server/pull/2746)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-15
* Fix Silent Saylinks Sending Message to Others. ([#2389](https://github.com/EQEmu/Server/pull/2389)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-22
* Fix Spell Bucket and Spell Global Logic Checks. ([#2285](https://github.com/EQEmu/Server/pull/2285)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-05
* Fix Spellinfo Command to work with SpellIDs above int16 ([#2437](https://github.com/EQEmu/Server/pull/2437)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-20
* Fix Strings::Money Missing Conditions. ([#2383](https://github.com/EQEmu/Server/pull/2383)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-21
* Fix Swarm Pet Flurry/Rampages Messages ([#2444](https://github.com/EQEmu/Server/pull/2444)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-25
* Fix bot compile locking client on server enter. ([#2210](https://github.com/EQEmu/Server/pull/2210)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-26
* Fix bot guild removal. ([#2194](https://github.com/EQEmu/Server/pull/2194)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23
* Fix botgrouplist to display unique entries. ([#2785](https://github.com/EQEmu/Server/pull/2785)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-23
* Fix bots equipping augments. ([#2772](https://github.com/EQEmu/Server/pull/2772)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22
* Fix case-sensitivity in #suspend Command. ([#2613](https://github.com/EQEmu/Server/pull/2613)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-05
* Fix duplicate and missing messages due to innate in spells ([#2170](https://github.com/EQEmu/Server/pull/2170)) ([noudess](https://github.com/noudess)) 2022-05-20
* Fix empty spawned merchants ([#2275](https://github.com/EQEmu/Server/pull/2275)) ([hgtw](https://github.com/hgtw)) 2022-06-28
* Fix for Bot command casting ([#1990](https://github.com/EQEmu/Server/pull/1990)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-12
* Fix for PR1954 target restriction with npcpc_only_flag from groupbuffs ([#1986](https://github.com/EQEmu/Server/pull/1986)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-10
* Fix for being able to skill up on corspe. ([#2058](https://github.com/EQEmu/Server/pull/2058)) ([noudess](https://github.com/noudess)) 2022-03-19
* Fix for castspell command ([#2010](https://github.com/EQEmu/Server/pull/2010)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-18
* Fix issue where #advnpcspawn addspawn does not add spawn sometimes. ([#2247](https://github.com/EQEmu/Server/pull/2247)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-07
* Fix issue where you can set your title to titles you don't have. ([#1917](https://github.com/EQEmu/Server/pull/1917)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-01-30
* Fix issue with Bot::LoadAndSpawnAllZonedBots. ([#2733](https://github.com/EQEmu/Server/pull/2733)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-15
* Fix issue with mobs summoning PCs into ceilings ([#1921](https://github.com/EQEmu/Server/pull/1921)) ([noudess](https://github.com/noudess)) 2022-01-30
* Fix loading world shared task state ([#2398](https://github.com/EQEmu/Server/pull/2398)) ([hgtw](https://github.com/hgtw)) 2022-08-28
* Fix luamod GetExperienceForKill return value ([Cole-SoD](https://github.com/Cole-SoD)) 2023-01-12
* Fix memory leak in ucs ([#2409](https://github.com/EQEmu/Server/pull/2409)) ([hgtw](https://github.com/hgtw)) 2022-09-03
* Fix miscellaneous memory leaks related to EQApplicationPacket and it's pBuffer ([#2262](https://github.com/EQEmu/Server/pull/2262)) ([Quintinon](https://github.com/Quintinon)) 2022-07-03
* Fix null pointer crash on zones that have not booted a zone yet with #reload commands or anything that calls GetZoneDescription ([#2231](https://github.com/EQEmu/Server/pull/2231)) ([Akkadius](https://github.com/Akkadius)) 2022-06-01
* Fix possible crash in ProcessSpecialAbilities. ([#2630](https://github.com/EQEmu/Server/pull/2630)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-11
* Fix possible crash with zone name methods. ([#2055](https://github.com/EQEmu/Server/pull/2055)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-13
* Fix possible issue where variables have the same name. ([#2156](https://github.com/EQEmu/Server/pull/2156)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-08
* Fix quest::updatespawntimer() Perl croak. ([#1947](https://github.com/EQEmu/Server/pull/1947)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-01-26
* Fix recipient sound (vtell) on non-player races ([#2066](https://github.com/EQEmu/Server/pull/2066)) ([noudess](https://github.com/noudess)) 2022-04-02
* Fix scenario where dereferenced object could be null. ([#2784](https://github.com/EQEmu/Server/pull/2784)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-23
* Fix stack leaks in Lua events #2254 ([hgtw](https://github.com/hgtw)) 2022-06-09
* Fix trading with bots when in an illusion. ([#2645](https://github.com/EQEmu/Server/pull/2645)) ([nytmyr](https://github.com/nytmyr)) 2022-12-15
* Fix two invalid data accesses in zone/client.cpp ([#2238](https://github.com/EQEmu/Server/pull/2238)) ([Quintinon](https://github.com/Quintinon)) 2022-06-07
* Fixed Spell Logic for Bot Nukes ([#2481](https://github.com/EQEmu/Server/pull/2481)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-13
* Fixed message on promote/demote permissions check. ([#2700](https://github.com/EQEmu/Server/pull/2700)) ([Valorith](https://github.com/Valorith)) 2023-01-02
* Fixed several instances of incorrect comparision - & executes after == ([#2025](https://github.com/EQEmu/Server/pull/2025)) ([noudess](https://github.com/noudess)) 2022-03-07
* Force NPCs to respect special ability 24 and 50 when set on player pets ([#2059](https://github.com/EQEmu/Server/pull/2059)) ([Natedog2012](https://github.com/Natedog2012)) 2022-03-16
* Free return value of ZoneDatabase::LoadTraderItemWithCharges() ([#2264](https://github.com/EQEmu/Server/pull/2264)) ([Quintinon](https://github.com/Quintinon)) 2022-06-18
* Hacker_Str was causing sql errors - Non Escaped ([#2251](https://github.com/EQEmu/Server/pull/2251)) ([fryguy503](https://github.com/fryguy503)) 2022-06-08
* Handle memory leaks from return value of Client::GetTraderItems() ([#2266](https://github.com/EQEmu/Server/pull/2266)) ([Quintinon](https://github.com/Quintinon)) 2022-07-03
* Handle_OP_AugmentItem could cause Zone crash ([#2750](https://github.com/EQEmu/Server/pull/2750)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-17
* HasPet() Zone Crashes ([#2744](https://github.com/EQEmu/Server/pull/2744)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-15
* Illusions will now properly display armor to other clients when they zone in. ([#1958](https://github.com/EQEmu/Server/pull/1958)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-04
* Instrument Mods should not affect spells that change model size. ([#2072](https://github.com/EQEmu/Server/pull/2072)) ([KayenEQ](https://github.com/KayenEQ)) 2022-04-13
* Invisible will display as dropped now on air pets when they attack. ([#2042](https://github.com/EQEmu/Server/pull/2042)) ([KayenEQ](https://github.com/KayenEQ)) 2022-03-07
* IsDamage test for lifetap was not complete. ([#2213](https://github.com/EQEmu/Server/pull/2213)) ([noudess](https://github.com/noudess)) 2022-05-27
* Limit merchant temp item list to zone and instance ([#2346](https://github.com/EQEmu/Server/pull/2346)) ([mackal](https://github.com/mackal)) 2022-07-31
* Lua GetBlockNextSpell() no return. ([#2151](https://github.com/EQEmu/Server/pull/2151)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Make Perl TakeMoneyFromPP int64 ([#2158](https://github.com/EQEmu/Server/pull/2158)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-08
* Missing break ([#2031](https://github.com/EQEmu/Server/pull/2031)) ([KayenEQ](https://github.com/KayenEQ)) 2022-03-04
* Move EVENT_SPAWN for adding NPCs back to original spot, also add NPCs… ([#2749](https://github.com/EQEmu/Server/pull/2749)) ([Natedog2012](https://github.com/Natedog2012)) 2023-01-17
* NPC Constructor was passing hp_regen_per_second out of order to Mob(). ([#2681](https://github.com/EQEmu/Server/pull/2681)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-29
* NPC::CountItem and Corpse::CountItem 0 Charge Item Fix. ([#1959](https://github.com/EQEmu/Server/pull/1959)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-04
* NPC::GetNPCStat has no default return. ([#2150](https://github.com/EQEmu/Server/pull/2150)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* NPCs were getting weapon proc added twice ([#2277](https://github.com/EQEmu/Server/pull/2277)) ([noudess](https://github.com/noudess)) 2022-07-07
* Objects::GetTiltX() and Objects::GetTiltY() Perl Croak Typos. ([#2028](https://github.com/EQEmu/Server/pull/2028)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-04
* PR 1982 ([#1985](https://github.com/EQEmu/Server/pull/1985)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-10
* PR 2032 would lock client on casting fail as written ([#2038](https://github.com/EQEmu/Server/pull/2038)) ([KayenEQ](https://github.com/KayenEQ)) 2022-03-07
* Remove StringUtilTest::EscapeStringMemoryTest ([#2310](https://github.com/EQEmu/Server/pull/2310)) ([mackal](https://github.com/mackal)) 2022-07-15
* Remove Unnecessary Attack Log ([#2643](https://github.com/EQEmu/Server/pull/2643)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-14
* Remove unnecessary log messages. ([#2642](https://github.com/EQEmu/Server/pull/2642)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-14
* Removed Lua Event Argument Dispatch. ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-01
* Resolve Warning due to Virtual Mob Method GetInv() ([#2650](https://github.com/EQEmu/Server/pull/2650)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-19
* Resolve XP Calculation Bug introduced w/ recent Rule addition ([#2703](https://github.com/EQEmu/Server/pull/2703)) ([Valorith](https://github.com/Valorith)) 2023-01-07
* Resolve logic error in Raid::QueueClients ([#2404](https://github.com/EQEmu/Server/pull/2404)) ([mackal](https://github.com/mackal)) 2022-09-01
* Resolve subroutine redefinition due to bot methods. ([#2117](https://github.com/EQEmu/Server/pull/2117)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Restore missing messages for lifetap and dmg spells. ([#2057](https://github.com/EQEmu/Server/pull/2057)) ([noudess](https://github.com/noudess)) 2022-04-14
* Shared Memory Faction Association Typo ([#2419](https://github.com/EQEmu/Server/pull/2419)) ([mackal](https://github.com/mackal)) 2022-09-03
* Spell Buckets/Globals SQL Escape. ([#2019](https://github.com/EQEmu/Server/pull/2019)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-26
* Spell Buckets/Globals did not allow string-based values. ([#2043](https://github.com/EQEmu/Server/pull/2043)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-09
* Stop skill ups on Charmed NPCs. ([#2249](https://github.com/EQEmu/Server/pull/2249)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-10
* Summon Companion causing pets to warps away. ([#1972](https://github.com/EQEmu/Server/pull/1972)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-08
* Touch Of Vinitras was ignoring pet DT rule ([#2469](https://github.com/EQEmu/Server/pull/2469)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-03
* Tradeskill Autocombine MinSkill ([#2260](https://github.com/EQEmu/Server/pull/2260)) ([fryguy503](https://github.com/fryguy503)) 2022-06-10
* Tradeskill Item 0 Error ([#2256](https://github.com/EQEmu/Server/pull/2256)) ([fryguy503](https://github.com/fryguy503)) 2022-06-10
* Zone Flags Regression ([#2760](https://github.com/EQEmu/Server/pull/2760)) ([Akkadius](https://github.com/Akkadius)) 2023-01-19
* checking casting_spell_slot before its defined is bad ([#2013](https://github.com/EQEmu/Server/pull/2013)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-20
* manifest for db version 9176 had incorrect field name ([#2062](https://github.com/EQEmu/Server/pull/2062)) ([noudess](https://github.com/noudess)) 2022-03-19
* quest::MovePCInstance() Arguments Fix. ([#2020](https://github.com/EQEmu/Server/pull/2020)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-27
### Hotfix
* Add Bazaar portal discs to SQL ([Akkadius](https://github.com/Akkadius)) 2022-09-05
* Add discord_webhooks to server tables ([Akkadius](https://github.com/Akkadius)) 2022-07-03
* Blocks are nested too deeply. ([#2689](https://github.com/EQEmu/Server/pull/2689)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01
* Cleanup #questerrors Command. ([#2116](https://github.com/EQEmu/Server/pull/2116)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Compiling fails on FMT 9.1 with Bots ([#2665](https://github.com/EQEmu/Server/pull/2665)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-21
* Correct database call to point to the content_db connection ([Akkadius](https://github.com/Akkadius)) 2022-06-12
* Corrected misnamed Database Query file for Experience Toggle ([#2683](https://github.com/EQEmu/Server/pull/2683)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-31
* Faction associations file naming / lock consistency ([Akkadius](https://github.com/Akkadius)) 2022-09-05
* Fix DB version merge ([Akkadius](https://github.com/Akkadius)) 2022-05-08
* Fix door click crash issue if destination zone doesn't exist ([Akkadius](https://github.com/Akkadius)) 2023-01-20
* Fix issue with Bot Loading with 0 Health causing buffs to be lost. ([#2552](https://github.com/EQEmu/Server/pull/2552)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-18
* Fix lua mod load path ([Akkadius](https://github.com/Akkadius)) 2022-09-29
* Fix merge issue ([Akkadius](https://github.com/Akkadius)) 2022-07-14
* Fix path load ordering for CLI commands ([Akkadius](https://github.com/Akkadius)) 2022-10-16
* Fix potential race for crash dumps (Linux) ([Akkadius](https://github.com/Akkadius)) 2022-07-31
* Fix regression caused by #2129 ([Akkadius](https://github.com/Akkadius)) 2022-05-09
* Flipped positive / negative values for legacy_combat.lua ([Akkadius](https://github.com/Akkadius)) 2022-06-09
* Force collation on conversion script ([Akkadius](https://github.com/Akkadius)) 2022-09-28
* Instances Repository Fix ([#2576](https://github.com/EQEmu/Server/pull/2576)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-26
* Login Server failing to compile on Windows. ([#2758](https://github.com/EQEmu/Server/pull/2758)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-19
* Lua Parser Needs Lua_ItemInst ([#2696](https://github.com/EQEmu/Server/pull/2696)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01
* Make sure we have a proper split size before assuming we can split it ([Akkadius](https://github.com/Akkadius)) 2023-01-20
* Move discord_webhooks to state tables because we don't want webhooks being exported ([Akkadius](https://github.com/Akkadius)) 2022-07-03
* Possible windows compile fix ([Akkadius](https://github.com/Akkadius)) 2022-07-07
* Possible windows compile fix take 2 ([Akkadius](https://github.com/Akkadius)) 2022-07-07
* Remove appveyor fetch bots ([Akkadius](https://github.com/Akkadius)) 2023-01-21
* Remove expansion field from account for those who have it ([#2357](https://github.com/EQEmu/Server/pull/2357)) ([Akkadius](https://github.com/Akkadius)) 2022-08-01
* Resolve Zone Crashing when grouped with Bots. ([#2747](https://github.com/EQEmu/Server/pull/2747)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-16
* Resolve issue with Bot Casting after zoning. ([#2617](https://github.com/EQEmu/Server/pull/2617)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-04
* Return weather_type_map ([Akkadius](https://github.com/Akkadius)) 2022-10-14
* SQL Update ([Akkadius](https://github.com/Akkadius)) 2022-07-31
* Shared Memory Protection Fixes ([Akkadius](https://github.com/Akkadius)) 2022-07-27
* Windows compile fix take 3 (final) ([Akkadius](https://github.com/Akkadius)) 2022-07-07
* fix manifest ([Akkadius](https://github.com/Akkadius)) 2022-07-16
### Logging
* Add stack trace in code paths that shouldn't occur ([#2453](https://github.com/EQEmu/Server/pull/2453)) ([Akkadius](https://github.com/Akkadius)) 2022-09-28
* Cleanup AI Logging Events ([#2615](https://github.com/EQEmu/Server/pull/2615)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-04
* Fix log messages to final damage values ([#2056](https://github.com/EQEmu/Server/pull/2056)) ([noudess](https://github.com/noudess)) 2022-03-14
* Fix zoning log typo ([#2478](https://github.com/EQEmu/Server/pull/2478)) ([Akkadius](https://github.com/Akkadius)) 2022-10-11
* Force crash logs to always be on regardless of setting ([#2762](https://github.com/EQEmu/Server/pull/2762)) ([Akkadius](https://github.com/Akkadius)) 2023-01-20
* Improvements to GM Say Logging ([#2765](https://github.com/EQEmu/Server/pull/2765)) ([Akkadius](https://github.com/Akkadius)) 2023-01-20
* Logging Improvements ([#2755](https://github.com/EQEmu/Server/pull/2755)) ([Akkadius](https://github.com/Akkadius)) 2023-01-18
* More AI Logging Cleanup ([#2616](https://github.com/EQEmu/Server/pull/2616)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-10
* Netcode Logging Unify ([#2443](https://github.com/EQEmu/Server/pull/2443)) ([Akkadius](https://github.com/Akkadius)) 2022-09-28
* Remove function prefixes ([#2766](https://github.com/EQEmu/Server/pull/2766)) ([Akkadius](https://github.com/Akkadius)) 2023-01-20
* Remove loginserver unhandled error ([#2458](https://github.com/EQEmu/Server/pull/2458)) ([Akkadius](https://github.com/Akkadius)) 2022-09-29
* Reset stream so we don't bold the whole line ([Akkadius](https://github.com/Akkadius)) 2023-01-18
* Table Injection - Member Variable Cleanup ([#2281](https://github.com/EQEmu/Server/pull/2281)) ([Akkadius](https://github.com/Akkadius)) 2022-07-07
* Update BUILD_LOGGING=false Blank Aliases ([#2083](https://github.com/EQEmu/Server/pull/2083)) ([Akkadius](https://github.com/Akkadius)) 2022-05-01
### Luamod
* Add CalcSpellEffectValue_formula to luamods ([#2721](https://github.com/EQEmu/Server/pull/2721)) ([Natedog2012](https://github.com/Natedog2012)) 2023-01-11
### Mercs
* Add Mercenary Support ([#2745](https://github.com/EQEmu/Server/pull/2745)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-17
### Optimization
* Handle channel name filter checks in memory ([#2767](https://github.com/EQEmu/Server/pull/2767)) ([Valorith](https://github.com/Valorith)) 2023-01-20
### QS
* Database class name change ([#2743](https://github.com/EQEmu/Server/pull/2743)) ([Akkadius](https://github.com/Akkadius)) 2023-01-15
### Quest API
* Add AddAISpellEffect(spell_effect_id, base_value, limit_value, max_value) and RemoveAISpellEffect(spell_effect_id) to Lua. ([#1981](https://github.com/EQEmu/Server/pull/1981)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-09
* Add AddItem() to Perl/Lua. ([#2054](https://github.com/EQEmu/Server/pull/2054)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-13
* Add AddPlatinum(), GetCarriedPlatinum() and TakePlatinum() to Perl/Lua. ([#2079](https://github.com/EQEmu/Server/pull/2079)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-30
* Add Area Damage Methods to Perl/Lua. ([#2549](https://github.com/EQEmu/Server/pull/2549)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-17
* Add Augment Slot Type/Visible to GetItemStat ([#2686](https://github.com/EQEmu/Server/pull/2686)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01
* Add Bot Methods to Lua. ([#2731](https://github.com/EQEmu/Server/pull/2731)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-14
* Add Bot::Camp() to Perl/Lua. ([#2718](https://github.com/EQEmu/Server/pull/2718)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-11
* Add BuffCount() Overloads to Perl/Lua. ([#2679](https://github.com/EQEmu/Server/pull/2679)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-29
* Add CampAllBots() to Perl/Lua. ([#2732](https://github.com/EQEmu/Server/pull/2732)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-14
* Add Charges/Augment/Attuned Support to Varlink. ([#2685](https://github.com/EQEmu/Server/pull/2685)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01
* Add CheckNameFilter to Perl/Lua. ([#2175](https://github.com/EQEmu/Server/pull/2175)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-20
* Add Client Augment Events to Perl/Lua. ([#2735](https://github.com/EQEmu/Server/pull/2735)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-15
* Add Client Spell Methods to Perl/Lua. ([#2550](https://github.com/EQEmu/Server/pull/2550)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Add CloneAppearance() to Perl/Lua. ([#2531](https://github.com/EQEmu/Server/pull/2531)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add CopyHateList() to Perl/Lua. ([#2623](https://github.com/EQEmu/Server/pull/2623)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-06
* Add Corpse::AddItem overloads for Lua ([#2509](https://github.com/EQEmu/Server/pull/2509)) ([hgtw](https://github.com/hgtw)) 2022-10-29
* Add Despawn Events to Perl/Lua. ([#2707](https://github.com/EQEmu/Server/pull/2707)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-07
* Add DoAnim Overloads to Perl/Lua. ([#2627](https://github.com/EQEmu/Server/pull/2627)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-10
* Add DoAugmentSlotsMatch() to Perl/Lua. ([#2687](https://github.com/EQEmu/Server/pull/2687)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01
* Add DoesAugmentFit() to Perl/Lua. ([#2688](https://github.com/EQEmu/Server/pull/2688)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01
* Add Door Methods to Perl/Lua. ([#2724](https://github.com/EQEmu/Server/pull/2724)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-12
* Add EVENT_AA_BUY and EVENT_AA_GAIN to Perl/Lua. ([#2504](https://github.com/EQEmu/Server/pull/2504)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-05
* Add EVENT_BOT_CREATE to Perl/Lua ([#2713](https://github.com/EQEmu/Server/pull/2713)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-09
* Add EVENT_CAST_ON exports to EVENT_CAST and EVENT_CAST_BEGIN. ([#2051](https://github.com/EQEmu/Server/pull/2051)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-12
* Add EVENT_EQUIP_ITEM_CLIENT and EVENT_UNEQUIP_ITEM_CLIENT to Perl/Lua. ([#2015](https://github.com/EQEmu/Server/pull/2015)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-23
* Add EVENT_GM_COMMAND to Perl/Lua. ([#2634](https://github.com/EQEmu/Server/pull/2634)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-11
* Add EVENT_LEVEL_DOWN to Perl/Lua. ([#2620](https://github.com/EQEmu/Server/pull/2620)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-11
* Add EVENT_PAYLOAD to Perl/Lua. ([#2611](https://github.com/EQEmu/Server/pull/2611)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-04
* Add EVENT_SKILL_UP & EVENT_LANGUAGE_SKILL_UP to Perl/Lua ([#2076](https://github.com/EQEmu/Server/pull/2076)) ([nytmyr](https://github.com/nytmyr)) 2022-04-25
* Add Entity Variable Methods to Perl/Lua. ([#2609](https://github.com/EQEmu/Server/pull/2609)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-04
* Add Fling Overloads to Perl/Lua. ([#2622](https://github.com/EQEmu/Server/pull/2622)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-06
* Add GetAugmentIDsBySlotID() to Perl/Lua. ([#2673](https://github.com/EQEmu/Server/pull/2673)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-25
* Add GetAverageLevel() to Perl/Lua. ([#2524](https://github.com/EQEmu/Server/pull/2524)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add GetBotItem() and GetBotItemIDBySlot() to Perl/Lua. ([#2350](https://github.com/EQEmu/Server/pull/2350)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-31
* Add GetBotListByCharacterID() to Perl/Lua. ([#2069](https://github.com/EQEmu/Server/pull/2069)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-02
* Add GetBotListByClientName() Class Overload to Perl/Lua. ([#2577](https://github.com/EQEmu/Server/pull/2577)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-26
* Add GetBotListByClientName(client_name) to Perl/Lua. ([#2064](https://github.com/EQEmu/Server/pull/2064)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-23
* Add GetEnvironmentalDamageName() to Perl/Lua. ([#1964](https://github.com/EQEmu/Server/pull/1964)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10
* Add GetGMStatus() to Perl/Lua. ([#2448](https://github.com/EQEmu/Server/pull/2448)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-09-28
* Add GetGuildPublicNote() to Perl/Lua. ([#2608](https://github.com/EQEmu/Server/pull/2608)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-04
* Add GetHealAmount() and GetSpellDamage() to Perl/Lua. ([#2165](https://github.com/EQEmu/Server/pull/2165)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-11
* Add GetLeader() and GetLeaderName() to Perl/Lua. ([#2701](https://github.com/EQEmu/Server/pull/2701)) ([Valorith](https://github.com/Valorith)) 2023-01-04
* Add GetLowestLevel() to Perl. ([#2517](https://github.com/EQEmu/Server/pull/2517)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-05
* Add GetRandomBot() to Perl/Lua ([#2543](https://github.com/EQEmu/Server/pull/2543)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16
* Add GetRandomClient(), GetRandomMob() and GetRandomNPC() overloads to Perl/Lua. ([#2541](https://github.com/EQEmu/Server/pull/2541)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add GetRandomMob() and GetRandomNPC() to Perl/Lua. ([#2006](https://github.com/EQEmu/Server/pull/2006)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-17
* Add GetSkillDmgAmt() to Perl. ([#2365](https://github.com/EQEmu/Server/pull/2365)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-10
* Add GetUltimateOwner() to Perl/Lua. ([#2516](https://github.com/EQEmu/Server/pull/2516)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-05
* Add Goto Player Teleport Methods. ([#2379](https://github.com/EQEmu/Server/pull/2379)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-20
* Add Group/Raid Overloads to Perl/Lua. ([#2587](https://github.com/EQEmu/Server/pull/2587)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27
* Add Group/Raid overloads to Perl/Lua. ([#2526](https://github.com/EQEmu/Server/pull/2526)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add HasBotSpellEntry() to Perl/Lua. ([#2563](https://github.com/EQEmu/Server/pull/2563)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-25
* Add Hotzone Methods to Perl/Lua. ([#2558](https://github.com/EQEmu/Server/pull/2558)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Add Instance ID/Version exports to EVENT_ZONE. ([#2502](https://github.com/EQEmu/Server/pull/2502)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-05
* Add Instance Methods to Perl/Lua. ([#2573](https://github.com/EQEmu/Server/pull/2573)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-26
* Add IsAttackAllowed() to Perl/Lua. ([#2672](https://github.com/EQEmu/Server/pull/2672)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-25
* Add IsRaining() and IsSnowing() to Perl/Lua. ([#2477](https://github.com/EQEmu/Server/pull/2477)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-14
* Add IsRareSpawn() to Perl/Lua. ([#2338](https://github.com/EQEmu/Server/pull/2338)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-30
* Add Lua handlers for zone controller events ([#2514](https://github.com/EQEmu/Server/pull/2514)) ([hgtw](https://github.com/hgtw)) 2022-11-05
* Add Marquee methods to Perl/Lua. ([#2544](https://github.com/EQEmu/Server/pull/2544)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16
* Add MaxSkills() to Perl/Lua. ([#2621](https://github.com/EQEmu/Server/pull/2621)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-06
* Add Merchant Events to Perl/Lua. ([#2452](https://github.com/EQEmu/Server/pull/2452)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-09-28
* Add Mob Hate Methods to Perl/Lua. ([#2548](https://github.com/EQEmu/Server/pull/2548)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16
* Add Overloads to MoveZone Methods in Perl/Lua. ([#2551](https://github.com/EQEmu/Server/pull/2551)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Add Owner methods to Perl/Lua. ([#2542](https://github.com/EQEmu/Server/pull/2542)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add Popup methods to Perl/Lua. ([#2533](https://github.com/EQEmu/Server/pull/2533)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add Proximity Range Methods to Perl/Lua. ([#2572](https://github.com/EQEmu/Server/pull/2572)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-26
* Add RandomizeFeature() overloads to Perl/Lua. ([#2532](https://github.com/EQEmu/Server/pull/2532)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add Recipe Methods ([#2393](https://github.com/EQEmu/Server/pull/2393)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-23
* Add ResetAlternateAdvancementRank() to Perl/Lua. ([#2510](https://github.com/EQEmu/Server/pull/2510)) ([hgtw](https://github.com/hgtw)) 2022-10-29
* Add ResetDecayTimer() to Perl/Lua. ([#2520](https://github.com/EQEmu/Server/pull/2520)) ([hgtw](https://github.com/hgtw)) 2022-11-06
* Add SendGMCommand() to Perl/Lua. ([#2527](https://github.com/EQEmu/Server/pull/2527)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add SendPath() to Perl/Lua. ([#2740](https://github.com/EQEmu/Server/pull/2740)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-15
* Add SignalAllBotsByOwnerName() to Perl/Lua. ([#2730](https://github.com/EQEmu/Server/pull/2730)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-13
* Add SplitMoney() with Client splitter to Perl. ([#2525](https://github.com/EQEmu/Server/pull/2525)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add TaskSelector to Perl/Lua. ([#2177](https://github.com/EQEmu/Server/pull/2177)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-15
* Add Time String to Seconds Method to Perl/Lua. ([#2580](https://github.com/EQEmu/Server/pull/2580)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27
* Add TrackNPC to Perl/Lua. ([#2272](https://github.com/EQEmu/Server/pull/2272)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-29
* Add WearChange Overloads to Perl/Lua. ([#2600](https://github.com/EQEmu/Server/pull/2600)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-01
* Add Zone Flag Methods to Perl/Lua. ([#2574](https://github.com/EQEmu/Server/pull/2574)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-26
* Add apis to end shared tasks ([#2521](https://github.com/EQEmu/Server/pull/2521)) ([hgtw](https://github.com/hgtw)) 2022-11-06
* Add caster_id and caster_level export to EVENT_CAST_ON in Perl/Lua. ([#2049](https://github.com/EQEmu/Server/pull/2049)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-11
* Add commify to Perl/Lua. ([#2099](https://github.com/EQEmu/Server/pull/2099)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-03
* Add inventory->CountItemEquippedByID(item_id) and inventory->HasItemEquippedByID(item_id) to Perl/Lua. ([#1963](https://github.com/EQEmu/Server/pull/1963)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-06
* Add missing methods/package.adds to Perl API. ([#2287](https://github.com/EQEmu/Server/pull/2287)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-05
* Add multiple inventory method short hands to client. ([#2078](https://github.com/EQEmu/Server/pull/2078)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-30
* Add option to Ignore Mods to CalcEXP ([#2704](https://github.com/EQEmu/Server/pull/2704)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-06
* Adjustment to depop_all function. ([#2595](https://github.com/EQEmu/Server/pull/2595)) ([fryguy503](https://github.com/fryguy503)) 2022-11-30
* Allow CreateInstance to be used without a Client initiator. ([#2399](https://github.com/EQEmu/Server/pull/2399)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-28
* Allow EVENT_ZONE to be parsed as non-zero to prevent zoning. ([#2052](https://github.com/EQEmu/Server/pull/2052)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-12
* Allow scripts to prevent door click ([#2327](https://github.com/EQEmu/Server/pull/2327)) ([hgtw](https://github.com/hgtw)) 2022-07-27
* Cleanup Proximity Events ([#2697](https://github.com/EQEmu/Server/pull/2697)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-02
* Cleanup Signal Methods in Perl/Lua. ([#2604](https://github.com/EQEmu/Server/pull/2604)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-04
* Expand Bot quest API functionality. ([#2096](https://github.com/EQEmu/Server/pull/2096)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-04
* Expand SaveGuardSpot ([#2258](https://github.com/EQEmu/Server/pull/2258)) ([fryguy503](https://github.com/fryguy503)) 2022-06-10
* Export corpse in EVENT_DEATH_COMPLETE ([#2519](https://github.com/EQEmu/Server/pull/2519)) ([hgtw](https://github.com/hgtw)) 2022-11-06
* Export killed XYZH to EVENT_DEATH_ZONE in Perl. ([#2050](https://github.com/EQEmu/Server/pull/2050)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-12
* Fix Lua Door/Object Create Methods. ([#2633](https://github.com/EQEmu/Server/pull/2633)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-11
* Fix Perl EVENT_HP double parsing in Spire. ([#2585](https://github.com/EQEmu/Server/pull/2585)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27
* Fix lua task selector count when over max ([#2353](https://github.com/EQEmu/Server/pull/2353)) ([hgtw](https://github.com/hgtw)) 2022-07-31
* Fix missing arg in perl set_proximity ([#2291](https://github.com/EQEmu/Server/pull/2291)) ([hgtw](https://github.com/hgtw)) 2022-07-09
* Fix parameters in some Perl worldwide methods. ([#2224](https://github.com/EQEmu/Server/pull/2224)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-31
* Let HasQuestSub check encounters ([#2435](https://github.com/EQEmu/Server/pull/2435)) ([hgtw](https://github.com/hgtw)) 2022-09-20
* Perl Doors Fix. ([#2288](https://github.com/EQEmu/Server/pull/2288)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-05
* Perl Money Fixes. ([#2098](https://github.com/EQEmu/Server/pull/2098)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-04
* Send delivered task items in trade events ([#2518](https://github.com/EQEmu/Server/pull/2518)) ([hgtw](https://github.com/hgtw)) 2022-11-06
* Use Floating Point for CameraEffect Intensity ([#2337](https://github.com/EQEmu/Server/pull/2337)) ([hgtw](https://github.com/hgtw)) 2022-07-31
* Use binding library for perl apis ([#2216](https://github.com/EQEmu/Server/pull/2216)) ([hgtw](https://github.com/hgtw)) 2022-07-04
### Rules
* Add Backstab Rules ([#2666](https://github.com/EQEmu/Server/pull/2666)) ([Valorith](https://github.com/Valorith)) 2022-12-21
* Add Frontal Stun Immunity Rules. ([#2217](https://github.com/EQEmu/Server/pull/2217)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-07
* Add Keep Level on Death ([#2319](https://github.com/EQEmu/Server/pull/2319)) ([trentdm](https://github.com/trentdm)) 2022-07-30
* Add LDoN Loot Count Modifier Rule ([#2694](https://github.com/EQEmu/Server/pull/2694)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-03
* Add ManaOnDeath and EndurOnDeath ([#2661](https://github.com/EQEmu/Server/pull/2661)) ([fryguy503](https://github.com/fryguy503)) 2022-12-20
* Add Rule to Disable NPC Last Names. ([#2227](https://github.com/EQEmu/Server/pull/2227)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-04
* Add Rule to Enable Tells with #hideme ([#2358](https://github.com/EQEmu/Server/pull/2358)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-04
* Add Rule to allow Assassinate on non-Humanoid body types. ([#2331](https://github.com/EQEmu/Server/pull/2331)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-29
* Add Rule to allow Headshots on non-Humanoid body types. ([#2329](https://github.com/EQEmu/Server/pull/2329)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-29
* Add Rules to disable various item functionalities and cleanup data types. ([#2225](https://github.com/EQEmu/Server/pull/2225)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-01
* Add Spells:BuffsFadeOnDeath. ([#2200](https://github.com/EQEmu/Server/pull/2200)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27
* Add Spells:IllusionsAlwaysPersist. ([#2199](https://github.com/EQEmu/Server/pull/2199)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27
* Add Toggle for Warrior Shielding ([#2496](https://github.com/EQEmu/Server/pull/2496)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-22
* Add adjustment for zone forage. ([#2330](https://github.com/EQEmu/Server/pull/2330)) ([fryguy503](https://github.com/fryguy503)) 2022-07-30
* Add rule for NPC Level Based Buff Restrictions. ([#2708](https://github.com/EQEmu/Server/pull/2708)) ([noudess](https://github.com/noudess)) 2023-01-15
* Add rule to allow players to permanently save chat channels to database, up to a limit. ([#2706](https://github.com/EQEmu/Server/pull/2706)) ([Valorith](https://github.com/Valorith)) 2023-01-19
* Change TradeskillUp Rules to be Floats ([#2674](https://github.com/EQEmu/Server/pull/2674)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-25
* Cleanup all unused rules. ([#2184](https://github.com/EQEmu/Server/pull/2184)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23
* Rule Gate Pet Zoning ([#2625](https://github.com/EQEmu/Server/pull/2625)) ([fryguy503](https://github.com/fryguy503)) 2022-12-07
* Rule to allow cap on % XP gain per kill ([#2667](https://github.com/EQEmu/Server/pull/2667)) ([Valorith](https://github.com/Valorith)) 2022-12-25
* Update logic checks everywhere for FVNoDropFlag. ([#2179](https://github.com/EQEmu/Server/pull/2179)) ([Quintinon](https://github.com/Quintinon)) 2022-07-30
### SQL
* Bugs Table Migration (#2602) ([#2559](https://github.com/EQEmu/Server/pull/2559)) ([joligario](https://github.com/joligario)) 2022-12-01
* Update 2023_01_15_merc_data.sql ([#2763](https://github.com/EQEmu/Server/pull/2763)) ([joligario](https://github.com/joligario)) 2023-01-20
### UCS
* Auto Client Reconnection ([#2154](https://github.com/EQEmu/Server/pull/2154)) ([Akkadius](https://github.com/Akkadius)) 2022-05-08
### Websocket
* Fix cpp20/gcc11 compile failure ([#2737](https://github.com/EQEmu/Server/pull/2737)) ([Akkadius](https://github.com/Akkadius)) 2023-01-15
### Zone Flags
* Use database connection, not content connection ([#2759](https://github.com/EQEmu/Server/pull/2759)) ([Akkadius](https://github.com/Akkadius)) 2023-01-19
+14 -20
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 14)
SET(CMAKE_CXX_STANDARD 20)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_EXTENSIONS OFF)
@@ -20,8 +20,10 @@ IF(MSVC)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
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)
@@ -121,8 +123,6 @@ ENDIF()
MESSAGE(STATUS "**************************************************")
#options
OPTION(EQEMU_DEPOP_INVALIDATES_CACHE "#repop invalidates the npc_types cache (will cause a larger database hit on #repop but is more convienent)." ON)
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,17 +176,13 @@ 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:
MySQL
MariaDB"
)
IF(DATABASE_LIBRARY_SELECTION STREQUAL "MySQL")
SET(DATABASE_LIBRARY_TYPE " MySQL")
SET(DATABASE_LIBRARY_LIBS ${MySQL_LIBRARIES})
@@ -217,7 +213,7 @@ IF(OpenSSL_FOUND AND MBEDTLS_FOUND)
OpenSSL
mbedTLS"
)
IF(TLS_LIBRARY_SELECTION STREQUAL "OpenSSL")
SET(TLS_LIBRARY_TYPE " OpenSSL")
SET(TLS_LIBRARY_ENABLED ON)
@@ -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})
@@ -357,12 +351,12 @@ ENDIF()
IF(LUA_LIBRARY_ENABLED)
OPTION(EQEMU_BUILD_LUA "Build Lua parser." ON)
IF(EQEMU_BUILD_LUA)
ADD_DEFINITIONS(-DLUA_EQEMU)
SET(ZONE_LIBS ${LUA_LIBRARY_LIBS})
INCLUDE_DIRECTORIES(SYSTEM "${LUA_LIBRARY_INCLUDE}")
OPTION(EQEMU_SANITIZE_LUA_LIBS "Sanitize Lua Libraries (Remove OS and IO standard libraries from being able to run)." ON)
IF(EQEMU_SANITIZE_LUA_LIBS)
ADD_DEFINITIONS(-DSANITIZE_LUA_LIBS)
@@ -373,7 +367,7 @@ ENDIF()
IF(PERL_LIBRARY_ENABLED)
OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON)
IF(EQEMU_BUILD_PERL)
SET(SERVER_LIBS ${SERVER_LIBS} ${PERL_LIBRARY_LIBS})
SET(SERVER_LIBS ${SERVER_LIBS} ${PERL_LIBRARY_LIBS} perlbind)
INCLUDE_DIRECTORIES(SYSTEM "${PERL_LIBRARY_INCLUDE}")
ADD_DEFINITIONS(-DEMBPERL)
ADD_DEFINITIONS(-DEMBPERL_PLUGIN)
@@ -410,13 +404,13 @@ IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_H
ADD_SUBDIRECTORY(libs)
ADD_SUBDIRECTORY(submodules/fmt)
ADD_SUBDIRECTORY(submodules/libuv)
IF(EQEMU_BUILD_ZLIB)
SET(ZLIB_COMPAT ON CACHE BOOL "Compile with zlib compatible API")
SET(ZLIB_ENABLE_TESTS OFF CACHE BOOL "Build test binaries")
ADD_SUBDIRECTORY(libs/zlibng)
ENDIF()
SET(RECASTNAVIGATION_DEMO OFF CACHE BOOL "Build demo")
SET(RECASTNAVIGATION_TESTS OFF CACHE BOOL "Build tests")
SET(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "Build examples")
-21
View File
@@ -1,21 +0,0 @@
version: 1.0.{build}
branches:
only:
- master
image: Visual Studio 2017
configuration: RelWithDebInfo
clone_folder: c:\projects\eqemu
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\" .."
build:
project: C:\projects\eqemu\build\EQEmu.sln
parallel: true
verbosity: minimal
after_build:
- cmd: >-
7z a build_x64-bots.zip C:\projects\eqemu\build\bin\RelWithDebInfo\*.exe C:\projects\eqemu\build\bin\RelWithDebInfo\*.dll C:\projects\eqemu\build\bin\RelWithDebInfo\*.pdb C:\projects\eqemu\build\libs\zlibng\RelWithDebInfo\*.dll
appveyor PushArtifact build_x64-bots.zip
-21
View File
@@ -1,21 +0,0 @@
version: 1.0.{build}
branches:
only:
- master
image: Visual Studio 2017
configuration: RelWithDebInfo
clone_folder: c:\projects\eqemu
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\" .."
build:
project: C:\projects\eqemu\build\EQEmu.sln
parallel: true
verbosity: minimal
after_build:
- cmd: >-
7z a build_x64-no-bots.zip C:\projects\eqemu\build\bin\RelWithDebInfo\*.exe C:\projects\eqemu\build\bin\RelWithDebInfo\*.dll C:\projects\eqemu\build\bin\RelWithDebInfo\*.pdb C:\projects\eqemu\build\libs\zlibng\RelWithDebInfo\*.dll
appveyor PushArtifact build_x64-no-bots.zip
+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
+16 -5
View File
@@ -25,11 +25,15 @@
#include "../../common/platform.h"
#include "../../common/crash.h"
#include "../../common/rulesys.h"
#include "../../common/string_util.h"
#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);
@@ -42,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");
@@ -84,6 +90,7 @@ int main(int argc, char **argv)
}
LogSys.SetDatabase(&database)
->SetLogPath(path.GetLogPath())
->LoadLogDatabaseSettings()
->StartFileLogs();
@@ -124,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;
@@ -206,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;
@@ -236,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;
@@ -269,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
+26 -15
View File
@@ -23,11 +23,15 @@
#include "../../common/platform.h"
#include "../../common/crash.h"
#include "../../common/rulesys.h"
#include "../../common/string_util.h"
#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);
@@ -39,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.");
@@ -81,6 +87,7 @@ int main(int argc, char **argv) {
}
LogSys.SetDatabase(&database)
->SetLogPath(path.GetLogPath())
->LoadLogDatabaseSettings()
->StartFileLogs();
@@ -125,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;
}
@@ -146,8 +154,8 @@ void ImportSpells(SharedDatabase *db) {
}
}
std::string escaped = ::EscapeString(buffer);
auto split = SplitString(escaped, '^');
std::string escaped = ::Strings::Escape(buffer);
auto split = Strings::Split(escaped, '^');
int line_columns = (int)split.size();
std::string sql;
@@ -214,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;
}
@@ -225,7 +234,7 @@ void ImportSkillCaps(SharedDatabase *db) {
char buffer[2048];
while(fgets(buffer, 2048, f)) {
auto split = SplitString(buffer, '^');
auto split = Strings::Split(buffer, '^');
if(split.size() < 4) {
continue;
@@ -249,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;
}
@@ -260,7 +270,7 @@ void ImportBaseData(SharedDatabase *db) {
char buffer[2048];
while(fgets(buffer, 2048, f)) {
auto split = SplitString(buffer, '^');
auto split = Strings::Split(buffer, '^');
if(split.size() < 10) {
continue;
@@ -294,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;
}
@@ -318,7 +329,7 @@ void ImportDBStrings(SharedDatabase *db) {
}
}
auto split = SplitString(buffer, '^');
auto split = Strings::Split(buffer, '^');
if(split.size() < 2) {
continue;
@@ -332,7 +343,7 @@ void ImportDBStrings(SharedDatabase *db) {
type = atoi(split[1].c_str());
if(split.size() >= 3) {
value = ::EscapeString(split[2]);
value = ::Strings::Escape(split[2]);
}
sql = StringFormat("INSERT INTO db_str(id, type, value) VALUES(%u, %u, '%s')",
+753 -731
View File
File diff suppressed because it is too large Load Diff
-190
View File
@@ -1,190 +0,0 @@
/*
* Boost Software License - Version 1.0 - August 17th, 2003
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
// EQ::Any is a modified version of Boost::Any and as such retains the Boost licensing.
#ifndef EQEMU_COMMON_ANY_H
#define EQEMU_COMMON_ANY_H
#include <algorithm>
#include <typeinfo>
namespace EQ
{
class Any
{
public:
Any()
: content(nullptr)
{
}
template<typename ValueType>
Any(const ValueType &value)
: content(new Holder<ValueType>(value))
{
}
Any(const Any &other)
: content(other.content ? other.content->clone() : 0)
{
}
~Any()
{
if(content)
delete content;
}
Any& swap(Any &rhs)
{
std::swap(content, rhs.content);
return *this;
}
template<typename ValueType>
Any& operator=(const ValueType &rhs)
{
Any(rhs).swap(*this);
return *this;
}
Any& operator=(Any rhs)
{
rhs.swap(*this);
return *this;
}
bool empty() const
{
return !content;
}
const std::type_info& type() const
{
return content ? content->type() : typeid(void);
}
class Placeholder
{
public:
virtual ~Placeholder()
{
}
virtual const std::type_info& type() const = 0;
virtual Placeholder* clone() const = 0;
};
template<typename ValueType>
class Holder : public Placeholder
{
public:
Holder(const ValueType &value)
: held(value)
{
}
virtual const std::type_info& type() const
{
return typeid(ValueType);
}
virtual Placeholder* clone() const
{
return new Holder(held);
}
ValueType held;
private:
Holder& operator=(const Holder&);
};
private:
template<typename ValueType>
friend ValueType* any_cast(Any*);
template<typename ValueType>
friend ValueType* unsafe_any_cast(Any*);
Placeholder* content;
};
class bad_any_cast : public std::bad_cast
{
public:
virtual const char * what() const throw()
{
return "DBI::bad_any_cast: failed conversion using DBI::any_cast";
}
};
template<typename ValueType>
ValueType* any_cast(Any* operand)
{
return operand &&
operand->type() == typeid(ValueType) ? &static_cast<Any::Holder<ValueType>*>(operand->content)->held : nullptr;
}
template<typename ValueType>
inline const ValueType* any_cast(const Any* operand)
{
return any_cast<ValueType>(const_cast<Any*>(operand));
}
template<typename ValueType>
ValueType any_cast(Any& operand)
{
typedef typename std::remove_reference<ValueType>::type nonref;
nonref* result = any_cast<nonref>(&operand);
if(!result)
throw bad_any_cast();
return *result;
}
template<typename ValueType>
inline ValueType any_cast(const Any& operand)
{
typedef typename std::remove_reference<ValueType>::type nonref;
return any_cast<const nonref&>(const_cast<Any&>(operand));
}
template<typename ValueType>
inline ValueType* unsafe_any_cast(Any* operand)
{
return &static_cast<Any::Holder<ValueType>*>(operand->content)->held;
}
template<typename ValueType>
inline const ValueType* unsafe_any_cast(const Any* operand)
{
return unsafe_any_cast<ValueType>(const_cast<Any*>(operand));
}
}
#endif
+8 -8
View File
@@ -23,18 +23,18 @@
BasePacket::BasePacket(const unsigned char *buf, uint32 len)
{
this->pBuffer=nullptr;
this->size=0;
this->_wpos = 0;
this->_rpos = 0;
this->timestamp.tv_sec = 0;
pBuffer=nullptr;
size=0;
_wpos = 0;
_rpos = 0;
timestamp.tv_sec = 0;
if (len>0) {
this->size=len;
size=len;
pBuffer= new unsigned char[len];
if (buf) {
memcpy(this->pBuffer,buf,len);
memcpy(pBuffer,buf,len);
} else {
memset(this->pBuffer,0,len);
memset(pBuffer,0,len);
}
}
}
+5 -5
View File
@@ -380,12 +380,12 @@ const char *GetClassIDName(uint8 class_id, uint8 level)
return "Merchant";
case DISCORD_MERCHANT:
return "Discord Merchant";
case ADVENTURERECRUITER:
case ADVENTURE_RECRUITER:
return "Adventure Recruiter";
case ADVENTUREMERCHANT:
case ADVENTURE_MERCHANT:
return "Adventure Merchant";
case CORPSE_CLASS:
return "Corpse Class";
case LDON_TREASURE:
return "LDoN Treasure";
case TRIBUTE_MASTER:
return "Tribute Master";
case GUILD_TRIBUTE_MASTER:
@@ -400,7 +400,7 @@ const char *GetClassIDName(uint8 class_id, uint8 level)
return "Fellowship Master";
case ALT_CURRENCY_MERCHANT:
return "Alternate Currency Merchant";
case MERCERNARY_MASTER:
case MERCENARY_MASTER:
return "Mercenary Liaison";
default:
return "Unknown";
+5 -5
View File
@@ -20,6 +20,7 @@
#include "../common/types.h"
#define NO_CLASS 0
#define WARRIOR 1
#define CLERIC 2
#define PALADIN 3
@@ -55,10 +56,9 @@
#define BANKER 40
#define MERCHANT 41
#define DISCORD_MERCHANT 59
#define ADVENTURERECRUITER 60
#define ADVENTUREMERCHANT 61
#define LDON_TREASURE 62 // objects you can use /open on first seen in LDONs
#define CORPSE_CLASS 62 // only seen on Danvi's Corpse in Akheva so far..
#define ADVENTURE_RECRUITER 60
#define ADVENTURE_MERCHANT 61
#define LDON_TREASURE 62 // objects you can use /open on first seen in LDONs, seen on Danvi's Corpse in Akheva
#define TRIBUTE_MASTER 63
#define GUILD_TRIBUTE_MASTER 64 // not sure
#define GUILD_BANKER 66
@@ -66,7 +66,7 @@
#define DARK_REIGN_MERCHANT 68
#define FELLOWSHIP_MASTER 69
#define ALT_CURRENCY_MERCHANT 70
#define MERCERNARY_MASTER 71
#define MERCENARY_MASTER 71
// player class values
+45
View File
@@ -22,6 +22,7 @@
#include "../database.h"
#include "../rulesys.h"
#include "../eqemu_logsys.h"
#include "../loottable.h"
#include "../repositories/content_flags_repository.h"
@@ -139,6 +140,50 @@ bool WorldContentService::IsContentFlagEnabled(const std::string &content_flag)
return false;
}
/**
* @param content_flag
* @return
*/
bool WorldContentService::IsContentFlagDisabled(const std::string &content_flag)
{
for (auto &f: GetContentFlags()) {
if (f.flag_name == content_flag && f.enabled == false) {
return true;
}
}
return false;
}
bool WorldContentService::DoesPassContentFiltering(const ContentFlags &f)
{
// if we're not set to (-1 All) then fail when we aren't within minimum expansion
if (f.min_expansion > Expansion::EXPANSION_ALL && current_expansion < f.min_expansion && current_expansion != -1) {
return false;
}
// if we're not set to (-1 All) then fail when we aren't within max expansion
if (f.max_expansion > Expansion::EXPANSION_ALL && current_expansion > f.max_expansion && current_expansion != -1) {
return false;
}
// if we don't have any enabled flag in enabled flags, we fail
for (const auto& flag: Strings::Split(f.content_flags)) {
if (!Strings::Contains(GetContentFlagsEnabled(), flag)) {
return false;
}
}
// if we don't have any disabled flag in disabled flags, we fail
for (const auto& flag: Strings::Split(f.content_flags_disabled)) {
if (!Strings::Contains(GetContentFlagsDisabled(), flag)) {
return false;
}
}
return true;
}
void WorldContentService::ReloadContentFlags()
{
std::vector<ContentFlagsRepository::ContentFlags> set_content_flags;
+7 -3
View File
@@ -23,6 +23,7 @@
#include <string>
#include <vector>
#include "../loottable.h"
#include "../repositories/content_flags_repository.h"
class Database;
@@ -53,7 +54,7 @@ namespace Expansion {
VeilOfAlaris,
RainOfFear,
CallOfTheForsaken,
TheDarkendSea,
TheDarkenedSea,
TheBrokenMirror,
EmpiresOfKunark,
RingOfScale,
@@ -126,7 +127,7 @@ public:
bool IsVeilOfAlarisEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::VeilOfAlaris || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsRainOfFearEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::RainOfFear || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsCallOfTheForsakenEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::CallOfTheForsaken || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsTheDarkendSeaEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheDarkendSea || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsTheDarkenedSeaEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheDarkenedSea || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsTheBrokenMirrorEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheBrokenMirror || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsEmpiresOfKunarkEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::EmpiresOfKunark || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsRingOfScaleEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::RingOfScale || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
@@ -154,7 +155,7 @@ public:
bool IsCurrentExpansionVeilOfAlaris() { return current_expansion == Expansion::ExpansionNumber::VeilOfAlaris; }
bool IsCurrentExpansionRainOfFear() { return current_expansion == Expansion::ExpansionNumber::RainOfFear; }
bool IsCurrentExpansionCallOfTheForsaken() { return current_expansion == Expansion::ExpansionNumber::CallOfTheForsaken; }
bool IsCurrentExpansionTheDarkendSea() { return current_expansion == Expansion::ExpansionNumber::TheDarkendSea; }
bool IsCurrentExpansionTheDarkenedSea() { return current_expansion == Expansion::ExpansionNumber::TheDarkenedSea; }
bool IsCurrentExpansionTheBrokenMirror() { return current_expansion == Expansion::ExpansionNumber::TheBrokenMirror; }
bool IsCurrentExpansionEmpiresOfKunark() { return current_expansion == Expansion::ExpansionNumber::EmpiresOfKunark; }
bool IsCurrentExpansionRingOfScale() { return current_expansion == Expansion::ExpansionNumber::RingOfScale; }
@@ -165,10 +166,13 @@ public:
std::vector<std::string> GetContentFlagsEnabled();
std::vector<std::string> GetContentFlagsDisabled();
bool IsContentFlagEnabled(const std::string& content_flag);
bool IsContentFlagDisabled(const std::string& content_flag);
void SetContentFlags(std::vector<ContentFlagsRepository::ContentFlags> content_flags);
void ReloadContentFlags();
WorldContentService * SetExpansionContext();
bool DoesPassContentFiltering(const ContentFlags& f);
WorldContentService * SetDatabase(Database *database);
Database *GetDatabase() const;
+145 -9
View File
@@ -1,6 +1,98 @@
#include "global_define.h"
#include "eqemu_logsys.h"
#include "crash.h"
#include "strings.h"
#include "process/process.h"
#include "http/httplib.h"
#include "http/uri.h"
#include "json/json.h"
#include "version.h"
#include "eqemu_config.h"
#include "serverinfo.h"
#include "rulesys.h"
#include "platform.h"
#include <cstdio>
#include <vector>
#if WINDOWS
#define popen _popen
#endif
void SendCrashReport(const std::string &crash_report)
{
// can configure multiple endpoints if need be
std::vector<std::string> endpoints = {
"http://spire.akkadius.com/api/v1/analytics/server-crash-report",
// "http://localhost:3010/api/v1/analytics/server-crash-report", // development
};
auto config = EQEmuConfig::get();
for (auto &e: endpoints) {
uri u(e);
std::string base_url = fmt::format("{}://{}", u.get_scheme(), u.get_host());
if (u.get_port()) {
base_url += fmt::format(":{}", u.get_port());
}
// client
httplib::Client r(base_url);
r.set_connection_timeout(1, 0);
r.set_read_timeout(1, 0);
r.set_write_timeout(1, 0);
httplib::Headers headers = {
{"Content-Type", "application/json"}
};
// os info
auto os = EQ::GetOS();
auto cpus = EQ::GetCPUs();
auto process_id = EQ::GetPID();
auto rss = EQ::GetRSS() / 1048576.0;
auto uptime = static_cast<uint32>(EQ::GetUptime());
// payload
Json::Value p;
p["platform_name"] = GetPlatformName();
p["crash_report"] = crash_report;
p["server_version"] = CURRENT_VERSION;
p["compile_date"] = COMPILE_DATE;
p["compile_time"] = COMPILE_TIME;
p["server_name"] = config->LongName;
p["server_short_name"] = config->ShortName;
p["uptime"] = uptime;
p["os_machine"] = os.machine;
p["os_release"] = os.release;
p["os_version"] = os.version;
p["os_sysname"] = os.sysname;
p["process_id"] = process_id;
p["rss_memory"] = rss;
p["cpus"] = cpus.size();
p["origination_info"] = "";
if (!LogSys.origination_info.zone_short_name.empty()) {
p["origination_info"] = fmt::format(
"{} ({}) instance_id [{}]",
LogSys.origination_info.zone_short_name,
LogSys.origination_info.zone_long_name,
LogSys.origination_info.instance_id
);
}
std::stringstream payload;
payload << p;
if (auto res = r.Post(e, payload.str(), "application/json")) {
if (res->status == 200) {
LogInfo("Sent crash report");
}
else {
LogError("Failed to send crash report to [{}]", e);
}
}
}
}
#if defined(_WINDOWS) && defined(CRASH_LOGGING)
#include "StackWalker.h"
@@ -12,22 +104,30 @@ public:
EQEmuStackWalker(DWORD dwProcessId, HANDLE hProcess) : StackWalker(dwProcessId, hProcess) { }
virtual void OnOutput(LPCSTR szText) {
char buffer[4096];
for(int i = 0; i < 4096; ++i) {
if(szText[i] == 0) {
for (int i = 0; i < 4096; ++i) {
if (szText[i] == 0) {
buffer[i] = '\0';
break;
}
if(szText[i] == '\n' || szText[i] == '\r') {
if (szText[i] == '\n' || szText[i] == '\r') {
buffer[i] = ' ';
} else {
}
else {
buffer[i] = szText[i];
}
}
std::string line = buffer;
_lines.push_back(line);
Log(Logs::General, Logs::Crash, buffer);
StackWalker::OnOutput(szText);
}
const std::vector<std::string>& const GetLines() { return _lines; }
private:
std::vector<std::string> _lines;
};
LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo)
@@ -101,7 +201,20 @@ LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo)
if(EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode)
{
EQEmuStackWalker sw; sw.ShowCallstack(GetCurrentThread(), ExceptionInfo->ContextRecord);
EQEmuStackWalker sw;
sw.ShowCallstack(GetCurrentThread(), ExceptionInfo->ContextRecord);
if (RuleB(Analytics, CrashReporting)) {
std::string crash_report;
auto& lines = sw.GetLines();
for (auto& line : lines) {
crash_report += line;
crash_report += "\n";
}
SendCrashReport(crash_report);
}
}
return EXCEPTION_EXECUTE_HANDLER;
@@ -125,9 +238,27 @@ void set_exception_handler() {
void print_trace()
{
auto uid = geteuid();
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"
);
std::exit(1);
}
std::string temp_output_file = "/tmp/dump-output";
auto uid = geteuid();
std::string temp_output_file = fmt::format("/tmp/dump-output-{}", Strings::Random(10));
// check for passwordless sudo if not root
if (uid != 0) {
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."
);
std::exit(1);
}
}
char pid_buf[30];
sprintf(pid_buf, "%d", getpid());
@@ -136,7 +267,6 @@ void print_trace()
int child_pid = fork();
if (!child_pid) {
int fd = open(temp_output_file.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
dup2(fd, 1); // redirect output to stderr
fprintf(stdout, "stack trace for %s pid=%s\n", name_buf, pid_buf);
if (uid == 0) {
@@ -151,16 +281,22 @@ 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);
std::string crash_report;
for (std::string line; getline(input, line);) {
LogCrash("{}", line);
crash_report += fmt::format("{}\n", line);
}
std::remove(temp_output_file.c_str());
if (RuleB(Analytics, CrashReporting)) {
SendCrashReport(crash_report);
}
exit(1);
}
+255 -344
View File
@@ -45,11 +45,14 @@
#include "database.h"
#include "eq_packet_structs.h"
#include "extprofile.h"
#include "string_util.h"
#include "strings.h"
#include "database_schema.h"
#include "http/httplib.h"
#include "http/uri.h"
#include "repositories/zone_repository.h"
#include "zone_store.h"
extern Client client;
Database::Database () {
@@ -68,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;
}
}
@@ -92,112 +95,123 @@ Database::~Database()
*/
uint32 Database::CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus) {
if(strlen(name) >= 50 || strlen(password) >= 50)
if (strlen(name) >= 50 || strlen(password) >= 50)
return(0);
char tmpUN[100];
char tmpPW[100];
char temporary_username[100];
char temporary_password[100];
DoEscapeString(tmpUN, name, strlen(name));
DoEscapeString(tmpPW, password, strlen(password));
DoEscapeString(temporary_username, name, strlen(name));
DoEscapeString(temporary_password, password, strlen(password));
std::string query = StringFormat("SELECT id, status FROM account WHERE `name`='%s' AND ls_id='%s' AND password is not null "
"and length(password) > 0 and (password='%s' or password=MD5('%s'))",
tmpUN, EscapeString(loginserver).c_str(), tmpPW, tmpPW);
std::string query = fmt::format(
"SELECT id, status FROM account WHERE `name` = '{}' AND ls_id = '{}' AND password is NOT NULL "
"AND length(password) > 0 AND (password = '{}' OR password = MD5('{}'))",
temporary_username,
Strings::Escape(loginserver),
temporary_password,
temporary_password
);
auto results = QueryDatabase(query);
if (!results.Success())
{
if (!results.Success() || !results.RowCount()) {
return 0;
}
if(results.RowCount() == 0)
return 0;
auto row = results.begin();
uint32 id = atoi(row[0]);
auto id = std::stoul(row[0]);
if (oStatus)
*oStatus = atoi(row[1]);
if (oStatus) {
*oStatus = std::stoi(row[1]);
}
return id;
}
//Get Banned IP Address List - Only return false if the incoming connection's IP address is not present in the banned_ips table.
bool Database::CheckBannedIPs(const char* loginIP)
bool Database::CheckBannedIPs(std::string login_ip)
{
std::string query = StringFormat("SELECT ip_address FROM banned_ips WHERE ip_address='%s'", loginIP);
auto query = fmt::format(
"SELECT ip_address FROM banned_ips WHERE ip_address = '{}'",
login_ip
);
auto results = QueryDatabase(query);
if (!results.Success())
{
if (!results.Success() || results.RowCount() != 0) {
return true;
}
if (results.RowCount() != 0)
return true;
return false;
}
bool Database::AddBannedIP(char* bannedIP, const char* notes) {
std::string query = StringFormat("INSERT into banned_ips SET ip_address='%s', notes='%s'", bannedIP, notes);
bool Database::AddBannedIP(std::string banned_ip, std::string notes) {
auto query = fmt::format(
"INSERT into banned_ips SET ip_address = '{}', notes = '{}'",
Strings::Escape(banned_ip),
Strings::Escape(notes)
);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
return true;
}
bool Database::CheckGMIPs(const char* ip_address, uint32 account_id) {
std::string query = StringFormat("SELECT * FROM `gm_ips` WHERE `ip_address` = '%s' AND `account_id` = %i", ip_address, account_id);
bool Database::CheckGMIPs(std::string login_ip, uint32 account_id) {
auto query = fmt::format(
"SELECT * FROM `gm_ips` WHERE `ip_address` = '{}' AND `account_id` = {}",
login_ip,
account_id
);
auto results = QueryDatabase(query);
if (!results.Success())
if (!results.Success()) {
return false;
}
if (results.RowCount() == 1)
if (results.RowCount() == 1) {
return true;
}
return false;
}
bool Database::AddGMIP(char* ip_address, char* name) {
std::string query = StringFormat("INSERT into `gm_ips` SET `ip_address` = '%s', `name` = '%s'", ip_address, name);
auto results = QueryDatabase(query);
return results.Success();
}
void Database::LoginIP(uint32 AccountID, const char* LoginIP) {
std::string query = StringFormat("INSERT INTO account_ip SET accid=%i, ip='%s' ON DUPLICATE KEY UPDATE count=count+1, lastused=now()", AccountID, LoginIP);
void Database::LoginIP(uint32 account_id, std::string login_ip) {
auto query = fmt::format(
"INSERT INTO account_ip SET accid = {}, ip = '{}' ON DUPLICATE KEY UPDATE count=count+1, lastused=now()",
account_id,
login_ip
);
QueryDatabase(query);
}
int16 Database::CheckStatus(uint32 account_id)
{
std::string query = StringFormat(
"SELECT `status`, TIMESTAMPDIFF(SECOND, NOW(), `suspendeduntil`) FROM `account` WHERE `id` = %i",
account_id);
auto query = fmt::format(
"SELECT `status`, TIMESTAMPDIFF(SECOND, NOW(), `suspendeduntil`) FROM `account` WHERE `id` = {}",
account_id
);
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if (results.RowCount() != 1)
if (!results.Success() || results.RowCount() != 1) {
return 0;
}
auto row = results.begin();
int16 status = atoi(row[0]);
int16 status = std::stoi(row[0]);
int32 date_diff = 0;
if (row[1] != nullptr)
date_diff = atoi(row[1]);
if (row[1]) {
date_diff = std::stoi(row[1]);
}
if (date_diff > 0)
if (date_diff > 0) {
return -1;
}
return status;
}
@@ -267,7 +281,7 @@ bool Database::DeleteAccount(const char* name, const char *loginserver) {
}
bool Database::SetLocalPassword(uint32 accid, const char* password) {
std::string query = StringFormat("UPDATE account SET password=MD5('%s') where id=%i;", EscapeString(password).c_str(), accid);
std::string query = StringFormat("UPDATE account SET password=MD5('%s') where id=%i;", Strings::Escape(password).c_str(), accid);
auto results = QueryDatabase(query);
@@ -307,9 +321,7 @@ bool Database::SetAccountStatus(const std::string& account_name, int16 status)
LogInfo("Account [{}] is attempting to be set to status [{}]", account_name, status);
std::string query = fmt::format(
SQL(
UPDATE account SET status = {} WHERE name = '{}'
),
"UPDATE account SET status = {} WHERE name = '{}'",
status,
account_name
);
@@ -364,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;
}
@@ -378,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;
}
@@ -608,8 +636,8 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
")",
character_id, // " id, "
account_id, // " account_id, "
EscapeString(pp->name).c_str(), // " `name`, "
EscapeString(pp->last_name).c_str(), // " last_name, "
Strings::Escape(pp->name).c_str(), // " `name`, "
Strings::Escape(pp->last_name).c_str(), // " last_name, "
pp->gender, // " gender, "
pp->race, // " race, "
pp->class_, // " class, "
@@ -633,8 +661,8 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
pp->ability_number, // " ability_number, "
pp->ability_time_minutes, // " ability_time_minutes, "
pp->ability_time_hours, // " ability_time_hours, "
EscapeString(pp->title).c_str(), // " title, "
EscapeString(pp->suffix).c_str(), // " suffix, "
Strings::Escape(pp->title).c_str(), // " title, "
Strings::Escape(pp->suffix).c_str(), // " suffix, "
pp->exp, // " exp, "
pp->points, // " points, "
pp->mana, // " mana, "
@@ -770,7 +798,7 @@ uint32 Database::GetCharacterID(const char *name) {
Zero will also be returned if there is a database error.
*/
uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) {
std::string query = StringFormat("SELECT `account_id`, `id` FROM `character_data` WHERE name='%s'", EscapeString(charname).c_str());
std::string query = StringFormat("SELECT `account_id`, `id` FROM `character_data` WHERE name='%s'", Strings::Escape(charname).c_str());
auto results = QueryDatabase(query);
@@ -807,36 +835,34 @@ uint32 Database::GetAccountIDByChar(uint32 char_id) {
return atoi(row[0]);
}
uint32 Database::GetAccountIDByName(const char* accname, const char *loginserver, int16* status, uint32* lsid) {
if (!isAlphaNumeric(accname))
uint32 Database::GetAccountIDByName(std::string account_name, std::string loginserver, int16* status, uint32* lsid) {
if (!isAlphaNumeric(account_name.c_str())) {
return 0;
}
std::string query = StringFormat("SELECT `id`, `status`, `lsaccount_id` FROM `account` WHERE `name` = '%s' AND `ls_id`='%s' LIMIT 1",
EscapeString(accname).c_str(), EscapeString(loginserver).c_str());
auto query = fmt::format(
"SELECT `id`, `status`, `lsaccount_id` FROM `account` WHERE `name` = '{}' AND `ls_id` = '{}' LIMIT 1",
Strings::Escape(account_name),
Strings::Escape(loginserver)
);
auto results = QueryDatabase(query);
if (!results.Success()) {
if (!results.Success() || !results.RowCount()) {
return 0;
}
if (results.RowCount() != 1)
return 0;
auto row = results.begin();
auto account_id = std::stoul(row[0]);
uint32 id = atoi(row[0]);
if (status)
*status = atoi(row[1]);
if (lsid) {
if (row[2])
*lsid = atoi(row[2]);
else
*lsid = 0;
if (status) {
*status = static_cast<int16>(std::stoi(row[1]));
}
return id;
if (lsid) {
*lsid = row[2] ? std::stoul(row[2]) : 0;
}
return account_id;
}
void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID) {
@@ -949,6 +975,8 @@ bool Database::LoadVariables() {
varcache.Add(key, value);
}
LogInfo("Loaded [{}] variable(s)", Strings::Commify(std::to_string(results.RowCount())));
return true;
}
@@ -973,8 +1001,8 @@ bool Database::GetVariable(std::string varname, std::string &varvalue)
bool Database::SetVariable(const std::string varname, const std::string &varvalue)
{
std::string escaped_name = EscapeString(varname);
std::string escaped_value = EscapeString(varvalue);
std::string escaped_name = Strings::Escape(varname);
std::string escaped_value = Strings::Escape(varvalue);
std::string query = StringFormat("Update variables set value='%s' WHERE varname like '%s'", escaped_value.c_str(), escaped_name.c_str());
auto results = QueryDatabase(query);
@@ -997,110 +1025,16 @@ bool Database::SetVariable(const std::string varname, const std::string &varvalu
return true;
}
// Get zone starting points from DB
bool Database::GetSafePoints(const char* zone_short_name, uint32 instance_version, float* safe_x, float* safe_y, float* safe_z, float* safe_heading, int16* min_status, uint8* min_level, char *flag_needed) {
if (zone_short_name == nullptr)
return false;
std::string query = fmt::format(
SQL(
SELECT
`safe_x`, `safe_y`, `safe_z`, `safe_heading`, `min_status`, `min_level`, `flag_needed`
FROM
zone
WHERE
`short_name` = '{}'
AND
(`version` = {} OR `version` = 0)
ORDER BY `version` DESC
), zone_short_name, instance_version
void Database::SetAccountCRCField(uint32 account_id, std::string field_name, uint64 checksum)
{
QueryDatabase(
fmt::format(
"UPDATE `account` SET `{}` = '{}' WHERE `id` = {}",
field_name,
checksum,
account_id
)
);
auto results = QueryDatabase(query);
if (!results.Success())
return false;
if (results.RowCount() == 0)
return false;
auto row = results.begin();
if (safe_x != nullptr)
*safe_x = atof(row[0]);
if (safe_y != nullptr)
*safe_y = atof(row[1]);
if (safe_z != nullptr)
*safe_z = atof(row[2]);
if (safe_heading != nullptr)
*safe_heading = atof(row[3]);
if (min_status != nullptr)
*min_status = atoi(row[4]);
if (min_level != nullptr)
*min_level = atoi(row[5]);
if (flag_needed != nullptr)
strcpy(flag_needed, row[6]);
return true;
}
bool Database::GetZoneLongName(const char* short_name, char** long_name, char* file_name, float* safe_x, float* safe_y, float* safe_z, uint32* graveyard_id, uint32* maxclients) {
std::string query = StringFormat("SELECT long_name, file_name, safe_x, safe_y, safe_z, graveyard_id, maxclients FROM zone WHERE short_name='%s' AND version=0", short_name);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
if (results.RowCount() == 0)
return false;
auto row = results.begin();
if (long_name != nullptr)
*long_name = strcpy(new char[strlen(row[0])+1], row[0]);
if (file_name != nullptr) {
if (row[1] == nullptr)
strcpy(file_name, short_name);
else
strcpy(file_name, row[1]);
}
if (safe_x != nullptr)
*safe_x = atof(row[2]);
if (safe_y != nullptr)
*safe_y = atof(row[3]);
if (safe_z != nullptr)
*safe_z = atof(row[4]);
if (graveyard_id != nullptr)
*graveyard_id = atoi(row[5]);
if (maxclients != nullptr)
*maxclients = atoi(row[6]);
return true;
}
uint32 Database::GetZoneGraveyardID(uint32 zone_id, uint32 version) {
std::string query = StringFormat("SELECT graveyard_id FROM zone WHERE zoneidnumber='%u' AND (version=%i OR version=0) ORDER BY version DESC", zone_id, version);
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
}
bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid, float* graveyard_x, float* graveyard_y, float* graveyard_z, float* graveyard_heading) {
@@ -1131,108 +1065,74 @@ bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zon
return true;
}
uint8 Database::GetPEQZone(uint32 zoneID, uint32 version){
uint8 Database::GetPEQZone(uint32 zone_id, uint32 version){
std::string query = StringFormat("SELECT peqzone from zone where zoneidnumber='%i' AND (version=%i OR version=0) ORDER BY version DESC", zoneID, version);
auto results = QueryDatabase(query);
auto z = GetZoneVersionWithFallback(zone_id, version);
if (!results.Success()) {
return 0;
}
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
return z ? z->peqzone : 0;
}
bool Database::CheckNameFilter(const char* name, bool surname)
bool Database::CheckNameFilter(std::string name, bool surname)
{
std::string str_name = name;
name = Strings::ToLower(name);
// the minimum 4 is enforced by the client too
if (!name || strlen(name) < 4)
{
if (name.empty() || name.size() < 4) {
return false;
}
// Given name length is enforced by the client too
if (!surname && strlen(name) > 15)
{
if (!surname && name.size() > 15) {
return false;
}
for (size_t i = 0; i < str_name.size(); i++)
{
if(!isalpha(str_name[i]))
{
for (size_t i = 0; i < name.size(); i++) {
if (!isalpha(name[i])) {
return false;
}
}
for(size_t x = 0; x < str_name.size(); ++x)
{
str_name[x] = tolower(str_name[x]);
}
char c = '\0';
uint8 num_c = 0;
for(size_t x = 0; x < str_name.size(); ++x)
{
if(str_name[x] == c)
{
for (size_t x = 0; x < name.size(); ++x) {
if (name[x] == c) {
num_c++;
}
else
{
} else {
num_c = 1;
c = str_name[x];
c = name[x];
}
if(num_c > 2)
{
if (num_c > 2) {
return false;
}
}
std::string query("SELECT name FROM name_filter");
std::string query = "SELECT name FROM name_filter";
auto results = QueryDatabase(query);
if (!results.Success())
{
// false through to true? shouldn't it be falls through to false?
if (!results.Success()) {
return true;
}
for (auto row = results.begin();row != results.end();++row)
{
std::string current_row = row[0];
for(size_t x = 0; x < current_row.size(); ++x)
current_row[x] = tolower(current_row[x]);
if(str_name.find(current_row) != std::string::npos)
for (auto row : results) {
std::string current_row = Strings::ToLower(row[0]);
if (name.find(current_row) != std::string::npos) {
return false;
}
}
return true;
}
bool Database::AddToNameFilter(const char* name) {
std::string query = StringFormat("INSERT INTO name_filter (name) values ('%s')", name);
bool Database::AddToNameFilter(std::string name) {
auto query = fmt::format(
"INSERT INTO name_filter (name) values ('{}')",
name
);
auto results = QueryDatabase(query);
if (!results.Success())
{
if (!results.Success() || !results.RowsAffected()) {
return false;
}
if (results.RowsAffected() == 0)
return false;
return true;
}
@@ -1320,16 +1220,16 @@ bool Database::UpdateName(const char* oldname, const char* newname) {
}
// If the name is used or an error occurs, it returns false, otherwise it returns true
bool Database::CheckUsedName(const char* name) {
std::string query = StringFormat("SELECT `id` FROM `character_data` WHERE `name` = '%s'", name);
bool Database::CheckUsedName(std::string name) {
auto query = fmt::format(
"SELECT `id` FROM `character_data` WHERE `name` = '{}'",
name
);
auto results = QueryDatabase(query);
if (!results.Success()) {
if (!results.Success() || results.RowCount()) {
return false;
}
if (results.RowCount() > 0)
return false;
return true;
}
@@ -1487,41 +1387,25 @@ uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16
return base_cap;
}
uint32 Database::GetCharacterInfo(
const char *iName,
uint32 *oAccID,
uint32 *oZoneID,
uint32 *oInstanceID,
float *oX,
float *oY,
float *oZ
)
uint32 Database::GetCharacterInfo(std::string character_name, uint32 *account_id, uint32 *zone_id, uint32 *instance_id)
{
std::string query = StringFormat(
"SELECT `id`, `account_id`, `zone_id`, `zone_instance`, `x`, `y`, `z` FROM `character_data` WHERE `name` = '%s'",
EscapeString(iName).c_str()
auto query = fmt::format(
"SELECT `id`, `account_id`, `zone_id`, `zone_instance` FROM `character_data` WHERE `name` = '{}'",
Strings::Escape(character_name)
);
auto results = QueryDatabase(query);
if (!results.Success()) {
if (!results.Success() || !results.RowCount()) {
return 0;
}
if (results.RowCount() != 1) {
return 0;
}
auto row = results.begin();
auto character_id = std::stoul(row[0]);
*account_id = std::stoul(row[1]);
*zone_id = std::stoul(row[2]);
*instance_id = std::stoul(row[3]);
auto row = results.begin();
uint32 charid = atoi(row[0]);
if (oAccID) { *oAccID = atoi(row[1]); }
if (oZoneID) { *oZoneID = atoi(row[2]); }
if (oInstanceID) { *oInstanceID = atoi(row[3]); }
if (oX) { *oX = atof(row[4]); }
if (oY) { *oY = atof(row[5]); }
if (oZ) { *oZ = atof(row[6]); }
return charid;
return character_id;
}
bool Database::UpdateLiveChar(char* charname, uint32 account_id) {
@@ -1580,7 +1464,7 @@ void Database::AddReport(std::string who, std::string against, std::string lines
auto escape_str = new char[lines.size() * 2 + 1];
DoEscapeString(escape_str, lines.c_str(), lines.size());
std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", EscapeString(who).c_str(), EscapeString(against).c_str(), escape_str);
std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", Strings::Escape(who).c_str(), Strings::Escape(against).c_str(), escape_str);
QueryDatabase(query);
safe_delete_array(escape_str);
}
@@ -1645,33 +1529,40 @@ uint32 Database::GetGroupID(const char* name){
return atoi(row[0]);
}
/* Is this really getting used properly... A half implementation ? Akkadius */
char* Database::GetGroupLeaderForLogin(const char* name, char* leaderbuf) {
strcpy(leaderbuf, "");
std::string Database::GetGroupLeaderForLogin(std::string character_name) {
uint32 group_id = 0;
std::string query = StringFormat("SELECT `groupid` FROM `group_id` WHERE `name` = '%s'", name);
auto query = fmt::format(
"SELECT `groupid` FROM `group_id` WHERE `name` = '{}'",
character_name
);
auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row)
if (row[0])
group_id = atoi(row[0]);
if (results.Success() && results.RowCount()) {
auto row = results.begin();
group_id = std::stoul(row[0]);
}
if (group_id == 0)
return leaderbuf;
if (!group_id) {
return std::string();
}
query = StringFormat("SELECT `leadername` FROM `group_leaders` WHERE `gid` = '%u' LIMIT 1", group_id);
query = fmt::format(
"SELECT `leadername` FROM `group_leaders` WHERE `gid` = {} LIMIT 1",
group_id
);
results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row)
if (row[0])
strcpy(leaderbuf, row[0]);
if (results.Success() && results.RowCount()) {
auto row = results.begin();
return row[0];
}
return leaderbuf;
return std::string();
}
void Database::SetGroupLeaderName(uint32 gid, const char* name) {
std::string query = StringFormat("UPDATE group_leaders SET leadername = '%s' WHERE gid = %u", EscapeString(name).c_str(), gid);
std::string query = StringFormat("UPDATE group_leaders SET leadername = '%s' WHERE gid = %u", Strings::Escape(name).c_str(), gid);
auto result = QueryDatabase(query);
if(result.RowsAffected() != 0) {
@@ -1679,7 +1570,7 @@ void Database::SetGroupLeaderName(uint32 gid, const char* name) {
}
query = StringFormat("REPLACE INTO group_leaders(gid, leadername, marknpc, leadershipaa, maintank, assist, puller, mentoree, mentor_percent) VALUES(%u, '%s', '', '', '', '', '', '', '0')",
gid, EscapeString(name).c_str());
gid, Strings::Escape(name).c_str());
result = QueryDatabase(query);
if(!result.Success()) {
@@ -2262,43 +2153,48 @@ bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year
}
int Database::GetIPExemption(std::string account_ip) {
std::string query = StringFormat("SELECT `exemption_amount` FROM `ip_exemptions` WHERE `exemption_ip` = '%s'", account_ip.c_str());
auto results = QueryDatabase(query);
if (results.Success() && results.RowCount() > 0) {
auto row = results.begin();
return atoi(row[0]);
}
return RuleI(World, MaxClientsPerIP);
}
void Database::SetIPExemption(std::string account_ip, int exemption_amount) {
std::string query = fmt::format(
"SELECT `exemption_id` FROM `ip_exemptions` WHERE `exemption_ip` = '{}'",
auto query = fmt::format(
"SELECT `exemption_amount` FROM `ip_exemptions` WHERE `exemption_ip` = '{}'",
account_ip
);
auto results = QueryDatabase(query);
uint32 exemption_id = 0;
if (results.Success() && results.RowCount() > 0) {
auto row = results.begin();
exemption_id = atoi(row[0]);
if (!results.Success() || !results.RowCount()) {
return RuleI(World, MaxClientsPerIP);
}
auto row = results.begin();
return std::stoi(row[0]);
}
void Database::SetIPExemption(std::string account_ip, int exemption_amount) {
auto query = fmt::format(
"SELECT `exemption_id` FROM `ip_exemptions` WHERE `exemption_ip` = '{}'",
account_ip
);
uint32 exemption_id = 0;
auto results = QueryDatabase(query);
if (results.Success() && results.RowCount()) {
auto row = results.begin();
exemption_id = std::stoul(row[0]);
}
query = fmt::format(
"INSERT INTO `ip_exemptions` (`exemption_ip`, `exemption_amount`) VALUES ('{}', {})",
account_ip,
exemption_amount
);
if (exemption_id != 0) {
if (exemption_id) {
query = fmt::format(
"UPDATE `ip_exemptions` SET `exemption_amount` = {} WHERE `exemption_ip` = '{}'",
exemption_amount,
account_ip
);
}
QueryDatabase(query);
}
@@ -2321,9 +2217,9 @@ int Database::GetInstanceID(uint32 char_id, uint32 zone_id) {
* @return
*/
bool Database::CopyCharacter(
std::string source_character_name,
std::string destination_character_name,
std::string destination_account_name
const std::string& source_character_name,
const std::string& destination_character_name,
const std::string& destination_account_name
)
{
auto results = QueryDatabase(
@@ -2335,6 +2231,7 @@ bool Database::CopyCharacter(
if (results.RowCount() == 0) {
LogError("No character found with name [{}]", source_character_name);
return false;
}
auto row = results.begin();
@@ -2349,6 +2246,7 @@ bool Database::CopyCharacter(
if (results.RowCount() == 0) {
LogError("No account found with name [{}]", destination_account_name);
return false;
}
row = results.begin();
@@ -2380,7 +2278,7 @@ bool Database::CopyCharacter(
results = QueryDatabase(
fmt::format(
"SELECT {} FROM {} WHERE {} = {}",
implode(",", wrap(columns, "`")),
Strings::Implode(",", Strings::Wrap(columns, "`")),
table_name,
character_id_column_name,
source_character_id
@@ -2416,7 +2314,7 @@ bool Database::CopyCharacter(
std::vector<std::string> insert_rows;
for (auto &r: new_rows) {
std::string insert_row = "(" + implode(",", wrap(r, "'")) + ")";
std::string insert_row = "(" + Strings::Implode(",", Strings::Wrap(r, "'")) + ")";
insert_rows.emplace_back(insert_row);
}
@@ -2434,8 +2332,8 @@ bool Database::CopyCharacter(
fmt::format(
"INSERT INTO {} ({}) VALUES {}",
table_name,
implode(",", wrap(columns, "`")),
implode(",", insert_rows)
Strings::Implode(",", Strings::Wrap(columns, "`")),
Strings::Implode(",", insert_rows)
)
);
@@ -2458,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(),
@@ -2487,8 +2385,8 @@ void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string ur
if (auto res = cli.Get(request_uri.get_path().c_str())) {
if (res->status == 200) {
for (auto &s: SplitString(res->body, ';')) {
if (!trim(s).empty()) {
for (auto &s: Strings::Split(res->body, ';')) {
if (!Strings::Trim(s).empty()) {
auto results = QueryDatabase(s);
if (!results.ErrorMessage().empty()) {
LogError("Error sourcing SQL [{}]", results.ErrorMessage());
@@ -2512,7 +2410,20 @@ 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());
}
}
uint8 Database::GetMinStatus(uint32 zone_id, uint32 instance_version)
{
auto zones = ZoneRepository::GetWhere(
*this,
fmt::format(
"zoneidnumber = {} AND (version = {} OR version = 0) ORDER BY version DESC LIMIT 1",
zone_id,
instance_version
)
);
return !zones.empty() ? zones[0].min_status : 0;
}
+28 -31
View File
@@ -88,7 +88,6 @@ public:
/* Character Creation */
bool AddToNameFilter(const char *name);
bool CreateCharacter(
uint32 account_id,
char *name,
@@ -114,25 +113,25 @@ public:
bool SetMQDetectionFlag(const char *accountname, const char *charactername, const std::string &hacked, const char *zone);
bool UpdateName(const char *oldname, const char *newname);
bool CopyCharacter(
std::string source_character_name,
std::string destination_character_name,
std::string destination_account_name
const std::string& source_character_name,
const std::string& destination_character_name,
const std::string& destination_account_name
);
/* General Information Queries */
bool AddBannedIP(char* bannedIP, const char* notes); //Add IP address to the banned_ips table.
bool AddGMIP(char* ip_address, char* name);
bool CheckBannedIPs(const char* loginIP); //Check incoming connection against banned IP table.
bool CheckGMIPs(const char* loginIP, uint32 account_id);
bool CheckNameFilter(const char* name, bool surname = false);
bool CheckUsedName(const char* name);
bool AddBannedIP(std::string banned_ip, std::string notes); //Add IP address to the banned_ips table.
bool AddToNameFilter(std::string name);
bool CheckBannedIPs(std::string login_ip); //Check incoming connection against banned IP table.
bool CheckGMIPs(std::string login_ip, uint32 account_id);
bool CheckNameFilter(std::string name, bool surname = false);
bool CheckUsedName(std::string name);
uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0);
uint32 GetAccountIDByChar(uint32 char_id);
uint32 GetAccountIDByName(const char* accname, const char *loginserver, int16* status = 0, uint32* lsid = 0);
uint32 GetAccountIDByName(std::string account_name, std::string loginserver, int16* status = 0, uint32* lsid = 0);
uint32 GetCharacterID(const char *name);
uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0, float* oX = 0, float* oY = 0, float* oZ = 0);
uint32 GetCharacterInfo(std::string character_name, uint32 *account_id, uint32 *zone_id, uint32 *instance_id);
uint32 GetGuildIDByCharID(uint32 char_id);
uint32 GetGroupIDByCharID(uint32 char_id);
uint32 GetRaidIDByCharID(uint32 char_id);
@@ -142,35 +141,34 @@ public:
std::string GetCharNameByID(uint32 char_id);
std::string GetNPCNameByID(uint32 npc_id);
std::string GetCleanNPCNameByID(uint32 npc_id);
void LoginIP(uint32 AccountID, const char* LoginIP);
void LoginIP(uint32 account_id, std::string login_ip);
/* 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);
@@ -190,6 +188,8 @@ public:
int16 CheckStatus(uint32 account_id);
void SetAccountCRCField(uint32 account_id, std::string field_name, uint64 checksum);
uint32 CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus = 0);
uint32 CreateAccount(const char* name, const char* password, int16 status, const char* loginserver, uint32 lsaccount_id);
uint32 GetAccountIDFromLSID(const std::string& in_loginserver_id, uint32 in_loginserver_account_id, char* in_account_name = 0, int16* in_status = 0);
@@ -206,8 +206,8 @@ public:
/* Groups */
char* GetGroupLeaderForLogin(const char* name,char* leaderbuf);
char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr);
std::string GetGroupLeaderForLogin(std::string character_name);
char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr);
uint32 GetGroupID(const char* name);
@@ -245,14 +245,11 @@ public:
/* General Queries */
bool GetSafePoints(const char* zone_short_name, uint32 instance_version, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, float* safe_heading = 0, int16* minstatus = 0, uint8* minlevel = 0, char *flag_needed = nullptr);
bool GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid = 0, float* graveyard_x = 0, float* graveyard_y = 0, float* graveyard_z = 0, float* graveyard_heading = 0);
bool GetZoneLongName(const char* short_name, char** long_name, char* file_name = 0, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, uint32* graveyard_id = 0, uint32* maxclients = 0);
bool LoadPTimers(uint32 charid, PTimerList &into);
uint32 GetZoneGraveyardID(uint32 zone_id, uint32 version);
uint8 GetPEQZone(uint32 zoneID, uint32 version);
uint8 GetPEQZone(uint32 zone_id, uint32 version);
uint8 GetMinStatus(uint32 zone_id, uint32 instance_version);
uint8 GetRaceSkill(uint8 skillid, uint8 in_race);
uint8 GetServerType();
uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level);
+70 -112
View File
@@ -23,10 +23,11 @@
#include <iterator>
#include "database_dump_service.h"
#include "../eqemu_logsys.h"
#include "../string_util.h"
#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,9 +86,9 @@ bool DatabaseDumpService::HasCompressionBinary()
*/
std::string DatabaseDumpService::GetMySQLVersion()
{
std::string version_output = execute("mysql --version");
std::string version_output = Process::execute("mysql --version");
return trim(version_output);
return Strings::Trim(version_output);
}
/**
@@ -149,95 +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 trim(tables_list);
return Strings::Join(DatabaseSchema::GetPlayerTables(), " ");
}
std::string DatabaseDumpService::GetBotTablesList()
{
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 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 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 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 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 trim(tables_list);
return Strings::Join(DatabaseSchema::GetContentTables(), " ");
}
/**
@@ -318,6 +245,16 @@ void DatabaseDumpService::Dump()
dump_descriptor += "-player";
}
if (IsDumpBotTables()) {
tables_to_dump += GetBotTablesList() + " ";
dump_descriptor += "-bots";
}
if (IsDumpMercTables()) {
tables_to_dump += GetMercTablesList() + " ";
dump_descriptor += "-mercs";
}
if (IsDumpSystemTables()) {
tables_to_dump += GetSystemTablesList() + " ";
dump_descriptor += "-system";
@@ -364,12 +301,12 @@ void DatabaseDumpService::Dump()
pipe_file
);
if (!FileUtil::exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) {
FileUtil::mkdir(GetSetDumpPath());
if (!File::Exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) {
File::Makedir(GetSetDumpPath());
}
if (IsDumpDropTableSyntaxOnly()) {
std::vector<std::string> tables = SplitString(tables_to_dump, ' ');
std::vector<std::string> tables = Strings::Split(tables_to_dump, ' ');
for (auto &table : tables) {
std::cout << "DROP TABLE IF EXISTS `" << table << "`;" << std::endl;
@@ -380,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());
@@ -397,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(),
@@ -408,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(),
@@ -436,6 +373,7 @@ void DatabaseDumpService::Dump()
// LogDebug("[{}] login", (IsDumpLoginServerTables() ? "true" : "false"));
// LogDebug("[{}] player", (IsDumpPlayerTables() ? "true" : "false"));
// LogDebug("[{}] system", (IsDumpSystemTables() ? "true" : "false"));
// LogDebug("[{}] bot", (IsDumpBotTables() ? "true" : "false"));
}
bool DatabaseDumpService::IsDumpSystemTables() const
@@ -577,3 +515,23 @@ void DatabaseDumpService::SetDumpStateTables(bool dump_state_tables)
{
DatabaseDumpService::dump_state_tables = dump_state_tables;
}
bool DatabaseDumpService::IsDumpBotTables() const
{
return dump_bot_tables;
}
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;
}
+8 -1
View File
@@ -53,6 +53,10 @@ public:
void SetDumpDropTableSyntaxOnly(bool dump_drop_table_syntax_only);
bool IsDumpStateTables() const;
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;
@@ -67,14 +71,17 @@ private:
bool dump_with_compression = false;
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();
+105 -96
View File
@@ -18,11 +18,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/global_define.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
#include "../common/strings.h"
#include "../common/timer.h"
#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) */
if(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;
}
@@ -961,7 +970,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
std::string rquery = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message)"
"VALUES (%u, '%s')",
character_id,
EscapeString(inspectmessage).c_str()
Strings::Escape(inspectmessage).c_str()
);
auto results = QueryDatabase(rquery);
}
@@ -1097,95 +1106,95 @@ bool Database::CheckDatabaseConvertPPDeblob(){
"e_expended_aa_spent"
")"
"VALUES ("
"%u," // id
"%u," // account_id
"'%s'," // `name`
"'%s'," // last_name
"%u," // gender
"%u," // race
"%u," // class
"%u," // `level`
"%u," // deity
"%u," // birthday
"%u," // last_login
"%u," // time_played
"%u," // pvp_status
"%u," // level2
"%u," // anon
"%u," // gm
"%u," // intoxication
"%u," // hair_color
"%u," // beard_color
"%u," // eye_color_1
"%u," // eye_color_2
"%u," // hair_style
"%u," // beard
"%u," // ability_time_seconds
"%u," // ability_number
"%u," // ability_time_minutes
"%u," // ability_time_hours
"'%s'," // title
"'%s'," // suffix
"%u," // exp
"%u," // points
"%u," // mana
"%u," // cur_hp
"%u," // str
"%u," // sta
"%u," // cha
"%u," // dex
"%u," // `int`
"%u," // agi
"%u," // wis
"%u," // face
"%f," // y
"%f," // x
"%f," // z
"%f," // heading
"%u," // pvp2
"%u," // pvp_type
"%u," // autosplit_enabled
"%u," // zone_change_count
"%u," // drakkin_heritage
"%u," // drakkin_tattoo
"%u," // drakkin_details
"%i," // toxicity
"%u," // hunger_level
"%u," // thirst_level
"%u," // ability_up
"%u," // zone_id
"%u," // zone_instance
"%u," // leadership_exp_on
"%u," // ldon_points_guk
"%u," // ldon_points_mir
"%u," // ldon_points_mmc
"%u," // ldon_points_ruj
"%u," // ldon_points_tak
"%u," // ldon_points_available
"%u," // tribute_time_remaining
"%u," // show_helm
"%u," // career_tribute_points
"%u," // tribute_points
"%u," // tribute_active
"%u," // endurance
"%u," // group_leadership_exp
"%u," // raid_leadership_exp
"%u," // group_leadership_points
"%u," // raid_leadership_points
"%u," // air_remaining
"%u," // pvp_kills
"%u," // pvp_deaths
"%u," // pvp_current_points
"%u," // pvp_career_points
"%u," // pvp_best_kill_streak
"%u," // pvp_worst_death_streak
"%u," // pvp_current_kill_streak
"%u," // aa_points_spent
"%u," // aa_exp
"%u," // aa_points
"%u," // group_auto_consent
"%u," // raid_auto_consent
"%u," // guild_auto_consent
"%u," // id
"%u," // account_id
"'%s'," // `name`
"'%s'," // last_name
"%u," // gender
"%u," // race
"%u," // class
"%u," // `level`
"%u," // deity
"%u," // birthday
"%u," // last_login
"%u," // time_played
"%u," // pvp_status
"%u," // level2
"%u," // anon
"%u," // gm
"%u," // intoxication
"%u," // hair_color
"%u," // beard_color
"%u," // eye_color_1
"%u," // eye_color_2
"%u," // hair_style
"%u," // beard
"%u," // ability_time_seconds
"%u," // ability_number
"%u," // ability_time_minutes
"%u," // ability_time_hours
"'%s'," // title
"'%s'," // suffix
"%u," // exp
"%u," // points
"%u," // mana
"%u," // cur_hp
"%u," // str
"%u," // sta
"%u," // cha
"%u," // dex
"%u," // `int`
"%u," // agi
"%u," // wis
"%u," // face
"%f," // y
"%f," // x
"%f," // z
"%f," // heading
"%u," // pvp2
"%u," // pvp_type
"%u," // autosplit_enabled
"%u," // zone_change_count
"%u," // drakkin_heritage
"%u," // drakkin_tattoo
"%u," // drakkin_details
"%i," // toxicity
"%u," // hunger_level
"%u," // thirst_level
"%u," // ability_up
"%u," // zone_id
"%u," // zone_instance
"%u," // leadership_exp_on
"%u," // ldon_points_guk
"%u," // ldon_points_mir
"%u," // ldon_points_mmc
"%u," // ldon_points_ruj
"%u," // ldon_points_tak
"%u," // ldon_points_available
"%u," // tribute_time_remaining
"%u," // show_helm
"%u," // career_tribute_points
"%u," // tribute_points
"%u," // tribute_active
"%u," // endurance
"%u," // group_leadership_exp
"%u," // raid_leadership_exp
"%u," // group_leadership_points
"%u," // raid_leadership_points
"%u," // air_remaining
"%u," // pvp_kills
"%u," // pvp_deaths
"%u," // pvp_current_points
"%u," // pvp_career_points
"%u," // pvp_best_kill_streak
"%u," // pvp_worst_death_streak
"%u," // pvp_current_kill_streak
"%u," // aa_points_spent
"%u," // aa_exp
"%u," // aa_points
"%u," // group_auto_consent
"%u," // raid_auto_consent
"%u," // guild_auto_consent
"%u," // RestTimer
"%u," // First Logon - References online status for EVENT_CONNECT/EVENT_DISCONNECt
"%u," // Looking for Group
@@ -1198,8 +1207,8 @@ bool Database::CheckDatabaseConvertPPDeblob(){
")",
character_id,
account_id,
EscapeString(pp->name).c_str(),
EscapeString(pp->last_name).c_str(),
Strings::Escape(pp->name).c_str(),
Strings::Escape(pp->last_name).c_str(),
pp->gender,
pp->race,
pp->class_,
@@ -1223,8 +1232,8 @@ bool Database::CheckDatabaseConvertPPDeblob(){
pp->ability_number,
pp->ability_time_minutes,
pp->ability_time_hours,
EscapeString(pp->title).c_str(),
EscapeString(pp->suffix).c_str(),
Strings::Escape(pp->title).c_str(),
Strings::Escape(pp->suffix).c_str(),
pp->exp,
pp->points,
pp->mana,
+230 -291
View File
@@ -18,10 +18,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/global_define.h"
#include "../common/rulesys.h"
#include "../common/string_util.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);
query = StringFormat("DELETE FROM respawn_times WHERE instance_id=%u", instance_id);
QueryDatabase(query);
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id = {}", instance_id));
query = StringFormat("DELETE FROM spawn_condition_values WHERE instance_id=%u", instance_id);
QueryDatabase(query);
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
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 = 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);
}
+61 -2
View File
@@ -62,6 +62,7 @@ namespace DatabaseSchema {
{"character_pet_buffs", "char_id"},
{"character_pet_info", "char_id"},
{"character_pet_inventory", "char_id"},
{"character_peqzone_flags", "id"},
{"character_potionbelt", "id"},
{"character_skills", "id"},
{"character_spells", "id"},
@@ -129,6 +130,7 @@ namespace DatabaseSchema {
"character_pet_buffs",
"character_pet_info",
"character_pet_inventory",
"character_peqzone_flags",
"character_potionbelt",
"character_skills",
"character_spells",
@@ -187,13 +189,14 @@ namespace DatabaseSchema {
"char_create_point_allocations",
"damageshieldtypes",
"doors",
"dynamic_zone_templates",
"faction_association",
"faction_base_data",
"faction_list",
"faction_list_mod",
"fishing",
"forage",
"global_loot",
"goallists",
"graveyard",
"grid",
"grid_entries",
@@ -222,7 +225,6 @@ namespace DatabaseSchema {
"pets_beastlord_data",
"pets_equipmentset",
"pets_equipmentset_entries",
"proximities",
"skill_caps",
"spawn2",
"spawn_conditions",
@@ -316,6 +318,7 @@ namespace DatabaseSchema {
"completed_shared_task_activity_state",
"completed_shared_task_members",
"completed_shared_tasks",
"discord_webhooks",
"dynamic_zone_members",
"dynamic_zones",
"eventlog",
@@ -329,7 +332,9 @@ namespace DatabaseSchema {
"ip_exemptions",
"item_tick",
"lfguild",
"merc_buffs",
"merchantlist_temp",
"mercs",
"object_contents",
"raid_details",
"raid_leaders",
@@ -374,6 +379,60 @@ namespace DatabaseSchema {
};
}
/**
* @description Gets all player bot tables
* @note These tables have no content in the PEQ daily dump
*
* @return
*/
static std::vector<std::string> GetBotTables()
{
return {
"bot_buffs",
"bot_command_settings",
"bot_create_combinations",
"bot_data",
"bot_group_members",
"bot_groups",
"bot_guild_members",
"bot_heal_rotation_members",
"bot_heal_rotation_targets",
"bot_heal_rotations",
"bot_inspect_messages",
"bot_inventories",
"bot_owner_options",
"bot_pet_buffs",
"bot_pet_inventories",
"bot_pets",
"bot_spell_casting_chances",
"bot_spell_settings",
"bot_spells_entries",
"bot_stances",
"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"
};
}
}
#endif //EQEMU_DATABASE_SCHEMA_H
+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",
+91
View File
@@ -0,0 +1,91 @@
#include "discord.h"
#include "../http/httplib.h"
#include "../json/json.h"
#include "../strings.h"
#include "../eqemu_logsys.h"
constexpr int MAX_RETRIES = 10;
void Discord::SendWebhookMessage(const std::string &message, const std::string &webhook_url)
{
// validate
if (webhook_url.empty()) {
LogDiscord("[webhook_url] is empty");
return;
}
// validate
if (webhook_url.find("http://") == std::string::npos && webhook_url.find("https://") == std::string::npos) {
LogDiscord("[webhook_url] [{}] does not contain a valid http/s prefix.", webhook_url);
return;
}
// split
auto s = Strings::Split(webhook_url, '/');
// url
std::string base_url = fmt::format("{}//{}", s[0], s[2]);
std::string endpoint = Strings::Replace(webhook_url, base_url, "");
// client
httplib::Client cli(base_url.c_str());
cli.set_connection_timeout(0, 15000000); // 15 sec
cli.set_read_timeout(15, 0); // 15 seconds
cli.set_write_timeout(15, 0); // 15 seconds
httplib::Headers headers = {
{"Content-Type", "application/json"}
};
// payload
Json::Value p;
p["content"] = message;
std::stringstream payload;
payload << p;
bool retry = true;
int retries = 0;
int retry_timer = 1000;
while (retry) {
if (auto res = cli.Post(endpoint.c_str(), payload.str(), "application/json")) {
if (res->status != 200 && res->status != 204) {
LogError("Code [{}] Error [{}]", res->status, res->body);
}
if (res->status == 429) {
if (!res->body.empty()) {
std::stringstream ss(res->body);
Json::Value response;
try {
ss >> response;
}
catch (std::exception const &ex) {
LogDiscord("JSON serialization failure [{}] via [{}]", ex.what(), res->body);
}
retry_timer = std::stoi(response["retry_after"].asString()) + 500;
}
LogDiscord("Rate limited... retrying message in [{}ms]", retry_timer);
std::this_thread::sleep_for(std::chrono::milliseconds(retry_timer + 500));
}
if (res->status == 204) {
retry = false;
}
if (retries > MAX_RETRIES) {
LogDiscord("Retries exceeded for message [{}]", message);
retry = false;
}
retries++;
}
}
}
std::string Discord::FormatDiscordMessage(uint16 category_id, const std::string &message)
{
if (category_id == Logs::LogCategory::MySQLQuery) {
return fmt::format("```sql\n{}\n```", message);
}
return message + "\n";
}
+15
View File
@@ -0,0 +1,15 @@
#ifndef EQEMU_DISCORD_H
#define EQEMU_DISCORD_H
#include <string>
#include "../types.h"
class Discord {
public:
static void SendWebhookMessage(const std::string& message, const std::string& webhook_url);
static std::string FormatDiscordMessage(uint16 category_id, const std::string& message);
};
#endif //EQEMU_DISCORD_H
+69
View File
@@ -0,0 +1,69 @@
#include "discord_manager.h"
#include "../common/discord/discord.h"
#include "../common/eqemu_logsys.h"
#include "../common/strings.h"
void DiscordManager::QueueWebhookMessage(uint32 webhook_id, const std::string &message)
{
webhook_queue_lock.lock();
webhook_message_queue[webhook_id].emplace_back(message);
webhook_queue_lock.unlock();
}
constexpr int MAX_MESSAGE_LENGTH = 1900;
void DiscordManager::ProcessMessageQueue()
{
if (webhook_message_queue.empty()) {
return;
}
webhook_queue_lock.lock();
for (auto &q: webhook_message_queue) {
LogDiscord("Processing [{}] messages in queue for webhook ID [{}]...", q.second.size(), q.first);
if (q.first >= MAX_DISCORD_WEBHOOK_ID) {
LogDiscord("Out of bounds webhook ID [{}] max [{}]", q.first, MAX_DISCORD_WEBHOOK_ID);
continue;
}
auto webhook = LogSys.GetDiscordWebhooks()[q.first];
std::string message;
for (auto &m: q.second) {
// next message would become too large
bool next_message_too_large = ((int) m.length() + (int) message.length()) > MAX_MESSAGE_LENGTH;
if (next_message_too_large) {
Discord::SendWebhookMessage(
message,
webhook.webhook_url
);
message = "";
}
message += m;
// one single message was too large
// this should rarely happen but the message will need to be split
if ((int) message.length() > MAX_MESSAGE_LENGTH) {
for (unsigned mi = 0; mi < message.length(); mi += MAX_MESSAGE_LENGTH) {
Discord::SendWebhookMessage(
message.substr(mi, MAX_MESSAGE_LENGTH),
webhook.webhook_url
);
}
message = "";
}
}
// final flush
if (!message.empty()) {
Discord::SendWebhookMessage(
message,
webhook.webhook_url
);
}
}
webhook_message_queue.clear();
webhook_queue_lock.unlock();
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef EQEMU_DISCORD_MANAGER_H
#define EQEMU_DISCORD_MANAGER_H
#include <mutex>
#include <map>
#include <vector>
#include "../common/types.h"
class DiscordManager {
public:
void QueueWebhookMessage(uint32 webhook_id, const std::string& message);
void ProcessMessageQueue();
private:
std::mutex webhook_queue_lock{};
std::map<uint32, std::vector<std::string>> webhook_message_queue{};
};
#endif
+51 -1
View File
@@ -79,6 +79,7 @@ void DynamicZoneBase::LoadRepositoryResult(DynamicZonesRepository::DynamicZoneIn
m_max_players = dz_entry.max_players;
m_instance_id = dz_entry.instance_id;
m_type = static_cast<DynamicZoneType>(dz_entry.type);
m_dz_switch_id = dz_entry.dz_switch_id;
m_compass.zone_id = dz_entry.compass_zone_id;
m_compass.x = dz_entry.compass_x;
m_compass.y = dz_entry.compass_y;
@@ -129,6 +130,7 @@ uint32_t DynamicZoneBase::SaveToDatabase()
insert_dz.max_players = m_max_players;
insert_dz.instance_id = m_instance_id,
insert_dz.type = static_cast<int>(m_type);
insert_dz.dz_switch_id = m_dz_switch_id;
insert_dz.compass_zone_id = m_compass.zone_id;
insert_dz.compass_x = m_compass.x;
insert_dz.compass_y = m_compass.y;
@@ -316,6 +318,17 @@ void DynamicZoneBase::SetZoneInLocation(float x, float y, float z, float heading
SetZoneInLocation({ 0, x, y, z, heading }, update_db);
}
void DynamicZoneBase::SetSwitchID(int dz_switch_id, bool update_db)
{
m_dz_switch_id = dz_switch_id;
if (update_db)
{
DynamicZonesRepository::UpdateSwitchID(GetDatabase(), m_id, dz_switch_id);
SendServerPacket(CreateServerDzSwitchIDPacket().get());
}
}
void DynamicZoneBase::SetLeader(const DynamicZoneMember& new_leader, bool update_db)
{
m_leader = new_leader;
@@ -403,6 +416,17 @@ std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerDzLocationPacket(
return pack;
}
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerDzSwitchIDPacket()
{
constexpr uint32_t pack_size = sizeof(ServerDzSwitchID_Struct);
auto pack = std::make_unique<ServerPacket>(ServerOP_DzSetSwitchID, pack_size);
auto buf = reinterpret_cast<ServerDzSwitchID_Struct*>(pack->pBuffer);
buf->dz_id = GetID();
buf->dz_switch_id = GetSwitchID();
return pack;
}
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerMemberStatusPacket(
uint32_t character_id, DynamicZoneMemberStatus status)
{
@@ -561,8 +585,9 @@ std::string DynamicZoneBase::GetDynamicZoneTypeName(DynamicZoneType dz_type)
return "Mission";
case DynamicZoneType::Quest:
return "Quest";
default:
return "Unknown";
}
return "Unknown";
}
EQ::Net::DynamicPacket DynamicZoneBase::GetSerializedDzPacket()
@@ -597,3 +622,28 @@ void DynamicZoneBase::LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_
cereal::BinaryInputArchive archive(ss);
archive(*this);
}
void DynamicZoneBase::LoadTemplate(const DynamicZoneTemplatesRepository::DynamicZoneTemplates& dz_template)
{
m_zone_id = dz_template.zone_id;
m_zone_version = dz_template.zone_version;
m_name = dz_template.name;
m_min_players = dz_template.min_players;
m_max_players = dz_template.max_players;
m_duration = std::chrono::seconds(dz_template.duration_seconds);
m_dz_switch_id = dz_template.dz_switch_id;
m_compass.zone_id = dz_template.compass_zone_id;
m_compass.x = dz_template.compass_x;
m_compass.y = dz_template.compass_y;
m_compass.z = dz_template.compass_z;
m_safereturn.zone_id = dz_template.return_zone_id;
m_safereturn.x = dz_template.return_x;
m_safereturn.y = dz_template.return_y;
m_safereturn.z = dz_template.return_z;
m_safereturn.heading = dz_template.return_h;
m_has_zonein = dz_template.override_zone_in;
m_zonein.x = dz_template.zone_in_x;
m_zonein.y = dz_template.zone_in_y;
m_zonein.z = dz_template.zone_in_z;
m_zonein.heading = dz_template.zone_in_h;
}
+9
View File
@@ -5,6 +5,7 @@
#include "net/packet.h"
#include "repositories/dynamic_zones_repository.h"
#include "repositories/dynamic_zone_members_repository.h"
#include "repositories/dynamic_zone_templates_repository.h"
#include <algorithm>
#include <chrono>
#include <cstdint>
@@ -74,6 +75,7 @@ public:
virtual void SetSecondsRemaining(uint32_t seconds_remaining) = 0;
int GetDuration() const { return static_cast<int>(m_duration.count()); }
uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); }
uint32_t GetID() const { return m_id; }
uint16_t GetInstanceID() const { return static_cast<uint16_t>(m_instance_id); }
@@ -85,6 +87,7 @@ public:
uint16_t GetZoneID() const { return static_cast<uint16_t>(m_zone_id); }
uint32_t GetZoneIndex() const { return (m_instance_id << 16) | (m_zone_id & 0xffff); }
uint32_t GetZoneVersion() const { return m_zone_version; }
int GetSwitchID() const { return m_dz_switch_id; }
DynamicZoneType GetType() const { return m_type; }
const std::string& GetLeaderName() const { return m_leader.name; }
const std::string& GetName() const { return m_name; }
@@ -112,6 +115,7 @@ public:
bool IsValid() const { return m_instance_id != 0; }
bool IsSameDz(uint32_t zone_id, uint32_t instance_id) const { return zone_id == m_zone_id && instance_id == m_instance_id; }
void LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_size);
void LoadTemplate(const DynamicZoneTemplatesRepository::DynamicZoneTemplates& dz_template);
void RemoveAllMembers();
bool RemoveMember(uint32_t character_id);
bool RemoveMember(const std::string& character_name);
@@ -127,6 +131,7 @@ public:
void SetName(const std::string& name) { m_name = name; }
void SetSafeReturn(const DynamicZoneLocation& location, bool update_db = false);
void SetSafeReturn(uint32_t zone_id, float x, float y, float z, float heading, bool update_db = false);
void SetSwitchID(int dz_switch_id, bool update_db = false);
void SetType(DynamicZoneType type) { m_type = type; }
void SetUUID(std::string uuid) { m_uuid = std::move(uuid); }
void SetZoneInLocation(const DynamicZoneLocation& location, bool update_db = false);
@@ -141,6 +146,7 @@ protected:
virtual void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed);
virtual bool ProcessMemberStatusChange(uint32_t member_id, DynamicZoneMemberStatus status);
virtual void ProcessRemoveAllMembers(bool silent = false) { m_members.clear(); }
virtual void ProcessSetSwitchID(int dz_switch_id) { m_dz_switch_id = dz_switch_id; }
virtual bool SendServerPacket(ServerPacket* packet) = 0;
void AddInternalMember(const DynamicZoneMember& member);
@@ -153,6 +159,7 @@ protected:
std::unique_ptr<ServerPacket> CreateServerDzCreatePacket(uint16_t origin_zone_id, uint16_t origin_instance_id);
std::unique_ptr<ServerPacket> CreateServerDzLocationPacket(uint16_t server_opcode, const DynamicZoneLocation& location);
std::unique_ptr<ServerPacket> CreateServerDzSwitchIDPacket();
std::unique_ptr<ServerPacket> CreateServerMemberAddRemovePacket(const DynamicZoneMember& member, bool removed);
std::unique_ptr<ServerPacket> CreateServerMemberStatusPacket(uint32_t character_id, DynamicZoneMemberStatus status);
std::unique_ptr<ServerPacket> CreateServerMemberSwapPacket(const DynamicZoneMember& remove_member, const DynamicZoneMember& add_member);
@@ -164,6 +171,7 @@ protected:
uint32_t m_zone_version = 0;
uint32_t m_min_players = 0;
uint32_t m_max_players = 0;
int m_dz_switch_id = 0;
bool m_never_expires = false;
bool m_has_zonein = false;
bool m_has_member_statuses = false;
@@ -190,6 +198,7 @@ public:
m_zone_version,
m_min_players,
m_max_players,
m_dz_switch_id,
m_never_expires,
m_has_zonein,
m_has_member_statuses,
+273 -31
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
@@ -18,10 +18,12 @@
*/
#include "emu_constants.h"
#include "languages.h"
#include "data_verification.h"
#include "bodytypes.h"
#include "data_verification.h"
#include "eqemu_logsys.h"
#include "eqemu_logsys_log_aliases.h"
#include "languages.h"
#include "rulesys.h"
int16 EQ::invtype::GetInvTypeSize(int16 inv_type) {
static const int16 local_array[] = {
@@ -118,7 +120,7 @@ EQ::bug::CategoryID EQ::bug::CategoryNameToCategoryID(const char* category_name)
return catLoNTCG;
if (!strcmp(category_name, "Mercenaries"))
return catMercenaries;
return catOther;
}
@@ -189,15 +191,16 @@ const std::map<int, std::string>& EQ::constants::GetLanguageMap()
{ LANG_HADAL, "Hadal" },
{ LANG_UNKNOWN, "Unknown" }
};
return language_map;
}
std::string EQ::constants::GetLanguageName(int language_id)
{
if (EQ::ValueWithin(language_id, LANG_COMMON_TONGUE, LANG_UNKNOWN)) {
auto languages = EQ::constants::GetLanguageMap();
return languages[language_id];
return EQ::constants::GetLanguageMap().find(language_id)->second;
}
return std::string();
}
@@ -211,37 +214,39 @@ const std::map<uint32, std::string>& EQ::constants::GetLDoNThemeMap()
{ LDoNThemes::RUJ, "Rujarkian Hills" },
{ LDoNThemes::TAK, "Takish-Hiz" },
};
return ldon_theme_map;
}
std::string EQ::constants::GetLDoNThemeName(uint32 theme_id)
{
if (EQ::ValueWithin(theme_id, LDoNThemes::Unused, LDoNThemes::TAK)) {
auto ldon_themes = EQ::constants::GetLDoNThemeMap();
return ldon_themes[theme_id];
return EQ::constants::GetLDoNThemeMap().find(theme_id)->second;
}
return std::string();
return std::string();
}
const std::map<uint8, std::string>& EQ::constants::GetFlyModeMap()
const std::map<int8, std::string>& EQ::constants::GetFlyModeMap()
{
static const std::map<uint8, std::string> flymode_map = {
{ EQ::constants::GravityBehavior::Ground, "Ground" },
{ EQ::constants::GravityBehavior::Flying, "Flying" },
{ EQ::constants::GravityBehavior::Levitating, "Levitating" },
{ EQ::constants::GravityBehavior::Water, "Water" },
{ EQ::constants::GravityBehavior::Floating, "Floating" },
{ EQ::constants::GravityBehavior::LevitateWhileRunning, "Levitating While Running" },
static const std::map<int8, std::string> flymode_map = {
{ GravityBehavior::Ground, "Ground" },
{ GravityBehavior::Flying, "Flying" },
{ GravityBehavior::Levitating, "Levitating" },
{ GravityBehavior::Water, "Water" },
{ GravityBehavior::Floating, "Floating" },
{ GravityBehavior::LevitateWhileRunning, "Levitating While Running" },
};
return flymode_map;
}
std::string EQ::constants::GetFlyModeName(uint8 flymode_id)
std::string EQ::constants::GetFlyModeName(int8 flymode_id)
{
if (EQ::ValueWithin(flymode_id, GravityBehavior::Ground, GravityBehavior::LevitateWhileRunning)) {
auto flymodes = EQ::constants::GetFlyModeMap();
return flymodes[flymode_id];
return EQ::constants::GetFlyModeMap().find(flymode_id)->second;
}
return std::string();
}
@@ -288,15 +293,16 @@ const std::map<bodyType, std::string>& EQ::constants::GetBodyTypeMap()
{ BT_InvisMan, "Invisible Man" },
{ BT_Special, "Special" },
};
return bodytype_map;
}
std::string EQ::constants::GetBodyTypeName(bodyType bodytype_id)
{
auto bodytypes = EQ::constants::GetBodyTypeMap();
if (!bodytypes[bodytype_id].empty()) {
return bodytypes[bodytype_id];
if (EQ::constants::GetBodyTypeMap().find(bodytype_id) != EQ::constants::GetBodyTypeMap().end()) {
return EQ::constants::GetBodyTypeMap().find(bodytype_id)->second;
}
return std::string();
}
@@ -318,22 +324,258 @@ const std::map<uint8, std::string>& EQ::constants::GetAccountStatusMap()
{ AccountStatus::GMAreas, "GM Areas" },
{ AccountStatus::GMCoder, "GM Coder" },
{ AccountStatus::GMMgmt, "GM Mgmt" },
{ AccountStatus::GMImpossible, "GM Impossible" },
{ AccountStatus::GMImpossible, "GM Impossible" },
{ AccountStatus::Max, "GM Max" }
};
return account_status_map;
}
std::string EQ::constants::GetAccountStatusName(uint8 account_status)
{
auto account_statuses = EQ::constants::GetAccountStatusMap();
std::string status_name;
for (auto status_level = account_statuses.rbegin(); status_level != account_statuses.rend(); ++status_level) {
for (
auto status_level = EQ::constants::GetAccountStatusMap().rbegin();
status_level != EQ::constants::GetAccountStatusMap().rend();
++status_level
) {
if (account_status >= status_level->first) {
status_name = status_level->second;
break;
return status_level->second;
}
}
return status_name;
return std::string();
}
const std::map<uint8, std::string>& EQ::constants::GetConsiderLevelMap()
{
static const std::map<uint8, std::string> consider_level_map = {
{ ConsiderLevel::Ally, "Ally" },
{ ConsiderLevel::Warmly, "Warmly" },
{ ConsiderLevel::Kindly, "Kindly" },
{ ConsiderLevel::Amiably, "Amiably" },
{ ConsiderLevel::Indifferently, "Indifferently" },
{ ConsiderLevel::Apprehensively, "Apprehensively" },
{ ConsiderLevel::Dubiously, "Dubiously" },
{ ConsiderLevel::Threateningly, "Threateningly" },
{ ConsiderLevel::Scowls, "Scowls" }
};
return consider_level_map;
}
std::string EQ::constants::GetConsiderLevelName(uint8 faction_consider_level)
{
if (EQ::constants::GetConsiderLevelMap().find(faction_consider_level) != EQ::constants::GetConsiderLevelMap().end()) {
return EQ::constants::GetConsiderLevelMap().find(faction_consider_level)->second;
}
return std::string();
}
const std::map<uint8, std::string>& EQ::constants::GetEnvironmentalDamageMap()
{
static const std::map<uint8, std::string> damage_type_map = {
{ EnvironmentalDamage::Lava, "Lava" },
{ EnvironmentalDamage::Drowning, "Drowning" },
{ EnvironmentalDamage::Falling, "Falling" },
{ EnvironmentalDamage::Trap, "Trap" }
};
return damage_type_map;
}
std::string EQ::constants::GetEnvironmentalDamageName(uint8 damage_type)
{
if (EQ::ValueWithin(damage_type, EnvironmentalDamage::Lava, EnvironmentalDamage::Trap)) {
return EQ::constants::GetEnvironmentalDamageMap().find(damage_type)->second;
}
return std::string();
}
const std::map<uint8, std::string>& EQ::constants::GetStuckBehaviorMap()
{
static const std::map<uint8, std::string> stuck_behavior_map = {
{ StuckBehavior::RunToTarget, "Run To Target" },
{ StuckBehavior::WarpToTarget, "Warp To Target" },
{ StuckBehavior::TakeNoAction, "Take No Action" },
{ StuckBehavior::EvadeCombat, "Evade Combat" }
};
return stuck_behavior_map;
}
std::string EQ::constants::GetStuckBehaviorName(uint8 behavior_id)
{
if (EQ::ValueWithin(behavior_id, StuckBehavior::RunToTarget, StuckBehavior::EvadeCombat)) {
return EQ::constants::GetStuckBehaviorMap().find(behavior_id)->second;
}
return std::string();
}
const std::map<uint8, std::string>& EQ::constants::GetSpawnAnimationMap()
{
static const std::map<uint8, std::string> spawn_animation_map = {
{ SpawnAnimations::Standing, "Standing" },
{ SpawnAnimations::Sitting, "Sitting" },
{ SpawnAnimations::Crouching, "Crouching" },
{ SpawnAnimations::Laying, "Laying" },
{ SpawnAnimations::Looting, "Looting" }
};
return spawn_animation_map;
}
std::string EQ::constants::GetSpawnAnimationName(uint8 animation_id)
{
if (EQ::ValueWithin(animation_id, SpawnAnimations::Standing, SpawnAnimations::Looting)) {
return EQ::constants::GetSpawnAnimationMap().find(animation_id)->second;
}
return std::string();
}
const std::map<int, std::string>& EQ::constants::GetObjectTypeMap()
{
static const std::map<int, std::string> object_type_map = {
{ ObjectTypes::SmallBag, "Small Bag" },
{ ObjectTypes::LargeBag, "Large Bag" },
{ ObjectTypes::Quiver, "Quiver" },
{ ObjectTypes::BeltPouch, "Belt Pouch" },
{ ObjectTypes::WristPouch, "Wrist Pouch" },
{ ObjectTypes::Backpack, "Backpack" },
{ ObjectTypes::SmallChest, "Small Chest" },
{ ObjectTypes::LargeChest, "Large Chest" },
{ ObjectTypes::Bandolier, "Bandolier" },
{ ObjectTypes::Medicine, "Medicine" },
{ ObjectTypes::Tinkering, "Tinkering" },
{ ObjectTypes::Lexicon, "Lexicon" },
{ ObjectTypes::PoisonMaking, "Mortar and Pestle" },
{ ObjectTypes::Quest, "Quest" },
{ ObjectTypes::MixingBowl, "Mixing Bowl" },
{ ObjectTypes::Baking, "Baking" },
{ ObjectTypes::Tailoring, "Tailoring" },
{ ObjectTypes::Blacksmithing, "Blacksmithing" },
{ ObjectTypes::Fletching, "Fletching" },
{ ObjectTypes::Brewing, "Brewing" },
{ ObjectTypes::JewelryMaking, "Jewelry Making" },
{ ObjectTypes::Pottery, "Pottery" },
{ ObjectTypes::Kiln, "Kiln" },
{ ObjectTypes::KeyMaker, "Key Maker" },
{ ObjectTypes::ResearchWIZ, "Lexicon" },
{ ObjectTypes::ResearchMAG, "Lexicon" },
{ ObjectTypes::ResearchNEC, "Lexicon" },
{ ObjectTypes::ResearchENC, "Lexicon" },
{ ObjectTypes::Unknown, "Unknown" },
{ ObjectTypes::ResearchPractice, "Lexicon" },
{ ObjectTypes::Alchemy, "Alchemy" },
{ ObjectTypes::HighElfForge, "High Elf Forge" },
{ ObjectTypes::DarkElfForge, "Dark Elf Forge" },
{ ObjectTypes::OgreForge, "Ogre Forge" },
{ ObjectTypes::DwarfForge, "Dwarf Forge" },
{ ObjectTypes::GnomeForge, "Gnome Forge" },
{ ObjectTypes::BarbarianForge, "Barbarian Forge" },
{ ObjectTypes::IksarForge, "Iksar Forge" },
{ ObjectTypes::HumanForgeOne, "Human Forge" },
{ ObjectTypes::HumanForgeTwo, "Human Forge" },
{ ObjectTypes::HalflingTailoringOne, "Halfling Tailoring" },
{ ObjectTypes::HalflingTailoringTwo, "Halfling Tailoring" },
{ ObjectTypes::EruditeTailoring, "Erudite Tailoring" },
{ ObjectTypes::WoodElfTailoring, "Wood Elf Tailoring" },
{ ObjectTypes::WoodElfFletching, "Wood Elf Fletching" },
{ ObjectTypes::IksarPottery, "Iksar Pottery" },
{ ObjectTypes::Fishing, "Fishing" },
{ ObjectTypes::TrollForge, "Troll Forge" },
{ ObjectTypes::WoodElfForge, "Wood Elf Forge" },
{ ObjectTypes::HalflingForge, "Halfling Forge" },
{ ObjectTypes::EruditeForge, "Erudite Forge" },
{ ObjectTypes::Merchant, "Merchant" },
{ ObjectTypes::FroglokForge, "Froglok Forge" },
{ ObjectTypes::Augmenter, "Augmenter" },
{ ObjectTypes::Churn, "Churn" },
{ ObjectTypes::TransformationMold, "Transformation Mold" },
{ ObjectTypes::DetransformationMold, "Detransformation Mold" },
{ ObjectTypes::Unattuner, "Unattuner" },
{ ObjectTypes::TradeskillBag, "Tradeskill Bag" },
{ ObjectTypes::CollectibleBag, "Collectible Bag" },
{ ObjectTypes::NoDeposit, "No Deposit" }
};
return object_type_map;
}
std::string EQ::constants::GetObjectTypeName(int object_type)
{
if (EQ::ValueWithin(object_type, ObjectTypes::SmallBag, ObjectTypes::NoDeposit)) {
return EQ::constants::GetObjectTypeMap().find(object_type)->second;
}
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();
}
+213 -11
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
@@ -32,10 +32,6 @@ namespace EQ
{
using RoF2::IINVALID;
using RoF2::INULL;
namespace inventory {
} /*inventory*/
namespace invtype {
using namespace RoF2::invtype::enum_;
@@ -201,7 +197,7 @@ namespace EQ
using RoF2::constants::EXPANSIONS_MASK;
using RoF2::constants::CHARACTER_CREATION_LIMIT;
const size_t SAY_LINK_OPENER_SIZE = 1;
using RoF2::constants::SAY_LINK_BODY_SIZE;
const size_t SAY_LINK_TEXT_SIZE = 256; // this may be varied until it breaks something (tested:374) - the others are constant
@@ -221,7 +217,26 @@ namespace EQ
stanceBurnAE
};
enum GravityBehavior : uint8 {
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,
Levitating,
@@ -230,6 +245,116 @@ namespace EQ
LevitateWhileRunning
};
enum EnvironmentalDamage : uint8 {
Lava = 250,
Drowning,
Falling,
Trap
};
enum StuckBehavior : uint8 {
RunToTarget,
WarpToTarget,
TakeNoAction,
EvadeCombat
};
enum SpawnAnimations : uint8 {
Standing,
Sitting,
Crouching,
Laying,
Looting
};
enum ObjectTypes : int {
SmallBag,
LargeBag,
Quiver,
BeltPouch,
WristPouch,
Backpack,
SmallChest,
LargeChest,
Bandolier,
Medicine,
Tinkering,
Lexicon,
PoisonMaking,
Quest,
MixingBowl,
Baking,
Tailoring,
Blacksmithing,
Fletching,
Brewing,
JewelryMaking,
Pottery,
Kiln,
KeyMaker,
ResearchWIZ,
ResearchMAG,
ResearchNEC,
ResearchENC,
Unknown,
ResearchPractice,
Alchemy,
HighElfForge,
DarkElfForge,
OgreForge,
DwarfForge,
GnomeForge,
BarbarianForge,
IksarForge,
HumanForgeOne,
HumanForgeTwo,
HalflingTailoringOne,
HalflingTailoringTwo,
EruditeTailoring,
WoodElfTailoring,
WoodElfFletching,
IksarPottery,
Fishing,
TrollForge,
WoodElfForge,
HalflingForge,
EruditeForge,
Merchant,
FroglokForge,
Augmenter,
Churn,
TransformationMold,
DetransformationMold,
Unattuner,
TradeskillBag,
CollectibleBag,
NoDeposit
};
enum WeatherTypes : uint8 {
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);
@@ -238,9 +363,9 @@ namespace EQ
extern const std::map<uint32, std::string>& GetLDoNThemeMap();
std::string GetLDoNThemeName(uint32 theme_id);
extern const std::map<uint8, std::string>& GetFlyModeMap();
std::string GetFlyModeName(uint8 flymode_id);
extern const std::map<int8, std::string>& GetFlyModeMap();
std::string GetFlyModeName(int8 flymode_id);
extern const std::map<bodyType, std::string>& GetBodyTypeMap();
std::string GetBodyTypeName(bodyType bodytype_id);
@@ -248,6 +373,30 @@ namespace EQ
extern const std::map<uint8, std::string>& GetAccountStatusMap();
std::string GetAccountStatusName(uint8 account_status);
extern const std::map<uint8, std::string>& GetConsiderLevelMap();
std::string GetConsiderLevelName(uint8 consider_level);
extern const std::map<uint8, std::string>& GetEnvironmentalDamageMap();
std::string GetEnvironmentalDamageName(uint8 damage_type);
extern const std::map<uint8, std::string>& GetStuckBehaviorMap();
std::string GetStuckBehaviorName(uint8 behavior_id);
extern const std::map<uint8, std::string>& GetSpawnAnimationMap();
std::string GetSpawnAnimationName(uint8 animation_id);
extern const std::map<int, std::string>& GetObjectTypeMap();
std::string GetObjectTypeName(int object_type);
extern const std::map<uint8, std::string>& GetWeatherTypeMap();
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;
@@ -257,7 +406,7 @@ namespace EQ
namespace profile {
using RoF2::profile::BANDOLIERS_SIZE;
using RoF2::profile::BANDOLIER_ITEM_COUNT;
using RoF2::profile::POTION_BELT_SIZE;
using RoF2::profile::SKILL_ARRAY_SIZE;
@@ -391,4 +540,57 @@ enum AugmentActions : int {
Destroy
};
enum ConsiderLevel : uint8 {
Ally = 1,
Warmly,
Kindly,
Amiably,
Indifferently,
Apprehensively,
Dubiously,
Threateningly,
Scowls
};
enum TargetDescriptionType : uint8 {
LCSelf,
UCSelf,
LCYou,
UCYou,
LCYour,
UCYour
};
enum ReloadWorld : uint8 {
NoRepop = 0,
Repop,
ForceRepop
};
enum BucketComparison : uint8 {
BucketEqualTo = 0,
BucketNotEqualTo,
BucketGreaterThanOrEqualTo,
BucketLesserThanOrEqualTo,
BucketGreaterThan,
BucketLesserThan,
BucketIsAny,
BucketIsNotAny,
BucketIsBetween,
BucketIsNotBetween
};
enum class EntityFilterType {
All,
Bots,
Clients,
NPCs
};
enum class ApplySpellType {
Solo,
Group,
Raid
};
#endif /*COMMON_EMU_CONSTANTS_H*/
+5 -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),
@@ -71,6 +71,7 @@ N(OP_Camp),
N(OP_CancelSneakHide),
N(OP_CancelTask),
N(OP_CancelTrade),
N(OP_CashReward),
N(OP_CastSpell),
N(OP_ChangeSize),
N(OP_ChannelMessage),
@@ -303,6 +304,7 @@ N(OP_LockoutTimerInfo),
N(OP_Login),
N(OP_LoginAccepted),
N(OP_LoginComplete),
N(OP_LoginExpansionPacketData), //added for Rof2 client to send expansion data packet. Requires login_opcodes_sod.conf to be updated.
N(OP_LoginUnknown1),
N(OP_LoginUnknown2),
N(OP_Logout),
@@ -455,6 +457,7 @@ N(OP_ServerListResponse),
N(OP_SessionReady),
N(OP_SetChatServer),
N(OP_SetChatServer2),
N(OP_SetFace),
N(OP_SetGroupTarget),
N(OP_SetGuildMOTD),
N(OP_SetGuildRank),
@@ -558,6 +561,7 @@ N(OP_WhoAllRequest),
N(OP_WhoAllResponse),
N(OP_World_Client_CRC1),
N(OP_World_Client_CRC2),
N(OP_World_Client_CRC3),
N(OP_WorldClientReady),
N(OP_WorldComplete),
N(OP_WorldLogout),
+28 -9
View File
@@ -79,6 +79,8 @@
#define ANIM_DEATH 0x73
#define ANIM_LOOT 0x69
constexpr int16 RECAST_TYPE_UNLINKED_ITEM = -1;
typedef enum {
eaStanding = 0,
eaSitting, //1
@@ -684,14 +686,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 +712,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,
@@ -1009,4 +1003,29 @@ enum StartZoneIndex {
SharVahl
};
enum FVNoDropFlagRule
{
Disabled = 0,
Enabled = 1,
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*/
+16 -16
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
@@ -11,7 +11,7 @@
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -26,7 +26,7 @@
static bool global_dictionary_init = false;
void EQ::InitializeDynamicLookups() {
if (global_dictionary_init == true)
if (global_dictionary_init)
return;
constants::InitializeDynamicLookups();
@@ -167,7 +167,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL,
ClientUnknown::INULL
),
ClientUnknown::INULL,
ClientUnknown::INULL,
ClientUnknown::INULL,
@@ -175,7 +175,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
ClientUnknown::INULL,
ClientUnknown::INULL,
ClientUnknown::INULL,
false,
false,
false,
@@ -194,7 +194,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
Client62::INULL, Client62::INULL, Client62::INULL,
Client62::INULL
),
Client62::INULL,
Client62::INULL,
Client62::INULL,
@@ -202,7 +202,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
Client62::INULL,
Client62::INULL,
Client62::INULL,
false,
false,
false,
@@ -221,7 +221,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
Titanium::INULL, Titanium::INULL, Titanium::INULL,
Titanium::invtype::OTHER_SIZE
),
Titanium::invslot::EQUIPMENT_BITMASK,
Titanium::invslot::GENERAL_BITMASK,
Titanium::invslot::CURSOR_BITMASK,
@@ -229,7 +229,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
Titanium::invslot::CORPSE_BITMASK,
Titanium::invbag::SLOT_COUNT,
Titanium::invaug::SOCKET_COUNT,
Titanium::inventory::AllowEmptyBagInBag,
Titanium::inventory::AllowClickCastFromBag,
Titanium::inventory::ConcatenateInvTypeLimbo,
@@ -248,7 +248,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
SoF::INULL, SoF::INULL, SoF::INULL,
SoF::invtype::OTHER_SIZE
),
SoF::invslot::EQUIPMENT_BITMASK,
SoF::invslot::GENERAL_BITMASK,
SoF::invslot::CURSOR_BITMASK,
@@ -256,7 +256,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
SoF::invslot::CORPSE_BITMASK,
SoF::invbag::SLOT_COUNT,
SoF::invaug::SOCKET_COUNT,
SoF::inventory::AllowEmptyBagInBag,
SoF::inventory::AllowClickCastFromBag,
SoF::inventory::ConcatenateInvTypeLimbo,
@@ -763,7 +763,7 @@ void EQ::inventory::InitializeDynamicLookups() {
// Notes:
// - Currently, there are only 3 known expansions that affect inventory-related settings in the clients..
// -- Expansion::PoR "Prophecy of Ro" - toggles between 24 (set) and 16 (clear) bank slots
// -- Expansion::TBS "The Buried Sea" - toggles slotPowerSource activated (set) and deactivated (clear)
// -- Expansion::TBS "The Buried Sea" - toggles slotPowerSource activated (set) and deactivated (clear)
// -- Expansion::HoT "House of Thule" - toggles slotGeneral9/slotGeneral10 activated (set) and deactivated (clear)
// - Corspe size does not appear to reflect loss of active possessions slots
// - Inspect size does not appear to reflect loss of active equipment slots
@@ -772,7 +772,7 @@ void EQ::inventory::InitializeDynamicLookups() {
// - General9 and General10 slots are activated by GM flag when expansion bit is (clear)
// - Obviously, the client must support the expansion to allow any (set) or override condition
const uint32 dynamic_check_mask =
const uint32 dynamic_check_mask =
(
EQ::expansions::bitPoR |
EQ::expansions::bitTBS |
@@ -1210,10 +1210,10 @@ void EQ::spells::InitializeDynamicLookups() {
if (spells_dictionary_init == true)
return;
spells_dictionary_init = true;
if (RuleB(World, UseClientBasedExpansionSettings))
return;
// use static references for now
}
@@ -1239,7 +1239,7 @@ const EQ::spells::LookupEntry* EQ::spells::DynamicGMLookup(versions::ClientVersi
client_version = versions::ValidateClientVersion(client_version);
if (spells_dynamic_gm_lookup_entries[static_cast<int>(client_version)])
return spells_dynamic_gm_lookup_entries[static_cast<int>(client_version)].get();
return &spells_static_lookup_entries[static_cast<int>(client_version)];
}
+48 -29
View File
@@ -374,18 +374,18 @@ struct NewZone_Struct {
/*0684*/ uint16 zone_id;
/*0686*/ uint16 zone_instance;
/*0688*/ uint32 unknown688;
/*0692*/ uint8 unknown692[8];
/*0692*/ uint8 unknown692[8];
// Titanium doesn't have a translator, but we can still safely add stuff under here without issues since client memcpy's only what it knows
// Just wastes some bandwidth sending to tit clients /shrug
/*0700*/ float fog_density;
/*0704*/ uint32 SuspendBuffs;
/*0708*/ uint32 FastRegenHP;
/*0712*/ uint32 FastRegenMana;
/*0716*/ uint32 FastRegenEndurance;
/*0720*/ uint32 NPCAggroMaxDist;
/*0724*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, if this value is 0, it prevents you from running off edges that would end up underworld
/*0728*/ uint32 LavaDamage; // Seen 50
/*0732*/ uint32 MinLavaDamage; // Seen 10
/*0700*/ float fog_density;
/*0704*/ uint32 suspend_buffs;
/*0708*/ uint32 fast_regen_hp;
/*0712*/ uint32 fast_regen_mana;
/*0716*/ uint32 fast_regen_endurance;
/*0720*/ uint32 npc_aggro_max_dist;
/*0724*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, if this value is 0, it prevents you from running off edges that would end up underworld
/*0728*/ uint32 lava_damage; // Seen 50
/*0732*/ uint32 min_lava_damage; // Seen 10
/*0736*/
};
@@ -2192,11 +2192,19 @@ struct QuestReward_Struct
/*068*/
};
struct CashReward_Struct
{
/*000*/ uint32 copper;
/*004*/ uint32 silver;
/*008*/ uint32 gold;
/*012*/ uint32 platinum;
};
// Size: 8
struct Camera_Struct
{
uint32 duration; // Duration in ms
uint32 intensity; // Between 1023410176 and 1090519040
float intensity;
};
struct ZonePoint_Entry {
@@ -2316,9 +2324,12 @@ struct FaceChange_Struct {
/*004*/ uint8 hairstyle;
/*005*/ uint8 beard;
/*006*/ uint8 face;
/*007*/ uint32 drakkin_heritage;
/*011*/ uint32 drakkin_tattoo;
/*015*/ uint32 drakkin_details;
/*007*/ uint8 unused_padding;
/*008*/ uint32 drakkin_heritage;
/*012*/ uint32 drakkin_tattoo;
/*016*/ uint32 drakkin_details;
/*020*/ uint32 entity_id;
/*024*/
//there are only 10 faces for barbs changing woad just
//increase the face value by ten so if there were 8 woad
//designs then there would be 80 barb faces
@@ -2762,7 +2773,7 @@ struct EnvDamage2_Struct {
/*0004*/ uint16 unknown4;
/*0006*/ uint32 damage;
/*0010*/ uint8 unknown10[12];
/*0022*/ uint8 dmgtype; //FA = Lava; FC = Falling
/*0022*/ uint8 dmgtype; // FA = Lava, FB = Drowning, FC = Falling, FD = Trap
/*0023*/ uint8 unknown2[4];
/*0027*/ uint16 constant; //Always FFFF
/*0029*/ uint16 unknown29;
@@ -3621,14 +3632,17 @@ struct LevelAppearance_Struct { //Sends a little graphic on level up
};
struct MerchantList {
uint32 id;
uint32 slot;
uint32 item;
int16 faction_required;
int8 level_required;
uint16 alt_currency_cost;
uint32 classes_required;
uint8 probability;
uint32 id;
uint32 slot;
uint32 item;
int16 faction_required;
int8 level_required;
uint16 alt_currency_cost;
uint32 classes_required;
uint8 probability;
std::string bucket_name;
std::string bucket_value;
uint8 bucket_comparison;
};
struct TempMerchantList {
@@ -4531,7 +4545,7 @@ struct ItemVerifyReply_Struct {
struct ItemRecastDelay_Struct {
/*000*/ uint32 recast_delay; // in seconds
/*004*/ uint32 recast_type;
/*008*/ uint32 unknown008;
/*008*/ bool ignore_casting_requirement; //Ignores recast times allows items to be reset?
/*012*/
};
@@ -4992,7 +5006,7 @@ struct DynamicZoneCompassEntry_Struct
/*000*/ uint16 dz_zone_id; // target dz id pair
/*002*/ uint16 dz_instance_id;
/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green)
/*008*/ uint32 unknown008;
/*008*/ uint32 dz_switch_id;
/*012*/ float y;
/*016*/ float x;
/*020*/ float z;
@@ -5149,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;
@@ -5582,6 +5596,11 @@ struct SayLinkBodyFrame_Struct {
/*056*/
};
struct Checksum_Struct {
uint64 checksum;
uint8 data[2048];
};
struct UpdateMovementEntry {
/* 00 */ float Y;
/* 04 */ float X;
+7 -7
View File
@@ -23,7 +23,7 @@
#include "op_codes.h"
#include "crc16.h"
#include "platform.h"
#include "string_util.h"
#include "strings.h"
#include <string>
#include <iomanip>
@@ -406,7 +406,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
LogNetcode(_L "Pre-OOA Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
}
//if the packet they got out of order is between our last acked packet and the last sent packet, then its valid.
if (CompareSequence(SequencedBase,seq) != SeqPast && CompareSequence(NextOutSeq,seq) == SeqPast) {
Log(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfOrderAck for sequence %d, starting retransmit at the start of our unacked buffer (seq %d, was %d)." __L,
@@ -453,7 +453,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
(unsigned long)ntohl(ClientStats->packets_received), (unsigned long)ntohl(ClientStats->packets_sent), (unsigned long)ntohl(ClientStats->last_local_delta),
(unsigned long)ntohl(ClientStats->low_delta), (unsigned long)ntohl(ClientStats->average_delta),
(unsigned long)ntohl(ClientStats->high_delta), (unsigned long)ntohl(ClientStats->last_remote_delta));
AdjustRates(ntohl(ClientStats->average_delta));
if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) {
@@ -951,7 +951,7 @@ EQRawApplicationPacket *p=nullptr;
EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode);
if (emu_op == OP_Unknown) {
// Log(Logs::General, Logs::Client_Server_Packet_Unhandled, "Unknown :: [%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->opcode, p->Size(), DumpPacketToString(p).c_str());
}
}
p->SetOpcode(emu_op);
}
}
@@ -1359,11 +1359,11 @@ void EQStream::AdjustRates(uint32 average_delta)
DecayRate=DECAYBASE/average_delta;
if (BytesWritten > RateThreshold)
BytesWritten = RateThreshold + DecayRate;
Log(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L,
Log(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L,
RateThreshold, DecayRate, average_delta);
MRate.unlock();
} else {
Log(Logs::Detail, Logs::Netcode, _L "Not adjusting data rate because avg delta over max (%d > %d)" __L,
Log(Logs::Detail, Logs::Netcode, _L "Not adjusting data rate because avg delta over max (%d > %d)" __L,
average_delta, AVERAGE_DELTA_MAX);
AverageDelta = AVERAGE_DELTA_MAX;
}
@@ -1374,7 +1374,7 @@ void EQStream::AdjustRates(uint32 average_delta)
BytesWritten = 0;
RateThreshold=RATEBASE/average_delta;
DecayRate=DECAYBASE/average_delta;
Log(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L,
Log(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L,
RateThreshold, DecayRate, average_delta);
MRate.unlock();
}
+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_*/
+4
View File
@@ -100,6 +100,10 @@ void EQEmuConfig::parse_config()
WorldHTTPEnabled = true;
}
if (_root["server"].get("disable_config_checks", "false").asString() == "true") {
DisableConfigChecks = true;
}
/**
* UCS
*/
+18 -7
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;
@@ -58,6 +60,7 @@ class EQEmuConfig
uint16 WorldHTTPPort;
std::string WorldHTTPMimeFile;
std::string SharedKey;
bool DisableConfigChecks;
// From <chatserver/>
std::string ChatHost;
@@ -130,7 +133,7 @@ class EQEmuConfig
void parse_config();
EQEmuConfig()
{
{
}
virtual ~EQEmuConfig() {}
@@ -151,30 +154,38 @@ 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();
}
catch (std::exception &) {
return false;
}
}
return true;
}
+370 -310
View File
@@ -21,20 +21,20 @@
#include "eqemu_logsys.h"
#include "rulesys.h"
#include "platform.h"
#include "string_util.h"
#include "misc.h"
#include "strings.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>
@@ -46,50 +46,17 @@ std::ofstream process_log;
#include <unistd.h>
#include <sys/stat.h>
#include <thread>
#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()
{
on_log_gmsay_hook = [](uint16 log_type, const std::string &) {};
on_log_console_hook = [](uint16 debug_level, 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 &) {};
}
/**
@@ -102,46 +69,43 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
/**
* Get Executable platform currently running this code (Zone/World/etc)
*/
log_platform = GetExecutablePlatformInt();
m_log_platform = GetExecutablePlatformInt();
for (int log_category_id = Logs::AA; log_category_id != Logs::MaxCategoryID; log_category_id++) {
log_settings[log_category_id].log_to_console = 0;
log_settings[log_category_id].log_to_file = 0;
log_settings[log_category_id].log_to_gmsay = 0;
log_settings[log_category_id].log_to_discord = 0;
log_settings[log_category_id].is_category_enabled = 0;
}
file_logs_enabled = false;
m_file_logs_enabled = false;
/**
* 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);
log_settings[Logs::Loot].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::Scheduler].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Cheat].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HTTP].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HTTP].log_to_gmsay = 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::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);
log_settings[Logs::Loot].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::Scheduler].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Cheat].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HTTP].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HTTP].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::ChecksumVerification].log_to_console = static_cast<uint8>(Logs::General);
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);
/**
@@ -151,7 +115,8 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
const bool log_to_console = log_settings[log_category_id].log_to_console > 0;
const bool log_to_file = log_settings[log_category_id].log_to_file > 0;
const bool log_to_gmsay = log_settings[log_category_id].log_to_gmsay > 0;
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay;
const bool log_to_discord = log_settings[log_category_id].log_to_discord > 0;
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay || log_to_discord;
if (is_category_enabled) {
log_settings[log_category_id].is_category_enabled = 1;
}
@@ -160,99 +125,37 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
/**
* Declare process file names for log writing=
*/
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformWorld) {
platform_file_name = "world";
if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformWorld) {
m_platform_file_name = "world";
}
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformQueryServ) {
platform_file_name = "query_server";
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformQueryServ) {
m_platform_file_name = "query_server";
}
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) {
platform_file_name = "zone";
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone) {
m_platform_file_name = "zone";
}
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformUCS) {
platform_file_name = "ucs";
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformUCS) {
m_platform_file_name = "ucs";
}
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin) {
platform_file_name = "login";
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformLogin) {
m_platform_file_name = "login";
}
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLaunch) {
platform_file_name = "launcher";
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformLaunch) {
m_platform_file_name = "launcher";
}
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformHC) {
platform_file_name = "hc";
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformHC) {
m_platform_file_name = "hc";
}
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
* @param message
*/
void EQEmuLogSys::ProcessGMSay(
uint16 debug_level,
uint16 log_category,
const std::string &message
)
{
/**
* Enabling Netcode based GMSay output creates a feedback loop that ultimately ends in a crash
*/
if (log_category == Logs::LogCategory::Netcode) {
return;
}
/**
* Processes that actually support hooks
*/
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone ||
EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformWorld
) {
on_log_gmsay_hook(log_category, message);
}
}
/**
* @param debug_level
* @param log_category
* @param message
*/
void EQEmuLogSys::ProcessLogWrite(
uint16 debug_level,
uint16 log_category,
const std::string &message
)
@@ -263,79 +166,20 @@ void EQEmuLogSys::ProcessLogWrite(
std::ofstream crash_log;
EQEmuLogSys::MakeDirectory("logs/crashes");
crash_log.open(
StringFormat("logs/crashes/crash_%s_%i.log", platform_file_name.c_str(), getpid()),
StringFormat("logs/crashes/crash_%s_%i.log", m_platform_file_name.c_str(), getpid()),
std::ios_base::app | std::ios_base::out
);
crash_log << time_stamp << " " << message << "\n";
crash_log.close();
}
char time_stamp[80];
EQEmuLogSys::SetCurrentTimeStamp(time_stamp);
if (process_log) {
char time_stamp[80];
EQEmuLogSys::SetCurrentTimeStamp(time_stamp);
process_log << time_stamp << " " << message << std::endl;
}
}
/**
* @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
@@ -343,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:
@@ -364,30 +206,146 @@ uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
}
}
/**
* @param debug_level
* @param log_category
* @param message
*/
void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, 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
);
on_log_console_hook(debug_level, log_category, message);
(!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);
}
/**
@@ -399,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
*
@@ -444,47 +375,55 @@ void EQEmuLogSys::Out(
...
)
{
bool log_to_console = true;
if (log_settings[log_category].log_to_console < debug_level) {
log_to_console = false;
}
auto l = GetLogsEnabled(debug_level, log_category);
bool log_to_file = true;
if (log_settings[log_category].log_to_file < debug_level) {
log_to_file = false;
}
bool log_to_gmsay = true;
if (log_settings[log_category].log_to_gmsay < debug_level) {
log_to_gmsay = false;
}
const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay;
if (nothing_to_log) {
// bail out 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(debug_level, log_category, output_debug_message);
if (l.log_to_console_enabled) {
EQEmuLogSys::ProcessConsoleMessage(
log_category,
output_message,
file,
func,
line
);
}
if (log_to_gmsay) {
EQEmuLogSys::ProcessGMSay(debug_level, log_category, output_debug_message);
if (l.log_to_gmsay_enabled) {
m_on_log_gmsay_hook(log_category, func, output_message);
}
if (log_to_file) {
EQEmuLogSys::ProcessLogWrite(debug_level, 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 (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);
}
}
@@ -497,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);
}
/**
@@ -536,53 +475,45 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name)
/**
* When loading settings, we must have been given a reason in category based logging to output to a file in order to even create or open one...
*/
if (!file_logs_enabled) {
if (!m_file_logs_enabled) {
return;
}
/**
* Zone
*/
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) {
if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone) {
if (!log_name.empty()) {
platform_file_name = log_name;
m_platform_file_name = log_name;
}
if (platform_file_name.empty()) {
if (m_platform_file_name.empty()) {
return;
}
LogInfo("Starting File Log [logs/{}_{}.log]", 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", 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
*/
if (platform_file_name.empty()) {
// All other processes
if (m_platform_file_name.empty()) {
return;
}
LogInfo("Starting File Log [logs/{}_{}.log]", 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", 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
);
}
@@ -597,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);
}
/**
@@ -612,6 +545,8 @@ void EQEmuLogSys::EnableConsoleLogging()
EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
{
InjectTablesIfNotExist();
auto categories = LogsysCategoriesRepository::GetWhere(
*m_database,
"TRUE ORDER BY log_category_id"
@@ -627,16 +562,20 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
continue;
}
log_settings[c.log_category_id].log_to_console = static_cast<uint8>(c.log_to_console);
log_settings[c.log_category_id].log_to_file = static_cast<uint8>(c.log_to_file);
log_settings[c.log_category_id].log_to_gmsay = static_cast<uint8>(c.log_to_gmsay);
log_settings[c.log_category_id].log_to_console = static_cast<uint8>(c.log_to_console);
log_settings[c.log_category_id].log_to_file = static_cast<uint8>(c.log_to_file);
log_settings[c.log_category_id].log_to_gmsay = static_cast<uint8>(c.log_to_gmsay);
log_settings[c.log_category_id].log_to_discord = static_cast<uint8>(c.log_to_discord);
log_settings[c.log_category_id].discord_webhook_id = c.discord_webhook_id;
// Determine if any output method is enabled for the category
// and set it to 1 so it can used to check if category is enabled
const bool log_to_console = log_settings[c.log_category_id].log_to_console > 0;
const bool log_to_file = log_settings[c.log_category_id].log_to_file > 0;
const bool log_to_gmsay = log_settings[c.log_category_id].log_to_gmsay > 0;
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay;
const bool log_to_discord = log_settings[c.log_category_id].log_to_discord > 0 &&
log_settings[c.log_category_id].discord_webhook_id > 0;
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay || log_to_discord;
if (is_category_enabled) {
log_settings[c.log_category_id].is_category_enabled = 1;
@@ -646,7 +585,7 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
// If we go through this whole loop and nothing is set to any debug level, there
// is no point to create a file or keep anything open
if (log_settings[c.log_category_id].log_to_file > 0) {
LogSys.file_logs_enabled = true;
LogSys.m_file_logs_enabled = true;
}
db_categories.emplace_back(c.log_category_id);
@@ -654,18 +593,32 @@ 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();
new_category.log_category_id = i;
new_category.log_category_description = EscapeString(Logs::LogCategoryName[i]);
new_category.log_category_description = Strings::Escape(Logs::LogCategoryName[i]);
new_category.log_to_console = log_settings[i].log_to_console;
new_category.log_to_gmsay = log_settings[i].log_to_gmsay;
new_category.log_to_file = log_settings[i].log_to_file;
new_category.log_to_discord = log_settings[i].log_to_discord;
LogsysCategoriesRepository::InsertOne(*m_database, new_category);
}
@@ -673,6 +626,19 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
LogInfo("Loaded [{}] log categories", categories.size());
auto webhooks = DiscordWebhooksRepository::GetWhere(*m_database, fmt::format("id < {}", MAX_DISCORD_WEBHOOK_ID));
if (!webhooks.empty()) {
for (auto &w: webhooks) {
m_discord_webhooks[w.id] = {w.id, w.webhook_name, w.webhook_url};
}
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;
}
@@ -682,3 +648,97 @@ EQEmuLogSys *EQEmuLogSys::SetDatabase(Database *db)
return this;
}
void EQEmuLogSys::InjectTablesIfNotExist()
{
// do not run injections for zone as its unnecessary hits every time a zone boots
// other processes less frequently ran can pick up injection
if (m_log_platform == EQEmuExePlatform::ExePlatformZone) {
return;
}
// inject discord_webhooks
if (!m_database->DoesTableExist("discord_webhooks")) {
LogInfo("Creating table [discord_webhooks]");
m_database->QueryDatabase(
SQL(
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;
)
);
}
// inject logsys_categories
if (!m_database->DoesTableExist("logsys_categories")) {
LogInfo("Creating table [logsys_categories]");
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
)
);
}
}
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;
}
+122 -63
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,
@@ -127,6 +126,16 @@ namespace Logs {
DiaWind,
HTTP,
Saylink,
ChecksumVerification,
CombatRecord,
Hate,
Discord,
Faction,
PacketServerClient,
PacketClientServer,
PacketServerToServer,
Bugs,
QuestErrors,
MaxCategoryID /* Don't Remove this */
};
@@ -139,7 +148,7 @@ namespace Logs {
"AI",
"Aggro",
"Attack",
"Packet :: Client -> Server",
"Deprecated",
"Combat",
"Commands",
"Crash",
@@ -150,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",
@@ -212,6 +221,16 @@ namespace Logs {
"DialogueWindow",
"HTTP",
"Saylink",
"ChecksumVer",
"CombatRecord",
"Hate",
"Discord",
"Faction",
"Packet S->C",
"Packet C->S",
"Packet S->S",
"Bugs",
"QuestErrors"
};
}
@@ -219,6 +238,8 @@ namespace Logs {
class Database;
constexpr uint16 MAX_DISCORD_WEBHOOK_ID = 300;
class EQEmuLogSys {
public:
EQEmuLogSys();
@@ -281,9 +302,19 @@ public:
uint8 log_to_file;
uint8 log_to_console;
uint8 log_to_gmsay;
uint8 log_to_discord;
int discord_webhook_id;
uint8 is_category_enabled; /* When any log output in a category > 0, set this to 1 as (Enabled) */
};
struct OriginationInfo {
std::string zone_short_name;
std::string zone_long_name;
int instance_id;
};
OriginationInfo origination_info{};
/**
* Internally used memory reference for all log settings per category
* These are loaded via DB and have defaults loaded in LoadLogSettingsDefaults
@@ -291,50 +322,78 @@ public:
*/
LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{};
bool file_logs_enabled = false;
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;
};
int log_platform = 0;
std::string platform_file_name;
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;
std::string webhook_url;
};
const DiscordWebhooks *GetDiscordWebhooks() const;
// gmsay
uint16 GetGMSayColorFromCategory(uint16 log_category);
EQEmuLogSys * SetGMSayHandler(std::function<void(uint16 log_type, const std::string &)> f) {
on_log_gmsay_hook = 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;
}
EQEmuLogSys *SetDiscordHandler(std::function<void(uint16 log_category, int webhook_id, const std::string &)> f)
{
m_on_log_discord_hook = f;
return this;
}
// console
void SetConsoleHandler(
std::function<void(
uint16 debug_level,
uint16 log_type,
const std::string &
)> f
) { on_log_console_hook = f; }
) { m_on_log_console_hook = f; }
void SilenceConsoleLogging();
void EnableConsoleLogging();
// 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;
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::function<void(uint16 log_category, const std::string &)> on_log_gmsay_hook;
std::function<void(uint16 debug_level, uint16 log_category, const std::string &)> on_log_console_hook;
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 debug_level, uint16 log_category, const std::string &message);
void ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message);
void ProcessLogWrite(uint16 debug_level, uint16 log_category, const std::string &message);
bool IsRfc5424LogCategory(uint16 log_category);
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);
void InjectTablesIfNotExist();
};
extern EQEmuLogSys LogSys;
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -1,14 +1,14 @@
#pragma once
#include <any>
#include <functional>
#include <exception>
#include "event_loop.h"
#include "../any.h"
namespace EQ {
class Task
{
public:
typedef std::function<void(const EQ::Any&)> ResolveFn;
typedef std::function<void(const std::any&)> ResolveFn;
typedef std::function<void(const std::exception&)> RejectFn;
typedef std::function<void()> FinallyFn;
typedef std::function<void(ResolveFn, RejectFn)> TaskFn;
@@ -19,7 +19,7 @@ namespace EQ {
RejectFn on_catch;
FinallyFn on_finally;
bool has_result;
EQ::Any result;
std::any result;
bool has_error;
std::exception error;
};
@@ -63,7 +63,7 @@ namespace EQ {
uv_queue_work(EventLoop::Get().Handle(), m_work, [](uv_work_t* req) {
TaskBaton *baton = (TaskBaton*)req->data;
baton->fn([baton](const EQ::Any& result) {
baton->fn([baton](const std::any& result) {
baton->has_error = false;
baton->has_result = true;
baton->result = result;
+2 -2
View File
@@ -60,8 +60,8 @@ namespace EQ
}
template<typename Fn, typename... Args>
auto Enqueue(Fn&& fn, Args&&... args) -> std::future<typename std::result_of<Fn(Args...)>::type> {
using return_type = typename std::result_of<Fn(Args...)>::type;
auto Enqueue(Fn&& fn, Args&&... args) -> std::future<typename std::invoke_result<Fn, Args...>::type> {
using return_type = typename std::invoke_result<Fn, Args...>::type;
auto task = std::make_shared<std::packaged_task<return_type()>>(
std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...)
+1 -1
View File
@@ -19,7 +19,7 @@
*/
#include "expedition_lockout_timer.h"
#include "../common/string_util.h"
#include "../common/strings.h"
#include "../common/rulesys.h"
#include "../common/util/uuid.h"
#include <fmt/format.h>
+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;
}
}
+17
View File
@@ -75,6 +75,23 @@ struct NPCFaction
uint8 temp;
};
// Faction Associations give a much more live like faction system
// Basically the primary faction and magnitude of a faction hit will generate the rest of them
// Largest faction I could find quickly was Lord Inquisitor Seru with 9 total hits (8 associations) so 8 + 2 for max for now
#define MAX_FACTION_ASSOC 10
// this is the ID of a faction association and it's multiplier
struct FactionAssociationHit {
int id;
float multiplier;
};
struct FactionAssociations {
// maybe there should be more data here, fine for now
FactionAssociationHit hits[MAX_FACTION_ASSOC];
};
const char *FactionValueToString(FACTION_VALUE faction_value);
FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value);
#endif
+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
+8 -20
View File
@@ -20,7 +20,7 @@
#include "database.h"
//#include "misc_functions.h"
#include "string_util.h"
#include "strings.h"
#include <cstdlib>
#include <cstring>
@@ -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;
}
@@ -1281,10 +1269,10 @@ bool BaseGuildManager::IsCharacterInGuild(uint32 character_id, uint32 guild_id)
if (current_guild_id == GUILD_NONE) {
return false;
}
if (guild_id && current_guild_id != guild_id) {
return false;
}
return true;
}
}
+2836 -2113
View File
File diff suppressed because it is too large Load Diff
+25 -11
View File
@@ -25,7 +25,7 @@
//#include "races.h"
//#include "rulesys.h"
//#include "shareddb.h"
#include "string_util.h"
#include "strings.h"
#include "../common/light_source.h"
@@ -245,7 +245,7 @@ int16 EQ::InventoryProfile::PutItem(int16 slot_id, const ItemInstance& inst)
if (temp_slot >= m_lookup->InventoryTypeSize.Bank)
return EQ::invslot::SLOT_INVALID;
}
// Clean up item already in slot (if exists)
DeleteItem(slot_id);
@@ -617,7 +617,7 @@ int EQ::InventoryProfile::CountAugmentEquippedByID(uint32 item_id)
quantity += item->CountAugmentByID(item_id);
}
}
return quantity;
}
@@ -648,7 +648,7 @@ int EQ::InventoryProfile::CountItemEquippedByID(uint32 item_id)
quantity += item->IsStackable() ? item->GetCharges() : 1;
}
}
return quantity;
}
@@ -993,7 +993,7 @@ int16 EQ::InventoryProfile::CalcSlotId(int16 slot_id) {
//else if (slot_id >= EmuConstants::BANK_BEGIN && slot_id <= EmuConstants::BANK_END)
// parent_slot_id = EmuConstants::BANK_BEGIN + (slot_id - EmuConstants::BANK_BEGIN) / EmuConstants::ITEM_CONTAINER_SIZE;
//else if (slot_id >= 3100 && slot_id <= 3179) should be {3031..3110}..where did this range come from!!? (verified db save range)
if (slot_id >= invbag::GENERAL_BAGS_BEGIN && slot_id <= invbag::GENERAL_BAGS_END) {
parent_slot_id = invslot::GENERAL_BEGIN + (slot_id - invbag::GENERAL_BAGS_BEGIN) / invbag::SLOT_COUNT;
}
@@ -1231,7 +1231,7 @@ uint8 EQ::InventoryProfile::FindBrightestLightType()
for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) {
if ((iter->first < invslot::EQUIPMENT_BEGIN || iter->first > invslot::EQUIPMENT_END))
continue;
if (iter->first == invslot::slotAmmo)
continue;
@@ -1369,7 +1369,7 @@ EQ::ItemInstance* EQ::InventoryProfile::_GetItem(const std::map<int16, ItemInsta
if (slot_id - EQ::invslot::BANK_BEGIN >= m_lookup->InventoryTypeSize.Bank)
return nullptr;
}
auto it = bucket.find(slot_id);
if (it != bucket.end()) {
return it->second;
@@ -1441,7 +1441,7 @@ int16 EQ::InventoryProfile::_PutItem(int16 slot_id, ItemInstance* inst)
result = slot_id;
}
}
if (result == INVALID_INDEX) {
LogError("InventoryProfile::_PutItem: Invalid slot_id specified ({}) with parent slot id ({})", slot_id, parentSlot);
InventoryProfile::MarkDirty(inst); // Slot not found, clean up
@@ -1478,7 +1478,7 @@ int16 EQ::InventoryProfile::_HasItem(std::map<int16, ItemInstance*>& bucket, uin
if (inst->GetAugmentItemID(index) == item_id && quantity <= 1)
return invslot::SLOT_AUGMENT_GENERIC_RETURN;
}
if (!inst->IsClassBag()) { continue; }
for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) {
@@ -1509,7 +1509,7 @@ int16 EQ::InventoryProfile::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint
// is sufficient. However, in cases where referential criteria is considered, this can lead
// to unintended results. Funtionality should be observed when referencing the return value
// of this query
uint32 quantity_found = 0;
for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) {
@@ -1715,6 +1715,20 @@ int16 EQ::InventoryProfile::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 lo
// We only check the visible cursor due to lack of queue processing ability (client allows duplicate in limbo)
break;
}
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
+5 -5
View File
@@ -19,7 +19,7 @@
#include "inventory_slot.h"
#include "textures.h"
#include "string_util.h"
#include "strings.h"
int8 EQ::inventory::ConvertEquipmentIndexToTextureIndex(int16 slot_index)
@@ -86,7 +86,7 @@ bool EQ::InventorySlot::IsValidSlot() const
{
if (_typeless)
return false;
int16 slot_count = invtype::GetInvTypeSize(_type_index);
if (!slot_count || _slot_index < invslot::SLOT_BEGIN || _slot_index >= slot_count)
return false;
@@ -136,7 +136,7 @@ bool EQ::InventorySlot::IsWeaponIndex(int16 slot_index)
{
if (slot_index == invslot::slotPrimary || slot_index == invslot::slotSecondary || slot_index == invslot::slotRange)
return true;
return false;
}
@@ -364,7 +364,7 @@ bool EQ::InventorySlot::operator<(const InventorySlot& rhs) const
{
if (Typeless() || rhs.Typeless())
return inventory_slot_typeless_lessthan(*this, rhs);
if (TypeIndex() < rhs.TypeIndex())
return true;
@@ -384,6 +384,6 @@ bool EQ::operator==(const InventorySlot& lhs, const InventorySlot& rhs)
{
if (lhs.Typeless() || rhs.Typeless())
return ((lhs.SlotIndex() == rhs.SlotIndex()) && (lhs.ContainerIndex() == rhs.ContainerIndex()) && (lhs.SocketIndex() == rhs.SocketIndex()));
return ((lhs.TypeIndex() == rhs.TypeIndex()) && (lhs.SlotIndex() == rhs.SlotIndex()) && (lhs.ContainerIndex() == rhs.ContainerIndex()) && (lhs.SocketIndex() == rhs.SocketIndex()));
}
+155
View File
@@ -18,7 +18,17 @@
*
*/
#include <cstring>
#include <fmt/format.h>
#include <csignal>
#include <vector>
#include "ip_util.h"
#include "http/httplib.h"
#include "http/uri.h"
#include "eqemu_logsys.h"
#include "event/event_loop.h"
#include "net/dns.h"
#include "event/task_scheduler.h"
/**
* @param ip
@@ -70,3 +80,148 @@ bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip)
IpUtil::IsIpInRange(ip, "192.168.0.0", "255.255.0.0")
);
}
/**
* Gets local address - pings google to inspect what interface was used locally
* @return
*/
std::string IpUtil::GetLocalIPAddress()
{
char my_ip_address[16];
unsigned int my_port;
struct sockaddr_in server_address{};
struct sockaddr_in my_address{};
int sockfd;
// Connect to server
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
return "";
}
// Set server_addr
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("172.217.160.99");
server_address.sin_port = htons(80);
// Connect to server
if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
close(sockfd);
return "";
}
// Get my ip address and port
memset(&my_address, 0, sizeof(my_address));
socklen_t len = sizeof(my_address);
getsockname(sockfd, (struct sockaddr *) &my_address, &len);
inet_ntop(AF_INET, &my_address.sin_addr, my_ip_address, sizeof(my_ip_address));
my_port = ntohs(my_address.sin_port);
return fmt::format("{}", my_ip_address);
}
/**
* Gets public address
* Uses various websites as options to return raw public IP back to the client
* @return
*/
std::string IpUtil::GetPublicIPAddress()
{
std::vector<std::string> endpoints = {
"http://ifconfig.me",
"http://api.ipify.org",
"http://ipinfo.io/ip",
"http://ipecho.net/plain",
};
for (auto &s: endpoints) {
// http get request
uri u(s);
httplib::Client r(
fmt::format(
"{}://{}",
u.get_scheme(),
u.get_host()
).c_str()
);
httplib::Headers headers = {
{"Content-type", "text/plain; charset=utf-8"},
{"User-Agent", "curl/7.81.0"}
};
r.set_connection_timeout(1, 0);
r.set_read_timeout(1, 0);
r.set_write_timeout(1, 0);
if (auto res = r.Get(fmt::format("/{}", u.get_path()).c_str(), headers)) {
if (res->status == 200) {
if (res->body.find('.') != std::string::npos) {
return res->body;
}
}
}
}
return {};
}
std::string IpUtil::DNSLookupSync(const std::string &addr, int port)
{
auto task_runner = new EQ::Event::TaskScheduler();
auto res = task_runner->Enqueue(
[&]() -> std::string {
bool running = true;
std::string ret;
EQ::Net::DNSLookup(
addr, port, false, [&](const std::string &addr) {
ret = addr;
if (addr.empty()) {
ret = "";
running = false;
}
return ret;
}
);
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
auto &loop = EQ::EventLoop::Get();
while (running) {
if (!ret.empty()) {
running = false;
}
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(
"Deadline exceeded [{}]",
1500
);
running = false;
}
loop.Process();
}
return ret;
}
);
std::string result = res.get();
safe_delete(task_runner);
return result;
}
bool IpUtil::IsIPAddress(const std::string &ip_address)
{
struct sockaddr_in sa{};
int result = inet_pton(AF_INET, ip_address.c_str(), &(sa.sin_addr));
return result != 0;
}
+8 -1
View File
@@ -30,7 +30,14 @@ public:
static uint32_t IPToUInt(const std::string &ip);
static bool IsIpInRange(const std::string &ip, const std::string &network, const std::string &mask);
static bool IsIpInPrivateRfc1918(const std::string &ip);
static std::string GetLocalIPAddress();
static std::string GetPublicIPAddress();
static std::string DNSLookupSync(
const std::string &addr,
int port
);
static bool IsIPAddress(const std::string &ip_address);
};
#endif //EQEMU_IP_UTIL_H
#endif //EQEMU_IP_UTIL_H
+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;
}
+11 -9
View File
@@ -370,7 +370,7 @@ namespace EQ
uint32 Slots; // Bitfield for which slots this item can be used in
uint32 Price; // Item cost (?)
uint32 Icon; // Icon Number
uint32 LoreGroup; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295)
int32 LoreGroup; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295)
bool LoreFlag; // This will be true if LoreGroup is non-zero
bool PendingLoreFlag;
bool ArtifactFlag;
@@ -473,14 +473,14 @@ namespace EQ
uint32 LDoNSold;
uint32 BaneDmgRaceAmt;
uint32 AugRestrict;
uint32 Endur;
uint32 DotShielding;
uint32 Attack;
uint32 Regen;
uint32 ManaRegen;
uint32 EnduranceRegen;
uint32 Haste;
uint32 DamageShield;
int32 Endur;
int32 DotShielding;
int32 Attack;
int32 Regen;
int32 ManaRegen;
int32 EnduranceRegen;
int32 Haste;
int32 DamageShield;
uint32 RecastDelay;
int RecastType;
uint32 AugDistiller;
@@ -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;
+89 -41
View File
@@ -23,7 +23,7 @@
//#include "races.h"
#include "rulesys.h"
#include "shareddb.h"
#include "string_util.h"
#include "strings.h"
//#include "../common/light_source.h"
@@ -214,7 +214,7 @@ EQ::ItemInstance::~ItemInstance()
bool EQ::ItemInstance::IsType(item::ItemClass item_class) const
{
// IsType(<ItemClassTypes>) does not protect against 'm_item = nullptr'
// Check usage type
if ((m_use_type == ItemInstWorldContainer) && (item_class == item::ItemClassBag))
return true;
@@ -245,7 +245,7 @@ bool EQ::ItemInstance::IsStackable() const
{
if (!m_item)
return false;
return m_item->Stackable;
}
@@ -253,7 +253,7 @@ bool EQ::ItemInstance::IsCharged() const
{
if (!m_item)
return false;
if (m_item->MaxCharges > 1)
return true;
else
@@ -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
@@ -381,7 +415,7 @@ EQ::ItemInstance* EQ::ItemInstance::PopItem(uint8 index)
m_contents.erase(index);
return inst; // Return pointer that needs to be deleted (or otherwise managed)
}
return nullptr;
}
@@ -476,7 +510,7 @@ uint8 EQ::ItemInstance::GetTotalItemCount() const
{
if (!m_item)
return 0;
uint8 item_count = 1;
if (m_item && !m_item->IsClassBag()) { return item_count; }
@@ -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;
}
@@ -526,7 +561,7 @@ EQ::ItemInstance* EQ::ItemInstance::GetOrnamentationAug(int32 ornamentationAugty
{
continue;
}
return this->GetAugment(i);
return GetAugment(i);
}
}
@@ -549,7 +584,7 @@ uint32 EQ::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const {
bool EQ::ItemInstance::UpdateOrnamentationInfo() {
if (!m_item || !m_item->IsClassCommon())
return false;
bool ornamentSet = false;
int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType);
@@ -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
@@ -642,7 +678,7 @@ void EQ::ItemInstance::PutAugment(uint8 slot, const ItemInstance& augment)
{
if (!m_item || !m_item->IsClassCommon())
return;
PutItem(slot, augment);
}
@@ -655,7 +691,7 @@ void EQ::ItemInstance::PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id
if (aug) {
PutAugment(slot, *aug);
safe_delete(aug);
}
}
}
// Remove augment from item and destroy it
@@ -663,7 +699,7 @@ void EQ::ItemInstance::DeleteAugment(uint8 index)
{
if (!m_item || !m_item->IsClassCommon())
return;
DeleteItem(index);
}
@@ -672,7 +708,7 @@ EQ::ItemInstance* EQ::ItemInstance::RemoveAugment(uint8 index)
{
if (!m_item || !m_item->IsClassCommon())
return nullptr;
return PopItem(index);
}
@@ -680,7 +716,7 @@ bool EQ::ItemInstance::IsAugmented()
{
if (!m_item || !m_item->IsClassCommon())
return false;
for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) {
if (GetAugmentItemID(index))
return true;
@@ -698,7 +734,7 @@ bool EQ::ItemInstance::ContainsAugmentByID(uint32 item_id)
if (!item_id) {
return false;
}
for (uint8 augment_slot = invaug::SOCKET_BEGIN; augment_slot <= invaug::SOCKET_END; ++augment_slot) {
if (GetAugmentItemID(augment_slot) == item_id) {
return true;
@@ -718,7 +754,7 @@ int EQ::ItemInstance::CountAugmentByID(uint32 item_id)
if (!item_id) {
return quantity;
}
for (uint8 augment_slot = invaug::SOCKET_BEGIN; augment_slot <= invaug::SOCKET_END; ++augment_slot) {
if (GetAugmentItemID(augment_slot) == item_id) {
quantity++;
@@ -873,7 +909,7 @@ bool EQ::ItemInstance::IsDroppable(bool recurse) const
return false;
}
}
return true;
}
@@ -1097,7 +1133,7 @@ int EQ::ItemInstance::GetItemElementalFlag(bool augments) const
int EQ::ItemInstance::GetItemElementalDamage(bool augments) const
{
int damage = 0;
int64 damage = 0;
const auto item = GetItem();
if (item) {
damage = item->ElemDmgAmt;
@@ -1162,7 +1198,7 @@ int EQ::ItemInstance::GetItemRequiredLevel(bool augments) const
int EQ::ItemInstance::GetItemWeaponDamage(bool augments) const
{
int damage = 0;
int64 damage = 0;
const auto item = GetItem();
if (item) {
damage = item->Damage;
@@ -1178,7 +1214,7 @@ int EQ::ItemInstance::GetItemWeaponDamage(bool augments) const
int EQ::ItemInstance::GetItemBackstabDamage(bool augments) const
{
int damage = 0;
int64 damage = 0;
const auto item = GetItem();
if (item) {
damage = item->BackstabDmg;
@@ -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;
@@ -1236,7 +1272,7 @@ int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const
int EQ::ItemInstance::GetItemBaneDamageBody(bodyType against, bool augments) const
{
int damage = 0;
int64 damage = 0;
const auto item = GetItem();
if (item) {
if (item->BaneDmgBody == against)
@@ -1253,7 +1289,7 @@ int EQ::ItemInstance::GetItemBaneDamageBody(bodyType against, bool augments) con
int EQ::ItemInstance::GetItemBaneDamageRace(uint16 against, bool augments) const
{
int damage = 0;
int64 damage = 0;
const auto item = GetItem();
if (item) {
if (item->BaneDmgRace == against)
@@ -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
//
@@ -1745,4 +1793,4 @@ EvolveInfo::EvolveInfo(uint32 first, uint8 max, bool allkills, uint32 L2, uint32
EvolveInfo::~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);
+14 -5
View File
@@ -30,11 +30,19 @@ struct LootTableEntries_Struct {
float probability;
};
struct ContentFlags {
int16 min_expansion;
int16 max_expansion;
char content_flags[100];
char content_flags_disabled[100];
};
struct LootTable_Struct {
uint32 mincash;
uint32 maxcash;
uint32 avgcoin;
uint32 NumEntries;
uint32 mincash;
uint32 maxcash;
uint32 avgcoin;
uint32 NumEntries;
ContentFlags content_flags;
LootTableEntries_Struct Entries[0];
};
@@ -51,7 +59,8 @@ struct LootDropEntries_Struct {
};
struct LootDrop_Struct {
uint32 NumEntries;
uint32 NumEntries;
ContentFlags content_flags;
LootDropEntries_Struct Entries[0];
};
#pragma pack()
+2 -2
View File
@@ -9,7 +9,7 @@
*/
#include <string.h> /* for memcpy() */
#include "../common/md5.h"
#include "../common/string_util.h"
#include "../common/strings.h"
#include "../common/seperator.h"
MD5::MD5() {
@@ -194,7 +194,7 @@ void MD5::Final(uint8 digest[16], MD5Context *ctx) {
/* The heart of the MD5 algorithm. */
void MD5::Transform(uint32 hash[4], const uint32 input[16]) {
register uint32 a = hash[0], b = hash[1], c = hash[2], d = hash[3];
uint32 a = hash[0], b = hash[1], c = hash[2], d = hash[3];
MD5STEP(F1, a, b, c, d, input[ 0]+0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, input[ 1]+0xe8c7b756, 12);
+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 {
+7 -1
View File
@@ -10,8 +10,14 @@
#include <iterator>
#include "types.h"
class MySQLRequestRow : public std::iterator<std::input_iterator_tag, MYSQL_ROW>
class MySQLRequestRow
{
public:
using iterator_category = std::input_iterator_tag;
using value_type = MYSQL_ROW;
using difference_type = std::ptrdiff_t;
using pointer = MYSQL_ROW*;
using reference = MYSQL_ROW&;
private:
MYSQL_RES* m_Result;
+6 -6
View File
@@ -1,5 +1,5 @@
#include "console_server.h"
#include "../string_util.h"
#include "../strings.h"
#include <fmt/format.h>
EQ::Net::ConsoleServer::ConsoleServer(const std::string &addr, int port)
@@ -52,11 +52,11 @@ void EQ::Net::ConsoleServer::ConnectionDisconnected(ConsoleServerConnection *c)
void EQ::Net::ConsoleServer::ProcessCommand(ConsoleServerConnection *c, const std::string &cmd)
{
auto split = SplitString(cmd, ' ');
auto split = Strings::Split(cmd, ' ');
if (split.size() > 0) {
auto command = split[0];
ToLowerString(command);
command = Strings::ToLower(command);
if (command == "help" || command == "?") {
c->SendLine("Commands:");
@@ -70,9 +70,9 @@ void EQ::Net::ConsoleServer::ProcessCommand(ConsoleServerConnection *c, const st
c->SendPrompt();
return;
}
split.erase(split.begin(), split.begin() + 1);
auto cmd_def = m_commands.find(command);
if (cmd_def != m_commands.end()) {
if (c->Admin() >= cmd_def->second.status_required) {
+26 -27
View File
@@ -116,43 +116,42 @@ bool EQ::Net::ConsoleServerConnection::SendChannelMessage(const ServerChannelMes
}
switch (scm->chan_num) {
case 4: {
if (RuleB(Chat, ServerWideAuction)) {
QueueMessage(fmt::format("{0} auctions, '{1}'", scm->from, scm->message));
break;
} else { // I think we want default action in this case?
return false;
}
}
case 5: {
if (RuleB(Chat, ServerWideOOC)) {
QueueMessage(fmt::format("{0} says ooc, '{1}'", scm->from, scm->message));
break;
} else { // I think we want default action in this case?
return false;
}
}
case 6: {
QueueMessage(fmt::format("{0} BROADCASTS, '{1}'", scm->from, scm->message));
case ChatChannel_Guild: {
QueueMessage(fmt::format("{} tells the guild [{}], '{}'", scm->from, scm->guilddbid, scm->message));
break;
}
case 7: {
QueueMessage(fmt::format("[{0}] tells you, '{1}'", scm->from, scm->message));
case ChatChannel_Auction: {
if (RuleB(Chat, ServerWideAuction)) {
QueueMessage(fmt::format("{} auctions, '{}'", scm->from, scm->message));
break;
} else { // I think we want default action in this case?
return false;
}
}
case ChatChannel_OOC: {
if (RuleB(Chat, ServerWideOOC)) {
QueueMessage(fmt::format("{} says ooc, '{}'", scm->from, scm->message));
break;
} else { // I think we want default action in this case?
return false;
}
}
case ChatChannel_Broadcast: {
QueueMessage(fmt::format("{} BROADCASTS, '{}'", scm->from, scm->message));
break;
}
case ChatChannel_Tell: {
QueueMessage(fmt::format("[{}] tells {}, '{}'", scm->from, scm->to, scm->message));
if (onTell) {
onTell();
}
break;
}
case 11: {
QueueMessage(fmt::format("{0} GMSAYS, '{1}'", scm->from, scm->message));
case ChatChannel_GMSAY: {
QueueMessage(fmt::format("{} GMSAYS, '{}'", scm->from, scm->message));
break;
}
default: {
return false;
}
+24 -6
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()) {
@@ -1394,7 +1412,7 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
first_header.total_size = (uint32_t)HostToNetwork((uint32_t)length);
size_t used = 0;
size_t sublen = m_max_packet_size - m_crc_bytes - DaybreakReliableFragmentHeader::size();
size_t sublen = m_max_packet_size - m_crc_bytes - DaybreakReliableFragmentHeader::size() - 1; // -1 for compress flag
DynamicPacket first_packet;
first_packet.PutSerialize(0, first_header);
first_packet.PutData(DaybreakReliableFragmentHeader::size(), (char*)p.Data() + used, sublen);
@@ -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
+34 -61
View File
@@ -11,7 +11,7 @@
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -28,10 +28,12 @@
#include "../eq_packet_structs.h"
#include "../misc_functions.h"
#include "../string_util.h"
#include "../strings.h"
#include "../inventory_profile.h"
#include "rof_structs.h"
#include "../rulesys.h"
#include "../path_manager.h"
#include "../races.h"
#include <iostream>
#include <sstream>
@@ -52,13 +54,13 @@ namespace RoF
static inline structs::InventorySlot_Struct ServerToRoFCorpseSlot(uint32 server_corpse_slot);
static inline uint32 ServerToRoFCorpseMainSlot(uint32 server_corpse_slot);
static inline structs::TypelessInventorySlot_Struct ServerToRoFTypelessSlot(uint32 server_slot, int16 server_type);
// client to server inventory location converters
static inline uint32 RoFToServerSlot(structs::InventorySlot_Struct rof_slot);
static inline uint32 RoFToServerCorpseSlot(structs::InventorySlot_Struct rof_corpse_slot);
static inline uint32 RoFToServerCorpseMainSlot(uint32 rof_corpse_slot);
static inline uint32 RoFToServerTypelessSlot(structs::TypelessInventorySlot_Struct rof_slot, int16 rof_type);
// server to client say link converter
static inline void ServerToRoFSayLink(std::string& rofSayLink, const std::string& serverSayLink);
@@ -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);
}
@@ -736,30 +729,6 @@ namespace RoF
FINISH_ENCODE();
}
ENCODE(OP_DzCompass)
{
SETUP_VAR_ENCODE(DynamicZoneCompass_Struct);
ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct,
sizeof(structs::DynamicZoneCompass_Struct) +
sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count
);
OUT(client_id);
OUT(count);
for (uint32 i = 0; i < emu->count; ++i)
{
OUT(entries[i].dz_zone_id);
OUT(entries[i].dz_instance_id);
OUT(entries[i].dz_type);
OUT(entries[i].x);
OUT(entries[i].y);
OUT(entries[i].z);
}
FINISH_ENCODE();
}
ENCODE(OP_DzExpeditionEndsWarning)
{
ENCODE_LENGTH_EXACT(ExpeditionExpireWarning);
@@ -1558,7 +1527,7 @@ namespace RoF
in->size = ob.size();
in->pBuffer = ob.detach();
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
@@ -1624,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);
@@ -1782,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);
@@ -1838,10 +1807,10 @@ namespace RoF
OUT_str(zone_short_name2);
OUT(zone_id);
OUT(zone_instance);
OUT(SuspendBuffs);
OUT(FastRegenHP);
OUT(FastRegenMana);
OUT(FastRegenEndurance);
OUT(suspend_buffs);
OUT(fast_regen_hp);
OUT(fast_regen_mana);
OUT(fast_regen_endurance);
OUT(underworld_teleport_index);
eq->FogDensity = emu->fog_density;
@@ -1849,8 +1818,8 @@ namespace RoF
/*fill in some unknowns with observed values, hopefully it will help */
eq->unknown800 = -1;
eq->unknown844 = 600;
OUT(LavaDamage);
OUT(MinLavaDamage);
OUT(lava_damage);
OUT(min_lava_damage);
eq->unknown888 = 1;
eq->unknown889 = 0;
eq->unknown890 = 1;
@@ -3862,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;
@@ -3994,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)
{
@@ -4849,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);
@@ -4864,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);
@@ -5188,7 +5161,7 @@ namespace RoF
void SerializeItem(EQ::OutBuffer& ob, const EQ::ItemInstance *inst, int16 slot_id_in, uint8 depth, ItemPacketType packet_type)
{
const EQ::ItemData *item = inst->GetUnscaledItem();
RoF::structs::ItemSerializationHeader hdr;
//sprintf(hdr.unknown000, "06e0002Y1W00");
@@ -5207,7 +5180,7 @@ namespace RoF
slot_id = ServerToRoFSlot(slot_id_in);
break;
}
hdr.slot_type = (inst->GetMerchantSlot() ? invtype::typeMerchant : slot_id.Type);
hdr.main_slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id.Slot);
hdr.sub_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.SubIndex);
@@ -5295,7 +5268,7 @@ namespace RoF
ob.write("\0", 1);
ob.write("\0", 1);
RoF::structs::ItemBodyStruct ibs;
memset(&ibs, 0, sizeof(RoF::structs::ItemBodyStruct));
@@ -5608,7 +5581,7 @@ namespace RoF
iqbs.unknown28 = 0;
iqbs.unknown30 = 0;
iqbs.unknown39 = 1;
ob.write((const char*)&iqbs, sizeof(RoF::structs::ItemQuaternaryBodyStruct));
EQ::OutBuffer::pos_type count_pos = ob.tellp();
@@ -5776,7 +5749,7 @@ namespace RoF
static inline uint32 ServerToRoFCorpseMainSlot(uint32 server_corpse_slot)
{
uint32 RoFSlot = invslot::SLOT_INVALID;
if (server_corpse_slot <= EQ::invslot::CORPSE_END && server_corpse_slot >= EQ::invslot::CORPSE_BEGIN) {
RoFSlot = server_corpse_slot;
}
@@ -6123,7 +6096,7 @@ namespace RoF
return;
}
auto segments = SplitString(serverSayLink, '\x12');
auto segments = Strings::Split(serverSayLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
@@ -6162,7 +6135,7 @@ namespace RoF
return;
}
auto segments = SplitString(rofSayLink, '\x12');
auto segments = Strings::Split(rofSayLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
+68 -91
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
@@ -28,10 +28,13 @@
#include "../eq_packet_structs.h"
#include "../misc_functions.h"
#include "../string_util.h"
#include "../strings.h"
#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>
@@ -53,13 +56,13 @@ namespace RoF2
static inline structs::InventorySlot_Struct ServerToRoF2CorpseSlot(uint32 server_corpse_slot);
static inline uint32 ServerToRoF2CorpseMainSlot(uint32 server_corpse_slot);
static inline structs::TypelessInventorySlot_Struct ServerToRoF2TypelessSlot(uint32 server_slot, int16 server_type);
// client to server inventory location converters
static inline uint32 RoF2ToServerSlot(structs::InventorySlot_Struct rof2_slot);
static inline uint32 RoF2ToServerCorpseSlot(structs::InventorySlot_Struct rof2_corpse_slot);
static inline uint32 RoF2ToServerCorpseMainSlot(uint32 rof2_corpse_slot);
static inline uint32 RoF2ToServerTypelessSlot(structs::TypelessInventorySlot_Struct rof2_slot, int16 rof2_type);
// server to client say link converter
static inline void ServerToRoF2SayLink(std::string &rof2_saylink, const std::string &server_saylink);
@@ -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);
}
@@ -785,30 +780,6 @@ namespace RoF2
FINISH_ENCODE();
}
ENCODE(OP_DzCompass)
{
SETUP_VAR_ENCODE(DynamicZoneCompass_Struct);
ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct,
sizeof(structs::DynamicZoneCompass_Struct) +
sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count
);
OUT(client_id);
OUT(count);
for (uint32 i = 0; i < emu->count; ++i)
{
OUT(entries[i].dz_zone_id);
OUT(entries[i].dz_instance_id);
OUT(entries[i].dz_type);
OUT(entries[i].x);
OUT(entries[i].y);
OUT(entries[i].z);
}
FINISH_ENCODE();
}
ENCODE(OP_DzExpeditionEndsWarning)
{
ENCODE_LENGTH_EXACT(ExpeditionExpireWarning);
@@ -1673,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);
@@ -1831,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);
@@ -1887,13 +1858,13 @@ namespace RoF2
OUT_str(zone_short_name2);
OUT(zone_id);
OUT(zone_instance);
OUT(SuspendBuffs);
OUT(FastRegenHP);
OUT(FastRegenMana);
OUT(FastRegenEndurance);
OUT(suspend_buffs);
OUT(fast_regen_hp);
OUT(fast_regen_mana);
OUT(fast_regen_endurance);
OUT(underworld_teleport_index);
eq->FogDensity = emu->fog_density;
eq->fog_density = emu->fog_density;
/*fill in some unknowns with observed values, hopefully it will help */
eq->ZoneTimeZone = 0;
@@ -1905,22 +1876,22 @@ namespace RoF2
eq->SkyRelated2 = -1;
eq->NPCAggroMaxDist = 600;
eq->FilterID = 2008; // Guild Lobby observed value
OUT(LavaDamage);
OUT(MinLavaDamage);
eq->bDisallowManaStone = 1;
eq->bNoBind = 0;
eq->bNoAttack = 0;
eq->bNoCallOfHero = 0;
eq->bNoFlux = 0;
eq->bNoFear = 0;
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
eq->unknown895 = 0;
eq->CanPlaceCampsite = 2;
eq->CanPlaceGuildBanner = 2;
eq->FishingRelated = -1; // Set from PoK Example
eq->ForageRelated = -1; // Set from PoK Example
eq->bNoLevitate = 0;
eq->Blooming = 1.0; // Set from PoK Example
OUT(lava_damage);
OUT(min_lava_damage);
eq->bDisallowManaStone = 1;
eq->bNoBind = 0;
eq->bNoAttack = 0;
eq->bNoCallOfHero = 0;
eq->bNoFlux = 0;
eq->bNoFear = 0;
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
eq->unknown895 = 0;
eq->can_place_campsite = 2;
eq->can_place_guild_banner = 2;
eq->fishing_related = -1; // Set from PoK Example
eq->forage_related = -1; // Set from PoK Example
eq->b_no_levitate = 0;
eq->blooming = 1.0; // Set from PoK Example
FINISH_ENCODE();
}
@@ -2894,12 +2865,12 @@ namespace RoF2
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
// the structs::SendAA_Struct includes enough space for 1 prereq which is the min even if it has no prereqs
auto prereq_size = emu->total_prereqs > 1 ? (emu->total_prereqs - 1) * 8 : 0;
auto outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability) + prereq_size);
inapp->SetReadPosition(sizeof(AARankInfo_Struct)+emu->total_effects * sizeof(AARankEffect_Struct));
std::vector<int32> skill;
std::vector<int32> points;
@@ -2962,7 +2933,7 @@ namespace RoF2
outapp->WriteUInt32(inapp->ReadUInt32()); // base2
outapp->WriteUInt32(inapp->ReadUInt32()); // slot
}
dest->FastQueuePacket(&outapp);
delete inapp;
}
@@ -3975,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
@@ -3996,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;
@@ -4063,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
@@ -4089,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);
@@ -4197,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)
{
@@ -5046,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);
@@ -5061,12 +5038,12 @@ 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);
IN(number_in_stack);
//LogNetcode("[RoF2] MoveItem Slot from [{}] to [{}], Number [{}]", emu->from_slot, emu->to_slot, emu->number_in_stack);
FINISH_DIRECT_DECODE();
@@ -5443,7 +5420,7 @@ namespace RoF2
void SerializeItem(EQ::OutBuffer& ob, const EQ::ItemInstance *inst, int16 slot_id_in, uint8 depth, ItemPacketType packet_type)
{
const EQ::ItemData *item = inst->GetUnscaledItem();
RoF2::structs::ItemSerializationHeader hdr;
//sprintf(hdr.unknown000, "06e0002Y1W00");
@@ -5462,7 +5439,7 @@ namespace RoF2
slot_id = ServerToRoF2Slot(slot_id_in);
break;
}
hdr.slot_type = (inst->GetMerchantSlot() ? invtype::typeMerchant : slot_id.Type);
hdr.main_slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id.Slot);
hdr.sub_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.SubIndex);
@@ -5550,7 +5527,7 @@ namespace RoF2
ob.write("\0", 1);
ob.write("\0", 1);
RoF2::structs::ItemBodyStruct ibs;
memset(&ibs, 0, sizeof(RoF2::structs::ItemBodyStruct));
@@ -5873,7 +5850,7 @@ namespace RoF2
iqbs.unknown37a = 0; // (guessed position) New to RoF2
iqbs.unknown38 = 0;
iqbs.unknown39 = 1;
ob.write((const char*)&iqbs, sizeof(RoF2::structs::ItemQuaternaryBodyStruct));
EQ::OutBuffer::pos_type count_pos = ob.tellp();
@@ -6073,7 +6050,7 @@ namespace RoF2
uint32 server_slot = EQ::invslot::SLOT_INVALID;
uint32 temp_slot = invslot::SLOT_INVALID;
switch (rof2_slot.Type) {
case invtype::typePossessions: {
if (rof2_slot.Slot >= invslot::POSSESSIONS_BEGIN && rof2_slot.Slot <= invslot::POSSESSIONS_END) {
@@ -6188,11 +6165,11 @@ namespace RoF2
static inline uint32 RoF2ToServerCorpseSlot(structs::InventorySlot_Struct rof2_corpse_slot)
{
uint32 ServerSlot = EQ::invslot::SLOT_INVALID;
if (rof2_corpse_slot.Type != invtype::typeCorpse || rof2_corpse_slot.SubIndex != invbag::SLOT_INVALID || rof2_corpse_slot.AugIndex != invaug::SOCKET_INVALID) {
ServerSlot = EQ::invslot::SLOT_INVALID;
}
else {
ServerSlot = RoF2ToServerCorpseMainSlot(rof2_corpse_slot.Slot);
}
@@ -6346,7 +6323,7 @@ namespace RoF2
return;
}
auto segments = SplitString(server_saylink, '\x12');
auto segments = Strings::Split(server_saylink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
@@ -6378,7 +6355,7 @@ namespace RoF2
return;
}
auto segments = SplitString(rof2_saylink, '\x12');
auto segments = Strings::Split(rof2_saylink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
+2 -2
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
@@ -19,7 +19,7 @@
#include "rof2_limits.h"
#include "../string_util.h"
#include "../strings.h"
int16 RoF2::invtype::GetInvTypeSize(int16 inv_type)
-1
View File
@@ -59,7 +59,6 @@ E(OP_DeleteItem)
E(OP_DeleteSpawn)
E(OP_DisciplineUpdate)
E(OP_DzChooseZone)
E(OP_DzCompass)
E(OP_DzExpeditionEndsWarning)
E(OP_DzExpeditionInfo)
E(OP_DzExpeditionInvite)
+45 -40
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
@@ -620,40 +620,40 @@ struct NewZone_Struct {
/*0800*/ int32 SkyRelated2; //seen -1 -- maybe some default sky time?
/*0804*/ char WeatherString2[32]; //
/*0836*/ float WeatherChangeTime; // not sure :P
/*0840*/ uint32 Climate;
/*0844*/ int32 NPCAggroMaxDist; //seen 600
/*0848*/ int32 FilterID; //seen 2008 -- maybe zone guide related?
/*0852*/ uint16 zone_id; // this might just be instance ID got 1736 for time
/*0854*/ uint16 zone_instance;
/*0856*/ uint32 scriptNPCReceivedanItem;
/*0860*/ uint32 bCheck; // padded bool
/*0864*/ uint32 scriptIDSomething;
/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
/*0872*/ uint32 scriptIDSomething3;
/*0876*/ uint32 SuspendBuffs; // padded bool
/*0880*/ uint32 LavaDamage; // LavaDamage value
/*0884*/ uint32 MinLavaDamage; // min cap after resist calcs
/*0888*/ uint8 bDisallowManaStone; // can't use manastone in this zone
/*0889*/ uint8 bNoBind; // can't bind even if outdoor says we can!
/*0890*/ uint8 bNoAttack; // non-attack zone
/*0891*/ uint8 bNoCallOfHero; // coth line disabled
/*0892*/ uint8 bNoFlux; // gflux no worky
/*0893*/ uint8 bNoFear; // fear spells no worky
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off MQ2 calls bNoEncumber
/*0895*/ uint8 unknown895; // padding
/*0896*/ uint32 FastRegenHP; // percentage I think?
/*0900*/ uint32 FastRegenMana; // percentage I think?
/*0904*/ uint32 FastRegenEndurance; // percentage I think?
/*0908*/ uint32 CanPlaceCampsite; // 0 = no, 1 = can place, 2 = place and goto
/*0912*/ uint32 CanPlaceGuildBanner; // ^
/*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16
/*0920*/ uint32 bAdjustGamma; // padded bool
/*0924*/ uint32 TimeStringID; // Seen 0
/*0928*/ uint32 bNoMercenaries; // padded bool
/*0932*/ int32 FishingRelated; // Seen -1 idk
/*0936*/ int32 ForageRelated; // Seen -1 idk
/*0940*/ uint32 bNoLevitate; // padded bool
/*0944*/ float Blooming; // Seen 1.0 in PoK, and 0.25 in Guild Lobby
/*0840*/ uint32 Climate;
/*0844*/ int32 NPCAggroMaxDist; //seen 600
/*0848*/ int32 FilterID; //seen 2008 -- maybe zone guide related?
/*0852*/ uint16 zone_id; // this might just be instance ID got 1736 for time
/*0854*/ uint16 zone_instance;
/*0856*/ uint32 scriptNPCReceivedanItem;
/*0860*/ uint32 bCheck; // padded bool
/*0864*/ uint32 scriptIDSomething;
/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
/*0872*/ uint32 scriptIDSomething3;
/*0876*/ uint32 suspend_buffs; // padded bool
/*0880*/ uint32 lava_damage; // lava_damage value
/*0884*/ uint32 min_lava_damage; // min cap after resist calcs
/*0888*/ uint8 bDisallowManaStone; // can't use manastone in this zone
/*0889*/ uint8 bNoBind; // can't bind even if outdoor says we can!
/*0890*/ uint8 bNoAttack; // non-attack zone
/*0891*/ uint8 bNoCallOfHero; // coth line disabled
/*0892*/ uint8 bNoFlux; // gflux no worky
/*0893*/ uint8 bNoFear; // fear spells no worky
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off MQ2 calls bNoEncumber
/*0895*/ uint8 unknown895; // padding
/*0896*/ uint32 fast_regen_hp; // percentage I think?
/*0900*/ uint32 fast_regen_mana; // percentage I think?
/*0904*/ uint32 fast_regen_endurance; // percentage I think?
/*0908*/ uint32 can_place_campsite; // 0 = no, 1 = can place, 2 = place and goto
/*0912*/ uint32 can_place_guild_banner; // ^
/*0916*/ float fog_density; // Most zones have this set to 0.33 Blightfire had 0.16
/*0920*/ uint32 b_adjust_gamma; // padded bool
/*0924*/ uint32 time_string_id; // Seen 0
/*0928*/ uint32 b_no_mercenaries; // padded bool
/*0932*/ int32 fishing_related; // Seen -1 idk
/*0936*/ int32 forage_related; // Seen -1 idk
/*0940*/ uint32 b_no_levitate; // padded bool
/*0944*/ float blooming; // Seen 1.0 in PoK, and 0.25 in Guild Lobby
/*0948*/
};
@@ -2649,11 +2649,11 @@ struct FaceChange_Struct {
/*004*/ uint8 hairstyle;
/*005*/ uint8 beard;
/*006*/ uint8 face;
/*007*/ uint8 unknown007;
/*007*/ uint8 unused_padding;
/*008*/ uint32 drakkin_heritage;
/*012*/ uint32 drakkin_tattoo;
/*016*/ uint32 drakkin_details;
/*020*/ uint32 unknown020;
/*020*/ uint32 entity_id;
/*024*/
};
//there are only 10 faces for barbs changing woad just
@@ -3061,7 +3061,7 @@ struct EnvDamage2_Struct {
/*0006*/ uint32 damage;
/*0010*/ float unknown10; // New to Underfoot - Seen 1
/*0014*/ uint8 unknown14[12];
/*0026*/ uint8 dmgtype; // FA = Lava; FC = Falling
/*0026*/ uint8 dmgtype; // FA = Lava, FB = Drowning, FC = Falling, FD = Trap
/*0027*/ uint8 unknown27[4];
/*0031*/ uint16 unknown31; // New to Underfoot - Seen 66
/*0033*/ uint16 constant; // Always FFFF
@@ -3476,7 +3476,7 @@ struct TraderClick_Struct{
/*000*/ uint32 Code;
/*004*/ uint32 TraderID;
/*008*/ uint32 Approval;
/*012*/
/*012*/
};
struct FormattedMessage_Struct{
@@ -4989,7 +4989,7 @@ struct DynamicZoneCompassEntry_Struct
/*000*/ uint16 dz_zone_id; // target dz id pair
/*002*/ uint16 dz_instance_id;
/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green)
/*008*/ uint32 unknown008;
/*008*/ uint32 dz_switch_id;
/*012*/ float y;
/*016*/ float x;
/*020*/ float z;
@@ -5218,6 +5218,11 @@ struct SayLinkBodyFrame_Struct {
/*056*/
};
struct Checksum_Struct {
uint64_t checksum;
uint8_t data[2048];
};
}; /*structs*/
}; /*RoF2*/
+2 -2
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
@@ -19,7 +19,7 @@
#include "rof_limits.h"
#include "../string_util.h"
#include "../strings.h"
int16 RoF::invtype::GetInvTypeSize(int16 inv_type)
-1
View File
@@ -45,7 +45,6 @@ E(OP_DeleteItem)
E(OP_DeleteSpawn)
E(OP_DisciplineUpdate)
E(OP_DzChooseZone)
E(OP_DzCompass)
E(OP_DzExpeditionEndsWarning)
E(OP_DzExpeditionInfo)
E(OP_DzExpeditionInvite)
+36 -36
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
@@ -571,39 +571,39 @@ struct NewZone_Struct {
/*0704*/ char zone_short_name2[96]; //zone file name? excludes instance number which can be in previous version.
/*0800*/ int32 unknown800; //seen -1
/*0804*/ char unknown804[40]; //
/*0844*/ int32 unknown844; //seen 600
/*0848*/ int32 unknown848;
/*0852*/ uint16 zone_id;
/*0854*/ uint16 zone_instance;
/*0856*/ uint32 scriptNPCReceivedanItem;
/*0860*/ uint32 bCheck; // padded bool
/*0864*/ uint32 scriptIDSomething;
/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
/*0872*/ uint32 scriptIDSomething3;
/*0876*/ uint32 SuspendBuffs;
/*0880*/ uint32 LavaDamage; // Seen 50
/*0884*/ uint32 MinLavaDamage; // Seen 10
/*0888*/ uint8 unknown888; // Seen 1
/*0889*/ uint8 unknown889; // Seen 0 (POK) or 1 (rujj)
/*0890*/ uint8 unknown890; // Seen 1
/*0891*/ uint8 unknown891; // Seen 0
/*0892*/ uint8 unknown892; // Seen 0
/*0893*/ uint8 unknown893; // Seen 0 - 00
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off
/*0895*/ uint8 unknown895; // Seen 0 - 00
/*0896*/ uint32 FastRegenHP; // Seen 180
/*0900*/ uint32 FastRegenMana; // Seen 180
/*0904*/ uint32 FastRegenEndurance; // Seen 180
/*0908*/ uint32 unknown908; // Seen 2
/*0912*/ uint32 unknown912; // Seen 2
/*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16
/*0920*/ uint32 unknown920; // Seen 0
/*0924*/ uint32 unknown924; // Seen 0
/*0928*/ uint32 unknown928; // Seen 0
/*0844*/ int32 unknown844; //seen 600
/*0848*/ int32 unknown848;
/*0852*/ uint16 zone_id;
/*0854*/ uint16 zone_instance;
/*0856*/ uint32 scriptNPCReceivedanItem;
/*0860*/ uint32 bCheck; // padded bool
/*0864*/ uint32 scriptIDSomething;
/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
/*0872*/ uint32 scriptIDSomething3;
/*0876*/ uint32 suspend_buffs;
/*0880*/ uint32 lava_damage; // Seen 50
/*0884*/ uint32 min_lava_damage; // Seen 10
/*0888*/ uint8 unknown888; // Seen 1
/*0889*/ uint8 unknown889; // Seen 0 (POK) or 1 (rujj)
/*0890*/ uint8 unknown890; // Seen 1
/*0891*/ uint8 unknown891; // Seen 0
/*0892*/ uint8 unknown892; // Seen 0
/*0893*/ uint8 unknown893; // Seen 0 - 00
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off
/*0895*/ uint8 unknown895; // Seen 0 - 00
/*0896*/ uint32 fast_regen_hp; // Seen 180
/*0900*/ uint32 fast_regen_mana; // Seen 180
/*0904*/ uint32 fast_regen_endurance; // Seen 180
/*0908*/ uint32 unknown908; // Seen 2
/*0912*/ uint32 unknown912; // Seen 2
/*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16
/*0920*/ uint32 unknown920; // Seen 0
/*0924*/ uint32 unknown924; // Seen 0
/*0928*/ uint32 unknown928; // Seen 0
/*0932*/ int32 unknown932; // Seen -1
/*0936*/ int32 unknown936; // Seen -1
/*0940*/ uint32 unknown940; // Seen 0
/*0944*/ float unknown944; // Seen 1.0
/*0940*/ uint32 unknown940; // Seen 0
/*0944*/ float unknown944; // Seen 1.0
/*0948*/
};
@@ -2622,11 +2622,11 @@ struct FaceChange_Struct {
/*004*/ uint8 hairstyle;
/*005*/ uint8 beard;
/*006*/ uint8 face;
/*007*/ uint8 unknown007;
/*007*/ uint8 unused_padding;
/*008*/ uint32 drakkin_heritage;
/*012*/ uint32 drakkin_tattoo;
/*016*/ uint32 drakkin_details;
/*020*/ uint32 unknown020;
/*020*/ uint32 entity_id;
/*024*/
};
//there are only 10 faces for barbs changing woad just
@@ -3032,7 +3032,7 @@ struct EnvDamage2_Struct {
/*0006*/ uint32 damage;
/*0010*/ float unknown10; // New to Underfoot - Seen 1
/*0014*/ uint8 unknown14[12];
/*0026*/ uint8 dmgtype; // FA = Lava; FC = Falling
/*0026*/ uint8 dmgtype; // FA = Lava, FB = Drowning, FC = Falling, FD = Trap
/*0027*/ uint8 unknown27[4];
/*0031*/ uint16 unknown31; // New to Underfoot - Seen 66
/*0033*/ uint16 constant; // Always FFFF
@@ -4921,7 +4921,7 @@ struct DynamicZoneCompassEntry_Struct
/*000*/ uint16 dz_zone_id; // target dz id pair
/*002*/ uint16 dz_instance_id;
/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green)
/*008*/ uint32 unknown008;
/*008*/ uint32 dz_switch_id;
/*012*/ float y;
/*016*/ float x;
/*020*/ float z;
+35 -61
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
@@ -28,10 +28,12 @@
#include "../eq_packet_structs.h"
#include "../misc_functions.h"
#include "../string_util.h"
#include "../strings.h"
#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;
@@ -407,7 +399,7 @@ namespace SoD
in->size = ob.size();
in->pBuffer = ob.detach();
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
@@ -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);
}
@@ -509,30 +501,6 @@ namespace SoD
FINISH_ENCODE();
}
ENCODE(OP_DzCompass)
{
SETUP_VAR_ENCODE(DynamicZoneCompass_Struct);
ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct,
sizeof(structs::DynamicZoneCompass_Struct) +
sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count
);
OUT(client_id);
OUT(count);
for (uint32 i = 0; i < emu->count; ++i)
{
OUT(entries[i].dz_zone_id);
OUT(entries[i].dz_instance_id);
OUT(entries[i].dz_type);
OUT(entries[i].x);
OUT(entries[i].y);
OUT(entries[i].z);
}
FINISH_ENCODE();
}
ENCODE(OP_DzExpeditionEndsWarning)
{
ENCODE_LENGTH_EXACT(ExpeditionExpireWarning);
@@ -1089,7 +1057,7 @@ namespace SoD
//store away the emu struct
uchar* __emu_buffer = in->pBuffer;
EQ::InternalSerializedItem_Struct* int_struct = (EQ::InternalSerializedItem_Struct*)(&__emu_buffer[4]);
EQ::OutBuffer ob;
@@ -1106,7 +1074,7 @@ namespace SoD
in->size = ob.size();
in->pBuffer = ob.detach();
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
@@ -1160,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);
@@ -1309,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);
@@ -1365,17 +1333,17 @@ namespace SoD
OUT_str(zone_short_name2);
OUT(zone_id);
OUT(zone_instance);
OUT(SuspendBuffs);
OUT(FastRegenHP);
OUT(FastRegenMana);
OUT(FastRegenEndurance);
OUT(suspend_buffs);
OUT(fast_regen_hp);
OUT(fast_regen_mana);
OUT(fast_regen_endurance);
OUT(underworld_teleport_index);
/*fill in some unknowns with observed values, hopefully it will help */
eq->unknown800 = -1;
eq->unknown844 = 600;
OUT(LavaDamage);
OUT(MinLavaDamage);
OUT(lava_damage);
OUT(min_lava_damage);
eq->unknown888 = 1;
eq->unknown889 = 0;
eq->unknown890 = 1;
@@ -1385,8 +1353,8 @@ namespace SoD
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
eq->unknown895 = 0;
eq->unknown908 = 2;
eq->unknown912 = 2;
eq->FogDensity = emu->fog_density;
eq->unknown912 = 2;
eq->fog_density = emu->fog_density;
FINISH_ENCODE();
}
@@ -2499,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);
@@ -2696,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)
{
@@ -2721,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;
@@ -3252,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);
@@ -3267,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);
@@ -3538,7 +3512,7 @@ namespace SoD
void SerializeItem(EQ::OutBuffer& ob, const EQ::ItemInstance *inst, int16 slot_id_in, uint8 depth)
{
const EQ::ItemData *item = inst->GetUnscaledItem();
SoD::structs::ItemSerializationHeader hdr;
hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()) : 1);
@@ -3849,7 +3823,7 @@ namespace SoD
iqbs.HealAmt = item->HealAmt;
iqbs.SpellDmg = item->SpellDmg;
iqbs.Clairvoyance = item->Clairvoyance;
ob.write((const char*)&iqbs, sizeof(SoD::structs::ItemQuaternaryBodyStruct));
EQ::OutBuffer::pos_type count_pos = ob.tellp();
@@ -4061,7 +4035,7 @@ namespace SoD
return;
}
auto segments = SplitString(server_saylink, '\x12');
auto segments = Strings::Split(server_saylink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
@@ -4101,7 +4075,7 @@ namespace SoD
return;
}
auto segments = SplitString(sod_saylink, '\x12');
auto segments = Strings::Split(sod_saylink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
+2 -2
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
@@ -19,7 +19,7 @@
#include "sod_limits.h"
#include "../string_util.h"
#include "../strings.h"
int16 SoD::invtype::GetInvTypeSize(int16 inv_type)
-1
View File
@@ -36,7 +36,6 @@ E(OP_Damage)
E(OP_DeleteCharge)
E(OP_DeleteItem)
E(OP_DzChooseZone)
E(OP_DzCompass)
E(OP_DzExpeditionEndsWarning)
E(OP_DzExpeditionInfo)
E(OP_DzExpeditionInvite)
+34 -34
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
@@ -440,35 +440,35 @@ struct NewZone_Struct {
/*0704*/ char zone_short_name2[96]; //zone file name? excludes instance number which can be in previous version.
/*0800*/ int32 unknown800; //seen -1
/*0804*/ char unknown804[40]; //
/*0844*/ int32 unknown844; //seen 600
/*0848*/ int32 unknown848;
/*0852*/ uint16 zone_id;
/*0854*/ uint16 zone_instance;
/*0856*/ uint32 scriptNPCReceivedanItem;
/*0860*/ uint32 bCheck; // padded bool
/*0864*/ uint32 scriptIDSomething;
/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
/*0872*/ uint32 scriptIDSomething3;
/*0876*/ uint32 SuspendBuffs;
/*0880*/ uint32 LavaDamage; //seen 50
/*0884*/ uint32 MinLavaDamage; //seen 10
/*0888*/ uint8 unknown888; //seen 1
/*0889*/ uint8 unknown889; //seen 0 (POK) or 1 (rujj)
/*0890*/ uint8 unknown890; //seen 1
/*0891*/ uint8 unknown891; //seen 0
/*0892*/ uint8 unknown892; //seen 0
/*0893*/ uint8 unknown893; //seen 0 - 00
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off
/*0895*/ uint8 unknown895; //seen 0 - 00
/*0896*/ uint32 FastRegenHP; //seen 180
/*0900*/ uint32 FastRegenMana; //seen 180
/*0904*/ uint32 FastRegenEndurance; //seen 180
/*0908*/ uint32 unknown908; //seen 2
/*0912*/ uint32 unknown912; //seen 2
/*0916*/ float FogDensity; //Of about 10 or so zones tested, all but one have this set to 0.33 Blightfire had 0.16
/*0920*/ uint32 unknown920; //seen 0
/*0924*/ uint32 unknown924; //seen 0
/*0928*/ uint32 unknown928; //seen 0
/*0844*/ int32 unknown844; //seen 600
/*0848*/ int32 unknown848;
/*0852*/ uint16 zone_id;
/*0854*/ uint16 zone_instance;
/*0856*/ uint32 scriptNPCReceivedanItem;
/*0860*/ uint32 bCheck; // padded bool
/*0864*/ uint32 scriptIDSomething;
/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
/*0872*/ uint32 scriptIDSomething3;
/*0876*/ uint32 suspend_buffs;
/*0880*/ uint32 lava_damage; //seen 50
/*0884*/ uint32 min_lava_damage; //seen 10
/*0888*/ uint8 unknown888; //seen 1
/*0889*/ uint8 unknown889; //seen 0 (POK) or 1 (rujj)
/*0890*/ uint8 unknown890; //seen 1
/*0891*/ uint8 unknown891; //seen 0
/*0892*/ uint8 unknown892; //seen 0
/*0893*/ uint8 unknown893; //seen 0 - 00
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off
/*0895*/ uint8 unknown895; //seen 0 - 00
/*0896*/ uint32 fast_regen_hp; //seen 180
/*0900*/ uint32 fast_regen_mana; //seen 180
/*0904*/ uint32 fast_regen_endurance; //seen 180
/*0908*/ uint32 unknown908; //seen 2
/*0912*/ uint32 unknown912; //seen 2
/*0916*/ float fog_density; //Of about 10 or so zones tested, all but one have this set to 0.33 Blightfire had 0.16
/*0920*/ uint32 unknown920; //seen 0
/*0924*/ uint32 unknown924; //seen 0
/*0928*/ uint32 unknown928; //seen 0
/*0932*/
};
@@ -2136,11 +2136,11 @@ struct FaceChange_Struct {
/*004*/ uint8 hairstyle;
/*005*/ uint8 beard;
/*006*/ uint8 face;
/*007*/ uint8 unknown007;
/*007*/ uint8 unused_padding;
/*008*/ uint32 drakkin_heritage;
/*012*/ uint32 drakkin_tattoo;
/*016*/ uint32 drakkin_details;
/*020*/ uint32 unknown020;
/*020*/ uint32 entity_id;
/*024*/
};
//there are only 10 faces for barbs changing woad just
@@ -2539,7 +2539,7 @@ struct EnvDamage2_Struct {
/*0004*/ uint16 unknown4;
/*0006*/ uint32 damage;
/*0010*/ uint8 unknown10[12];
/*0022*/ uint8 dmgtype; //FA = Lava; FC = Falling
/*0022*/ uint8 dmgtype; // FA = Lava, FB = Drowning, FC = Falling, FD = Trap
/*0023*/ uint8 unknown2[4];
/*0027*/ uint16 constant; //Always FFFF
/*0029*/ uint16 unknown29;
@@ -4276,7 +4276,7 @@ struct DynamicZoneCompassEntry_Struct
/*000*/ uint16 dz_zone_id; // target dz id pair
/*002*/ uint16 dz_instance_id;
/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green)
/*008*/ uint32 unknown008;
/*008*/ uint32 dz_switch_id;
/*012*/ float y;
/*016*/ float x;
/*020*/ float z;
+24 -57
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
@@ -28,10 +28,11 @@
#include "../eq_packet_structs.h"
#include "../misc_functions.h"
#include "../string_util.h"
#include "../strings.h"
#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;
@@ -387,7 +378,7 @@ namespace SoF
in->size = ob.size();
in->pBuffer = ob.detach();
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
@@ -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);
}
@@ -497,30 +488,6 @@ namespace SoF
FINISH_ENCODE();
}
ENCODE(OP_DzCompass)
{
SETUP_VAR_ENCODE(DynamicZoneCompass_Struct);
ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct,
sizeof(structs::DynamicZoneCompass_Struct) +
sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count
);
OUT(client_id);
OUT(count);
for (uint32 i = 0; i < emu->count; ++i)
{
OUT(entries[i].dz_zone_id);
OUT(entries[i].dz_instance_id);
OUT(entries[i].dz_type);
OUT(entries[i].x);
OUT(entries[i].y);
OUT(entries[i].z);
}
FINISH_ENCODE();
}
ENCODE(OP_DzExpeditionEndsWarning)
{
ENCODE_LENGTH_EXACT(ExpeditionExpireWarning);
@@ -885,7 +852,7 @@ namespace SoF
//store away the emu struct
uchar* __emu_buffer = in->pBuffer;
EQ::InternalSerializedItem_Struct* int_struct = (EQ::InternalSerializedItem_Struct*)(&__emu_buffer[4]);
EQ::OutBuffer ob;
@@ -902,7 +869,7 @@ namespace SoF
in->size = ob.size();
in->pBuffer = ob.detach();
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
@@ -956,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);
@@ -987,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);
@@ -1043,17 +1010,17 @@ namespace SoF
OUT_str(zone_short_name2);
OUT(zone_id);
OUT(zone_instance);
OUT(SuspendBuffs);
OUT(FastRegenHP);
OUT(FastRegenMana);
OUT(FastRegenEndurance);
OUT(suspend_buffs);
OUT(fast_regen_hp);
OUT(fast_regen_mana);
OUT(fast_regen_endurance);
OUT(underworld_teleport_index);
/*fill in some unknowns with observed values, hopefully it will help */
eq->unknown796 = -1;
eq->unknown840 = 600;
OUT(LavaDamage);
OUT(MinLavaDamage);
OUT(lava_damage);
OUT(min_lava_damage);
eq->unknown884 = 1;
eq->unknown885 = 0;
eq->unknown886 = 1;
@@ -2664,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);
@@ -2679,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);
@@ -2936,7 +2903,7 @@ namespace SoF
void SerializeItem(EQ::OutBuffer& ob, const EQ::ItemInstance *inst, int16 slot_id_in, uint8 depth)
{
const EQ::ItemData *item = inst->GetUnscaledItem();
SoF::structs::ItemSerializationHeader hdr;
hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()) : 1);
@@ -3245,7 +3212,7 @@ namespace SoF
iqbs.HeroicSVCorrup = item->HeroicSVCorrup;
iqbs.HealAmt = item->HealAmt;
iqbs.SpellDmg = item->SpellDmg;
ob.write((const char*)&iqbs, sizeof(SoF::structs::ItemQuaternaryBodyStruct));
EQ::OutBuffer::pos_type count_pos = ob.tellp();
@@ -3354,7 +3321,7 @@ namespace SoF
static inline uint32 ServerToSoFCorpseSlot(uint32 server_corpse_slot)
{
uint32 SoFSlot = invslot::SLOT_INVALID;
if (server_corpse_slot <= EQ::invslot::slotGeneral8 && server_corpse_slot >= EQ::invslot::slotGeneral1) {
SoFSlot = server_corpse_slot;
}
@@ -3465,7 +3432,7 @@ namespace SoF
return;
}
auto segments = SplitString(server_saylink, '\x12');
auto segments = Strings::Split(server_saylink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
@@ -3505,7 +3472,7 @@ namespace SoF
return;
}
auto segments = SplitString(sof_saylink, '\x12');
auto segments = Strings::Split(sof_saylink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
+2 -2
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
@@ -19,7 +19,7 @@
#include "sof_limits.h"
#include "../string_util.h"
#include "../strings.h"
int16 SoF::invtype::GetInvTypeSize(int16 inv_type)
-1
View File
@@ -37,7 +37,6 @@ E(OP_DeleteCharge)
E(OP_DeleteItem)
E(OP_DeleteSpawn)
E(OP_DzChooseZone)
E(OP_DzCompass)
E(OP_DzExpeditionEndsWarning)
E(OP_DzExpeditionInfo)
E(OP_DzExpeditionInvite)

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