mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-22 16:28:28 +00:00
Compare commits
100 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a7e9af2d27 | |||
| 7a72d5d67e | |||
| 25872203ff | |||
| 6396a6fbef | |||
| 6db0a5c3f0 | |||
| 4fa9e1d66f | |||
| 556af8c5e9 | |||
| f3ef8a0993 | |||
| 267c280db8 | |||
| e06c7d7735 | |||
| 028ebc3a0c | |||
| b3bd44cd76 | |||
| 75a627a3a2 | |||
| 0194aedc92 | |||
| 5cc87cbda7 | |||
| 703862d977 | |||
| 6e325c1ee3 | |||
| 933b83add6 | |||
| b3cd4e63f1 | |||
| 3c894cb533 | |||
| b19ad64800 | |||
| 2cd3d27c67 | |||
| d3b46becd0 | |||
| 286479198f | |||
| 21ec832ca6 | |||
| bdf5f8b4a3 | |||
| 4ca6485398 | |||
| 0c9c2e25c1 | |||
| 7e651877c7 | |||
| 9739c1c8ef | |||
| 8aae59eebe | |||
| c1b07afae9 | |||
| 9c238cd08d | |||
| 33adb9bcc1 | |||
| 2e8bf82861 | |||
| 4d118ab978 | |||
| fcb40daaf1 | |||
| 553bafdbe1 | |||
| d0443db199 | |||
| 9206163190 | |||
| e504482b94 | |||
| 77b88e3dec | |||
| aeeb350068 | |||
| df83113cea | |||
| 940abfaf7a | |||
| a46443b95e | |||
| 871f320311 | |||
| a222128599 | |||
| 45b249e33d | |||
| c24834de5d | |||
| 841d7f2700 | |||
| 56c29154f0 | |||
| 6466c2ff21 | |||
| 16dc210cd8 | |||
| 77045f558e | |||
| e1fa2d5bc5 | |||
| b03f52de18 | |||
| 226cc3d6cb | |||
| 7f54e26dec | |||
| 11a81d8e8a | |||
| e719aa43cf | |||
| 22994e3264 | |||
| cfbdecad19 | |||
| 2427f7e034 | |||
| 9a6403b196 | |||
| d8953c5156 | |||
| 33b40e83b7 | |||
| e75c31d524 | |||
| cf1f8d5460 | |||
| 690cacdaab | |||
| f9f45eedcd | |||
| 93ddffa57f | |||
| c9993fb698 | |||
| aa0fbb8b45 | |||
| 62532c6bdd | |||
| f8c3c03185 | |||
| 692a90f3f0 | |||
| 3a49d851ca | |||
| fdc5c27061 | |||
| 56be69ddb1 | |||
| 9477ff72ac | |||
| 6d8e80b1e5 | |||
| ebeaef598b | |||
| 60b65da7f2 | |||
| 100e6698ea | |||
| 2bd94ab7a2 | |||
| 4c8d68c24b | |||
| 1755678b1f | |||
| 39e2763968 | |||
| f7780b0247 | |||
| c0fe0f11f7 | |||
| a1f1f11940 | |||
| 4c5013e09e | |||
| 838ffbd8c7 | |||
| 42b41d973c | |||
| e7761133a9 | |||
| 93f2bea96e | |||
| ded82ac6d6 | |||
| 6ef182edfd | |||
| e466ca1c6d |
+1
-1
@@ -15,7 +15,7 @@ volumes:
|
||||
|
||||
steps:
|
||||
- name: Build Linux X64
|
||||
image: akkadius/eqemu-server:v13
|
||||
image: akkadius/eqemu-server:v14
|
||||
environment:
|
||||
GITHUB_TOKEN:
|
||||
from_secret: GH_RELEASE_GITHUB_API_TOKEN
|
||||
|
||||
+231
@@ -1,3 +1,234 @@
|
||||
## [22.38.0] - 12/26/2023
|
||||
|
||||
### Bots
|
||||
|
||||
* Remove unnecessary error on SetItemReuse ([#3795](https://github.com/EQEmu/Server/pull/3795)) @nytmyr 2023-12-20
|
||||
|
||||
### Code
|
||||
|
||||
* Consolidate GetHateRandom(), GetHateRandomBot(), GetHateRandomClient(), and GetHateRandomNPC() ([#3794](https://github.com/EQEmu/Server/pull/3794)) @Kinglykrab 2023-12-25
|
||||
* Race constants refactor ([#3782](https://github.com/EQEmu/Server/pull/3782)) @Akkadius 2023-12-23
|
||||
|
||||
### Database
|
||||
|
||||
* Fix issue with saylinks query in MySQL 8.0+ ([#3800](https://github.com/EQEmu/Server/pull/3800)) @Akkadius 2023-12-24
|
||||
* Update faction mods with Live data ([#3799](https://github.com/EQEmu/Server/pull/3799)) @joligario 2023-12-23
|
||||
|
||||
### Fixes
|
||||
|
||||
* Disable Hide/Improved Hide on Trap damage ([#3791](https://github.com/EQEmu/Server/pull/3791)) @Kinglykrab 2023-12-19
|
||||
* Fix Bard Invisibility Songs breaking every 4 ticks ([#3783](https://github.com/EQEmu/Server/pull/3783)) @Kinglykrab 2023-12-19
|
||||
* Fix can_riposte parameter in DoMeleeSkillAttackDmg ([#3792](https://github.com/EQEmu/Server/pull/3792)) @Kinglykrab 2023-12-19
|
||||
|
||||
### Forage
|
||||
|
||||
* Add a rule to disabled using common_food_ids from the list in forage.cpp. currently set to enabled. ([#3796](https://github.com/EQEmu/Server/pull/3796)) @regneq 2023-12-22
|
||||
|
||||
### NPC
|
||||
|
||||
* Support for multiple emotes per type, emote variables ([#3801](https://github.com/EQEmu/Server/pull/3801)) @regneq 2023-12-25
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add GetHateTopBot(), GetHateTopClient(), and GetHateTopNPC() to Perl/Lua ([#3793](https://github.com/EQEmu/Server/pull/3793)) @Kinglykrab 2023-12-22
|
||||
* Add SummonItemIntoInventory() to Perl/Lua ([#3797](https://github.com/EQEmu/Server/pull/3797)) @Kinglykrab 2023-12-22
|
||||
|
||||
### Repositories
|
||||
|
||||
* Add ReplaceOne and ReplaceMany ([#3802](https://github.com/EQEmu/Server/pull/3802)) @Akkadius 2023-12-26
|
||||
|
||||
## [22.37.0] - 12/18/2023
|
||||
|
||||
### Bots
|
||||
|
||||
* Add ScanCloseMobs support to fix AEs ([#3786](https://github.com/EQEmu/Server/pull/3786)) @nytmyr 2023-12-18
|
||||
* Expand ^itemuse options ([#3756](https://github.com/EQEmu/Server/pull/3756)) @nytmyr 2023-12-17
|
||||
* Fix ^defensive from checking aggressive disciplines. ([#3787](https://github.com/EQEmu/Server/pull/3787)) @nytmyr 2023-12-18
|
||||
* Fix ^oo autodefend from sending bots/pets to invalid haters ([#3772](https://github.com/EQEmu/Server/pull/3772)) @nytmyr 2023-12-16
|
||||
* Fix unnecessary failed to save timer error ([#3788](https://github.com/EQEmu/Server/pull/3788)) @nytmyr 2023-12-18
|
||||
* [Quest API] Add ^clickitem, ^timer, fix GetBestBotSpellForCure ([#3755](https://github.com/EQEmu/Server/pull/3755)) @nytmyr 2023-12-17
|
||||
|
||||
### CI
|
||||
|
||||
* Switch to use clang for Linux builds (speed) ([#3777](https://github.com/EQEmu/Server/pull/3777)) @Akkadius 2023-12-17
|
||||
|
||||
### Compilation
|
||||
|
||||
* Use pre-compiled headers for Windows (speed) ([#3778](https://github.com/EQEmu/Server/pull/3778)) @Akkadius 2023-12-18
|
||||
|
||||
### Fixes
|
||||
|
||||
* Drop Invisibility when hit by traps ([#3785](https://github.com/EQEmu/Server/pull/3785)) @Kinglykrab 2023-12-18
|
||||
* Fix NPCs routing to 0.0, 0.0 on #summon ([#3780](https://github.com/EQEmu/Server/pull/3780)) @Kinglykrab 2023-12-18
|
||||
* Fix bad merge @Akkadius 2023-12-17
|
||||
* Fix issue with HOTBonusHealingSplitOverDuration Rule ([#3776](https://github.com/EQEmu/Server/pull/3776)) @Kinglykrab 2023-12-17
|
||||
* Fixed the discrepacy with time using command #time and in quests. ([#3767](https://github.com/EQEmu/Server/pull/3767)) @regneq 2023-12-17
|
||||
* Send Entity ID in Death Events to resolve #3721 ([#3779](https://github.com/EQEmu/Server/pull/3779)) @Kinglykrab 2023-12-18
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add EVENT_ALT_CURRENCY_GAIN and EVENT_ALT_CURRENCY_LOSS to Perl/Lua ([#3734](https://github.com/EQEmu/Server/pull/3734)) @Kinglykrab 2023-12-17
|
||||
* Add EVENT_CRYSTAL_GAIN and EVENT_CRYSTAL_LOSS to Perl/Lua ([#3735](https://github.com/EQEmu/Server/pull/3735)) @Kinglykrab 2023-12-17
|
||||
* Add EVENT_LDON_POINTS_GAIN and EVENT_LDON_POINTS_LOSS to Perl/Lua ([#3742](https://github.com/EQEmu/Server/pull/3742)) @Kinglykrab 2023-12-17
|
||||
* Add EVENT_LEVEL_UP and EVENT_LEVEL_DOWN to Bots ([#3750](https://github.com/EQEmu/Server/pull/3750)) @Kinglykrab 2023-12-17
|
||||
* Add EVENT_LOOT_ADDED to Perl/Lua ([#3739](https://github.com/EQEmu/Server/pull/3739)) @Kinglykrab 2023-12-17
|
||||
* Add GetNPCAggro() and SetNPCAggro() to Perl/Lua ([#3781](https://github.com/EQEmu/Server/pull/3781)) @Kinglykrab 2023-12-18
|
||||
|
||||
## [22.36.0] - 12/16/2023
|
||||
|
||||
### Bots
|
||||
|
||||
* Add rule to toggle DT hitting owner ([#3757](https://github.com/EQEmu/Server/pull/3757)) @nytmyr 2023-12-11
|
||||
* Enable auto-saving of bots. ([#3758](https://github.com/EQEmu/Server/pull/3758)) @nytmyr 2023-12-13
|
||||
|
||||
### Code
|
||||
|
||||
* Cleanup classes.cpp/classes.h ([#3752](https://github.com/EQEmu/Server/pull/3752)) @Kinglykrab 2023-12-13
|
||||
|
||||
### Corpse
|
||||
|
||||
* Fix /corpse command regression from #3727 ([#3770](https://github.com/EQEmu/Server/pull/3770)) @Akkadius 2023-12-16
|
||||
|
||||
### Database
|
||||
|
||||
* Make it clearer to users that a database backup is occurring ([#3769](https://github.com/EQEmu/Server/pull/3769)) @Akkadius 2023-12-16
|
||||
* When database version is greater than binary, we are up to date ([#3771](https://github.com/EQEmu/Server/pull/3771)) @Akkadius 2023-12-16
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix Starting Items SQL ([#3766](https://github.com/EQEmu/Server/pull/3766)) @Kinglykrab 2023-12-16
|
||||
|
||||
### Logging
|
||||
|
||||
* Change empty object loading to warning ([#3759](https://github.com/EQEmu/Server/pull/3759)) @nytmyr 2023-12-11
|
||||
|
||||
### Rules
|
||||
|
||||
* Add DOT and HOT Rules ([#3760](https://github.com/EQEmu/Server/pull/3760)) @Kinglykrab 2023-12-16
|
||||
|
||||
## [22.35.0] - 12/10/2023
|
||||
|
||||
### Bots
|
||||
|
||||
* Add BotHealOnLevel to fully heal/mana on level. ([#3745](https://github.com/EQEmu/Server/pull/3745)) @nytmyr 2023-12-08
|
||||
* Fix bots learning spells on level ([#3744](https://github.com/EQEmu/Server/pull/3744)) @nytmyr 2023-12-08
|
||||
|
||||
### Bug
|
||||
|
||||
* Fix blocked spells regression from #3638 ([#3753](https://github.com/EQEmu/Server/pull/3753)) @joligario 2023-12-11
|
||||
* PR 3638 Missed the blocked spells repository updates ([#3748](https://github.com/EQEmu/Server/pull/3748)) @fryguy503 2023-12-08
|
||||
|
||||
### CMake
|
||||
|
||||
* Update minimum version of CMake ([#3743](https://github.com/EQEmu/Server/pull/3743)) @joligario 2023-12-08
|
||||
|
||||
### Code
|
||||
|
||||
* Remove hard-coded Status Checks ([#3727](https://github.com/EQEmu/Server/pull/3727)) @Kinglykrab 2023-12-03
|
||||
|
||||
### Commands
|
||||
|
||||
* #guild set CharName 0 did not remove char from guild. ([#3717](https://github.com/EQEmu/Server/pull/3717)) @noudess 2023-11-25
|
||||
* #petname changes PC to Nobody if selected. ([#3720](https://github.com/EQEmu/Server/pull/3720)) @noudess 2023-11-26
|
||||
* Add #show aas Command ([#3710](https://github.com/EQEmu/Server/pull/3710)) @Kinglykrab 2023-11-26
|
||||
* Add #task complete Command ([#3711](https://github.com/EQEmu/Server/pull/3711)) @Kinglykrab 2023-11-26
|
||||
* Cleanup #acceptrules Command ([#3716](https://github.com/EQEmu/Server/pull/3716)) @Kinglykrab 2023-11-26
|
||||
* Cleanup #disarmtrap Command ([#3713](https://github.com/EQEmu/Server/pull/3713)) @Kinglykrab 2023-11-26
|
||||
* Cleanup #list Command ([#3714](https://github.com/EQEmu/Server/pull/3714)) @Kinglykrab 2023-11-26
|
||||
* Cleanup #movement Command ([#3715](https://github.com/EQEmu/Server/pull/3715)) @Kinglykrab 2023-11-26
|
||||
* Cleanup #object Command ([#3722](https://github.com/EQEmu/Server/pull/3722)) @Kinglykrab 2023-12-03
|
||||
* Cleanup #zonebootup and #zoneshutdown Commands ([#3729](https://github.com/EQEmu/Server/pull/3729)) @Kinglykrab 2023-12-03
|
||||
* Fix formatting of #wpinfo output. ([#3728](https://github.com/EQEmu/Server/pull/3728)) @noudess 2023-12-01
|
||||
|
||||
### Database
|
||||
|
||||
* Add primary key to keyring table ([#3746](https://github.com/EQEmu/Server/pull/3746)) @Kinglykrab 2023-12-08
|
||||
* Consolidate Starting Items Table ([#3723](https://github.com/EQEmu/Server/pull/3723)) @Kinglykrab 2023-11-30
|
||||
* Extra whitespace in #3723 ([#3730](https://github.com/EQEmu/Server/pull/3730)) @joligario 2023-12-02
|
||||
* Minor adjustment to #3726 ([#3732](https://github.com/EQEmu/Server/pull/3732)) @joligario 2023-12-03
|
||||
* Modify `updated` column in `items` table with proper default. ([#3726](https://github.com/EQEmu/Server/pull/3726)) @joligario 2023-12-02
|
||||
* Pull Spell Group Cache from Content DB ([#3749](https://github.com/EQEmu/Server/pull/3749)) @fryguy503 2023-12-08
|
||||
|
||||
### Faction
|
||||
|
||||
* Alliance line is only allowed 1 faction change at a time. ([#3718](https://github.com/EQEmu/Server/pull/3718)) @noudess 2023-11-26
|
||||
|
||||
### Fixes
|
||||
|
||||
* Changing Group Leader Invalidated GetLeaderName() ([#3712](https://github.com/EQEmu/Server/pull/3712)) @Kinglykrab 2023-11-26
|
||||
* Fix 9245 SQL ([#3740](https://github.com/EQEmu/Server/pull/3740)) @Kinglykrab 2023-12-05
|
||||
* Fix Swarm Pets Requiring NPC Aggros Flag ([#3738](https://github.com/EQEmu/Server/pull/3738)) @Kinglykrab 2023-12-05
|
||||
* Guild Message Limits ([#3724](https://github.com/EQEmu/Server/pull/3724)) @neckkola 2023-11-29
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add EVENT_AA_GAIN to AddAAPoints() ([#3733](https://github.com/EQEmu/Server/pull/3733)) @Kinglykrab 2023-12-03
|
||||
* Add GMMove Overloads to Perl/Lua ([#3719](https://github.com/EQEmu/Server/pull/3719)) @Kinglykrab 2023-11-25
|
||||
|
||||
### Scripts
|
||||
|
||||
* Import items into `items_new` table instead of writing directly to the existing `items` table. ([#3725](https://github.com/EQEmu/Server/pull/3725)) @joligario 2023-11-30
|
||||
* Revert database engine change from #3702. ([#3736](https://github.com/EQEmu/Server/pull/3736)) @joligario 2023-12-03
|
||||
* Update 13th Floor Import Tool ([#3702](https://github.com/EQEmu/Server/pull/3702)) @joligario 2023-11-26
|
||||
|
||||
## [22.34.2] - 11/23/2023
|
||||
|
||||
### Admin
|
||||
|
||||
* Update date in changelog ([#3698](https://github.com/EQEmu/Server/pull/3698)) @joligario 2023-11-19
|
||||
|
||||
### Code
|
||||
|
||||
* Fix typo in #giveitem ([#3704](https://github.com/EQEmu/Server/pull/3704)) @Kinglykrab 2023-11-22
|
||||
|
||||
### Fixes
|
||||
|
||||
* Add "IgnoreLevelBasedHasteCaps" rule to GetHaste() ([#3705](https://github.com/EQEmu/Server/pull/3705)) @jcr4990 2023-11-23
|
||||
* Fix bots/Mercenaries being removed from hatelist ([#3708](https://github.com/EQEmu/Server/pull/3708)) @Kinglykrab 2023-11-23
|
||||
* Fix some spell types failing IsValidSpellRange check ([#3707](https://github.com/EQEmu/Server/pull/3707)) @nytmyr 2023-11-23
|
||||
|
||||
### Loginserver
|
||||
|
||||
* Update ticket login table structure ([#3703](https://github.com/EQEmu/Server/pull/3703)) @KimLS 2023-11-22
|
||||
|
||||
## [22.34.1] - 11/20/2023
|
||||
|
||||
### EQTime
|
||||
|
||||
Hotfix for world not spamming save messages by setting to detail level logging @Akkadius 2023-11-20
|
||||
|
||||
## [22.34.0] - 11/19/2023
|
||||
|
||||
### Bots
|
||||
|
||||
* Add ownerraid, byclass and byrace actionables and fix group-based arguments for raids. ([#3680](https://github.com/EQEmu/Server/pull/3680)) @nytmyr 2023-11-19
|
||||
|
||||
### Code
|
||||
|
||||
* Cleanup #giveitem and #summonitem ([#3692](https://github.com/EQEmu/Server/pull/3692)) @Kinglykrab 2023-11-19
|
||||
* Cleanup #show currencies Command ([#3693](https://github.com/EQEmu/Server/pull/3693)) @Kinglykrab 2023-11-19
|
||||
|
||||
### Commands
|
||||
|
||||
* Add #show aa_points Command ([#3695](https://github.com/EQEmu/Server/pull/3695)) @Kinglykrab 2023-11-19
|
||||
|
||||
### Database
|
||||
|
||||
* Pull pet power from content database ([#3689](https://github.com/EQEmu/Server/pull/3689)) @joligario 2023-11-18
|
||||
|
||||
### GM Commands
|
||||
|
||||
* Add `#takeplatinum` ([#3690](https://github.com/EQEmu/Server/pull/3690)) @joligario 2023-11-19
|
||||
* Remove duplicate comment ([#3691](https://github.com/EQEmu/Server/pull/3691)) @joligario 2023-11-19
|
||||
|
||||
### Illusions
|
||||
|
||||
* RandomizeFeastures erased texture. ([#3686](https://github.com/EQEmu/Server/pull/3686)) @noudess 2023-11-12
|
||||
|
||||
### Spawn
|
||||
|
||||
* (imported from takp) Added min_time and max_time to spawnentry. This will prevent a NPC from… ([#3685](https://github.com/EQEmu/Server/pull/3685)) @regneq 2023-11-18
|
||||
|
||||
## [22.33.0] - 11/11/2023
|
||||
|
||||
### Feature
|
||||
|
||||
@@ -17,6 +17,7 @@ SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
SET(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
OPTION(EQEMU_BUILD_STATIC "Build with static linking" OFF)
|
||||
OPTION(EQEMU_BUILD_PCH "Build with precompiled headers (Windows)" ON)
|
||||
|
||||
IF (EQEMU_BUILD_STATIC)
|
||||
SET(BUILD_SHARED_LIBS OFF)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
|
||||
|
||||
add_subdirectory(import)
|
||||
add_subdirectory(export)
|
||||
|
||||
@@ -792,5 +792,8 @@ IF (UNIX)
|
||||
SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0)
|
||||
ENDIF (UNIX)
|
||||
|
||||
IF (WIN32 AND EQEMU_BUILD_PCH)
|
||||
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/pch.h)
|
||||
ENDIF()
|
||||
|
||||
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
||||
|
||||
+296
-473
File diff suppressed because it is too large
Load Diff
+96
-93
@@ -19,99 +19,106 @@
|
||||
#define CLASSES_CH
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#define NO_CLASS 0
|
||||
#define WARRIOR 1
|
||||
#define CLERIC 2
|
||||
#define PALADIN 3
|
||||
#define RANGER 4
|
||||
#define SHADOWKNIGHT 5
|
||||
#define DRUID 6
|
||||
#define MONK 7
|
||||
#define BARD 8
|
||||
#define ROGUE 9
|
||||
#define SHAMAN 10
|
||||
#define NECROMANCER 11
|
||||
#define WIZARD 12
|
||||
#define MAGICIAN 13
|
||||
#define ENCHANTER 14
|
||||
#define BEASTLORD 15
|
||||
#define BERSERKER 16
|
||||
#define WARRIORGM 20
|
||||
#define CLERICGM 21
|
||||
#define PALADINGM 22
|
||||
#define RANGERGM 23
|
||||
#define SHADOWKNIGHTGM 24
|
||||
#define DRUIDGM 25
|
||||
#define MONKGM 26
|
||||
#define BARDGM 27
|
||||
#define ROGUEGM 28
|
||||
#define SHAMANGM 29
|
||||
#define NECROMANCERGM 30
|
||||
#define WIZARDGM 31
|
||||
#define MAGICIANGM 32
|
||||
#define ENCHANTERGM 33
|
||||
#define BEASTLORDGM 34
|
||||
#define BERSERKERGM 35
|
||||
#define BANKER 40
|
||||
#define MERCHANT 41
|
||||
#define DISCORD_MERCHANT 59
|
||||
#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
|
||||
#define NORRATHS_KEEPERS_MERCHANT 67
|
||||
#define DARK_REIGN_MERCHANT 68
|
||||
#define FELLOWSHIP_MASTER 69
|
||||
#define ALT_CURRENCY_MERCHANT 70
|
||||
#define MERCENARY_MASTER 71
|
||||
namespace Class {
|
||||
constexpr uint8 None = 0;
|
||||
constexpr uint8 Warrior = 1;
|
||||
constexpr uint8 Cleric = 2;
|
||||
constexpr uint8 Paladin = 3;
|
||||
constexpr uint8 Ranger = 4;
|
||||
constexpr uint8 ShadowKnight = 5;
|
||||
constexpr uint8 Druid = 6;
|
||||
constexpr uint8 Monk = 7;
|
||||
constexpr uint8 Bard = 8;
|
||||
constexpr uint8 Rogue = 9;
|
||||
constexpr uint8 Shaman = 10;
|
||||
constexpr uint8 Necromancer = 11;
|
||||
constexpr uint8 Wizard = 12;
|
||||
constexpr uint8 Magician = 13;
|
||||
constexpr uint8 Enchanter = 14;
|
||||
constexpr uint8 Beastlord = 15;
|
||||
constexpr uint8 Berserker = 16;
|
||||
constexpr uint8 WarriorGM = 20;
|
||||
constexpr uint8 ClericGM = 21;
|
||||
constexpr uint8 PaladinGM = 22;
|
||||
constexpr uint8 RangerGM = 23;
|
||||
constexpr uint8 ShadowKnightGM = 24;
|
||||
constexpr uint8 DruidGM = 25;
|
||||
constexpr uint8 MonkGM = 26;
|
||||
constexpr uint8 BardGM = 27;
|
||||
constexpr uint8 RogueGM = 28;
|
||||
constexpr uint8 ShamanGM = 29;
|
||||
constexpr uint8 NecromancerGM = 30;
|
||||
constexpr uint8 WizardGM = 31;
|
||||
constexpr uint8 MagicianGM = 32;
|
||||
constexpr uint8 EnchanterGM = 33;
|
||||
constexpr uint8 BeastlordGM = 34;
|
||||
constexpr uint8 BerserkerGM = 35;
|
||||
constexpr uint8 Banker = 40;
|
||||
constexpr uint8 Merchant = 41;
|
||||
constexpr uint8 DiscordMerchant = 59;
|
||||
constexpr uint8 AdventureRecruiter = 60;
|
||||
constexpr uint8 AdventureMerchant = 61;
|
||||
constexpr uint8 LDoNTreasure = 62;
|
||||
constexpr uint8 TributeMaster = 63;
|
||||
constexpr uint8 GuildTributeMaster = 64;
|
||||
constexpr uint8 GuildBanker = 66;
|
||||
constexpr uint8 NorrathsKeepersMerchant = 67;
|
||||
constexpr uint8 DarkReignMerchant = 68;
|
||||
constexpr uint8 FellowshipMaster = 69;
|
||||
constexpr uint8 AlternateCurrencyMerchant = 70;
|
||||
constexpr uint8 MercenaryLiaison = 71;
|
||||
|
||||
constexpr uint8 PLAYER_CLASS_COUNT = 16;
|
||||
constexpr uint16 ALL_CLASSES_BITMASK = 65535;
|
||||
};
|
||||
|
||||
// player class values
|
||||
#define PLAYER_CLASS_UNKNOWN 0
|
||||
#define PLAYER_CLASS_WARRIOR 1
|
||||
#define PLAYER_CLASS_CLERIC 2
|
||||
#define PLAYER_CLASS_PALADIN 3
|
||||
#define PLAYER_CLASS_RANGER 4
|
||||
#define PLAYER_CLASS_SHADOWKNIGHT 5
|
||||
#define PLAYER_CLASS_DRUID 6
|
||||
#define PLAYER_CLASS_MONK 7
|
||||
#define PLAYER_CLASS_BARD 8
|
||||
#define PLAYER_CLASS_ROGUE 9
|
||||
#define PLAYER_CLASS_SHAMAN 10
|
||||
#define PLAYER_CLASS_NECROMANCER 11
|
||||
#define PLAYER_CLASS_WIZARD 12
|
||||
#define PLAYER_CLASS_MAGICIAN 13
|
||||
#define PLAYER_CLASS_ENCHANTER 14
|
||||
#define PLAYER_CLASS_BEASTLORD 15
|
||||
#define PLAYER_CLASS_BERSERKER 16
|
||||
static std::map<uint8, uint16> player_class_bitmasks = {
|
||||
{Class::Warrior, 1},
|
||||
{Class::Cleric, 2},
|
||||
{Class::Paladin, 4},
|
||||
{Class::Ranger, 8},
|
||||
{Class::ShadowKnight, 16},
|
||||
{Class::Druid, 32},
|
||||
{Class::Monk, 64},
|
||||
{Class::Bard, 128},
|
||||
{Class::Rogue, 256},
|
||||
{Class::Shaman, 512},
|
||||
{Class::Necromancer, 1024},
|
||||
{Class::Wizard, 2048},
|
||||
{Class::Magician, 4096},
|
||||
{Class::Enchanter, 8192},
|
||||
{Class::Beastlord, 16384},
|
||||
{Class::Berserker, 32768},
|
||||
};
|
||||
|
||||
#define PLAYER_CLASS_COUNT 16
|
||||
static std::string shadow_knight_class_name = (
|
||||
RuleB(World, UseOldShadowKnightClassExport) ?
|
||||
"Shadowknight" :
|
||||
"Shadow Knight"
|
||||
);
|
||||
|
||||
|
||||
// player class bits
|
||||
#define PLAYER_CLASS_UNKNOWN_BIT 0
|
||||
#define PLAYER_CLASS_WARRIOR_BIT 1
|
||||
#define PLAYER_CLASS_CLERIC_BIT 2
|
||||
#define PLAYER_CLASS_PALADIN_BIT 4
|
||||
#define PLAYER_CLASS_RANGER_BIT 8
|
||||
#define PLAYER_CLASS_SHADOWKNIGHT_BIT 16
|
||||
#define PLAYER_CLASS_DRUID_BIT 32
|
||||
#define PLAYER_CLASS_MONK_BIT 64
|
||||
#define PLAYER_CLASS_BARD_BIT 128
|
||||
#define PLAYER_CLASS_ROGUE_BIT 256
|
||||
#define PLAYER_CLASS_SHAMAN_BIT 512
|
||||
#define PLAYER_CLASS_NECROMANCER_BIT 1024
|
||||
#define PLAYER_CLASS_WIZARD_BIT 2048
|
||||
#define PLAYER_CLASS_MAGICIAN_BIT 4096
|
||||
#define PLAYER_CLASS_ENCHANTER_BIT 8192
|
||||
#define PLAYER_CLASS_BEASTLORD_BIT 16384
|
||||
#define PLAYER_CLASS_BERSERKER_BIT 32768
|
||||
|
||||
#define PLAYER_CLASS_ALL_MASK 65535 // was 65536
|
||||
static std::map<uint8, std::string> class_names = {
|
||||
{Class::Warrior, "Warrior"},
|
||||
{Class::Cleric, "Cleric"},
|
||||
{Class::Paladin, "Paladin"},
|
||||
{Class::Ranger, "Ranger"},
|
||||
{Class::ShadowKnight, shadow_knight_class_name},
|
||||
{Class::Druid, "Druid"},
|
||||
{Class::Monk, "Monk"},
|
||||
{Class::Bard, "Bard"},
|
||||
{Class::Rogue, "Rogue"},
|
||||
{Class::Shaman, "Shaman"},
|
||||
{Class::Necromancer, "Necromancer"},
|
||||
{Class::Wizard, "Wizard"},
|
||||
{Class::Magician, "Magician"},
|
||||
{Class::Enchanter, "Enchanter"},
|
||||
{Class::Beastlord, "Beastlord"},
|
||||
{Class::Berserker, "Berserker"},
|
||||
};
|
||||
|
||||
|
||||
#define ARMOR_TYPE_UNKNOWN 0
|
||||
@@ -126,16 +133,12 @@
|
||||
|
||||
|
||||
const char* GetClassIDName(uint8 class_id, uint8 level = 0);
|
||||
const char* GetPlayerClassName(uint32 player_class_value, uint8 level = 0);
|
||||
|
||||
bool IsPlayerClass(uint8 class_id);
|
||||
const std::string GetPlayerClassAbbreviation(uint8 class_id);
|
||||
|
||||
uint32 GetPlayerClassValue(uint8 class_id);
|
||||
uint32 GetPlayerClassBit(uint8 class_id);
|
||||
|
||||
uint8 GetClassIDFromPlayerClassValue(uint32 player_class_value);
|
||||
uint8 GetClassIDFromPlayerClassBit(uint32 player_class_bit);
|
||||
uint8 GetPlayerClassValue(uint8 class_id);
|
||||
uint16 GetPlayerClassBit(uint8 class_id);
|
||||
|
||||
bool IsFighterClass(uint8 class_id);
|
||||
bool IsSpellFighterClass(uint8 class_id);
|
||||
|
||||
+41
-36
@@ -29,6 +29,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../common/repositories/account_repository.h"
|
||||
|
||||
// Disgrace: for windows compile
|
||||
#ifdef _WINDOWS
|
||||
#include <windows.h>
|
||||
@@ -1643,25 +1645,20 @@ void Database::ClearGroupLeader(uint32 gid) {
|
||||
std::cout << "Unable to clear group leader: " << results.ErrorMessage() << std::endl;
|
||||
}
|
||||
|
||||
uint8 Database::GetAgreementFlag(uint32 acctid) {
|
||||
|
||||
std::string query = StringFormat("SELECT rulesflag FROM account WHERE id=%i",acctid);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success())
|
||||
uint8 Database::GetAgreementFlag(uint32 account_id)
|
||||
{
|
||||
const auto& e = AccountRepository::FindOne(*this, account_id);
|
||||
if (!e.id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (results.RowCount() != 1)
|
||||
return 0;
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
return Strings::ToUnsignedInt(row[0]);
|
||||
return e.rulesflag;
|
||||
}
|
||||
|
||||
void Database::SetAgreementFlag(uint32 acctid) {
|
||||
std::string query = StringFormat("UPDATE account SET rulesflag=1 where id=%i", acctid);
|
||||
QueryDatabase(query);
|
||||
void Database::SetAgreementFlag(uint32 account_id) {
|
||||
auto e = AccountRepository::FindOne(*this, account_id);
|
||||
e.rulesflag = 1;
|
||||
AccountRepository::UpdateOne(*this, e);
|
||||
}
|
||||
|
||||
void Database::ClearRaid(uint32 rid) {
|
||||
@@ -2097,37 +2094,45 @@ void Database::ClearInvSnapshots(bool from_now) {
|
||||
|
||||
struct TimeOfDay_Struct Database::LoadTime(time_t &realtime)
|
||||
{
|
||||
|
||||
TimeOfDay_Struct eqTime;
|
||||
std::string query = StringFormat("SELECT minute,hour,day,month,year,realtime FROM eqtime limit 1");
|
||||
TimeOfDay_Struct t{};
|
||||
std::string query = StringFormat("SELECT minute,hour,day,month,year,realtime FROM eqtime limit 1");
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success() || results.RowCount() == 0){
|
||||
if (!results.Success() || results.RowCount() == 0) {
|
||||
LogInfo("Loading EQ time of day failed. Using defaults");
|
||||
eqTime.minute = 0;
|
||||
eqTime.hour = 9;
|
||||
eqTime.day = 1;
|
||||
eqTime.month = 1;
|
||||
eqTime.year = 3100;
|
||||
t.minute = 0;
|
||||
t.hour = 9;
|
||||
t.day = 1;
|
||||
t.month = 1;
|
||||
t.year = 3100;
|
||||
realtime = time(nullptr);
|
||||
}
|
||||
else{
|
||||
auto row = results.begin();
|
||||
|
||||
eqTime.minute = Strings::ToUnsignedInt(row[0]);
|
||||
eqTime.hour = Strings::ToUnsignedInt(row[1]);
|
||||
eqTime.day = Strings::ToUnsignedInt(row[2]);
|
||||
eqTime.month = Strings::ToUnsignedInt(row[3]);
|
||||
eqTime.year = Strings::ToUnsignedInt(row[4]);
|
||||
realtime = Strings::ToBigInt(row[5]);
|
||||
return t;
|
||||
}
|
||||
|
||||
return eqTime;
|
||||
auto row = results.begin();
|
||||
|
||||
uint8 hour = Strings::ToUnsignedInt(row[1]);
|
||||
time_t realtime_ = Strings::ToBigInt(row[5]);
|
||||
if (RuleI(World, BootHour) > 0 && RuleI(World, BootHour) <= 24) {
|
||||
hour = RuleI(World, BootHour);
|
||||
realtime_ = time(nullptr);
|
||||
}
|
||||
|
||||
t.minute = Strings::ToUnsignedInt(row[0]);
|
||||
t.hour = hour;
|
||||
t.day = Strings::ToUnsignedInt(row[2]);
|
||||
t.month = Strings::ToUnsignedInt(row[3]);
|
||||
t.year = Strings::ToUnsignedInt(row[4]);
|
||||
realtime = realtime_;
|
||||
|
||||
LogEqTime("Setting hour to [{}]", hour);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year)
|
||||
{
|
||||
std::string query = StringFormat("UPDATE eqtime set minute = %d, hour = %d, day = %d, month = %d, year = %d, realtime = %d limit 1", minute, hour, day, month, year, time(0));
|
||||
std::string query = StringFormat("UPDATE eqtime set minute = %d, hour = %d, day = %d, month = %d, year = %d, realtime = %d limit 1", minute, hour, day, month, year, time(nullptr));
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
return results.Success();
|
||||
|
||||
+2
-2
@@ -188,10 +188,10 @@ public:
|
||||
uint32 CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus = 0);
|
||||
uint32 CreateAccount(const char* name, const char* password, int16 status, const char* loginserver, uint32 lsaccount_id);
|
||||
uint32 GetAccountIDFromLSID(const std::string& in_loginserver_id, uint32 in_loginserver_account_id, char* in_account_name = 0, int16* in_status = 0);
|
||||
uint8 GetAgreementFlag(uint32 acctid);
|
||||
uint8 GetAgreementFlag(uint32 account_id);
|
||||
|
||||
void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus);
|
||||
void SetAgreementFlag(uint32 acctid);
|
||||
void SetAgreementFlag(uint32 account_id);
|
||||
|
||||
int GetIPExemption(std::string account_ip);
|
||||
void SetIPExemption(std::string account_ip, int exemption_amount);
|
||||
|
||||
@@ -322,6 +322,10 @@ void DatabaseDumpService::DatabaseDump()
|
||||
pipe_file
|
||||
);
|
||||
|
||||
LogInfo("Backing up database [{}]", execute_command);
|
||||
LogInfo("This can take a few minutes depending on the size of your database");
|
||||
LogInfo("LOADING... PLEASE WAIT...");
|
||||
|
||||
BuildCredentialsFile();
|
||||
std::string execution_result = Process::execute(execute_command);
|
||||
if (!execution_result.empty() && IsDumpOutputToConsole()) {
|
||||
|
||||
@@ -274,9 +274,9 @@ bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
|
||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||
|
||||
// server database version is required
|
||||
bool server_up_to_date = v.server_database_version == b.server_database_version;
|
||||
bool server_up_to_date = v.server_database_version >= b.server_database_version;
|
||||
// bots database version is optional, if not enabled then it is always up-to-date
|
||||
bool bots_up_to_date = RuleB(Bots, Enabled) ? v.bots_database_version == b.bots_database_version : true;
|
||||
bool bots_up_to_date = RuleB(Bots, Enabled) ? v.bots_database_version >= b.bots_database_version : true;
|
||||
|
||||
return server_up_to_date && bots_up_to_date;
|
||||
}
|
||||
|
||||
@@ -5018,6 +5018,133 @@ INSERT INTO spawn2_disabled (spawn2_id, disabled) SELECT id, 1 FROM spawn2 WHERE
|
||||
ALTER TABLE `spawn2` DROP COLUMN `enabled`;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9242,
|
||||
.description = "2023_11_7_mintime_maxtime_spawnentry.sql",
|
||||
.check = "SHOW COLUMNS FROM `spawnentry` LIKE 'min_time'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `spawnentry`
|
||||
ADD COLUMN `min_time` smallint(4) NOT NULL DEFAULT 0 AFTER `condition_value_filter`,
|
||||
ADD COLUMN `max_time` smallint(4) NOT NULL DEFAULT 0 AFTER `min_time`;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9243,
|
||||
.description = "2023_11_27_starting_items_revamp.sql",
|
||||
.check = "SHOW COLUMNS FROM `starting_items` LIKE 'race_list'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
CREATE TABLE `starting_items_backup_9243` LIKE `starting_items`;
|
||||
INSERT INTO `starting_items_backup_9243` SELECT * FROM `starting_items`;
|
||||
|
||||
CREATE TABLE `starting_items_new` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`race_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
|
||||
`class_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
|
||||
`deity_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
|
||||
`zone_id_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
|
||||
`item_id` int(11) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`item_charges` tinyint(3) UNSIGNED NOT NULL DEFAULT 1,
|
||||
`gm` mediumint(3) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`slot` mediumint(9) NOT NULL DEFAULT -1,
|
||||
`min_expansion` tinyint(4) NOT NULL DEFAULT -1,
|
||||
`max_expansion` tinyint(4) NOT NULL DEFAULT -1,
|
||||
`content_flags` varchar(100) NULL,
|
||||
`content_flags_disabled` varchar(100) NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
INSERT INTO
|
||||
`starting_items_new`
|
||||
(
|
||||
SELECT
|
||||
0 AS `id`,
|
||||
GROUP_CONCAT(DISTINCT `class` ORDER BY class ASC SEPARATOR '|') AS `class_list`,
|
||||
GROUP_CONCAT(DISTINCT `race` ORDER BY race ASC SEPARATOR '|') AS `race_list`,
|
||||
GROUP_CONCAT(DISTINCT `deityid` ORDER BY deityid ASC SEPARATOR '|') AS `deity_list`,
|
||||
GROUP_CONCAT(DISTINCT `zoneid` ORDER BY zoneid ASC SEPARATOR '|') AS `zone_list`,
|
||||
`itemid`,
|
||||
`item_charges`,
|
||||
`gm`,
|
||||
`slot`,
|
||||
`min_expansion`,
|
||||
`max_expansion`,
|
||||
`content_flags`,
|
||||
`content_flags_disabled`
|
||||
FROM
|
||||
`starting_items`
|
||||
GROUP BY
|
||||
`itemid`
|
||||
);
|
||||
|
||||
DROP TABLE `starting_items`;
|
||||
RENAME TABLE `starting_items_new` TO `starting_items`;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9244,
|
||||
.description = "2023_11_30_items_table_schema.sql",
|
||||
.check = "SHOW COLUMNS FROM `items` LIKE 'updated'",
|
||||
.condition = "contains",
|
||||
.match = "0000-00-00 00:00:00",
|
||||
.sql = R"(
|
||||
ALTER TABLE `items` MODIFY COLUMN `updated` datetime NULL DEFAULT NULL;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9245,
|
||||
.description = "2023_12_03_object_incline.sql",
|
||||
.check = "SHOW COLUMNS FROM `object` LIKE 'incline'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `object` CHANGE COLUMN `unknown08` `size_percentage` float NOT NULL DEFAULT 0 AFTER `icon`;
|
||||
ALTER TABLE `object` CHANGE COLUMN `unknown10` `solid_type` mediumint(5) NOT NULL DEFAULT 0 AFTER `size`;
|
||||
ALTER TABLE `object` CHANGE COLUMN `unknown20` `incline` int(11) NOT NULL DEFAULT 0 AFTER `solid_type`;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9246,
|
||||
.description = "2023_12_07_keyring_id.sql",
|
||||
.check = "SHOW COLUMNS FROM `keyring` LIKE 'id'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `keyring`
|
||||
ADD COLUMN `id` int UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
|
||||
ADD PRIMARY KEY (`id`);
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9247,
|
||||
.description = "2023_12_14_starting_items_fix.sql",
|
||||
.check = "SHOW COLUMNS FROM `starting_items` LIKE 'inventory_slot'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `starting_items`
|
||||
CHANGE COLUMN `race_list` `temporary` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `id`,
|
||||
CHANGE COLUMN `class_list` `race_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `temporary`,
|
||||
CHANGE COLUMN `gm` `status` mediumint(3) NOT NULL DEFAULT 0 AFTER `item_charges`,
|
||||
CHANGE COLUMN `slot` `inventory_slot` mediumint(9) NOT NULL DEFAULT -1 AFTER `status`;
|
||||
|
||||
ALTER TABLE `starting_items`
|
||||
CHANGE COLUMN `temporary` `class_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `id`;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9248,
|
||||
.description = "2023_12_22_drop_npc_emotes_index.sql",
|
||||
.check = "show index from npc_emotes where key_name = 'emoteid'",
|
||||
.condition = "not_empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `npc_emotes` DROP INDEX `emoteid`;
|
||||
)"
|
||||
}
|
||||
|
||||
// -- template; copy/paste this when you need to create a new entry
|
||||
// ManifestEntry{
|
||||
|
||||
@@ -82,6 +82,28 @@ CREATE TABLE `bot_starting_items` (
|
||||
`content_flags_disabled` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci;
|
||||
)",
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9041,
|
||||
.description = "2023_12_04_bot_timers.sql",
|
||||
.check = "SHOW COLUMNS FROM `bot_timers` LIKE 'recast_time'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `bot_timers`
|
||||
ADD COLUMN `recast_time` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `timer_value`,
|
||||
ADD COLUMN `is_spell` TINYINT(2) UNSIGNED NOT NULL DEFAULT 0 AFTER `recast_time`,
|
||||
ADD COLUMN `is_disc` TINYINT(2) UNSIGNED NOT NULL DEFAULT 0 AFTER `is_spell`,
|
||||
ADD COLUMN `spell_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `is_disc`,
|
||||
ADD COLUMN `is_item` TINYINT(2) UNSIGNED NOT NULL DEFAULT 0 AFTER `spell_id`,
|
||||
ADD COLUMN `item_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `is_item`;
|
||||
ALTER TABLE `bot_timers`
|
||||
DROP FOREIGN KEY `FK_bot_timers_1`;
|
||||
ALTER TABLE `bot_timers`
|
||||
DROP PRIMARY KEY;
|
||||
ALTER TABLE `bot_timers`
|
||||
ADD PRIMARY KEY (`bot_id`, `timer_id`, `spell_id`, `item_id`);
|
||||
)"
|
||||
}
|
||||
// -- template; copy/paste this when you need to create a new entry
|
||||
|
||||
@@ -1059,4 +1059,20 @@ enum SpellTimeRestrictions
|
||||
Night
|
||||
};
|
||||
|
||||
enum MoneyTypes
|
||||
{
|
||||
Copper,
|
||||
Silver,
|
||||
Gold,
|
||||
Platinum
|
||||
};
|
||||
|
||||
enum MoneySubtypes
|
||||
{
|
||||
Personal,
|
||||
Bank,
|
||||
Cursor,
|
||||
SharedBank // Platinum Only
|
||||
};
|
||||
|
||||
#endif /*COMMON_EQ_CONSTANTS_H*/
|
||||
|
||||
@@ -124,6 +124,12 @@ struct LDoNTrapTemplate
|
||||
uint8 locked;
|
||||
};
|
||||
|
||||
enum CrystalReclaimTypes
|
||||
{
|
||||
Ebon = 5,
|
||||
Radiant = 4,
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -2594,11 +2600,11 @@ struct BookButton_Struct
|
||||
struct Object_Struct {
|
||||
/*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list
|
||||
/*08*/ float size; //
|
||||
/*10*/ uint16 solidtype; //
|
||||
/*10*/ uint16 solid_type; //
|
||||
/*12*/ uint32 drop_id; // Unique object id for zone
|
||||
/*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in
|
||||
/*18*/ uint16 zone_instance; //
|
||||
/*20*/ uint32 unknown020; //
|
||||
/*20*/ uint32 incline; //
|
||||
/*24*/ uint32 unknown024; //
|
||||
/*28*/ float tilt_x;
|
||||
/*32*/ float tilt_y;
|
||||
|
||||
@@ -100,6 +100,8 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
|
||||
log_settings[Logs::Discord].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::QuestErrors].log_to_gmsay = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::QuestErrors].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::EqTime].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::EqTime].log_to_gmsay = static_cast<uint8>(Logs::General);
|
||||
|
||||
/**
|
||||
* RFC 5424
|
||||
|
||||
@@ -139,6 +139,7 @@ namespace Logs {
|
||||
PlayerEvents,
|
||||
DataBuckets,
|
||||
Zoning,
|
||||
EqTime,
|
||||
MaxCategoryID /* Don't Remove this */
|
||||
};
|
||||
|
||||
@@ -237,6 +238,7 @@ namespace Logs {
|
||||
"PlayerEvents",
|
||||
"DataBuckets",
|
||||
"Zoning",
|
||||
"EqTime",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -814,6 +814,16 @@
|
||||
OutF(LogSys, Logs::Detail, Logs::Zoning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogEqTime(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::EqTime))\
|
||||
OutF(LogSys, Logs::General, Logs::EqTime, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogEqTimeDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::EqTime))\
|
||||
OutF(LogSys, Logs::Detail, Logs::EqTime, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define Log(debug_level, log_category, message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(debug_level, log_category))\
|
||||
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
|
||||
+31
-9
@@ -46,16 +46,16 @@ EQTime::EQTime()
|
||||
timezone = 0;
|
||||
memset(&eqTime, 0, sizeof(eqTime));
|
||||
//Defaults for time
|
||||
TimeOfDay_Struct start;
|
||||
start.day = 1;
|
||||
start.hour = 9;
|
||||
start.minute = 0;
|
||||
start.month = 1;
|
||||
start.year = 3100;
|
||||
TimeOfDay_Struct t{};
|
||||
t.day = 1;
|
||||
t.hour = 9;
|
||||
t.minute = 0;
|
||||
t.month = 1;
|
||||
t.year = 3100;
|
||||
//Set default time zone
|
||||
timezone = 0;
|
||||
//Start EQTimer
|
||||
SetCurrentEQTimeOfDay(start, time(0));
|
||||
SetCurrentEQTimeOfDay(t, time(nullptr));
|
||||
}
|
||||
|
||||
//getEQTimeOfDay - Reads timeConvert and writes the result to eqTimeOfDay
|
||||
@@ -202,7 +202,7 @@ void EQTime::ToString(TimeOfDay_Struct *t, std::string &str) {
|
||||
}
|
||||
|
||||
bool EQTime::IsDayTime() {
|
||||
TimeOfDay_Struct tod; //Day time is 5am to 6:59pm (14 hours in-game)
|
||||
TimeOfDay_Struct tod{}; //Day time is 5am to 6:59pm (14 hours in-game)
|
||||
GetCurrentEQTimeOfDay(&tod); //TODO: what if it fails and returns zero?
|
||||
|
||||
if (tod.hour >= 5 || tod.hour < 19) {
|
||||
@@ -213,7 +213,7 @@ bool EQTime::IsDayTime() {
|
||||
}
|
||||
|
||||
bool EQTime::IsNightTime() {
|
||||
TimeOfDay_Struct tod; //Night time is 7pm to 4:59am (10 hours in-game)
|
||||
TimeOfDay_Struct tod{}; //Night time is 7pm to 4:59am (10 hours in-game)
|
||||
GetCurrentEQTimeOfDay(&tod); //TODO: what if it fails and returns zero?
|
||||
|
||||
if (tod.hour >= 19 || tod.hour < 5) {
|
||||
@@ -222,3 +222,25 @@ bool EQTime::IsNightTime() {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQTime::IsInbetweenTime(uint8 min_time, uint8 max_time) {
|
||||
TimeOfDay_Struct tod{};
|
||||
GetCurrentEQTimeOfDay(&tod);
|
||||
|
||||
if (min_time == 0 || max_time == 0 || min_time > 24 || max_time > 24) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (max_time < min_time) {
|
||||
if ((tod.hour >= min_time && tod.hour > max_time) || (tod.hour < min_time && tod.hour <= max_time)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (tod.hour >= min_time && tod.hour <= max_time) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ public:
|
||||
uint32 getEQTimeZoneMin() { return timezone%60; }
|
||||
bool IsDayTime();
|
||||
bool IsNightTime();
|
||||
bool IsInbetweenTime(uint8 min_time, uint8 max_time);
|
||||
|
||||
//Set functions
|
||||
int SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real);
|
||||
|
||||
+2
-2
@@ -96,12 +96,12 @@ bool IsOfEqualRace(int r1, int r2)
|
||||
// TODO: add more values
|
||||
switch (r1) {
|
||||
case DARK_ELF:
|
||||
if (r2 == RACE_NERIAK_CITIZEN_77) {
|
||||
if (r2 == Race::NeriakCitizen) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case BARBARIAN:
|
||||
if (r2 == RACE_HALAS_CITIZEN_90) {
|
||||
if (r2 == Race::HalasCitizen) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,25 +238,6 @@ enum { //some random constants
|
||||
// Timer to update aggrometer
|
||||
#define AGGRO_METER_UPDATE_MS 1000
|
||||
|
||||
//Some hard coded statuses from commands and other places:
|
||||
enum {
|
||||
minStatusToBeGM = 40,
|
||||
minStatusToUseGMCommands = 80,
|
||||
minStatusToKick = 150,
|
||||
minStatusToAvoidFalling = 100,
|
||||
minStatusToIgnoreZoneFlags = 80,
|
||||
minStatusToSeeOthersZoneFlags = 80,
|
||||
minStatusToEditOtherGuilds = 80,
|
||||
commandMovecharSelfOnly = 80, //below this == only self move allowed
|
||||
commandMovecharToSpecials = 200, //ability to send people to cshom/load zones
|
||||
commandCastSpecials = 100, //can cast special spells
|
||||
commandDoAnimOthers = 100, //can #doanim on others
|
||||
commandEditPlayerCorpses = 150, //can Edit Player Corpses
|
||||
commandInterrogateInv = 100, //below this == only log on error state and self-only target dump
|
||||
commandInvSnapshot = 150 //ability to clear/restore snapshots
|
||||
};
|
||||
|
||||
|
||||
// This is the item ID we use for say links, we use the max that fits in 5 ASCII chars
|
||||
#define SAYLINK_ITEM_ID 0xFFFFF
|
||||
|
||||
|
||||
@@ -801,34 +801,35 @@ int16 EQ::InventoryProfile::HasItemByLoreGroup(uint32 loregroup, uint8 where)
|
||||
// Returns slot_id when there's one available, else SLOT_INVALID
|
||||
int16 EQ::InventoryProfile::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, bool is_arrow)
|
||||
{
|
||||
// Check basic inventory
|
||||
for (int16 i = invslot::GENERAL_BEGIN; i <= invslot::GENERAL_END; i++) {
|
||||
if ((((uint64)1 << i) & m_lookup->PossessionsBitmask) == 0)
|
||||
continue;
|
||||
const int16 last_bag_slot = RuleI(World, ExpansionSettings) & EQ::expansions::bitHoT ? EQ::invslot::slotGeneral10 : EQ::invslot::slotGeneral8;
|
||||
|
||||
if (!GetItem(i))
|
||||
// Found available slot in personal inventory
|
||||
return i;
|
||||
for (int16 i = invslot::GENERAL_BEGIN; i <= last_bag_slot; i++) { // Check basic inventory
|
||||
if ((((uint64) 1 << i) & m_lookup->PossessionsBitmask) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!GetItem(i)) {
|
||||
return i; // Found available slot in personal inventory
|
||||
}
|
||||
}
|
||||
|
||||
if (!for_bag) {
|
||||
for (int16 i = invslot::GENERAL_BEGIN; i <= invslot::GENERAL_END; i++) {
|
||||
if ((((uint64)1 << i) & m_lookup->PossessionsBitmask) == 0)
|
||||
for (int16 i = invslot::GENERAL_BEGIN; i <= last_bag_slot; i++) {
|
||||
if ((((uint64) 1 << i) & m_lookup->PossessionsBitmask) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const ItemInstance* inst = GetItem(i);
|
||||
if (inst && inst->IsClassBag() && inst->GetItem()->BagSize >= min_size)
|
||||
{
|
||||
if (inst->GetItem()->BagType == item::BagTypeQuiver && inst->GetItem()->ItemType != item::ItemTypeArrow)
|
||||
{
|
||||
const auto *inst = GetItem(i);
|
||||
if (inst && inst->IsClassBag() && inst->GetItem()->BagSize >= min_size) {
|
||||
if (inst->GetItem()->BagType == item::BagTypeQuiver &&
|
||||
inst->GetItem()->ItemType != item::ItemTypeArrow) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int16 base_slot_id = InventoryProfile::CalcSlotId(i, invbag::SLOT_BEGIN);
|
||||
const int16 base_slot_id = InventoryProfile::CalcSlotId(i, invbag::SLOT_BEGIN);
|
||||
|
||||
uint8 slots = inst->GetItem()->BagSlots;
|
||||
uint8 j;
|
||||
for (j = invbag::SLOT_BEGIN; j<slots; j++) {
|
||||
const uint8 slots = inst->GetItem()->BagSlots;
|
||||
for (uint8 j = invbag::SLOT_BEGIN; j < slots; j++) {
|
||||
if (!GetItem(base_slot_id + j)) {
|
||||
// Found available slot within bag
|
||||
return (base_slot_id + j);
|
||||
|
||||
@@ -132,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 = RACE_DOUG_0, uint8 class_id = NO_CLASS, uint16 deity_id = deity::DeityType::DeityUnknown, uint8 level = 0);
|
||||
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = Race::Doug, uint8 class_id = Class::None, uint16 deity_id = deity::DeityType::DeityUnknown, uint8 level = 0);
|
||||
|
||||
// Remove item from inventory
|
||||
bool DeleteItem(int16 slot_id, int16 quantity = 0);
|
||||
|
||||
@@ -1273,7 +1273,7 @@ int EQ::ItemInstance::GetItemBaneDamageBody(bool augments) const
|
||||
|
||||
int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const
|
||||
{
|
||||
int race = RACE_DOUG_0;
|
||||
int race = Race::Doug;
|
||||
const auto item = GetItem();
|
||||
if (item) {
|
||||
race = item->BaneDmgRace;
|
||||
|
||||
@@ -3868,8 +3868,8 @@ namespace RoF
|
||||
}
|
||||
|
||||
float SpawnSize = emu->size;
|
||||
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))
|
||||
if (!((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
|
||||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin))
|
||||
)
|
||||
{
|
||||
PacketSize += 60;
|
||||
@@ -4002,8 +4002,8 @@ namespace RoF
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown18
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown19
|
||||
|
||||
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)
|
||||
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
|
||||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin)
|
||||
)
|
||||
{
|
||||
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
|
||||
|
||||
@@ -2706,7 +2706,7 @@ namespace RoF2
|
||||
|
||||
switch (raid_gen->action)
|
||||
{
|
||||
case raidAdd:
|
||||
case raidAdd:
|
||||
{
|
||||
RaidAddMember_Struct* emu = (RaidAddMember_Struct*)__emu_buffer;
|
||||
|
||||
@@ -3986,7 +3986,7 @@ namespace RoF2
|
||||
if (strlen(emu->suffix))
|
||||
PacketSize += strlen(emu->suffix) + 1;
|
||||
|
||||
if (emu->DestructibleObject || emu->class_ == LDON_TREASURE)
|
||||
if (emu->DestructibleObject || emu->class_ == Class::LDoNTreasure)
|
||||
{
|
||||
if (emu->DestructibleObject)
|
||||
PacketSize = PacketSize - 4; // No bodytype
|
||||
@@ -4007,8 +4007,8 @@ namespace RoF2
|
||||
}
|
||||
|
||||
float SpawnSize = emu->size;
|
||||
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))
|
||||
if (!((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
|
||||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin))
|
||||
)
|
||||
{
|
||||
PacketSize += 60;
|
||||
@@ -4076,7 +4076,7 @@ namespace RoF2
|
||||
// actually part of bitfields
|
||||
uint8 OtherData = 0;
|
||||
|
||||
if (emu->class_ == LDON_TREASURE) //LDoN Chest
|
||||
if (emu->class_ == Class::LDoNTreasure) //LDoN Chest
|
||||
{
|
||||
OtherData = OtherData | 0x04;
|
||||
}
|
||||
@@ -4104,7 +4104,7 @@ namespace RoF2
|
||||
// int DefaultEmitterID
|
||||
VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4
|
||||
|
||||
if (emu->DestructibleObject || emu->class_ == LDON_TREASURE)
|
||||
if (emu->DestructibleObject || emu->class_ == Class::LDoNTreasure)
|
||||
{
|
||||
VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleModel);
|
||||
VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleName2);
|
||||
@@ -4212,8 +4212,8 @@ 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 <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
|
||||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
|
||||
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
|
||||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin)
|
||||
)
|
||||
{
|
||||
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
|
||||
|
||||
@@ -2507,8 +2507,8 @@ namespace SoD
|
||||
}
|
||||
|
||||
float SpawnSize = emu->size;
|
||||
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))
|
||||
if (!((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
|
||||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin))
|
||||
)
|
||||
{
|
||||
PacketSize -= (sizeof(structs::Texture_Struct) * EQ::textures::materialCount);
|
||||
@@ -2706,8 +2706,8 @@ namespace SoD
|
||||
|
||||
Buffer += sizeof(structs::Spawn_Struct_Position);
|
||||
|
||||
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)
|
||||
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
|
||||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin)
|
||||
)
|
||||
{
|
||||
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
|
||||
@@ -2733,8 +2733,8 @@ namespace SoD
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
|
||||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin)
|
||||
)
|
||||
{
|
||||
structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer;
|
||||
|
||||
@@ -2758,7 +2758,7 @@ namespace UF
|
||||
if (strlen(emu->suffix))
|
||||
PacketSize += strlen(emu->suffix) + 1;
|
||||
|
||||
if (emu->DestructibleObject || emu->class_ == LDON_TREASURE)
|
||||
if (emu->DestructibleObject || emu->class_ == Class::LDoNTreasure)
|
||||
{
|
||||
if (emu->DestructibleObject)
|
||||
PacketSize = PacketSize - 4; // No bodytype
|
||||
@@ -2779,8 +2779,8 @@ namespace UF
|
||||
}
|
||||
|
||||
float SpawnSize = emu->size;
|
||||
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))
|
||||
if (!((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
|
||||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin))
|
||||
)
|
||||
{
|
||||
PacketSize -= (sizeof(structs::Texture_Struct) * EQ::textures::materialCount);
|
||||
@@ -2847,7 +2847,7 @@ namespace UF
|
||||
|
||||
uint8 OtherData = 0;
|
||||
|
||||
if (emu->class_ == LDON_TREASURE) //Ldon chest
|
||||
if (emu->class_ == Class::LDoNTreasure) //Ldon chest
|
||||
{
|
||||
OtherData = OtherData | 0x01;
|
||||
}
|
||||
@@ -2873,7 +2873,7 @@ namespace UF
|
||||
}
|
||||
VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4
|
||||
|
||||
if (emu->DestructibleObject || emu->class_ == LDON_TREASURE)
|
||||
if (emu->DestructibleObject || emu->class_ == Class::LDoNTreasure)
|
||||
{
|
||||
VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleModel);
|
||||
VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleName2);
|
||||
@@ -2982,8 +2982,8 @@ namespace UF
|
||||
|
||||
Buffer += sizeof(structs::Spawn_Struct_Position);
|
||||
|
||||
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)
|
||||
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
|
||||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin)
|
||||
)
|
||||
{
|
||||
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
|
||||
@@ -3018,8 +3018,8 @@ namespace UF
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
}
|
||||
|
||||
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)
|
||||
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
|
||||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin)
|
||||
)
|
||||
{
|
||||
structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// types
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <cctype>
|
||||
#include <sstream>
|
||||
|
||||
// containers
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
// utilities
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <tuple>
|
||||
#include <fstream>
|
||||
#include <cstdio>
|
||||
|
||||
// fmt
|
||||
#include <fmt/format.h>
|
||||
|
||||
// lua
|
||||
#include "lua.hpp"
|
||||
#include <luabind/luabind.hpp>
|
||||
#include <luabind/object.hpp>
|
||||
+755
-755
File diff suppressed because it is too large
Load Diff
+739
-1471
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseBlockedSpellsRepository {
|
||||
public:
|
||||
struct BlockedSpells {
|
||||
@@ -31,6 +32,10 @@ public:
|
||||
float z_diff;
|
||||
std::string message;
|
||||
std::string description;
|
||||
int8_t min_expansion;
|
||||
int8_t max_expansion;
|
||||
std::string content_flags;
|
||||
std::string content_flags_disabled;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -53,6 +58,10 @@ public:
|
||||
"z_diff",
|
||||
"message",
|
||||
"description",
|
||||
"min_expansion",
|
||||
"max_expansion",
|
||||
"content_flags",
|
||||
"content_flags_disabled",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -71,6 +80,10 @@ public:
|
||||
"z_diff",
|
||||
"message",
|
||||
"description",
|
||||
"min_expansion",
|
||||
"max_expansion",
|
||||
"content_flags",
|
||||
"content_flags_disabled",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -111,18 +124,22 @@ public:
|
||||
{
|
||||
BlockedSpells e{};
|
||||
|
||||
e.id = 0;
|
||||
e.spellid = 0;
|
||||
e.type = 0;
|
||||
e.zoneid = 0;
|
||||
e.x = 0;
|
||||
e.y = 0;
|
||||
e.z = 0;
|
||||
e.x_diff = 0;
|
||||
e.y_diff = 0;
|
||||
e.z_diff = 0;
|
||||
e.message = "";
|
||||
e.description = "";
|
||||
e.id = 0;
|
||||
e.spellid = 0;
|
||||
e.type = 0;
|
||||
e.zoneid = 0;
|
||||
e.x = 0;
|
||||
e.y = 0;
|
||||
e.z = 0;
|
||||
e.x_diff = 0;
|
||||
e.y_diff = 0;
|
||||
e.z_diff = 0;
|
||||
e.message = "";
|
||||
e.description = "";
|
||||
e.min_expansion = -1;
|
||||
e.max_expansion = -1;
|
||||
e.content_flags = "";
|
||||
e.content_flags_disabled = "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -148,8 +165,9 @@ public:
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE id = {} LIMIT 1",
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
blocked_spells_id
|
||||
)
|
||||
);
|
||||
@@ -158,18 +176,22 @@ public:
|
||||
if (results.RowCount() == 1) {
|
||||
BlockedSpells e{};
|
||||
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.type = static_cast<int8_t>(atoi(row[2]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.x = strtof(row[4], nullptr);
|
||||
e.y = strtof(row[5], nullptr);
|
||||
e.z = strtof(row[6], nullptr);
|
||||
e.x_diff = strtof(row[7], nullptr);
|
||||
e.y_diff = strtof(row[8], nullptr);
|
||||
e.z_diff = strtof(row[9], nullptr);
|
||||
e.message = row[10] ? row[10] : "";
|
||||
e.description = row[11] ? row[11] : "";
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.type = static_cast<int8_t>(atoi(row[2]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.x = strtof(row[4], nullptr);
|
||||
e.y = strtof(row[5], nullptr);
|
||||
e.z = strtof(row[6], nullptr);
|
||||
e.x_diff = strtof(row[7], nullptr);
|
||||
e.y_diff = strtof(row[8], nullptr);
|
||||
e.z_diff = strtof(row[9], nullptr);
|
||||
e.message = row[10] ? row[10] : "";
|
||||
e.description = row[11] ? row[11] : "";
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[12]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[13]));
|
||||
e.content_flags = row[14] ? row[14] : "";
|
||||
e.content_flags_disabled = row[15] ? row[15] : "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -214,6 +236,10 @@ public:
|
||||
v.push_back(columns[9] + " = " + std::to_string(e.z_diff));
|
||||
v.push_back(columns[10] + " = '" + Strings::Escape(e.message) + "'");
|
||||
v.push_back(columns[11] + " = '" + Strings::Escape(e.description) + "'");
|
||||
v.push_back(columns[12] + " = " + std::to_string(e.min_expansion));
|
||||
v.push_back(columns[13] + " = " + std::to_string(e.max_expansion));
|
||||
v.push_back(columns[14] + " = '" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back(columns[15] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -247,6 +273,10 @@ public:
|
||||
v.push_back(std::to_string(e.z_diff));
|
||||
v.push_back("'" + Strings::Escape(e.message) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.description) + "'");
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -288,6 +318,10 @@ public:
|
||||
v.push_back(std::to_string(e.z_diff));
|
||||
v.push_back("'" + Strings::Escape(e.message) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.description) + "'");
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -321,18 +355,22 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
BlockedSpells e{};
|
||||
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.type = static_cast<int8_t>(atoi(row[2]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.x = strtof(row[4], nullptr);
|
||||
e.y = strtof(row[5], nullptr);
|
||||
e.z = strtof(row[6], nullptr);
|
||||
e.x_diff = strtof(row[7], nullptr);
|
||||
e.y_diff = strtof(row[8], nullptr);
|
||||
e.z_diff = strtof(row[9], nullptr);
|
||||
e.message = row[10] ? row[10] : "";
|
||||
e.description = row[11] ? row[11] : "";
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.type = static_cast<int8_t>(atoi(row[2]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.x = strtof(row[4], nullptr);
|
||||
e.y = strtof(row[5], nullptr);
|
||||
e.z = strtof(row[6], nullptr);
|
||||
e.x_diff = strtof(row[7], nullptr);
|
||||
e.y_diff = strtof(row[8], nullptr);
|
||||
e.z_diff = strtof(row[9], nullptr);
|
||||
e.message = row[10] ? row[10] : "";
|
||||
e.description = row[11] ? row[11] : "";
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[12]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[13]));
|
||||
e.content_flags = row[14] ? row[14] : "";
|
||||
e.content_flags_disabled = row[15] ? row[15] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -357,18 +395,22 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
BlockedSpells e{};
|
||||
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.type = static_cast<int8_t>(atoi(row[2]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.x = strtof(row[4], nullptr);
|
||||
e.y = strtof(row[5], nullptr);
|
||||
e.z = strtof(row[6], nullptr);
|
||||
e.x_diff = strtof(row[7], nullptr);
|
||||
e.y_diff = strtof(row[8], nullptr);
|
||||
e.z_diff = strtof(row[9], nullptr);
|
||||
e.message = row[10] ? row[10] : "";
|
||||
e.description = row[11] ? row[11] : "";
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.type = static_cast<int8_t>(atoi(row[2]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.x = strtof(row[4], nullptr);
|
||||
e.y = strtof(row[5], nullptr);
|
||||
e.z = strtof(row[6], nullptr);
|
||||
e.x_diff = strtof(row[7], nullptr);
|
||||
e.y_diff = strtof(row[8], nullptr);
|
||||
e.z_diff = strtof(row[9], nullptr);
|
||||
e.message = row[10] ? row[10] : "";
|
||||
e.description = row[11] ? row[11] : "";
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[12]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[13]));
|
||||
e.content_flags = row[14] ? row[14] : "";
|
||||
e.content_flags_disabled = row[15] ? row[15] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
@@ -16,12 +16,19 @@
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseBotTimersRepository {
|
||||
public:
|
||||
struct BotTimers {
|
||||
uint32_t bot_id;
|
||||
uint32_t timer_id;
|
||||
uint32_t timer_value;
|
||||
uint32_t recast_time;
|
||||
uint8_t is_spell;
|
||||
uint8_t is_disc;
|
||||
uint32_t spell_id;
|
||||
uint8_t is_item;
|
||||
uint32_t item_id;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -35,6 +42,12 @@ public:
|
||||
"bot_id",
|
||||
"timer_id",
|
||||
"timer_value",
|
||||
"recast_time",
|
||||
"is_spell",
|
||||
"is_disc",
|
||||
"spell_id",
|
||||
"is_item",
|
||||
"item_id",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -44,6 +57,12 @@ public:
|
||||
"bot_id",
|
||||
"timer_id",
|
||||
"timer_value",
|
||||
"recast_time",
|
||||
"is_spell",
|
||||
"is_disc",
|
||||
"spell_id",
|
||||
"is_item",
|
||||
"item_id",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -87,6 +106,12 @@ public:
|
||||
e.bot_id = 0;
|
||||
e.timer_id = 0;
|
||||
e.timer_value = 0;
|
||||
e.recast_time = 0;
|
||||
e.is_spell = 0;
|
||||
e.is_disc = 0;
|
||||
e.spell_id = 0;
|
||||
e.is_item = 0;
|
||||
e.item_id = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -112,8 +137,9 @@ public:
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE id = {} LIMIT 1",
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
bot_timers_id
|
||||
)
|
||||
);
|
||||
@@ -125,6 +151,12 @@ public:
|
||||
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.timer_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.timer_value = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
|
||||
e.recast_time = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.is_spell = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
|
||||
e.is_disc = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
|
||||
e.spell_id = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
|
||||
e.is_item = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
|
||||
e.item_id = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -161,6 +193,12 @@ public:
|
||||
v.push_back(columns[0] + " = " + std::to_string(e.bot_id));
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.timer_id));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.timer_value));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.recast_time));
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.is_spell));
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.is_disc));
|
||||
v.push_back(columns[6] + " = " + std::to_string(e.spell_id));
|
||||
v.push_back(columns[7] + " = " + std::to_string(e.is_item));
|
||||
v.push_back(columns[8] + " = " + std::to_string(e.item_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -185,6 +223,12 @@ public:
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.timer_id));
|
||||
v.push_back(std::to_string(e.timer_value));
|
||||
v.push_back(std::to_string(e.recast_time));
|
||||
v.push_back(std::to_string(e.is_spell));
|
||||
v.push_back(std::to_string(e.is_disc));
|
||||
v.push_back(std::to_string(e.spell_id));
|
||||
v.push_back(std::to_string(e.is_item));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -217,6 +261,12 @@ public:
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.timer_id));
|
||||
v.push_back(std::to_string(e.timer_value));
|
||||
v.push_back(std::to_string(e.recast_time));
|
||||
v.push_back(std::to_string(e.is_spell));
|
||||
v.push_back(std::to_string(e.is_disc));
|
||||
v.push_back(std::to_string(e.spell_id));
|
||||
v.push_back(std::to_string(e.is_item));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -253,6 +303,12 @@ public:
|
||||
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.timer_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.timer_value = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
|
||||
e.recast_time = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.is_spell = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
|
||||
e.is_disc = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
|
||||
e.spell_id = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
|
||||
e.is_item = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
|
||||
e.item_id = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -280,6 +336,12 @@ public:
|
||||
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.timer_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.timer_value = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
|
||||
e.recast_time = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.is_spell = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
|
||||
e.is_disc = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
|
||||
e.spell_id = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
|
||||
e.is_item = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
|
||||
e.item_id = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
int32_t damageshield;
|
||||
int32_t deity;
|
||||
int32_t delay;
|
||||
int32_t augdistiller;
|
||||
uint32_t augdistiller;
|
||||
int32_t dotshielding;
|
||||
int32_t dr;
|
||||
int32_t clicktype;
|
||||
@@ -227,7 +227,7 @@ public:
|
||||
int32_t focusunk5;
|
||||
std::string focusunk6;
|
||||
int32_t focusunk7;
|
||||
int32_t scrollunk1;
|
||||
uint32_t scrollunk1;
|
||||
int32_t scrollunk2;
|
||||
int32_t scrollunk3;
|
||||
int32_t scrollunk4;
|
||||
@@ -266,10 +266,10 @@ public:
|
||||
std::string created;
|
||||
int16_t elitematerial;
|
||||
int16_t ldonsellbackrate;
|
||||
int16_t scriptfileid;
|
||||
int32_t scriptfileid;
|
||||
int16_t expendablearrow;
|
||||
int16_t powersourcecapacity;
|
||||
int16_t bardeffect;
|
||||
int32_t powersourcecapacity;
|
||||
int32_t bardeffect;
|
||||
int16_t bardeffecttype;
|
||||
int16_t bardlevel2;
|
||||
int16_t bardlevel;
|
||||
@@ -1307,7 +1307,7 @@ public:
|
||||
e.damageshield = static_cast<int32_t>(atoi(row[52]));
|
||||
e.deity = static_cast<int32_t>(atoi(row[53]));
|
||||
e.delay = static_cast<int32_t>(atoi(row[54]));
|
||||
e.augdistiller = static_cast<int32_t>(atoi(row[55]));
|
||||
e.augdistiller = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
|
||||
e.dotshielding = static_cast<int32_t>(atoi(row[56]));
|
||||
e.dr = static_cast<int32_t>(atoi(row[57]));
|
||||
e.clicktype = static_cast<int32_t>(atoi(row[58]));
|
||||
@@ -1459,7 +1459,7 @@ public:
|
||||
e.focusunk5 = static_cast<int32_t>(atoi(row[204]));
|
||||
e.focusunk6 = row[205] ? row[205] : "";
|
||||
e.focusunk7 = static_cast<int32_t>(atoi(row[206]));
|
||||
e.scrollunk1 = static_cast<int32_t>(atoi(row[207]));
|
||||
e.scrollunk1 = static_cast<uint32_t>(strtoul(row[207], nullptr, 10));
|
||||
e.scrollunk2 = static_cast<int32_t>(atoi(row[208]));
|
||||
e.scrollunk3 = static_cast<int32_t>(atoi(row[209]));
|
||||
e.scrollunk4 = static_cast<int32_t>(atoi(row[210]));
|
||||
@@ -1498,10 +1498,10 @@ public:
|
||||
e.created = row[243] ? row[243] : "";
|
||||
e.elitematerial = static_cast<int16_t>(atoi(row[244]));
|
||||
e.ldonsellbackrate = static_cast<int16_t>(atoi(row[245]));
|
||||
e.scriptfileid = static_cast<int16_t>(atoi(row[246]));
|
||||
e.scriptfileid = static_cast<int32_t>(atoi(row[246]));
|
||||
e.expendablearrow = static_cast<int16_t>(atoi(row[247]));
|
||||
e.powersourcecapacity = static_cast<int16_t>(atoi(row[248]));
|
||||
e.bardeffect = static_cast<int16_t>(atoi(row[249]));
|
||||
e.powersourcecapacity = static_cast<int32_t>(atoi(row[248]));
|
||||
e.bardeffect = static_cast<int32_t>(atoi(row[249]));
|
||||
e.bardeffecttype = static_cast<int16_t>(atoi(row[250]));
|
||||
e.bardlevel2 = static_cast<int16_t>(atoi(row[251]));
|
||||
e.bardlevel = static_cast<int16_t>(atoi(row[252]));
|
||||
@@ -2563,7 +2563,7 @@ public:
|
||||
e.damageshield = static_cast<int32_t>(atoi(row[52]));
|
||||
e.deity = static_cast<int32_t>(atoi(row[53]));
|
||||
e.delay = static_cast<int32_t>(atoi(row[54]));
|
||||
e.augdistiller = static_cast<int32_t>(atoi(row[55]));
|
||||
e.augdistiller = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
|
||||
e.dotshielding = static_cast<int32_t>(atoi(row[56]));
|
||||
e.dr = static_cast<int32_t>(atoi(row[57]));
|
||||
e.clicktype = static_cast<int32_t>(atoi(row[58]));
|
||||
@@ -2715,7 +2715,7 @@ public:
|
||||
e.focusunk5 = static_cast<int32_t>(atoi(row[204]));
|
||||
e.focusunk6 = row[205] ? row[205] : "";
|
||||
e.focusunk7 = static_cast<int32_t>(atoi(row[206]));
|
||||
e.scrollunk1 = static_cast<int32_t>(atoi(row[207]));
|
||||
e.scrollunk1 = static_cast<uint32_t>(strtoul(row[207], nullptr, 10));
|
||||
e.scrollunk2 = static_cast<int32_t>(atoi(row[208]));
|
||||
e.scrollunk3 = static_cast<int32_t>(atoi(row[209]));
|
||||
e.scrollunk4 = static_cast<int32_t>(atoi(row[210]));
|
||||
@@ -2754,10 +2754,10 @@ public:
|
||||
e.created = row[243] ? row[243] : "";
|
||||
e.elitematerial = static_cast<int16_t>(atoi(row[244]));
|
||||
e.ldonsellbackrate = static_cast<int16_t>(atoi(row[245]));
|
||||
e.scriptfileid = static_cast<int16_t>(atoi(row[246]));
|
||||
e.scriptfileid = static_cast<int32_t>(atoi(row[246]));
|
||||
e.expendablearrow = static_cast<int16_t>(atoi(row[247]));
|
||||
e.powersourcecapacity = static_cast<int16_t>(atoi(row[248]));
|
||||
e.bardeffect = static_cast<int16_t>(atoi(row[249]));
|
||||
e.powersourcecapacity = static_cast<int32_t>(atoi(row[248]));
|
||||
e.bardeffect = static_cast<int32_t>(atoi(row[249]));
|
||||
e.bardeffecttype = static_cast<int16_t>(atoi(row[250]));
|
||||
e.bardlevel2 = static_cast<int16_t>(atoi(row[251]));
|
||||
e.bardlevel = static_cast<int16_t>(atoi(row[252]));
|
||||
@@ -2872,7 +2872,7 @@ public:
|
||||
e.damageshield = static_cast<int32_t>(atoi(row[52]));
|
||||
e.deity = static_cast<int32_t>(atoi(row[53]));
|
||||
e.delay = static_cast<int32_t>(atoi(row[54]));
|
||||
e.augdistiller = static_cast<int32_t>(atoi(row[55]));
|
||||
e.augdistiller = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
|
||||
e.dotshielding = static_cast<int32_t>(atoi(row[56]));
|
||||
e.dr = static_cast<int32_t>(atoi(row[57]));
|
||||
e.clicktype = static_cast<int32_t>(atoi(row[58]));
|
||||
@@ -3024,7 +3024,7 @@ public:
|
||||
e.focusunk5 = static_cast<int32_t>(atoi(row[204]));
|
||||
e.focusunk6 = row[205] ? row[205] : "";
|
||||
e.focusunk7 = static_cast<int32_t>(atoi(row[206]));
|
||||
e.scrollunk1 = static_cast<int32_t>(atoi(row[207]));
|
||||
e.scrollunk1 = static_cast<uint32_t>(strtoul(row[207], nullptr, 10));
|
||||
e.scrollunk2 = static_cast<int32_t>(atoi(row[208]));
|
||||
e.scrollunk3 = static_cast<int32_t>(atoi(row[209]));
|
||||
e.scrollunk4 = static_cast<int32_t>(atoi(row[210]));
|
||||
@@ -3063,10 +3063,10 @@ public:
|
||||
e.created = row[243] ? row[243] : "";
|
||||
e.elitematerial = static_cast<int16_t>(atoi(row[244]));
|
||||
e.ldonsellbackrate = static_cast<int16_t>(atoi(row[245]));
|
||||
e.scriptfileid = static_cast<int16_t>(atoi(row[246]));
|
||||
e.scriptfileid = static_cast<int32_t>(atoi(row[246]));
|
||||
e.expendablearrow = static_cast<int16_t>(atoi(row[247]));
|
||||
e.powersourcecapacity = static_cast<int16_t>(atoi(row[248]));
|
||||
e.bardeffect = static_cast<int16_t>(atoi(row[249]));
|
||||
e.powersourcecapacity = static_cast<int32_t>(atoi(row[248]));
|
||||
e.bardeffect = static_cast<int32_t>(atoi(row[249]));
|
||||
e.bardeffecttype = static_cast<int16_t>(atoi(row[250]));
|
||||
e.bardlevel2 = static_cast<int16_t>(atoi(row[251]));
|
||||
e.bardlevel = static_cast<int16_t>(atoi(row[252]));
|
||||
|
||||
@@ -0,0 +1,344 @@
|
||||
/**
|
||||
* DO NOT MODIFY THIS FILE
|
||||
*
|
||||
* This repository was automatically generated and is NOT to be modified directly.
|
||||
* Any repository modifications are meant to be made to the repository extending the base.
|
||||
* Any modifications to base repositories are to be made by the generator only
|
||||
*
|
||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_BASE_KEYRING_REPOSITORY_H
|
||||
#define EQEMU_BASE_KEYRING_REPOSITORY_H
|
||||
|
||||
#include "../../database.h"
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseKeyringRepository {
|
||||
public:
|
||||
struct Keyring {
|
||||
uint32_t id;
|
||||
int32_t char_id;
|
||||
int32_t item_id;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
{
|
||||
return std::string("id");
|
||||
}
|
||||
|
||||
static std::vector<std::string> Columns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"char_id",
|
||||
"item_id",
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::string> SelectColumns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"char_id",
|
||||
"item_id",
|
||||
};
|
||||
}
|
||||
|
||||
static std::string ColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", Columns()));
|
||||
}
|
||||
|
||||
static std::string SelectColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", SelectColumns()));
|
||||
}
|
||||
|
||||
static std::string TableName()
|
||||
{
|
||||
return std::string("keyring");
|
||||
}
|
||||
|
||||
static std::string BaseSelect()
|
||||
{
|
||||
return fmt::format(
|
||||
"SELECT {} FROM {}",
|
||||
SelectColumnsRaw(),
|
||||
TableName()
|
||||
);
|
||||
}
|
||||
|
||||
static std::string BaseInsert()
|
||||
{
|
||||
return fmt::format(
|
||||
"INSERT INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static Keyring NewEntity()
|
||||
{
|
||||
Keyring e{};
|
||||
|
||||
e.id = 0;
|
||||
e.char_id = 0;
|
||||
e.item_id = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static Keyring GetKeyring(
|
||||
const std::vector<Keyring> &keyrings,
|
||||
int keyring_id
|
||||
)
|
||||
{
|
||||
for (auto &keyring : keyrings) {
|
||||
if (keyring.id == keyring_id) {
|
||||
return keyring;
|
||||
}
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static Keyring FindOne(
|
||||
Database& db,
|
||||
int keyring_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
keyring_id
|
||||
)
|
||||
);
|
||||
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1) {
|
||||
Keyring e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.char_id = static_cast<int32_t>(atoi(row[1]));
|
||||
e.item_id = static_cast<int32_t>(atoi(row[2]));
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static int DeleteOne(
|
||||
Database& db,
|
||||
int keyring_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {} = {}",
|
||||
TableName(),
|
||||
PrimaryKey(),
|
||||
keyring_id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int UpdateOne(
|
||||
Database& db,
|
||||
const Keyring &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.char_id));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.item_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE {} SET {} WHERE {} = {}",
|
||||
TableName(),
|
||||
Strings::Implode(", ", v),
|
||||
PrimaryKey(),
|
||||
e.id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static Keyring InsertOne(
|
||||
Database& db,
|
||||
Keyring e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.char_id));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
if (results.Success()) {
|
||||
e.id = results.LastInsertedID();
|
||||
return e;
|
||||
}
|
||||
|
||||
e = NewEntity();
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static int InsertMany(
|
||||
Database& db,
|
||||
const std::vector<Keyring> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.char_id));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static std::vector<Keyring> All(Database& db)
|
||||
{
|
||||
std::vector<Keyring> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{}",
|
||||
BaseSelect()
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
Keyring e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.char_id = static_cast<int32_t>(atoi(row[1]));
|
||||
e.item_id = static_cast<int32_t>(atoi(row[2]));
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static std::vector<Keyring> GetWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
std::vector<Keyring> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {}",
|
||||
BaseSelect(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
Keyring e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.char_id = static_cast<int32_t>(atoi(row[1]));
|
||||
e.item_id = static_cast<int32_t>(atoi(row[2]));
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static int DeleteWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {}",
|
||||
TableName(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int Truncate(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"TRUNCATE TABLE {}",
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int64 GetMaxId(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COALESCE(MAX({}), 0) FROM {}",
|
||||
PrimaryKey(),
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
static int64 Count(Database& db, const std::string &where_filter = "")
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COUNT(*) FROM {} {}",
|
||||
TableName(),
|
||||
(where_filter.empty() ? "" : "WHERE " + where_filter)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_BASE_KEYRING_REPOSITORY_H
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseNpcEmotesRepository {
|
||||
public:
|
||||
struct NpcEmotes {
|
||||
@@ -120,8 +121,9 @@ public:
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE id = {} LIMIT 1",
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
npc_emotes_id
|
||||
)
|
||||
);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseObjectRepository {
|
||||
public:
|
||||
struct Object {
|
||||
@@ -31,9 +32,9 @@ public:
|
||||
std::string objectname;
|
||||
int32_t type;
|
||||
int32_t icon;
|
||||
int32_t unknown08;
|
||||
int32_t unknown10;
|
||||
int32_t unknown20;
|
||||
float size_percentage;
|
||||
int32_t solid_type;
|
||||
int32_t incline;
|
||||
int32_t unknown24;
|
||||
int32_t unknown60;
|
||||
int32_t unknown64;
|
||||
@@ -71,9 +72,9 @@ public:
|
||||
"objectname",
|
||||
"type",
|
||||
"icon",
|
||||
"unknown08",
|
||||
"unknown10",
|
||||
"unknown20",
|
||||
"size_percentage",
|
||||
"solid_type",
|
||||
"incline",
|
||||
"unknown24",
|
||||
"unknown60",
|
||||
"unknown64",
|
||||
@@ -107,9 +108,9 @@ public:
|
||||
"objectname",
|
||||
"type",
|
||||
"icon",
|
||||
"unknown08",
|
||||
"unknown10",
|
||||
"unknown20",
|
||||
"size_percentage",
|
||||
"solid_type",
|
||||
"incline",
|
||||
"unknown24",
|
||||
"unknown60",
|
||||
"unknown64",
|
||||
@@ -177,9 +178,9 @@ public:
|
||||
e.objectname = "";
|
||||
e.type = 0;
|
||||
e.icon = 0;
|
||||
e.unknown08 = 0;
|
||||
e.unknown10 = 0;
|
||||
e.unknown20 = 0;
|
||||
e.size_percentage = 0;
|
||||
e.solid_type = 0;
|
||||
e.incline = 0;
|
||||
e.unknown24 = 0;
|
||||
e.unknown60 = 0;
|
||||
e.unknown64 = 0;
|
||||
@@ -220,8 +221,9 @@ public:
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE id = {} LIMIT 1",
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
object_id
|
||||
)
|
||||
);
|
||||
@@ -242,9 +244,9 @@ public:
|
||||
e.objectname = row[9] ? row[9] : "";
|
||||
e.type = static_cast<int32_t>(atoi(row[10]));
|
||||
e.icon = static_cast<int32_t>(atoi(row[11]));
|
||||
e.unknown08 = static_cast<int32_t>(atoi(row[12]));
|
||||
e.unknown10 = static_cast<int32_t>(atoi(row[13]));
|
||||
e.unknown20 = static_cast<int32_t>(atoi(row[14]));
|
||||
e.size_percentage = strtof(row[12], nullptr);
|
||||
e.solid_type = static_cast<int32_t>(atoi(row[13]));
|
||||
e.incline = static_cast<int32_t>(atoi(row[14]));
|
||||
e.unknown24 = static_cast<int32_t>(atoi(row[15]));
|
||||
e.unknown60 = static_cast<int32_t>(atoi(row[16]));
|
||||
e.unknown64 = static_cast<int32_t>(atoi(row[17]));
|
||||
@@ -304,9 +306,9 @@ public:
|
||||
v.push_back(columns[9] + " = '" + Strings::Escape(e.objectname) + "'");
|
||||
v.push_back(columns[10] + " = " + std::to_string(e.type));
|
||||
v.push_back(columns[11] + " = " + std::to_string(e.icon));
|
||||
v.push_back(columns[12] + " = " + std::to_string(e.unknown08));
|
||||
v.push_back(columns[13] + " = " + std::to_string(e.unknown10));
|
||||
v.push_back(columns[14] + " = " + std::to_string(e.unknown20));
|
||||
v.push_back(columns[12] + " = " + std::to_string(e.size_percentage));
|
||||
v.push_back(columns[13] + " = " + std::to_string(e.solid_type));
|
||||
v.push_back(columns[14] + " = " + std::to_string(e.incline));
|
||||
v.push_back(columns[15] + " = " + std::to_string(e.unknown24));
|
||||
v.push_back(columns[16] + " = " + std::to_string(e.unknown60));
|
||||
v.push_back(columns[17] + " = " + std::to_string(e.unknown64));
|
||||
@@ -355,9 +357,9 @@ public:
|
||||
v.push_back("'" + Strings::Escape(e.objectname) + "'");
|
||||
v.push_back(std::to_string(e.type));
|
||||
v.push_back(std::to_string(e.icon));
|
||||
v.push_back(std::to_string(e.unknown08));
|
||||
v.push_back(std::to_string(e.unknown10));
|
||||
v.push_back(std::to_string(e.unknown20));
|
||||
v.push_back(std::to_string(e.size_percentage));
|
||||
v.push_back(std::to_string(e.solid_type));
|
||||
v.push_back(std::to_string(e.incline));
|
||||
v.push_back(std::to_string(e.unknown24));
|
||||
v.push_back(std::to_string(e.unknown60));
|
||||
v.push_back(std::to_string(e.unknown64));
|
||||
@@ -414,9 +416,9 @@ public:
|
||||
v.push_back("'" + Strings::Escape(e.objectname) + "'");
|
||||
v.push_back(std::to_string(e.type));
|
||||
v.push_back(std::to_string(e.icon));
|
||||
v.push_back(std::to_string(e.unknown08));
|
||||
v.push_back(std::to_string(e.unknown10));
|
||||
v.push_back(std::to_string(e.unknown20));
|
||||
v.push_back(std::to_string(e.size_percentage));
|
||||
v.push_back(std::to_string(e.solid_type));
|
||||
v.push_back(std::to_string(e.incline));
|
||||
v.push_back(std::to_string(e.unknown24));
|
||||
v.push_back(std::to_string(e.unknown60));
|
||||
v.push_back(std::to_string(e.unknown64));
|
||||
@@ -477,9 +479,9 @@ public:
|
||||
e.objectname = row[9] ? row[9] : "";
|
||||
e.type = static_cast<int32_t>(atoi(row[10]));
|
||||
e.icon = static_cast<int32_t>(atoi(row[11]));
|
||||
e.unknown08 = static_cast<int32_t>(atoi(row[12]));
|
||||
e.unknown10 = static_cast<int32_t>(atoi(row[13]));
|
||||
e.unknown20 = static_cast<int32_t>(atoi(row[14]));
|
||||
e.size_percentage = strtof(row[12], nullptr);
|
||||
e.solid_type = static_cast<int32_t>(atoi(row[13]));
|
||||
e.incline = static_cast<int32_t>(atoi(row[14]));
|
||||
e.unknown24 = static_cast<int32_t>(atoi(row[15]));
|
||||
e.unknown60 = static_cast<int32_t>(atoi(row[16]));
|
||||
e.unknown64 = static_cast<int32_t>(atoi(row[17]));
|
||||
@@ -531,9 +533,9 @@ public:
|
||||
e.objectname = row[9] ? row[9] : "";
|
||||
e.type = static_cast<int32_t>(atoi(row[10]));
|
||||
e.icon = static_cast<int32_t>(atoi(row[11]));
|
||||
e.unknown08 = static_cast<int32_t>(atoi(row[12]));
|
||||
e.unknown10 = static_cast<int32_t>(atoi(row[13]));
|
||||
e.unknown20 = static_cast<int32_t>(atoi(row[14]));
|
||||
e.size_percentage = strtof(row[12], nullptr);
|
||||
e.solid_type = static_cast<int32_t>(atoi(row[13]));
|
||||
e.incline = static_cast<int32_t>(atoi(row[14]));
|
||||
e.unknown24 = static_cast<int32_t>(atoi(row[15]));
|
||||
e.unknown60 = static_cast<int32_t>(atoi(row[16]));
|
||||
e.unknown64 = static_cast<int32_t>(atoi(row[17]));
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseSpawnentryRepository {
|
||||
public:
|
||||
struct Spawnentry {
|
||||
@@ -23,6 +24,8 @@ public:
|
||||
int32_t npcID;
|
||||
int16_t chance;
|
||||
int32_t condition_value_filter;
|
||||
int16_t min_time;
|
||||
int16_t max_time;
|
||||
int8_t min_expansion;
|
||||
int8_t max_expansion;
|
||||
std::string content_flags;
|
||||
@@ -41,6 +44,8 @@ public:
|
||||
"npcID",
|
||||
"chance",
|
||||
"condition_value_filter",
|
||||
"min_time",
|
||||
"max_time",
|
||||
"min_expansion",
|
||||
"max_expansion",
|
||||
"content_flags",
|
||||
@@ -55,6 +60,8 @@ public:
|
||||
"npcID",
|
||||
"chance",
|
||||
"condition_value_filter",
|
||||
"min_time",
|
||||
"max_time",
|
||||
"min_expansion",
|
||||
"max_expansion",
|
||||
"content_flags",
|
||||
@@ -103,6 +110,8 @@ public:
|
||||
e.npcID = 0;
|
||||
e.chance = 0;
|
||||
e.condition_value_filter = 1;
|
||||
e.min_time = 0;
|
||||
e.max_time = 0;
|
||||
e.min_expansion = -1;
|
||||
e.max_expansion = -1;
|
||||
e.content_flags = "";
|
||||
@@ -132,8 +141,9 @@ public:
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE id = {} LIMIT 1",
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
spawnentry_id
|
||||
)
|
||||
);
|
||||
@@ -146,10 +156,12 @@ public:
|
||||
e.npcID = static_cast<int32_t>(atoi(row[1]));
|
||||
e.chance = static_cast<int16_t>(atoi(row[2]));
|
||||
e.condition_value_filter = static_cast<int32_t>(atoi(row[3]));
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[4]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[5]));
|
||||
e.content_flags = row[6] ? row[6] : "";
|
||||
e.content_flags_disabled = row[7] ? row[7] : "";
|
||||
e.min_time = static_cast<int16_t>(atoi(row[4]));
|
||||
e.max_time = static_cast<int16_t>(atoi(row[5]));
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[6]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[7]));
|
||||
e.content_flags = row[8] ? row[8] : "";
|
||||
e.content_flags_disabled = row[9] ? row[9] : "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -187,10 +199,12 @@ public:
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.npcID));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.chance));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.condition_value_filter));
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.min_expansion));
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.max_expansion));
|
||||
v.push_back(columns[6] + " = '" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back(columns[7] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.min_time));
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.max_time));
|
||||
v.push_back(columns[6] + " = " + std::to_string(e.min_expansion));
|
||||
v.push_back(columns[7] + " = " + std::to_string(e.max_expansion));
|
||||
v.push_back(columns[8] + " = '" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back(columns[9] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -216,6 +230,8 @@ public:
|
||||
v.push_back(std::to_string(e.npcID));
|
||||
v.push_back(std::to_string(e.chance));
|
||||
v.push_back(std::to_string(e.condition_value_filter));
|
||||
v.push_back(std::to_string(e.min_time));
|
||||
v.push_back(std::to_string(e.max_time));
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
@@ -253,6 +269,8 @@ public:
|
||||
v.push_back(std::to_string(e.npcID));
|
||||
v.push_back(std::to_string(e.chance));
|
||||
v.push_back(std::to_string(e.condition_value_filter));
|
||||
v.push_back(std::to_string(e.min_time));
|
||||
v.push_back(std::to_string(e.max_time));
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
@@ -294,10 +312,12 @@ public:
|
||||
e.npcID = static_cast<int32_t>(atoi(row[1]));
|
||||
e.chance = static_cast<int16_t>(atoi(row[2]));
|
||||
e.condition_value_filter = static_cast<int32_t>(atoi(row[3]));
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[4]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[5]));
|
||||
e.content_flags = row[6] ? row[6] : "";
|
||||
e.content_flags_disabled = row[7] ? row[7] : "";
|
||||
e.min_time = static_cast<int16_t>(atoi(row[4]));
|
||||
e.max_time = static_cast<int16_t>(atoi(row[5]));
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[6]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[7]));
|
||||
e.content_flags = row[8] ? row[8] : "";
|
||||
e.content_flags_disabled = row[9] ? row[9] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -326,10 +346,12 @@ public:
|
||||
e.npcID = static_cast<int32_t>(atoi(row[1]));
|
||||
e.chance = static_cast<int16_t>(atoi(row[2]));
|
||||
e.condition_value_filter = static_cast<int32_t>(atoi(row[3]));
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[4]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[5]));
|
||||
e.content_flags = row[6] ? row[6] : "";
|
||||
e.content_flags_disabled = row[7] ? row[7] : "";
|
||||
e.min_time = static_cast<int16_t>(atoi(row[4]));
|
||||
e.max_time = static_cast<int16_t>(atoi(row[5]));
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[6]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[7]));
|
||||
e.content_flags = row[8] ? row[8] : "";
|
||||
e.content_flags_disabled = row[9] ? row[9] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
@@ -16,18 +16,19 @@
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseStartingItemsRepository {
|
||||
public:
|
||||
struct StartingItems {
|
||||
uint32_t id;
|
||||
int32_t race;
|
||||
int32_t class_;
|
||||
int32_t deityid;
|
||||
int32_t zoneid;
|
||||
int32_t itemid;
|
||||
std::string class_list;
|
||||
std::string race_list;
|
||||
std::string deity_list;
|
||||
std::string zone_id_list;
|
||||
uint32_t item_id;
|
||||
uint8_t item_charges;
|
||||
int8_t gm;
|
||||
int32_t slot;
|
||||
int32_t status;
|
||||
int32_t inventory_slot;
|
||||
int8_t min_expansion;
|
||||
int8_t max_expansion;
|
||||
std::string content_flags;
|
||||
@@ -43,14 +44,14 @@ public:
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"race",
|
||||
"`class`",
|
||||
"deityid",
|
||||
"zoneid",
|
||||
"itemid",
|
||||
"class_list",
|
||||
"race_list",
|
||||
"deity_list",
|
||||
"zone_id_list",
|
||||
"item_id",
|
||||
"item_charges",
|
||||
"gm",
|
||||
"slot",
|
||||
"status",
|
||||
"inventory_slot",
|
||||
"min_expansion",
|
||||
"max_expansion",
|
||||
"content_flags",
|
||||
@@ -62,14 +63,14 @@ public:
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"race",
|
||||
"`class`",
|
||||
"deityid",
|
||||
"zoneid",
|
||||
"itemid",
|
||||
"class_list",
|
||||
"race_list",
|
||||
"deity_list",
|
||||
"zone_id_list",
|
||||
"item_id",
|
||||
"item_charges",
|
||||
"gm",
|
||||
"slot",
|
||||
"status",
|
||||
"inventory_slot",
|
||||
"min_expansion",
|
||||
"max_expansion",
|
||||
"content_flags",
|
||||
@@ -115,14 +116,14 @@ public:
|
||||
StartingItems e{};
|
||||
|
||||
e.id = 0;
|
||||
e.race = 0;
|
||||
e.class_ = 0;
|
||||
e.deityid = 0;
|
||||
e.zoneid = 0;
|
||||
e.itemid = 0;
|
||||
e.class_list = "";
|
||||
e.race_list = "";
|
||||
e.deity_list = "";
|
||||
e.zone_id_list = "";
|
||||
e.item_id = 0;
|
||||
e.item_charges = 1;
|
||||
e.gm = 0;
|
||||
e.slot = -1;
|
||||
e.status = 0;
|
||||
e.inventory_slot = -1;
|
||||
e.min_expansion = -1;
|
||||
e.max_expansion = -1;
|
||||
e.content_flags = "";
|
||||
@@ -152,8 +153,9 @@ public:
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE id = {} LIMIT 1",
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
starting_items_id
|
||||
)
|
||||
);
|
||||
@@ -163,14 +165,14 @@ public:
|
||||
StartingItems e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.race = static_cast<int32_t>(atoi(row[1]));
|
||||
e.class_ = static_cast<int32_t>(atoi(row[2]));
|
||||
e.deityid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[4]));
|
||||
e.itemid = static_cast<int32_t>(atoi(row[5]));
|
||||
e.class_list = row[1] ? row[1] : "";
|
||||
e.race_list = row[2] ? row[2] : "";
|
||||
e.deity_list = row[3] ? row[3] : "";
|
||||
e.zone_id_list = row[4] ? row[4] : "";
|
||||
e.item_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
|
||||
e.item_charges = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
|
||||
e.gm = static_cast<int8_t>(atoi(row[7]));
|
||||
e.slot = static_cast<int32_t>(atoi(row[8]));
|
||||
e.status = static_cast<int32_t>(atoi(row[7]));
|
||||
e.inventory_slot = static_cast<int32_t>(atoi(row[8]));
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[9]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[10]));
|
||||
e.content_flags = row[11] ? row[11] : "";
|
||||
@@ -208,14 +210,14 @@ public:
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.race));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.class_));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.deityid));
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.zoneid));
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.itemid));
|
||||
v.push_back(columns[1] + " = '" + Strings::Escape(e.class_list) + "'");
|
||||
v.push_back(columns[2] + " = '" + Strings::Escape(e.race_list) + "'");
|
||||
v.push_back(columns[3] + " = '" + Strings::Escape(e.deity_list) + "'");
|
||||
v.push_back(columns[4] + " = '" + Strings::Escape(e.zone_id_list) + "'");
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.item_id));
|
||||
v.push_back(columns[6] + " = " + std::to_string(e.item_charges));
|
||||
v.push_back(columns[7] + " = " + std::to_string(e.gm));
|
||||
v.push_back(columns[8] + " = " + std::to_string(e.slot));
|
||||
v.push_back(columns[7] + " = " + std::to_string(e.status));
|
||||
v.push_back(columns[8] + " = " + std::to_string(e.inventory_slot));
|
||||
v.push_back(columns[9] + " = " + std::to_string(e.min_expansion));
|
||||
v.push_back(columns[10] + " = " + std::to_string(e.max_expansion));
|
||||
v.push_back(columns[11] + " = '" + Strings::Escape(e.content_flags) + "'");
|
||||
@@ -242,14 +244,14 @@ public:
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.race));
|
||||
v.push_back(std::to_string(e.class_));
|
||||
v.push_back(std::to_string(e.deityid));
|
||||
v.push_back(std::to_string(e.zoneid));
|
||||
v.push_back(std::to_string(e.itemid));
|
||||
v.push_back("'" + Strings::Escape(e.class_list) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.race_list) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.deity_list) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.zone_id_list) + "'");
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.item_charges));
|
||||
v.push_back(std::to_string(e.gm));
|
||||
v.push_back(std::to_string(e.slot));
|
||||
v.push_back(std::to_string(e.status));
|
||||
v.push_back(std::to_string(e.inventory_slot));
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
@@ -284,14 +286,14 @@ public:
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.race));
|
||||
v.push_back(std::to_string(e.class_));
|
||||
v.push_back(std::to_string(e.deityid));
|
||||
v.push_back(std::to_string(e.zoneid));
|
||||
v.push_back(std::to_string(e.itemid));
|
||||
v.push_back("'" + Strings::Escape(e.class_list) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.race_list) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.deity_list) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.zone_id_list) + "'");
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.item_charges));
|
||||
v.push_back(std::to_string(e.gm));
|
||||
v.push_back(std::to_string(e.slot));
|
||||
v.push_back(std::to_string(e.status));
|
||||
v.push_back(std::to_string(e.inventory_slot));
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
@@ -330,14 +332,14 @@ public:
|
||||
StartingItems e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.race = static_cast<int32_t>(atoi(row[1]));
|
||||
e.class_ = static_cast<int32_t>(atoi(row[2]));
|
||||
e.deityid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[4]));
|
||||
e.itemid = static_cast<int32_t>(atoi(row[5]));
|
||||
e.class_list = row[1] ? row[1] : "";
|
||||
e.race_list = row[2] ? row[2] : "";
|
||||
e.deity_list = row[3] ? row[3] : "";
|
||||
e.zone_id_list = row[4] ? row[4] : "";
|
||||
e.item_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
|
||||
e.item_charges = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
|
||||
e.gm = static_cast<int8_t>(atoi(row[7]));
|
||||
e.slot = static_cast<int32_t>(atoi(row[8]));
|
||||
e.status = static_cast<int32_t>(atoi(row[7]));
|
||||
e.inventory_slot = static_cast<int32_t>(atoi(row[8]));
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[9]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[10]));
|
||||
e.content_flags = row[11] ? row[11] : "";
|
||||
@@ -367,14 +369,14 @@ public:
|
||||
StartingItems e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.race = static_cast<int32_t>(atoi(row[1]));
|
||||
e.class_ = static_cast<int32_t>(atoi(row[2]));
|
||||
e.deityid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[4]));
|
||||
e.itemid = static_cast<int32_t>(atoi(row[5]));
|
||||
e.class_list = row[1] ? row[1] : "";
|
||||
e.race_list = row[2] ? row[2] : "";
|
||||
e.deity_list = row[3] ? row[3] : "";
|
||||
e.zone_id_list = row[4] ? row[4] : "";
|
||||
e.item_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
|
||||
e.item_charges = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
|
||||
e.gm = static_cast<int8_t>(atoi(row[7]));
|
||||
e.slot = static_cast<int32_t>(atoi(row[8]));
|
||||
e.status = static_cast<int32_t>(atoi(row[7]));
|
||||
e.inventory_slot = static_cast<int32_t>(atoi(row[8]));
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[9]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[10]));
|
||||
e.content_flags = row[11] ? row[11] : "";
|
||||
|
||||
@@ -120,6 +120,8 @@ public:
|
||||
{.parent_command = "set", .sub_command = "title_suffix", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "titlesuffix"},
|
||||
{.parent_command = "set", .sub_command = "weather", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "weather"},
|
||||
{.parent_command = "set", .sub_command = "zone", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "zclip|zcolor|zheader|zonelock|zsafecoords|zsky|zunderworld"},
|
||||
{.parent_command = "show", .sub_command = "aas", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showaas"},
|
||||
{.parent_command = "show", .sub_command = "aa_points", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showaapoints|showaapts"},
|
||||
{.parent_command = "show", .sub_command = "aggro", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "aggro"},
|
||||
{.parent_command = "show", .sub_command = "buffs", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showbuffs"},
|
||||
{.parent_command = "show", .sub_command = "buried_corpse_count", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "getplayerburiedcorpsecount"},
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef EQEMU_KEYRING_REPOSITORY_H
|
||||
#define EQEMU_KEYRING_REPOSITORY_H
|
||||
|
||||
#include "../database.h"
|
||||
#include "../strings.h"
|
||||
#include "base/base_keyring_repository.h"
|
||||
|
||||
class KeyringRepository: public BaseKeyringRepository {
|
||||
public:
|
||||
|
||||
/**
|
||||
* This file was auto generated and can be modified and extended upon
|
||||
*
|
||||
* Base repository methods are automatically
|
||||
* generated in the "base" version of this repository. The base repository
|
||||
* is immutable and to be left untouched, while methods in this class
|
||||
* are used as extension methods for more specific persistence-layer
|
||||
* accessors or mutators.
|
||||
*
|
||||
* Base Methods (Subject to be expanded upon in time)
|
||||
*
|
||||
* Note: Not all tables are designed appropriately to fit functionality with all base methods
|
||||
*
|
||||
* InsertOne
|
||||
* UpdateOne
|
||||
* DeleteOne
|
||||
* FindOne
|
||||
* GetWhere(std::string where_filter)
|
||||
* DeleteWhere(std::string where_filter)
|
||||
* InsertMany
|
||||
* All
|
||||
*
|
||||
* Example custom methods in a repository
|
||||
*
|
||||
* KeyringRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||
* KeyringRepository::GetWhereNeverExpires()
|
||||
* KeyringRepository::GetWhereXAndY()
|
||||
* KeyringRepository::DeleteWhereXAndY()
|
||||
*
|
||||
* Most of the above could be covered by base methods, but if you as a developer
|
||||
* find yourself re-using logic for other parts of the code, its best to just make a
|
||||
* method that can be re-used easily elsewhere especially if it can use a base repository
|
||||
* method and encapsulate filters there
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_KEYRING_REPOSITORY_H
|
||||
@@ -6,7 +6,7 @@
|
||||
* Any modifications to base repositories are to be made by the generator only
|
||||
*
|
||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
||||
* @docs https://docs.eqemu.io/developer/repositories
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_BASE_{{TABLE_NAME_UPPER}}_REPOSITORY_H
|
||||
@@ -319,6 +319,62 @@ public:
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
static std::string BaseReplace()
|
||||
{
|
||||
return fmt::format(
|
||||
"REPLACE INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static int ReplaceOne(
|
||||
Database& db,
|
||||
const {{TABLE_NAME_STRUCT}} &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
{{INSERT_ONE_ENTRIES}}
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseReplace(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int ReplaceMany(
|
||||
Database& db,
|
||||
const std::vector<{{TABLE_NAME_STRUCT}}> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
{{INSERT_MANY_ENTRIES}}
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseReplace(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_BASE_{{TABLE_NAME_UPPER}}_REPOSITORY_H
|
||||
|
||||
@@ -215,6 +215,7 @@ RULE_BOOL(Character, EnableRaidEXPModifier, true, "Enable or disable the raid ex
|
||||
RULE_BOOL(Character, EnableRaidMemberEXPModifier, true, "Enable or disable the raid experience modifier based on members in raid, default is true")
|
||||
RULE_BOOL(Character, LeaveCursorMoneyOnCorpse, false, "Enable or disable leaving cursor money on player corpses")
|
||||
RULE_BOOL(Character, ItemExtraSkillDamageCalcAsPercent, false, "If enabled, apply Item Extra Skill Damage as Percentage-based modifiers")
|
||||
RULE_BOOL(Character, UseForageCommonFood, true, "If enabled, use the common foods specified in the code.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Mercs)
|
||||
@@ -303,6 +304,9 @@ RULE_BOOL(World, EnforceCharacterLimitAtLogin, false, "Enforce the limit for cha
|
||||
RULE_BOOL(World, EnableDevTools, true, "Enable or Disable the Developer Tools globally (Most of the time you want this enabled)")
|
||||
RULE_BOOL(World, EnableChecksumVerification, false, "Enable or Disable the Checksum Verification for eqgame.exe and spells_us.txt")
|
||||
RULE_INT(World, MaximumQuestErrors, 30, "Changes the maximum number of quest errors that can be displayed in #questerrors, default is 30")
|
||||
RULE_INT(World, BootHour, 0, "Sets the in-game hour world will set when it first boots. 0-24 are valid options, where 0 disables this rule")
|
||||
RULE_BOOL(World, UseItemLinksForKeyRing, false, "Uses item links for Key Ring Listing instead of item name")
|
||||
RULE_BOOL(World, UseOldShadowKnightClassExport, true, "Disable to have Shadowknight show as Shadow Knight (live-like)")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Zone)
|
||||
@@ -456,6 +460,8 @@ RULE_INT(Spells, WizardCritMinimumRandomRatio, 20, "The minimum value for the ra
|
||||
RULE_INT(Spells, WizardCritMaximumRandomRatio, 70, "The maximum value for the random range which Wizards and Caster DPS Mercs innately have for spell crit ratio. Set to 70 for vanilla values.")
|
||||
RULE_INT(Spells, DefensiveProcPenaltyLevelGap, 6, "Defensive Proc Penalty Level Gap where procs start losing their proc rate at RuleR(Spells, DefensiveProcPenaltyModifier)% per level difference")
|
||||
RULE_REAL(Spells, DefensiveProcPenaltyLevelGapModifier, 10.0f, "Defensive Proc Penalty Level Gap Modifier where procs start losing their proc rate at defined % after RuleI(Spells, DefensiveProcLevelGap) level difference")
|
||||
RULE_BOOL(Spells, DOTBonusDamageSplitOverDuration, true, "Disable to have Damage Over Time total bonus damage added to each tick instead of divided across duration")
|
||||
RULE_BOOL(Spells, HOTBonusHealingSplitOverDuration, true, "Disable to have Heal Over Time total bonus healing added to each tick instead of divided across duration")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Combat)
|
||||
@@ -648,6 +654,12 @@ RULE_BOOL(Bots, ResurrectionSickness, true, "Use Resurrection Sickness based on
|
||||
RULE_INT(Bots, OldResurrectionSicknessSpell, 757, "757 is Default Old Resurrection Sickness Spell")
|
||||
RULE_INT(Bots, ResurrectionSicknessSpell, 756, "756 is Default Resurrection Sickness Spell")
|
||||
RULE_BOOL(Bots, AllowPickpocketCommand, true, "Allows the use of the bot command 'pickpocket'")
|
||||
RULE_BOOL(Bots, BotHealOnLevel, false, "Setting whether a bot should heal completely when leveling. Default FALSE.")
|
||||
RULE_INT(Bots, AutosaveIntervalSeconds, 300, "Number of seconds after which a timer is triggered which stores the bot data. The value 0 means no periodic automatic saving.")
|
||||
RULE_BOOL(Bots, CazicTouchBotsOwner, true, "Default True. Cazic Touch/DT will hit bot owner rather than bot.")
|
||||
RULE_INT(Bots, BotsClickItemsMinLvl, 1, "Minimum level for bots to be able to use ^clickitem. Default 1.")
|
||||
RULE_BOOL(Bots, BotsCanClickItems, true, "Enabled the ability for bots to click items they have equipped. Default TRUE")
|
||||
RULE_BOOL(Bots, CanClickMageEpicV1, true, "Whether or not bots are allowed to click Mage Epic 1.0. Default TRUE")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Chat)
|
||||
|
||||
+1
-1
@@ -376,7 +376,7 @@ std::string EQ::SayLinkEngine::InjectSaylinksIfNotExist(const char *message)
|
||||
|
||||
void EQ::SayLinkEngine::LoadCachedSaylinks()
|
||||
{
|
||||
auto saylinks = SaylinkRepository::GetWhere(database, "phrase not REGEXP BINARY '[A-Z]' and phrase not REGEXP '[0-9]'");
|
||||
auto saylinks = SaylinkRepository::GetWhere(database, "phrase not REGEXP '[A-Z]' and phrase not REGEXP '[0-9]'");
|
||||
LogSaylink("Loaded [{}] saylinks into cache", saylinks.size());
|
||||
g_cached_saylinks = saylinks;
|
||||
}
|
||||
|
||||
+6
-6
@@ -461,12 +461,12 @@ struct SPackSendQueue {
|
||||
uchar buffer[0];
|
||||
};
|
||||
|
||||
struct ServerZoneStateChange_struct {
|
||||
uint32 ZoneServerID;
|
||||
char adminname[64];
|
||||
uint32 zoneid;
|
||||
uint16 instanceid;
|
||||
bool makestatic;
|
||||
struct ServerZoneStateChange_Struct {
|
||||
uint32 zone_server_id;
|
||||
uint32 zone_id;
|
||||
uint16 instance_id;
|
||||
bool is_static;
|
||||
char admin_name[64];
|
||||
};
|
||||
|
||||
struct ServerZoneIncomingClient_Struct {
|
||||
|
||||
+69
-32
@@ -41,6 +41,7 @@
|
||||
#include "repositories/criteria/content_filter_criteria.h"
|
||||
#include "repositories/account_repository.h"
|
||||
#include "repositories/faction_association_repository.h"
|
||||
#include "repositories/starting_items_repository.h"
|
||||
#include "path_manager.h"
|
||||
#include "repositories/loottable_repository.h"
|
||||
|
||||
@@ -446,45 +447,81 @@ bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, EQ::InventoryProfile* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) {
|
||||
bool SharedDatabase::SetStartingItems(
|
||||
PlayerProfile_Struct *pp,
|
||||
EQ::InventoryProfile *inv,
|
||||
uint32 si_race,
|
||||
uint32 si_class,
|
||||
uint32 si_deity,
|
||||
uint32 si_current_zone,
|
||||
char *si_name,
|
||||
int admin_level
|
||||
)
|
||||
{
|
||||
const EQ::ItemData *item_data;
|
||||
|
||||
const EQ::ItemData *myitem;
|
||||
const auto &l = StartingItemsRepository::All(*this);
|
||||
|
||||
const std::string query = StringFormat(
|
||||
"SELECT itemid, item_charges, slot FROM starting_items "
|
||||
"WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND "
|
||||
"(deityid = %i or deityid = 0) AND (zoneid = %i or zoneid = 0) AND "
|
||||
"gm <= %i %s ORDER BY id",
|
||||
si_race,
|
||||
si_class,
|
||||
si_deity,
|
||||
si_current_zone,
|
||||
admin_level,
|
||||
ContentFilterCriteria::apply().c_str()
|
||||
);
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
if (l.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<StartingItemsRepository::StartingItems> v;
|
||||
|
||||
for (auto& row = results.begin(); row != results.end(); ++row) {
|
||||
const int32 itemid = Strings::ToInt(row[0]);
|
||||
const int32 charges = Strings::ToInt(row[1]);
|
||||
int32 slot = Strings::ToInt(row[2]);
|
||||
myitem = GetItem(itemid);
|
||||
for (const auto &e : l) {
|
||||
const auto &classes = Strings::Split(e.class_list, "|");
|
||||
const auto &deities = Strings::Split(e.deity_list, "|");
|
||||
const auto &races = Strings::Split(e.race_list, "|");
|
||||
const auto &zones = Strings::Split(e.zone_id_list, "|");
|
||||
|
||||
if(!myitem)
|
||||
const std::string &all = std::to_string(0);
|
||||
|
||||
if (classes[0] != all) {
|
||||
if (!Strings::Contains(classes, std::to_string(si_class))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (deities[0] != all) {
|
||||
if (!Strings::Contains(deities, std::to_string(si_deity))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (races[0] != all) {
|
||||
if (!Strings::Contains(races, std::to_string(si_race))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (zones[0] != all) {
|
||||
if (!Strings::Contains(zones, std::to_string(si_current_zone))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
v.emplace_back(e);
|
||||
}
|
||||
|
||||
for (const auto &e : v) {
|
||||
const uint32 item_id = e.item_id;
|
||||
const uint8 item_charges = e.item_charges;
|
||||
int32 slot = e.inventory_slot;
|
||||
|
||||
item_data = GetItem(item_id);
|
||||
|
||||
if (!item_data) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const EQ::ItemInstance* myinst = CreateBaseItem(myitem, charges);
|
||||
const auto *inst = CreateBaseItem(item_data, item_charges);
|
||||
|
||||
if(slot < 0)
|
||||
slot = inv->FindFreeSlot(0, 0);
|
||||
if (slot < EQ::invslot::slotCharm) {
|
||||
slot = inv->FindFreeSlot(false, false);
|
||||
}
|
||||
|
||||
inv->PutItem(slot, *myinst);
|
||||
safe_delete(myinst);
|
||||
inv->PutItem(slot, *inst);
|
||||
safe_delete(inst);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1771,7 +1808,7 @@ bool SharedDatabase::LoadSkillCaps(const std::string &prefix) {
|
||||
}
|
||||
|
||||
void SharedDatabase::LoadSkillCaps(void *data) {
|
||||
const uint32 class_count = PLAYER_CLASS_COUNT;
|
||||
const uint32 class_count = Class::PLAYER_CLASS_COUNT;
|
||||
const uint32 skill_count = EQ::skills::HIGHEST_SKILL + 1;
|
||||
const uint32 level_count = HARD_LEVEL_CAP + 1;
|
||||
uint16 *skill_caps_table = static_cast<uint16*>(data);
|
||||
@@ -1811,7 +1848,7 @@ uint16 SharedDatabase::GetSkillCap(uint8 Class_, EQ::skills::SkillType Skill, ui
|
||||
SkillMaxLevel = RuleI(Character, MaxLevel);
|
||||
}
|
||||
|
||||
const uint32 class_count = PLAYER_CLASS_COUNT;
|
||||
const uint32 class_count = Class::PLAYER_CLASS_COUNT;
|
||||
const uint32 skill_count = EQ::skills::HIGHEST_SKILL + 1;
|
||||
const uint32 level_count = HARD_LEVEL_CAP + 1;
|
||||
if(Class_ > class_count || static_cast<uint32>(Skill) > skill_count || Level > level_count) {
|
||||
@@ -1841,7 +1878,7 @@ uint8 SharedDatabase::GetTrainLevel(uint8 Class_, EQ::skills::SkillType Skill, u
|
||||
SkillMaxLevel = RuleI(Character, MaxLevel);
|
||||
}
|
||||
|
||||
const uint32 class_count = PLAYER_CLASS_COUNT;
|
||||
const uint32 class_count = Class::PLAYER_CLASS_COUNT;
|
||||
const uint32 skill_count = EQ::skills::HIGHEST_SKILL + 1;
|
||||
const uint32 level_count = HARD_LEVEL_CAP + 1;
|
||||
if(Class_ > class_count || static_cast<uint32>(Skill) > skill_count || Level > level_count) {
|
||||
@@ -2024,7 +2061,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) {
|
||||
sp[tempid].environment_type=Strings::ToInt(row[102]);
|
||||
sp[tempid].time_of_day=Strings::ToInt(row[103]);
|
||||
|
||||
for(y=0; y < PLAYER_CLASS_COUNT;y++)
|
||||
for(y=0; y < Class::PLAYER_CLASS_COUNT;y++)
|
||||
sp[tempid].classes[y]=Strings::ToInt(row[104+y]);
|
||||
|
||||
sp[tempid].casting_animation=Strings::ToInt(row[120]);
|
||||
|
||||
+3
-3
@@ -666,7 +666,7 @@ bool IsBardSong(uint16 spell_id)
|
||||
const auto& spell = spells[spell_id];
|
||||
|
||||
if (
|
||||
spell.classes[BARD - 1] < UINT8_MAX &&
|
||||
spell.classes[Class::Bard - 1] < UINT8_MAX &&
|
||||
!spell.is_discipline
|
||||
) {
|
||||
return true;
|
||||
@@ -780,7 +780,7 @@ uint8 GetSpellMinimumLevel(uint16 spell_id)
|
||||
|
||||
const auto& spell = spells[spell_id];
|
||||
|
||||
for (int i = 0; i < PLAYER_CLASS_COUNT; i++) {
|
||||
for (int i = 0; i < Class::PLAYER_CLASS_COUNT; i++) {
|
||||
if (spell.classes[i] < minimum_level) {
|
||||
minimum_level = spell.classes[i];
|
||||
}
|
||||
@@ -798,7 +798,7 @@ uint8 GetSpellLevel(uint16 spell_id, uint8 class_id)
|
||||
return UINT8_MAX;
|
||||
}
|
||||
|
||||
if (class_id >= PLAYER_CLASS_COUNT) {
|
||||
if (class_id >= Class::PLAYER_CLASS_COUNT) {
|
||||
return UINT8_MAX;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1369,7 +1369,7 @@ struct SPDat_Spell_Struct
|
||||
/* 101 */ int8 zone_type; // 01=Outdoors, 02=dungeons, ff=Any -- ZONETYPE
|
||||
/* 102 */ int8 environment_type; // -- ENVIRONMENTTYPE
|
||||
/* 103 */ int8 time_of_day; // -- TIMEOFDAY
|
||||
/* 104 */ uint8 classes[PLAYER_CLASS_COUNT]; // Classes, and their min levels -- WARRIORMIN ... BERSERKERMIN
|
||||
/* 104 */ uint8 classes[Class::PLAYER_CLASS_COUNT]; // Classes, and their min levels -- WARRIORMIN ... BERSERKERMIN
|
||||
/* 120 */ uint8 casting_animation; // -- CASTINGANIM
|
||||
/* 121 */ //uint8 TargetAnim; // -- TARGETANIM
|
||||
/* 122 */ //uint32 TravelType; // -- TRAVELTYPE
|
||||
|
||||
+3
-3
@@ -25,7 +25,7 @@
|
||||
|
||||
// Build variables
|
||||
// these get injected during the build pipeline
|
||||
#define CURRENT_VERSION "22.33.0-dev" // always append -dev to the current version for custom-builds
|
||||
#define CURRENT_VERSION "22.38.0-dev" // always append -dev to the current version for custom-builds
|
||||
#define LOGIN_VERSION "0.8.0"
|
||||
#define COMPILE_DATE __DATE__
|
||||
#define COMPILE_TIME __TIME__
|
||||
@@ -42,9 +42,9 @@
|
||||
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9241
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9248
|
||||
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9040
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9041
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+10
-28
@@ -121,43 +121,25 @@ bool Database::GetLoginTokenDataFromToken(
|
||||
std::string &user
|
||||
)
|
||||
{
|
||||
auto query = fmt::format(
|
||||
"SELECT tbllogintokens.Id, tbllogintokens.IpAddress, tbllogintokenclaims.Name, tbllogintokenclaims.Value FROM tbllogintokens "
|
||||
"JOIN tbllogintokenclaims ON tbllogintokens.Id = tbllogintokenclaims.TokenId WHERE tbllogintokens.Expires > NOW() "
|
||||
"AND tbllogintokens.Id='{0}' AND tbllogintokens.IpAddress='{1}'",
|
||||
auto query = fmt::format("SELECT login_server, username, account_id FROM login_tickets WHERE expires > NOW()"
|
||||
" AND id='{0}' AND ip_address='{1}' LIMIT 1",
|
||||
Strings::Escape(token),
|
||||
Strings::Escape(ip)
|
||||
);
|
||||
Strings::Escape(ip));
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
if (results.RowCount() == 0 || !results.Success()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool found_username = false;
|
||||
bool found_login_id = false;
|
||||
bool found_login_server_name = false;
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
if (strcmp(row[2], "username") == 0) {
|
||||
user = row[3];
|
||||
found_username = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(row[2], "login_server_id") == 0) {
|
||||
db_account_id = Strings::ToUnsignedInt(row[3]);
|
||||
found_login_id = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(row[2], "login_server_name") == 0) {
|
||||
db_loginserver = row[3];
|
||||
found_login_server_name = true;
|
||||
continue;
|
||||
}
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
db_loginserver = row[0];
|
||||
user = row[1];
|
||||
db_account_id = Strings::ToUnsignedInt(row[2]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return found_username && found_login_id && found_login_server_name;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
DROP TABLE IF EXISTS `login_tickets`;
|
||||
CREATE TABLE `login_tickets` (
|
||||
`id` VARCHAR(128) NOT NULL,
|
||||
`login_server` TEXT NOT NULL,
|
||||
`username` TEXT NOT NULL,
|
||||
`account_id` INT(10) UNSIGNED NOT NULL,
|
||||
`ip_address` VARCHAR(45) NOT NULL,
|
||||
`expires` DATETIME NOT NULL,
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
)
|
||||
ENGINE=InnoDB;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eqemu-server",
|
||||
"version": "22.33.0",
|
||||
"version": "22.38.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/EQEmu/Server.git"
|
||||
|
||||
@@ -29,7 +29,7 @@ void LoadSkillCaps(SharedDatabase *database, const std::string &prefix) {
|
||||
EQ::IPCMutex mutex("skill_caps");
|
||||
mutex.Lock();
|
||||
|
||||
uint32 class_count = PLAYER_CLASS_COUNT;
|
||||
uint32 class_count = Class::PLAYER_CLASS_COUNT;
|
||||
uint32 skill_count = EQ::skills::HIGHEST_SKILL + 1;
|
||||
uint32 level_count = HARD_LEVEL_CAP + 1;
|
||||
uint32 size = (class_count * skill_count * level_count * sizeof(uint16));
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
module constantconvert
|
||||
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/gammazero/deque v0.2.0 // indirect
|
||||
github.com/gammazero/workerpool v1.1.3 // indirect
|
||||
)
|
||||
@@ -0,0 +1,4 @@
|
||||
github.com/gammazero/deque v0.2.0 h1:SkieyNB4bg2/uZZLxvya0Pq6diUlwx7m2TeT7GAIWaA=
|
||||
github.com/gammazero/deque v0.2.0/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU=
|
||||
github.com/gammazero/workerpool v1.1.3 h1:WixN4xzukFoN0XSeXF6puqEqFTl2mECI9S6W44HWy9Q=
|
||||
github.com/gammazero/workerpool v1.1.3/go.mod h1:wPjyBLDbyKnUn2XwwyD3EEwo9dHutia9/fwNmSHWACc=
|
||||
@@ -0,0 +1,313 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gammazero/workerpool"
|
||||
"io/fs"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
loadDefinitions()
|
||||
|
||||
// get processor count
|
||||
wp := workerpool.New(runtime.NumCPU())
|
||||
|
||||
// loop through all files in current dir that are cpp files or h files
|
||||
err := filepath.WalkDir("../../", func(path string, d fs.DirEntry, err error) error {
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !strings.Contains(path, ".cpp") && !strings.Contains(path, ".h") {
|
||||
return nil
|
||||
}
|
||||
|
||||
// if file ends with ".o" skip it
|
||||
if strings.HasSuffix(path, ".o") {
|
||||
return nil
|
||||
}
|
||||
|
||||
var ignoreFiles = []string{
|
||||
"submodules", "/libs", "utils/", "races.h", "backward", "database_update_manifest.cpp", "zonedb.h",
|
||||
}
|
||||
|
||||
ignore := false
|
||||
for _, ignoreString := range ignoreFiles {
|
||||
if strings.Contains(path, ignoreString) {
|
||||
ignore = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if ignore {
|
||||
return nil
|
||||
}
|
||||
|
||||
wp.Submit(func() {
|
||||
|
||||
// open file for reading
|
||||
// get file contents
|
||||
contents, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
log.Fatalf("impossible to read file: %s", err)
|
||||
}
|
||||
|
||||
content := string(contents)
|
||||
|
||||
wroteChanges := false
|
||||
|
||||
var newLines []string
|
||||
for _, line := range strings.Split(content, "\n") {
|
||||
newLine := line
|
||||
|
||||
// loop through oldDefs and see if any of them are in contents
|
||||
for key, value := range oldDefs {
|
||||
// combine all of the above contains into a slice
|
||||
// loop through slice and if any of them are in line, continue
|
||||
var ignoreMatches = []string{
|
||||
"#define ", "MALE", "FEMALE", "_BIT", "LANG_",
|
||||
}
|
||||
|
||||
ignore := false
|
||||
for _, ignoreString := range ignoreMatches {
|
||||
if strings.Contains(newLine, ignoreString) && !strings.Contains(newLine, "NPC_") {
|
||||
ignore = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if ignore {
|
||||
continue
|
||||
}
|
||||
|
||||
// below we hackishly use a series of specific string contains to avoid
|
||||
// making blind and wrong replacements
|
||||
// but hey - at least its 100% accurate :)
|
||||
if strings.Contains(line, "case "+key+":") {
|
||||
for key2, value2 := range newDefs {
|
||||
if value == value2 {
|
||||
newLine = strings.ReplaceAll(newLine, " "+key+":", " "+key2+":")
|
||||
wroteChanges = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if strings.Contains(line, "\t"+key) {
|
||||
for key2, value2 := range newDefs {
|
||||
if value == value2 {
|
||||
newLine = strings.ReplaceAll(newLine, "\t"+key, "\t"+key2)
|
||||
wroteChanges = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if strings.Contains(line, key+",") {
|
||||
for key2, value2 := range newDefs {
|
||||
if value == value2 {
|
||||
newLine = strings.ReplaceAll(newLine, key+",", key2+",")
|
||||
wroteChanges = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if strings.Contains(line, ", "+key) {
|
||||
for key2, value2 := range newDefs {
|
||||
if value == value2 {
|
||||
newLine = strings.ReplaceAll(newLine, ", "+key, ", "+key2)
|
||||
wroteChanges = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if strings.Contains(line, "= "+key+" ") {
|
||||
for key2, value2 := range newDefs {
|
||||
if value == value2 {
|
||||
newLine = strings.ReplaceAll(newLine, "= "+key+" ", "= "+key2+" ")
|
||||
wroteChanges = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if strings.Contains(line, "= "+key+")") {
|
||||
for key2, value2 := range newDefs {
|
||||
if value == value2 {
|
||||
newLine = strings.ReplaceAll(newLine, "= "+key+")", "= "+key2+")")
|
||||
wroteChanges = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if strings.Contains(line, "= "+key+";") {
|
||||
for key2, value2 := range newDefs {
|
||||
if value == value2 {
|
||||
newLine = strings.ReplaceAll(newLine, "= "+key+";", "= "+key2+";")
|
||||
wroteChanges = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if strings.Contains(line, "= "+key+" ||") {
|
||||
for key2, value2 := range newDefs {
|
||||
if value == value2 {
|
||||
newLine = strings.ReplaceAll(newLine, "= "+key+" ||", "= "+key2+" ||")
|
||||
wroteChanges = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// match cases where our match is on the last line and last column
|
||||
// we need to be exact in the last column and not do a partial because we can
|
||||
// accidentally rename say OGRE to OGRE2 mistakenly
|
||||
if strings.Contains(line, key) {
|
||||
columns := strings.Split(line, " ")
|
||||
// get the last column
|
||||
lastColumn := strings.TrimSpace(columns[len(columns)-1])
|
||||
if lastColumn == key {
|
||||
for key2, value2 := range newDefs {
|
||||
if value == value2 {
|
||||
newLine = strings.ReplaceAll(newLine, lastColumn, key2)
|
||||
wroteChanges = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if strings.Contains(line, "race == "+key) {
|
||||
// for key2, value2 := range newDefs {
|
||||
// if value == value2 {
|
||||
// newLine = strings.ReplaceAll(newLine, "race == "+key, "race == "+key2)
|
||||
// wroteChanges = true
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
newLines = append(newLines, newLine)
|
||||
}
|
||||
|
||||
// write contents back to file
|
||||
if wroteChanges {
|
||||
fmt.Printf("wrote changes to file [%v]\n", path)
|
||||
err = os.WriteFile(path, []byte(strings.Join(newLines, "\n")), 0644)
|
||||
if err != nil {
|
||||
log.Fatalf("impossible to write file: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
})
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("impossible to walk directories: %s", err)
|
||||
}
|
||||
|
||||
wp.StopWait()
|
||||
}
|
||||
|
||||
var newDefs = make(map[string]int)
|
||||
var oldDefs = make(map[string]int)
|
||||
|
||||
func loadDefinitions() {
|
||||
// git show master:common/races.h
|
||||
cmd := exec.Command("git", "show", "master:common/races.h")
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
println(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// load into a string -> int map
|
||||
for _, line := range strings.Split(string(out), "\n") {
|
||||
if strings.Contains(line, "#define ") {
|
||||
if len(strings.Split(line, " ")) <= 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
// ignore
|
||||
// #define MALE 0
|
||||
// #define FEMALE 1
|
||||
// #define NEUTER 2
|
||||
if strings.Contains(line, "#define MALE") {
|
||||
continue
|
||||
}
|
||||
if strings.Contains(line, "#define FEMALE") {
|
||||
continue
|
||||
}
|
||||
if strings.Contains(line, "#define NEUTER") {
|
||||
continue
|
||||
}
|
||||
|
||||
// load "#define RACE_FLYING_CARPET_720 720" into map
|
||||
|
||||
key := strings.Split(line, " ")[1]
|
||||
value := strings.Split(line, " ")[2]
|
||||
value = strings.ReplaceAll(value, "//", "")
|
||||
value = strings.TrimSpace(value)
|
||||
//fmt.Printf("key [%v] value [%v]\n", key, value)
|
||||
|
||||
if !strings.HasPrefix(key, "RACE_") && !strings.HasPrefix(key, "RT_") {
|
||||
continue
|
||||
}
|
||||
|
||||
// convert value to int
|
||||
intValue, err := strconv.Atoi(value)
|
||||
if err != nil {
|
||||
println(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
oldDefs[key] = intValue
|
||||
|
||||
fmt.Printf("oldDefs key [%v] value [%v]\n", key, intValue)
|
||||
}
|
||||
}
|
||||
|
||||
// cleanup/races_cpp_h
|
||||
cmd = exec.Command("git", "show", "cleanup/races_cpp_h:common/races.h")
|
||||
out, err = cmd.Output()
|
||||
if err != nil {
|
||||
println(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// load into a string -> int map
|
||||
for _, line := range strings.Split(string(out), "\n") {
|
||||
if strings.Contains(line, "constexpr uint16") {
|
||||
if len(strings.Split(line, " ")) <= 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
// remove all extra spaces in between characters in line
|
||||
line = strings.Join(strings.Fields(line), " ")
|
||||
|
||||
// load " constexpr uint16 Doug = 0;" into map
|
||||
key := strings.Split(line, " ")[2]
|
||||
value := strings.Split(line, " ")[4]
|
||||
value = strings.ReplaceAll(value, "//", "")
|
||||
value = strings.ReplaceAll(value, ";", "")
|
||||
value = strings.TrimSpace(value)
|
||||
|
||||
// convert value to int
|
||||
intValue, err := strconv.Atoi(value)
|
||||
if err != nil {
|
||||
println(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
mapKey := "Race::" + key
|
||||
|
||||
newDefs[mapKey] = intValue
|
||||
|
||||
fmt.Printf("newDefs key [%v] value [%v]\n", mapKey, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,8 @@ mkdir -p build && cd build && \
|
||||
-DEQEMU_BUILD_LOGIN=ON \
|
||||
-DEQEMU_BUILD_LUA=ON \
|
||||
-DEQEMU_BUILD_PERL=ON \
|
||||
-DCMAKE_CXX_FLAGS:STRING="-O1 -g" \
|
||||
-DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING="-O1 -g" \
|
||||
-DCMAKE_CXX_FLAGS:STRING="-O1 -g -Wno-everything" \
|
||||
-DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING="-O1 -g -Wno-everything" \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-G 'Unix Makefiles' \
|
||||
.. && make -j$((`nproc`-4))
|
||||
|
||||
@@ -10,7 +10,7 @@ require (
|
||||
require (
|
||||
github.com/golang/protobuf v1.3.2 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/crypto v0.17.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
)
|
||||
|
||||
@@ -10,8 +10,8 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
|
||||
@@ -2,8 +2,13 @@
|
||||
|
||||
########################################################################
|
||||
#::: 13th floor import script
|
||||
#::: Current Source: http://items.sodeq.org/download.php
|
||||
#::: Authors: (Natedog, Akkadius)
|
||||
#::: Items Source: http://items.sodeq.org/download.php
|
||||
#::: How To:
|
||||
#::: 1. Place this script with your server eqemu_config.json
|
||||
#::: 2. Download the items.txt file and place with this script
|
||||
#::: 3. Run this script with Perl
|
||||
#::: 4. Review new and updated items in the items_new table
|
||||
#::: 5. Make any desired changes and replace the items table contents
|
||||
########################################################################
|
||||
|
||||
use DBI;
|
||||
@@ -16,6 +21,7 @@ my $db_user = "";
|
||||
my $db_pass = "";
|
||||
my $total_items = 0;
|
||||
my $read_items_file = "items.txt"; #default
|
||||
my $keep_temp_items_table = 0; #keeps the imported items table
|
||||
|
||||
read_eqemu_config_json();
|
||||
|
||||
@@ -24,7 +30,7 @@ my $dbh = DBI->connect("DBI:mysql:database=$db_name;host=$db_host;port=$db_port"
|
||||
read_items_file_from_13th_floor_text();
|
||||
update_items_table();
|
||||
|
||||
print "\n\nImport complete!\n\n";
|
||||
print "\n\nImport complete! Review items_new table before replacing into items table.\n\n";
|
||||
|
||||
sub read_eqemu_config_json {
|
||||
use JSON;
|
||||
@@ -139,7 +145,12 @@ sub read_items_file_from_13th_floor_text {
|
||||
|
||||
sub update_items_table {
|
||||
|
||||
print "Updating items table...\n";
|
||||
#::: Establish items_new table
|
||||
print "Setting up new items table...\n";
|
||||
$dbh->do("DROP TABLE IF EXISTS items_new");
|
||||
$dbh->do("CREATE TABLE items_new AS SELECT * FROM items");
|
||||
|
||||
print "Updating new items table...\n";
|
||||
|
||||
my @matching_table;
|
||||
my @missing_items_table;
|
||||
@@ -147,7 +158,7 @@ sub update_items_table {
|
||||
|
||||
print "Comparing table structure...\n";
|
||||
#::: Get columns from `items`
|
||||
my $sth = $dbh->prepare("SHOW COLUMNS FROM `items`;");
|
||||
my $sth = $dbh->prepare("SHOW COLUMNS FROM `items_new`;");
|
||||
$sth->execute();
|
||||
my @items_table;
|
||||
while (my @row = $sth->fetchrow_array()) {
|
||||
@@ -230,7 +241,7 @@ sub update_items_table {
|
||||
}
|
||||
|
||||
my $update_query = "
|
||||
INSERT INTO items (" . $items_field_list . ")
|
||||
INSERT INTO items_new (" . $items_field_list . ")
|
||||
SELECT " . $items_floor_field_list . "
|
||||
FROM items_floor fi
|
||||
ON DUPLICATE KEY UPDATE " . $update_fields;
|
||||
@@ -257,14 +268,20 @@ sub update_items_table {
|
||||
|
||||
#::: Update stackables
|
||||
print "Updating stackable field...\n";
|
||||
$dbh->do("UPDATE items i SET i.stackable = 1 WHERE i.stacksize > 1");
|
||||
$dbh->do("UPDATE items_new i SET i.stackable = 1 WHERE i.stacksize > 1");
|
||||
|
||||
#::: Update legacy research tome bagtypes
|
||||
print "Updating legacy research tomes...\n";
|
||||
$dbh->do("UPDATE items i SET i.bagtype = 24 WHERE i.id IN (17655, 17903)"); #RESEARCHWIZ
|
||||
$dbh->do("UPDATE items i SET i.bagtype = 25 WHERE i.id IN (17502, 17653)"); #RESEARCHMAG
|
||||
$dbh->do("UPDATE items i SET i.bagtype = 26 WHERE i.id IN (17501, 17654)"); #RESEARCHNEC
|
||||
$dbh->do("UPDATE items i SET i.bagtype = 27 WHERE i.id IN (17500, 17652)"); #RESEARCHENC
|
||||
$dbh->do("UPDATE items_new i SET i.bagtype = 24 WHERE i.id IN (17655, 17903)"); #RESEARCHWIZ
|
||||
$dbh->do("UPDATE items_new i SET i.bagtype = 25 WHERE i.id IN (17502, 17653)"); #RESEARCHMAG
|
||||
$dbh->do("UPDATE items_new i SET i.bagtype = 26 WHERE i.id IN (17501, 17654)"); #RESEARCHNEC
|
||||
$dbh->do("UPDATE items_new i SET i.bagtype = 27 WHERE i.id IN (17500, 17652)"); #RESEARCHENC
|
||||
|
||||
#::: Remove temp table
|
||||
if (!$keep_temp_items_table) {
|
||||
print "Cleaning up temp items table...\n";
|
||||
$dbh->do("DROP TABLE items_floor");
|
||||
}
|
||||
}
|
||||
|
||||
sub trim($) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -78,6 +78,10 @@ ADD_EXECUTABLE(world ${world_sources} ${world_headers})
|
||||
|
||||
INSTALL(TARGETS world RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
|
||||
IF (WIN32 AND EQEMU_BUILD_PCH)
|
||||
TARGET_PRECOMPILE_HEADERS(world PRIVATE ../common/pch/pch.h)
|
||||
ENDIF ()
|
||||
|
||||
ADD_DEFINITIONS(-DWORLD)
|
||||
|
||||
TARGET_LINK_LIBRARIES(world ${SERVER_LIBS})
|
||||
|
||||
+5
-5
@@ -1966,7 +1966,7 @@ bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc)
|
||||
{ /*Drakkin*/ 70, 80, 85, 75, 80, 85, 75}
|
||||
};
|
||||
|
||||
static const int BaseClass[PLAYER_CLASS_COUNT][8] =
|
||||
static const int BaseClass[Class::PLAYER_CLASS_COUNT][8] =
|
||||
{ /* STR STA AGI DEX WIS INT CHR ADD*/
|
||||
{ /*Warrior*/ 10, 10, 5, 0, 0, 0, 0, 25},
|
||||
{ /*Cleric*/ 5, 5, 0, 0, 10, 0, 0, 30},
|
||||
@@ -1986,7 +1986,7 @@ bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc)
|
||||
{ /*Berserker*/ 10, 5, 0, 10, 0, 0, 0, 25}
|
||||
};
|
||||
|
||||
static const bool ClassRaceLookupTable[PLAYER_CLASS_COUNT][_TABLE_RACES]=
|
||||
static const bool ClassRaceLookupTable[Class::PLAYER_CLASS_COUNT][_TABLE_RACES]=
|
||||
{ /*Human Barbarian Erudite Woodelf Highelf Darkelf Halfelf Dwarf Troll Ogre Halfling Gnome Iksar Vahshir Froglok Drakkin*/
|
||||
{ /*Warrior*/ true, true, false, true, false, true, true, true, true, true, true, true, true, true, true, true},
|
||||
{ /*Cleric*/ true, false, true, false, true, true, true, true, false, false, true, true, false, false, true, true},
|
||||
@@ -2021,7 +2021,7 @@ bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc)
|
||||
|
||||
// if out of range looking it up in the table would crash stuff
|
||||
// so we return from these
|
||||
if (classtemp >= PLAYER_CLASS_COUNT) {
|
||||
if (classtemp >= Class::PLAYER_CLASS_COUNT) {
|
||||
LogInfo(" class is out of range");
|
||||
return false;
|
||||
}
|
||||
@@ -2114,7 +2114,7 @@ void Client::SetClassStartingSkills(PlayerProfile_Struct *pp)
|
||||
}
|
||||
}
|
||||
|
||||
if (cle->GetClientVersion() < static_cast<uint8>(EQ::versions::ClientVersion::RoF2) && pp->class_ == BERSERKER) {
|
||||
if (cle->GetClientVersion() < static_cast<uint8>(EQ::versions::ClientVersion::RoF2) && pp->class_ == Class::Berserker) {
|
||||
pp->skills[EQ::skills::Skill1HPiercing] = pp->skills[EQ::skills::Skill2HPiercing];
|
||||
pp->skills[EQ::skills::Skill2HPiercing] = 0;
|
||||
}
|
||||
@@ -2299,7 +2299,7 @@ void Client::SetClassLanguages(PlayerProfile_Struct *pp)
|
||||
{
|
||||
// we only need to handle one class, but custom server might want to do more
|
||||
switch(pp->class_) {
|
||||
case ROGUE:
|
||||
case Class::Rogue:
|
||||
pp->languages[LANG_THIEVES_CANT] = 100;
|
||||
break;
|
||||
default:
|
||||
|
||||
+10
-10
@@ -578,25 +578,25 @@ void ConsoleZoneShutdown(
|
||||
strcpy(&tmpname[1], connection->UserName().c_str());
|
||||
|
||||
auto pack = new ServerPacket;
|
||||
pack->size = sizeof(ServerZoneStateChange_struct);
|
||||
pack->size = sizeof(ServerZoneStateChange_Struct);
|
||||
pack->pBuffer = new uchar[pack->size];
|
||||
memset(pack->pBuffer, 0, sizeof(ServerZoneStateChange_struct));
|
||||
ServerZoneStateChange_struct *s = (ServerZoneStateChange_struct *) pack->pBuffer;
|
||||
memset(pack->pBuffer, 0, sizeof(ServerZoneStateChange_Struct));
|
||||
auto *s = (ServerZoneStateChange_Struct *) pack->pBuffer;
|
||||
pack->opcode = ServerOP_ZoneShutdown;
|
||||
strcpy(s->adminname, tmpname);
|
||||
strcpy(s->admin_name, tmpname);
|
||||
if (Strings::IsNumber(args[0])) {
|
||||
s->ZoneServerID = Strings::ToInt(args[0]);
|
||||
s->zone_server_id = Strings::ToInt(args[0]);
|
||||
}
|
||||
else {
|
||||
s->zoneid = ZoneID(args[0].c_str());
|
||||
s->zone_id = ZoneID(args[0].c_str());
|
||||
}
|
||||
|
||||
ZoneServer *zs = 0;
|
||||
if (s->ZoneServerID != 0) {
|
||||
zs = zoneserver_list.FindByID(s->ZoneServerID);
|
||||
if (s->zone_server_id != 0) {
|
||||
zs = zoneserver_list.FindByID(s->zone_server_id);
|
||||
}
|
||||
else if (s->zoneid != 0) {
|
||||
zs = zoneserver_list.FindByName(ZoneName(s->zoneid));
|
||||
else if (s->zone_id != 0) {
|
||||
zs = zoneserver_list.FindByName(ZoneName(s->zone_id));
|
||||
}
|
||||
else {
|
||||
connection->SendLine("Error: ZoneShutdown: neither ID nor name specified");
|
||||
|
||||
+2
-2
@@ -33,7 +33,7 @@ GroupLFP::GroupLFP(uint32 inLeaderID) {
|
||||
LeaderID = inLeaderID;
|
||||
for (auto &member : Members) {
|
||||
member.Name[0] = '\0';
|
||||
member.Class = NO_CLASS;
|
||||
member.Class = Class::None;
|
||||
member.Level = 0;
|
||||
member.Zone = 0;
|
||||
}
|
||||
@@ -77,7 +77,7 @@ void GroupLFP::SetDetails(ServerLFPUpdate_Struct *Update) {
|
||||
Members[i].GuildID = CLE->GuildID();
|
||||
}
|
||||
else {
|
||||
Members[i].Class = NO_CLASS;
|
||||
Members[i].Class = Class::None;
|
||||
Members[i].Level = 0;
|
||||
Members[i].Zone = 0;
|
||||
Members[i].GuildID = 0xFFFF;
|
||||
|
||||
+14
-6
@@ -424,12 +424,20 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (EQTimeTimer.Check()) {
|
||||
TimeOfDay_Struct tod;
|
||||
zoneserver_list.worldclock.GetCurrentEQTimeOfDay(time(0), &tod);
|
||||
if (!database.SaveTime(tod.minute, tod.hour, tod.day, tod.month, tod.year))
|
||||
LogError("Failed to save eqtime");
|
||||
else
|
||||
LogDebug("EQTime successfully saved");
|
||||
TimeOfDay_Struct tod{};
|
||||
zoneserver_list.worldclock.GetCurrentEQTimeOfDay(time(nullptr), &tod);
|
||||
if (!database.SaveTime(tod.minute, tod.hour, tod.day, tod.month, tod.year)) {
|
||||
LogEqTime("Failed to save eqtime");
|
||||
}
|
||||
else {
|
||||
LogEqTimeDetail("EQTime successfully saved - time is now year [{}] month [{}] day [{}] hour [{}] minute [{}]",
|
||||
tod.year,
|
||||
tod.month,
|
||||
tod.day,
|
||||
tod.hour - 1,
|
||||
tod.minute
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
zoneserver_list.Process();
|
||||
|
||||
+21
-18
@@ -720,15 +720,15 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
break;
|
||||
}
|
||||
case ServerOP_ZoneShutdown: {
|
||||
auto s = (ServerZoneStateChange_struct*) pack->pBuffer;
|
||||
auto *s = (ServerZoneStateChange_Struct*) pack->pBuffer;
|
||||
ZoneServer* zs = 0;
|
||||
if (s->ZoneServerID) {
|
||||
zs = zoneserver_list.FindByID(s->ZoneServerID);
|
||||
} else if (s->zoneid) {
|
||||
zs = zoneserver_list.FindByName(ZoneName(s->zoneid));
|
||||
if (s->zone_server_id) {
|
||||
zs = zoneserver_list.FindByID(s->zone_server_id);
|
||||
} else if (s->zone_id) {
|
||||
zs = zoneserver_list.FindByName(ZoneName(s->zone_id));
|
||||
} else {
|
||||
zoneserver_list.SendEmoteMessage(
|
||||
s->adminname,
|
||||
s->admin_name,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
@@ -738,7 +738,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
|
||||
if (!zs) {
|
||||
zoneserver_list.SendEmoteMessage(
|
||||
s->adminname,
|
||||
s->admin_name,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
@@ -751,8 +751,8 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
break;
|
||||
}
|
||||
case ServerOP_ZoneBootup: {
|
||||
auto s = (ServerZoneStateChange_struct*) pack->pBuffer;
|
||||
zoneserver_list.SOPZoneBootup(s->adminname, s->ZoneServerID, ZoneName(s->zoneid), s->makestatic);
|
||||
auto *s = (ServerZoneStateChange_Struct*) pack->pBuffer;
|
||||
zoneserver_list.SOPZoneBootup(s->admin_name, s->zone_server_id, ZoneName(s->zone_id), s->is_static);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ZoneStatus: {
|
||||
@@ -1606,20 +1606,23 @@ void ZoneServer::ChangeWID(uint32 iCharID, uint32 iWID) {
|
||||
|
||||
|
||||
void ZoneServer::TriggerBootup(uint32 in_zone_id, uint32 in_instance_id, const char* admin_name, bool is_static_zone) {
|
||||
is_booting_up = true;
|
||||
is_booting_up = true;
|
||||
zone_server_zone_id = in_zone_id;
|
||||
instance_id = in_instance_id;
|
||||
instance_id = in_instance_id;
|
||||
|
||||
auto pack = new ServerPacket(ServerOP_ZoneBootup, sizeof(ServerZoneStateChange_Struct));
|
||||
auto *s = (ServerZoneStateChange_Struct*) pack->pBuffer;
|
||||
|
||||
s->zone_server_id = zone_server_id;
|
||||
|
||||
s->zone_id = in_zone_id ? in_zone_id : GetZoneID();
|
||||
s->instance_id = in_instance_id;
|
||||
s->is_static = is_static_zone;
|
||||
|
||||
auto pack = new ServerPacket(ServerOP_ZoneBootup, sizeof(ServerZoneStateChange_struct));
|
||||
auto s = (ServerZoneStateChange_struct*) pack->pBuffer;
|
||||
s->ZoneServerID = zone_server_id;
|
||||
if (admin_name) {
|
||||
strn0cpy(s->adminname, admin_name, sizeof(s->adminname));
|
||||
strn0cpy(s->admin_name, admin_name, sizeof(s->admin_name));
|
||||
}
|
||||
|
||||
s->zoneid = in_zone_id ? in_zone_id : GetZoneID();
|
||||
s->instanceid = in_instance_id;
|
||||
s->makestatic = is_static_zone;
|
||||
SendPacket(pack);
|
||||
delete pack;
|
||||
LSBootUpdate(in_zone_id, in_instance_id);
|
||||
|
||||
@@ -284,6 +284,12 @@ ADD_EXECUTABLE(zone ${zone_sources} ${zone_headers})
|
||||
|
||||
INSTALL(TARGETS zone RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
|
||||
IF (WIN32 AND EQEMU_BUILD_PCH)
|
||||
TARGET_PRECOMPILE_HEADERS(zone PRIVATE ../common/pch/pch.h)
|
||||
TARGET_PRECOMPILE_HEADERS(zone PRIVATE ../common/types.h ../common/eqemu_logsys.h ../common/eqemu_logsys_log_aliases.h ../common/features.h ../common/global_define.h)
|
||||
TARGET_PRECOMPILE_HEADERS(zone PRIVATE mob.h npc.h corpse.h doors.h bot.h entity.h client.h zone.h)
|
||||
ENDIF()
|
||||
|
||||
ADD_DEFINITIONS(-DZONE)
|
||||
|
||||
TARGET_LINK_LIBRARIES(zone ${ZONE_LIBS})
|
||||
|
||||
+111
-17
@@ -373,72 +373,72 @@ void Mob::WakeTheDead(uint16 spell_id, Corpse *corpse_to_use, Mob *tar, uint32 d
|
||||
//some basic combat mods here too since it's convienent
|
||||
switch (corpse_to_use->class_)
|
||||
{
|
||||
case CLERIC:
|
||||
case Class::Cleric:
|
||||
made_npc->npc_spells_id = 1;
|
||||
break;
|
||||
case WIZARD:
|
||||
case Class::Wizard:
|
||||
made_npc->npc_spells_id = 2;
|
||||
break;
|
||||
case NECROMANCER:
|
||||
case Class::Necromancer:
|
||||
made_npc->npc_spells_id = 3;
|
||||
break;
|
||||
case MAGICIAN:
|
||||
case Class::Magician:
|
||||
made_npc->npc_spells_id = 4;
|
||||
break;
|
||||
case ENCHANTER:
|
||||
case Class::Enchanter:
|
||||
made_npc->npc_spells_id = 5;
|
||||
break;
|
||||
case SHAMAN:
|
||||
case Class::Shaman:
|
||||
made_npc->npc_spells_id = 6;
|
||||
break;
|
||||
case DRUID:
|
||||
case Class::Druid:
|
||||
made_npc->npc_spells_id = 7;
|
||||
break;
|
||||
case PALADIN:
|
||||
case Class::Paladin:
|
||||
//SPECATK_TRIPLE
|
||||
strcpy(made_npc->special_abilities, "6,1");
|
||||
made_npc->current_hp = made_npc->current_hp * 150 / 100;
|
||||
made_npc->max_hp = made_npc->max_hp * 150 / 100;
|
||||
made_npc->npc_spells_id = 8;
|
||||
break;
|
||||
case SHADOWKNIGHT:
|
||||
case Class::ShadowKnight:
|
||||
strcpy(made_npc->special_abilities, "6,1");
|
||||
made_npc->current_hp = made_npc->current_hp * 150 / 100;
|
||||
made_npc->max_hp = made_npc->max_hp * 150 / 100;
|
||||
made_npc->npc_spells_id = 9;
|
||||
break;
|
||||
case RANGER:
|
||||
case Class::Ranger:
|
||||
strcpy(made_npc->special_abilities, "7,1");
|
||||
made_npc->current_hp = made_npc->current_hp * 135 / 100;
|
||||
made_npc->max_hp = made_npc->max_hp * 135 / 100;
|
||||
made_npc->npc_spells_id = 10;
|
||||
break;
|
||||
case BARD:
|
||||
case Class::Bard:
|
||||
strcpy(made_npc->special_abilities, "6,1");
|
||||
made_npc->current_hp = made_npc->current_hp * 110 / 100;
|
||||
made_npc->max_hp = made_npc->max_hp * 110 / 100;
|
||||
made_npc->npc_spells_id = 11;
|
||||
break;
|
||||
case BEASTLORD:
|
||||
case Class::Beastlord:
|
||||
strcpy(made_npc->special_abilities, "7,1");
|
||||
made_npc->current_hp = made_npc->current_hp * 110 / 100;
|
||||
made_npc->max_hp = made_npc->max_hp * 110 / 100;
|
||||
made_npc->npc_spells_id = 12;
|
||||
break;
|
||||
case ROGUE:
|
||||
case Class::Rogue:
|
||||
strcpy(made_npc->special_abilities, "7,1");
|
||||
made_npc->max_dmg = made_npc->max_dmg * 150 / 100;
|
||||
made_npc->current_hp = made_npc->current_hp * 110 / 100;
|
||||
made_npc->max_hp = made_npc->max_hp * 110 / 100;
|
||||
break;
|
||||
case MONK:
|
||||
case Class::Monk:
|
||||
strcpy(made_npc->special_abilities, "7,1");
|
||||
made_npc->max_dmg = made_npc->max_dmg * 150 / 100;
|
||||
made_npc->current_hp = made_npc->current_hp * 135 / 100;
|
||||
made_npc->max_hp = made_npc->max_hp * 135 / 100;
|
||||
break;
|
||||
case WARRIOR:
|
||||
case BERSERKER:
|
||||
case Class::Warrior:
|
||||
case Class::Berserker:
|
||||
strcpy(made_npc->special_abilities, "7,1");
|
||||
made_npc->max_dmg = made_npc->max_dmg * 150 / 100;
|
||||
made_npc->current_hp = made_npc->current_hp * 175 / 100;
|
||||
@@ -1354,7 +1354,7 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) {
|
||||
}
|
||||
else {
|
||||
// Bards can cast instant cast AAs while they are casting or channeling item cast.
|
||||
if (GetClass() == BARD && IsCasting() && spells[rank->spell].cast_time == 0) {
|
||||
if (GetClass() == Class::Bard && IsCasting() && spells[rank->spell].cast_time == 0) {
|
||||
if (!DoCastingChecksOnCaster(rank->spell, EQ::spells::CastingSlot::AltAbility)) {
|
||||
return;
|
||||
}
|
||||
@@ -2207,3 +2207,97 @@ bool Client::HasAlreadyPurchasedRank(AA::Rank* rank) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Client::ListPurchasedAAs(Client *to, std::string search_criteria)
|
||||
{
|
||||
if (!to) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<std::string, uint8> client_aa_ranks;
|
||||
|
||||
for (auto &aa : zone->aa_abilities) {
|
||||
AA::Ability *ability = aa.second.get();
|
||||
|
||||
AA::Rank *rank = ability->first;
|
||||
while (rank) {
|
||||
if (!CanUseAlternateAdvancementRank(rank)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (HasAlreadyPurchasedRank(rank)) {
|
||||
const std::string aa_name = zone->GetAAName(rank->id);
|
||||
if (
|
||||
search_criteria.empty() ||
|
||||
Strings::Contains(
|
||||
Strings::ToLower(aa_name),
|
||||
Strings::ToLower(search_criteria)
|
||||
)
|
||||
) {
|
||||
if (client_aa_ranks.find(aa_name) == client_aa_ranks.end()) {
|
||||
client_aa_ranks[aa_name] = 1;
|
||||
} else {
|
||||
client_aa_ranks[aa_name]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rank = rank->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (client_aa_ranks.empty()) {
|
||||
to->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} {} no purchased AAs{}.",
|
||||
to->GetTargetDescription(this, TargetDescriptionType::UCYou),
|
||||
this == to ? "have" : "has",
|
||||
(
|
||||
!search_criteria.empty() ?
|
||||
fmt::format(
|
||||
" matching '{}'",
|
||||
search_criteria
|
||||
) :
|
||||
""
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
int aa_number = 1;
|
||||
|
||||
for (const auto &aa : client_aa_ranks) {
|
||||
to->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{}. {} (Rank {})",
|
||||
aa_number,
|
||||
aa.first,
|
||||
aa.second
|
||||
).c_str()
|
||||
);
|
||||
|
||||
aa_number++;
|
||||
}
|
||||
|
||||
to->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} {} {} purchased AA{}{}.",
|
||||
to->GetTargetDescription(this, TargetDescriptionType::UCYou),
|
||||
this == to ? "have" : "has",
|
||||
client_aa_ranks.size(),
|
||||
client_aa_ranks.size() > 1 ? "s" : "",
|
||||
(
|
||||
!search_criteria.empty() ?
|
||||
fmt::format(
|
||||
" matching '{}'",
|
||||
search_criteria
|
||||
) :
|
||||
""
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
+9
-9
@@ -46,7 +46,7 @@ void EntityList::DescribeAggro(Client *to_who, NPC *from_who, float d, bool verb
|
||||
);
|
||||
|
||||
bool is_engaged = from_who->IsEngaged();
|
||||
bool will_aggro_npcs = from_who->WillAggroNPCs();
|
||||
bool will_aggro_npcs = from_who->GetNPCAggro();
|
||||
if (is_engaged) {
|
||||
Mob *top = from_who->GetHateTop();
|
||||
to_who->Message(
|
||||
@@ -678,7 +678,7 @@ bool Mob::IsAttackAllowed(Mob *target, bool isSpellAttack)
|
||||
|
||||
if(!isSpellAttack)
|
||||
{
|
||||
if(GetClass() == LDON_TREASURE)
|
||||
if(GetClass() == Class::LDoNTreasure)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -983,14 +983,14 @@ bool Mob::CombatRange(Mob* other, float fixed_size_mod, bool aeRampage, ExtraAtt
|
||||
float size_mod = GetSize();
|
||||
float other_size_mod = other->GetSize();
|
||||
|
||||
if (GetRace() == RACE_LAVA_DRAGON_49 || GetRace() == RACE_WURM_158 || GetRace() == RACE_GHOST_DRAGON_196) { //For races with a fixed size
|
||||
if (GetRace() == Race::LavaDragon || GetRace() == Race::Wurm || GetRace() == Race::GhostDragon) { //For races with a fixed size
|
||||
size_mod = 60.0f;
|
||||
}
|
||||
else if (size_mod < 6.0) {
|
||||
size_mod = 8.0f;
|
||||
}
|
||||
|
||||
if (other->GetRace() == RACE_LAVA_DRAGON_49 || other->GetRace() == RACE_WURM_158 || other->GetRace() == RACE_GHOST_DRAGON_196) { //For races with a fixed size
|
||||
if (other->GetRace() == Race::LavaDragon || other->GetRace() == Race::Wurm || other->GetRace() == Race::GhostDragon) { //For races with a fixed size
|
||||
other_size_mod = 60.0f;
|
||||
}
|
||||
else if (other_size_mod < 6.0) {
|
||||
@@ -1011,11 +1011,11 @@ bool Mob::CombatRange(Mob* other, float fixed_size_mod, bool aeRampage, ExtraAtt
|
||||
size_mod *= size_mod * 4;
|
||||
}
|
||||
|
||||
if (other->GetRace() == RACE_VELIOUS_DRAGON_184) // Lord Vyemm and other velious dragons
|
||||
if (other->GetRace() == Race::VeliousDragon) // Lord Vyemm and other velious dragons
|
||||
{
|
||||
size_mod *= 1.75;
|
||||
}
|
||||
if (other->GetRace() == RACE_DRAGON_SKELETON_122) // Dracoliche in Fear. Skeletal Dragon
|
||||
if (other->GetRace() == Race::DragonSkeleton) // Dracoliche in Fear. Skeletal Dragon
|
||||
{
|
||||
size_mod *= 2.25;
|
||||
}
|
||||
@@ -1070,10 +1070,10 @@ bool Mob::CombatRange(Mob* other, float fixed_size_mod, bool aeRampage, ExtraAtt
|
||||
SetPseudoRoot(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (aeRampage) {
|
||||
float aeramp_size = RuleR(Combat, AERampageMaxDistance);
|
||||
|
||||
|
||||
LogCombatDetail("AERampage: Default - aeramp_size = [{}] ", aeramp_size);
|
||||
|
||||
if (opts) {
|
||||
@@ -1093,7 +1093,7 @@ bool Mob::CombatRange(Mob* other, float fixed_size_mod, bool aeRampage, ExtraAtt
|
||||
|
||||
LogCombatDetail("AE Rampage: ramp_range = [{}] -- (size_mod [{}] * aeramp_size [{}])", ramp_range, size_mod, aeramp_size);
|
||||
LogCombatDetail("AE Rampage: _DistNoRoot [{}] <= ramp_range [{}]", _DistNoRoot, ramp_range);
|
||||
|
||||
|
||||
if (_DistNoRoot <= ramp_range) {
|
||||
LogCombatDetail("AE Rampage: Combat Distance returned [true]");
|
||||
return true;
|
||||
|
||||
@@ -245,7 +245,7 @@ Json::Value ApiGetNpcListDetail(EQ::Net::WebsocketServerConnection *connection,
|
||||
row["swarm_owner"] = npc->GetSwarmOwner();
|
||||
row["swarm_target"] = npc->GetSwarmTarget();
|
||||
row["waypoint_max"] = npc->GetWaypointMax();
|
||||
row["will_aggro_npcs"] = npc->WillAggroNPCs();
|
||||
row["npc_aggro"] = npc->GetNPCAggro();
|
||||
|
||||
response.append(row);
|
||||
}
|
||||
|
||||
+165
-165
@@ -558,7 +558,7 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit)
|
||||
}
|
||||
|
||||
// dodge
|
||||
if (CanThisClassDodge() && (InFront || GetClass() == MONK)) {
|
||||
if (CanThisClassDodge() && (InFront || GetClass() == Class::Monk)) {
|
||||
if (IsClient())
|
||||
CastToClient()->CheckIncreaseSkill(EQ::skills::SkillDodge, other, -10);
|
||||
// check auto discs ... I guess aa/items too :P
|
||||
@@ -674,28 +674,28 @@ int Mob::GetACSoftcap()
|
||||
int level = std::min(105, static_cast<int>(GetLevel())) - 1;
|
||||
|
||||
switch (GetClass()) {
|
||||
case WARRIOR:
|
||||
case Class::Warrior:
|
||||
return war_softcaps[level];
|
||||
case CLERIC:
|
||||
case BARD:
|
||||
case MONK:
|
||||
case Class::Cleric:
|
||||
case Class::Bard:
|
||||
case Class::Monk:
|
||||
return clrbrdmnk_softcaps[level];
|
||||
case PALADIN:
|
||||
case SHADOWKNIGHT:
|
||||
case Class::Paladin:
|
||||
case Class::ShadowKnight:
|
||||
return palshd_softcaps[level];
|
||||
case RANGER:
|
||||
case Class::Ranger:
|
||||
return rng_softcaps[level];
|
||||
case DRUID:
|
||||
case Class::Druid:
|
||||
return dru_softcaps[level];
|
||||
case ROGUE:
|
||||
case SHAMAN:
|
||||
case BEASTLORD:
|
||||
case BERSERKER:
|
||||
case Class::Rogue:
|
||||
case Class::Shaman:
|
||||
case Class::Beastlord:
|
||||
case Class::Berserker:
|
||||
return rogshmbstber_softcaps[level];
|
||||
case NECROMANCER:
|
||||
case WIZARD:
|
||||
case MAGICIAN:
|
||||
case ENCHANTER:
|
||||
case Class::Necromancer:
|
||||
case Class::Wizard:
|
||||
case Class::Magician:
|
||||
case Class::Enchanter:
|
||||
return necwizmagenc_softcaps[level];
|
||||
default:
|
||||
return 350;
|
||||
@@ -707,28 +707,28 @@ double Mob::GetSoftcapReturns()
|
||||
// These are based on the dev post, they seem to be correct for every level
|
||||
// AKA no more hard caps
|
||||
switch (GetClass()) {
|
||||
case WARRIOR:
|
||||
case Class::Warrior:
|
||||
return 0.35;
|
||||
case CLERIC:
|
||||
case BARD:
|
||||
case MONK:
|
||||
case Class::Cleric:
|
||||
case Class::Bard:
|
||||
case Class::Monk:
|
||||
return 0.3;
|
||||
case PALADIN:
|
||||
case SHADOWKNIGHT:
|
||||
case Class::Paladin:
|
||||
case Class::ShadowKnight:
|
||||
return 0.33;
|
||||
case RANGER:
|
||||
case Class::Ranger:
|
||||
return 0.315;
|
||||
case DRUID:
|
||||
case Class::Druid:
|
||||
return 0.265;
|
||||
case ROGUE:
|
||||
case SHAMAN:
|
||||
case BEASTLORD:
|
||||
case BERSERKER:
|
||||
case Class::Rogue:
|
||||
case Class::Shaman:
|
||||
case Class::Beastlord:
|
||||
case Class::Berserker:
|
||||
return 0.28;
|
||||
case NECROMANCER:
|
||||
case WIZARD:
|
||||
case MAGICIAN:
|
||||
case ENCHANTER:
|
||||
case Class::Necromancer:
|
||||
case Class::Wizard:
|
||||
case Class::Magician:
|
||||
case Class::Enchanter:
|
||||
return 0.25;
|
||||
default:
|
||||
return 0.3;
|
||||
@@ -739,7 +739,7 @@ int Mob::GetClassRaceACBonus()
|
||||
{
|
||||
int ac_bonus = 0;
|
||||
auto level = GetLevel();
|
||||
if (GetClass() == MONK) {
|
||||
if (GetClass() == Class::Monk) {
|
||||
int hardcap = 30;
|
||||
int softcap = 14;
|
||||
if (level > 99) {
|
||||
@@ -824,7 +824,7 @@ int Mob::GetClassRaceACBonus()
|
||||
}
|
||||
}
|
||||
|
||||
if (GetClass() == ROGUE) {
|
||||
if (GetClass() == Class::Rogue) {
|
||||
int level_scaler = level - 26;
|
||||
if (GetAGI() < 80)
|
||||
ac_bonus = level_scaler / 4;
|
||||
@@ -840,7 +840,7 @@ int Mob::GetClassRaceACBonus()
|
||||
ac_bonus = 12;
|
||||
}
|
||||
|
||||
if (GetClass() == BEASTLORD) {
|
||||
if (GetClass() == Class::Beastlord) {
|
||||
int level_scaler = level - 6;
|
||||
if (GetAGI() < 80)
|
||||
ac_bonus = level_scaler / 5;
|
||||
@@ -894,14 +894,14 @@ int Mob::ACSum(bool skip_caps)
|
||||
ac += GetPetACBonusFromOwner();
|
||||
auto spell_aa_ac = aabonuses.AC + spellbonuses.AC;
|
||||
ac += GetSkill(EQ::skills::SkillDefense) / 5;
|
||||
if (EQ::ValueWithin(static_cast<int>(GetClass()), NECROMANCER, ENCHANTER))
|
||||
if (EQ::ValueWithin(static_cast<int>(GetClass()), Class::Necromancer, Class::Enchanter))
|
||||
ac += spell_aa_ac / 3;
|
||||
else
|
||||
ac += spell_aa_ac / 4;
|
||||
}
|
||||
else { // TODO: so we can't set NPC skills ... so the skill bonus ends up being HUGE so lets nerf them a bit
|
||||
auto spell_aa_ac = aabonuses.AC + spellbonuses.AC;
|
||||
if (EQ::ValueWithin(static_cast<int>(GetClass()), NECROMANCER, ENCHANTER))
|
||||
if (EQ::ValueWithin(static_cast<int>(GetClass()), Class::Necromancer, Class::Enchanter))
|
||||
ac += GetSkill(EQ::skills::SkillDefense) / 2 + spell_aa_ac / 3;
|
||||
else
|
||||
ac += GetSkill(EQ::skills::SkillDefense) / 3 + spell_aa_ac / 4;
|
||||
@@ -1085,7 +1085,7 @@ int64 Mob::GetWeaponDamage(Mob *against, const EQ::ItemData *weapon_item) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if ((GetClass() == MONK || GetClass() == BEASTLORD) && GetLevel() >= 30) {
|
||||
else if ((GetClass() == Class::Monk || GetClass() == Class::Beastlord) && GetLevel() >= 30) {
|
||||
dmg = GetHandToHandDamage();
|
||||
}
|
||||
else {
|
||||
@@ -1199,7 +1199,7 @@ int64 Mob::GetWeaponDamage(Mob *against, const EQ::ItemInstance *weapon_item, in
|
||||
MagicGloves = gloves->GetItemMagical(true);
|
||||
}
|
||||
|
||||
if (GetClass() == MONK || GetClass() == BEASTLORD) {
|
||||
if (GetClass() == Class::Monk || GetClass() == Class::Beastlord) {
|
||||
if (MagicGloves || GetLevel() >= 30) {
|
||||
dmg = GetHandToHandDamage();
|
||||
if (hate)
|
||||
@@ -1295,15 +1295,15 @@ int64 Mob::DoDamageCaps(int64 base_damage)
|
||||
}
|
||||
else if (level >= 40) {
|
||||
switch (GetClass()) {
|
||||
case CLERIC:
|
||||
case DRUID:
|
||||
case SHAMAN:
|
||||
case Class::Cleric:
|
||||
case Class::Druid:
|
||||
case Class::Shaman:
|
||||
cap = 80;
|
||||
break;
|
||||
case NECROMANCER:
|
||||
case WIZARD:
|
||||
case MAGICIAN:
|
||||
case ENCHANTER:
|
||||
case Class::Necromancer:
|
||||
case Class::Wizard:
|
||||
case Class::Magician:
|
||||
case Class::Enchanter:
|
||||
cap = 40;
|
||||
break;
|
||||
default:
|
||||
@@ -1313,15 +1313,15 @@ int64 Mob::DoDamageCaps(int64 base_damage)
|
||||
}
|
||||
else if (level >= 30) {
|
||||
switch (GetClass()) {
|
||||
case CLERIC:
|
||||
case DRUID:
|
||||
case SHAMAN:
|
||||
case Class::Cleric:
|
||||
case Class::Druid:
|
||||
case Class::Shaman:
|
||||
cap = 26;
|
||||
break;
|
||||
case NECROMANCER:
|
||||
case WIZARD:
|
||||
case MAGICIAN:
|
||||
case ENCHANTER:
|
||||
case Class::Necromancer:
|
||||
case Class::Wizard:
|
||||
case Class::Magician:
|
||||
case Class::Enchanter:
|
||||
cap = 18;
|
||||
break;
|
||||
default:
|
||||
@@ -1331,15 +1331,15 @@ int64 Mob::DoDamageCaps(int64 base_damage)
|
||||
}
|
||||
else if (level >= 20) {
|
||||
switch (GetClass()) {
|
||||
case CLERIC:
|
||||
case DRUID:
|
||||
case SHAMAN:
|
||||
case Class::Cleric:
|
||||
case Class::Druid:
|
||||
case Class::Shaman:
|
||||
cap = 20;
|
||||
break;
|
||||
case NECROMANCER:
|
||||
case WIZARD:
|
||||
case MAGICIAN:
|
||||
case ENCHANTER:
|
||||
case Class::Necromancer:
|
||||
case Class::Wizard:
|
||||
case Class::Magician:
|
||||
case Class::Enchanter:
|
||||
cap = 12;
|
||||
break;
|
||||
default:
|
||||
@@ -1349,15 +1349,15 @@ int64 Mob::DoDamageCaps(int64 base_damage)
|
||||
}
|
||||
else if (level >= 10) {
|
||||
switch (GetClass()) {
|
||||
case CLERIC:
|
||||
case DRUID:
|
||||
case SHAMAN:
|
||||
case Class::Cleric:
|
||||
case Class::Druid:
|
||||
case Class::Shaman:
|
||||
cap = 12;
|
||||
break;
|
||||
case NECROMANCER:
|
||||
case WIZARD:
|
||||
case MAGICIAN:
|
||||
case ENCHANTER:
|
||||
case Class::Necromancer:
|
||||
case Class::Wizard:
|
||||
case Class::Magician:
|
||||
case Class::Enchanter:
|
||||
cap = 10;
|
||||
break;
|
||||
default:
|
||||
@@ -1367,15 +1367,15 @@ int64 Mob::DoDamageCaps(int64 base_damage)
|
||||
}
|
||||
else {
|
||||
switch (GetClass()) {
|
||||
case CLERIC:
|
||||
case DRUID:
|
||||
case SHAMAN:
|
||||
case Class::Cleric:
|
||||
case Class::Druid:
|
||||
case Class::Shaman:
|
||||
cap = 9;
|
||||
break;
|
||||
case NECROMANCER:
|
||||
case WIZARD:
|
||||
case MAGICIAN:
|
||||
case ENCHANTER:
|
||||
case Class::Necromancer:
|
||||
case Class::Wizard:
|
||||
case Class::Magician:
|
||||
case Class::Enchanter:
|
||||
cap = 6;
|
||||
break;
|
||||
default:
|
||||
@@ -1476,7 +1476,7 @@ bool Mob::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
|
||||
LogCombatDetail("Attacking [{}] with hand [{}] [{}]", other->GetName(), Hand, bRiposte ? "this is a riposte" : "");
|
||||
|
||||
if (
|
||||
(IsCasting() && GetClass() != BARD && !IsFromSpell)
|
||||
(IsCasting() && GetClass() != Class::Bard && !IsFromSpell)
|
||||
|| ((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead))
|
||||
|| (GetHP() < 0)
|
||||
|| (!IsAttackAllowed(other))
|
||||
@@ -1820,7 +1820,7 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill
|
||||
|
||||
auto emote_id = killerMob->GetEmoteID();
|
||||
if (emote_id) {
|
||||
killerMob->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledPC, emoteid);
|
||||
killerMob->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledPC, emoteid, this);
|
||||
}
|
||||
|
||||
killerMob->TrySpellOnKill(killed_level, spell);
|
||||
@@ -2019,7 +2019,7 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill
|
||||
/*
|
||||
Reset reuse timer for classic skill based Lay on Hands (For tit I guess)
|
||||
*/
|
||||
if (GetClass() == PALADIN) { // we could check if it's not expired I guess, but should be fine not to
|
||||
if (GetClass() == Class::Paladin) { // we could check if it's not expired I guess, but should be fine not to
|
||||
p_timers.Clear(&database, pTimerLayHands);
|
||||
}
|
||||
|
||||
@@ -2343,7 +2343,7 @@ void NPC::Damage(Mob* other, int64 damage, uint16 spell_id, EQ::skills::SkillTyp
|
||||
if (!IsEngaged())
|
||||
zone->AddAggroMob();
|
||||
|
||||
if (GetClass() == LDON_TREASURE)
|
||||
if (GetClass() == Class::LDoNTreasure)
|
||||
{
|
||||
if (IsLDoNLocked() && GetLDoNLockedSkill() != LDoNTypeMechanical)
|
||||
{
|
||||
@@ -2461,7 +2461,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
||||
BuffFadeAll();
|
||||
const auto killed_level = GetLevel();
|
||||
|
||||
if (GetClass() == LDON_TREASURE) { // open chest
|
||||
if (GetClass() == Class::LDoNTreasure) { // open chest
|
||||
auto outapp = new EQApplicationPacket(OP_Animation, sizeof(Animation_Struct));
|
||||
Animation_Struct* anim = (Animation_Struct*)outapp->pBuffer;
|
||||
anim->spawnid = GetID();
|
||||
@@ -2488,7 +2488,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
||||
respawn2->DeathReset(1);
|
||||
}
|
||||
|
||||
if (killer_mob && GetClass() != LDON_TREASURE) {
|
||||
if (killer_mob && GetClass() != Class::LDoNTreasure) {
|
||||
hate_list.AddEntToHateList(killer_mob, damage);
|
||||
}
|
||||
|
||||
@@ -2535,7 +2535,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
||||
hate_list.DoFactionHits(GetNPCFactionID(), GetPrimaryFaction(), GetFactionAmount());
|
||||
}
|
||||
|
||||
bool IsLdonTreasure = (GetClass() == LDON_TREASURE);
|
||||
bool IsLdonTreasure = (GetClass() == Class::LDoNTreasure);
|
||||
|
||||
if (give_exp_client && !IsCorpse()) {
|
||||
Group *kg = entity_list.GetGroupByClient(give_exp_client);
|
||||
@@ -2701,10 +2701,73 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
||||
}
|
||||
|
||||
bool allow_merchant_corpse = RuleB(Merchant, AllowCorpse);
|
||||
bool is_merchant = (class_ == MERCHANT || class_ == ADVENTURE_MERCHANT || MerchantType != 0);
|
||||
bool is_merchant = (class_ == Class::Merchant || class_ == Class::AdventureMerchant || MerchantType != 0);
|
||||
|
||||
Corpse* corpse = nullptr;
|
||||
|
||||
// Parse quests even if we're killed by an NPC
|
||||
if (oos) {
|
||||
if (IsNPC()) {
|
||||
auto emote_id = GetEmoteID();
|
||||
if (emote_id) {
|
||||
DoNPCEmote(EQ::constants::EmoteEventTypes::OnDeath, emoteid, killer_mob);
|
||||
}
|
||||
}
|
||||
|
||||
if (oos->IsNPC()) {
|
||||
if (parse->HasQuestSub(oos->GetNPCTypeID(), EVENT_NPC_SLAY)) {
|
||||
parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0);
|
||||
}
|
||||
|
||||
auto emote_id = oos->GetEmoteID();
|
||||
if (emote_id) {
|
||||
oos->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledNPC, emote_id, this);
|
||||
}
|
||||
if (killer_mob) {
|
||||
killer_mob->TrySpellOnKill(killed_level, spell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (killer_mob && killer_mob->IsBot()) {
|
||||
if (parse->BotHasQuestSub(EVENT_NPC_SLAY)) {
|
||||
parse->EventBot(EVENT_NPC_SLAY, killer_mob->CastToBot(), this, "", 0);
|
||||
}
|
||||
|
||||
killer_mob->TrySpellOnKill(killed_level, spell);
|
||||
}
|
||||
|
||||
m_combat_record.Stop();
|
||||
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DEATH_COMPLETE)) {
|
||||
const auto& export_string = fmt::format(
|
||||
"{} {} {} {}",
|
||||
killer_mob ? killer_mob->GetID() : 0,
|
||||
damage,
|
||||
spell,
|
||||
static_cast<int>(attack_skill)
|
||||
);
|
||||
|
||||
std::vector<std::any> args = { corpse };
|
||||
|
||||
parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, export_string, 0, &args);
|
||||
}
|
||||
|
||||
/* Zone controller process EVENT_DEATH_ZONE (Death events) */
|
||||
|
||||
if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DEATH_ZONE)) {
|
||||
const auto& export_string = fmt::format(
|
||||
"{} {} {} {}",
|
||||
killer_mob ? killer_mob->GetID() : 0,
|
||||
damage,
|
||||
spell,
|
||||
static_cast<int>(attack_skill)
|
||||
);
|
||||
|
||||
std::vector<std::any> args = { corpse, this };
|
||||
|
||||
DispatchZoneControllerEvent(EVENT_DEATH_ZONE, oos, export_string, 0, &args);
|
||||
}
|
||||
|
||||
if (!HasOwner() && !IsMerc() && !GetSwarmInfo() && (!is_merchant || allow_merchant_corpse) &&
|
||||
((killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) ||
|
||||
(killer->IsNPC() && killer->CastToNPC()->GetSwarmInfo() && killer->CastToNPC()->GetSwarmInfo()->GetOwner() && killer->CastToNPC()->GetSwarmInfo()->GetOwner()->IsClient())))
|
||||
@@ -2736,7 +2799,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
||||
ApplyIllusionToCorpse(illusion_spell_id, corpse);
|
||||
|
||||
if (killer != 0 && emoteid != 0)
|
||||
corpse->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::AfterDeath, emoteid);
|
||||
corpse->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::AfterDeath, emoteid, killer);
|
||||
if (killer != 0 && killer->IsClient()) {
|
||||
corpse->AllowPlayerLoot(killer, 0);
|
||||
if (killer->IsGrouped()) {
|
||||
@@ -2814,38 +2877,6 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
||||
entity_list.RemoveFromXTargets(this);
|
||||
}
|
||||
|
||||
// Parse quests even if we're killed by an NPC
|
||||
if (oos) {
|
||||
if (IsNPC()) {
|
||||
auto emote_id = GetEmoteID();
|
||||
if (emote_id) {
|
||||
DoNPCEmote(EQ::constants::EmoteEventTypes::OnDeath, emoteid);
|
||||
}
|
||||
}
|
||||
|
||||
if (oos->IsNPC()) {
|
||||
if (parse->HasQuestSub(oos->GetNPCTypeID(), EVENT_NPC_SLAY)) {
|
||||
parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0);
|
||||
}
|
||||
|
||||
auto emote_id = oos->GetEmoteID();
|
||||
if (emote_id) {
|
||||
oos->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledNPC, emote_id);
|
||||
}
|
||||
if (killer_mob) {
|
||||
killer_mob->TrySpellOnKill(killed_level, spell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (killer_mob && killer_mob->IsBot()) {
|
||||
if (parse->BotHasQuestSub(EVENT_NPC_SLAY)) {
|
||||
parse->EventBot(EVENT_NPC_SLAY, killer_mob->CastToBot(), this, "", 0);
|
||||
}
|
||||
|
||||
killer_mob->TrySpellOnKill(killed_level, spell);
|
||||
}
|
||||
|
||||
WipeHateList();
|
||||
p_depop = true;
|
||||
|
||||
@@ -2854,37 +2885,6 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
||||
|
||||
entity_list.UpdateFindableNPCState(this, true);
|
||||
|
||||
m_combat_record.Stop();
|
||||
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DEATH_COMPLETE)) {
|
||||
const auto& export_string = fmt::format(
|
||||
"{} {} {} {}",
|
||||
killer_mob ? killer_mob->GetID() : 0,
|
||||
damage,
|
||||
spell,
|
||||
static_cast<int>(attack_skill)
|
||||
);
|
||||
|
||||
std::vector<std::any> args = { corpse };
|
||||
|
||||
parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, export_string, 0, &args);
|
||||
}
|
||||
|
||||
/* Zone controller process EVENT_DEATH_ZONE (Death events) */
|
||||
|
||||
if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DEATH_ZONE)) {
|
||||
const auto& export_string = fmt::format(
|
||||
"{} {} {} {}",
|
||||
killer_mob ? killer_mob->GetID() : 0,
|
||||
damage,
|
||||
spell,
|
||||
static_cast<int>(attack_skill)
|
||||
);
|
||||
|
||||
std::vector<std::any> args = { corpse, this };
|
||||
|
||||
DispatchZoneControllerEvent(EVENT_DEATH_ZONE, oos, export_string, 0, &args);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3295,14 +3295,14 @@ int Mob::GetHandToHandDamage(void)
|
||||
7, 7, 7, 8, 8, 8, 8, 8, 8, 9, // 21-30
|
||||
9, 9, 9, 9, 9, 10, 10, 10, 10, 10, // 31-40
|
||||
10, 11, 11, 11, 11, 11, 11, 12, 12 }; // 41-49
|
||||
if (GetClass() == MONK) {
|
||||
if (GetClass() == Class::Monk) {
|
||||
if (IsClient() && CastToClient()->GetItemIDAt(12) == 10652 && GetLevel() > 50)
|
||||
return 9;
|
||||
if (level > 62)
|
||||
return 15;
|
||||
return mnk_dmg[level];
|
||||
}
|
||||
else if (GetClass() == BEASTLORD) {
|
||||
else if (GetClass() == Class::Beastlord) {
|
||||
if (level > 49)
|
||||
return 13;
|
||||
return bst_dmg[level];
|
||||
@@ -3354,7 +3354,7 @@ int Mob::GetHandToHandDelay(void)
|
||||
28, 28, 28, 27, 27, 27, 27, 27, 26, 26, // 61-70
|
||||
26, 26, 26 }; // 71-73
|
||||
|
||||
if (GetClass() == MONK) {
|
||||
if (GetClass() == Class::Monk) {
|
||||
// Have a look to see if we have epic fists on
|
||||
if (IsClient() && CastToClient()->GetItemIDAt(12) == 10652 && GetLevel() > 50)
|
||||
return 16;
|
||||
@@ -3363,7 +3363,7 @@ int Mob::GetHandToHandDelay(void)
|
||||
return GetRace() == IKSAR ? 21 : 20;
|
||||
return GetRace() == IKSAR ? mnk_iks_delay[level] : mnk_hum_delay[level];
|
||||
}
|
||||
else if (GetClass() == BEASTLORD) {
|
||||
else if (GetClass() == Class::Beastlord) {
|
||||
int level = GetLevel();
|
||||
if (level > 73)
|
||||
return 25;
|
||||
@@ -4067,7 +4067,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
||||
}
|
||||
}
|
||||
else if (skill_used == EQ::skills::SkillKick &&
|
||||
(attacker->GetLevel() > 55 || attacker->IsNPC()) && GetClass() == WARRIOR) {
|
||||
(attacker->GetLevel() > 55 || attacker->IsNPC()) && GetClass() == Class::Warrior) {
|
||||
can_stun = true;
|
||||
}
|
||||
|
||||
@@ -4087,7 +4087,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
||||
IsPlayerRace(GetBaseRace()) &&
|
||||
RuleI(Combat, FrontalStunImmunityRaces) & GetPlayerRaceBit(GetBaseRace())
|
||||
) ||
|
||||
GetBaseRace() == RACE_OGGOK_CITIZEN_93
|
||||
GetBaseRace() == Race::OggokCitizen
|
||||
) {
|
||||
is_immune_to_frontal_stun = true;
|
||||
}
|
||||
@@ -4107,7 +4107,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
||||
IsPlayerRace(GetBaseRace()) &&
|
||||
RuleI(Combat, FrontalStunImmunityRaces) & GetPlayerRaceBit(GetBaseRace())
|
||||
) ||
|
||||
GetBaseRace() == RACE_OGGOK_CITIZEN_93
|
||||
GetBaseRace() == Race::OggokCitizen
|
||||
)
|
||||
) {
|
||||
is_immune_to_frontal_stun = true;
|
||||
@@ -5053,11 +5053,11 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
|
||||
// We either require an innate crit chance or some SPA 169 to crit
|
||||
bool innate_crit = false;
|
||||
int crit_chance = GetCriticalChanceBonus(hit.skill);
|
||||
if ((GetClass() == WARRIOR || GetClass() == BERSERKER) && GetLevel() >= 12)
|
||||
if ((GetClass() == Class::Warrior || GetClass() == Class::Berserker) && GetLevel() >= 12)
|
||||
innate_crit = true;
|
||||
else if (GetClass() == RANGER && GetLevel() >= 12 && hit.skill == EQ::skills::SkillArchery)
|
||||
else if (GetClass() == Class::Ranger && GetLevel() >= 12 && hit.skill == EQ::skills::SkillArchery)
|
||||
innate_crit = true;
|
||||
else if (GetClass() == ROGUE && GetLevel() >= 12 && hit.skill == EQ::skills::SkillThrowing)
|
||||
else if (GetClass() == Class::Rogue && GetLevel() >= 12 && hit.skill == EQ::skills::SkillThrowing)
|
||||
innate_crit = true;
|
||||
|
||||
// we have a chance to crit!
|
||||
@@ -5077,7 +5077,7 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
|
||||
dex_bonus += 45; // chances did not match live without a small boost
|
||||
|
||||
// so if we have an innate crit we have a better chance, except for ber throwing
|
||||
if (!innate_crit || (GetClass() == BERSERKER && hit.skill == EQ::skills::SkillThrowing))
|
||||
if (!innate_crit || (GetClass() == Class::Berserker && hit.skill == EQ::skills::SkillThrowing))
|
||||
dex_bonus = dex_bonus * 3 / 5;
|
||||
|
||||
if (crit_chance)
|
||||
@@ -5101,7 +5101,7 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
|
||||
LogCombat("Crit success roll [{}] dex chance [{}] og dmg [{}] crit_mod [{}] new dmg [{}]", roll, dex_bonus, og_damage, crit_mod, hit.damage_done);
|
||||
|
||||
// step 3: check deadly strike
|
||||
if (GetClass() == ROGUE && hit.skill == EQ::skills::SkillThrowing) {
|
||||
if (GetClass() == Class::Rogue && hit.skill == EQ::skills::SkillThrowing) {
|
||||
if (BehindMob(defender, GetX(), GetY())) {
|
||||
int chance = GetLevel() * 12;
|
||||
if (zone->random.Int(1, 1000) < chance) {
|
||||
@@ -5284,7 +5284,7 @@ void Mob::DoRiposte(Mob *defender)
|
||||
if (DoubleRipChance && zone->random.Roll(DoubleRipChance)) {
|
||||
LogCombat("Preforming a return SPECIAL ATTACK ([{}] percent chance)", DoubleRipChance);
|
||||
|
||||
if (defender->GetClass() == MONK)
|
||||
if (defender->GetClass() == Class::Monk)
|
||||
defender->MonkSpecialAttack(this, defender->aabonuses.GiveDoubleRiposte[SBIndex::DOUBLE_RIPOSTE_SKILL]);
|
||||
else if (defender->IsClient()) // so yeah, even if you don't have the skill you can still do the attack :P (and we don't crash anymore)
|
||||
defender->CastToClient()->DoClassAttacks(this, defender->aabonuses.GiveDoubleRiposte[SBIndex::DOUBLE_RIPOSTE_SKILL], true);
|
||||
@@ -5301,7 +5301,7 @@ void Mob::ApplyMeleeDamageMods(uint16 skill, int64 &damage, Mob *defender, Extra
|
||||
dmgbonusmod += opts->melee_damage_bonus_flat;
|
||||
|
||||
if (defender) {
|
||||
if (defender->IsOfClientBotMerc() && defender->GetClass() == WARRIOR) {
|
||||
if (defender->IsOfClientBotMerc() && defender->GetClass() == Class::Warrior) {
|
||||
dmgbonusmod -= 5;
|
||||
}
|
||||
// 168 defensive
|
||||
@@ -5445,7 +5445,7 @@ const DamageTable &Mob::GetDamageTable() const
|
||||
{ 415, 15, 40 }, // 105
|
||||
};
|
||||
|
||||
bool monk = GetClass() == MONK;
|
||||
bool monk = GetClass() == Class::Monk;
|
||||
bool melee = IsWarriorClass();
|
||||
// tables caped at 105 for now -- future proofed for a while at least :P
|
||||
int level = std::min(static_cast<int>(GetLevel()), 105);
|
||||
@@ -5893,7 +5893,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
|
||||
|
||||
// BER weren't parsing the halving
|
||||
if (hit.skill == EQ::skills::SkillArchery ||
|
||||
(hit.skill == EQ::skills::SkillThrowing && GetClass() != BERSERKER))
|
||||
(hit.skill == EQ::skills::SkillThrowing && GetClass() != Class::Berserker))
|
||||
hit.damage_done /= 2;
|
||||
|
||||
if (hit.damage_done < 1)
|
||||
@@ -5906,7 +5906,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
|
||||
if (headshot > 0) {
|
||||
hit.damage_done = headshot;
|
||||
}
|
||||
else if (GetClass() == RANGER && GetLevel() > 50) { // no double dmg on headshot
|
||||
else if (GetClass() == Class::Ranger && GetLevel() > 50) { // no double dmg on headshot
|
||||
if ((defender->IsNPC() && !defender->IsMoving() && !defender->IsRooted()) || !RuleB(Combat, ArcheryBonusRequiresStationary)) {
|
||||
hit.damage_done *= 2;
|
||||
MessageString(Chat::MeleeCrit, BOW_DOUBLE_DAMAGE);
|
||||
@@ -5931,7 +5931,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
|
||||
hit.damage_done = ass;
|
||||
}
|
||||
}
|
||||
else if (hit.skill == EQ::skills::SkillFrenzy && GetClass() == BERSERKER && GetLevel() > 50) {
|
||||
else if (hit.skill == EQ::skills::SkillFrenzy && GetClass() == Class::Berserker && GetLevel() > 50) {
|
||||
extra_mincap = 4 * GetLevel() / 5;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -117,7 +117,7 @@ void Client::CalcBonuses()
|
||||
|
||||
// hmm maybe a better way to do this
|
||||
int metabolism = spellbonuses.Metabolism + itembonuses.Metabolism + aabonuses.Metabolism;
|
||||
int timer = GetClass() == MONK ? CONSUMPTION_MNK_TIMER : CONSUMPTION_TIMER;
|
||||
int timer = GetClass() == Class::Monk ? CONSUMPTION_MNK_TIMER : CONSUMPTION_TIMER;
|
||||
timer = timer * (100 + metabolism) / 100;
|
||||
if (timer != consume_food_timer.GetTimerTime())
|
||||
consume_food_timer.SetTimer(timer);
|
||||
@@ -2053,7 +2053,7 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon)
|
||||
}
|
||||
}
|
||||
|
||||
if (GetClass() == BARD)
|
||||
if (GetClass() == Class::Bard)
|
||||
newbon->ManaRegen = 0; // Bards do not get mana regen from spells.
|
||||
}
|
||||
|
||||
|
||||
+841
-186
File diff suppressed because it is too large
Load Diff
+35
-17
@@ -42,13 +42,12 @@ constexpr uint32 BOT_FOLLOW_DISTANCE_DEFAULT_MAX = 2500; // as DSq value (50 uni
|
||||
|
||||
constexpr uint32 BOT_KEEP_ALIVE_INTERVAL = 5000; // 5 seconds
|
||||
|
||||
constexpr uint32 MAG_EPIC_1_0 = 28034;
|
||||
|
||||
extern WorldServer worldserver;
|
||||
|
||||
constexpr int BotAISpellRange = 100; // TODO: Write a method that calcs what the bot's spell range is based on spell, equipment, AA, whatever and replace this
|
||||
constexpr int MaxSpellTimer = 15;
|
||||
constexpr int MaxDisciplineTimer = 10;
|
||||
constexpr int DisciplineReuseStart = MaxSpellTimer + 1;
|
||||
constexpr int MaxTimer = MaxSpellTimer + MaxDisciplineTimer;
|
||||
constexpr int NegativeItemReuse = -1; // Unlinked timer for items
|
||||
|
||||
// nHSND negative Healer/Slower/Nuker/Doter
|
||||
// pH positive Healer
|
||||
@@ -222,6 +221,8 @@ public:
|
||||
void SetPullFlag(bool flag = true) { m_pull_flag = flag; }
|
||||
bool GetPullingFlag() const { return m_pulling_flag; }
|
||||
bool GetReturningFlag() const { return m_returning_flag; }
|
||||
bool GetIsUsingItemClick() { return is_using_item_click; }
|
||||
void SetIsUsingItemClick(bool flag = true) { is_using_item_click = flag; }
|
||||
bool UseDiscipline(uint32 spell_id, uint32 target);
|
||||
uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets, Raid* raid);
|
||||
uint8 GetNumberNeedingHealedInRaidGroup(uint8& need_healed, uint8 hpr, bool includePets, Raid* raid);
|
||||
@@ -286,6 +287,10 @@ public:
|
||||
void SetEndurance(int32 newEnd) override;
|
||||
void DoEnduranceUpkeep();
|
||||
|
||||
void TryItemClick(uint16 slot_id);
|
||||
EQ::ItemInstance* GetClickItem(uint16 slot_id);
|
||||
void DoItemClick(const EQ::ItemData* inst, uint16 slot_id);
|
||||
|
||||
bool AI_AddBotSpells(uint32 bot_spell_id);
|
||||
void AddSpellToBotList(
|
||||
int16 iPriority,
|
||||
@@ -394,25 +399,20 @@ public:
|
||||
|
||||
// Static Class Methods
|
||||
static Bot* LoadBot(uint32 botID);
|
||||
static uint32 SpawnedBotCount(const uint32 owner_id, uint8 class_id = NO_CLASS);
|
||||
static uint32 SpawnedBotCount(const uint32 owner_id, uint8 class_id = Class::None);
|
||||
static void LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp);
|
||||
|
||||
static bool IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined);
|
||||
static Bot* GetBotByBotClientOwnerAndBotName(Client* c, const std::string& botName);
|
||||
static void ProcessBotGroupInvite(Client* c, std::string const& botName);
|
||||
static void ProcessBotGroupDisband(Client* c, const std::string& botName);
|
||||
static void BotOrderCampAll(Client* c, uint8 class_id = NO_CLASS);
|
||||
static void BotOrderCampAll(Client* c, uint8 class_id = Class::None);
|
||||
static void ProcessBotInspectionRequest(Bot* inspectedBot, Client* client);
|
||||
static void LoadAndSpawnAllZonedBots(Client* bot_owner);
|
||||
static bool GroupHasBot(Group* group);
|
||||
static Bot* GetFirstBotInGroup(Group* group);
|
||||
static void ProcessClientZoneChange(Client* botOwner);
|
||||
static void ProcessBotOwnerRefDelete(Mob* botOwner); // Removes a Client* reference when the Client object is destroyed
|
||||
static int32 GetSpellRecastTimer(Bot *caster, int timer_index);
|
||||
static bool CheckSpellRecastTimers(Bot *caster, int SpellIndex);
|
||||
static int32 GetDisciplineRecastTimer(Bot *caster, int timer_index);
|
||||
static bool CheckDisciplineRecastTimers(Bot *caster, int timer_index);
|
||||
static uint32 GetDisciplineRemainingTime(Bot *caster, int timer_index);
|
||||
|
||||
//Raid methods
|
||||
static void ProcessRaidInvite(Mob* invitee, Client* invitor, bool group_invite = false);
|
||||
@@ -604,7 +604,7 @@ public:
|
||||
void SetBotCharmer(bool c) { _botCharmer = c; }
|
||||
void SetPetChooser(bool p) { _petChooser = p; }
|
||||
void SetBotOwner(Mob* botOwner) { this->_botOwner = botOwner; }
|
||||
void SetRangerAutoWeaponSelect(bool enable) { GetClass() == RANGER ? _rangerAutoWeaponSelect = enable : _rangerAutoWeaponSelect = false; }
|
||||
void SetRangerAutoWeaponSelect(bool enable) { GetClass() == Class::Ranger ? _rangerAutoWeaponSelect = enable : _rangerAutoWeaponSelect = false; }
|
||||
void SetBotStance(EQ::constants::StanceType botStance) {
|
||||
if (botStance >= EQ::constants::stancePassive && botStance <= EQ::constants::stanceBurnAE)
|
||||
_botStance = botStance;
|
||||
@@ -612,8 +612,23 @@ public:
|
||||
_botStance = EQ::constants::stancePassive;
|
||||
}
|
||||
void SetBotCasterRange(uint32 bot_caster_range) { m_bot_caster_range = bot_caster_range; }
|
||||
void SetSpellRecastTimer(int timer_index, int32 recast_delay);
|
||||
void SetDisciplineRecastTimer(int timer_index, int32 recast_delay);
|
||||
uint32 GetSpellRecastTimer(uint16 spell_id = 0);
|
||||
bool CheckSpellRecastTimer(uint16 spell_id = 0);
|
||||
uint32 GetSpellRecastRemainingTime(uint16 spell_id = 0);
|
||||
void SetSpellRecastTimer(uint16 spell_id, int32 recast_delay = 0);
|
||||
uint32 CalcSpellRecastTimer(uint16 spell_id);
|
||||
uint32 GetDisciplineReuseTimer(uint16 spell_id = 0);
|
||||
bool CheckDisciplineReuseTimer(uint16 spell_id = 0);
|
||||
uint32 GetDisciplineReuseRemainingTime(uint16 spell_id = 0);
|
||||
void SetDisciplineReuseTimer(uint16 spell_id, int32 reuse_timer = 0);
|
||||
uint32 GetItemReuseTimer(uint32 item_id = 0);
|
||||
bool CheckItemReuseTimer(uint32 item_id = 0);
|
||||
void SetItemReuseTimer(uint32 item_id, uint32 reuse_timer = 0);
|
||||
void ClearDisciplineReuseTimer(uint16 spell_id = 0);
|
||||
void ClearItemReuseTimer(uint32 item_id = 0);
|
||||
void ClearSpellRecastTimer(uint16 spell_id = 0);
|
||||
uint32 GetItemReuseRemainingTime(uint32 item_id = 0);
|
||||
void ClearExpiredTimers();
|
||||
void SetAltOutOfCombatBehavior(bool behavior_flag) { _altoutofcombatbehavior = behavior_flag;}
|
||||
void SetShowHelm(bool showhelm) { _showhelm = showhelm; }
|
||||
void SetBeardColor(uint8 value) { beardcolor = value; }
|
||||
@@ -713,7 +728,8 @@ public:
|
||||
|
||||
// New accessors for BotDatabase access
|
||||
bool DeleteBot();
|
||||
uint32* GetTimers() { return timers; }
|
||||
std::vector<BotTimer_Struct> GetBotTimers() { return bot_timers; }
|
||||
void SetBotTimers(std::vector<BotTimer_Struct> timers) { bot_timers = timers; }
|
||||
uint32 GetLastZoneID() const { return _lastZoneId; }
|
||||
int32 GetBaseAC() const { return _baseAC; }
|
||||
int32 GetBaseATK() const { return _baseATK; }
|
||||
@@ -738,7 +754,7 @@ public:
|
||||
//Raid additions
|
||||
Raid* p_raid_instance;
|
||||
|
||||
static uint8 spell_casting_chances[SPELL_TYPE_COUNT][PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND];
|
||||
static uint8 spell_casting_chances[SPELL_TYPE_COUNT][Class::PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND];
|
||||
|
||||
bool BotCastMez(Mob* tar, uint8 botLevel, bool checked_los, BotSpell& botSpell, Raid* raid);
|
||||
bool BotCastHeal(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpell, Raid* raid);
|
||||
@@ -828,6 +844,7 @@ protected:
|
||||
|
||||
std::vector<BotSpells_Struct> AIBot_spells;
|
||||
std::vector<BotSpells_Struct> AIBot_spells_enforced;
|
||||
std::vector<BotTimer_Struct> bot_timers;
|
||||
|
||||
private:
|
||||
// Class Members
|
||||
@@ -861,11 +878,11 @@ private:
|
||||
int32 cur_end;
|
||||
int32 max_end;
|
||||
int32 end_regen;
|
||||
uint32 timers[MaxTimer];
|
||||
|
||||
Timer m_evade_timer; // can be moved to pTimers at some point
|
||||
Timer m_alt_combat_hate_timer;
|
||||
Timer m_auto_defend_timer;
|
||||
Timer auto_save_timer;
|
||||
bool m_dirtyautohaters;
|
||||
bool m_guard_flag;
|
||||
bool m_hold_flag;
|
||||
@@ -874,6 +891,7 @@ private:
|
||||
bool m_pull_flag;
|
||||
bool m_pulling_flag;
|
||||
bool m_returning_flag;
|
||||
bool is_using_item_click;
|
||||
eStandingPetOrder m_previous_pet_order;
|
||||
uint32 m_bot_caster_range;
|
||||
BotCastingRoles m_CastingRoles;
|
||||
|
||||
+1083
-308
File diff suppressed because it is too large
Load Diff
+3
-1
@@ -554,6 +554,7 @@ void bot_command_bind_affinity(Client *c, const Seperator *sep);
|
||||
void bot_command_bot(Client *c, const Seperator *sep);
|
||||
void bot_command_caster_range(Client* c, const Seperator* sep);
|
||||
void bot_command_charm(Client *c, const Seperator *sep);
|
||||
void bot_command_click_item(Client* c, const Seperator* sep);
|
||||
void bot_command_cure(Client *c, const Seperator *sep);
|
||||
void bot_command_defensive(Client *c, const Seperator *sep);
|
||||
void bot_command_depart(Client *c, const Seperator *sep);
|
||||
@@ -595,6 +596,7 @@ void bot_command_enforce_spell_list(Client* c, const Seperator* sep);
|
||||
void bot_command_summon_corpse(Client *c, const Seperator *sep);
|
||||
void bot_command_suspend(Client *c, const Seperator *sep);
|
||||
void bot_command_taunt(Client *c, const Seperator *sep);
|
||||
void bot_command_timer(Client* c, const Seperator* sep);
|
||||
void bot_command_track(Client *c, const Seperator *sep);
|
||||
void bot_command_view_combos(Client *c, const Seperator *sep);
|
||||
void bot_command_water_breathing(Client *c, const Seperator *sep);
|
||||
@@ -677,7 +679,7 @@ void helper_command_depart_list(Client* bot_owner, Bot* druid_bot, Bot* wizard_b
|
||||
bool helper_is_help_or_usage(const char* arg);
|
||||
bool helper_no_available_bots(Client *bot_owner, Bot *my_bot = nullptr);
|
||||
void helper_send_available_subcommands(Client *bot_owner, const char* command_simile, const std::list<const char*>& subcommand_list);
|
||||
void helper_send_usage_required_bots(Client *bot_owner, BCEnum::SpType spell_type, uint8 bot_class = NO_CLASS);
|
||||
void helper_send_usage_required_bots(Client *bot_owner, BCEnum::SpType spell_type, uint8 bot_class = Class::None);
|
||||
bool helper_spell_check_fail(STBaseEntry* local_entry);
|
||||
bool helper_spell_list_fail(Client *bot_owner, bcst_list* spell_list, BCEnum::SpType spell_type);
|
||||
#endif
|
||||
|
||||
+79
-56
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "../common/repositories/bot_data_repository.h"
|
||||
#include "../common/repositories/bot_inventories_repository.h"
|
||||
#include "../common/repositories/bot_timers_repository.h"
|
||||
|
||||
#include "zonedb.h"
|
||||
#include "bot.h"
|
||||
@@ -141,7 +142,7 @@ bool BotDatabase::LoadBotSpellCastingChances()
|
||||
if (spell_type_index >= Bot::SPELL_TYPE_COUNT)
|
||||
continue;
|
||||
uint8 class_index = Strings::ToInt(row[1]);
|
||||
if (class_index < WARRIOR || class_index > BERSERKER)
|
||||
if (class_index < Class::Warrior || class_index > Class::Berserker)
|
||||
continue;
|
||||
--class_index;
|
||||
uint8 stance_index = Strings::ToInt(row[2]);
|
||||
@@ -224,7 +225,7 @@ bool BotDatabase::QueryBotCount(const uint32 owner_id, int class_id, uint32& bot
|
||||
auto row = results.begin();
|
||||
bot_count = Strings::ToUnsignedInt(row[0]);
|
||||
|
||||
if (EQ::ValueWithin(class_id, WARRIOR, BERSERKER)) {
|
||||
if (EQ::ValueWithin(class_id, Class::Warrior, Class::Berserker)) {
|
||||
query = fmt::format(
|
||||
"SELECT COUNT(`bot_id`) FROM `bot_data` WHERE `owner_id` = {} AND `class` = {}",
|
||||
owner_id,
|
||||
@@ -917,45 +918,39 @@ bool BotDatabase::LoadTimers(Bot* bot_inst)
|
||||
if (!bot_inst)
|
||||
return false;
|
||||
|
||||
query = StringFormat(
|
||||
"SELECT"
|
||||
" IfNull(bt.`timer_id`, '0') As timer_id,"
|
||||
" IfNull(bt.`timer_value`, '0') As timer_value,"
|
||||
" IfNull(MAX(sn.`recast_time`), '0') AS MaxTimer"
|
||||
" FROM `bot_timers` bt, `spells_new` sn"
|
||||
" WHERE bt.`bot_id` = '%u' AND sn.`EndurTimerIndex` = ("
|
||||
"SELECT case"
|
||||
" WHEN timer_id > '%i' THEN timer_id - '%i'"
|
||||
" ELSE timer_id END AS timer_id"
|
||||
" FROM `bot_timers` WHERE `timer_id` = bt.`timer_id` AND `bot_id` = bt.`bot_id`" // double-check validity
|
||||
")"
|
||||
" AND sn.`classes%i` <= '%i'",
|
||||
bot_inst->GetBotID(),
|
||||
(DisciplineReuseStart - 1),
|
||||
(DisciplineReuseStart - 1),
|
||||
bot_inst->GetClass(),
|
||||
bot_inst->GetLevel()
|
||||
auto timers = BotTimersRepository::GetWhere(
|
||||
database,
|
||||
fmt::format("bot_id = {}", bot_inst->GetBotID())
|
||||
);
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
if (!results.RowCount())
|
||||
return true;
|
||||
|
||||
uint32* bot_timers = bot_inst->GetTimers();
|
||||
if (!bot_timers)
|
||||
return false;
|
||||
std::vector<BotTimer_Struct> bot_timers;
|
||||
|
||||
int timer_id = 0;
|
||||
uint32 timer_value = 0;
|
||||
uint32 max_value = 0;
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
timer_id = Strings::ToInt(row[0]) - 1;
|
||||
timer_value = Strings::ToInt(row[1]);
|
||||
max_value = Strings::ToInt(row[2]);
|
||||
BotTimer_Struct t{};
|
||||
t.timer_id = 0;
|
||||
t.timer_value = 0;
|
||||
t.recast_time = 0;
|
||||
t.is_spell = false;
|
||||
t.is_disc = false;
|
||||
t.spell_id = 0;
|
||||
t.is_item = false;
|
||||
t.item_id = 0;
|
||||
|
||||
if (timer_id >= 0 && timer_id < MaxTimer && timer_value < (Timer::GetCurrentTime() + max_value))
|
||||
bot_timers[timer_id] = timer_value;
|
||||
for (auto& timer : timers) {
|
||||
if (t.timer_value < (Timer::GetCurrentTime() + t.recast_time)) {
|
||||
t.timer_id = timer.timer_id;
|
||||
t.timer_value = timer.timer_value;
|
||||
t.recast_time = timer.recast_time;
|
||||
t.is_spell = timer.is_spell ? true : false;
|
||||
t.is_disc = timer.is_disc ? true : false;
|
||||
t.spell_id = timer.spell_id;
|
||||
t.is_item = timer.is_item ? true : false;
|
||||
t.item_id = timer.item_id;
|
||||
bot_timers.push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
if (!bot_timers.empty()) {
|
||||
bot_inst->SetBotTimers(bot_timers);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -963,26 +958,56 @@ bool BotDatabase::LoadTimers(Bot* bot_inst)
|
||||
|
||||
bool BotDatabase::SaveTimers(Bot* bot_inst)
|
||||
{
|
||||
if (!bot_inst)
|
||||
if (!bot_inst) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DeleteTimers(bot_inst->GetBotID()))
|
||||
if (!DeleteTimers(bot_inst->GetBotID())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32* bot_timers = bot_inst->GetTimers();
|
||||
if (!bot_timers)
|
||||
return false;
|
||||
std::vector<BotTimer_Struct> bot_timers = bot_inst->GetBotTimers();
|
||||
|
||||
for (int timer_index = 0; timer_index < MaxTimer; ++timer_index) {
|
||||
if (bot_timers[timer_index] <= Timer::GetCurrentTime())
|
||||
continue;
|
||||
if (bot_timers.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
query = fmt::format(
|
||||
"REPLACE INTO `bot_timers` (`bot_id`, `timer_id`, `timer_value`) VALUES ('{}', '{}', '{}')",
|
||||
bot_inst->GetBotID(), (timer_index + 1), bot_timers[timer_index]
|
||||
std::vector<BotTimersRepository::BotTimers> timers;
|
||||
|
||||
if (!bot_timers.empty()) {
|
||||
for (auto & bot_timer : bot_timers) {
|
||||
if (bot_timer.timer_value <= Timer::GetCurrentTime()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto t = BotTimersRepository::BotTimers{
|
||||
.bot_id = bot_inst->GetBotID(),
|
||||
.timer_id = bot_timer.timer_id,
|
||||
.timer_value = bot_timer.timer_value,
|
||||
.recast_time = bot_timer.recast_time,
|
||||
.is_spell = bot_timer.is_spell ? true : false,
|
||||
.is_disc = bot_timer.is_disc ? true : false,
|
||||
.spell_id = bot_timer.spell_id,
|
||||
.is_item = bot_timer.is_item ? true : false,
|
||||
.item_id = bot_timer.item_id
|
||||
};
|
||||
|
||||
timers.push_back(t);
|
||||
}
|
||||
|
||||
if (timers.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// delete existing
|
||||
BotTimersRepository::DeleteWhere(
|
||||
database,
|
||||
fmt::format("bot_id = {}", bot_inst->GetBotID())
|
||||
);
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
|
||||
// bulk insert current
|
||||
auto success = BotTimersRepository::InsertMany(database, timers);
|
||||
if (!success) {
|
||||
DeleteTimers(bot_inst->GetBotID());
|
||||
return false;
|
||||
}
|
||||
@@ -993,13 +1018,11 @@ bool BotDatabase::SaveTimers(Bot* bot_inst)
|
||||
|
||||
bool BotDatabase::DeleteTimers(const uint32 bot_id)
|
||||
{
|
||||
if (!bot_id)
|
||||
if (!bot_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
query = StringFormat("DELETE FROM `bot_timers` WHERE `bot_id` = '%u'", bot_id);
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
BotTimersRepository::DeleteWhere(database, fmt::format("bot_id = {}", bot_id));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -2517,7 +2540,7 @@ uint8 BotDatabase::GetSpellCastingChance(uint8 spell_type_index, uint8 class_ind
|
||||
{
|
||||
if (spell_type_index >= Bot::SPELL_TYPE_COUNT)
|
||||
return 0;
|
||||
if (class_index >= PLAYER_CLASS_COUNT)
|
||||
if (class_index >= Class::PLAYER_CLASS_COUNT)
|
||||
return 0;
|
||||
if (stance_index >= EQ::constants::STANCE_TYPE_COUNT)
|
||||
return 0;
|
||||
|
||||
@@ -81,4 +81,15 @@ struct BotSpells_Struct {
|
||||
uint8 bucket_comparison;
|
||||
};
|
||||
|
||||
struct BotTimer_Struct {
|
||||
uint32 timer_id;
|
||||
uint32 timer_value;
|
||||
uint32 recast_time;
|
||||
bool is_spell;
|
||||
bool is_disc;
|
||||
uint16 spell_id;
|
||||
bool is_item;
|
||||
uint32 item_id;
|
||||
};
|
||||
|
||||
#endif // BOT_STRUCTS
|
||||
|
||||
+115
-180
@@ -101,14 +101,14 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) {
|
||||
|
||||
bool Bot::BotCastSong(Mob* tar, uint8 botLevel) {
|
||||
bool casted_spell = false;
|
||||
if (GetClass() != BARD || tar != this || IsEngaged()) // Out-of-Combat songs can not be cast in combat
|
||||
if (GetClass() != Class::Bard || tar != this || IsEngaged()) // Out-of-Combat songs can not be cast in combat
|
||||
return casted_spell;
|
||||
|
||||
for (auto botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_OutOfCombatBuffSong);
|
||||
auto iter : botSongList) {
|
||||
if (!iter.SpellId)
|
||||
continue;
|
||||
if (!CheckSpellRecastTimers(this, iter.SpellIndex))
|
||||
if (!CheckSpellRecastTimer(iter.SpellId))
|
||||
continue;
|
||||
if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType()))
|
||||
continue;
|
||||
@@ -142,7 +142,7 @@ bool Bot::BotCastCombatSong(Mob* tar, uint8 botLevel) {
|
||||
auto iter : botSongList) {
|
||||
if (!iter.SpellId)
|
||||
continue;
|
||||
if (!CheckSpellRecastTimers(this, iter.SpellIndex))
|
||||
if (!CheckSpellRecastTimer(iter.SpellId))
|
||||
continue;
|
||||
if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType()))
|
||||
continue;
|
||||
@@ -169,12 +169,12 @@ bool Bot::BotCastCombatSong(Mob* tar, uint8 botLevel) {
|
||||
|
||||
bool Bot::BotCastHateReduction(Mob* tar, uint8 botLevel, const BotSpell& botSpell) {
|
||||
bool casted_spell = false;
|
||||
if (GetClass() == BARD) {
|
||||
if (GetClass() == Class::Bard) {
|
||||
std::list<BotSpell_wPriority> botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_HateRedux);
|
||||
for (auto iter : botSongList) {
|
||||
if (!iter.SpellId)
|
||||
continue;
|
||||
if (!CheckSpellRecastTimers(this, iter.SpellIndex))
|
||||
if (!CheckSpellRecastTimer(iter.SpellId))
|
||||
continue;
|
||||
if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType()))
|
||||
continue;
|
||||
@@ -183,7 +183,7 @@ bool Bot::BotCastHateReduction(Mob* tar, uint8 botLevel, const BotSpell& botSpel
|
||||
if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0)
|
||||
continue;
|
||||
|
||||
if (IsValidSpellRange(botSpell.SpellId, tar)) {
|
||||
if (IsValidSpellRange(iter.SpellId, tar)) {
|
||||
casted_spell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost);
|
||||
}
|
||||
if (casted_spell) {
|
||||
@@ -220,7 +220,7 @@ bool Bot::BotCastCure(Mob* tar, uint8 botClass, BotSpell& botSpell, Raid* raid)
|
||||
|
||||
casted_spell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontCureMeBeforeTime);
|
||||
|
||||
if (casted_spell && botClass != BARD) {
|
||||
if (casted_spell && botClass != Class::Bard) {
|
||||
if (IsGroupSpell(botSpell.SpellId)) {
|
||||
if (HasGroup()) {
|
||||
Group const* group = GetGroup();
|
||||
@@ -301,7 +301,7 @@ bool Bot::BotCastSlow(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
|
||||
}
|
||||
|
||||
switch (botClass) {
|
||||
case BARD: {
|
||||
case Class::Bard: {
|
||||
// probably needs attackable check
|
||||
for (
|
||||
auto botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_Slow);
|
||||
@@ -312,7 +312,7 @@ bool Bot::BotCastSlow(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!CheckSpellRecastTimers(this, iter.SpellIndex)) {
|
||||
if (!CheckSpellRecastTimer(iter.SpellId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -328,7 +328,7 @@ bool Bot::BotCastSlow(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsValidSpellRange(botSpell.SpellId, tar)) {
|
||||
if (IsValidSpellRange(iter.SpellId, tar)) {
|
||||
casted_spell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost);
|
||||
}
|
||||
|
||||
@@ -339,12 +339,12 @@ bool Bot::BotCastSlow(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
|
||||
|
||||
break;
|
||||
}
|
||||
case ENCHANTER: {
|
||||
case Class::Enchanter: {
|
||||
botSpell = GetBestBotSpellForMagicBasedSlow(this);
|
||||
break;
|
||||
}
|
||||
case SHAMAN:
|
||||
case BEASTLORD: {
|
||||
case Class::Shaman:
|
||||
case Class::Beastlord: {
|
||||
botSpell = GetBestBotSpellForDiseaseBasedSlow(this);
|
||||
|
||||
if (botSpell.SpellId == 0 || ((tar->GetMR() - 50) < (tar->GetDR() + spells[botSpell.SpellId].resist_difficulty)))
|
||||
@@ -364,7 +364,7 @@ bool Bot::BotCastSlow(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
|
||||
casted_spell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost);
|
||||
}
|
||||
|
||||
if (casted_spell && GetClass() != BARD) {
|
||||
if (casted_spell && GetClass() != Class::Bard) {
|
||||
if (raid) {
|
||||
const auto msg = fmt::format("Attempting to slow {}.", tar->GetCleanName());
|
||||
raid->RaidSay(msg.c_str(), GetCleanName(), 0, 100);
|
||||
@@ -391,7 +391,7 @@ bool Bot::BotCastDOT(Mob* tar, uint8 botLevel, const BotSpell& botSpell, const b
|
||||
return casted_spell;
|
||||
}
|
||||
|
||||
if (GetClass() == BARD) {
|
||||
if (GetClass() == Class::Bard) {
|
||||
std::list<BotSpell_wPriority> dotList = GetPrioritizedBotSpellsBySpellType(this, SpellType_DOT);
|
||||
|
||||
const int maxDotSelect = 5;
|
||||
@@ -403,7 +403,7 @@ bool Bot::BotCastDOT(Mob* tar, uint8 botLevel, const BotSpell& botSpell, const b
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CheckSpellRecastTimers(this, s.SpellIndex))
|
||||
if (CheckSpellRecastTimer(s.SpellId))
|
||||
{
|
||||
|
||||
if (!(!tar->IsImmuneToSpell(s.SpellId, this) && tar->CanBuffStack(s.SpellId, botLevel, true) >= 0)) {
|
||||
@@ -438,7 +438,7 @@ bool Bot::BotCastDOT(Mob* tar, uint8 botLevel, const BotSpell& botSpell, const b
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CheckSpellRecastTimers(this, s.SpellIndex)) {
|
||||
if (CheckSpellRecastTimer(s.SpellId)) {
|
||||
|
||||
if (!(!tar->IsImmuneToSpell(s.SpellId, this) &&
|
||||
tar->CanBuffStack(s.SpellId, botLevel, true) >= 0)) {
|
||||
@@ -447,7 +447,7 @@ bool Bot::BotCastDOT(Mob* tar, uint8 botLevel, const BotSpell& botSpell, const b
|
||||
|
||||
uint32 TempDontDotMeBefore = tar->DontDotMeBefore();
|
||||
|
||||
if (IsValidSpellRange(botSpell.SpellId, tar)) {
|
||||
if (IsValidSpellRange(s.SpellId, tar)) {
|
||||
casted_spell = AIDoSpellCast(s.SpellIndex, tar, s.ManaCost, &TempDontDotMeBefore);
|
||||
}
|
||||
|
||||
@@ -569,7 +569,7 @@ bool Bot::BotCastCombatBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
|
||||
(tar == this && spells[s.SpellId].target_type != ST_TargetsTarget) ||
|
||||
spells[s.SpellId].target_type == ST_Group ||
|
||||
spells[s.SpellId].target_type == ST_GroupTeleport ||
|
||||
(botClass == BARD && spells[s.SpellId].target_type == ST_AEBard)
|
||||
(botClass == Class::Bard && spells[s.SpellId].target_type == ST_AEBard)
|
||||
) &&
|
||||
!tar->IsImmuneToSpell(s.SpellId, this) &&
|
||||
tar->CanBuffStack(s.SpellId, botLevel, true) >= 0
|
||||
@@ -582,7 +582,7 @@ bool Bot::BotCastCombatBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
|
||||
if (
|
||||
((IsEffectInSpell(s.SpellId, SE_Levitate) && !zone->CanLevitate()) ||
|
||||
(IsEffectInSpell(s.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor())) &&
|
||||
(botClass != BARD || !IsSpellUsableInThisZoneType(s.SpellId, zone->GetZoneType()))
|
||||
(botClass != Class::Bard || !IsSpellUsableInThisZoneType(s.SpellId, zone->GetZoneType()))
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
@@ -625,7 +625,7 @@ bool Bot::BotCastCombatBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
|
||||
}
|
||||
}
|
||||
// TODO: Add TriggerSpell Support for Exchanter Runes
|
||||
if (botClass == ENCHANTER && IsEffectInSpell(s.SpellId, SE_Rune)) {
|
||||
if (botClass == Class::Enchanter && IsEffectInSpell(s.SpellId, SE_Rune)) {
|
||||
float manaRatioToCast = 75.0f;
|
||||
|
||||
switch(GetBotStance()) {
|
||||
@@ -652,7 +652,7 @@ bool Bot::BotCastCombatBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
|
||||
}
|
||||
}
|
||||
|
||||
if (CheckSpellRecastTimers(this, s.SpellIndex)) {
|
||||
if (CheckSpellRecastTimer(s.SpellId)) {
|
||||
uint32 TempDontBuffMeBefore = tar->DontBuffMeBefore();
|
||||
casted_spell = AIDoSpellCast(s.SpellIndex, tar, s.ManaCost, &TempDontBuffMeBefore);
|
||||
if (TempDontBuffMeBefore != tar->DontBuffMeBefore()) {
|
||||
@@ -671,7 +671,7 @@ bool Bot::BotCastCombatBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
|
||||
bool Bot::BotCastPet(Mob* tar, uint8 botClass, BotSpell& botSpell) {
|
||||
bool casted_spell = false;
|
||||
if (!IsPet() && !GetPetID() && !IsBotCharmer()) {
|
||||
if (botClass == WIZARD) {
|
||||
if (botClass == Class::Wizard) {
|
||||
auto buffs_max = GetMaxBuffSlots();
|
||||
auto my_buffs = GetBuffs();
|
||||
int familiar_buff_slot = -1;
|
||||
@@ -694,7 +694,7 @@ bool Bot::BotCastPet(Mob* tar, uint8 botClass, BotSpell& botSpell) {
|
||||
|
||||
botSpell = GetFirstBotSpellBySpellType(this, SpellType_Pet);
|
||||
}
|
||||
else if (botClass == MAGICIAN) {
|
||||
else if (botClass == Class::Magician) {
|
||||
botSpell = GetBestBotMagicianPetSpell(this);
|
||||
}
|
||||
else {
|
||||
@@ -735,13 +735,13 @@ bool Bot::BotCastDispel(Mob* tar, BotSpell& botSpell, uint32 iSpellTypes, const
|
||||
bool Bot::BotCastNuke(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpell, const bool& checked_los) {
|
||||
|
||||
bool casted_spell = false;
|
||||
if ((tar->GetHPRatio() <= 95.0f) || ((botClass == BARD) || (botClass == SHAMAN) || (botClass == ENCHANTER) || (botClass == PALADIN) || (botClass == SHADOWKNIGHT) || (botClass == WARRIOR)))
|
||||
if ((tar->GetHPRatio() <= 95.0f) || ((botClass == Class::Bard) || (botClass == Class::Shaman) || (botClass == Class::Enchanter) || (botClass == Class::Paladin) || (botClass == Class::ShadowKnight) || (botClass == Class::Warrior)))
|
||||
{
|
||||
if (!checked_los && (!CheckLosFN(tar) || !CheckWaterLoS(tar))) {
|
||||
return casted_spell;
|
||||
}
|
||||
|
||||
if (botClass == CLERIC || botClass == ENCHANTER)
|
||||
if (botClass == Class::Cleric || botClass == Class::Enchanter)
|
||||
{
|
||||
float manaRatioToCast = 75.0f;
|
||||
|
||||
@@ -770,17 +770,17 @@ bool Bot::BotCastNuke(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
|
||||
return casted_spell;
|
||||
}
|
||||
|
||||
if (botClass == MAGICIAN || botClass == SHADOWKNIGHT || botClass == NECROMANCER || botClass == PALADIN || botClass == RANGER || botClass == DRUID || botClass == CLERIC) {
|
||||
if (botClass == Class::Magician || botClass == Class::ShadowKnight || botClass == Class::Necromancer || botClass == Class::Paladin || botClass == Class::Ranger || botClass == Class::Druid || botClass == Class::Cleric) {
|
||||
if (tar->GetBodyType() == BT_Undead || tar->GetBodyType() == BT_SummonedUndead || tar->GetBodyType() == BT_Vampire)
|
||||
botSpell = GetBestBotSpellForNukeByTargetType(this, ST_Undead);
|
||||
else if (tar->GetBodyType() == BT_Summoned || tar->GetBodyType() == BT_Summoned2 || tar->GetBodyType() == BT_Summoned3)
|
||||
botSpell = GetBestBotSpellForNukeByTargetType(this, ST_Summoned);
|
||||
}
|
||||
|
||||
if ((botClass == PALADIN || botClass == DRUID || botClass == CLERIC || botClass == ENCHANTER || botClass == WIZARD) && !IsValidSpell(botSpell.SpellId)) {
|
||||
if ((botClass == Class::Paladin || botClass == Class::Druid || botClass == Class::Cleric || botClass == Class::Enchanter || botClass == Class::Wizard) && !IsValidSpell(botSpell.SpellId)) {
|
||||
uint8 stunChance = (tar->IsCasting() ? 30: 15);
|
||||
|
||||
if (botClass == PALADIN) {
|
||||
if (botClass == Class::Paladin) {
|
||||
stunChance = 50;
|
||||
}
|
||||
|
||||
@@ -789,7 +789,7 @@ bool Bot::BotCastNuke(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
|
||||
}
|
||||
}
|
||||
|
||||
if (botClass == WIZARD && botSpell.SpellId == 0) {
|
||||
if (botClass == Class::Wizard && botSpell.SpellId == 0) {
|
||||
botSpell = GetBestBotWizardNukeSpellByTargetResists(this, tar);
|
||||
}
|
||||
|
||||
@@ -819,7 +819,7 @@ bool Bot::BotCastEscape(Mob*& tar, uint8 botClass, BotSpell& botSpell, uint32 iS
|
||||
auto hpr = (uint8) GetHPRatio();
|
||||
bool mayGetAggro = false;
|
||||
|
||||
if (hpr > 15 && ((botClass == WIZARD) || (botClass == ENCHANTER) || (botClass == RANGER))) {
|
||||
if (hpr > 15 && ((botClass == Class::Wizard) || (botClass == Class::Enchanter) || (botClass == Class::Ranger))) {
|
||||
mayGetAggro = HasOrMayGetAggro();
|
||||
}
|
||||
|
||||
@@ -835,7 +835,7 @@ bool Bot::BotCastEscape(Mob*& tar, uint8 botClass, BotSpell& botSpell, uint32 iS
|
||||
tar = this; //target self for invul type spells
|
||||
}
|
||||
|
||||
if (IsValidSpellRange(botSpell.SpellId, tar) || botClass == BARD) {
|
||||
if (IsValidSpellRange(botSpell.SpellId, tar) || botClass == Class::Bard) {
|
||||
casted_spell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost);
|
||||
}
|
||||
}
|
||||
@@ -877,7 +877,7 @@ bool Bot::BotCastBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
|
||||
(tar == this && spells[s.SpellId].target_type != ST_TargetsTarget) ||
|
||||
spells[s.SpellId].target_type == ST_Group ||
|
||||
spells[s.SpellId].target_type == ST_GroupTeleport ||
|
||||
(botClass == BARD && spells[s.SpellId].target_type == ST_AEBard)
|
||||
(botClass == Class::Bard && spells[s.SpellId].target_type == ST_AEBard)
|
||||
) &&
|
||||
!tar->IsImmuneToSpell(s.SpellId, this) &&
|
||||
tar->CanBuffStack(s.SpellId, botLevel, true) >= 0
|
||||
@@ -892,7 +892,7 @@ bool Bot::BotCastBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
|
||||
(IsEffectInSpell(s.SpellId, SE_Levitate) && !zone->CanLevitate()) ||
|
||||
(IsEffectInSpell(s.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor())
|
||||
) &&
|
||||
(botClass != BARD || !IsSpellUsableInThisZoneType(s.SpellId, zone->GetZoneType()))
|
||||
(botClass != Class::Bard || !IsSpellUsableInThisZoneType(s.SpellId, zone->GetZoneType()))
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
@@ -919,7 +919,7 @@ bool Bot::BotCastBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (botClass == ENCHANTER && IsEffectInSpell(s.SpellId, SE_Rune))
|
||||
if (botClass == Class::Enchanter && IsEffectInSpell(s.SpellId, SE_Rune))
|
||||
{
|
||||
float manaRatioToCast = 75.0f;
|
||||
|
||||
@@ -947,7 +947,7 @@ bool Bot::BotCastBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
|
||||
}
|
||||
}
|
||||
|
||||
if (CheckSpellRecastTimers(this, s.SpellIndex))
|
||||
if (CheckSpellRecastTimer(s.SpellId))
|
||||
{
|
||||
uint32 TempDontBuffMeBefore = tar->DontBuffMeBefore();
|
||||
|
||||
@@ -1003,17 +1003,17 @@ bool Bot::BotCastHeal(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
|
||||
isPrimaryHealer = IsGroupHealer();
|
||||
}
|
||||
|
||||
if (hpr < 95 || tar->IsClient() || botClass == BARD) {
|
||||
if (tar->GetClass() == NECROMANCER && hpr >= 40) {
|
||||
if (hpr < 95 || tar->IsClient() || botClass == Class::Bard) {
|
||||
if (tar->GetClass() == Class::Necromancer && hpr >= 40) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tar->GetClass() == SHAMAN && hpr >= 80) {
|
||||
if (tar->GetClass() == Class::Shaman && hpr >= 80) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Evaluate the situation
|
||||
if ((IsEngaged()) && ((botClass == CLERIC) || (botClass == DRUID) || (botClass == SHAMAN) || (botClass == PALADIN))) {
|
||||
if ((IsEngaged()) && ((botClass == Class::Cleric) || (botClass == Class::Druid) || (botClass == Class::Shaman) || (botClass == Class::Paladin))) {
|
||||
if (tar->GetTarget() && tar->GetTarget()->GetHateTop() && tar->GetTarget()->GetHateTop() == tar) {
|
||||
hasAggro = true;
|
||||
}
|
||||
@@ -1045,7 +1045,7 @@ bool Bot::BotCastHeal(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((botClass == CLERIC) || (botClass == DRUID) || (botClass == SHAMAN) || (botClass == PALADIN)) {
|
||||
else if ((botClass == Class::Cleric) || (botClass == Class::Druid) || (botClass == Class::Shaman) || (botClass == Class::Paladin)) {
|
||||
if (GetNumberNeedingHealedInGroup(40, true, raid) >= 2) {
|
||||
botSpell = GetBestBotSpellForGroupCompleteHeal(this);
|
||||
|
||||
@@ -1119,7 +1119,7 @@ bool Bot::BotCastHeal(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
|
||||
if (!IsValidSpell(botSpell.SpellId)) {
|
||||
botSpell = GetFirstBotSpellForSingleTargetHeal(this);
|
||||
}
|
||||
if (botSpell.SpellId == 0 && botClass == BARD) {
|
||||
if (botSpell.SpellId == 0 && botClass == Class::Bard) {
|
||||
botSpell = GetFirstBotSpellBySpellType(this, SpellType_Heal);
|
||||
}
|
||||
|
||||
@@ -1134,11 +1134,11 @@ bool Bot::BotCastHeal(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
|
||||
|
||||
uint32 TempDontHealMeBeforeTime = tar->DontHealMeBefore();
|
||||
|
||||
if (IsValidSpellRange(botSpell.SpellId, tar) || botClass == BARD) {
|
||||
if (IsValidSpellRange(botSpell.SpellId, tar) || botClass == Class::Bard) {
|
||||
casted_spell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontHealMeBeforeTime);
|
||||
}
|
||||
|
||||
if (casted_spell && botClass != BARD) {
|
||||
if (casted_spell && botClass != Class::Bard) {
|
||||
if (IsGroupSpell(botSpell.SpellId)) {
|
||||
if (HasGroup()) {
|
||||
Group *group = GetGroup();
|
||||
@@ -1306,10 +1306,8 @@ bool Bot::AIDoSpellCast(int32 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain
|
||||
SetMana(hasMana);
|
||||
}
|
||||
else {
|
||||
AIBot_spells[i].time_cancast = Timer::GetCurrentTime() + spells[AIBot_spells[i].spellid].recast_time;
|
||||
|
||||
if (spells[AIBot_spells[i].spellid].timer_id > 0) {
|
||||
SetSpellRecastTimer(spells[AIBot_spells[i].spellid].timer_id, spells[AIBot_spells[i].spellid].recast_time);
|
||||
if (CalcSpellRecastTimer(AIBot_spells[i].spellid) > 0) {
|
||||
SetSpellRecastTimer(AIBot_spells[i].spellid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1362,9 +1360,9 @@ bool Bot::AI_IdleCastCheck() {
|
||||
//Ok, IdleCastCheck depends of class.
|
||||
switch (GetClass()) {
|
||||
// Healers WITHOUT pets will check if a heal is needed before buffing.
|
||||
case CLERIC:
|
||||
case PALADIN:
|
||||
case RANGER: {
|
||||
case Class::Cleric:
|
||||
case Class::Paladin:
|
||||
case Class::Ranger: {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Heal)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Heal)) {
|
||||
@@ -1379,10 +1377,10 @@ bool Bot::AI_IdleCastCheck() {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
case MONK:
|
||||
case ROGUE:
|
||||
case WARRIOR:
|
||||
case BERSERKER: {
|
||||
case Class::Monk:
|
||||
case Class::Rogue:
|
||||
case Class::Warrior:
|
||||
case Class::Berserker: {
|
||||
if (!AICastSpell(this, 100, SpellType_Cure)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Heal)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Buff)) {
|
||||
@@ -1397,10 +1395,10 @@ bool Bot::AI_IdleCastCheck() {
|
||||
}
|
||||
// Pets class will first cast their pet, then buffs
|
||||
|
||||
case MAGICIAN:
|
||||
case SHADOWKNIGHT:
|
||||
case NECROMANCER:
|
||||
case ENCHANTER: {
|
||||
case Class::Magician:
|
||||
case Class::ShadowKnight:
|
||||
case Class::Necromancer:
|
||||
case Class::Enchanter: {
|
||||
if (!AICastSpell(this, 100, SpellType_Pet)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Cure)) {
|
||||
if (!AICastSpell(GetPet(), 100, SpellType_Cure)) {
|
||||
@@ -1417,9 +1415,9 @@ bool Bot::AI_IdleCastCheck() {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
case DRUID:
|
||||
case SHAMAN:
|
||||
case BEASTLORD: {
|
||||
case Class::Druid:
|
||||
case Class::Shaman:
|
||||
case Class::Beastlord: {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Pet)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Heal)) {
|
||||
@@ -1438,7 +1436,7 @@ bool Bot::AI_IdleCastCheck() {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
case WIZARD: { // This can eventually be move into the BEASTLORD case handler once pre-combat is fully implemented
|
||||
case Class::Wizard: { // This can eventually be move into the Class::Beastlord case handler once pre-combat is fully implemented
|
||||
if (pre_combat) {
|
||||
if (!AICastSpell(this, 100, SpellType_Pet)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Cure)) {
|
||||
@@ -1469,7 +1467,7 @@ bool Bot::AI_IdleCastCheck() {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
case BARD: {
|
||||
case Class::Bard: {
|
||||
if (pre_combat) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Buff)) {
|
||||
@@ -1518,7 +1516,7 @@ bool Bot::AI_EngagedCastCheck() {
|
||||
|
||||
LogAIDetail("Engaged autocast check triggered (BOTS). Trying to cast healing spells then maybe offensive spells");
|
||||
|
||||
if (botClass == CLERIC) {
|
||||
if (botClass == Class::Cleric) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) {
|
||||
if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_Heal), BotAISpellRange, SpellType_Heal)) {
|
||||
@@ -1534,7 +1532,7 @@ bool Bot::AI_EngagedCastCheck() {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (botClass == DRUID) {
|
||||
else if (botClass == Class::Druid) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) {
|
||||
if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_Heal), BotAISpellRange, SpellType_Heal)) {
|
||||
@@ -1552,7 +1550,7 @@ bool Bot::AI_EngagedCastCheck() {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (botClass == SHAMAN) {
|
||||
else if (botClass == Class::Shaman) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Slow), SpellType_Slow)) {
|
||||
if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) {
|
||||
@@ -1573,7 +1571,7 @@ bool Bot::AI_EngagedCastCheck() {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (botClass == RANGER) {
|
||||
else if (botClass == Class::Ranger) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) {
|
||||
if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) {
|
||||
@@ -1588,7 +1586,7 @@ bool Bot::AI_EngagedCastCheck() {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (botClass == BEASTLORD) {
|
||||
else if (botClass == Class::Beastlord) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Slow), SpellType_Slow)) {
|
||||
if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) {
|
||||
@@ -1609,7 +1607,7 @@ bool Bot::AI_EngagedCastCheck() {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (botClass == WIZARD) {
|
||||
else if (botClass == Class::Wizard) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) {
|
||||
@@ -1620,7 +1618,7 @@ bool Bot::AI_EngagedCastCheck() {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (botClass == PALADIN) {
|
||||
else if (botClass == Class::Paladin) {
|
||||
if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) {
|
||||
@@ -1633,7 +1631,7 @@ bool Bot::AI_EngagedCastCheck() {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (botClass == SHADOWKNIGHT) {
|
||||
else if (botClass == Class::ShadowKnight) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Lifetap), SpellType_Lifetap)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) {
|
||||
@@ -1646,7 +1644,7 @@ bool Bot::AI_EngagedCastCheck() {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (botClass == MAGICIAN) {
|
||||
else if (botClass == Class::Magician) {
|
||||
if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Pet), SpellType_Pet)) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) {
|
||||
@@ -1659,7 +1657,7 @@ bool Bot::AI_EngagedCastCheck() {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (botClass == NECROMANCER) {
|
||||
else if (botClass == Class::Necromancer) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) {
|
||||
if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Pet), SpellType_Pet)) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) {
|
||||
@@ -1678,7 +1676,7 @@ bool Bot::AI_EngagedCastCheck() {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (botClass == ENCHANTER) {
|
||||
else if (botClass == Class::Enchanter) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Mez), SpellType_Mez)) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Slow), SpellType_Slow)) {
|
||||
@@ -1695,7 +1693,7 @@ bool Bot::AI_EngagedCastCheck() {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (botClass == BARD) {
|
||||
else if (botClass == Class::Bard) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) {// Bards will use their escape songs
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_HateRedux), BotAISpellRange, SpellType_HateRedux)) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Slow), SpellType_Slow)) {
|
||||
@@ -1714,7 +1712,7 @@ bool Bot::AI_EngagedCastCheck() {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (botClass == BERSERKER) {
|
||||
else if (botClass == Class::Berserker) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) {
|
||||
if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) {
|
||||
@@ -1731,7 +1729,7 @@ bool Bot::AI_EngagedCastCheck() {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (botClass == MONK) {
|
||||
else if (botClass == Class::Monk) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) {
|
||||
if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) {
|
||||
@@ -1748,7 +1746,7 @@ bool Bot::AI_EngagedCastCheck() {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (botClass == ROGUE) {
|
||||
else if (botClass == Class::Rogue) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) {
|
||||
if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) {
|
||||
@@ -1765,7 +1763,7 @@ bool Bot::AI_EngagedCastCheck() {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (botClass == WARRIOR) {
|
||||
else if (botClass == Class::Warrior) {
|
||||
if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) {
|
||||
if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) {
|
||||
@@ -2044,7 +2042,7 @@ BotSpell Bot::GetFirstBotSpellBySpellType(Bot* botCaster, uint32 spellType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((botSpellList[i].type & spellType) && CheckSpellRecastTimers(botCaster, i)) {
|
||||
if ((botSpellList[i].type & spellType) && botCaster->CheckSpellRecastTimer(botSpellList[i].spellid)) {
|
||||
result.SpellId = botSpellList[i].spellid;
|
||||
result.SpellIndex = i;
|
||||
result.ManaCost = botSpellList[i].manacost;
|
||||
@@ -2069,7 +2067,7 @@ BotSpell Bot::GetBestBotSpellForFastHeal(Bot *botCaster) {
|
||||
|
||||
for (auto botSpellListItr : botSpellList) {
|
||||
// Assuming all the spells have been loaded into this list by level and in descending order
|
||||
if (IsFastHealSpell(botSpellListItr.SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr.SpellIndex)) {
|
||||
if (IsFastHealSpell(botSpellListItr.SpellId) && botCaster->CheckSpellRecastTimer(botSpellListItr.SpellId)) {
|
||||
result.SpellId = botSpellListItr.SpellId;
|
||||
result.SpellIndex = botSpellListItr.SpellIndex;
|
||||
result.ManaCost = botSpellListItr.ManaCost;
|
||||
@@ -2106,7 +2104,7 @@ BotSpell Bot::GetBestBotSpellForHealOverTime(Bot* botCaster) {
|
||||
if (
|
||||
botSpellList[i].spellid == botSpellListItr.SpellId &&
|
||||
(botSpellList[i].type & SpellType_Heal) &&
|
||||
CheckSpellRecastTimers(botCaster, botSpellListItr.SpellIndex)
|
||||
botCaster->CheckSpellRecastTimer(botSpellListItr.SpellId)
|
||||
) {
|
||||
result.SpellId = botSpellListItr.SpellId;
|
||||
result.SpellIndex = botSpellListItr.SpellIndex;
|
||||
@@ -2139,7 +2137,7 @@ BotSpell Bot::GetBestBotSpellForPercentageHeal(Bot *botCaster) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsCompleteHealSpell(botSpellList[i].spellid) && CheckSpellRecastTimers(botCaster, i)) {
|
||||
if (IsCompleteHealSpell(botSpellList[i].spellid) && botCaster->CheckSpellRecastTimer(botSpellList[i].spellid)) {
|
||||
result.SpellId = botSpellList[i].spellid;
|
||||
result.SpellIndex = i;
|
||||
result.ManaCost = botSpellList[i].manacost;
|
||||
@@ -2163,7 +2161,7 @@ BotSpell Bot::GetBestBotSpellForRegularSingleTargetHeal(Bot* botCaster) {
|
||||
|
||||
for (std::list<BotSpell>::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) {
|
||||
// Assuming all the spells have been loaded into this list by level and in descending order
|
||||
if (IsRegularSingleTargetHealSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) {
|
||||
if (IsRegularSingleTargetHealSpell(botSpellListItr->SpellId) && botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId)) {
|
||||
result.SpellId = botSpellListItr->SpellId;
|
||||
result.SpellIndex = botSpellListItr->SpellIndex;
|
||||
result.ManaCost = botSpellListItr->ManaCost;
|
||||
@@ -2192,7 +2190,7 @@ BotSpell Bot::GetFirstBotSpellForSingleTargetHeal(Bot* botCaster) {
|
||||
IsRegularSingleTargetHealSpell(botSpellListItr->SpellId) ||
|
||||
IsFastHealSpell(botSpellListItr->SpellId)
|
||||
) &&
|
||||
CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)
|
||||
botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId)
|
||||
) {
|
||||
result.SpellId = botSpellListItr->SpellId;
|
||||
result.SpellIndex = botSpellListItr->SpellIndex;
|
||||
@@ -2219,7 +2217,7 @@ BotSpell Bot::GetBestBotSpellForGroupHeal(Bot* botCaster) {
|
||||
// Assuming all the spells have been loaded into this list by level and in descending order
|
||||
if (
|
||||
IsRegularGroupHealSpell(botSpellListItr->SpellId) &&
|
||||
CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)
|
||||
botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId)
|
||||
) {
|
||||
result.SpellId = botSpellListItr->SpellId;
|
||||
result.SpellIndex = botSpellListItr->SpellIndex;
|
||||
@@ -2257,7 +2255,7 @@ BotSpell Bot::GetBestBotSpellForGroupHealOverTime(Bot* botCaster) {
|
||||
if (
|
||||
botSpellList[i].spellid == botSpellListItr->SpellId &&
|
||||
(botSpellList[i].type & SpellType_Heal) &&
|
||||
CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)
|
||||
botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId)
|
||||
) {
|
||||
result.SpellId = botSpellListItr->SpellId;
|
||||
result.SpellIndex = botSpellListItr->SpellIndex;
|
||||
@@ -2287,7 +2285,7 @@ BotSpell Bot::GetBestBotSpellForGroupCompleteHeal(Bot* botCaster) {
|
||||
// Assuming all the spells have been loaded into this list by level and in descending order
|
||||
if (
|
||||
IsGroupCompleteHealSpell(botSpellListItr->SpellId) &&
|
||||
CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)
|
||||
botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId)
|
||||
) {
|
||||
result.SpellId = botSpellListItr->SpellId;
|
||||
result.SpellIndex = botSpellListItr->SpellIndex;
|
||||
@@ -2314,7 +2312,7 @@ BotSpell Bot::GetBestBotSpellForMez(Bot* botCaster) {
|
||||
// Assuming all the spells have been loaded into this list by level and in descending order
|
||||
if (
|
||||
IsMesmerizeSpell(botSpellListItr->SpellId) &&
|
||||
CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)
|
||||
botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId)
|
||||
) {
|
||||
result.SpellId = botSpellListItr->SpellId;
|
||||
result.SpellIndex = botSpellListItr->SpellIndex;
|
||||
@@ -2343,7 +2341,7 @@ BotSpell Bot::GetBestBotSpellForMagicBasedSlow(Bot* botCaster) {
|
||||
if (
|
||||
IsSlowSpell(botSpellListItr->SpellId) &&
|
||||
spells[botSpellListItr->SpellId].resist_type == RESIST_MAGIC &&
|
||||
CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)
|
||||
botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId)
|
||||
) {
|
||||
result.SpellId = botSpellListItr->SpellId;
|
||||
result.SpellIndex = botSpellListItr->SpellIndex;
|
||||
@@ -2371,7 +2369,7 @@ BotSpell Bot::GetBestBotSpellForDiseaseBasedSlow(Bot* botCaster) {
|
||||
if (
|
||||
IsSlowSpell(botSpellListItr->SpellId) &&
|
||||
spells[botSpellListItr->SpellId].resist_type == RESIST_DISEASE &&
|
||||
CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)
|
||||
botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId)
|
||||
) {
|
||||
result.SpellId = botSpellListItr->SpellId;
|
||||
result.SpellIndex = botSpellListItr->SpellIndex;
|
||||
@@ -2437,7 +2435,7 @@ BotSpell Bot::GetBestBotMagicianPetSpell(Bot *botCaster) {
|
||||
|
||||
for(std::list<BotSpell>::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) {
|
||||
// Assuming all the spells have been loaded into this list by level and in descending order
|
||||
if (IsSummonPetSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) {
|
||||
if (IsSummonPetSpell(botSpellListItr->SpellId) && botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId)) {
|
||||
if (!strncmp(spells[botSpellListItr->SpellId].teleport_zone, petType.c_str(), petType.length())) {
|
||||
result.SpellId = botSpellListItr->SpellId;
|
||||
result.SpellIndex = botSpellListItr->SpellIndex;
|
||||
@@ -2546,7 +2544,7 @@ BotSpell Bot::GetBestBotSpellForNukeByTargetType(Bot* botCaster, SpellTargetType
|
||||
|
||||
for(std::list<BotSpell>::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) {
|
||||
// Assuming all the spells have been loaded into this list by level and in descending order
|
||||
if ((IsPureNukeSpell(botSpellListItr->SpellId) || IsDamageSpell(botSpellListItr->SpellId)) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) {
|
||||
if ((IsPureNukeSpell(botSpellListItr->SpellId) || IsDamageSpell(botSpellListItr->SpellId)) && botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId)) {
|
||||
result.SpellId = botSpellListItr->SpellId;
|
||||
result.SpellIndex = botSpellListItr->SpellIndex;
|
||||
result.ManaCost = botSpellListItr->ManaCost;
|
||||
@@ -2574,7 +2572,7 @@ BotSpell Bot::GetBestBotSpellForStunByTargetType(Bot* botCaster, SpellTargetType
|
||||
for(std::list<BotSpell>::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr)
|
||||
{
|
||||
// Assuming all the spells have been loaded into this list by level and in descending order
|
||||
if (IsStunSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex))
|
||||
if (IsStunSpell(botSpellListItr->SpellId) && botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId))
|
||||
{
|
||||
result.SpellId = botSpellListItr->SpellId;
|
||||
result.SpellIndex = botSpellListItr->SpellIndex;
|
||||
@@ -2614,7 +2612,7 @@ BotSpell Bot::GetBestBotWizardNukeSpellByTargetResists(Bot* botCaster, Mob* targ
|
||||
// Assuming all the spells have been loaded into this list by level and in descending order
|
||||
bool spellSelected = false;
|
||||
|
||||
if (CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) {
|
||||
if (botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId)) {
|
||||
if (selectLureNuke && (spells[botSpellListItr->SpellId].resist_difficulty < lureResisValue)) {
|
||||
spellSelected = true;
|
||||
}
|
||||
@@ -2682,7 +2680,7 @@ BotSpell Bot::GetDebuffBotSpell(Bot* botCaster, Mob *tar) {
|
||||
if (((botSpellList[i].type & SpellType_Debuff) || IsDebuffSpell(botSpellList[i].spellid))
|
||||
&& (!tar->IsImmuneToSpell(botSpellList[i].spellid, botCaster)
|
||||
&& tar->CanBuffStack(botSpellList[i].spellid, botCaster->GetLevel(), true) >= 0)
|
||||
&& CheckSpellRecastTimers(botCaster, i)) {
|
||||
&& botCaster->CheckSpellRecastTimer(botSpellList[i].spellid)) {
|
||||
result.SpellId = botSpellList[i].spellid;
|
||||
result.SpellIndex = i;
|
||||
result.ManaCost = botSpellList[i].manacost;
|
||||
@@ -2735,7 +2733,7 @@ BotSpell Bot::GetBestBotSpellForResistDebuff(Bot* botCaster, Mob *tar) {
|
||||
|| (needsDiseaseResistDebuff && (IsEffectInSpell(botSpellList[i].spellid, SE_ResistDisease)) || IsEffectInSpell(botSpellList[i].spellid, SE_ResistAll)))
|
||||
&& (!tar->IsImmuneToSpell(botSpellList[i].spellid, botCaster)
|
||||
&& tar->CanBuffStack(botSpellList[i].spellid, botCaster->GetLevel(), true) >= 0)
|
||||
&& CheckSpellRecastTimers(botCaster, i)) {
|
||||
&& botCaster->CheckSpellRecastTimer(botSpellList[i].spellid)) {
|
||||
result.SpellId = botSpellList[i].spellid;
|
||||
result.SpellIndex = i;
|
||||
result.ManaCost = botSpellList[i].manacost;
|
||||
@@ -2786,31 +2784,31 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* botCaster, Mob *tar) {
|
||||
for (std::list<BotSpell_wPriority>::iterator itr = cureList.begin(); itr != cureList.end(); ++itr) {
|
||||
BotSpell selectedBotSpell = *itr;
|
||||
|
||||
if (IsGroupSpell(itr->SpellId) && CheckSpellRecastTimers(botCaster, itr->SpellIndex)) {
|
||||
if (IsGroupSpell(itr->SpellId) && botCaster->CheckSpellRecastTimer(selectedBotSpell.SpellId)) {
|
||||
if (selectedBotSpell.SpellId == 0)
|
||||
continue;
|
||||
|
||||
if (isPoisoned && IsEffectInSpell(itr->SpellId, SE_PoisonCounter)) {
|
||||
if (isPoisoned && IsEffectInSpell(selectedBotSpell.SpellId, SE_PoisonCounter)) {
|
||||
spellSelected = true;
|
||||
}
|
||||
else if (isDiseased && IsEffectInSpell(itr->SpellId, SE_DiseaseCounter)) {
|
||||
else if (isDiseased && IsEffectInSpell(selectedBotSpell.SpellId, SE_DiseaseCounter)) {
|
||||
spellSelected = true;
|
||||
}
|
||||
else if (isCursed && IsEffectInSpell(itr->SpellId, SE_CurseCounter)) {
|
||||
else if (isCursed && IsEffectInSpell(selectedBotSpell.SpellId, SE_CurseCounter)) {
|
||||
spellSelected = true;
|
||||
}
|
||||
else if (isCorrupted && IsEffectInSpell(itr->SpellId, SE_CorruptionCounter)) {
|
||||
else if (isCorrupted && IsEffectInSpell(selectedBotSpell.SpellId, SE_CorruptionCounter)) {
|
||||
spellSelected = true;
|
||||
}
|
||||
else if (IsEffectInSpell(itr->SpellId, SE_DispelDetrimental)) {
|
||||
else if (IsEffectInSpell(selectedBotSpell.SpellId, SE_DispelDetrimental)) {
|
||||
spellSelected = true;
|
||||
}
|
||||
|
||||
if (spellSelected)
|
||||
{
|
||||
result.SpellId = itr->SpellId;
|
||||
result.SpellIndex = itr->SpellIndex;
|
||||
result.ManaCost = itr->ManaCost;
|
||||
result.SpellId = selectedBotSpell.SpellId;
|
||||
result.SpellIndex = selectedBotSpell.SpellIndex;
|
||||
result.ManaCost = selectedBotSpell.ManaCost;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -2823,31 +2821,31 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* botCaster, Mob *tar) {
|
||||
for(std::list<BotSpell_wPriority>::iterator itr = cureList.begin(); itr != cureList.end(); ++itr) {
|
||||
BotSpell selectedBotSpell = *itr;
|
||||
|
||||
if (CheckSpellRecastTimers(botCaster, itr->SpellIndex)) {
|
||||
if (botCaster->CheckSpellRecastTimer(selectedBotSpell.SpellId)) {
|
||||
if (selectedBotSpell.SpellId == 0)
|
||||
continue;
|
||||
|
||||
if (isPoisoned && IsEffectInSpell(itr->SpellId, SE_PoisonCounter)) {
|
||||
if (isPoisoned && IsEffectInSpell(selectedBotSpell.SpellId, SE_PoisonCounter)) {
|
||||
spellSelected = true;
|
||||
}
|
||||
else if (isDiseased && IsEffectInSpell(itr->SpellId, SE_DiseaseCounter)) {
|
||||
else if (isDiseased && IsEffectInSpell(selectedBotSpell.SpellId, SE_DiseaseCounter)) {
|
||||
spellSelected = true;
|
||||
}
|
||||
else if (isCursed && IsEffectInSpell(itr->SpellId, SE_CurseCounter)) {
|
||||
else if (isCursed && IsEffectInSpell(selectedBotSpell.SpellId, SE_CurseCounter)) {
|
||||
spellSelected = true;
|
||||
}
|
||||
else if (isCorrupted && IsEffectInSpell(itr->SpellId, SE_CorruptionCounter)) {
|
||||
else if (isCorrupted && IsEffectInSpell(selectedBotSpell.SpellId, SE_CorruptionCounter)) {
|
||||
spellSelected = true;
|
||||
}
|
||||
else if (IsEffectInSpell(itr->SpellId, SE_DispelDetrimental)) {
|
||||
else if (IsEffectInSpell(selectedBotSpell.SpellId, SE_DispelDetrimental)) {
|
||||
spellSelected = true;
|
||||
}
|
||||
|
||||
if (spellSelected)
|
||||
{
|
||||
result.SpellId = itr->SpellId;
|
||||
result.SpellIndex = itr->SpellIndex;
|
||||
result.ManaCost = itr->ManaCost;
|
||||
result.SpellId = selectedBotSpell.SpellId;
|
||||
result.SpellIndex = selectedBotSpell.SpellIndex;
|
||||
result.ManaCost = selectedBotSpell.ManaCost;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -2859,69 +2857,6 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* botCaster, Mob *tar) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void Bot::SetSpellRecastTimer(int timer_index, int32 recast_delay) {
|
||||
if (timer_index > 0 && timer_index <= MaxSpellTimer) {
|
||||
timers[timer_index - 1] = Timer::GetCurrentTime() + recast_delay;
|
||||
}
|
||||
}
|
||||
|
||||
int32 Bot::GetSpellRecastTimer(Bot *caster, int timer_index) {
|
||||
int32 result = 0;
|
||||
if (caster) {
|
||||
if (timer_index > 0 && timer_index <= MaxSpellTimer) {
|
||||
result = caster->timers[timer_index - 1];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Bot::CheckSpellRecastTimers(Bot *caster, int SpellIndex) {
|
||||
if (caster) {
|
||||
if (caster->AIBot_spells[SpellIndex].time_cancast < Timer::GetCurrentTime()) { //checks spell recast
|
||||
if (GetSpellRecastTimer(caster, spells[caster->AIBot_spells[SpellIndex].spellid].timer_id) < Timer::GetCurrentTime()) { //checks for spells on the same timer
|
||||
return true; //can cast spell
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Bot::SetDisciplineRecastTimer(int timer_index, int32 recast_delay) {
|
||||
if (timer_index > 0 && timer_index <= MaxDisciplineTimer) {
|
||||
timers[DisciplineReuseStart + timer_index - 1] = Timer::GetCurrentTime() + recast_delay;
|
||||
}
|
||||
}
|
||||
|
||||
int32 Bot::GetDisciplineRecastTimer(Bot *caster, int timer_index) {
|
||||
int32 result = 0;
|
||||
if (caster) {
|
||||
if (timer_index > 0 && timer_index <= MaxDisciplineTimer) {
|
||||
result = caster->timers[DisciplineReuseStart + timer_index - 1];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32 Bot::GetDisciplineRemainingTime(Bot *caster, int timer_index) {
|
||||
int32 result = 0;
|
||||
if (caster) {
|
||||
if (timer_index > 0 && timer_index <= MaxDisciplineTimer) {
|
||||
if (GetDisciplineRecastTimer(caster, timer_index) > Timer::GetCurrentTime())
|
||||
result = GetDisciplineRecastTimer(caster, timer_index) - Timer::GetCurrentTime();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Bot::CheckDisciplineRecastTimers(Bot *caster, int timer_index) {
|
||||
if (caster) {
|
||||
if (GetDisciplineRecastTimer(caster, timer_index) < Timer::GetCurrentTime()) { //checks for spells on the same timer
|
||||
return true; //can cast spell
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8 Bot::GetChanceToCastBySpellType(uint32 spellType)
|
||||
{
|
||||
uint8 spell_type_index = SPELL_TYPE_COUNT;
|
||||
@@ -3000,7 +2935,7 @@ uint8 Bot::GetChanceToCastBySpellType(uint32 spellType)
|
||||
return 0;
|
||||
|
||||
uint8 class_index = GetClass();
|
||||
if (class_index > BERSERKER || class_index < WARRIOR)
|
||||
if (class_index > Class::Berserker || class_index < Class::Warrior)
|
||||
return 0;
|
||||
--class_index;
|
||||
|
||||
|
||||
+346
-187
@@ -65,6 +65,7 @@ extern volatile bool RunLoops;
|
||||
#include "../common/repositories/character_disciplines_repository.h"
|
||||
#include "../common/repositories/character_data_repository.h"
|
||||
#include "../common/repositories/discovered_items_repository.h"
|
||||
#include "../common/repositories/keyring_repository.h"
|
||||
#include "../common/events/player_events.h"
|
||||
#include "../common/events/player_event_logs.h"
|
||||
#include "dialogue_window.h"
|
||||
@@ -1410,126 +1411,163 @@ void Client::SetMaxHP() {
|
||||
Save();
|
||||
}
|
||||
|
||||
bool Client::UpdateLDoNPoints(uint32 theme_id, int points) {
|
||||
|
||||
/* make sure total stays in sync with individual buckets
|
||||
m_pp.ldon_points_available = m_pp.ldon_points_guk
|
||||
+m_pp.ldon_points_mir
|
||||
+m_pp.ldon_points_mmc
|
||||
+m_pp.ldon_points_ruj
|
||||
+m_pp.ldon_points_tak; */
|
||||
|
||||
if(points < 0) {
|
||||
if(m_pp.ldon_points_available < (0 - points))
|
||||
bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
|
||||
{
|
||||
if (points < 0) {
|
||||
if (m_pp.ldon_points_available < (0 - points)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_loss = false;
|
||||
|
||||
switch (theme_id) {
|
||||
case LDoNThemes::Unused: { // No theme, so distribute evenly across all
|
||||
int split_points = (points / 5);
|
||||
|
||||
int guk_points = (split_points + (points % 5));
|
||||
int mir_points = split_points;
|
||||
int mmc_points = split_points;
|
||||
int ruj_points = split_points;
|
||||
int tak_points = split_points;
|
||||
|
||||
split_points = 0;
|
||||
if(points < 0) {
|
||||
if(m_pp.ldon_points_available < (0 - points)) {
|
||||
|
||||
if (points < 0) {
|
||||
if (m_pp.ldon_points_available < (0 - points)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_pp.ldon_points_guk < (0 - guk_points)) {
|
||||
is_loss = true;
|
||||
|
||||
if (m_pp.ldon_points_guk < (0 - guk_points)) {
|
||||
mir_points += (guk_points + m_pp.ldon_points_guk);
|
||||
guk_points = (0 - m_pp.ldon_points_guk);
|
||||
}
|
||||
|
||||
if(m_pp.ldon_points_mir < (0 - mir_points)) {
|
||||
if (m_pp.ldon_points_mir < (0 - mir_points)) {
|
||||
mmc_points += (mir_points + m_pp.ldon_points_mir);
|
||||
mir_points = (0 - m_pp.ldon_points_mir);
|
||||
}
|
||||
|
||||
if(m_pp.ldon_points_mmc < (0 - mmc_points)) {
|
||||
if (m_pp.ldon_points_mmc < (0 - mmc_points)) {
|
||||
ruj_points += (mmc_points + m_pp.ldon_points_mmc);
|
||||
mmc_points = (0 - m_pp.ldon_points_mmc);
|
||||
}
|
||||
|
||||
if(m_pp.ldon_points_ruj < (0 - ruj_points)) {
|
||||
if (m_pp.ldon_points_ruj < (0 - ruj_points)) {
|
||||
tak_points += (ruj_points + m_pp.ldon_points_ruj);
|
||||
ruj_points = (0 - m_pp.ldon_points_ruj);
|
||||
}
|
||||
|
||||
if(m_pp.ldon_points_tak < (0 - tak_points)) {
|
||||
if (m_pp.ldon_points_tak < (0 - tak_points)) {
|
||||
split_points = (tak_points + m_pp.ldon_points_tak);
|
||||
tak_points = (0 - m_pp.ldon_points_tak);
|
||||
tak_points = (0 - m_pp.ldon_points_tak);
|
||||
}
|
||||
}
|
||||
|
||||
m_pp.ldon_points_guk += guk_points;
|
||||
m_pp.ldon_points_mir += mir_points;
|
||||
m_pp.ldon_points_mmc += mmc_points;
|
||||
m_pp.ldon_points_ruj += ruj_points;
|
||||
m_pp.ldon_points_tak += tak_points;
|
||||
|
||||
points -= split_points;
|
||||
|
||||
if (split_points != 0) { // if anything left, recursively loop thru again
|
||||
UpdateLDoNPoints(0, split_points);
|
||||
UpdateLDoNPoints(LDoNThemes::Unused, split_points);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case LDoNThemes::GUK: {
|
||||
if(points < 0) {
|
||||
if(m_pp.ldon_points_guk < (0 - points)) {
|
||||
case LDoNThemes::GUK: {
|
||||
if (points < 0) {
|
||||
if (m_pp.ldon_points_guk < (0 - points)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
is_loss = true;
|
||||
}
|
||||
|
||||
m_pp.ldon_points_guk += points;
|
||||
break;
|
||||
}
|
||||
case LDoNThemes::MIR: {
|
||||
if(points < 0) {
|
||||
if(m_pp.ldon_points_mir < (0 - points)) {
|
||||
if (points < 0) {
|
||||
if (m_pp.ldon_points_mir < (0 - points)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
is_loss = true;
|
||||
}
|
||||
|
||||
m_pp.ldon_points_mir += points;
|
||||
break;
|
||||
}
|
||||
case LDoNThemes::MMC: {
|
||||
if(points < 0) {
|
||||
if(m_pp.ldon_points_mmc < (0 - points)) {
|
||||
if (points < 0) {
|
||||
if (m_pp.ldon_points_mmc < (0 - points)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
is_loss = true;
|
||||
}
|
||||
|
||||
m_pp.ldon_points_mmc += points;
|
||||
break;
|
||||
}
|
||||
case LDoNThemes::RUJ: {
|
||||
if(points < 0) {
|
||||
if(m_pp.ldon_points_ruj < (0 - points)) {
|
||||
if (points < 0) {
|
||||
if (m_pp.ldon_points_ruj < (0 - points)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
is_loss = true;
|
||||
}
|
||||
|
||||
m_pp.ldon_points_ruj += points;
|
||||
break;
|
||||
}
|
||||
case LDoNThemes::TAK: {
|
||||
if(points < 0) {
|
||||
if(m_pp.ldon_points_tak < (0 - points)) {
|
||||
if (points < 0) {
|
||||
if (m_pp.ldon_points_tak < (0 - points)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
is_loss = true;
|
||||
}
|
||||
|
||||
m_pp.ldon_points_tak += points;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_pp.ldon_points_available += points;
|
||||
|
||||
QuestEventID event_id = is_loss ? EVENT_LDON_POINTS_LOSS : EVENT_LDON_POINTS_GAIN;
|
||||
|
||||
if (parse->PlayerHasQuestSub(event_id)) {
|
||||
const std::string &export_string = fmt::format(
|
||||
"{} {}",
|
||||
theme_id,
|
||||
std::abs(points)
|
||||
);
|
||||
|
||||
parse->EventPlayer(event_id, this, export_string, 0);
|
||||
}
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_AdventurePointsUpdate, sizeof(AdventurePoints_Update_Struct));
|
||||
AdventurePoints_Update_Struct* apus = (AdventurePoints_Update_Struct*)outapp->pBuffer;
|
||||
auto *apus = (AdventurePoints_Update_Struct *) outapp->pBuffer;
|
||||
|
||||
apus->ldon_available_points = m_pp.ldon_points_available;
|
||||
apus->ldon_guk_points = m_pp.ldon_points_guk;
|
||||
apus->ldon_mirugal_points = m_pp.ldon_points_mir;
|
||||
apus->ldon_guk_points = m_pp.ldon_points_guk;
|
||||
apus->ldon_mirugal_points = m_pp.ldon_points_mir;
|
||||
apus->ldon_mistmoore_points = m_pp.ldon_points_mmc;
|
||||
apus->ldon_rujarkian_points = m_pp.ldon_points_ruj;
|
||||
apus->ldon_takish_points = m_pp.ldon_points_tak;
|
||||
apus->ldon_takish_points = m_pp.ldon_points_tak;
|
||||
|
||||
outapp->priority = 6;
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
return true;
|
||||
@@ -2262,10 +2300,10 @@ void Client::QuestReadBook(const char* text, uint8 type) {
|
||||
|
||||
uint32 Client::GetCarriedPlatinum() {
|
||||
return (
|
||||
GetMoney(3, 0) +
|
||||
(GetMoney(2, 0) / 10) +
|
||||
(GetMoney(1, 0) / 100) +
|
||||
(GetMoney(0, 0) / 1000)
|
||||
GetMoney(MoneyTypes::Platinum, MoneySubtypes::Personal) +
|
||||
(GetMoney(MoneyTypes::Gold, MoneySubtypes::Personal) / 10) +
|
||||
(GetMoney(MoneyTypes::Silver, MoneySubtypes::Personal) / 100) +
|
||||
(GetMoney(MoneyTypes::Copper, MoneySubtypes::Personal) / 1000)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2675,7 +2713,7 @@ bool Client::HasSkill(EQ::skills::SkillType skill_id) const {
|
||||
}
|
||||
|
||||
bool Client::CanHaveSkill(EQ::skills::SkillType skill_id) const {
|
||||
if (ClientVersion() < EQ::versions::ClientVersion::RoF2 && class_ == BERSERKER && skill_id == EQ::skills::Skill1HPiercing)
|
||||
if (ClientVersion() < EQ::versions::ClientVersion::RoF2 && class_ == Class::Berserker && skill_id == EQ::skills::Skill1HPiercing)
|
||||
skill_id = EQ::skills::Skill2HPiercing;
|
||||
|
||||
return(content_db.GetSkillCap(GetClass(), skill_id, RuleI(Character, MaxLevel)) > 0);
|
||||
@@ -2683,7 +2721,7 @@ bool Client::CanHaveSkill(EQ::skills::SkillType skill_id) const {
|
||||
}
|
||||
|
||||
uint16 Client::MaxSkill(EQ::skills::SkillType skillid, uint16 class_, uint16 level) const {
|
||||
if (ClientVersion() < EQ::versions::ClientVersion::RoF2 && class_ == BERSERKER && skillid == EQ::skills::Skill1HPiercing)
|
||||
if (ClientVersion() < EQ::versions::ClientVersion::RoF2 && class_ == Class::Berserker && skillid == EQ::skills::Skill1HPiercing)
|
||||
skillid = EQ::skills::Skill2HPiercing;
|
||||
|
||||
return(content_db.GetSkillCap(class_, skillid, level));
|
||||
@@ -2691,7 +2729,7 @@ uint16 Client::MaxSkill(EQ::skills::SkillType skillid, uint16 class_, uint16 lev
|
||||
|
||||
uint8 Client::SkillTrainLevel(EQ::skills::SkillType skillid, uint16 class_)
|
||||
{
|
||||
if (ClientVersion() < EQ::versions::ClientVersion::RoF2 && class_ == BERSERKER && skillid == EQ::skills::Skill1HPiercing)
|
||||
if (ClientVersion() < EQ::versions::ClientVersion::RoF2 && class_ == Class::Berserker && skillid == EQ::skills::Skill1HPiercing)
|
||||
skillid = EQ::skills::Skill2HPiercing;
|
||||
|
||||
return(content_db.GetTrainLevel(class_, skillid, RuleI(Character, MaxLevel)));
|
||||
@@ -3027,7 +3065,7 @@ bool Client::BindWound(Mob *bindmob, bool start, bool fail)
|
||||
|
||||
int max_percent = 50 + maxHPBonus;
|
||||
|
||||
if (GetClass() == MONK && GetSkill(EQ::skills::SkillBindWound) > 200) {
|
||||
if (GetClass() == Class::Monk && GetSkill(EQ::skills::SkillBindWound) > 200) {
|
||||
max_percent = 70 + maxHPBonus;
|
||||
}
|
||||
|
||||
@@ -3076,9 +3114,9 @@ bool Client::BindWound(Mob *bindmob, bool start, bool fail)
|
||||
else {
|
||||
int percent_base = 50;
|
||||
if (GetRawSkill(EQ::skills::SkillBindWound) > 200) {
|
||||
if ((GetClass() == MONK) || (GetClass() == BEASTLORD))
|
||||
if ((GetClass() == Class::Monk) || (GetClass() == Class::Beastlord))
|
||||
percent_base = 70;
|
||||
else if ((GetLevel() > 50) && ((GetClass() == WARRIOR) || (GetClass() == ROGUE) || (GetClass() == CLERIC)))
|
||||
else if ((GetLevel() > 50) && ((GetClass() == Class::Warrior) || (GetClass() == Class::Rogue) || (GetClass() == Class::Cleric)))
|
||||
percent_base = 70;
|
||||
}
|
||||
|
||||
@@ -4087,54 +4125,87 @@ void Client::SendWindow(
|
||||
|
||||
void Client::KeyRingLoad()
|
||||
{
|
||||
std::string query = StringFormat("SELECT item_id FROM keyring "
|
||||
"WHERE char_id = '%i' ORDER BY item_id", character_id);
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
const auto &l = KeyringRepository::GetWhere(
|
||||
database,
|
||||
fmt::format(
|
||||
"`char_id` = {} ORDER BY `item_id`",
|
||||
character_id
|
||||
)
|
||||
);
|
||||
|
||||
if (l.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
keyring.push_back(Strings::ToInt(row[0]));
|
||||
|
||||
for (const auto &e : l) {
|
||||
keyring.emplace_back(e.item_id);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::KeyRingAdd(uint32 item_id)
|
||||
{
|
||||
if(0==item_id)
|
||||
return;
|
||||
|
||||
bool found = KeyRingCheck(item_id);
|
||||
if (found)
|
||||
return;
|
||||
|
||||
std::string query = StringFormat("INSERT INTO keyring(char_id, item_id) VALUES(%i, %i)", character_id, item_id);
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
if (!item_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
Message(Chat::LightBlue,"Added to keyring.");
|
||||
const bool found = KeyRingCheck(item_id);
|
||||
if (found) {
|
||||
return;
|
||||
}
|
||||
|
||||
keyring.push_back(item_id);
|
||||
auto e = KeyringRepository::NewEntity();
|
||||
|
||||
e.char_id = CharacterID();
|
||||
e.item_id = item_id;
|
||||
|
||||
e = KeyringRepository::InsertOne(database, e);
|
||||
|
||||
if (!e.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
keyring.emplace_back(item_id);
|
||||
|
||||
if (!RuleB(World, UseItemLinksForKeyRing)) {
|
||||
Message(Chat::LightBlue, "Added to keyring.");
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string &item_link = database.CreateItemLink(item_id);
|
||||
|
||||
Message(
|
||||
Chat::LightBlue,
|
||||
fmt::format(
|
||||
"Added {} to keyring.",
|
||||
item_link
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
bool Client::KeyRingCheck(uint32 item_id)
|
||||
{
|
||||
for (auto iter = keyring.begin(); iter != keyring.end(); ++iter) {
|
||||
if(*iter == item_id)
|
||||
for (const auto &e : keyring) {
|
||||
if (e == item_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Client::KeyRingList()
|
||||
{
|
||||
Message(Chat::LightBlue,"Keys on Keyring:");
|
||||
Message(Chat::LightBlue, "Keys on Keyring:");
|
||||
|
||||
const EQ::ItemData *item = nullptr;
|
||||
for (auto iter = keyring.begin(); iter != keyring.end(); ++iter) {
|
||||
if ((item = database.GetItem(*iter))!=nullptr) {
|
||||
Message(Chat::LightBlue,item->Name);
|
||||
|
||||
for (const auto &e : keyring) {
|
||||
item = database.GetItem(e);
|
||||
if (item) {
|
||||
const std::string &item_string = RuleB(World, UseItemLinksForKeyRing) ? database.CreateItemLink(e) : item->Name;
|
||||
|
||||
Message(Chat::LightBlue, item_string.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4198,7 +4269,7 @@ void Client::UpdateLFP() {
|
||||
|
||||
for(unsigned int i=0; i<MAX_GROUP_MEMBERS; i++) {
|
||||
LFPMembers[i].Name[0] = '\0';
|
||||
LFPMembers[i].Class = NO_CLASS;
|
||||
LFPMembers[i].Class = Class::None;
|
||||
LFPMembers[i].Level = 0;
|
||||
LFPMembers[i].Zone = 0;
|
||||
}
|
||||
@@ -4815,7 +4886,7 @@ void Client::HandleLDoNOpen(NPC *target)
|
||||
{
|
||||
if(target)
|
||||
{
|
||||
if(target->GetClass() != LDON_TREASURE)
|
||||
if(target->GetClass() != Class::LDoNTreasure)
|
||||
{
|
||||
LogDebug("[{}] tried to open [{}] but [{}] was not a treasure chest",
|
||||
GetName(), target->GetName(), target->GetName());
|
||||
@@ -4884,7 +4955,7 @@ void Client::HandleLDoNOpen(NPC *target)
|
||||
|
||||
void Client::HandleLDoNSenseTraps(NPC *target, uint16 skill, uint8 type)
|
||||
{
|
||||
if(target && target->GetClass() == LDON_TREASURE)
|
||||
if(target && target->GetClass() == Class::LDoNTreasure)
|
||||
{
|
||||
if(target->IsLDoNTrapped())
|
||||
{
|
||||
@@ -4927,7 +4998,7 @@ void Client::HandleLDoNDisarm(NPC *target, uint16 skill, uint8 type)
|
||||
{
|
||||
if(target)
|
||||
{
|
||||
if(target->GetClass() == LDON_TREASURE)
|
||||
if(target->GetClass() == Class::LDoNTreasure)
|
||||
{
|
||||
if(!target->IsLDoNTrapped())
|
||||
{
|
||||
@@ -4977,7 +5048,7 @@ void Client::HandleLDoNPickLock(NPC *target, uint16 skill, uint8 type)
|
||||
{
|
||||
if(target)
|
||||
{
|
||||
if(target->GetClass() == LDON_TREASURE)
|
||||
if(target->GetClass() == Class::LDoNTreasure)
|
||||
{
|
||||
if(target->IsLDoNTrapped())
|
||||
{
|
||||
@@ -5656,26 +5727,89 @@ void Client::AddPVPPoints(uint32 Points)
|
||||
SendPVPStats();
|
||||
}
|
||||
|
||||
void Client::AddCrystals(uint32 radiant, uint32 ebon)
|
||||
{
|
||||
m_pp.currentRadCrystals += radiant;
|
||||
m_pp.careerRadCrystals += radiant;
|
||||
m_pp.currentEbonCrystals += ebon;
|
||||
m_pp.careerEbonCrystals += ebon;
|
||||
void Client::AddEbonCrystals(uint32 amount, bool is_reclaim) {
|
||||
m_pp.currentEbonCrystals += amount;
|
||||
m_pp.careerEbonCrystals += amount;
|
||||
|
||||
SaveCurrency();
|
||||
|
||||
SendCrystalCounts();
|
||||
|
||||
// newer clients handle message client side (older clients likely used eqstr 5967 and 5968, this matches live)
|
||||
if (radiant > 0)
|
||||
{
|
||||
MessageString(Chat::Yellow, YOU_RECEIVE, fmt::format("{} Radiant Crystals", radiant).c_str());
|
||||
}
|
||||
MessageString(
|
||||
Chat::Yellow,
|
||||
YOU_RECEIVE,
|
||||
fmt::format(
|
||||
"{} {}",
|
||||
amount,
|
||||
database.CreateItemLink(RuleI(Zone, EbonCrystalItemID))
|
||||
).c_str()
|
||||
);
|
||||
|
||||
if (ebon > 0)
|
||||
{
|
||||
MessageString(Chat::Yellow, YOU_RECEIVE, fmt::format("{} Ebon Crystals", ebon).c_str());
|
||||
if (parse->PlayerHasQuestSub(EVENT_CRYSTAL_GAIN)) {
|
||||
const std::string &export_string = fmt::format(
|
||||
"{} 0 {}",
|
||||
amount,
|
||||
is_reclaim ? 1 : 0
|
||||
);
|
||||
parse->EventPlayer(EVENT_CRYSTAL_GAIN, this, export_string, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::AddRadiantCrystals(uint32 amount, bool is_reclaim) {
|
||||
m_pp.currentRadCrystals += amount;
|
||||
m_pp.careerRadCrystals += amount;
|
||||
|
||||
SaveCurrency();
|
||||
SendCrystalCounts();
|
||||
|
||||
MessageString(
|
||||
Chat::Yellow,
|
||||
YOU_RECEIVE,
|
||||
fmt::format(
|
||||
"{} {}",
|
||||
amount,
|
||||
database.CreateItemLink(RuleI(Zone, RadiantCrystalItemID))
|
||||
).c_str()
|
||||
);
|
||||
|
||||
if (parse->PlayerHasQuestSub(EVENT_CRYSTAL_GAIN)) {
|
||||
const std::string &export_string = fmt::format(
|
||||
"0 {} {}",
|
||||
amount,
|
||||
is_reclaim ? 1 : 0
|
||||
);
|
||||
parse->EventPlayer(EVENT_CRYSTAL_GAIN, this, export_string, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::RemoveEbonCrystals(uint32 amount, bool is_reclaim) {
|
||||
m_pp.currentEbonCrystals -= amount;
|
||||
|
||||
SaveCurrency();
|
||||
SendCrystalCounts();
|
||||
|
||||
if (parse->PlayerHasQuestSub(EVENT_CRYSTAL_LOSS)) {
|
||||
const std::string &export_string = fmt::format(
|
||||
"{} 0 {}",
|
||||
amount,
|
||||
is_reclaim ? 1 : 0
|
||||
);
|
||||
parse->EventPlayer(EVENT_CRYSTAL_LOSS, this, export_string, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::RemoveRadiantCrystals(uint32 amount, bool is_reclaim) {
|
||||
m_pp.currentRadCrystals -= amount;
|
||||
|
||||
SaveCurrency();
|
||||
SendCrystalCounts();
|
||||
|
||||
if (parse->PlayerHasQuestSub(EVENT_CRYSTAL_LOSS)) {
|
||||
const std::string &export_string = fmt::format(
|
||||
"0 {} {}",
|
||||
amount,
|
||||
is_reclaim ? 1 : 0
|
||||
);
|
||||
parse->EventPlayer(EVENT_CRYSTAL_LOSS, this, export_string, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6038,7 +6172,7 @@ void Client::CheckEmoteHail(NPC* n, const char* message)
|
||||
|
||||
const auto emote_id = n->GetEmoteID();
|
||||
if (emote_id) {
|
||||
n->DoNPCEmote(EQ::constants::EmoteEventTypes::Hailed, emote_id);
|
||||
n->DoNPCEmote(EQ::constants::EmoteEventTypes::Hailed, emote_id, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6420,11 +6554,10 @@ void Client::SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount)
|
||||
SendAlternateCurrencyValue(currency_id);
|
||||
}
|
||||
|
||||
int Client::AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method)
|
||||
int Client::AddAlternateCurrencyValue(uint32 currency_id, int amount, bool is_scripted)
|
||||
{
|
||||
|
||||
/* Added via Quest, rest of the logging methods may be done inline due to information available in that area of the code */
|
||||
if (method == 1){
|
||||
if (is_scripted) {
|
||||
/* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */
|
||||
if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)){
|
||||
std::string event_desc = StringFormat("Added via Quest :: Cursor to Item :: alt_currency_id:%i amount:%i in zoneid:%i instid:%i", currency_id, GetZoneID(), GetInstanceID());
|
||||
@@ -6432,32 +6565,47 @@ int Client::AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 met
|
||||
}
|
||||
}
|
||||
|
||||
if(amount == 0) {
|
||||
if (!amount) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!alternate_currency_loaded) {
|
||||
if (!alternate_currency_loaded) {
|
||||
alternate_currency_queued_operations.push(std::make_pair(currency_id, amount));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int new_value = 0;
|
||||
auto iter = alternate_currency.find(currency_id);
|
||||
if(iter == alternate_currency.end()) {
|
||||
if (iter == alternate_currency.end()) {
|
||||
new_value = amount;
|
||||
} else {
|
||||
new_value = (*iter).second + amount;
|
||||
}
|
||||
|
||||
if(new_value < 0) {
|
||||
if (new_value < 0) {
|
||||
new_value = 0;
|
||||
alternate_currency[currency_id] = 0;
|
||||
database.UpdateAltCurrencyValue(CharacterID(), currency_id, 0);
|
||||
} else {
|
||||
alternate_currency[currency_id] = new_value;
|
||||
database.UpdateAltCurrencyValue(CharacterID(), currency_id, new_value);
|
||||
}
|
||||
|
||||
SendAlternateCurrencyValue(currency_id);
|
||||
|
||||
QuestEventID event_id = amount > 0 ? EVENT_ALT_CURRENCY_GAIN : EVENT_ALT_CURRENCY_LOSS;
|
||||
|
||||
if (parse->PlayerHasQuestSub(event_id)) {
|
||||
const std::string &export_string = fmt::format(
|
||||
"{} {} {}",
|
||||
currency_id,
|
||||
std::abs(amount),
|
||||
new_value
|
||||
);
|
||||
|
||||
parse->EventPlayer(event_id, this, export_string, 0);
|
||||
}
|
||||
|
||||
return new_value;
|
||||
}
|
||||
|
||||
@@ -8119,16 +8267,17 @@ void Client::SendHPUpdateMarquee(){
|
||||
|
||||
uint32 Client::GetMoney(uint8 type, uint8 subtype) {
|
||||
uint32 value = 0;
|
||||
|
||||
switch (type) {
|
||||
case 0: {
|
||||
case MoneyTypes::Copper: {
|
||||
switch (subtype) {
|
||||
case 0:
|
||||
case MoneySubtypes::Personal:
|
||||
value = static_cast<uint32>(m_pp.copper);
|
||||
break;
|
||||
case 1:
|
||||
case MoneySubtypes::Bank:
|
||||
value = static_cast<uint32>(m_pp.copper_bank);
|
||||
break;
|
||||
case 2:
|
||||
case MoneySubtypes::Cursor:
|
||||
value = static_cast<uint32>(m_pp.copper_cursor);
|
||||
break;
|
||||
default:
|
||||
@@ -8136,15 +8285,15 @@ uint32 Client::GetMoney(uint8 type, uint8 subtype) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
case MoneyTypes::Silver: {
|
||||
switch (subtype) {
|
||||
case 0:
|
||||
case MoneySubtypes::Personal:
|
||||
value = static_cast<uint32>(m_pp.silver);
|
||||
break;
|
||||
case 1:
|
||||
case MoneySubtypes::Bank:
|
||||
value = static_cast<uint32>(m_pp.silver_bank);
|
||||
break;
|
||||
case 2:
|
||||
case MoneySubtypes::Cursor:
|
||||
value = static_cast<uint32>(m_pp.silver_cursor);
|
||||
break;
|
||||
default:
|
||||
@@ -8152,15 +8301,15 @@ uint32 Client::GetMoney(uint8 type, uint8 subtype) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
case MoneyTypes::Gold: {
|
||||
switch (subtype) {
|
||||
case 0:
|
||||
case MoneySubtypes::Personal:
|
||||
value = static_cast<uint32>(m_pp.gold);
|
||||
break;
|
||||
case 1:
|
||||
case MoneySubtypes::Bank:
|
||||
value = static_cast<uint32>(m_pp.gold_bank);
|
||||
break;
|
||||
case 2:
|
||||
case MoneySubtypes::Cursor:
|
||||
value = static_cast<uint32>(m_pp.gold_cursor);
|
||||
break;
|
||||
default:
|
||||
@@ -8168,18 +8317,18 @@ uint32 Client::GetMoney(uint8 type, uint8 subtype) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
case MoneyTypes::Platinum: {
|
||||
switch (subtype) {
|
||||
case 0:
|
||||
case MoneySubtypes::Personal:
|
||||
value = static_cast<uint32>(m_pp.platinum);
|
||||
break;
|
||||
case 1:
|
||||
case MoneySubtypes::Bank:
|
||||
value = static_cast<uint32>(m_pp.platinum_bank);
|
||||
break;
|
||||
case 2:
|
||||
case MoneySubtypes::Cursor:
|
||||
value = static_cast<uint32>(m_pp.platinum_cursor);
|
||||
break;
|
||||
case 3:
|
||||
case MoneySubtypes::SharedBank:
|
||||
value = static_cast<uint32>(m_pp.platinum_shared);
|
||||
break;
|
||||
default:
|
||||
@@ -8190,6 +8339,7 @@ uint32 Client::GetMoney(uint8 type, uint8 subtype) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -8482,8 +8632,8 @@ void Client::InitInnates()
|
||||
m_pp.InnateSkills[InnateInspect] = InnateEnabled;
|
||||
m_pp.InnateSkills[InnateOpen] = InnateEnabled;
|
||||
|
||||
if (race >= RT_FROGLOK_3) {
|
||||
if (race == RT_SKELETON_2 || race == RT_FROGLOK_3) {
|
||||
if (race >= Race::Froglok2) {
|
||||
if (race == Race::Skeleton2 || race == Race::Froglok2) {
|
||||
m_pp.InnateSkills[InnateUltraVision] = InnateEnabled;
|
||||
} else {
|
||||
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
|
||||
@@ -8491,75 +8641,75 @@ void Client::InitInnates()
|
||||
}
|
||||
|
||||
switch (race) {
|
||||
case RT_BARBARIAN:
|
||||
case RT_BARBARIAN_2:
|
||||
case Race::Barbarian:
|
||||
case Race::HalasCitizen:
|
||||
m_pp.InnateSkills[InnateSlam] = InnateEnabled;
|
||||
break;
|
||||
case RT_ERUDITE:
|
||||
case RT_ERUDITE_2:
|
||||
case Race::Erudite:
|
||||
case Race::EruditeCitizen:
|
||||
m_pp.InnateSkills[InnateLore] = InnateEnabled;
|
||||
break;
|
||||
case RT_WOOD_ELF:
|
||||
case RT_GUARD_3:
|
||||
case Race::WoodElf:
|
||||
case Race::Fayguard:
|
||||
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
|
||||
break;
|
||||
case RT_GNOME:
|
||||
case RT_HIGH_ELF:
|
||||
case RT_GUARD_2:
|
||||
case Race::Gnome:
|
||||
case Race::HighElf:
|
||||
case Race::Felguard:
|
||||
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
|
||||
m_pp.InnateSkills[InnateLore] = InnateEnabled;
|
||||
break;
|
||||
case RT_TROLL:
|
||||
case RT_TROLL_2:
|
||||
case Race::Troll:
|
||||
case Race::GrobbCitizen:
|
||||
m_pp.InnateSkills[InnateRegen] = InnateEnabled;
|
||||
m_pp.InnateSkills[InnateSlam] = InnateEnabled;
|
||||
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
|
||||
break;
|
||||
case RT_DWARF:
|
||||
case RT_DWARF_2:
|
||||
case Race::Dwarf:
|
||||
case Race::KaladimCitizen:
|
||||
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
|
||||
break;
|
||||
case RT_OGRE:
|
||||
case RT_OGRE_2:
|
||||
case Race::Ogre:
|
||||
case Race::OggokCitizen:
|
||||
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
|
||||
m_pp.InnateSkills[InnateSlam] = InnateEnabled;
|
||||
m_pp.InnateSkills[InnateNoBash] = InnateEnabled;
|
||||
m_pp.InnateSkills[InnateBashDoor] = InnateEnabled;
|
||||
break;
|
||||
case RT_HALFLING:
|
||||
case RT_HALFLING_2:
|
||||
case Race::Halfling:
|
||||
case Race::RivervaleCitizen:
|
||||
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
|
||||
break;
|
||||
case RT_IKSAR:
|
||||
case Race::Iksar:
|
||||
m_pp.InnateSkills[InnateRegen] = InnateEnabled;
|
||||
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
|
||||
break;
|
||||
case RT_VAH_SHIR:
|
||||
case Race::VahShir:
|
||||
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
|
||||
break;
|
||||
case RT_DARK_ELF:
|
||||
case RT_DARK_ELF_2:
|
||||
case RT_VAMPIRE_2:
|
||||
case RT_FROGLOK_2:
|
||||
case RT_GHOST:
|
||||
case RT_GHOUL:
|
||||
case RT_SKELETON:
|
||||
case RT_VAMPIRE:
|
||||
case RT_WILL_O_WISP:
|
||||
case RT_ZOMBIE:
|
||||
case RT_SPECTRE:
|
||||
case RT_GHOST_2:
|
||||
case RT_GHOST_3:
|
||||
case RT_DRAGON_2:
|
||||
case RT_INNORUUK:
|
||||
case Race::DarkElf:
|
||||
case Race::NeriakCitizen:
|
||||
case Race::ElfVampire:
|
||||
case Race::FroglokGhoul:
|
||||
case Race::Ghost:
|
||||
case Race::Ghoul:
|
||||
case Race::Skeleton:
|
||||
case Race::Vampire:
|
||||
case Race::Wisp:
|
||||
case Race::Zombie:
|
||||
case Race::Spectre:
|
||||
case Race::DwarfGhost:
|
||||
case Race::EruditeGhost:
|
||||
case Race::DragonSkeleton:
|
||||
case Race::Innoruuk:
|
||||
m_pp.InnateSkills[InnateUltraVision] = InnateEnabled;
|
||||
break;
|
||||
case RT_HUMAN:
|
||||
case RT_GUARD:
|
||||
case RT_BEGGAR:
|
||||
case RT_HUMAN_2:
|
||||
case RT_HUMAN_3:
|
||||
case RT_FROGLOK_3: // client does froglok weird, but this should work out fine
|
||||
case Race::Human:
|
||||
case Race::FreeportGuard:
|
||||
case Race::HumanBeggar:
|
||||
case Race::HighpassCitizen:
|
||||
case Race::QeynosCitizen:
|
||||
case Race::Froglok2: // client does froglok weird, but this should work out fine
|
||||
break;
|
||||
default:
|
||||
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
|
||||
@@ -8567,20 +8717,20 @@ void Client::InitInnates()
|
||||
}
|
||||
|
||||
switch (class_) {
|
||||
case DRUID:
|
||||
case Class::Druid:
|
||||
m_pp.InnateSkills[InnateHarmony] = InnateEnabled;
|
||||
break;
|
||||
case BARD:
|
||||
case Class::Bard:
|
||||
m_pp.InnateSkills[InnateReveal] = InnateEnabled;
|
||||
break;
|
||||
case ROGUE:
|
||||
case Class::Rogue:
|
||||
m_pp.InnateSkills[InnateSurprise] = InnateEnabled;
|
||||
m_pp.InnateSkills[InnateReveal] = InnateEnabled;
|
||||
break;
|
||||
case RANGER:
|
||||
case Class::Ranger:
|
||||
m_pp.InnateSkills[InnateAwareness] = InnateEnabled;
|
||||
break;
|
||||
case MONK:
|
||||
case Class::Monk:
|
||||
m_pp.InnateSkills[InnateSurprise] = InnateEnabled;
|
||||
m_pp.InnateSkills[InnateAwareness] = InnateEnabled;
|
||||
default:
|
||||
@@ -9718,7 +9868,7 @@ std::vector<int> Client::GetLearnableDisciplines(uint8 min_level, uint8 max_leve
|
||||
continue;
|
||||
}
|
||||
|
||||
if (spells[spell_id].classes[WARRIOR] == 0) {
|
||||
if (spells[spell_id].classes[Class::Warrior] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -9789,7 +9939,7 @@ std::vector<int> Client::GetScribeableSpells(uint8 min_level, uint8 max_level) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (spells[spell_id].classes[WARRIOR] == 0) {
|
||||
if (spells[spell_id].classes[Class::Warrior] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -10353,6 +10503,16 @@ void Client::SetDoorToolEntityId(uint16 door_tool_entity_id)
|
||||
Client::m_door_tool_entity_id = door_tool_entity_id;
|
||||
}
|
||||
|
||||
uint16 Client::GetObjectToolEntityId() const
|
||||
{
|
||||
return m_object_tool_entity_id;
|
||||
}
|
||||
|
||||
void Client::SetObjectToolEntityId(uint16 object_tool_entity_id)
|
||||
{
|
||||
Client::m_object_tool_entity_id = object_tool_entity_id;
|
||||
}
|
||||
|
||||
int Client::GetIPExemption()
|
||||
{
|
||||
return database.GetIPExemption(GetIPString());
|
||||
@@ -10648,37 +10808,37 @@ uint16 Client::LearnDisciplines(uint8 min_level, uint8 max_level)
|
||||
|
||||
uint16 Client::GetClassTrackingDistanceMultiplier(uint16 class_) {
|
||||
switch (class_) {
|
||||
case WARRIOR:
|
||||
case Class::Warrior:
|
||||
return RuleI(Character, WarriorTrackingDistanceMultiplier);
|
||||
case CLERIC:
|
||||
case Class::Cleric:
|
||||
return RuleI(Character, ClericTrackingDistanceMultiplier);
|
||||
case PALADIN:
|
||||
case Class::Paladin:
|
||||
return RuleI(Character, PaladinTrackingDistanceMultiplier);
|
||||
case RANGER:
|
||||
case Class::Ranger:
|
||||
return RuleI(Character, RangerTrackingDistanceMultiplier);
|
||||
case SHADOWKNIGHT:
|
||||
case Class::ShadowKnight:
|
||||
return RuleI(Character, ShadowKnightTrackingDistanceMultiplier);
|
||||
case DRUID:
|
||||
case Class::Druid:
|
||||
return RuleI(Character, DruidTrackingDistanceMultiplier);
|
||||
case MONK:
|
||||
case Class::Monk:
|
||||
return RuleI(Character, MonkTrackingDistanceMultiplier);
|
||||
case BARD:
|
||||
case Class::Bard:
|
||||
return RuleI(Character, BardTrackingDistanceMultiplier);
|
||||
case ROGUE:
|
||||
case Class::Rogue:
|
||||
return RuleI(Character, RogueTrackingDistanceMultiplier);
|
||||
case SHAMAN:
|
||||
case Class::Shaman:
|
||||
return RuleI(Character, ShamanTrackingDistanceMultiplier);
|
||||
case NECROMANCER:
|
||||
case Class::Necromancer:
|
||||
return RuleI(Character, NecromancerTrackingDistanceMultiplier);
|
||||
case WIZARD:
|
||||
case Class::Wizard:
|
||||
return RuleI(Character, WizardTrackingDistanceMultiplier);
|
||||
case MAGICIAN:
|
||||
case Class::Magician:
|
||||
return RuleI(Character, MagicianTrackingDistanceMultiplier);
|
||||
case ENCHANTER:
|
||||
case Class::Enchanter:
|
||||
return RuleI(Character, EnchanterTrackingDistanceMultiplier);
|
||||
case BEASTLORD:
|
||||
case Class::Beastlord:
|
||||
return RuleI(Character, BeastlordTrackingDistanceMultiplier);
|
||||
case BERSERKER:
|
||||
case Class::Berserker:
|
||||
return RuleI(Character, BerserkerTrackingDistanceMultiplier);
|
||||
default:
|
||||
return 0;
|
||||
@@ -11125,16 +11285,15 @@ void Client::AddAAPoints(uint32 points)
|
||||
{
|
||||
m_pp.aapoints += points;
|
||||
|
||||
if (points == 1 && m_pp.aapoints == 1)
|
||||
{
|
||||
if (parse->PlayerHasQuestSub(EVENT_AA_GAIN)) {
|
||||
parse->EventPlayer(EVENT_AA_GAIN, this, std::to_string(points), 0);
|
||||
}
|
||||
|
||||
if (points == 1 && m_pp.aapoints == 1) {
|
||||
MessageString(Chat::Yellow, GAIN_SINGLE_AA_SINGLE_AA, fmt::format_int(m_pp.aapoints).c_str());
|
||||
}
|
||||
else if (points == 1 && m_pp.aapoints > 1)
|
||||
{
|
||||
} else if (points == 1 && m_pp.aapoints > 1) {
|
||||
MessageString(Chat::Yellow, GAIN_SINGLE_AA_MULTI_AA, fmt::format_int(m_pp.aapoints).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
MessageString(Chat::Yellow, GAIN_MULTI_AA_MULTI_AA, fmt::format_int(points).c_str(), fmt::format_int(m_pp.aapoints).c_str());
|
||||
}
|
||||
|
||||
|
||||
+21
-9
@@ -611,11 +611,14 @@ public:
|
||||
void SetPVPPoints(uint32 Points) { m_pp.PVPCurrentPoints = Points; }
|
||||
uint32 GetPVPPoints() { return m_pp.PVPCurrentPoints; }
|
||||
void AddPVPPoints(uint32 Points);
|
||||
void AddEbonCrystals(uint32 amount, bool is_reclaim = false);
|
||||
void AddRadiantCrystals(uint32 amount, bool is_reclaim = false);
|
||||
void RemoveEbonCrystals(uint32 amount, bool is_reclaim = false);
|
||||
void RemoveRadiantCrystals(uint32 amount, bool is_reclaim = false);
|
||||
uint32 GetRadiantCrystals() { return m_pp.currentRadCrystals; }
|
||||
void SetRadiantCrystals(uint32 value);
|
||||
uint32 GetEbonCrystals() { return m_pp.currentEbonCrystals; }
|
||||
void SetEbonCrystals(uint32 value);
|
||||
void AddCrystals(uint32 Radiant, uint32 Ebon);
|
||||
void SendCrystalCounts();
|
||||
|
||||
uint64 GetExperienceForKill(Mob *against);
|
||||
@@ -908,6 +911,7 @@ public:
|
||||
void AutoGrantAAPoints();
|
||||
void GrantAllAAPoints(uint8 unlock_level = 0);
|
||||
bool HasAlreadyPurchasedRank(AA::Rank* rank);
|
||||
void ListPurchasedAAs(Client *to, std::string search_criteria = std::string());
|
||||
|
||||
bool SendGMCommand(std::string message, bool ignore_status = false);
|
||||
|
||||
@@ -978,6 +982,7 @@ public:
|
||||
void PutLootInInventory(int16 slot_id, const EQ::ItemInstance &inst, ServerLootItem_Struct** bag_item_data = 0);
|
||||
bool AutoPutLootInInventory(EQ::ItemInstance& inst, bool try_worn = false, bool try_cursor = true, ServerLootItem_Struct** bag_item_data = 0);
|
||||
bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false, uint16 to_slot = EQ::invslot::slotCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0);
|
||||
void SummonItemIntoInventory(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool is_attuned = false);
|
||||
void SummonBaggedItems(uint32 bag_item_id, const std::vector<ServerLootItem_Struct>& bag_items);
|
||||
void SetStats(uint8 type,int16 set_val);
|
||||
void IncStats(uint8 type,int16 increase_val);
|
||||
@@ -1274,6 +1279,10 @@ public:
|
||||
}
|
||||
else { return 0; }
|
||||
}
|
||||
inline bool CompleteTask(uint32 task_id)
|
||||
{
|
||||
return task_state ? task_state->CompleteTask(this, task_id) : false;
|
||||
}
|
||||
inline void FailTask(int task_id) { if (task_state) { task_state->FailTask(this, task_id); }}
|
||||
inline int TaskTimeLeft(int task_id) { return (task_state ? task_state->TaskTimeLeft(task_id) : 0); }
|
||||
inline int EnabledTaskCount(int task_set_id)
|
||||
@@ -1488,7 +1497,7 @@ public:
|
||||
void ConsentCorpses(std::string consent_name, bool deny = false);
|
||||
void SendAltCurrencies();
|
||||
void SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount);
|
||||
int AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method = 0);
|
||||
int AddAlternateCurrencyValue(uint32 currency_id, int amount, bool is_scripted = false);
|
||||
void SendAlternateCurrencyValues();
|
||||
void SendAlternateCurrencyValue(uint32 currency_id, bool send_if_null = true);
|
||||
uint32 GetAlternateCurrencyValue(uint32 currency_id) const;
|
||||
@@ -1809,9 +1818,12 @@ private:
|
||||
bool dev_tools_enabled;
|
||||
|
||||
uint16 m_door_tool_entity_id;
|
||||
uint16 m_object_tool_entity_id;
|
||||
public:
|
||||
uint16 GetDoorToolEntityId() const;
|
||||
void SetDoorToolEntityId(uint16 door_tool_entity_id);
|
||||
uint16 GetObjectToolEntityId() const;
|
||||
void SetObjectToolEntityId(uint16 object_tool_entity_id);
|
||||
private:
|
||||
|
||||
int32 max_end;
|
||||
@@ -2037,14 +2049,14 @@ public:
|
||||
bool GetBotPrecombat() { return m_bot_precombat; }
|
||||
void SetBotPrecombat(bool flag = true) { m_bot_precombat = flag; }
|
||||
|
||||
int GetBotRequiredLevel(uint8 class_id = NO_CLASS);
|
||||
uint32 GetBotCreationLimit(uint8 class_id = NO_CLASS);
|
||||
int GetBotSpawnLimit(uint8 class_id = NO_CLASS);
|
||||
void SetBotCreationLimit(uint32 new_creation_limit, uint8 class_id = NO_CLASS);
|
||||
void SetBotRequiredLevel(int new_required_level, uint8 class_id = NO_CLASS);
|
||||
void SetBotSpawnLimit(int new_spawn_limit, uint8 class_id = NO_CLASS);
|
||||
int GetBotRequiredLevel(uint8 class_id = Class::None);
|
||||
uint32 GetBotCreationLimit(uint8 class_id = Class::None);
|
||||
int GetBotSpawnLimit(uint8 class_id = Class::None);
|
||||
void SetBotCreationLimit(uint32 new_creation_limit, uint8 class_id = Class::None);
|
||||
void SetBotRequiredLevel(int new_required_level, uint8 class_id = Class::None);
|
||||
void SetBotSpawnLimit(int new_spawn_limit, uint8 class_id = Class::None);
|
||||
|
||||
void CampAllBots(uint8 class_id = NO_CLASS);
|
||||
void CampAllBots(uint8 class_id = Class::None);
|
||||
void SpawnRaidBotsOnConnect(Raid* raid);
|
||||
|
||||
private:
|
||||
|
||||
+29
-29
@@ -345,7 +345,7 @@ uint32 Mob::GetClassLevelFactor()
|
||||
uint32 multiplier = 0;
|
||||
uint8 mlevel = GetLevel();
|
||||
switch (GetClass()) {
|
||||
case WARRIOR: {
|
||||
case Class::Warrior: {
|
||||
if (mlevel < 20) {
|
||||
multiplier = 220;
|
||||
}
|
||||
@@ -372,9 +372,9 @@ uint32 Mob::GetClassLevelFactor()
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DRUID:
|
||||
case CLERIC:
|
||||
case SHAMAN: {
|
||||
case Class::Druid:
|
||||
case Class::Cleric:
|
||||
case Class::Shaman: {
|
||||
if (mlevel < 70) {
|
||||
multiplier = 150;
|
||||
}
|
||||
@@ -383,9 +383,9 @@ uint32 Mob::GetClassLevelFactor()
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BERSERKER:
|
||||
case PALADIN:
|
||||
case SHADOWKNIGHT: {
|
||||
case Class::Berserker:
|
||||
case Class::Paladin:
|
||||
case Class::ShadowKnight: {
|
||||
if (mlevel < 35) {
|
||||
multiplier = 210;
|
||||
}
|
||||
@@ -409,10 +409,10 @@ uint32 Mob::GetClassLevelFactor()
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MONK:
|
||||
case BARD:
|
||||
case ROGUE:
|
||||
case BEASTLORD: {
|
||||
case Class::Monk:
|
||||
case Class::Bard:
|
||||
case Class::Rogue:
|
||||
case Class::Beastlord: {
|
||||
if (mlevel < 51) {
|
||||
multiplier = 180;
|
||||
}
|
||||
@@ -427,7 +427,7 @@ uint32 Mob::GetClassLevelFactor()
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RANGER: {
|
||||
case Class::Ranger: {
|
||||
if (mlevel < 58) {
|
||||
multiplier = 200;
|
||||
}
|
||||
@@ -439,10 +439,10 @@ uint32 Mob::GetClassLevelFactor()
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MAGICIAN:
|
||||
case WIZARD:
|
||||
case NECROMANCER:
|
||||
case ENCHANTER: {
|
||||
case Class::Magician:
|
||||
case Class::Wizard:
|
||||
case Class::Necromancer:
|
||||
case Class::Enchanter: {
|
||||
if (mlevel < 70) {
|
||||
multiplier = 120;
|
||||
}
|
||||
@@ -677,7 +677,7 @@ int64 Client::CalcManaRegen(bool bCombat)
|
||||
if (IsSitting() || CanMedOnHorse()) {
|
||||
// kind of weird to do it here w/e
|
||||
// client does some base medding regen for shrouds here
|
||||
if (GetClass() != BARD) {
|
||||
if (GetClass() != Class::Bard) {
|
||||
auto skill = GetSkill(EQ::skills::SkillMeditate);
|
||||
if (skill > 0) {
|
||||
regen++;
|
||||
@@ -1077,7 +1077,7 @@ int32 Client::CalcMR()
|
||||
MR = 20;
|
||||
}
|
||||
MR += itembonuses.MR + spellbonuses.MR + aabonuses.MR;
|
||||
if (GetClass() == WARRIOR || GetClass() == BERSERKER) {
|
||||
if (GetClass() == Class::Warrior || GetClass() == Class::Berserker) {
|
||||
MR += GetLevel() / 2;
|
||||
}
|
||||
if (MR < 1) {
|
||||
@@ -1151,14 +1151,14 @@ int32 Client::CalcFR()
|
||||
FR = 20;
|
||||
}
|
||||
int c = GetClass();
|
||||
if (c == RANGER) {
|
||||
if (c == Class::Ranger) {
|
||||
FR += 4;
|
||||
int l = GetLevel();
|
||||
if (l > 49) {
|
||||
FR += l - 49;
|
||||
}
|
||||
}
|
||||
if (c == MONK) {
|
||||
if (c == Class::Monk) {
|
||||
FR += 8;
|
||||
int l = GetLevel();
|
||||
if (l > 49) {
|
||||
@@ -1238,19 +1238,19 @@ int32 Client::CalcDR()
|
||||
}
|
||||
int c = GetClass();
|
||||
// the monk one is part of base resist
|
||||
if (c == MONK) {
|
||||
if (c == Class::Monk) {
|
||||
int l = GetLevel();
|
||||
if (l > 50)
|
||||
DR += l - 50;
|
||||
}
|
||||
if (c == PALADIN) {
|
||||
if (c == Class::Paladin) {
|
||||
DR += 8;
|
||||
int l = GetLevel();
|
||||
if (l > 49) {
|
||||
DR += l - 49;
|
||||
}
|
||||
}
|
||||
else if (c == SHADOWKNIGHT || c == BEASTLORD) {
|
||||
else if (c == Class::ShadowKnight || c == Class::Beastlord) {
|
||||
DR += 4;
|
||||
int l = GetLevel();
|
||||
if (l > 49) {
|
||||
@@ -1330,19 +1330,19 @@ int32 Client::CalcPR()
|
||||
}
|
||||
int c = GetClass();
|
||||
// this monk bonus is part of the base
|
||||
if (c == MONK) {
|
||||
if (c == Class::Monk) {
|
||||
int l = GetLevel();
|
||||
if (l > 50)
|
||||
PR += l - 50;
|
||||
}
|
||||
if (c == ROGUE) {
|
||||
if (c == Class::Rogue) {
|
||||
PR += 8;
|
||||
int l = GetLevel();
|
||||
if (l > 49) {
|
||||
PR += l - 49;
|
||||
}
|
||||
}
|
||||
else if (c == SHADOWKNIGHT) {
|
||||
else if (c == Class::ShadowKnight) {
|
||||
PR += 4;
|
||||
int l = GetLevel();
|
||||
if (l > 49) {
|
||||
@@ -1421,7 +1421,7 @@ int32 Client::CalcCR()
|
||||
CR = 25;
|
||||
}
|
||||
int c = GetClass();
|
||||
if (c == RANGER || c == BEASTLORD) {
|
||||
if (c == Class::Ranger || c == Class::Beastlord) {
|
||||
CR += 4;
|
||||
int l = GetLevel();
|
||||
if (l > 49) {
|
||||
@@ -1455,7 +1455,7 @@ int32 Client::CalcATK()
|
||||
|
||||
uint32 Mob::GetInstrumentMod(uint16 spell_id)
|
||||
{
|
||||
if (GetClass() != BARD) {
|
||||
if (GetClass() != Class::Bard) {
|
||||
//Other classes can get a base effects mod using SPA 413
|
||||
if (HasBaseEffectFocus()) {
|
||||
return (10 + (GetFocusEffect(focusFcBaseEffects, spell_id) / 10));//TODO: change action->instrument mod to float to support < 10% focus values
|
||||
@@ -1689,7 +1689,7 @@ int64 Client::CalcEnduranceRegen(bool bCombat)
|
||||
|
||||
int weight_limit = GetSTR();
|
||||
auto level = GetLevel();
|
||||
if (GetClass() == MONK) {
|
||||
if (GetClass() == Class::Monk) {
|
||||
if (level > 99)
|
||||
weight_limit = 58;
|
||||
else if (level > 94)
|
||||
|
||||
+274
-256
File diff suppressed because it is too large
Load Diff
@@ -434,7 +434,7 @@ bool Client::Process() {
|
||||
}
|
||||
}
|
||||
|
||||
if (GetClass() == WARRIOR || GetClass() == BERSERKER) {
|
||||
if (GetClass() == Class::Warrior || GetClass() == Class::Berserker) {
|
||||
if (!dead && !IsBerserk() && GetHPRatio() < RuleI(Combat, BerserkerFrenzyStart)) {
|
||||
entity_list.MessageCloseString(this, false, 200, 0, BERSERK_START, GetName());
|
||||
berserk = true;
|
||||
@@ -1121,7 +1121,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app)
|
||||
if (
|
||||
m->scribing != memSpellForget &&
|
||||
(
|
||||
!EQ::ValueWithin(GetClass(), PLAYER_CLASS_WARRIOR, PLAYER_CLASS_BERSERKER) ||
|
||||
!IsPlayerClass(GetClass()) ||
|
||||
GetLevel() < spells[m->spell_id].classes[GetClass() - 1]
|
||||
)
|
||||
) {
|
||||
@@ -1552,12 +1552,12 @@ void Client::OPGMTraining(const EQApplicationPacket *app)
|
||||
|
||||
Mob* pTrainer = entity_list.GetMob(gmtrain->npcid);
|
||||
|
||||
if(!pTrainer || !pTrainer->IsNPC() || pTrainer->GetClass() < WARRIORGM || pTrainer->GetClass() > BERSERKERGM)
|
||||
if(!pTrainer || !pTrainer->IsNPC() || pTrainer->GetClass() < Class::WarriorGM || pTrainer->GetClass() > Class::BerserkerGM)
|
||||
return;
|
||||
|
||||
//you can only use your own trainer, client enforces this, but why trust it
|
||||
if (!RuleB(Character, AllowCrossClassTrainers)) {
|
||||
int trains_class = pTrainer->GetClass() - (WARRIORGM - WARRIOR);
|
||||
int trains_class = pTrainer->GetClass() - (Class::WarriorGM - Class::Warrior);
|
||||
if (GetClass() != trains_class)
|
||||
return;
|
||||
}
|
||||
@@ -1579,7 +1579,7 @@ void Client::OPGMTraining(const EQApplicationPacket *app)
|
||||
}
|
||||
}
|
||||
|
||||
if (ClientVersion() < EQ::versions::ClientVersion::RoF2 && GetClass() == BERSERKER) {
|
||||
if (ClientVersion() < EQ::versions::ClientVersion::RoF2 && GetClass() == Class::Berserker) {
|
||||
gmtrain->skills[EQ::skills::Skill1HPiercing] = gmtrain->skills[EQ::skills::Skill2HPiercing];
|
||||
gmtrain->skills[EQ::skills::Skill2HPiercing] = 0;
|
||||
}
|
||||
@@ -1607,12 +1607,12 @@ void Client::OPGMEndTraining(const EQApplicationPacket *app)
|
||||
FastQueuePacket(&outapp);
|
||||
|
||||
Mob* pTrainer = entity_list.GetMob(p->npcid);
|
||||
if(!pTrainer || !pTrainer->IsNPC() || pTrainer->GetClass() < WARRIORGM || pTrainer->GetClass() > BERSERKERGM)
|
||||
if(!pTrainer || !pTrainer->IsNPC() || pTrainer->GetClass() < Class::WarriorGM || pTrainer->GetClass() > Class::BerserkerGM)
|
||||
return;
|
||||
|
||||
//you can only use your own trainer, client enforces this, but why trust it
|
||||
if (!RuleB(Character, AllowCrossClassTrainers)) {
|
||||
int trains_class = pTrainer->GetClass() - (WARRIORGM - WARRIOR);
|
||||
int trains_class = pTrainer->GetClass() - (Class::WarriorGM - Class::Warrior);
|
||||
if (GetClass() != trains_class)
|
||||
return;
|
||||
}
|
||||
@@ -1638,12 +1638,12 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
|
||||
GMSkillChange_Struct* gmskill = (GMSkillChange_Struct*) app->pBuffer;
|
||||
|
||||
Mob* pTrainer = entity_list.GetMob(gmskill->npcid);
|
||||
if(!pTrainer || !pTrainer->IsNPC() || pTrainer->GetClass() < WARRIORGM || pTrainer->GetClass() > BERSERKERGM)
|
||||
if(!pTrainer || !pTrainer->IsNPC() || pTrainer->GetClass() < Class::WarriorGM || pTrainer->GetClass() > Class::BerserkerGM)
|
||||
return;
|
||||
|
||||
//you can only use your own trainer, client enforces this, but why trust it
|
||||
if (!RuleB(Character, AllowCrossClassTrainers)) {
|
||||
int trains_class = pTrainer->GetClass() - (WARRIORGM - WARRIOR);
|
||||
int trains_class = pTrainer->GetClass() - (Class::WarriorGM - Class::Warrior);
|
||||
if (GetClass() != trains_class)
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -217,6 +217,7 @@ int command_init(void)
|
||||
command_add("summonitem", "[itemid] [charges] - Summon an item onto your cursor. Charges are optional.", AccountStatus::GMMgmt, command_summonitem) ||
|
||||
command_add("suspend", "[name] [days] [reason] - Suspend by character name and for specificed number of days", AccountStatus::GMLeadAdmin, command_suspend) ||
|
||||
command_add("suspendmulti", "[Character Name One|Character Name Two|etc] [Days] [Reason] - Suspend multiple characters by name for specified number of days", AccountStatus::GMLeadAdmin, command_suspendmulti) ||
|
||||
command_add("takeplatinum", "[Platinum] - Takes specified amount of platinum from you or your player target", AccountStatus::GMMgmt, command_takeplatinum) ||
|
||||
command_add("task", "(subcommand) - Task system commands", AccountStatus::GMLeadAdmin, command_task) ||
|
||||
command_add("petname", "[newname] - Temporarily renames your pet. Leave name blank to restore the original name.", AccountStatus::GMAdmin, command_petname) ||
|
||||
command_add("traindisc", "[level] - Trains all the disciplines usable by the target, up to level specified. (may freeze client for a few seconds)", AccountStatus::GMLeadAdmin, command_traindisc) ||
|
||||
@@ -865,6 +866,7 @@ void command_bot(Client *c, const Seperator *sep)
|
||||
#include "gm_commands/nukebuffs.cpp"
|
||||
#include "gm_commands/nukeitem.cpp"
|
||||
#include "gm_commands/object.cpp"
|
||||
#include "gm_commands/object_manipulation.cpp"
|
||||
#include "gm_commands/path.cpp"
|
||||
#include "gm_commands/peqzone.cpp"
|
||||
#include "gm_commands/petitems.cpp"
|
||||
@@ -903,6 +905,7 @@ void command_bot(Client *c, const Seperator *sep)
|
||||
#include "gm_commands/summonitem.cpp"
|
||||
#include "gm_commands/suspend.cpp"
|
||||
#include "gm_commands/suspendmulti.cpp"
|
||||
#include "gm_commands/takeplatinum.cpp"
|
||||
#include "gm_commands/task.cpp"
|
||||
#include "gm_commands/traindisc.cpp"
|
||||
#include "gm_commands/tune.cpp"
|
||||
|
||||
@@ -168,6 +168,7 @@ void command_summonburiedplayercorpse(Client *c, const Seperator *sep);
|
||||
void command_summonitem(Client *c, const Seperator *sep);
|
||||
void command_suspend(Client *c, const Seperator *sep);
|
||||
void command_suspendmulti(Client *c, const Seperator *sep);
|
||||
void command_takeplatinum(Client* c, const Seperator* sep);
|
||||
void command_task(Client *c, const Seperator *sep);
|
||||
void command_petname(Client *c, const Seperator *sep);
|
||||
void command_traindisc(Client *c, const Seperator *sep);
|
||||
|
||||
+1
-1
@@ -277,7 +277,7 @@ void Doors::HandleClick(Client *sender, uint8 trigger)
|
||||
// enforce flags before they hit zoning process
|
||||
auto z = GetZone(m_destination_zone_name, 0);
|
||||
if (z && !z->flag_needed.empty() && Strings::IsNumber(z->flag_needed) && Strings::ToInt(z->flag_needed) == 1) {
|
||||
if (sender->Admin() < minStatusToIgnoreZoneFlags && !sender->HasZoneFlag(z->zoneidnumber)) {
|
||||
if (!sender->GetGM() && !sender->HasZoneFlag(z->zoneidnumber)) {
|
||||
LogInfo(
|
||||
"Character [{}] does not have the flag to be in this zone [{}]!",
|
||||
sender->GetCleanName(),
|
||||
|
||||
+29
-20
@@ -75,7 +75,7 @@ int64 Mob::GetActSpellDamage(uint16 spell_id, int64 value, Mob* target) {
|
||||
chance += itembonuses.FrenziedDevastation + spellbonuses.FrenziedDevastation + aabonuses.FrenziedDevastation;
|
||||
|
||||
//Crtical Hit Calculation pathway
|
||||
if (chance > 0 || (IsOfClientBot() && GetClass() == WIZARD && GetLevel() >= RuleI(Spells, WizCritLevel))) {
|
||||
if (chance > 0 || (IsOfClientBot() && GetClass() == Class::Wizard && GetLevel() >= RuleI(Spells, WizCritLevel))) {
|
||||
|
||||
int32 ratio = RuleI(Spells, BaseCritRatio); //Critical modifier is applied from spell effects only. Keep at 100 for live like criticals.
|
||||
|
||||
@@ -92,7 +92,7 @@ int64 Mob::GetActSpellDamage(uint16 spell_id, int64 value, Mob* target) {
|
||||
ratio += itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack;
|
||||
}
|
||||
|
||||
else if ((IsOfClientBot() && GetClass() == WIZARD) || (IsMerc() && GetClass() == CASTERDPS)) {
|
||||
else if ((IsOfClientBot() && GetClass() == Class::Wizard) || (IsMerc() && GetClass() == CASTERDPS)) {
|
||||
if ((GetLevel() >= RuleI(Spells, WizCritLevel)) && zone->random.Roll(RuleI(Spells, WizCritChance))){
|
||||
//Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. (20-70 is parse confirmed)
|
||||
ratio += zone->random.Int(RuleI(Spells, WizardCritMinimumRandomRatio), RuleI(Spells, WizardCritMaximumRandomRatio));
|
||||
@@ -100,7 +100,7 @@ int64 Mob::GetActSpellDamage(uint16 spell_id, int64 value, Mob* target) {
|
||||
}
|
||||
}
|
||||
|
||||
if (IsOfClientBot() && GetClass() == WIZARD) {
|
||||
if (IsOfClientBot() && GetClass() == Class::Wizard) {
|
||||
ratio += RuleI(Spells, WizCritRatio); //Default is zero
|
||||
}
|
||||
|
||||
@@ -285,10 +285,13 @@ int64 Mob::GetActDoTDamage(uint16 spell_id, int64 value, Mob* target, bool from_
|
||||
extra_dmg += GetSkillDmgAmt(spells[spell_id].skill) * ratio / 100;
|
||||
}
|
||||
|
||||
if (extra_dmg) {
|
||||
int duration = CalcBuffDuration(this, target, spell_id);
|
||||
if (duration > 0)
|
||||
extra_dmg /= duration;
|
||||
if (RuleB(Spells, DOTBonusDamageSplitOverDuration)) {
|
||||
if (extra_dmg) {
|
||||
const int duration = CalcBuffDuration(this, target, spell_id);
|
||||
if (duration > 0) {
|
||||
extra_dmg /= duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
value -= extra_dmg;
|
||||
@@ -328,10 +331,13 @@ int64 Mob::GetActDoTDamage(uint16 spell_id, int64 value, Mob* target, bool from_
|
||||
extra_dmg += GetSkillDmgAmt(spells[spell_id].skill);
|
||||
}
|
||||
|
||||
if (extra_dmg) {
|
||||
int duration = CalcBuffDuration(this, target, spell_id);
|
||||
if (duration > 0)
|
||||
extra_dmg /= duration;
|
||||
if (RuleB(Spells, DOTBonusDamageSplitOverDuration)) {
|
||||
if (extra_dmg) {
|
||||
const int duration = CalcBuffDuration(this, target, spell_id);
|
||||
if (duration > 0) {
|
||||
extra_dmg /= duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
value -= extra_dmg;
|
||||
@@ -426,7 +432,7 @@ int64 Mob::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target, bool fr
|
||||
}
|
||||
}
|
||||
|
||||
if (GetClass() == CLERIC) {
|
||||
if (GetClass() == Class::Cleric) {
|
||||
value += int64(base_value*RuleI(Spells, ClericInnateHealFocus) / 100); //confirmed on live parsing clerics get an innate 5 pct heal focus
|
||||
}
|
||||
value += int64(base_value*GetFocusEffect(focusImprovedHeal, spell_id, nullptr, from_buff_tic) / 100);
|
||||
@@ -518,11 +524,14 @@ int64 Mob::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target, bool fr
|
||||
}
|
||||
|
||||
if (extra_heal) {
|
||||
int duration = CalcBuffDuration(this, target, spell_id);
|
||||
if (duration > 0) {
|
||||
extra_heal /= duration;
|
||||
value += extra_heal;
|
||||
if (RuleB(Spells, HOTBonusHealingSplitOverDuration)) {
|
||||
const int duration = CalcBuffDuration(this, target, spell_id);
|
||||
if (duration > 0) {
|
||||
extra_heal /= duration;
|
||||
}
|
||||
}
|
||||
|
||||
value += extra_heal;
|
||||
}
|
||||
|
||||
value *= critical_modifier;
|
||||
@@ -632,7 +641,7 @@ bool Client::TrainDiscipline(uint32 itemid) {
|
||||
}
|
||||
|
||||
const auto player_class = GetClass();
|
||||
if (player_class == WIZARD || player_class == ENCHANTER || player_class == MAGICIAN || player_class == NECROMANCER) {
|
||||
if (player_class == Class::Wizard || player_class == Class::Enchanter || player_class == Class::Magician || player_class == Class::Necromancer) {
|
||||
Message(Chat::Red, "Your class cannot learn from this tome.");
|
||||
//summon them the item back...
|
||||
SummonItem(itemid);
|
||||
@@ -906,7 +915,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
|
||||
if (reduced_recast > 0) {
|
||||
instant_recast = false;
|
||||
|
||||
if (GetClass() == BARD && IsCasting() && spells[spell_id].cast_time == 0) {
|
||||
if (GetClass() == Class::Bard && IsCasting() && spells[spell_id].cast_time == 0) {
|
||||
if (DoCastingChecksOnCaster(spell_id, EQ::spells::CastingSlot::Discipline)) {
|
||||
SpellFinished(spell_id, entity_list.GetMob(target), EQ::spells::CastingSlot::Discipline, 0, -1, spells[spell_id].resist_difficulty, false, -1, (uint32)DiscTimer, reduced_recast, false);
|
||||
}
|
||||
@@ -921,7 +930,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
|
||||
}
|
||||
|
||||
if (instant_recast) {
|
||||
if (GetClass() == BARD && IsCasting() && spells[spell_id].cast_time == 0) {
|
||||
if (GetClass() == Class::Bard && IsCasting() && spells[spell_id].cast_time == 0) {
|
||||
if (DoCastingChecksOnCaster(spell_id, EQ::spells::CastingSlot::Discipline)) {
|
||||
SpellFinished(spell_id, entity_list.GetMob(target), EQ::spells::CastingSlot::Discipline, 0, -1, spells[spell_id].resist_difficulty, false, -1, 0xFFFFFFFF, 0, false);
|
||||
}
|
||||
@@ -1320,7 +1329,7 @@ void EntityList::AEAttack(
|
||||
) {
|
||||
|
||||
for (int i = 0; i < attack_rounds; i++) {
|
||||
if (!attacker->IsClient() || attacker->GetClass() == MONK || attacker->GetClass() == RANGER) {
|
||||
if (!attacker->IsClient() || attacker->GetClass() == Class::Monk || attacker->GetClass() == Class::Ranger) {
|
||||
attacker->Attack(current_mob, Hand, false, false, is_from_spell);
|
||||
} else {
|
||||
attacker->CastToClient()->DoAttackRounds(current_mob, Hand, is_from_spell);
|
||||
|
||||
+61
-11
@@ -186,6 +186,14 @@ const char *QuestEventSubroutines[_LargestEventID] = {
|
||||
"EVENT_UNMEMORIZE_SPELL",
|
||||
"EVENT_SCRIBE_SPELL",
|
||||
"EVENT_UNSCRIBE_SPELL",
|
||||
"EVENT_LOOT_ADDED",
|
||||
"EVENT_LDON_POINTS_GAIN",
|
||||
"EVENT_LDON_POINTS_LOSS",
|
||||
"EVENT_ALT_CURRENCY_GAIN",
|
||||
"EVENT_ALT_CURRENCY_LOSS",
|
||||
"EVENT_CRYSTAL_GAIN",
|
||||
"EVENT_CRYSTAL_LOSS",
|
||||
|
||||
// Add new events before these or Lua crashes
|
||||
"EVENT_SPELL_EFFECT_BOT",
|
||||
"EVENT_SPELL_EFFECT_BUFF_TIC_BOT"
|
||||
@@ -1440,7 +1448,7 @@ void PerlembParser::ExportZoneVariables(std::string &package_name)
|
||||
ExportVar(package_name.c_str(), "zonesn", zone->GetShortName());
|
||||
ExportVar(package_name.c_str(), "instanceid", zone->GetInstanceID());
|
||||
ExportVar(package_name.c_str(), "instanceversion", zone->GetInstanceVersion());
|
||||
TimeOfDay_Struct eqTime;
|
||||
TimeOfDay_Struct eqTime{};
|
||||
zone->zone_time.GetCurrentEQTimeOfDay(time(0), &eqTime);
|
||||
ExportVar(package_name.c_str(), "zonehour", eqTime.hour - 1);
|
||||
ExportVar(package_name.c_str(), "zonemin", eqTime.minute);
|
||||
@@ -1883,19 +1891,17 @@ void PerlembParser::ExportEventVariables(
|
||||
ExportVar(package_name.c_str(), "killer_damage", sep.arg[1]);
|
||||
ExportVar(package_name.c_str(), "killer_spell", sep.arg[2]);
|
||||
ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]);
|
||||
if (extra_pointers && extra_pointers->size() >= 1)
|
||||
{
|
||||
Corpse* corpse = std::any_cast<Corpse*>(extra_pointers->at(0));
|
||||
if (corpse)
|
||||
{
|
||||
|
||||
if (extra_pointers && extra_pointers->size() >= 1) {
|
||||
Corpse *corpse = std::any_cast<Corpse *>(extra_pointers->at(0));
|
||||
if (corpse) {
|
||||
ExportVar(package_name.c_str(), "killed_corpse_id", corpse->GetID());
|
||||
}
|
||||
}
|
||||
if (extra_pointers && extra_pointers->size() >= 2)
|
||||
{
|
||||
NPC* killed = std::any_cast<NPC*>(extra_pointers->at(1));
|
||||
if (killed)
|
||||
{
|
||||
|
||||
if (extra_pointers && extra_pointers->size() >= 2) {
|
||||
NPC *killed = std::any_cast<NPC *>(extra_pointers->at(1));
|
||||
if (killed) {
|
||||
ExportVar(package_name.c_str(), "killed_entity_id", killed->GetID());
|
||||
ExportVar(package_name.c_str(), "killed_bot_id", killed->IsBot() ? killed->CastToBot()->GetBotID() : 0);
|
||||
ExportVar(package_name.c_str(), "killed_npc_id", killed->IsNPC() ? killed->GetNPCTypeID() : 0);
|
||||
@@ -2241,6 +2247,50 @@ void PerlembParser::ExportEventVariables(
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_LOOT_ADDED: {
|
||||
if (extra_pointers && extra_pointers->size() == 1) {
|
||||
auto *inst = std::any_cast<EQ::ItemInstance *>(extra_pointers->at(0));
|
||||
if (inst) {
|
||||
ExportVar(package_name.c_str(), "item", "QuestItem", inst);
|
||||
ExportVar(package_name.c_str(), "item_id", inst->GetID());
|
||||
ExportVar(package_name.c_str(), "item_name", inst->GetItem()->Name);
|
||||
ExportVar(package_name.c_str(), "item_charges", inst->GetCharges());
|
||||
ExportVar(package_name.c_str(), "augment_one", inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN));
|
||||
ExportVar(package_name.c_str(), "augment_two", inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 1));
|
||||
ExportVar(package_name.c_str(), "augment_three", inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 2));
|
||||
ExportVar(package_name.c_str(), "augment_four", inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 3));
|
||||
ExportVar(package_name.c_str(), "augment_five", inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 4));
|
||||
ExportVar(package_name.c_str(), "augment_six", inst->GetAugmentItemID(EQ::invaug::SOCKET_END));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case EVENT_LDON_POINTS_GAIN:
|
||||
case EVENT_LDON_POINTS_LOSS: {
|
||||
Seperator sep(data);
|
||||
ExportVar(package_name.c_str(), "theme_id", sep.arg[0]);
|
||||
ExportVar(package_name.c_str(), "points", sep.arg[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_ALT_CURRENCY_GAIN:
|
||||
case EVENT_ALT_CURRENCY_LOSS: {
|
||||
Seperator sep(data);
|
||||
ExportVar(package_name.c_str(), "currency_id", sep.arg[0]);
|
||||
ExportVar(package_name.c_str(), "amount", sep.arg[1]);
|
||||
ExportVar(package_name.c_str(), "total", sep.arg[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_CRYSTAL_GAIN:
|
||||
case EVENT_CRYSTAL_LOSS: {
|
||||
Seperator sep(data);
|
||||
ExportVar(package_name.c_str(), "ebon_amount", sep.arg[0]);
|
||||
ExportVar(package_name.c_str(), "radiant_amount", sep.arg[1]);
|
||||
ExportVar(package_name.c_str(), "is_reclaim", sep.arg[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
|
||||
+7
-7
@@ -4918,9 +4918,9 @@ void EntityList::ZoneWho(Client *c, Who_All_Struct *Who)
|
||||
FormatMSGID = 5024; // 5024 %T1[ANONYMOUS] %2 %3
|
||||
else if (ClientEntry->GetAnon() == 2)
|
||||
FormatMSGID = 5023; // 5023 %T1[ANONYMOUS] %2 %3 %4
|
||||
uint32 PlayerClass = NO_CLASS;
|
||||
uint32 PlayerClass = Class::None;
|
||||
uint32 PlayerLevel = 0;
|
||||
uint32 PlayerRace = RACE_DOUG_0;
|
||||
uint32 PlayerRace = Race::Doug;
|
||||
uint32 ZoneMSGID = 0xFFFFFFFF;
|
||||
|
||||
if (ClientEntry->GetAnon()==0) {
|
||||
@@ -4995,7 +4995,7 @@ uint32 EntityList::CheckNPCsClose(Mob *center)
|
||||
auto it = npc_list.begin();
|
||||
while (it != npc_list.end()) {
|
||||
NPC *cur = it->second;
|
||||
if (!cur || cur == center || cur->IsPet() || cur->GetClass() == LDON_TREASURE ||
|
||||
if (!cur || cur == center || cur->IsPet() || cur->GetClass() == Class::LDoNTreasure ||
|
||||
cur->GetBodyType() == BT_NoTarget || cur->GetBodyType() == BT_Special) {
|
||||
++it;
|
||||
continue;
|
||||
@@ -5355,7 +5355,7 @@ void EntityList::AddLootToNPCS(uint32 item_id, uint32 count)
|
||||
auto it = npc_list.begin();
|
||||
while (it != npc_list.end()) {
|
||||
if (!it->second->IsPet()
|
||||
&& it->second->GetClass() != LDON_TREASURE
|
||||
&& it->second->GetClass() != Class::LDoNTreasure
|
||||
&& it->second->GetBodyType() != BT_NoTarget
|
||||
&& it->second->GetBodyType() != BT_NoTarget2
|
||||
&& it->second->GetBodyType() != BT_Special)
|
||||
@@ -5376,7 +5376,7 @@ void EntityList::AddLootToNPCS(uint32 item_id, uint32 count)
|
||||
it = npc_list.begin();
|
||||
while (it != npc_list.end()) {
|
||||
if (!it->second->IsPet()
|
||||
&& it->second->GetClass() != LDON_TREASURE
|
||||
&& it->second->GetClass() != Class::LDoNTreasure
|
||||
&& it->second->GetBodyType() != BT_NoTarget
|
||||
&& it->second->GetBodyType() != BT_NoTarget2
|
||||
&& it->second->GetBodyType() != BT_Special)
|
||||
@@ -5429,7 +5429,7 @@ NPC *EntityList::GetClosestBanker(Mob *sender, uint32 &distance)
|
||||
|
||||
auto it = npc_list.begin();
|
||||
while (it != npc_list.end()) {
|
||||
if (it->second->GetClass() == BANKER) {
|
||||
if (it->second->GetClass() == Class::Banker) {
|
||||
uint32 nd = ((it->second->GetY() - sender->GetY()) * (it->second->GetY() - sender->GetY())) +
|
||||
((it->second->GetX() - sender->GetX()) * (it->second->GetX() - sender->GetX()));
|
||||
if (nd < distance){
|
||||
@@ -5750,7 +5750,7 @@ void EntityList::DespawnGridNodes(int32 grid_id) {
|
||||
Mob *mob = m.second;
|
||||
if (
|
||||
mob->IsNPC() &&
|
||||
mob->GetRace() == RACE_NODE_2254 &&
|
||||
mob->GetRace() == Race::Node &&
|
||||
mob->EntityVariableExists("grid_id") &&
|
||||
Strings::ToInt(mob->GetEntityVariable("grid_id")) == grid_id)
|
||||
{
|
||||
|
||||
+2
-2
@@ -529,8 +529,8 @@ public:
|
||||
inline const std::unordered_map<uint16, Merc *> &GetMercList() { return merc_list; }
|
||||
inline const std::unordered_map<uint16, Client *> &GetClientList() { return client_list; }
|
||||
inline const std::list<Bot *> &GetBotList() { return bot_list; }
|
||||
std::vector<Bot *> GetBotListByCharacterID(uint32 character_id, uint8 class_id = NO_CLASS);
|
||||
std::vector<Bot *> GetBotListByClientName(std::string client_name, uint8 class_id = NO_CLASS);
|
||||
std::vector<Bot *> GetBotListByCharacterID(uint32 character_id, uint8 class_id = Class::None);
|
||||
std::vector<Bot *> GetBotListByClientName(std::string client_name, uint8 class_id = Class::None);
|
||||
void SignalAllBotsByOwnerCharacterID(uint32 character_id, int signal_id);
|
||||
void SignalAllBotsByOwnerName(std::string owner_name, int signal_id);
|
||||
void SignalBotByBotID(uint32 bot_id, int signal_id);
|
||||
|
||||
@@ -128,6 +128,14 @@ typedef enum {
|
||||
EVENT_UNMEMORIZE_SPELL,
|
||||
EVENT_SCRIBE_SPELL,
|
||||
EVENT_UNSCRIBE_SPELL,
|
||||
EVENT_LOOT_ADDED,
|
||||
EVENT_LDON_POINTS_GAIN,
|
||||
EVENT_LDON_POINTS_LOSS,
|
||||
EVENT_ALT_CURRENCY_GAIN,
|
||||
EVENT_ALT_CURRENCY_LOSS,
|
||||
EVENT_CRYSTAL_GAIN,
|
||||
EVENT_CRYSTAL_LOSS,
|
||||
|
||||
// Add new events before these or Lua crashes
|
||||
EVENT_SPELL_EFFECT_BOT,
|
||||
EVENT_SPELL_EFFECT_BUFF_TIC_BOT,
|
||||
|
||||
+9
-9
@@ -128,8 +128,8 @@ uint64 Client::CalcEXP(uint8 consider_level, bool ignore_modifiers) {
|
||||
|
||||
if (RuleB(Character, UseRaceClassExpBonuses)) {
|
||||
if (
|
||||
GetClass() == WARRIOR ||
|
||||
GetClass() == ROGUE ||
|
||||
GetClass() == Class::Warrior ||
|
||||
GetClass() == Class::Rogue ||
|
||||
GetBaseRace() == HALFLING
|
||||
) {
|
||||
total_modifier *= 1.05;
|
||||
@@ -295,7 +295,7 @@ void Client::CalculateStandardAAExp(uint64 &add_aaxp, uint8 conlevel, bool resex
|
||||
aatotalmod *= 1.05;
|
||||
}
|
||||
|
||||
if (GetClass() == ROGUE || GetClass() == WARRIOR) {
|
||||
if (GetClass() == Class::Rogue || GetClass() == Class::Warrior) {
|
||||
aatotalmod *= 1.05;
|
||||
}
|
||||
}
|
||||
@@ -443,7 +443,7 @@ void Client::CalculateExp(uint64 in_add_exp, uint64 &add_exp, uint64 &add_aaxp,
|
||||
totalmod *= 1.05;
|
||||
}
|
||||
|
||||
if (GetClass() == ROGUE || GetClass() == WARRIOR) {
|
||||
if (GetClass() == Class::Rogue || GetClass() == Class::Warrior) {
|
||||
totalmod *= 1.05;
|
||||
}
|
||||
}
|
||||
@@ -1051,15 +1051,15 @@ uint32 Client::GetEXPForLevel(uint16 check_level)
|
||||
if(RuleB(Character,UseOldClassExpPenalties))
|
||||
{
|
||||
float classmod = 1.0;
|
||||
if(GetClass() == PALADIN || GetClass() == SHADOWKNIGHT || GetClass() == RANGER || GetClass() == BARD) {
|
||||
if(GetClass() == Class::Paladin || GetClass() == Class::ShadowKnight || GetClass() == Class::Ranger || GetClass() == Class::Bard) {
|
||||
classmod = 1.4;
|
||||
} else if(GetClass() == MONK) {
|
||||
} else if(GetClass() == Class::Monk) {
|
||||
classmod = 1.2;
|
||||
} else if(GetClass() == WIZARD || GetClass() == ENCHANTER || GetClass() == MAGICIAN || GetClass() == NECROMANCER) {
|
||||
} else if(GetClass() == Class::Wizard || GetClass() == Class::Enchanter || GetClass() == Class::Magician || GetClass() == Class::Necromancer) {
|
||||
classmod = 1.1;
|
||||
} else if(GetClass() == ROGUE) {
|
||||
} else if(GetClass() == Class::Rogue) {
|
||||
classmod = 0.91;
|
||||
} else if(GetClass() == WARRIOR) {
|
||||
} else if(GetClass() == Class::Warrior) {
|
||||
classmod = 0.9;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -456,7 +456,7 @@ void Client::ForageItem(bool guarantee) {
|
||||
}
|
||||
|
||||
//not an else in case theres no DB food
|
||||
if (foragedfood == 0) {
|
||||
if (foragedfood == 0 && RuleB(Character, UseForageCommonFood)) {
|
||||
uint8 index = 0;
|
||||
index = zone->random.Int(0, MAX_COMMON_FOOD_IDS-1);
|
||||
foragedfood = common_food_ids[index];
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
|
||||
void command_acceptrules(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (!database.GetAgreementFlag(c->AccountID())) {
|
||||
database.SetAgreementFlag(c->AccountID());
|
||||
c->SendAppearancePacket(AT_Anim, ANIM_STAND);
|
||||
c->Message(Chat::White, "It is recorded you have agreed to the rules.");
|
||||
if (database.GetAgreementFlag(c->AccountID())) {
|
||||
c->Message(Chat::White, "You have already agreed to the rules.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
database.SetAgreementFlag(c->AccountID());
|
||||
c->SendAppearancePacket(AT_Anim, ANIM_STAND);
|
||||
c->Message(Chat::White, "It is recorded you have agreed to the rules.");
|
||||
}
|
||||
|
||||
@@ -23,10 +23,7 @@ void command_castspell(Client *c, const Seperator *sep)
|
||||
|
||||
const uint16 spell_id = Strings::ToUnsignedInt(sep->arg[1]);
|
||||
|
||||
if (IsCastRestrictedSpell(spell_id) && c->Admin() < commandCastSpecials) {
|
||||
c->Message(Chat::White, "Unable to cast spell.");
|
||||
return;
|
||||
} else if (spell_id >= SPDAT_RECORDS) {
|
||||
if (spell_id >= SPDAT_RECORDS) {
|
||||
c->Message(Chat::White, "Invalid Spell ID.");
|
||||
return;
|
||||
}
|
||||
|
||||
+113
-182
@@ -9,18 +9,22 @@ void command_corpse(Client *c, const Seperator *sep)
|
||||
c->Message(Chat::White, "Usage: #corpse deletenpccorpses - Deletes all NPC corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse inspectloot - Inspects the loot on a corpse");
|
||||
c->Message(Chat::White, "Usage: #corpse listnpc - Lists all NPC corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse lock - Locks the corpse, only GMs can loot the corpse when it is locked");
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"Usage: #corpse lock - Locks the corpse, only GMs can loot the corpse when it is locked"
|
||||
);
|
||||
c->Message(Chat::White, "Usage: #corpse removecash - Removes the cash from a corpse");
|
||||
c->Message(Chat::White, "Usage: #corpse unlock - Unlocks the corpses, allowing non-GMs to loot the corpse");
|
||||
if (c->Admin() >= commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Usage: #corpse charid [Character ID] - Change player corpse's owner");
|
||||
c->Message(Chat::White, "Usage: #corpse deleteplayercorpses - Deletes all player corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse depop [Bury] - Depops single target corpse.");
|
||||
c->Message(Chat::White, "Usage: #corpse depopall [Bury] - Depops all target player's corpses.");
|
||||
c->Message(Chat::White, "Usage: #corpse listplayer - Lists all player corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse moveallgraveyard - Moves all player corpses to the current zone's graveyard or non-instance");
|
||||
c->Message(Chat::White, "Note: Set bury to 0 to skip burying the corpses.");
|
||||
}
|
||||
c->Message(Chat::White, "Usage: #corpse charid [Character ID] - Change player corpse's owner");
|
||||
c->Message(Chat::White, "Usage: #corpse deleteplayercorpses - Deletes all player corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse depop [Bury] - Depops single target corpse.");
|
||||
c->Message(Chat::White, "Usage: #corpse depopall [Bury] - Depops all target player's corpses.");
|
||||
c->Message(Chat::White, "Usage: #corpse listplayer - Lists all player corpses");
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"Usage: #corpse moveallgraveyard - Moves all player corpses to the current zone's graveyard or non-instance"
|
||||
);
|
||||
c->Message(Chat::White, "Note: Set bury to 0 to skip burying the corpses.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -59,72 +63,57 @@ void command_corpse(Client *c, const Seperator *sep)
|
||||
c->Message(Chat::White, "Usage: #corpse deletenpccorpses - Deletes all NPC corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse inspectloot - Inspects the loot on a corpse");
|
||||
c->Message(Chat::White, "Usage: #corpse listnpc - Lists all NPC corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse lock - Locks the corpse, only GMs can loot the corpse when it is locked");
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"Usage: #corpse lock - Locks the corpse, only GMs can loot the corpse when it is locked"
|
||||
);
|
||||
c->Message(Chat::White, "Usage: #corpse removecash - Removes the cash from a corpse");
|
||||
c->Message(Chat::White, "Usage: #corpse unlock - Unlocks the corpses, allowing non-GMs to loot the corpse");
|
||||
if (c->Admin() >= commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Usage: #corpse charid [Character ID] - Change player corpse's owner");
|
||||
c->Message(Chat::White, "Usage: #corpse deleteplayercorpses - Deletes all player corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse depop [Bury] - Depops single target corpse.");
|
||||
c->Message(Chat::White, "Usage: #corpse depopall [Bury] - Depops all target player's corpses.");
|
||||
c->Message(Chat::White, "Usage: #corpse listplayer - Lists all player corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse moveallgraveyard - Moves all player corpses to the current zone's graveyard or non-instance");
|
||||
c->Message(Chat::White, "Note: Set bury to 0 to skip burying the corpses.");
|
||||
}
|
||||
c->Message(Chat::White, "Usage: #corpse charid [Character ID] - Change player corpse's owner");
|
||||
c->Message(Chat::White, "Usage: #corpse deleteplayercorpses - Deletes all player corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse depop [Bury] - Depops single target corpse.");
|
||||
c->Message(Chat::White, "Usage: #corpse depopall [Bury] - Depops all target player's corpses.");
|
||||
c->Message(Chat::White, "Usage: #corpse listplayer - Lists all player corpses");
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"Usage: #corpse moveallgraveyard - Moves all player corpses to the current zone's graveyard or non-instance"
|
||||
);
|
||||
c->Message(Chat::White, "Note: Set bury to 0 to skip burying the corpses.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (is_delete_player_corpses) {
|
||||
if (c->Admin() >= commandEditPlayerCorpses) {
|
||||
auto corpses_deleted = entity_list.DeletePlayerCorpses();
|
||||
auto deleted_string = (
|
||||
corpses_deleted ?
|
||||
fmt::format(
|
||||
"{} Player corpse{} deleted.",
|
||||
corpses_deleted,
|
||||
corpses_deleted != 1 ? "s" : ""
|
||||
) :
|
||||
"There are no player corpses to delete."
|
||||
);
|
||||
c->Message(Chat::White, deleted_string.c_str());
|
||||
} else {
|
||||
c->Message(Chat::White, "Your status is not high enough to delete player corpses.");
|
||||
return;
|
||||
}
|
||||
auto corpses_deleted = entity_list.DeletePlayerCorpses();
|
||||
auto deleted_string = (
|
||||
corpses_deleted ?
|
||||
fmt::format(
|
||||
"{} Player corpse{} deleted.",
|
||||
corpses_deleted,
|
||||
corpses_deleted != 1 ? "s" : ""
|
||||
) :
|
||||
"There are no player corpses to delete."
|
||||
);
|
||||
c->Message(Chat::White, deleted_string.c_str());
|
||||
} else if (is_delete) {
|
||||
if (!target || !target->IsCorpse()) {
|
||||
c->Message(Chat::White, "You must target a corpse to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Your status is not high enough to delete a player corpse.");
|
||||
return;
|
||||
}
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Deleting {} corpse {}.",
|
||||
target->IsNPCCorpse() ? "NPC" : "player",
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
if (
|
||||
target->IsNPCCorpse() ||
|
||||
c->Admin() >= commandEditPlayerCorpses
|
||||
) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Deleting {} corpse {}.",
|
||||
target->IsNPCCorpse() ? "NPC" : "player",
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
target->CastToCorpse()->Delete();
|
||||
}
|
||||
target->CastToCorpse()->Delete();
|
||||
} else if (is_list_npc) {
|
||||
entity_list.ListNPCCorpses(c);
|
||||
} else if (is_list_player) {
|
||||
if (c->Admin() < commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Your status is not high enough to list player corpses.");
|
||||
return;
|
||||
}
|
||||
|
||||
entity_list.ListPlayerCorpses(c);
|
||||
} else if (is_delete_npc_corpses) {
|
||||
auto corpses_deleted = entity_list.DeleteNPCCorpses();
|
||||
@@ -139,42 +128,32 @@ void command_corpse(Client *c, const Seperator *sep)
|
||||
);
|
||||
c->Message(Chat::White, deleted_string.c_str());
|
||||
} else if (is_character_id) {
|
||||
if (c->Admin() >= commandEditPlayerCorpses) {
|
||||
if (!target || !target->IsPlayerCorpse()) {
|
||||
c->Message(Chat::White, "You must target a player corpse to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sep->IsNumber(2)) {
|
||||
c->Message(Chat::White, "Usage: #corpse charid [Character ID] - Change player corpse's owner");
|
||||
return;
|
||||
}
|
||||
|
||||
auto character_id = Strings::ToInt(sep->arg[2]);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Setting the owner to {} ({}) for the player corpse {}.",
|
||||
database.GetCharNameByID(character_id),
|
||||
target->CastToCorpse()->SetCharID(character_id),
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
c->Message(Chat::White, "Your status is not high enough to modify a player corpse's owner.");
|
||||
if (!target || !target->IsPlayerCorpse()) {
|
||||
c->Message(Chat::White, "You must target a player corpse to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sep->IsNumber(2)) {
|
||||
c->Message(Chat::White, "Usage: #corpse charid [Character ID] - Change player corpse's owner");
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32 character_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Setting the owner to {} ({}) for the player corpse {}.",
|
||||
database.GetCharNameByID(character_id),
|
||||
target->CastToCorpse()->SetCharID(character_id),
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
} else if (is_reset_looter) {
|
||||
if (!target || !target->IsCorpse()) {
|
||||
c->Message(Chat::White, "You must target a corpse to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Your status is not high enough to reset looter on a player corpse.");
|
||||
return;
|
||||
}
|
||||
|
||||
target->CastToCorpse()->ResetLooter();
|
||||
c->Message(
|
||||
Chat::White,
|
||||
@@ -190,36 +169,22 @@ void command_corpse(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Your status is not high enough to remove cash from a player corpse.");
|
||||
return;
|
||||
}
|
||||
target->CastToCorpse()->RemoveCash();
|
||||
|
||||
if (
|
||||
target->IsNPCCorpse() ||
|
||||
c->Admin() >= commandEditPlayerCorpses
|
||||
) {
|
||||
target->CastToCorpse()->RemoveCash();
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Removed cash from {} corpse {}.",
|
||||
target->IsNPCCorpse() ? "NPC" : "player",
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Removed cash from {} corpse {}.",
|
||||
target->IsNPCCorpse() ? "NPC" : "player",
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
} else if (is_inspect_loot) {
|
||||
if (!target || !target->IsCorpse()) {
|
||||
c->Message(Chat::White, "You must target a corpse to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Your status is not high enough to inspect the loot of a player corpse.");
|
||||
return;
|
||||
}
|
||||
|
||||
target->CastToCorpse()->QueryLoot(c);
|
||||
} else if (is_lock) {
|
||||
if (!target || !target->IsCorpse()) {
|
||||
@@ -227,11 +192,6 @@ void command_corpse(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Your status is not high enough to lock player corpses.");
|
||||
return;
|
||||
}
|
||||
|
||||
target->CastToCorpse()->Lock();
|
||||
c->Message(
|
||||
Chat::White,
|
||||
@@ -247,11 +207,6 @@ void command_corpse(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Your status is not high enough to unlock player corpses.");
|
||||
return;
|
||||
}
|
||||
|
||||
target->CastToCorpse()->UnLock();
|
||||
c->Message(
|
||||
Chat::White,
|
||||
@@ -267,30 +222,20 @@ void command_corpse(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
if (c->Admin() >= commandEditPlayerCorpses) {
|
||||
bool bury_corpse = (
|
||||
sep->IsNumber(2) ?
|
||||
(
|
||||
Strings::ToInt(sep->arg[2]) != 0 ?
|
||||
true :
|
||||
false
|
||||
) :
|
||||
false
|
||||
);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Depopping player corpse {}.",
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
target->CastToCorpse()->DepopPlayerCorpse();
|
||||
if (bury_corpse) {
|
||||
target->CastToCorpse()->Bury();
|
||||
}
|
||||
} else {
|
||||
c->Message(Chat::White, "Your status is not high enough to depop a player corpse.");
|
||||
return;
|
||||
const bool bury_corpse = sep->IsNumber(2) ? Strings::ToBool(sep->arg[2]) : false;
|
||||
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Depopping player corpse {}.",
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
target->CastToCorpse()->DepopPlayerCorpse();
|
||||
|
||||
if (bury_corpse) {
|
||||
target->CastToCorpse()->Bury();
|
||||
}
|
||||
} else if (is_depop_all) {
|
||||
if (!target || !target->IsClient()) {
|
||||
@@ -298,50 +243,36 @@ void command_corpse(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
if (c->Admin() >= commandEditPlayerCorpses) {
|
||||
bool bury_corpse = (
|
||||
sep->IsNumber(2) ?
|
||||
(
|
||||
Strings::ToInt(sep->arg[2]) != 0 ?
|
||||
true :
|
||||
false
|
||||
) :
|
||||
false
|
||||
);
|
||||
const bool bury_corpse = sep->IsNumber(2) ? Strings::ToBool(sep->arg[2]) : false;
|
||||
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Depopping all player corpses for {}.",
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
target->CastToClient()->DepopAllCorpses();
|
||||
|
||||
if (bury_corpse) {
|
||||
target->CastToClient()->BuryPlayerCorpses();
|
||||
}
|
||||
} else if (is_move_all_to_graveyard) {
|
||||
const int moved_count = entity_list.MovePlayerCorpsesToGraveyard(true);
|
||||
if (moved_count) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Depopping all player corpses for {}.",
|
||||
c->GetTargetDescription(target)
|
||||
"Moved {} player corpse{} to graveyard in {} ({}).",
|
||||
moved_count,
|
||||
moved_count != 1 ? "s" : "",
|
||||
ZoneLongName(zone->GetZoneID()),
|
||||
ZoneName(zone->GetZoneID())
|
||||
).c_str()
|
||||
);
|
||||
target->CastToClient()->DepopAllCorpses();
|
||||
if (bury_corpse) {
|
||||
target->CastToClient()->BuryPlayerCorpses();
|
||||
}
|
||||
} else {
|
||||
c->Message(Chat::White, "Your status is not high enough to depop all of a player's corpses.");
|
||||
return;
|
||||
}
|
||||
} else if (is_move_all_to_graveyard) {
|
||||
int moved_count = entity_list.MovePlayerCorpsesToGraveyard(true);
|
||||
if (c->Admin() >= commandEditPlayerCorpses) {
|
||||
if (moved_count) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Moved {} player corpse{} to graveyard in {} ({}).",
|
||||
moved_count,
|
||||
moved_count != 1 ? "s" : "",
|
||||
ZoneLongName(zone->GetZoneID()),
|
||||
ZoneName(zone->GetZoneID())
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
c->Message(Chat::White, "There are no player corpses to move to the graveyard.");
|
||||
}
|
||||
} else {
|
||||
c->Message(Chat::White, "Your status is not high enough to move all player corpses to the graveyard.");
|
||||
c->Message(Chat::White, "There are no player corpses to move to the graveyard.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,24 +2,27 @@
|
||||
|
||||
void command_disarmtrap(Client *c, const Seperator *sep)
|
||||
{
|
||||
Mob *target = c->GetTarget();
|
||||
|
||||
if (!target) {
|
||||
c->Message(Chat::Red, "You must have a target.");
|
||||
Mob *t = c->GetTarget();
|
||||
if (!t || !t->IsNPC()) {
|
||||
c->Message(Chat::White, "You must target an NPC to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (target->IsNPC()) {
|
||||
if (c->HasSkill(EQ::skills::SkillDisarmTraps)) {
|
||||
if (DistanceSquaredNoZ(c->GetPosition(), target->GetPosition()) > RuleI(Adventure, LDoNTrapDistanceUse)) {
|
||||
c->Message(Chat::Red, "%s is too far away.", target->GetCleanName());
|
||||
return;
|
||||
}
|
||||
c->HandleLDoNDisarm(target->CastToNPC(), c->GetSkill(EQ::skills::SkillDisarmTraps), LDoNTypeMechanical);
|
||||
}
|
||||
else {
|
||||
c->Message(Chat::Red, "You do not have the disarm trap skill.");
|
||||
}
|
||||
if (!c->HasSkill(EQ::skills::SkillDisarmTraps)) {
|
||||
c->Message(Chat::White, "You do not have the Disarm Trap skill.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (DistanceSquaredNoZ(c->GetPosition(), t->GetPosition()) > RuleI(Adventure, LDoNTrapDistanceUse)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} is too far away.",
|
||||
t->GetCleanName()
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
c->HandleLDoNDisarm(t->CastToNPC(), c->GetSkill(EQ::skills::SkillDisarmTraps), LDoNTypeMechanical);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user