Compare commits

...

31 Commits

Author SHA1 Message Date
Chris Miles 703862d977 [Release] 22.37.0 (#3789) 2023-12-18 15:43:09 -06:00
nytmyr 6e325c1ee3 [Bots] Fix unnecessary failed to save timer error (#3788) 2023-12-18 15:39:14 -06:00
nytmyr 933b83add6 [Bots] Fix ^defensive from checking aggressive disciplines. (#3787)
Bots were checking for aggressive disciplines with both ^aggressive and ^defensive.
2023-12-18 15:38:37 -06:00
Alex King b3cd4e63f1 [Bug Fix] Drop Invisibility when hit by traps (#3785)
# Notes
- Resolves https://github.com/EQEmu/Server/issues/663.

# Video
[Drop Invisibility Trap Test](https://github.com/EQEmu/Server/assets/89047260/d6e96704-ee6d-4b16-bd52-4122e3b37577)
2023-12-18 15:37:53 -06:00
nytmyr 3c894cb533 [Bots] Add ScanCloseMobs support to fix AEs (#3786)
Previously bots were only scanning for nearby clients so any AE spells or procs didn't have mobs to hit.

This changes that to scan for mobs instead of clients so their close entity list supports AEs with mobs to hit.
2023-12-18 15:37:07 -06:00
Alex King b19ad64800 [Bug Fix] Send Entity ID in Death Events to resolve #3721 (#3779)
* [Bug Fix] Send Entity ID in Death Events to resolve #3721

# Notes
- Due to some pointers becoming invalid you may get an invalid entity ID on the killed mob if we don't just directly send the entity ID in the export string.

* Update attack.cpp

* Remove GetID() export.
2023-12-17 19:43:41 -06:00
Alex King 2cd3d27c67 [Quest API] Add GetNPCAggro() and SetNPCAggro() to Perl/Lua (#3781)
* [Quest API] Add GetNPCAggro() and SetNPCAggro() to Perl/Lua

# Perl
- Add `$npc->GetNPCAggro()`.
- Add `$npc->SetNPCAggro(in_npc_aggro)`.

# Lua
- Add `npc:GetNPCAggro()`.
- Add `npc:SetNPCAggro(in_npc_aggro)`.

# Notes
- Allows operators to enable or disable an NPC's NPC aggro capability dynamically.

* Update api_service.cpp
2023-12-17 20:34:06 -05:00
Alex King d3b46becd0 [Bug Fix] Fix NPCs routing to 0.0, 0.0 on #summon (#3780)
# Notes
- Resolves #2474.
2023-12-17 20:24:24 -05:00
Chris Miles 286479198f [Compilation] Use pre-compiled headers for Windows (speed) (#3778)
* Experiment with PCH

* Another run

* GCC test

* Different test

* Another one

* Another one

* Lua headers

* PCH main zone primitives

* Tweaks

* Tweaks

* Tweaks

* Add EQEMU_BUILD_PCH option default to ON
2023-12-17 19:04:21 -06:00
Chris Miles 21ec832ca6 [CI] Switch to use clang for Linux builds (speed) (#3777) 2023-12-17 15:17:29 -06:00
nytmyr bdf5f8b4a3 [Bots] [Quest API] Add ^clickitem, ^timer, fix GetBestBotSpellForCure (#3755)
* [Bots][Quest API] Add ^clickitem, ^timer, revamp bot timers, fix GetBestBotSpellForCure

This adds the command **^clickitem** for bots.
Bots can click items they are wearing with the provided slot ID, players can use **^invlist** on their bots to see items and slot IDs.
This supports actionables.
**^itemclick 13 byclass 11** would command all Necromancer bots to attempt to click their Primary item.

This adds and supports charges for items to bots, when an item is used, it will lose a charge and cannot be clicked once no charges remain.

This adds the following rules:
**Bots, BotsClickItemsMinLvl** - Minimum level bots can use **^clickitem**.
**Bots, BotsCanClickItems** - Whether or not **^clickitem** is allowed for bots.
**Bots, CanClickMageEpicV1** - Whether or not players are allowed to command their bots to use the Magician Epic 1.0

This adds quest methods to Perl/Lua for:
ClearDisciplineReuseTimer, ClearItemReuseTimer, ClearSpellRecastTimer
GetDisciplineReuseTimer, GetItemReuseTimer, GetSpellRecastTimer
SetDisciplineReuseTimer, SetItemReuseTimer, SetSpellRecastTimer

Discipline and Spell methods use the spell_id to check, get and set. Item uses the item_id.
Clear and Get support wildcards (no spell/item id) to clear all timers of the type or get the first timer of the type.
Get will return the remaining time on the chosen timer, if any.
Set supports a wildcard (no recast/reuse provided) to use the default of the provided type, you can also specify a recast/reuse timer to set that timer to the chosen value.

**^timer** has been added as a bot command, defaulted for GM access.
This can be used to set, get and clear timers of different types. Use **^timer help** for info.

This revamps the way timers are set, stored, loaded for bots.

**GetBestBotSpellForCure** was previously checking only the first spell found and not properly iterating through the checks.

This requires modifications to the **bot_timers** table and is included in this commit.

* Rebase Conflicts

* Update queries to use repositories

* Minor adjustment

* Formatting

* Handle delete as well

* Cleanup.

* Adjust primary keys to prevent conflicts

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2023-12-17 14:53:34 -05:00
Alex King 4ca6485398 [Bug Fix] Fix issue with HOTBonusHealingSplitOverDuration Rule (#3776)
# Notes
- This rule didn't function properly since we didn't add extra heal regardless of rule setting.
2023-12-16 22:48:19 -06:00
Alex King 0c9c2e25c1 [Quest API] Add EVENT_CRYSTAL_GAIN and EVENT_CRYSTAL_LOSS to Perl/Lua (#3735)
* [Quest API] Add EVENT_CRYSTAL_GAIN and EVENT_CRYSTAL_LOSS

- Add `$client->AddEbonCrystals(amount)`.
- Add `$client->AddRadiantCrystals(amount)`.
- Add `$client->RemoveEbonCrystals(amount)`.
- Add `$client->RemoveRadiantCrystals(amount)`.
- Add `EVENT_CRYSTAL_GAIN`.
- Add `EVENT_CRYSTAL_LOSS`.
- Export `$ebon_amount`, `$radiant_amount`, and `$is_reclaim`.

- Add `client:AddEbonCrystals(amount)`.
- Add `client:AddRadiantCrystals(amount)`.
- Add `client:RemoveEbonCrystals(amount)`.
- Add `client:RemoveRadiantCrystals(amount)`.
- Add `event_crystal_gain`.
- Add `event_crystal_loss`.
- Export `e.ebon_amount`, `e.radiant_amount`, and `e.is_reclaim`.

- Allows operators to add or remove Ebon/Radiant Crystals directly.
- Allows operators to track gain/loss of Ebon/Radiant Crystals.

* Update perl_client.cpp

* Update lua_client.cpp
2023-12-16 22:47:13 -06:00
regneq 7e651877c7 [Bug Fix] Fixed the discrepacy with time using command #time and in quests. (#3767)
* [BUG] Fixed the discrepacy with time using command #time and in quests. https://github.com/EQEmu/Server/issues/3700

* removed comments and paratheses from previous commit.

* fixed typos.

* made some adjustment so #time, /time, scripting, and log all match.

* Update lua_general.cpp
2023-12-16 22:40:40 -06:00
Alex King 9739c1c8ef [Quest API] Add EVENT_ALT_CURRENCY_GAIN and EVENT_ALT_CURRENCY_LOSS to Perl/Lua (#3734)
* [Quest API] Add EVENT_ALT_CURRENCY_GAIN and EVENT_ALT_CURRENCY_LOSS

- Add `EVENT_ALT_CURRENCY_GAIN`.
- Add `EVENT_ALT_CURRENCY_LOSS`.
- Export `$currency_id`, `$amount`, and `$total.

- Add `event_alt_currency_gain`.
- Add `event_alt_currency_loss`.
- Export `e.currency_id`, `e.amount`, and `e.total.

- Convert `int8 method` to `bool is_scripted` in `Client::AddAlternateCurrencyValue`.
- Properly utilize `is_scripted` parameter in `perl_client.cpp`.
- Allows operators to perform events on alternate currency gains/losses.

* Update lua_general.cpp

* Cleanup types.

* Update lua_client.cpp
2023-12-16 22:40:24 -06:00
Alex King 8aae59eebe [Quest API] Add EVENT_LDON_POINTS_GAIN and EVENT_LDON_POINTS_LOSS to Perl/Lua (#3742)
* [Quest API] Add EVENT_LDON_POINTS_GAIN and EVENT_LDON_POINTS_LOSS to Perl/Lua

- Add `EVENT_LDON_POINTS_GAIN`.
- Add `EVENT_LDON_POINTS_LOSS`.
- Exports `$theme_id` and `$points`.

- Add `event_ldon_points_gain`.
- Add `event_ldon_points_loss`.
- Exports `e.theme_id` and `e.points`.

- Allows operators to track gain/loss of LDoN Points of any theme.

* Update client.cpp
2023-12-16 22:31:25 -06:00
Alex King c1b07afae9 [Quest API] Add EVENT_LOOT_ADDED to Perl/Lua (#3739)
* [Quest API] Add EVENT_ADDED_LOOT to Perl/Lua

# Perl
- Add `EVENT_ADDED_LOOT`.
- Exports `$item`, `$item_id`, `$item_name`, `$item_charges`, `$augment_one`, `$augment_two`, `$augment_three`, `$augment_four`, `$augment_five`, and `$augment_six`.

# Lua
- Add `event_added_loot`.
- Exports `e.item`, `e.item_id`, `e.item_name`, `e.item_charges`, `e.augment_one`, `e.augment_two`, `e.augment_three`, `e.augment_four`, `e.augment_five`, and `e.augment_six`.

# Notes
- Allows operators to perform events when loot is added to an NPC, such as removing the loot or keeping track of it.

* Update lua_parser_events.cpp

* Rename event.

* loot_added

* AddItem changese
2023-12-16 22:25:09 -06:00
Alex King 9c238cd08d [Quest API] Add EVENT_LEVEL_UP and EVENT_LEVEL_DOWN to Bots (#3750)
* [Quest API] Add EVENT_LEVEL_UP and EVENT_LEVEL_DOWN to bots

# Notes
- Bots did not have these events, this will allow operators to perform events on bot level up/down.

* Update bot.cpp
2023-12-16 22:23:38 -06:00
Akkadius 33adb9bcc1 [Hotfix] Fix bad merge 2023-12-16 21:06:36 -06:00
nytmyr 2e8bf82861 [Bots] Expand ^itemuse options (#3756)
Adds additional options to **^itemuse** to narrow down the list of accepting bots.

You can now specify by class, casters, hybrids, melee, WIS caster, INT caster or plate/chain/leather/cloth wearing.
2023-12-16 20:54:23 -05:00
nytmyr 4d118ab978 [Bots] Fix ^oo autodefend from sending bots/pets to invalid haters (#3772)
Bots and especially their pets could get in a loop where they try to attack an invalid target. This would result in their pets spamming "That is not a legal target" messages.
2023-12-16 16:08:16 -05:00
Chris Miles fcb40daaf1 [Release] 22.36.0 (#3774) 2023-12-16 01:07:19 -06:00
Alex King 553bafdbe1 [Bug Fix] Fix Starting Items SQL (#3766)
* [Bug Fix] Fix Starting Items SQL

# Notes
- `race_list` comes before `class_list`,query had them in the wrong order.

* Real fix.

* Update database_update_manifest.cpp

* Manifest change

* Repository generate

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-12-16 00:45:27 -06:00
Chris Miles d0443db199 [Database] When database version is greater than binary, we are up to date (#3771) 2023-12-16 00:44:40 -06:00
Chris Miles 9206163190 [Database] Make it clearer to users that a database backup is occurring (#3769) 2023-12-16 00:44:25 -06:00
Chris Miles e504482b94 [Corpse] Fix /corpse command regression from #3727 (#3770) 2023-12-16 00:44:11 -06:00
Alex King 77b88e3dec [Rules] Add DOT and HOT Rules (#3760)
* [Rules] Add DOT and HOT Rules

# Notes
- Add `Spells:DOTDamageBonusSplitOverDuration` rule.
- Allows operators to disable the DOT bonus damage being split over duration and instead adds the full amount every tic.
- Add `Spells:HOTBonusHealingSplitOverDuration` rule.
- Allows operators to disable the HOT bonus healing being split over duration and instead adds the full amount every tic.

* Update effects.cpp

* Update effects.cpp
2023-12-15 19:25:38 -06:00
Alex King aeeb350068 [Cleanup] Cleanup classes.cpp/classes.h (#3752)
* [Cleanup] Cleanup classes.cpp/classes.h

# Notes
- Remove unused methods and cleanup logic.

* Update classes.cpp

* Final push.
2023-12-13 18:38:45 -05:00
nytmyr df83113cea [Bots] Enable auto-saving of bots. (#3758)
Adds the rule **Bots, AutosaveIntervalSeconds** to control the frequency of the autosave of bots. Currently they only fully save on camp/zone.

Co-authored-by: Alex King <89047260+Kinglykrab@users.noreply.github.com>
2023-12-12 22:22:44 -05:00
nytmyr 940abfaf7a [Logging] Change empty object loading to warning (#3759) 2023-12-11 17:06:29 -05:00
nytmyr a46443b95e [Bots] Add rule to toggle DT hitting owner (#3757)
**Bots, CazicTouchBotsOwner** is a rule that will toggle whether or not DT will hit the targeted bot or the owner. Similar to how **Spells, CazicTouchTargetsPetOwner** functions except for  bots.
2023-12-11 14:31:33 -05:00
90 changed files with 4092 additions and 2235 deletions
+1 -1
View File
@@ -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
+69
View File
@@ -1,3 +1,72 @@
## [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
+1
View File
@@ -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)
+3
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+96 -93
View File
@@ -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);
@@ -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()) {
+2 -2
View File
@@ -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;
}
@@ -5116,6 +5116,23 @@ ALTER TABLE `object` CHANGE COLUMN `unknown20` `incline` int(11) NOT NULL DEFAUL
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`;
)"
}
@@ -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
+6
View File
@@ -124,6 +124,12 @@ struct LDoNTrapTemplate
uint8 locked;
};
enum CrystalReclaimTypes
{
Ebon = 5,
Radiant = 4,
};
///////////////////////////////////////////////////////////////////////////////
+1 -1
View File
@@ -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_0, 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);
+4 -4
View File
@@ -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
@@ -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);
+3 -3
View File
@@ -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
@@ -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);
+34
View File
@@ -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>
@@ -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);
}
@@ -21,14 +21,14 @@ class BaseStartingItemsRepository {
public:
struct StartingItems {
uint32_t id;
std::string race_list;
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;
uint8_t gm;
int32_t slot;
int32_t status;
int32_t inventory_slot;
int8_t min_expansion;
int8_t max_expansion;
std::string content_flags;
@@ -44,14 +44,14 @@ public:
{
return {
"id",
"race_list",
"class_list",
"race_list",
"deity_list",
"zone_id_list",
"item_id",
"item_charges",
"gm",
"slot",
"status",
"inventory_slot",
"min_expansion",
"max_expansion",
"content_flags",
@@ -63,14 +63,14 @@ public:
{
return {
"id",
"race_list",
"class_list",
"race_list",
"deity_list",
"zone_id_list",
"item_id",
"item_charges",
"gm",
"slot",
"status",
"inventory_slot",
"min_expansion",
"max_expansion",
"content_flags",
@@ -116,14 +116,14 @@ public:
StartingItems e{};
e.id = 0;
e.race_list = "";
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 = "";
@@ -165,14 +165,14 @@ public:
StartingItems e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.race_list = row[1] ? row[1] : "";
e.class_list = row[2] ? row[2] : "";
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<uint8_t>(strtoul(row[7], nullptr, 10));
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] : "";
@@ -210,14 +210,14 @@ public:
auto columns = Columns();
v.push_back(columns[1] + " = '" + Strings::Escape(e.race_list) + "'");
v.push_back(columns[2] + " = '" + Strings::Escape(e.class_list) + "'");
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) + "'");
@@ -244,14 +244,14 @@ public:
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.race_list) + "'");
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) + "'");
@@ -286,14 +286,14 @@ public:
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.race_list) + "'");
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) + "'");
@@ -332,14 +332,14 @@ public:
StartingItems e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.race_list = row[1] ? row[1] : "";
e.class_list = row[2] ? row[2] : "";
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<uint8_t>(strtoul(row[7], nullptr, 10));
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] : "";
@@ -369,14 +369,14 @@ public:
StartingItems e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.race_list = row[1] ? row[1] : "";
e.class_list = row[2] ? row[2] : "";
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<uint8_t>(strtoul(row[7], nullptr, 10));
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] : "";
+8
View File
@@ -305,6 +305,7 @@ RULE_BOOL(World, EnableChecksumVerification, false, "Enable or Disable the Check
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)
@@ -458,6 +459,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)
@@ -651,6 +654,11 @@ RULE_INT(Bots, OldResurrectionSicknessSpell, 757, "757 is Default Old Resurrecti
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)
+5 -5
View File
@@ -506,7 +506,7 @@ bool SharedDatabase::SetStartingItems(
for (const auto &e : v) {
const uint32 item_id = e.item_id;
const uint8 item_charges = e.item_charges;
int32 slot = e.slot;
int32 slot = e.inventory_slot;
item_data = GetItem(item_id);
@@ -1808,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);
@@ -1848,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) {
@@ -1878,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) {
@@ -2061,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
View File
@@ -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
View File
@@ -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
View File
@@ -25,7 +25,7 @@
// Build variables
// these get injected during the build pipeline
#define CURRENT_VERSION "22.35.0-dev" // always append -dev to the current version for custom-builds
#define CURRENT_VERSION "22.37.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 9246
#define CURRENT_BINARY_DATABASE_VERSION 9247
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9040
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9041
#endif
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "eqemu-server",
"version": "22.35.0",
"version": "22.37.0",
"repository": {
"type": "git",
"url": "https://github.com/EQEmu/Server.git"
+1 -1
View File
@@ -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));
+2 -2
View File
@@ -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))
+4
View File
@@ -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
View File
@@ -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:
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -434,7 +434,7 @@ int main(int argc, char **argv)
tod.year,
tod.month,
tod.day,
tod.hour,
tod.hour - 1,
tod.minute
);
}
+6
View File
@@ -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})
+17 -17
View File
@@ -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;
}
+5 -5
View File
@@ -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;
}
@@ -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;
+1 -1
View File
@@ -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);
}
+161 -161
View File
@@ -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))
@@ -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);
}
}
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);
}
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())))
@@ -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;
}
@@ -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
View File
@@ -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.
}
+830 -191
View File
File diff suppressed because it is too large Load Diff
+35 -17
View File
@@ -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;
+435 -98
View File
@@ -84,8 +84,8 @@ namespace
enum { EffectIDFirst = 1, EffectIDLast = 12 };
#define VALIDATECLASSID(x) ((x >= WARRIOR && x <= BERSERKER) ? (x) : (0))
#define CLASSIDTOINDEX(x) ((x >= WARRIOR && x <= BERSERKER) ? (x - 1) : (0))
#define VALIDATECLASSID(x) ((x >= Class::Warrior && x <= Class::Berserker) ? (x) : (0))
#define CLASSIDTOINDEX(x) ((x >= Class::Warrior && x <= Class::Berserker) ? (x - 1) : (0))
#define EFFECTIDTOINDEX(x) ((x >= EffectIDFirst && x <= EffectIDLast) ? (x - 1) : (0))
#define AILMENTIDTOINDEX(x) ((x >= BCEnum::AT_Blindness && x <= BCEnum::AT_Corruption) ? (x - 1) : (0))
#define RESISTANCEIDTOINDEX(x) ((x >= BCEnum::RT_Fire && x <= BCEnum::RT_Corruption) ? (x - 1) : (0))
@@ -196,7 +196,7 @@ public:
uint8 class_levels[16] = {0};
bool player_spell = false;
for (int class_type = WARRIOR; class_type <= BERSERKER; ++class_type) {
for (int class_type = Class::Warrior; class_type <= Class::Berserker; ++class_type) {
int class_index = CLASSIDTOINDEX(class_type);
if (spells[spell_id].classes[class_index] == 0 ||
spells[spell_id].classes[class_index] > HARD_LEVEL_CAP) {
@@ -489,7 +489,7 @@ public:
entry_prototype->target_type = target_type;
bcst_levels& bot_levels = bot_levels_map[entry_prototype->BCST()];
for (int class_type = WARRIOR; class_type <= BERSERKER; ++class_type) {
for (int class_type = Class::Warrior; class_type <= Class::Berserker; ++class_type) {
int class_index = CLASSIDTOINDEX(class_type);
if (!class_levels[class_index])
continue;
@@ -1119,7 +1119,7 @@ private:
}
static void helper_bots_string(BCEnum::SpType type_index, bcst_levels& bot_levels) {
for (int i = WARRIOR; i <= BERSERKER; ++i)
for (int i = Class::Warrior; i <= Class::Berserker; ++i)
required_bots_map_by_class[type_index][i] = "Unavailable...";
if (bot_levels.empty()) {
@@ -1375,6 +1375,7 @@ int bot_command_init(void)
bot_command_add("casterrange", "Controls the range casters will try to stay away from a mob (if too far, they will skip spells that are out-of-range)", AccountStatus::Player, bot_command_caster_range) ||
bot_command_add("charm", "Attempts to have a bot charm your target", AccountStatus::Player, bot_command_charm) ||
bot_command_add("circle", "Orders a Druid bot to open a magical doorway to a specified destination", AccountStatus::Player, bot_subcommand_circle) ||
bot_command_add("clickitem", "Orders your targeted bot to click the item in the provided inventory slot.", AccountStatus::Player, bot_command_click_item) ||
bot_command_add("cure", "Orders a bot to remove any ailments", AccountStatus::Player, bot_command_cure) ||
bot_command_add("defensive", "Orders a bot to use a defensive discipline", AccountStatus::Player, bot_command_defensive) ||
bot_command_add("depart", "Orders a bot to open a magical doorway to a specified destination", AccountStatus::Player, bot_command_depart) ||
@@ -1444,6 +1445,7 @@ int bot_command_init(void)
bot_command_add("summoncorpse", "Orders a bot to summon a corpse to its feet", AccountStatus::Player, bot_command_summon_corpse) ||
bot_command_add("suspend", "Suspends a bot's AI processing until released", AccountStatus::Player, bot_command_suspend) ||
bot_command_add("taunt", "Toggles taunt use by a bot", AccountStatus::Player, bot_command_taunt) ||
bot_command_add("timer", "Checks or clears timers of the chosen type.", AccountStatus::GMMgmt, bot_command_timer) ||
bot_command_add("track", "Orders a capable bot to track enemies", AccountStatus::Player, bot_command_track) ||
bot_command_add("viewcombos", "Views bot race class combinations", AccountStatus::Player, bot_command_view_combos) ||
bot_command_add("waterbreathing", "Orders a bot to cast a water breathing spell", AccountStatus::Player, bot_command_water_breathing)
@@ -2377,7 +2379,7 @@ namespace ActionableBots
else if (!ab_type_arg.compare("healrotationtargets")) {
ab_type = ABT_HealRotationTargets;
}
else if (!ab_type_arg.compare("byclass")) {
else if (!ab_type_arg.compare("byclass")) {
ab_type = ABT_Class;
}
else if (!ab_type_arg.compare("byrace")) {
@@ -2730,9 +2732,9 @@ namespace ActionableBots
static void Filter_ByHighestPickLock(Client* bot_owner, std::list<Bot*>& sbl, float& pick_lock_value) {
sbl.remove_if([bot_owner](Bot* l) { return (!MyBots::IsMyBot(bot_owner, l)); });
sbl.remove_if([bot_owner](const Bot* l) { return (l->GetClass() != ROGUE && l->GetClass() != BARD); });
sbl.remove_if([bot_owner](const Bot* l) { return (l->GetClass() == ROGUE && l->GetLevel() < 5); });
sbl.remove_if([bot_owner](const Bot* l) { return (l->GetClass() == BARD && l->GetLevel() < 40); });
sbl.remove_if([bot_owner](const Bot* l) { return (l->GetClass() != Class::Rogue && l->GetClass() != Class::Bard); });
sbl.remove_if([bot_owner](const Bot* l) { return (l->GetClass() == Class::Rogue && l->GetLevel() < 5); });
sbl.remove_if([bot_owner](const Bot* l) { return (l->GetClass() == Class::Bard && l->GetLevel() < 40); });
ActionableBots::Filter_ByHighestSkill(bot_owner, sbl, EQ::skills::SkillPickLock, pick_lock_value);
}
@@ -2832,7 +2834,7 @@ void bot_command_aggressive(Client *c, const Seperator *sep)
}
}
c->Message(Chat::White, "%i of %i bots have used aggressive disciplines", success_count, candidate_count);
c->Message(Chat::White, "%i of %i bots have attempted to use aggressive disciplines", success_count, candidate_count);
}
void bot_command_apply_poison(Client *c, const Seperator *sep)
@@ -2856,7 +2858,7 @@ void bot_command_apply_poison(Client *c, const Seperator *sep)
t &&
t->IsBot() &&
t->CastToBot()->GetBotOwnerCharacterID() == c->CharacterID() &&
t->GetClass() == ROGUE
t->GetClass() == Class::Rogue
) {
my_rogue_bot = t->CastToBot();
}
@@ -2964,7 +2966,7 @@ void bot_command_apply_potion(Client* c, const Seperator* sep)
if (potion_data->ItemType == EQ::item::ItemTypePotion && potion_data->Click.Effect > 0) {
if (RuleB(Bots, RestrictApplyPotionToRogue) && potion_data->Classes != PLAYER_CLASS_ROGUE_BIT) {
if (RuleB(Bots, RestrictApplyPotionToRogue) && potion_data->Classes != player_class_bitmasks[Class::Rogue]) {
c->Message(Chat::White, "This command is restricted to rogue poison potions only!");
return;
@@ -3300,7 +3302,7 @@ void bot_command_defensive(Client *c, const Seperator *sep)
auto local_entry = list_iter->SafeCastToStance();
if (helper_spell_check_fail(local_entry))
continue;
if (local_entry->stance_type != BCEnum::StT_Aggressive)
if (local_entry->stance_type != BCEnum::StT_Defensive)
continue;
for (auto bot_iter = sbl.begin(); bot_iter != sbl.end(); ) {
@@ -3332,7 +3334,7 @@ void bot_command_defensive(Client *c, const Seperator *sep)
}
}
c->Message(Chat::White, "%i of %i bots have used defensive disciplines", success_count, candidate_count);
c->Message(Chat::White, "%i of %i bots have attempted to use defensive disciplines", success_count, candidate_count);
}
void bot_command_depart(Client *c, const Seperator *sep)
@@ -3353,8 +3355,8 @@ void bot_command_depart(Client *c, const Seperator *sep)
std::string destination = sep->arg[1];
if (!destination.compare("list")) {
Bot* my_druid_bot = ActionableBots::AsGroupMember_ByClass(c, c, DRUID);
Bot* my_wizard_bot = ActionableBots::AsGroupMember_ByClass(c, c, WIZARD);
Bot* my_druid_bot = ActionableBots::AsGroupMember_ByClass(c, c, Class::Druid);
Bot* my_wizard_bot = ActionableBots::AsGroupMember_ByClass(c, c, Class::Wizard);
helper_command_depart_list(c, my_druid_bot, my_wizard_bot, local_list, single);
return;
}
@@ -3906,16 +3908,77 @@ void bot_command_invisibility(Client *c, const Seperator *sep)
void bot_command_item_use(Client* c, const Seperator* sep)
{
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s ([empty])", sep->arg[0]);
c->Message(Chat::White, "usage: [%s empty] will display only bots that can use the item in an empty slot.", sep->arg[0]);
c->Message(Chat::White, "usage: [%s byclass classID] - Example: [%s byclass 7] will display only bots that match the class that can use the item. Example is a Monk, use [^create help] for a list of class IDs.", sep->arg[0], sep->arg[0]);
c->Message(Chat::White, "usage: [%s casteronly] will display only caster bots that can use the item.", sep->arg[0]);
c->Message(Chat::White, "usage: [%s hybridonly] will display only hybrid bots that can use the item.", sep->arg[0]);
c->Message(Chat::White, "usage: [%s meleeonly] will display only melee bots that can use the item.", sep->arg[0]);
c->Message(Chat::White, "usage: [%s wiscasteronly] will display only Wisdom-based Caster bots that can use the item.", sep->arg[0]);
c->Message(Chat::White, "usage: [%s intcasteronly] will display only Intelligence-based Caster bots that can use the item.", sep->arg[0]);
c->Message(Chat::White, "usage: [%s plateonly] will display only Plate-wearing bots that can use the item.", sep->arg[0]);
c->Message(Chat::White, "usage: [%s chainonly] will display only Chain-wearing bots that can use the item.", sep->arg[0]);
c->Message(Chat::White, "usage: [%s leatheronly] will display only Leather-wearing bots that can use the item.", sep->arg[0]);
c->Message(Chat::White, "usage: [%s clothonly] will display only Cloth-wearing bots that can use the item.", sep->arg[0]);
return;
}
bool empty_only = false;
int8 class_mask = 0;
bool caster_only = false;
bool hybrid_only = false;
bool melee_only = false;
bool wis_caster_only = false;
bool int_caster_only = false;
bool plate_only = false;
bool chain_only = false;
bool leather_only = false;
bool cloth_only = false;
std::string arg1 = sep->arg[1];
std::string arg2 = sep->arg[2];
if (arg1.compare("empty") == 0) {
empty_only = true;
}
else if (arg1.compare("byclass") == 0) {
if (Strings::IsNumber(sep->arg[2])) {
class_mask = Strings::ToUnsignedInt(sep->arg[2]);
if (!(class_mask >= Class::Warrior && class_mask <= Class::Berserker)) {
c->Message(Chat::White, "Invalid class range, you must choose between 1 (Warrior) and 15 (Beastlord)");
return;
}
}
}
else if (arg1.compare("casteronly") == 0) {
caster_only = true;
}
else if (arg1.compare("hybridonly") == 0) {
hybrid_only = true;
}
else if (arg1.compare("meleeonly") == 0) {
melee_only = true;
}
else if (arg1.compare("wiscasteronly") == 0) {
wis_caster_only = true;
}
else if (arg1.compare("intcasteronly") == 0) {
int_caster_only = true;
}
else if (arg1.compare("plateonly") == 0) {
plate_only = true;
}
else if (arg1.compare("chainonly") == 0) {
chain_only = true;
}
else if (arg1.compare("leatheronly") == 0) {
leather_only = true;
}
else if (arg1.compare("clothonly") == 0) {
cloth_only = true;
}
else if (!arg1.empty()) {
c->Message(Chat::White, "Please choose the correct subtype. For help use %s help.", sep->arg[0]);
return;
}
const auto item_instance = c->GetInv().GetItem(EQ::invslot::slotCursor);
if (!item_instance) {
c->Message(Chat::White, "No item found on cursor!");
@@ -3948,11 +4011,41 @@ void bot_command_item_use(Client* c, const Seperator* sep)
std::list<Bot*> sbl;
MyBots::PopulateSBL_BySpawnedBots(c, sbl);
if (class_mask) {
ActionableBots::Filter_ByClasses(c, sbl, GetPlayerClassBit(class_mask));
}
for (const auto& bot_iter : sbl) {
if (!bot_iter) {
continue;
}
if (caster_only && !IsCasterClass(bot_iter->GetClass())) {
continue;
}
if (hybrid_only && !IsSpellFighterClass(bot_iter->GetClass())) {
continue;
}
if (melee_only && !IsNonSpellFighterClass(bot_iter->GetClass())) {
continue;
}
if (wis_caster_only && !IsWISCasterClass(bot_iter->GetClass())) {
continue;
}
if (int_caster_only && !IsINTCasterClass(bot_iter->GetClass())) {
continue;
}
if (plate_only && !IsPlateClass(bot_iter->GetClass())) {
continue;
}
if (chain_only && !IsChainClass(bot_iter->GetClass())) {
continue;
}
if (leather_only && !IsLeatherClass(bot_iter->GetClass())) {
continue;
}
if (cloth_only && !IsClothClass(bot_iter->GetClass())) {
continue;
}
if (((~item_data->Races) & GetPlayerRaceBit(bot_iter->GetRace())) || ((~item_data->Classes) & GetPlayerClassBit(bot_iter->GetClass()))) {
continue;
}
@@ -3997,7 +4090,8 @@ void bot_command_item_use(Client* c, const Seperator* sep)
);
bot_iter->DoAnim(29);
} else if (!equipped_item) {
}
else if (!equipped_item) {
c->Message(
Chat::Say,
fmt::format(
@@ -4647,17 +4741,17 @@ void bot_command_pull(Client *c, const Seperator *sep)
}
switch (bot_iter->GetClass()) {
case ROGUE:
case MONK:
case BARD:
case RANGER:
case Class::Rogue:
case Class::Monk:
case Class::Bard:
case Class::Ranger:
bot_puller = bot_iter;
break;
case WARRIOR:
case SHADOWKNIGHT:
case PALADIN:
case BERSERKER:
case BEASTLORD:
case Class::Warrior:
case Class::ShadowKnight:
case Class::Paladin:
case Class::Berserker:
case Class::Beastlord:
if (!bot_puller) {
bot_puller = bot_iter;
@@ -4665,22 +4759,22 @@ void bot_command_pull(Client *c, const Seperator *sep)
}
switch (bot_puller->GetClass()) {
case DRUID:
case SHAMAN:
case CLERIC:
case WIZARD:
case NECROMANCER:
case MAGICIAN:
case ENCHANTER:
case Class::Druid:
case Class::Shaman:
case Class::Cleric:
case Class::Wizard:
case Class::Necromancer:
case Class::Magician:
case Class::Enchanter:
bot_puller = bot_iter;
default:
continue;
}
continue;
case DRUID:
case SHAMAN:
case CLERIC:
case Class::Druid:
case Class::Shaman:
case Class::Cleric:
if (!bot_puller) {
bot_puller = bot_iter;
@@ -4688,20 +4782,20 @@ void bot_command_pull(Client *c, const Seperator *sep)
}
switch (bot_puller->GetClass()) {
case WIZARD:
case NECROMANCER:
case MAGICIAN:
case ENCHANTER:
case Class::Wizard:
case Class::Necromancer:
case Class::Magician:
case Class::Enchanter:
bot_puller = bot_iter;
default:
continue;
}
continue;
case WIZARD:
case NECROMANCER:
case MAGICIAN:
case ENCHANTER:
case Class::Wizard:
case Class::Necromancer:
case Class::Magician:
case Class::Enchanter:
if (!bot_puller) {
bot_puller = bot_iter;
}
@@ -5194,6 +5288,194 @@ void bot_command_taunt(Client *c, const Seperator *sep)
}
}
void bot_command_timer(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_timer", sep->arg[0], "timer"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s [clear | has | set] [disc | item | spell] [timer ID | item ID | spell ID | all] [optional ms for set] [actionable].", sep->arg[0]);
c->Message(Chat::White, "When setting, you can leave the value blank to use the default for the item or specify a value in ms to set the timer to.");
c->Message(Chat::White, "Returns or sets the provided timer(s) for the selected bot(s) or clears the selected timer(s) for the selected bot(s).");
return;
}
const int ab_mask = ActionableBots::ABM_Type1;
std::string arg1 = sep->arg[1];
std::string arg2 = sep->arg[2];
std::string arg3 = sep->arg[3];
int ab_arg = 4;
bool clear = false;
bool has = false;
bool set = false;
bool disc = false;
bool item = false;
bool spell = false;
uint32 timer_id = 0;
uint32 timer_value = 0;
bool all = false;
if (!arg1.compare("clear")) {
clear = true;
}
else if (!arg1.compare("has")) {
has = true;
}
else if (!arg1.compare("set")) {
set = true;
}
else {
c->Message(Chat::White, "Incorrect argument, use %s help for a list of options.", sep->arg[0]);
return;
}
if (!arg2.compare("disc")) {
disc = true;
}
else if (!arg2.compare("item")) {
item = true;
}
else if (!arg2.compare("spell")) {
spell = true;
}
else {
c->Message(Chat::White, "Incorrect timer type, use %s help for a list of options.", sep->arg[0]);
return;
}
if (sep->IsNumber(3)) {
timer_id = atoi(sep->arg[3]);
if (timer_id < 0) {
c->Message(Chat::White, "You cannot use negative numbers.");
return;
}
}
else if (!arg3.compare("all")) {
if (has || set) {
c->Message(Chat::White, "You can only use 'all' for clearing timers.");
return;
}
all = true;
}
else {
c->Message(Chat::White, "Incorrect ID option, use %s help for a list of options.", sep->arg[0]);
return;
}
if (set) {
if (sep->IsNumber(4)) {
ab_arg = 5;
timer_value = atoi(sep->arg[4]);
if (timer_value <= 0) {
c->Message(Chat::White, "You cannot use 0 or negative numbers.");
return;
}
}
}
std::string class_race_arg = sep->arg[ab_arg];
bool class_race_check = false;
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
class_race_check = true;
}
std::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
return;
}
sbl.remove(nullptr);
for (auto my_bot : sbl) {
bool found = false;
if (clear) {
c->Message(
Chat::White,
fmt::format(
"{} says, 'Clearing {} timer{}'",
my_bot->GetCleanName(),
disc ? "Discipline" : item ? "Item" : "Spell",
(all ? "s." : ".")
).c_str()
);
if (disc) {
my_bot->ClearDisciplineReuseTimer(timer_id);
}
else if (item) {
my_bot->ClearItemReuseTimer(timer_id);
}
else if (spell) {
my_bot->ClearSpellRecastTimer(timer_id);
}
}
else if (has) {
uint32 remaining_time;
std::string time_string = "";
if (disc) {
if (!my_bot->CheckDisciplineReuseTimer(timer_id)) {
remaining_time = my_bot->GetDisciplineReuseRemainingTime(timer_id) / 1000;
time_string = Strings::SecondsToTime(remaining_time);
found = true;
}
}
else if (item) {
if (!my_bot->CheckItemReuseTimer(timer_id)) {
remaining_time = my_bot->GetItemReuseRemainingTime(timer_id) / 1000;
time_string = Strings::SecondsToTime(remaining_time);
found = true;
}
}
else if (spell) {
if (!my_bot->CheckSpellRecastTimer(timer_id)) {
remaining_time = my_bot->GetSpellRecastRemainingTime(timer_id) / 1000;
time_string = Strings::SecondsToTime(remaining_time);
found = true;
}
}
c->Message(
Chat::White,
fmt::format(
"{} says, 'I {}{}{}'",
my_bot->GetCleanName(),
(!found ? " do not have that timer currently" : " have "),
(!found ? "" : time_string),
(!found ? "." : " remaining.")
).c_str()
);
}
else if (set) {
c->Message(
Chat::White,
fmt::format(
"{} says, 'Setting {} timer{} for {} to {}.'",
my_bot->GetCleanName(),
disc ? "Discipline" : item ? "Item" : "Spell",
(all ? "s" : ""),
timer_id,
timer_value ? std::to_string(timer_value) : "the default value"
).c_str()
);
if (disc) {
my_bot->ClearDisciplineReuseTimer(timer_id);
my_bot->SetDisciplineReuseTimer(timer_id, timer_value);
}
else if (item) {
my_bot->ClearItemReuseTimer(timer_id);
my_bot->SetItemReuseTimer(timer_id, timer_value);
}
else if (spell) {
my_bot->ClearSpellRecastTimer(timer_id);
my_bot->SetSpellRecastTimer(timer_id, timer_value);
}
}
}
}
void bot_command_track(Client *c, const Seperator *sep)
{
if (helper_command_alias_fail(c, "bot_command_track", sep->arg[0], "track"))
@@ -5210,15 +5492,15 @@ void bot_command_track(Client *c, const Seperator *sep)
std::list<Bot*> sbl;
MyBots::PopulateSBL_BySpawnedBots(c, sbl);
uint16 class_mask = (PLAYER_CLASS_RANGER_BIT | PLAYER_CLASS_DRUID_BIT | PLAYER_CLASS_BARD_BIT);
uint16 class_mask = (player_class_bitmasks[Class::Ranger] | player_class_bitmasks[Class::Druid] | player_class_bitmasks[Class::Bard]);
ActionableBots::Filter_ByClasses(c, sbl, class_mask);
Bot* my_bot = ActionableBots::AsSpawned_ByMinLevelAndClass(c, sbl, 1, RANGER);
Bot* my_bot = ActionableBots::AsSpawned_ByMinLevelAndClass(c, sbl, 1, Class::Ranger);
if (tracking_scope.empty()) {
if (!my_bot)
my_bot = ActionableBots::AsSpawned_ByMinLevelAndClass(c, sbl, 20, DRUID);
my_bot = ActionableBots::AsSpawned_ByMinLevelAndClass(c, sbl, 20, Class::Druid);
if (!my_bot)
my_bot = ActionableBots::AsSpawned_ByMinLevelAndClass(c, sbl, 35, BARD);
my_bot = ActionableBots::AsSpawned_ByMinLevelAndClass(c, sbl, 35, Class::Bard);
}
if (!my_bot) {
c->Message(Chat::White, "No bots are capable of performing this action");
@@ -5229,7 +5511,7 @@ void bot_command_track(Client *c, const Seperator *sep)
bool track_named = false;
std::string tracking_msg;
switch (my_bot->GetClass()) {
case RANGER:
case Class::Ranger:
if (!tracking_scope.compare("local")) {
base_distance = 30;
tracking_msg = "Local tracking...";
@@ -5244,11 +5526,11 @@ void bot_command_track(Client *c, const Seperator *sep)
tracking_msg = "Advanced tracking...";
}
break;
case DRUID:
case Class::Druid:
base_distance = 30;
tracking_msg = "Local tracking...";
break;
case BARD:
case Class::Bard:
base_distance = 20;
tracking_msg = "Near tracking...";
break;
@@ -6612,7 +6894,7 @@ void bot_subcommand_bot_list(Client *c, const Seperator *sep)
).c_str()
);
for (uint8 class_id = WARRIOR; class_id <= BERSERKER; class_id++) {
for (uint8 class_id = Class::Warrior; class_id <= Class::Berserker; class_id++) {
auto class_creation_limit = c->GetBotCreationLimit(class_id);
if (class_creation_limit != overall_bot_creation_limit) {
@@ -6865,7 +7147,7 @@ void bot_subcommand_bot_spawn(Client *c, const Seperator *sep)
std::string bot_name = sep->arg[1];
uint32 bot_id = 0;
uint8 bot_class = NO_CLASS;
uint8 bot_class = Class::None;
if (!database.botdb.LoadBotID(c->CharacterID(), bot_name, bot_id, bot_class)) {
c->Message(
Chat::White,
@@ -6972,22 +7254,22 @@ void bot_subcommand_bot_spawn(Client *c, const Seperator *sep)
static std::string bot_spawn_message[17] = {
"I am ready to fight!", // DEFAULT
"A solid weapon is my ally!", // WARRIOR
"The pious shall never die!", // CLERIC
"I am the symbol of Light!", // PALADIN
"There are enemies near!", // RANGER
"Out of the shadows, I step!", // SHADOWKNIGHT
"Nature's fury shall be wrought!", // DRUID
"Your punishment will be my fist!", // MONK
"A solid weapon is my ally!", // Class::Warrior
"The pious shall never die!", // Class::Cleric
"I am the symbol of Light!", // Class::Paladin
"There are enemies near!", // Class::Ranger
"Out of the shadows, I step!", // Class::ShadowKnight
"Nature's fury shall be wrought!", // Class::Druid
"Your punishment will be my fist!", // Class::Monk
"Music is the overture of battle! ", // BARD
"Daggers into the backs of my enemies!", // ROGUE
"More bones to grind!", // SHAMAN
"Death is only the beginning!", // NECROMANCER
"I am the harbinger of demise!", // WIZARD
"The elements are at my command!", // MAGICIAN
"No being can resist my charm!", // ENCHANTER
"Battles are won by hand and paw!", // BEASTLORD
"My bloodthirst shall not be quenched!" // BERSERKER
"Daggers into the backs of my enemies!", // Class::Rogue
"More bones to grind!", // Class::Shaman
"Death is only the beginning!", // Class::Necromancer
"I am the harbinger of demise!", // Class::Wizard
"The elements are at my command!", // Class::Magician
"No being can resist my charm!", // Class::Enchanter
"Battles are won by hand and paw!", // Class::Beastlord
"My bloodthirst shall not be quenched!" // Class::Berserker
};
uint8 message_index = 0;
@@ -7257,7 +7539,7 @@ void bot_subcommand_bot_toggle_archer(Client *c, const Seperator *sep)
}
bot_iter->ChangeBotArcherWeapons(bot_iter->IsBotArcher());
if (bot_iter->GetClass() == RANGER && bot_iter->GetLevel() >= 61) {
if (bot_iter->GetClass() == Class::Ranger && bot_iter->GetLevel() >= 61) {
bot_iter->SetRangerAutoWeaponSelect(bot_iter->IsBotArcher());
}
}
@@ -7467,7 +7749,7 @@ void bot_subcommand_circle(Client *c, const Seperator *sep)
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s [list | destination] ([option: single])", sep->arg[0]);
helper_send_usage_required_bots(c, BCEnum::SpT_Depart, DRUID);
helper_send_usage_required_bots(c, BCEnum::SpT_Depart, Class::Druid);
return;
}
@@ -7478,7 +7760,7 @@ void bot_subcommand_circle(Client *c, const Seperator *sep)
std::string destination = sep->arg[1];
if (!destination.compare("list")) {
auto my_druid_bot = ActionableBots::AsGroupMember_ByClass(c, c, DRUID);
auto my_druid_bot = ActionableBots::AsGroupMember_ByClass(c, c, Class::Druid);
helper_command_depart_list(c, my_druid_bot, nullptr, local_list, single);
return;
}
@@ -7497,7 +7779,7 @@ void bot_subcommand_circle(Client *c, const Seperator *sep)
auto local_entry = list_iter->SafeCastToDepart();
if (helper_spell_check_fail(local_entry))
continue;
if (local_entry->caster_class != DRUID)
if (local_entry->caster_class != Class::Druid)
continue;
if (local_entry->single != single)
continue;
@@ -8988,7 +9270,7 @@ void bot_subcommand_pet_remove(Client *c, const Seperator *sep)
if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None)
return;
uint16 class_mask = (PLAYER_CLASS_DRUID_BIT | PLAYER_CLASS_NECROMANCER_BIT | PLAYER_CLASS_ENCHANTER_BIT);
uint16 class_mask = (player_class_bitmasks[Class::Druid] | player_class_bitmasks[Class::Necromancer] | player_class_bitmasks[Class::Enchanter]);
ActionableBots::Filter_ByClasses(c, sbl, class_mask);
if (sbl.empty()) {
c->Message(Chat::White, "You have no spawned bots capable of charming");
@@ -9068,7 +9350,7 @@ void bot_subcommand_pet_set_type(Client *c, const Seperator *sep)
if (ActionableBots::PopulateSBL(c, sep->arg[2], sbl, ab_mask, sep->arg[3]) == ActionableBots::ABT_None)
return;
uint16 class_mask = PLAYER_CLASS_MAGICIAN_BIT;
uint16 class_mask = player_class_bitmasks[Class::Magician];
ActionableBots::Filter_ByClasses(c, sbl, class_mask);
if (sbl.empty()) {
c->Message(Chat::White, "You have no spawned Magician bots");
@@ -9103,7 +9385,7 @@ void bot_subcommand_portal(Client *c, const Seperator *sep)
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s [list | destination] ([option: single])", sep->arg[0]);
helper_send_usage_required_bots(c, BCEnum::SpT_Depart, WIZARD);
helper_send_usage_required_bots(c, BCEnum::SpT_Depart, Class::Wizard);
return;
}
@@ -9114,7 +9396,7 @@ void bot_subcommand_portal(Client *c, const Seperator *sep)
std::string destination = sep->arg[1];
if (!destination.compare("list")) {
auto my_wizard_bot = ActionableBots::AsGroupMember_ByClass(c, c, WIZARD);
auto my_wizard_bot = ActionableBots::AsGroupMember_ByClass(c, c, Class::Wizard);
helper_command_depart_list(c, nullptr, my_wizard_bot, local_list, single);
return;
}
@@ -9133,7 +9415,7 @@ void bot_subcommand_portal(Client *c, const Seperator *sep)
auto local_entry = list_iter->SafeCastToDepart();
if (helper_spell_check_fail(local_entry))
continue;
if (local_entry->caster_class != WIZARD)
if (local_entry->caster_class != Class::Wizard)
continue;
if (local_entry->single != single)
continue;
@@ -9427,26 +9709,26 @@ void helper_bot_out_of_combat(Client *bot_owner, Bot *my_bot)
return;
switch (my_bot->GetClass()) {
case WARRIOR:
case CLERIC:
case PALADIN:
case RANGER:
case SHADOWKNIGHT:
case DRUID:
case MONK:
case Class::Warrior:
case Class::Cleric:
case Class::Paladin:
case Class::Ranger:
case Class::ShadowKnight:
case Class::Druid:
case Class::Monk:
bot_owner->Message(Chat::White, "%s has no out-of-combat behavior defined", my_bot->GetCleanName());
break;
case BARD:
case Class::Bard:
bot_owner->Message(Chat::White, "%s will %s use out-of-combat behavior for bard songs", my_bot->GetCleanName(), ((my_bot->GetAltOutOfCombatBehavior()) ? ("now") : ("no longer")));
break;
case ROGUE:
case SHAMAN:
case NECROMANCER:
case WIZARD:
case MAGICIAN:
case ENCHANTER:
case BEASTLORD:
case BERSERKER:
case Class::Rogue:
case Class::Shaman:
case Class::Necromancer:
case Class::Wizard:
case Class::Magician:
case Class::Enchanter:
case Class::Beastlord:
case Class::Berserker:
bot_owner->Message(Chat::White, "%s has no out-of-combat behavior defined", my_bot->GetCleanName());
break;
default:
@@ -10438,6 +10720,61 @@ void bot_command_caster_range(Client* c, const Seperator* sep)
}
}
void bot_command_click_item(Client* c, const Seperator* sep)
{
if (!RuleB(Bots, BotsCanClickItems)) {
c->Message(Chat::White, "The ability for bots to click equipped items is currently disabled.");
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: <slot id> %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "This will cause the selected bots to click the item in the given slot ID.");
c->Message(Chat::White, "Use ^invlist to see their items along with slot IDs.");
return;
}
if (!sep->IsNumber(1)) {
c->Message(Chat::Yellow, "You must specify a slot ID. Use %s help for more information.", sep->arg[0]);
return;
}
const int ab_mask = ActionableBots::ABM_Type1;
int ab_arg = 1;
uint32 slot_id = 0;
if (sep->IsNumber(1)) {
ab_arg = 2;
slot_id = atoi(sep->arg[1]);
if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END) {
c->Message(Chat::Yellow, "You must specify a valid inventory slot from 0 to 22. Use %s help for more information", sep->arg[0]);
return;
}
}
std::string class_race_arg = sep->arg[ab_arg];
bool class_race_check = false;
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
class_race_check = true;
}
std::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
return;
}
sbl.remove(nullptr);
for (auto my_bot : sbl) {
if (RuleI(Bots, BotsClickItemsMinLvl) > my_bot->GetLevel()) {
c->Message(Chat::White, "%s must be level %i to use clickable items.", my_bot->GetCleanName(), RuleI(Bots, BotsClickItemsMinLvl));
continue;
}
my_bot->TryItemClick(slot_id);
}
}
void bot_command_pickpocket(Client *c, const Seperator *sep)
{
if (helper_command_disabled(c, RuleB(Bots, AllowPickpocketCommand), "pickpocket")) {
@@ -10457,8 +10794,8 @@ void bot_command_pickpocket(Client *c, const Seperator *sep)
MyBots::PopulateSBL_BySpawnedBots(c, sbl);
// Check for capable rogue
ActionableBots::Filter_ByClasses(c, sbl, PLAYER_CLASS_ROGUE_BIT);
Bot *my_bot = ActionableBots::AsSpawned_ByMinLevelAndClass(c, sbl, 7, ROGUE);
ActionableBots::Filter_ByClasses(c, sbl, player_class_bitmasks[Class::Rogue]);
Bot *my_bot = ActionableBots::AsSpawned_ByMinLevelAndClass(c, sbl, 7, Class::Rogue);
if (!my_bot) {
c->Message(Chat::White, "No bots are capable of performing this action");
return;
+3 -1
View File
@@ -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
View File
@@ -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;
+11
View File
@@ -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
+112 -177
View File
@@ -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;
@@ -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;
}
@@ -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)) {
@@ -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;
+205 -91
View File
@@ -1411,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;
@@ -2676,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);
@@ -2684,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));
@@ -2692,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)));
@@ -3028,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;
}
@@ -3077,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;
}
@@ -4232,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;
}
@@ -4849,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());
@@ -4918,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())
{
@@ -4961,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())
{
@@ -5011,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())
{
@@ -5690,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);
}
}
@@ -6454,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());
@@ -6466,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;
}
@@ -8603,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:
@@ -9754,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;
}
@@ -9825,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;
}
@@ -10694,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;
+12 -9
View File
@@ -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);
@@ -1493,7 +1496,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;
@@ -2045,14 +2048,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
View File
@@ -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)
+63 -74
View File
@@ -1381,7 +1381,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
SetClientMaxLevel(client_max_level);
// we know our class now, so we might have to fix our consume timer!
if (class_ == MONK)
if (class_ == Class::Monk)
consume_food_timer.SetTimer(CONSUMPTION_MNK_TIMER);
InitInnates();
@@ -1592,9 +1592,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
m_pp.spellSlotRefresh[i] = p_timers.GetRemainingTime(pTimerSpellStart + m_pp.mem_spells[i]) * 1000;
/* Ability slot refresh send SK/PAL */
if (m_pp.class_ == SHADOWKNIGHT || m_pp.class_ == PALADIN) {
if (m_pp.class_ == Class::ShadowKnight || m_pp.class_ == Class::Paladin) {
uint32 abilitynum = 0;
if (m_pp.class_ == SHADOWKNIGHT) { abilitynum = pTimerHarmTouch; }
if (m_pp.class_ == Class::ShadowKnight) { abilitynum = pTimerHarmTouch; }
else { abilitynum = pTimerLayHands; }
uint32 remaining = p_timers.GetRemainingTime(abilitynum);
@@ -1935,8 +1935,8 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app)
Adventure_Purchase_Struct* aps = (Adventure_Purchase_Struct*)app->pBuffer;
uint32 merchantid = 0;
Mob* tmp = entity_list.GetMob(aps->npcid);
if (tmp == 0 || !tmp->IsNPC() || ((tmp->GetClass() != ADVENTURE_MERCHANT) &&
(tmp->GetClass() != DISCORD_MERCHANT) && (tmp->GetClass() != NORRATHS_KEEPERS_MERCHANT) && (tmp->GetClass() != DARK_REIGN_MERCHANT)))
if (tmp == 0 || !tmp->IsNPC() || ((tmp->GetClass() != Class::AdventureMerchant) &&
(tmp->GetClass() != Class::DiscordMerchant) && (tmp->GetClass() != Class::NorrathsKeepersMerchant) && (tmp->GetClass() != Class::DarkReignMerchant)))
return;
//you have to be somewhat close to them to be properly using them
@@ -2121,8 +2121,8 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app)
uint32 merchantid = 0;
Mob* tmp = entity_list.GetMob(eid->entity_id);
if (tmp == 0 || !tmp->IsNPC() || ((tmp->GetClass() != ADVENTURE_MERCHANT) &&
(tmp->GetClass() != DISCORD_MERCHANT) && (tmp->GetClass() != NORRATHS_KEEPERS_MERCHANT) && (tmp->GetClass() != DARK_REIGN_MERCHANT)))
if (tmp == 0 || !tmp->IsNPC() || ((tmp->GetClass() != Class::AdventureMerchant) &&
(tmp->GetClass() != Class::DiscordMerchant) && (tmp->GetClass() != Class::NorrathsKeepersMerchant) && (tmp->GetClass() != Class::DarkReignMerchant)))
return;
if (!tmp->CastToNPC()->IsMerchantOpen()) {
@@ -2197,8 +2197,8 @@ void Client::Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app)
Adventure_Sell_Struct *ams_in = (Adventure_Sell_Struct*)app->pBuffer;
Mob* vendor = entity_list.GetMob(ams_in->npcid);
if (vendor == 0 || !vendor->IsNPC() || ((vendor->GetClass() != ADVENTURE_MERCHANT) &&
(vendor->GetClass() != NORRATHS_KEEPERS_MERCHANT) && (vendor->GetClass() != DARK_REIGN_MERCHANT)))
if (vendor == 0 || !vendor->IsNPC() || ((vendor->GetClass() != Class::AdventureMerchant) &&
(vendor->GetClass() != Class::NorrathsKeepersMerchant) && (vendor->GetClass() != Class::DarkReignMerchant)))
{
Message(Chat::Red, "Vendor was not found.");
return;
@@ -2298,17 +2298,17 @@ void Client::Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app)
switch (vendor->GetClass())
{
case ADVENTURE_MERCHANT:
case Class::AdventureMerchant:
{
UpdateLDoNPoints(6, price);
break;
}
case NORRATHS_KEEPERS_MERCHANT:
case Class::NorrathsKeepersMerchant:
{
SetRadiantCrystals(GetRadiantCrystals() + price);
break;
}
case DARK_REIGN_MERCHANT:
case Class::DarkReignMerchant:
{
SetEbonCrystals(GetEbonCrystals() + price);
break;
@@ -2482,7 +2482,7 @@ void Client::Handle_OP_AltCurrencyMerchantRequest(const EQApplicationPacket *app
return;
}
if (target->GetClass() != ALT_CURRENCY_MERCHANT) {
if (target->GetClass() != Class::AlternateCurrencyMerchant) {
return;
}
@@ -2553,7 +2553,7 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app)
if (DistanceSquared(m_Position, tar->GetPosition())> USE_NPC_RANGE2)
return;
if (tar->GetClass() != ALT_CURRENCY_MERCHANT) {
if (tar->GetClass() != Class::AlternateCurrencyMerchant) {
return;
}
@@ -2626,7 +2626,7 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app)
parse->EventPlayer(EVENT_ALT_CURRENCY_MERCHANT_BUY, this, export_string, 0);
}
uint64 current_balance = AddAlternateCurrencyValue(alt_cur_id, -((int32) cost));
uint64 current_balance = AddAlternateCurrencyValue(alt_cur_id, -((int) cost));
int16 charges = 1;
if (item->MaxCharges != 0) {
charges = item->MaxCharges;
@@ -2701,7 +2701,7 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app)
}
else {
SummonItem(item_id, reclaim->count, 0, 0, 0, 0, 0, 0, false, EQ::invslot::slotCursor);
AddAlternateCurrencyValue(reclaim->currency_id, -((int32)reclaim->count));
AddAlternateCurrencyValue(reclaim->currency_id, -((int)reclaim->count));
}
/* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */
if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)) {
@@ -2722,7 +2722,7 @@ void Client::Handle_OP_AltCurrencySell(const EQApplicationPacket *app)
if (DistanceSquared(m_Position, tar->GetPosition()) > USE_NPC_RANGE2)
return;
if (tar->GetClass() != ALT_CURRENCY_MERCHANT) {
if (tar->GetClass() != Class::AlternateCurrencyMerchant) {
return;
}
@@ -2858,7 +2858,7 @@ void Client::Handle_OP_AltCurrencySellSelection(const EQApplicationPacket *app)
if (DistanceSquared(m_Position, tar->GetPosition()) > USE_NPC_RANGE2)
return;
if (tar->GetClass() != ALT_CURRENCY_MERCHANT) {
if (tar->GetClass() != Class::AlternateCurrencyMerchant) {
return;
}
@@ -2966,7 +2966,7 @@ void Client::Handle_OP_ApplyPoison(const EQApplicationPacket *app)
bool IsPoison = (poison && poison->ItemType == EQ::item::ItemTypePoison);
if (IsPoison && GetClass() == ROGUE) {
if (IsPoison && GetClass() == Class::Rogue) {
// Live always checks for skillup, even when poison is too high
CheckIncreaseSkill(EQ::skills::SkillApplyPoison, nullptr, 10);
@@ -3926,7 +3926,7 @@ void Client::Handle_OP_Begging(const EQApplicationPacket *app)
if (!HasSkill(EQ::skills::SkillBegging) || !GetTarget())
return;
if (GetTarget()->GetClass() == LDON_TREASURE)
if (GetTarget()->GetClass() == Class::LDoNTreasure)
return;
p_timers.Start(pTimerBeggingPickPocket, 8);
@@ -4471,7 +4471,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
else if (slot == CastingSlot::Ability) {
uint16 spell_to_cast = 0;
if (castspell->spell_id == SPELL_LAY_ON_HANDS && GetClass() == PALADIN) {
if (castspell->spell_id == SPELL_LAY_ON_HANDS && GetClass() == Class::Paladin) {
if (!p_timers.Expired(&database, pTimerLayHands)) {
Message(Chat::Red, "Ability recovery time not yet met.");
InterruptSpell(castspell->spell_id);
@@ -4481,7 +4481,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
p_timers.Start(pTimerLayHands, LayOnHandsReuseTime);
}
else if ((castspell->spell_id == SPELL_HARM_TOUCH
|| castspell->spell_id == SPELL_HARM_TOUCH2) && GetClass() == SHADOWKNIGHT) {
|| castspell->spell_id == SPELL_HARM_TOUCH2) && GetClass() == Class::ShadowKnight) {
if (!p_timers.Expired(&database, pTimerHarmTouch)) {
Message(Chat::Red, "Ability recovery time not yet met.");
InterruptSpell(castspell->spell_id);
@@ -5122,7 +5122,7 @@ void Client::Handle_OP_Consider(const EQApplicationPacket *app)
}
}
if (t->GetClass() == LDON_TREASURE) {
if (t->GetClass() == Class::LDoNTreasure) {
Message(Chat::Yellow, fmt::format("{}", t->GetCleanName()).c_str());
return;
}
@@ -5475,59 +5475,50 @@ void Client::Handle_OP_CreateObject(const EQApplicationPacket *app)
void Client::Handle_OP_CrystalCreate(const EQApplicationPacket *app)
{
VERIFY_PACKET_LENGTH(OP_CrystalCreate, app, CrystalReclaim_Struct);
CrystalReclaim_Struct *cr = (CrystalReclaim_Struct*)app->pBuffer;
auto *cr = (CrystalReclaim_Struct *) app->pBuffer;
const uint32 requestQty = cr->amount;
const bool isRadiant = cr->type == 4;
const bool isEbon = cr->type == 5;
const uint32 quantity = cr->amount;
const bool is_radiant = cr->type == CrystalReclaimTypes::Radiant;
const bool is_ebon = cr->type == CrystalReclaimTypes::Ebon;
// Check: Valid type requested.
if (!isRadiant && !isEbon) {
if (!is_radiant && !is_ebon) {
return;
}
// Check: Valid quantity requested.
if (requestQty < 1) {
if (quantity < 1) {
return;
}
// Check: Valid client state to make request.
// In this situation the client is either desynced or attempting an exploit.
const uint32 currentQty = isRadiant ? GetRadiantCrystals() : GetEbonCrystals();
if (currentQty == 0) {
const uint32 current_quantity = is_radiant ? GetRadiantCrystals() : GetEbonCrystals();
if (!current_quantity) {
return;
}
// Prevent the client from creating more than they have.
const uint32 amount = EQ::ClampUpper(requestQty, currentQty);
const uint32 itemID = isRadiant ? RuleI(Zone, RadiantCrystalItemID) : RuleI(Zone, EbonCrystalItemID);
// Summon crystals for player.
const bool success = SummonItem(itemID, amount);
const uint32 amount = EQ::ClampUpper(quantity, current_quantity);
const uint32 item_id = is_radiant ? RuleI(Zone, RadiantCrystalItemID) : RuleI(Zone, EbonCrystalItemID);
const bool success = SummonItem(item_id, amount);
if (!success) {
return;
}
// Deduct crystals from client and update them.
if (isRadiant) {
m_pp.currentRadCrystals -= amount;
m_pp.careerRadCrystals -= amount;
if (is_ebon) {
RemoveEbonCrystals(amount, true);
} else if (is_radiant) {
RemoveRadiantCrystals(amount, true);
}
else if (isEbon) {
m_pp.currentEbonCrystals -= amount;
m_pp.careerEbonCrystals -= amount;
}
SaveCurrency();
SendCrystalCounts();
}
void Client::Handle_OP_CrystalReclaim(const EQApplicationPacket *app)
{
uint32 ebon = NukeItem(RuleI(Zone, EbonCrystalItemID), invWhereWorn | invWherePersonal | invWhereCursor);
uint32 radiant = NukeItem(RuleI(Zone, RadiantCrystalItemID), invWhereWorn | invWherePersonal | invWhereCursor);
const uint32 ebon = NukeItem(RuleI(Zone, EbonCrystalItemID), invWhereWorn | invWherePersonal | invWhereCursor);
const uint32 radiant = NukeItem(RuleI(Zone, RadiantCrystalItemID), invWhereWorn | invWherePersonal | invWhereCursor);
if ((ebon + radiant) > 0) {
AddCrystals(radiant, ebon);
AddEbonCrystals(ebon, true);
AddRadiantCrystals(radiant, true);
}
}
@@ -6293,6 +6284,10 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app)
);
parse->EventPlayer(EVENT_ENVIRONMENTAL_DAMAGE, this, export_string, 0);
}
if (ed->dmgtype == EQ::constants::EnvironmentalDamage::Trap) {
BreakInvisibleSpells();
}
}
if (GetHP() <= 0) {
@@ -6879,12 +6874,6 @@ void Client::Handle_OP_GMSummon(const EQApplicationPacket *app)
return;
}
if (!GetGM()) {
Message(Chat::Red, "Your account has been reported for hacking.");
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /summon"});
return;
}
OPGMSummon(app);
return;
}
@@ -8626,7 +8615,7 @@ void Client::Handle_OP_Hide(const EQApplicationPacket *app)
hidden = true;
tmHidden = Timer::GetCurrentTime();
}
if (GetClass() == ROGUE) {
if (GetClass() == Class::Rogue) {
auto outapp = new EQApplicationPacket(OP_SimpleMessage, sizeof(SimpleMessage_Struct));
SimpleMessage_Struct *msg = (SimpleMessage_Struct *)outapp->pBuffer;
msg->color = 0x010E;
@@ -9175,7 +9164,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
Bards on live can click items while casting spell gems, it stops that song cast and replaces it with item click cast.
Can not click while casting other items.
*/
if (GetClass() == BARD && IsCasting() && casting_spell_slot < CastingSlot::MaxGems)
if (GetClass() == Class::Bard && IsCasting() && casting_spell_slot < CastingSlot::MaxGems)
{
is_casting_bard_song = true;
}
@@ -9341,7 +9330,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
if (!IsCastWhileInvisibleSpell(item->Click.Effect)) {
CommonBreakInvisible(); // client can't do this for us :(
}
if (GetClass() == BARD){
if (GetClass() == Class::Bard){
DoBardCastingFromItemClick(is_casting_bard_song, item->CastTime, item->Click.Effect, target_id, CastingSlot::Item, slot_id, item->RecastType, item->RecastDelay);
}
else {
@@ -9413,7 +9402,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
if (!IsCastWhileInvisibleSpell(augitem->Click.Effect)) {
CommonBreakInvisible(); // client can't do this for us :(
}
if (GetClass() == BARD) {
if (GetClass() == Class::Bard) {
DoBardCastingFromItemClick(is_casting_bard_song, augitem->CastTime, augitem->Click.Effect, target_id, CastingSlot::Item, slot_id, augitem->RecastType, augitem->RecastDelay);
}
else {
@@ -9549,7 +9538,7 @@ void Client::Handle_OP_LDoNDisarmTraps(const EQApplicationPacket *app)
void Client::Handle_OP_LDoNInspect(const EQApplicationPacket *app)
{
auto* t = GetTarget();
if (t && t->GetClass() == LDON_TREASURE && !t->IsAura()) {
if (t && t->GetClass() == Class::LDoNTreasure && !t->IsAura()) {
if (parse->PlayerHasQuestSub(EVENT_INSPECT)) {
std::vector<std::any> args = { t };
if (parse->EventPlayer(EVENT_INSPECT, this, "", t->GetID(), &args) == 0) {
@@ -9878,7 +9867,7 @@ void Client::Handle_OP_LFPCommand(const EQApplicationPacket *app)
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;
LFPMembers[i].GuildID = 0xFFFF;
@@ -10219,7 +10208,7 @@ void Client::Handle_OP_MercenaryDataRequest(const EQApplicationPacket *app)
if (DistanceSquared(m_Position, tar->GetPosition()) > USE_NPC_RANGE2)
return;
if (tar->GetClass() != MERCENARY_MASTER) {
if (tar->GetClass() != Class::MercenaryLiaison) {
return;
}
@@ -10594,7 +10583,7 @@ void Client::Handle_OP_OpenGuildTributeMaster(const EQApplicationPacket *app)
//Opens the guild tribute master window
StartTribute_Struct* st = (StartTribute_Struct*)app->pBuffer;
Mob* tribmast = entity_list.GetMob(st->tribute_master_id);
if (tribmast && tribmast->IsNPC() && tribmast->GetClass() == GUILD_TRIBUTE_MASTER
if (tribmast && tribmast->IsNPC() && tribmast->GetClass() == Class::GuildTributeMaster
&& DistanceSquared(m_Position, tribmast->GetPosition()) <= USE_NPC_RANGE2) {
st->response = 1;
QueuePacket(app);
@@ -10625,7 +10614,7 @@ void Client::Handle_OP_OpenTributeMaster(const EQApplicationPacket *app)
//Opens the tribute master window
StartTribute_Struct* st = (StartTribute_Struct*)app->pBuffer;
Mob* tribmast = entity_list.GetMob(st->tribute_master_id);
if (tribmast && tribmast->IsNPC() && tribmast->GetClass() == TRIBUTE_MASTER
if (tribmast && tribmast->IsNPC() && tribmast->GetClass() == Class::TributeMaster
&& DistanceSquared(m_Position, tribmast->GetPosition()) <= USE_NPC_RANGE2) {
st->response = 1;
QueuePacket(app);
@@ -13531,7 +13520,7 @@ void Client::Handle_OP_Shielding(const EQApplicationPacket *app)
return;
}
if (GetClass() != WARRIOR){
if (GetClass() != Class::Warrior){
return;
}
@@ -13587,7 +13576,7 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app)
bool tmpmer_used = false;
Mob* tmp = entity_list.GetMob(mp->npcid);
if (tmp == 0 || !tmp->IsNPC() || tmp->GetClass() != MERCHANT)
if (tmp == 0 || !tmp->IsNPC() || tmp->GetClass() != Class::Merchant)
return;
if (mp->quantity < 1) return;
@@ -13896,7 +13885,7 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app)
Mob* vendor = entity_list.GetMob(mp->npcid);
if (vendor == 0 || !vendor->IsNPC() || vendor->GetClass() != MERCHANT)
if (vendor == 0 || !vendor->IsNPC() || vendor->GetClass() != Class::Merchant)
return;
//you have to be somewhat close to them to be properly using them
@@ -14122,7 +14111,7 @@ void Client::Handle_OP_ShopRequest(const EQApplicationPacket *app)
int merchantid = 0;
Mob* tmp = entity_list.GetMob(mc->npcid);
if (tmp == 0 || !tmp->IsNPC() || tmp->GetClass() != MERCHANT)
if (tmp == 0 || !tmp->IsNPC() || tmp->GetClass() != Class::Merchant)
return;
//you have to be somewhat close to them to be properly using them
@@ -14229,7 +14218,7 @@ void Client::Handle_OP_Sneak(const EQApplicationPacket *app)
sa_out->parameter = sneaking;
QueuePacket(outapp);
safe_delete(outapp);
if (GetClass() == ROGUE) {
if (GetClass() == Class::Rogue) {
outapp = new EQApplicationPacket(OP_SimpleMessage, 12);
SimpleMessage_Struct *msg = (SimpleMessage_Struct *)outapp->pBuffer;
msg->color = 0x010E;
@@ -15545,7 +15534,7 @@ void Client::Handle_OP_TributeItem(const EQApplicationPacket *app)
tribute_master_id = t->tribute_master_id;
//make sure they are dealing with a valid tribute master
Mob* tribmast = entity_list.GetMob(t->tribute_master_id);
if (!tribmast || !tribmast->IsNPC() || tribmast->GetClass() != TRIBUTE_MASTER)
if (!tribmast || !tribmast->IsNPC() || tribmast->GetClass() != Class::TributeMaster)
return;
if (DistanceSquared(m_Position, tribmast->GetPosition()) > USE_NPC_RANGE2)
return;
@@ -15572,7 +15561,7 @@ void Client::Handle_OP_TributeMoney(const EQApplicationPacket *app)
tribute_master_id = t->tribute_master_id;
//make sure they are dealing with a valid tribute master
Mob* tribmast = entity_list.GetMob(t->tribute_master_id);
if (!tribmast || !tribmast->IsNPC() || tribmast->GetClass() != TRIBUTE_MASTER)
if (!tribmast || !tribmast->IsNPC() || tribmast->GetClass() != Class::TributeMaster)
return;
if (DistanceSquared(m_Position, tribmast->GetPosition()) > USE_NPC_RANGE2)
return;
+9 -9
View File
@@ -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;
}
+29 -20
View File
@@ -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);
+60 -10
View File
@@ -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"
@@ -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;
}
+5 -5
View File
@@ -4918,7 +4918,7 @@ 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 ZoneMSGID = 0xFFFFFFFF;
@@ -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){
+2 -2
View File
@@ -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);
+8
View File
@@ -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
View File
@@ -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;
}
+2 -2
View File
@@ -4,7 +4,7 @@ void FindClass(Client *c, const Seperator *sep)
{
if (sep->IsNumber(2)) {
const auto class_id = Strings::ToInt(sep->arg[2]);
if (EQ::ValueWithin(class_id, WARRIOR, BERSERKER)) {
if (EQ::ValueWithin(class_id, Class::Warrior, Class::Berserker)) {
const std::string& class_name = GetClassIDName(class_id);
c->Message(
Chat::White,
@@ -41,7 +41,7 @@ void FindClass(Client *c, const Seperator *sep)
auto found_count = 0;
for (uint16 class_id = WARRIOR; class_id <= MERCENARY_MASTER; class_id++) {
for (uint16 class_id = Class::Warrior; class_id <= Class::MercenaryLiaison; class_id++) {
const std::string& class_name = GetClassIDName(class_id);
const auto& class_name_lower = Strings::ToLower(class_name);
if (!Strings::Contains(class_name_lower, search_criteria)) {
+6 -6
View File
@@ -7,12 +7,12 @@ void command_merchantshop(Client *c, const Seperator *sep)
!m ||
!m->IsNPC() ||
(
m->GetClass() != MERCHANT &&
m->GetClass() != DISCORD_MERCHANT &&
m->GetClass() != ADVENTURE_MERCHANT &&
m->GetClass() != NORRATHS_KEEPERS_MERCHANT &&
m->GetClass() != DARK_REIGN_MERCHANT &&
m->GetClass() != ALT_CURRENCY_MERCHANT
m->GetClass() != Class::Merchant &&
m->GetClass() != Class::DiscordMerchant &&
m->GetClass() != Class::AdventureMerchant &&
m->GetClass() != Class::NorrathsKeepersMerchant &&
m->GetClass() != Class::DarkReignMerchant &&
m->GetClass() != Class::AlternateCurrencyMerchant
)
) {
c->Message(Chat::White, "You must target a merchant.");
+1 -1
View File
@@ -46,7 +46,7 @@ void command_scribespell(Client *c, const Seperator *sep)
);
if (
spells[spell_id].classes[WARRIOR] != 0 &&
spells[spell_id].classes[Class::Warrior] != 0 &&
spells[spell_id].skill != EQ::skills::SkillTigerClaw &&
spells[spell_id].classes[t->GetPP().class_ - 1] > 0 &&
!IsDiscipline(spell_id)
+9 -16
View File
@@ -9,17 +9,11 @@ void SetTime(Client *c, const Seperator *sep)
TimeOfDay_Struct world_time{};
zone->zone_time.GetCurrentEQTimeOfDay(time(0), &world_time);
auto time_string = fmt::format(
"{} (Timezone: {})",
Strings::ZoneTime(world_time.hour, world_time.minute),
Strings::ZoneTime(zone->zone_time.getEQTimeZoneHr(), zone->zone_time.getEQTimeZoneHr())
);
c->Message(
Chat::White,
fmt::format(
"It is currently {}.",
time_string
Strings::ZoneTime(world_time.hour - 1, world_time.minute)
).c_str()
);
@@ -27,15 +21,15 @@ void SetTime(Client *c, const Seperator *sep)
}
uint8 minutes = 0;
uint8 hours = Strings::ToUnsignedInt(sep->arg[2]) + 1;
uint8 hours = Strings::ToUnsignedInt(sep->arg[2]);
if (hours > 24) {
hours = 24;
}
uint8 real_hours = (
(hours - 1) > 0 ?
(hours - 1) :
hours > 0 ?
hours :
0
);
@@ -47,21 +41,20 @@ void SetTime(Client *c, const Seperator *sep)
}
}
c->Message(
Chat::White,
fmt::format(
"Setting world time to {} (Timezone: {}).",
Strings::ZoneTime(hours, minutes),
Strings::ZoneTime(zone->zone_time.getEQTimeZoneHr(), zone->zone_time.getEQTimeZoneHr())
"Setting world time to {}.",
Strings::ZoneTime(hours, minutes)
).c_str()
);
zone->SetTime(real_hours, minutes);
LogInfo(
"{} :: Setting world time to {} (Timezone: {})",
"{} :: Setting world time to {}.",
c->GetCleanName(),
Strings::ZoneTime(hours, minutes),
Strings::ZoneTime(zone->zone_time.getEQTimeZoneHr(), zone->zone_time.getEQTimeZoneHr())
Strings::ZoneTime(hours, minutes)
);
}
+14 -19
View File
@@ -3,19 +3,16 @@
extern WorldServer worldserver;
#include "../corpse.h"
void command_summon(Client *c, const Seperator *sep)
{
int arguments = sep->argnum;
const int arguments = sep->argnum;
if (!arguments && !c->GetTarget()) {
c->Message(Chat::White, "Usage: #summon - Summon your target, if you have one, to your position");
c->Message(Chat::White, "Usage: #summon [Character Name] - Summon a character by name to your position");
c->Message(Chat::White, "Note: You may also summon your target if you have one.");
return;
}
Mob* t = c;
Mob *t = c;
if (arguments == 1) {
std::string character_name = sep->arg[1];
@@ -31,9 +28,9 @@ void command_summon(Client *c, const Seperator *sep)
return;
}
auto search_client = entity_list.GetClientByName(character_name.c_str());
if (search_client) {
t = search_client->CastToMob();
Client *s = entity_list.GetClientByName(character_name.c_str());
if (s) {
t = s->CastToMob();
} else {
if (!worldserver.Connected()) {
c->Message(Chat::White, "World server is currently disconnected.");
@@ -42,15 +39,18 @@ void command_summon(Client *c, const Seperator *sep)
auto pack = new ServerPacket(ServerOP_ZonePlayer, sizeof(ServerZonePlayer_Struct));
auto szp = (ServerZonePlayer_Struct *) pack->pBuffer;
strn0cpy(szp->adminname, c->GetName(), sizeof(szp->adminname));
szp->adminrank = c->Admin();
szp->ignorerestrictions = 2;
strn0cpy(szp->name, character_name.c_str(), sizeof(szp->name));
strn0cpy(szp->zone, zone->GetShortName(), sizeof(szp->zone));
szp->x_pos = c->GetX();
szp->y_pos = c->GetY();
szp->z_pos = c->GetZ();
szp->instance_id = zone->GetInstanceID();
szp->adminrank = c->Admin();
szp->ignorerestrictions = 2;
szp->instance_id = zone->GetInstanceID();
szp->x_pos = c->GetX();
szp->y_pos = c->GetY();
szp->z_pos = c->GetZ();
worldserver.SendPacket(pack);
safe_delete(pack);
return;
@@ -97,9 +97,4 @@ void command_summon(Client *c, const Seperator *sep)
}
t->GMMove(c->GetPosition());
if (t->IsNPC()) {
t->CastToNPC()->SaveGuardSpot(glm::vec4(0.0f));
}
}
+5 -5
View File
@@ -600,7 +600,7 @@ bool HealRotation::healable_target(bool use_class_at, bool critical_only)
return false;
if (healable_target->GetHPRatio() > m_safe_hp_ratio[ClassArmorType(healable_target->GetClass())])
return false;
if (healable_target->IsBerserk() && (healable_target->GetClass() == WARRIOR || healable_target->GetClass() == BERSERKER)) {
if (healable_target->IsBerserk() && (healable_target->GetClass() == Class::Warrior || healable_target->GetClass() == Class::Berserker)) {
if (healable_target->GetHPRatio() <= RuleI(Combat, BerserkerFrenzyEnd) && healable_target->GetHPRatio() > m_critical_hp_ratio[ClassArmorType(healable_target->GetClass())])
return false;
}
@@ -610,7 +610,7 @@ bool HealRotation::healable_target(bool use_class_at, bool critical_only)
return false;
if (healable_target->GetHPRatio() > SAFE_HP_RATIO_BASE)
return false;
if (healable_target->IsBerserk() && (healable_target->GetClass() == WARRIOR || healable_target->GetClass() == BERSERKER)) {
if (healable_target->IsBerserk() && (healable_target->GetClass() == Class::Warrior || healable_target->GetClass() == Class::Berserker)) {
if (healable_target->GetHPRatio() <= RuleI(Combat, BerserkerFrenzyEnd) && healable_target->GetHPRatio() > CRITICAL_HP_RATIO_BASE)
return false;
}
@@ -938,9 +938,9 @@ void HealRotation::validate_hot()
bool IsHealRotationMemberClass(uint8 class_id)
{
switch (class_id) {
case CLERIC:
case DRUID:
case SHAMAN:
case Class::Cleric:
case Class::Druid:
case Class::Shaman:
return true;
default:
return false;
+234 -215
View File
@@ -27,24 +27,37 @@
#include "zonedb.h"
#include "global_loot_manager.h"
#include "../common/repositories/criteria/content_filter_criteria.h"
#include "quest_parser_collection.h"
#ifdef _WINDOWS
#define snprintf _snprintf
#endif
// Queries the loottable: adds item & coin to the npc
void ZoneDatabase::AddLootTableToNPC(NPC* npc, uint32 loottable_id, ItemList* itemlist, uint32* copper, uint32* silver, uint32* gold, uint32* plat) {
const LootTable_Struct* lts = nullptr;
// global loot passes nullptr for these
bool bGlobal = copper == nullptr && silver == nullptr && gold == nullptr && plat == nullptr;
if (!bGlobal) {
void ZoneDatabase::AddLootTableToNPC(
NPC *npc,
uint32 loottable_id,
ItemList *itemlist,
uint32 *copper,
uint32 *silver,
uint32 *gold,
uint32 *plat
)
{
const bool is_global = (
copper == nullptr &&
silver == nullptr &&
gold == nullptr &&
plat == nullptr
);
if (!is_global) {
*copper = 0;
*silver = 0;
*gold = 0;
*plat = 0;
}
lts = database.GetLootTable(loottable_id);
const auto *lts = database.GetLootTable(loottable_id);
if (!lts) {
return;
}
@@ -55,19 +68,23 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc, uint32 loottable_id, ItemList* it
uint32 min_cash = lts->mincash;
uint32 max_cash = lts->maxcash;
if(min_cash > max_cash) {
uint32 t = min_cash;
if (min_cash > max_cash) {
const uint32 t = min_cash;
min_cash = max_cash;
max_cash = t;
}
uint32 cash = 0;
if (!bGlobal) {
if(max_cash > 0 && lts->avgcoin > 0 && EQ::ValueWithin(lts->avgcoin, min_cash, max_cash)) {
float upper_chance = (float)(lts->avgcoin - min_cash) / (float)(max_cash - min_cash);
float avg_cash_roll = (float)zone->random.Real(0.0, 1.0);
if (!is_global) {
if (
max_cash > 0 &&
lts->avgcoin > 0 &&
EQ::ValueWithin(lts->avgcoin, min_cash, max_cash)
) {
const float upper_chance = static_cast<float>(lts->avgcoin - min_cash) / static_cast<float>(max_cash - min_cash);
const float avg_cash_roll = static_cast<float>(zone->random.Real(0.0, 1.0));
if(avg_cash_roll < upper_chance) {
if (avg_cash_roll < upper_chance) {
cash = zone->random.Int(lts->avgcoin, max_cash);
} else {
cash = zone->random.Int(min_cash, lts->avgcoin);
@@ -77,7 +94,7 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc, uint32 loottable_id, ItemList* it
}
}
if(cash != 0) {
if (cash != 0) {
*plat = cash / 1000;
cash -= *plat * 1000;
@@ -90,25 +107,23 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc, uint32 loottable_id, ItemList* it
*copper = cash;
}
uint32 global_loot_multiplier = RuleI(Zone, GlobalLootMultiplier);
const uint32 global_loot_multiplier = RuleI(Zone, GlobalLootMultiplier);
// Do items
for (uint32 i=0; i<lts->NumEntries; i++) {
for (uint32 i = 0; i < lts->NumEntries; i++) {
for (uint32 k = 1; k <= (lts->Entries[i].multiplier * global_loot_multiplier); k++) {
uint8 droplimit = lts->Entries[i].droplimit;
uint8 mindrop = lts->Entries[i].mindrop;
const uint8 drop_limit = lts->Entries[i].droplimit;
const uint8 minimum_drop = lts->Entries[i].mindrop;
//LootTable Entry probability
float ltchance = 0.0f;
ltchance = lts->Entries[i].probability;
const float probability = lts->Entries[i].probability;
float drop_chance = 0.0f;
if(ltchance > 0.0 && ltchance < 100.0) {
drop_chance = (float)zone->random.Real(0.0, 100.0);
if (EQ::ValueWithin(probability, 0.0f, 100.0f)) {
drop_chance = static_cast<float>(zone->random.Real(0.0, 100.0));
}
if (ltchance != 0.0 && (ltchance == 100.0 || drop_chance <= ltchance)) {
AddLootDropToNPC(npc, lts->Entries[i].lootdrop_id, itemlist, droplimit, mindrop);
if (probability != 0.0 && (probability == 100.0 || drop_chance <= probability)) {
AddLootDropToNPC(npc, lts->Entries[i].lootdrop_id, itemlist, drop_limit, minimum_drop);
}
}
}
@@ -118,31 +133,29 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc, uint32 loottable_id, ItemList* it
// maxdrops = size of the array npcd
void ZoneDatabase::AddLootDropToNPC(NPC *npc, uint32 lootdrop_id, ItemList *item_list, uint8 droplimit, uint8 mindrop)
{
const LootDrop_Struct *loot_drop = GetLootDrop(lootdrop_id);
if (!loot_drop) {
return;
}
if (loot_drop->NumEntries == 0) {
return;
}
if (!content_service.DoesPassContentFiltering(loot_drop->content_flags)) {
const auto *lds = GetLootDrop(lootdrop_id);
if (
!lds ||
lds->NumEntries == 0 ||
!content_service.DoesPassContentFiltering(lds->content_flags)
) {
return;
}
// if this lootdrop is droplimit=0 and mindrop 0, scan list once and return
if (droplimit == 0 && mindrop == 0) {
for (uint32 i = 0; i < loot_drop->NumEntries; ++i) {
int charges = loot_drop->Entries[i].multiplier;
for (int j = 0; j < charges; ++j) {
if (zone->random.Real(0.0, 100.0) <= loot_drop->Entries[i].chance &&
npc->MeetsLootDropLevelRequirements(loot_drop->Entries[i], true)) {
const EQ::ItemData *database_item = GetItem(loot_drop->Entries[i].item_id);
for (uint32 i = 0; i < lds->NumEntries; ++i) {
const uint8 charges = lds->Entries[i].multiplier;
for (int j = 0; j < charges; ++j) {
if (
zone->random.Real(0.0, 100.0) <= lds->Entries[i].chance &&
npc->MeetsLootDropLevelRequirements(lds->Entries[i], true)
) {
const EQ::ItemData *database_item = GetItem(lds->Entries[i].item_id);
npc->AddLootDrop(
database_item,
item_list,
loot_drop->Entries[i]
lds->Entries[i]
);
}
}
@@ -150,7 +163,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC *npc, uint32 lootdrop_id, ItemList *item
return;
}
if (loot_drop->NumEntries > 100 && droplimit == 0) {
if (lds->NumEntries > 100 && droplimit == 0) {
droplimit = 10;
}
@@ -163,16 +176,17 @@ void ZoneDatabase::AddLootDropToNPC(NPC *npc, uint32 lootdrop_id, ItemList *item
bool roll_table_chance_bypass = false;
bool active_item_list = false;
for (uint32 i = 0; i < loot_drop->NumEntries; ++i) {
const EQ::ItemData *db_item = GetItem(loot_drop->Entries[i].item_id);
if (db_item && npc->MeetsLootDropLevelRequirements(loot_drop->Entries[i])) {
roll_t += loot_drop->Entries[i].chance;
if (loot_drop->Entries[i].chance >= 100) {
for (uint32 i = 0; i < lds->NumEntries; ++i) {
const EQ::ItemData *db_item = GetItem(lds->Entries[i].item_id);
if (db_item && npc->MeetsLootDropLevelRequirements(lds->Entries[i])) {
roll_t += lds->Entries[i].chance;
if (lds->Entries[i].chance >= 100) {
roll_table_chance_bypass = true;
} else {
no_loot_prob *= (100 - lds->Entries[i].chance) / 100.0f;
}
else {
no_loot_prob *= (100 - loot_drop->Entries[i].chance) / 100.0f;
}
active_item_list = true;
}
}
@@ -191,41 +205,40 @@ void ZoneDatabase::AddLootDropToNPC(NPC *npc, uint32 lootdrop_id, ItemList *item
for (int i = 0; i < droplimit; ++i) {
if (drops < mindrop || roll_table_chance_bypass || (float) zone->random.Real(0.0, 1.0) >= no_loot_prob) {
float roll = (float) zone->random.Real(0.0, roll_t);
for (uint32 j = 0; j < loot_drop->NumEntries; ++j) {
const EQ::ItemData *db_item = GetItem(loot_drop->Entries[j].item_id);
for (uint32 j = 0; j < lds->NumEntries; ++j) {
const auto *db_item = GetItem(lds->Entries[j].item_id);
if (db_item) {
// if it doesn't meet the requirements do nothing
if (!npc->MeetsLootDropLevelRequirements(loot_drop->Entries[j])) {
if (!npc->MeetsLootDropLevelRequirements(lds->Entries[j])) {
continue;
}
if (roll < loot_drop->Entries[j].chance) {
if (roll < lds->Entries[j].chance) {
npc->AddLootDrop(
db_item,
item_list,
loot_drop->Entries[j]
lds->Entries[j]
);
drops++;
int charges = (int) loot_drop->Entries[i].multiplier;
charges = EQ::ClampLower(charges, 1);
uint8 charges = lds->Entries[i].multiplier;
charges = EQ::ClampLower(charges, static_cast<uint8>(1));
for (int k = 1; k < charges; ++k) {
float c_roll = (float) zone->random.Real(0.0, 100.0);
if (c_roll <= loot_drop->Entries[i].chance) {
float c_roll = static_cast<float>(zone->random.Real(0.0, 100.0));
if (c_roll <= lds->Entries[i].chance) {
npc->AddLootDrop(
db_item,
item_list,
loot_drop->Entries[i]
lds->Entries[i]
);
}
}
j = loot_drop->NumEntries;
j = lds->NumEntries;
break;
}
else {
roll -= loot_drop->Entries[j].chance;
} else {
roll -= lds->Entries[j].chance;
}
}
}
@@ -291,19 +304,18 @@ void NPC::AddLootDrop(
ItemList *itemlist,
LootDropEntries_Struct loot_drop,
bool wear_change,
uint32 aug1,
uint32 aug2,
uint32 aug3,
uint32 aug4,
uint32 aug5,
uint32 aug6
uint32 augment_one,
uint32 augment_two,
uint32 augment_three,
uint32 augment_four,
uint32 augment_five,
uint32 augment_six
)
{
if (!item2) {
return;
}
//make sure we are doing something...
if (!itemlist && !wear_change) {
return;
}
@@ -340,18 +352,17 @@ void NPC::AddLootDrop(
item->item_id = item2->ID;
item->charges = loot_drop.item_charges;
item->aug_1 = aug1;
item->aug_2 = aug2;
item->aug_3 = aug3;
item->aug_4 = aug4;
item->aug_5 = aug5;
item->aug_6 = aug6;
item->attuned = 0;
item->aug_1 = augment_one;
item->aug_2 = augment_two;
item->aug_3 = augment_three;
item->aug_4 = augment_four;
item->aug_5 = augment_five;
item->aug_6 = augment_six;
item->attuned = false;
item->trivial_min_level = loot_drop.trivial_min_level;
item->trivial_max_level = loot_drop.trivial_max_level;
item->equip_slot = EQ::invslot::SLOT_INVALID;
// unsure if required to equip, YOLO for now
if (item2->ItemType == EQ::item::ItemTypeBow) {
SetBowEquipped(true);
@@ -363,17 +374,17 @@ void NPC::AddLootDrop(
bool found = false; // track if we found an empty slot we fit into
int foundslot = INVALID_INDEX; // for multi-slot items
int found_slot = INVALID_INDEX; // for multi-slot items
const auto* inst = database.CreateItem(
auto *inst = database.CreateItem(
item2->ID,
loot_drop.item_charges,
aug1,
aug2,
aug3,
aug4,
aug5,
aug6
augment_one,
augment_two,
augment_three,
augment_four,
augment_five,
augment_six
);
if (!inst) {
@@ -381,9 +392,8 @@ void NPC::AddLootDrop(
}
if (loot_drop.equip_item > 0) {
uint8 eslot = 0xFF;
char newid[20];
const EQ::ItemData* compitem = nullptr;
uint8 equipment_slot = UINT8_MAX;
const EQ::ItemData *compitem = nullptr;
// Equip rules are as follows:
// If the item has the NoPet flag set it will not be equipped.
@@ -395,141 +405,136 @@ void NPC::AddLootDrop(
// it is an improvement.
if (!item2->NoPet) {
for (int i = EQ::invslot::EQUIPMENT_BEGIN; !found && i <= EQ::invslot::EQUIPMENT_END; i++) {
uint32 slots = (1 << i);
for (
int i = EQ::invslot::EQUIPMENT_BEGIN;
!found && i <= EQ::invslot::EQUIPMENT_END;
i++
) {
const uint32 slots = (1 << i);
if (item2->Slots & slots) {
if(equipment[i])
{
if (equipment[i]) {
compitem = database.GetItem(equipment[i]);
if (item2->AC > compitem->AC ||
(item2->AC == compitem->AC && item2->HP > compitem->HP))
{
if (
item2->AC > compitem->AC ||
(item2->AC == compitem->AC && item2->HP > compitem->HP)
) {
// item would be an upgrade
// check if we're multi-slot, if yes then we have to keep
// looking in case any of the other slots we can fit into are empty.
if (item2->Slots != slots) {
foundslot = i;
}
else {
found_slot = i;
} else {
// Unequip old item
auto* olditem = GetItem(i);
auto *old_item = GetItem(i);
olditem->equip_slot = EQ::invslot::SLOT_INVALID;
old_item->equip_slot = EQ::invslot::SLOT_INVALID;
equipment[i] = item2->ID;
foundslot = i;
found = true;
found_slot = i;
found = true;
}
} // end if ac
}
else
{
}
} else {
equipment[i] = item2->ID;
foundslot = i;
found = true;
found_slot = i;
found = true;
}
} // end if (slots)
} // end for
} // end if NoPet
}
}
}
// Possible slot was found but not selected. Pick it now.
if (!found && foundslot >= 0) {
equipment[foundslot] = item2->ID;
if (!found && found_slot >= 0) {
equipment[found_slot] = item2->ID;
found = true;
}
// @merth: IDFile size has been increased, this needs to change
uint16 emat;
if(item2->Material <= 0
|| (item2->Slots & ((1 << EQ::invslot::slotPrimary) | (1 << EQ::invslot::slotSecondary)))) {
memset(newid, 0, sizeof(newid));
for(int i=0;i<7;i++){
if (!isalpha(item2->IDFile[i])){
strn0cpy(newid, &item2->IDFile[i],6);
i=8;
uint32 equipment_material;
if (
item2->Material <= 0 ||
(
item2->Slots & (
(1 << EQ::invslot::slotPrimary) |
(1 << EQ::invslot::slotSecondary)
)
)
) {
equipment_material = Strings::ToUnsignedInt(&item2->IDFile[2]);
} else {
equipment_material = item2->Material;
}
if (found_slot == EQ::invslot::slotPrimary) {
equipment_slot = EQ::textures::weaponPrimary;
if (item2->Damage > 0) {
SendAddPlayerState(PlayerState::PrimaryWeaponEquipped);
if (!RuleB(Combat, ClassicNPCBackstab)) {
SetFacestab(true);
}
}
emat = Strings::ToInt(newid);
} else {
emat = item2->Material;
}
if (foundslot == EQ::invslot::slotPrimary) {
eslot = EQ::textures::weaponPrimary;
if (item2->Damage > 0) {
SendAddPlayerState(PlayerState::PrimaryWeaponEquipped);
if (!RuleB(Combat, ClassicNPCBackstab))
SetFacestab(true);
}
if (item2->IsType2HWeapon())
if (item2->IsType2HWeapon()) {
SetTwoHanderEquipped(true);
}
else if (foundslot == EQ::invslot::slotSecondary
&& (GetOwner() != nullptr || (CanThisClassDualWield() && zone->random.Roll(NPC_DW_CHANCE)) || (item2->Damage==0)) &&
(item2->IsType1HWeapon() || item2->ItemType == EQ::item::ItemTypeShield || item2->ItemType == EQ::item::ItemTypeLight))
{
eslot = EQ::textures::weaponSecondary;
if (item2->Damage > 0)
SendAddPlayerState(PlayerState::SecondaryWeaponEquipped);
}
else if (foundslot == EQ::invslot::slotHead) {
eslot = EQ::textures::armorHead;
}
else if (foundslot == EQ::invslot::slotChest) {
eslot = EQ::textures::armorChest;
}
else if (foundslot == EQ::invslot::slotArms) {
eslot = EQ::textures::armorArms;
}
else if (foundslot == EQ::invslot::slotWrist1 || foundslot == EQ::invslot::slotWrist2) {
eslot = EQ::textures::armorWrist;
}
else if (foundslot == EQ::invslot::slotHands) {
eslot = EQ::textures::armorHands;
}
else if (foundslot == EQ::invslot::slotLegs) {
eslot = EQ::textures::armorLegs;
}
else if (foundslot == EQ::invslot::slotFeet) {
eslot = EQ::textures::armorFeet;
}
/*
what was this about???
if (((npc->GetRace()==127) && (npc->CastToMob()->GetOwnerID()!=0)) && (item2->Slots==24576) || (item2->Slots==8192) || (item2->Slots==16384)){
npc->d_melee_texture2=Strings::ToInt(newid);
wc->wear_slot_id=8;
if (item2->Material >0)
wc->material=item2->Material;
else
wc->material=Strings::ToInt(newid);
npc->AC+=item2->AC;
npc->STR+=item2->STR;
npc->INT+=item2->INT;
}
*/
//if we found an open slot it goes in...
if(eslot != 0xFF) {
if(wear_change) {
p_wear_change_struct->wear_slot_id = eslot;
p_wear_change_struct->material = emat;
}
} else if (
found_slot == EQ::invslot::slotSecondary &&
(
GetOwner() ||
(CanThisClassDualWield() && zone->random.Roll(NPC_DW_CHANCE)) ||
item2->Damage == 0
) &&
(
item2->IsType1HWeapon() ||
item2->ItemType == EQ::item::ItemTypeShield ||
item2->ItemType == EQ::item::ItemTypeLight
)
) {
equipment_slot = EQ::textures::weaponSecondary;
if (item2->Damage > 0) {
SendAddPlayerState(PlayerState::SecondaryWeaponEquipped);
}
} else if (found_slot == EQ::invslot::slotHead) {
equipment_slot = EQ::textures::armorHead;
} else if (found_slot == EQ::invslot::slotChest) {
equipment_slot = EQ::textures::armorChest;
} else if (found_slot == EQ::invslot::slotArms) {
equipment_slot = EQ::textures::armorArms;
} else if (EQ::ValueWithin(found_slot, EQ::invslot::slotWrist1, EQ::invslot::slotWrist2)) {
equipment_slot = EQ::textures::armorWrist;
} else if (found_slot == EQ::invslot::slotHands) {
equipment_slot = EQ::textures::armorHands;
} else if (found_slot == EQ::invslot::slotLegs) {
equipment_slot = EQ::textures::armorLegs;
} else if (found_slot == EQ::invslot::slotFeet) {
equipment_slot = EQ::textures::armorFeet;
}
if (equipment_slot != UINT8_MAX) {
if (wear_change) {
p_wear_change_struct->wear_slot_id = equipment_slot;
p_wear_change_struct->material = equipment_material;
}
}
if (found) {
item->equip_slot = foundslot;
item->equip_slot = found_slot;
}
}
if (itemlist) {
if (foundslot != INVALID_INDEX) {
GetInv().PutItem(foundslot, *inst);
if (found_slot != INVALID_INDEX) {
GetInv().PutItem(found_slot, *inst);
}
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_LOOT_ADDED)) {
std::vector<std::any> args = { inst };
parse->EventNPC(EVENT_LOOT_ADDED, this, nullptr, "", 0, &args);
}
itemlist->push_back(item);
@@ -551,55 +556,69 @@ void NPC::AddLootDrop(
}
UpdateEquipmentLight();
if (UpdateActiveLight()) {
SendAppearancePacket(AT_Light, GetActiveLightType());
}
}
void NPC::AddItem(const EQ::ItemData *item, uint16 charges, bool equipitem)
void NPC::AddItem(const EQ::ItemData *item, uint16 charges, bool equip_item)
{
//slot isnt needed, its determined from the item.
auto loot_drop_entry = NPC::NewLootDropEntry();
loot_drop_entry.equip_item = static_cast<uint8>(equipitem ? 1 : 0);
loot_drop_entry.equip_item = static_cast<uint8>(equip_item ? 1 : 0);
loot_drop_entry.item_charges = charges;
AddLootDrop(item, &itemlist, loot_drop_entry, true);
}
void NPC::AddItem(
uint32 itemid,
uint32 item_id,
uint16 charges,
bool equipitem,
uint32 aug1,
uint32 aug2,
uint32 aug3,
uint32 aug4,
uint32 aug5,
uint32 aug6
bool equip_item,
uint32 augment_one,
uint32 augment_two,
uint32 augment_three,
uint32 augment_four,
uint32 augment_five,
uint32 augment_six
)
{
//slot isnt needed, its determined from the item.
const EQ::ItemData *i = database.GetItem(itemid);
if (i == nullptr) {
const auto *item = database.GetItem(item_id);
if (!item) {
return;
}
auto loot_drop_entry = NPC::NewLootDropEntry();
loot_drop_entry.equip_item = static_cast<uint8>(equipitem ? 1 : 0);
loot_drop_entry.equip_item = static_cast<uint8>(equip_item ? 1 : 0);
loot_drop_entry.item_charges = charges;
AddLootDrop(i, &itemlist, loot_drop_entry, true, aug1, aug2, aug3, aug4, aug5, aug6);
AddLootDrop(
item,
&itemlist,
loot_drop_entry,
true,
augment_one,
augment_two,
augment_three,
augment_four,
augment_five,
augment_six
);
}
void NPC::AddLootTable() {
void NPC::AddLootTable()
{
if (npctype_id != 0) { // check if it's a GM spawn
database.AddLootTableToNPC(this,loottable_id, &itemlist, &copper, &silver, &gold, &platinum);
database.AddLootTableToNPC(this, loottable_id, &itemlist, &copper, &silver, &gold, &platinum);
}
}
void NPC::AddLootTable(uint32 ldid) {
void NPC::AddLootTable(uint32 loottable_id)
{
if (npctype_id != 0) { // check if it's a GM spawn
database.AddLootTableToNPC(this,ldid, &itemlist, &copper, &silver, &gold, &platinum);
database.AddLootTableToNPC(this, loottable_id, &itemlist, &copper, &silver, &gold, &platinum);
}
}
+109 -1
View File
@@ -389,6 +389,96 @@ int Lua_Bot::GetRawItemAC() {
return self->GetRawItemAC();
}
void Lua_Bot::ClearDisciplineReuseTimer() {
Lua_Safe_Call_Void();
return self->ClearDisciplineReuseTimer();
}
void Lua_Bot::ClearDisciplineReuseTimer(uint16 spell_id) {
Lua_Safe_Call_Void();
return self->ClearDisciplineReuseTimer(spell_id);
}
void Lua_Bot::ClearItemReuseTimer() {
Lua_Safe_Call_Void();
return self->ClearItemReuseTimer();
}
void Lua_Bot::ClearItemReuseTimer(uint32 item_id) {
Lua_Safe_Call_Void();
return self->ClearItemReuseTimer(item_id);
}
void Lua_Bot::ClearSpellRecastTimer() {
Lua_Safe_Call_Void();
return self->ClearSpellRecastTimer();
}
void Lua_Bot::ClearSpellRecastTimer(uint16 spell_id) {
Lua_Safe_Call_Void();
return self->ClearSpellRecastTimer(spell_id);
}
uint32 Lua_Bot::GetDisciplineReuseTimer() {
Lua_Safe_Call_Int();
return self->GetDisciplineReuseRemainingTime();
}
uint32 Lua_Bot::GetDisciplineReuseTimer(uint16 spell_id) {
Lua_Safe_Call_Int();
return self->GetDisciplineReuseRemainingTime(spell_id);
}
uint32 Lua_Bot::GetItemReuseTimer() {
Lua_Safe_Call_Int();
return self->GetItemReuseRemainingTime();
}
uint32 Lua_Bot::GetItemReuseTimer(uint32 item_id) {
Lua_Safe_Call_Int();
return self->GetItemReuseRemainingTime(item_id);
}
uint32 Lua_Bot::GetSpellRecastTimer() {
Lua_Safe_Call_Int();
return self->GetSpellRecastRemainingTime();
}
uint32 Lua_Bot::GetSpellRecastTimer(uint16 spell_id) {
Lua_Safe_Call_Int();
return self->GetSpellRecastRemainingTime(spell_id);
}
void Lua_Bot::SetDisciplineReuseTimer(uint16 spell_id) {
Lua_Safe_Call_Void();
return self->SetDisciplineReuseTimer(spell_id);
}
void Lua_Bot::SetDisciplineReuseTimer(uint16 spell_id, uint32 reuse_timer) {
Lua_Safe_Call_Void();
return self->SetDisciplineReuseTimer(spell_id, reuse_timer);
}
void Lua_Bot::SetItemReuseTimer(uint32 item_id) {
Lua_Safe_Call_Void();
return self->SetItemReuseTimer(item_id);
}
void Lua_Bot::SetItemReuseTimer(uint32 item_id, uint32 reuse_timer) {
Lua_Safe_Call_Void();
return self->SetItemReuseTimer(item_id, reuse_timer);
}
void Lua_Bot::SetSpellRecastTimer(uint16 spell_id) {
Lua_Safe_Call_Void();
return self->SetSpellRecastTimer(spell_id);
}
void Lua_Bot::SetSpellRecastTimer(uint16 spell_id, uint32 recast_delay) {
Lua_Safe_Call_Void();
return self->SetSpellRecastTimer(spell_id, recast_delay);
}
bool Lua_Bot::IsGrouped() {
Lua_Safe_Call_Bool();
return self->IsGrouped();
@@ -600,6 +690,12 @@ luabind::scope lua_register_bot() {
.def("ApplySpellRaid", (void(Lua_Bot::*)(int,int,int,bool,bool))&Lua_Bot::ApplySpellRaid)
.def("Camp", (void(Lua_Bot::*)(void))&Lua_Bot::Camp)
.def("Camp", (void(Lua_Bot::*)(bool))&Lua_Bot::Camp)
.def("ClearDisciplineReuseTimer", (void(Lua_Bot::*)())&Lua_Bot::ClearDisciplineReuseTimer)
.def("ClearDisciplineReuseTimer", (void(Lua_Bot::*)(uint16))&Lua_Bot::ClearDisciplineReuseTimer)
.def("ClearItemReuseTimer", (void(Lua_Bot::*)())&Lua_Bot::ClearItemReuseTimer)
.def("ClearItemReuseTimer", (void(Lua_Bot::*)(uint32))&Lua_Bot::ClearItemReuseTimer)
.def("ClearSpellRecastTimer", (void(Lua_Bot::*)())&Lua_Bot::ClearSpellRecastTimer)
.def("ClearSpellRecastTimer", (void(Lua_Bot::*)(uint16))&Lua_Bot::ClearSpellRecastTimer)
.def("CountBotItem", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::CountBotItem)
.def("CountItemEquippedByID", (int(Lua_Bot::*)(uint32))&Lua_Bot::CountItemEquippedByID)
.def("DeleteBucket", (void(Lua_Bot::*)(std::string))&Lua_Bot::DeleteBucket)
@@ -623,6 +719,8 @@ luabind::scope lua_register_bot() {
.def("GetBotID", (uint32(Lua_Bot::*)(void))&Lua_Bot::GetBotID)
.def("GetBotItem", (Lua_ItemInst(Lua_Bot::*)(uint16))&Lua_Bot::GetBotItem)
.def("GetBotItemIDBySlot", (uint32(Lua_Bot::*)(uint16))&Lua_Bot::GetBotItemIDBySlot)
.def("GetDisciplineReuseTimer", (uint32(Lua_Bot::*)())&Lua_Bot::GetDisciplineReuseTimer)
.def("GetDisciplineReuseTimer", (uint32(Lua_Bot::*)(uint16))&Lua_Bot::GetDisciplineReuseTimer)
.def("GetBucket", (std::string(Lua_Bot::*)(std::string))&Lua_Bot::GetBucket)
.def("GetBucketExpires", (std::string(Lua_Bot::*)(std::string))&Lua_Bot::GetBucketExpires)
.def("GetBucketRemaining", (std::string(Lua_Bot::*)(std::string))&Lua_Bot::GetBucketRemaining)
@@ -633,13 +731,17 @@ luabind::scope lua_register_bot() {
.def("GetInstrumentMod", (int(Lua_Bot::*)(int))&Lua_Bot::GetInstrumentMod)
.def("GetItemAt", (Lua_ItemInst(Lua_Bot::*)(int16))&Lua_Bot::GetItemAt)
.def("GetItemIDAt", (int(Lua_Bot::*)(int16))&Lua_Bot::GetItemIDAt)
.def("GetItemReuseTimer", (uint32(Lua_Bot::*)())&Lua_Bot::GetItemReuseTimer)
.def("GetItemReuseTimer", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::GetItemReuseTimer)
.def("GetOwner", (Lua_Mob(Lua_Bot::*)(void))&Lua_Bot::GetOwner)
.def("GetRaceAbbreviation", (std::string(Lua_Bot::*)(void))&Lua_Bot::GetRaceAbbreviation)
.def("GetRawItemAC", (int(Lua_Bot::*)(void))&Lua_Bot::GetRawItemAC)
.def("GetSpellDamage", (int(Lua_Bot::*)(void))&Lua_Bot::GetSpellDamage)
.def("GetSpellRecastTimer", (uint32(Lua_Bot::*)())&Lua_Bot::GetSpellRecastTimer)
.def("GetSpellRecastTimer", (uint32(Lua_Bot::*)(uint16))&Lua_Bot::GetSpellRecastTimer)
.def("HasAugmentEquippedByID", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasAugmentEquippedByID)
.def("HasBotItem", (int16(Lua_Bot::*)(uint32))&Lua_Bot::HasBotItem)
.def("HasBotSpellEntry", (bool(Lua_Bot::*)(uint16)) & Lua_Bot::HasBotSpellEntry)
.def("HasBotSpellEntry", (bool(Lua_Bot::*)(uint16))&Lua_Bot::HasBotSpellEntry)
.def("HasItemEquippedByID", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasItemEquippedByID)
.def("IsGrouped", (bool(Lua_Bot::*)(void))&Lua_Bot::IsGrouped)
.def("IsSitting", (bool(Lua_Bot::*)(void))&Lua_Bot::IsSitting)
@@ -655,6 +757,10 @@ luabind::scope lua_register_bot() {
.def("SetBucket", (void(Lua_Bot::*)(std::string,std::string,std::string))&Lua_Bot::SetBucket)
.def("SetExpansionBitmask", (void(Lua_Bot::*)(int))&Lua_Bot::SetExpansionBitmask)
.def("SetExpansionBitmask", (void(Lua_Bot::*)(int,bool))&Lua_Bot::SetExpansionBitmask)
.def("SetDisciplineReuseTimer", (void(Lua_Bot::*)(uint16))&Lua_Bot::SetDisciplineReuseTimer)
.def("SetDisciplineReuseTimer", (void(Lua_Bot::*)(uint16, uint32))&Lua_Bot::SetDisciplineReuseTimer)
.def("SetItemReuseTimer", (void(Lua_Bot::*)(uint32))&Lua_Bot::SetItemReuseTimer)
.def("SetItemReuseTimer", (void(Lua_Bot::*)(uint32, uint32))&Lua_Bot::SetItemReuseTimer)
.def("SetSpellDuration", (void(Lua_Bot::*)(int))&Lua_Bot::SetSpellDuration)
.def("SetSpellDuration", (void(Lua_Bot::*)(int,int))&Lua_Bot::SetSpellDuration)
.def("SetSpellDuration", (void(Lua_Bot::*)(int,int,int))&Lua_Bot::SetSpellDuration)
@@ -668,6 +774,8 @@ luabind::scope lua_register_bot() {
.def("SetSpellDurationRaid", (void(Lua_Bot::*)(int,int,int))&Lua_Bot::SetSpellDurationRaid)
.def("SetSpellDurationRaid", (void(Lua_Bot::*)(int,int,int,bool))&Lua_Bot::SetSpellDurationRaid)
.def("SetSpellDurationRaid", (void(Lua_Bot::*)(int,int,int,bool,bool))&Lua_Bot::SetSpellDurationRaid)
.def("SetSpellRecastTimer", (void(Lua_Bot::*)(uint16))&Lua_Bot::SetSpellRecastTimer)
.def("SetSpellRecastTimer", (void(Lua_Bot::*)(uint16, uint32))&Lua_Bot::SetSpellRecastTimer)
.def("SendPayload", (void(Lua_Bot::*)(int))&Lua_Bot::SendPayload)
.def("SendPayload", (void(Lua_Bot::*)(int,std::string))&Lua_Bot::SendPayload)
.def("Signal", (void(Lua_Bot::*)(int))&Lua_Bot::Signal)
+19
View File
@@ -107,6 +107,25 @@ public:
void SetSpellDurationRaid(int spell_id, int duration, int level, bool allow_pets);
void SetSpellDurationRaid(int spell_id, int duration, int level, bool allow_pets, bool is_raid_group_only);
void ClearDisciplineReuseTimer();
void ClearDisciplineReuseTimer(uint16 spell_id);
void ClearItemReuseTimer();
void ClearItemReuseTimer(uint32 item_id);
void ClearSpellRecastTimer();
void ClearSpellRecastTimer(uint16 spell_id);
uint32 GetDisciplineReuseTimer();
uint32 GetDisciplineReuseTimer(uint16 spell_id);
uint32 GetItemReuseTimer();
uint32 GetItemReuseTimer(uint32 item_id);
uint32 GetSpellRecastTimer();
uint32 GetSpellRecastTimer(uint16 spell_id);
void SetDisciplineReuseTimer(uint16 spell_id);
void SetDisciplineReuseTimer(uint16 spell_id, uint32 reuse_timer);
void SetItemReuseTimer(uint32 item_id);
void SetItemReuseTimer(uint32 item_id, uint32 reuse_timer);
void SetSpellRecastTimer(uint16 spell_id);
void SetSpellRecastTimer(uint16 spell_id, uint32 reuse_timer);
int CountAugmentEquippedByID(uint32 item_id);
int CountItemEquippedByID(uint32 item_id);
bool HasAugmentEquippedByID(uint32 item_id);
+51 -6
View File
@@ -1211,7 +1211,24 @@ void Lua_Client::AddPVPPoints(uint32 points) {
void Lua_Client::AddCrystals(uint32 radiant, uint32 ebon) {
Lua_Safe_Call_Void();
self->AddCrystals(radiant, ebon);
if (ebon != 0) {
if (ebon > 0) {
self->AddEbonCrystals(ebon);
return;
}
self->RemoveEbonCrystals(ebon);
}
if (radiant != 0) {
if (radiant > 0) {
self->AddRadiantCrystals(radiant);
return;
}
self->RemoveRadiantCrystals(radiant);
}
}
void Lua_Client::SetEbonCrystals(uint32 value) {
@@ -1486,15 +1503,15 @@ void Lua_Client::Signal(int signal_id) {
void Lua_Client::AddAlternateCurrencyValue(uint32 currency, int amount) {
Lua_Safe_Call_Void();
self->AddAlternateCurrencyValue(currency, amount, 1);
self->AddAlternateCurrencyValue(currency, amount, true);
}
void Lua_Client::SetAlternateCurrencyValue(uint32 currency, int amount) {
void Lua_Client::SetAlternateCurrencyValue(uint32 currency, uint32 amount) {
Lua_Safe_Call_Void();
self->SetAlternateCurrencyValue(currency, amount);
}
int Lua_Client::GetAlternateCurrencyValue(uint32 currency) {
uint32 Lua_Client::GetAlternateCurrencyValue(uint32 currency) {
Lua_Safe_Call_Int();
return self->GetAlternateCurrencyValue(currency);
}
@@ -3176,6 +3193,30 @@ void Lua_Client::GrantAllAAPoints(uint8 unlock_level)
self->GrantAllAAPoints(unlock_level);
}
void Lua_Client::AddEbonCrystals(uint32 amount)
{
Lua_Safe_Call_Void();
self->AddEbonCrystals(amount);
}
void Lua_Client::AddRadiantCrystals(uint32 amount)
{
Lua_Safe_Call_Void();
self->AddRadiantCrystals(amount);
}
void Lua_Client::RemoveEbonCrystals(uint32 amount)
{
Lua_Safe_Call_Void();
self->RemoveEbonCrystals(amount);
}
void Lua_Client::RemoveRadiantCrystals(uint32 amount)
{
Lua_Safe_Call_Void();
self->RemoveRadiantCrystals(amount);
}
luabind::scope lua_register_client() {
return luabind::class_<Lua_Client, Lua_Mob>("Client")
.def(luabind::constructor<>())
@@ -3187,6 +3228,7 @@ luabind::scope lua_register_client() {
.def("AddEXP", (void(Lua_Client::*)(uint32))&Lua_Client::AddEXP)
.def("AddEXP", (void(Lua_Client::*)(uint32,int))&Lua_Client::AddEXP)
.def("AddEXP", (void(Lua_Client::*)(uint32,int,bool))&Lua_Client::AddEXP)
.def("AddEbonCrystals", (void(Lua_Client::*)(uint32))&Lua_Client::AddEbonCrystals)
.def("AddExpeditionLockout", (void(Lua_Client::*)(std::string, std::string, uint32))&Lua_Client::AddExpeditionLockout)
.def("AddExpeditionLockout", (void(Lua_Client::*)(std::string, std::string, uint32, std::string))&Lua_Client::AddExpeditionLockout)
.def("AddExpeditionLockoutDuration", (void(Lua_Client::*)(std::string, std::string, int))&Lua_Client::AddExpeditionLockoutDuration)
@@ -3202,6 +3244,7 @@ luabind::scope lua_register_client() {
.def("AddPlatinum", (void(Lua_Client::*)(uint32))&Lua_Client::AddPlatinum)
.def("AddPlatinum", (void(Lua_Client::*)(uint32,bool))&Lua_Client::AddPlatinum)
.def("AddPVPPoints", (void(Lua_Client::*)(uint32))&Lua_Client::AddPVPPoints)
.def("AddRadiantCrystals", (void(Lua_Client::*)(uint32))&Lua_Client::AddRadiantCrystals)
.def("AddSkill", (void(Lua_Client::*)(int,int))&Lua_Client::AddSkill)
.def("Admin", (int16(Lua_Client::*)(void))&Lua_Client::Admin)
.def("ApplySpell", (void(Lua_Client::*)(int))&Lua_Client::ApplySpell)
@@ -3303,7 +3346,7 @@ luabind::scope lua_register_client() {
.def("GetAccountFlags", (luabind::object(Lua_Client::*)(lua_State*))&Lua_Client::GetAccountFlags)
.def("GetAggroCount", (uint32(Lua_Client::*)(void))&Lua_Client::GetAggroCount)
.def("GetAllMoney", (uint64(Lua_Client::*)(void))&Lua_Client::GetAllMoney)
.def("GetAlternateCurrencyValue", (int(Lua_Client::*)(uint32))&Lua_Client::GetAlternateCurrencyValue)
.def("GetAlternateCurrencyValue", (uint32(Lua_Client::*)(uint32))&Lua_Client::GetAlternateCurrencyValue)
.def("GetAnon", (int(Lua_Client::*)(void))&Lua_Client::GetAnon)
.def("GetAugmentIDAt", (int(Lua_Client::*)(int,int))&Lua_Client::GetAugmentIDAt)
.def("GetAugmentIDsBySlotID", (luabind::object(Lua_Client::*)(lua_State* L,int16))&Lua_Client::GetAugmentIDsBySlotID)
@@ -3554,7 +3597,9 @@ luabind::scope lua_register_client() {
.def("ResetCastbarCooldownBySlot", (void(Lua_Client::*)(int))&Lua_Client::ResetCastbarCooldownBySlot)
.def("ResetCastbarCooldownBySpellID", (void(Lua_Client::*)(uint32))&Lua_Client::ResetCastbarCooldownBySpellID)
.def("ResetDisciplineTimer", (void(Lua_Client::*)(uint32))&Lua_Client::ResetDisciplineTimer)
.def("RemoveEbonCrystals", (void(Lua_Client::*)(uint32))&Lua_Client::RemoveEbonCrystals)
.def("ResetItemCooldown", (void(Lua_Client::*)(uint32))&Lua_Client::ResetItemCooldown)
.def("RemoveRadiantCrystals", (void(Lua_Client::*)(uint32))&Lua_Client::RemoveRadiantCrystals)
.def("ResetTrade", (void(Lua_Client::*)(void))&Lua_Client::ResetTrade)
.def("RewardFaction", (void(Lua_Client::*)(int,int))&Lua_Client::RewardFaction)
.def("Save", (void(Lua_Client::*)(int))&Lua_Client::Save)
@@ -3586,7 +3631,7 @@ luabind::scope lua_register_client() {
.def("SetAATitle", (void(Lua_Client::*)(std::string,bool))&Lua_Client::SetAATitle)
.def("SetAFK", (void(Lua_Client::*)(uint8))&Lua_Client::SetAFK)
.def("SetAccountFlag", (void(Lua_Client::*)(const std::string&,const std::string&))&Lua_Client::SetAccountFlag)
.def("SetAlternateCurrencyValue", (void(Lua_Client::*)(uint32,int))&Lua_Client::SetAlternateCurrencyValue)
.def("SetAlternateCurrencyValue", (void(Lua_Client::*)(uint32,uint32))&Lua_Client::SetAlternateCurrencyValue)
.def("SetAnon", (void(Lua_Client::*)(uint8))&Lua_Client::SetAnon)
.def("SetBaseClass", (void(Lua_Client::*)(int))&Lua_Client::SetBaseClass)
.def("SetBaseGender", (void(Lua_Client::*)(int))&Lua_Client::SetBaseGender)
+6 -2
View File
@@ -376,8 +376,8 @@ public:
void NotifyNewTitlesAvailable();
void Signal(int signal_id);
void AddAlternateCurrencyValue(uint32 currency, int amount);
void SetAlternateCurrencyValue(uint32 currency, int amount);
int GetAlternateCurrencyValue(uint32 currency);
void SetAlternateCurrencyValue(uint32 currency, uint32 amount);
uint32 GetAlternateCurrencyValue(uint32 currency);
void SendWebLink(const char *site);
bool HasSpellScribed(int spell_id);
void ClearAccountFlag(const std::string& flag);
@@ -482,6 +482,10 @@ public:
void SetBucket(std::string bucket_name, std::string bucket_value, std::string expiration);
void GrantAllAAPoints();
void GrantAllAAPoints(uint8 unlock_level);
void AddEbonCrystals(uint32 amount);
void AddRadiantCrystals(uint32 amount);
void RemoveEbonCrystals(uint32 amount);
void RemoveRadiantCrystals(uint32 amount);
void ApplySpell(int spell_id);
void ApplySpell(int spell_id, int duration);
+55 -47
View File
@@ -5431,7 +5431,7 @@ void lua_create_npc(luabind::adl::object table, float x, float y, float z, float
LuaCreateNPCParse(runspeed, float, 1.25f);
LuaCreateNPCParse(gender, uint8, 0);
LuaCreateNPCParse(race, uint16, 1);
LuaCreateNPCParse(class_, uint8, WARRIOR);
LuaCreateNPCParse(class_, uint8, Class::Warrior);
LuaCreateNPCParse(bodytype, uint8, 0);
LuaCreateNPCParse(deity, uint8, 0);
LuaCreateNPCParse(level, uint8, 1);
@@ -6609,7 +6609,14 @@ luabind::scope lua_register_events() {
luabind::value("memorize_spell", static_cast<int>(EVENT_MEMORIZE_SPELL)),
luabind::value("unmemorize_spell", static_cast<int>(EVENT_UNMEMORIZE_SPELL)),
luabind::value("scribe_spell", static_cast<int>(EVENT_SCRIBE_SPELL)),
luabind::value("unscribe_spell", static_cast<int>(EVENT_UNSCRIBE_SPELL))
luabind::value("unscribe_spell", static_cast<int>(EVENT_UNSCRIBE_SPELL)),
luabind::value("loot_added", static_cast<int>(EVENT_LOOT_ADDED)),
luabind::value("ldon_points_gain", static_cast<int>(EVENT_LDON_POINTS_GAIN)),
luabind::value("ldon_points_loss", static_cast<int>(EVENT_LDON_POINTS_LOSS)),
luabind::value("alt_currency_gain", static_cast<int>(EVENT_ALT_CURRENCY_GAIN)),
luabind::value("alt_currency_loss", static_cast<int>(EVENT_ALT_CURRENCY_LOSS)),
luabind::value("crystal_gain", static_cast<int>(EVENT_CRYSTAL_GAIN)),
luabind::value("crystal_loss", static_cast<int>(EVENT_CRYSTAL_LOSS))
)];
}
@@ -6778,51 +6785,52 @@ luabind::scope lua_register_classes() {
return luabind::class_<Classes>("Class")
.enum_("constants")
[(
luabind::value("WARRIOR", WARRIOR),
luabind::value("CLERIC", CLERIC),
luabind::value("PALADIN", PALADIN),
luabind::value("RANGER", RANGER),
luabind::value("SHADOWKNIGHT", SHADOWKNIGHT),
luabind::value("DRUID", DRUID),
luabind::value("MONK", MONK),
luabind::value("BARD", BARD),
luabind::value("ROGUE", ROGUE),
luabind::value("SHAMAN", SHAMAN),
luabind::value("NECROMANCER", NECROMANCER),
luabind::value("WIZARD", WIZARD),
luabind::value("MAGICIAN", MAGICIAN),
luabind::value("ENCHANTER", ENCHANTER),
luabind::value("BEASTLORD", BEASTLORD),
luabind::value("BERSERKER", BERSERKER),
luabind::value("WARRIORGM", WARRIORGM),
luabind::value("CLERICGM", CLERICGM),
luabind::value("PALADINGM", PALADINGM),
luabind::value("RANGERGM", RANGERGM),
luabind::value("SHADOWKNIGHTGM", SHADOWKNIGHTGM),
luabind::value("DRUIDGM", DRUIDGM),
luabind::value("MONKGM", MONKGM),
luabind::value("BARDGM", BARDGM),
luabind::value("ROGUEGM", ROGUEGM),
luabind::value("SHAMANGM", SHAMANGM),
luabind::value("NECROMANCERGM", NECROMANCERGM),
luabind::value("WIZARDGM", WIZARDGM),
luabind::value("MAGICIANGM", MAGICIANGM),
luabind::value("ENCHANTERGM", ENCHANTERGM),
luabind::value("BEASTLORDGM", BEASTLORDGM),
luabind::value("BERSERKERGM", BERSERKERGM),
luabind::value("BANKER", BANKER),
luabind::value("MERCHANT", MERCHANT),
luabind::value("DISCORD_MERCHANT", DISCORD_MERCHANT),
luabind::value("ADVENTURE_RECRUITER", ADVENTURE_RECRUITER),
luabind::value("ADVENTURE_MERCHANT", ADVENTURE_MERCHANT),
luabind::value("LDON_TREASURE", LDON_TREASURE),
luabind::value("TRIBUTE_MASTER", TRIBUTE_MASTER),
luabind::value("GUILD_TRIBUTE_MASTER", GUILD_TRIBUTE_MASTER),
luabind::value("NORRATHS_KEEPERS_MERCHANT", NORRATHS_KEEPERS_MERCHANT),
luabind::value("DARK_REIGN_MERCHANT", DARK_REIGN_MERCHANT),
luabind::value("FELLOWSHIP_MASTER", FELLOWSHIP_MASTER),
luabind::value("ALT_CURRENCY_MERCHANT", ALT_CURRENCY_MERCHANT),
luabind::value("MERCENARY_MASTER", MERCENARY_MASTER)
luabind::value("WARRIOR", Class::Warrior),
luabind::value("CLERIC", Class::Cleric),
luabind::value("PALADIN", Class::Paladin),
luabind::value("RANGER", Class::Ranger),
luabind::value("SHADOWKNIGHT", Class::ShadowKnight),
luabind::value("DRUID", Class::Druid),
luabind::value("MONK", Class::Monk),
luabind::value("BARD", Class::Bard),
luabind::value("ROGUE", Class::Rogue),
luabind::value("SHAMAN", Class::Shaman),
luabind::value("NECROMANCER", Class::Necromancer),
luabind::value("WIZARD", Class::Wizard),
luabind::value("MAGICIAN", Class::Magician),
luabind::value("ENCHANTER", Class::Enchanter),
luabind::value("BEASTLORD", Class::Beastlord),
luabind::value("BERSERKER", Class::Berserker),
luabind::value("WARRIORGM", Class::WarriorGM),
luabind::value("CLERICGM", Class::ClericGM),
luabind::value("PALADINGM", Class::PaladinGM),
luabind::value("RANGERGM", Class::RangerGM),
luabind::value("SHADOWKNIGHTGM", Class::ShadowKnightGM),
luabind::value("DRUIDGM", Class::DruidGM),
luabind::value("MONKGM", Class::MonkGM),
luabind::value("BARDGM", Class::BardGM),
luabind::value("ROGUEGM", Class::RogueGM),
luabind::value("SHAMANGM", Class::ShamanGM),
luabind::value("NECROMANCERGM", Class::NecromancerGM),
luabind::value("WIZARDGM", Class::WizardGM),
luabind::value("MAGICIANGM", Class::MagicianGM),
luabind::value("ENCHANTERGM", Class::EnchanterGM),
luabind::value("BEASTLORDGM", Class::BeastlordGM),
luabind::value("BERSERKERGM", Class::BerserkerGM),
luabind::value("BANKER", Class::Banker),
luabind::value("MERCHANT", Class::Merchant),
luabind::value("DISCORD_MERCHANT", Class::DiscordMerchant),
luabind::value("ADVENTURE_RECRUITER", Class::AdventureRecruiter),
luabind::value("ADVENTURE_MERCHANT", Class::AdventureMerchant),
luabind::value("LDON_TREASURE", Class::LDoNTreasure),
luabind::value("TRIBUTE_MASTER", Class::TributeMaster),
luabind::value("GUILD_TRIBUTE_MASTER", Class::GuildTributeMaster),
luabind::value("GUILD_BANKER", Class::GuildBanker),
luabind::value("NORRATHS_KEEPERS_MERCHANT", Class::NorrathsKeepersMerchant),
luabind::value("DARK_REIGN_MERCHANT", Class::DarkReignMerchant),
luabind::value("FELLOWSHIP_MASTER", Class::FellowshipMaster),
luabind::value("ALT_CURRENCY_MERCHANT", Class::AlternateCurrencyMerchant),
luabind::value("MERCENARY_MASTER", Class::MercenaryLiaison)
)];
}
+14
View File
@@ -813,6 +813,18 @@ void Lua_NPC::SetBucket(std::string bucket_name, std::string bucket_value, std::
self->SetBucket(bucket_name, bucket_value, expiration);
}
bool Lua_NPC::GetNPCAggro()
{
Lua_Safe_Call_Bool();
return self->GetNPCAggro();
}
void Lua_NPC::SetNPCAggro(bool in_npc_aggro)
{
Lua_Safe_Call_Void();
self->SetNPCAggro(in_npc_aggro);
}
luabind::scope lua_register_npc() {
return luabind::class_<Lua_NPC, Lua_Mob>("NPC")
.def(luabind::constructor<>())
@@ -872,6 +884,7 @@ luabind::scope lua_register_npc() {
.def("GetLDoNLockedSkill", (uint16(Lua_NPC::*)(void))&Lua_NPC::GetLDoNLockedSkill)
.def("GetLDoNTrapType", (uint8(Lua_NPC::*)(void))&Lua_NPC::GetLDoNTrapType)
.def("GetLDoNTrapSpellID", (uint16(Lua_NPC::*)(void))&Lua_NPC::GetLDoNTrapSpellID)
.def("GetNPCAggro", (bool(Lua_NPC::*)(void))&Lua_NPC::GetNPCAggro)
.def("GetNPCFactionID", (int(Lua_NPC::*)(void))&Lua_NPC::GetNPCFactionID)
.def("GetNPCHate", (int64(Lua_NPC::*)(Lua_Mob))&Lua_NPC::GetNPCHate)
.def("GetNPCSpellsID", (int(Lua_NPC::*)(void))&Lua_NPC::GetNPCSpellsID)
@@ -949,6 +962,7 @@ luabind::scope lua_register_npc() {
.def("SetLDoNTrapDetected", (void(Lua_NPC::*)(bool))&Lua_NPC::SetLDoNTrapDetected)
.def("SetLDoNTrapSpellID", (void(Lua_NPC::*)(uint16))&Lua_NPC::SetLDoNTrapSpellID)
.def("SetLDoNTrapType", (void(Lua_NPC::*)(uint8))&Lua_NPC::SetLDoNTrapType)
.def("SetNPCAggro", (void(Lua_NPC::*)(bool))&Lua_NPC::SetNPCAggro)
.def("SetNPCFactionID", (void(Lua_NPC::*)(int))&Lua_NPC::SetNPCFactionID)
.def("SetPetSpellID", (void(Lua_NPC::*)(int))&Lua_NPC::SetPetSpellID)
.def("SetPlatinum", (void(Lua_NPC::*)(uint32))&Lua_NPC::SetPlatinum)
+2
View File
@@ -182,6 +182,8 @@ public:
std::string GetBucketRemaining(std::string bucket_name);
void SetBucket(std::string bucket_name, std::string bucket_value);
void SetBucket(std::string bucket_name, std::string bucket_value, std::string expiration);
bool GetNPCAggro();
void SetNPCAggro(bool in_npc_aggro);
};
#endif
+17 -1
View File
@@ -168,7 +168,14 @@ const char *LuaEvents[_LargestEventID] = {
"event_memorize_spell",
"event_unmemorize_spell",
"event_scribe_spell",
"event_unscribe_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"
};
extern Zone *zone;
@@ -226,6 +233,7 @@ LuaParser::LuaParser() {
NPCArgumentDispatch[EVENT_DESPAWN_ZONE] = handle_npc_despawn_zone;
NPCArgumentDispatch[EVENT_DAMAGE_GIVEN] = handle_npc_damage;
NPCArgumentDispatch[EVENT_DAMAGE_TAKEN] = handle_npc_damage;
NPCArgumentDispatch[EVENT_LOOT_ADDED] = handle_npc_loot_added;
PlayerArgumentDispatch[EVENT_SAY] = handle_player_say;
PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage;
@@ -300,6 +308,12 @@ LuaParser::LuaParser() {
PlayerArgumentDispatch[EVENT_UNMEMORIZE_SPELL] = handle_player_memorize_scribe_spell;
PlayerArgumentDispatch[EVENT_SCRIBE_SPELL] = handle_player_memorize_scribe_spell;
PlayerArgumentDispatch[EVENT_UNSCRIBE_SPELL] = handle_player_memorize_scribe_spell;
PlayerArgumentDispatch[EVENT_LDON_POINTS_GAIN] = handle_player_ldon_points_gain_loss;
PlayerArgumentDispatch[EVENT_LDON_POINTS_LOSS] = handle_player_ldon_points_gain_loss;
PlayerArgumentDispatch[EVENT_ALT_CURRENCY_GAIN] = handle_player_alt_currency_gain_loss;
PlayerArgumentDispatch[EVENT_ALT_CURRENCY_LOSS] = handle_player_alt_currency_gain_loss;
PlayerArgumentDispatch[EVENT_CRYSTAL_GAIN] = handle_player_crystal_gain_loss;
PlayerArgumentDispatch[EVENT_CRYSTAL_LOSS] = handle_player_crystal_gain_loss;
ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click;
ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click;
@@ -341,6 +355,8 @@ LuaParser::LuaParser() {
BotArgumentDispatch[EVENT_UNEQUIP_ITEM_BOT] = handle_bot_equip_item;
BotArgumentDispatch[EVENT_DAMAGE_GIVEN] = handle_bot_damage;
BotArgumentDispatch[EVENT_DAMAGE_TAKEN] = handle_bot_damage;
BotArgumentDispatch[EVENT_LEVEL_UP] = handle_bot_level_up;
BotArgumentDispatch[EVENT_LEVEL_DOWN] = handle_bot_level_down;
#endif
L = nullptr;
+140
View File
@@ -492,6 +492,63 @@ void handle_npc_damage(
lua_setfield(L, -2, "other");
}
void handle_npc_loot_added(
QuestInterface *parse,
lua_State* L,
NPC* npc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
if (extra_pointers && extra_pointers->size() == 1) {
auto *inst = std::any_cast<EQ::ItemInstance *>(extra_pointers->at(0));
auto *item = database.GetItem(inst->GetID());
if (item) {
Lua_Item l_item(item);
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
l_item_o.push(L);
lua_setfield(L, -2, "item");
} else {
Lua_Item l_item(nullptr);
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
l_item_o.push(L);
lua_setfield(L, -2, "item");
}
if (inst) {
lua_pushinteger(L, inst->GetID());
lua_setfield(L, -2, "item_id");
lua_pushstring(L, inst->GetItem()->Name);
lua_setfield(L, -2, "item_name");
lua_pushinteger(L, inst->GetCharges());
lua_setfield(L, -2, "item_charges");
lua_pushinteger(L, inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN));
lua_setfield(L, -2, "augment_one");
lua_pushinteger(L, inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 1));
lua_setfield(L, -2, "augment_two");
lua_pushinteger(L, inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 2));
lua_setfield(L, -2, "augment_three");
lua_pushinteger(L, inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 3));
lua_setfield(L, -2, "augment_four");
lua_pushinteger(L, inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 4));
lua_setfield(L, -2, "augment_five");
lua_pushinteger(L, inst->GetAugmentItemID(EQ::invaug::SOCKET_END));
lua_setfield(L, -2, "augment_six");
}
}
}
// Player
void handle_player_say(
QuestInterface *parse,
@@ -1444,6 +1501,63 @@ void handle_player_memorize_scribe_spell(
}
}
void handle_player_ldon_points_gain_loss(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushnumber(L, Strings::ToUnsignedInt(sep.arg[0]));
lua_setfield(L, -2, "theme_id");
lua_pushnumber(L, Strings::ToUnsignedInt(sep.arg[1]));
lua_setfield(L, -2, "points");
}
void handle_player_crystal_gain_loss(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushnumber(L, Strings::ToUnsignedInt(sep.arg[0]));
lua_setfield(L, -2, "ebon_amount");
lua_pushnumber(L, Strings::ToUnsignedInt(sep.arg[1]));
lua_setfield(L, -2, "radiant_amount");
lua_pushboolean(L, Strings::ToBool(sep.arg[2]));
lua_setfield(L, -2, "is_reclaim");
}
void handle_player_alt_currency_gain_loss(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushnumber(L, Strings::ToUnsignedInt(sep.arg[0]));
lua_setfield(L, -2, "currency_id");
lua_pushnumber(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "amount");
lua_pushnumber(L, Strings::ToUnsignedInt(sep.arg[2]));
lua_setfield(L, -2, "total");
}
// Item
void handle_item_click(
QuestInterface *parse,
@@ -2300,4 +2414,30 @@ void handle_bot_damage(
lua_setfield(L, -2, "other");
}
void handle_bot_level_up(
QuestInterface *parse,
lua_State* L,
Bot* bot,
Mob *init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushinteger(L, Strings::ToInt(data));
lua_setfield(L, -2, "levels_gained");
}
void handle_bot_level_down(
QuestInterface *parse,
lua_State* L,
Bot* bot,
Mob *init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushinteger(L, Strings::ToInt(data));
lua_setfield(L, -2, "levels_lost");
}
#endif
+57
View File
@@ -210,6 +210,16 @@ void handle_npc_damage(
std::vector<std::any> *extra_pointers
);
void handle_npc_loot_added(
QuestInterface *parse,
lua_State* L,
NPC* npc,
Mob *init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
// Player
void handle_player_say(
QuestInterface *parse,
@@ -733,6 +743,33 @@ void handle_player_memorize_scribe_spell(
std::vector<std::any> *extra_pointers
);
void handle_player_ldon_points_gain_loss(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
void handle_player_alt_currency_gain_loss(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
void handle_player_crystal_gain_loss(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
// Item
void handle_item_click(
QuestInterface *parse,
@@ -1055,5 +1092,25 @@ void handle_bot_damage(
std::vector<std::any> *extra_pointers
);
void handle_bot_level_up(
QuestInterface *parse,
lua_State* L,
Bot* bot,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
void handle_bot_level_down(
QuestInterface *parse,
lua_State* L,
Bot* bot,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
#endif
#endif
+7 -7
View File
@@ -60,7 +60,7 @@ Merc::Merc(const NPCType* d, float x, float y, float z, float heading)
SetStance(EQ::constants::stanceBalanced);
rest_timer.Disable();
if (GetClass() == ROGUE)
if (GetClass() == Class::Rogue)
evade_timer.Start();
int r;
@@ -1090,7 +1090,7 @@ void Merc::AI_Process() {
float meleeDistance = GetMaxMeleeRangeToTarget(GetTarget());
if(GetClass() == SHADOWKNIGHT || GetClass() == PALADIN || GetClass() == WARRIOR) {
if(GetClass() == Class::ShadowKnight || GetClass() == Class::Paladin || GetClass() == Class::Warrior) {
meleeDistance = meleeDistance * .30;
}
else {
@@ -1118,7 +1118,7 @@ void Merc::AI_Process() {
if(AI_movement_timer->Check()) {
if (!IsMoving()) {
if (GetClass() == ROGUE) {
if (GetClass() == Class::Rogue) {
if (HasTargetReflection() && !GetTarget()->IsFeared() && !GetTarget()->IsStunned()) {
// Hate redux actions
if (evade_timer.Check(false)) {
@@ -1161,7 +1161,7 @@ void Merc::AI_Process() {
}
}
}
else if (GetClass() != ROGUE && (DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) < GetTarget()->GetSize())) {
else if (GetClass() != Class::Rogue && (DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) < GetTarget()->GetSize())) {
// If we are not a rogue trying to backstab, let's try to adjust our melee range so we don't appear to be bunched up
float newX = 0;
float newY = 0;
@@ -1240,7 +1240,7 @@ void Merc::AI_Process() {
}
// TODO: Do mercs berserk? Find this out on live...
//if (GetClass() == WARRIOR || GetClass() == BERSERKER) {
//if (GetClass() == Class::Warrior || GetClass() == Class::Berserker) {
// if(GetHP() > 0 && !berserk && GetHPRatio() < 30) {
// entity_list.MessageCloseString(this, false, 200, 0, BERSERK_START, GetName());
// berserk = true;
@@ -1685,8 +1685,8 @@ bool Merc::AICastSpell(int8 iChance, uint32 iSpellTypes) {
continue;
}
if(IsEngaged() && (g->members[i]->GetClass() == NECROMANCER && hpr >= 50)
|| (g->members[i]->GetClass() == SHAMAN && hpr >= 80)) {
if(IsEngaged() && (g->members[i]->GetClass() == Class::Necromancer && hpr >= 50)
|| (g->members[i]->GetClass() == Class::Shaman && hpr >= 80)) {
//allow necros to lifetap & shaman to canni without wasting mana
continue;
}
+131 -137
View File
@@ -983,33 +983,33 @@ int64 Mob::GetSpellHPBonuses() {
char Mob::GetCasterClass() const {
switch(class_)
{
case CLERIC:
case PALADIN:
case RANGER:
case DRUID:
case SHAMAN:
case BEASTLORD:
case CLERICGM:
case PALADINGM:
case RANGERGM:
case DRUIDGM:
case SHAMANGM:
case BEASTLORDGM:
case Class::Cleric:
case Class::Paladin:
case Class::Ranger:
case Class::Druid:
case Class::Shaman:
case Class::Beastlord:
case Class::ClericGM:
case Class::PaladinGM:
case Class::RangerGM:
case Class::DruidGM:
case Class::ShamanGM:
case Class::BeastlordGM:
return 'W';
break;
case SHADOWKNIGHT:
case BARD:
case NECROMANCER:
case WIZARD:
case MAGICIAN:
case ENCHANTER:
case SHADOWKNIGHTGM:
case BARDGM:
case NECROMANCERGM:
case WIZARDGM:
case MAGICIANGM:
case ENCHANTERGM:
case Class::ShadowKnight:
case Class::Bard:
case Class::Necromancer:
case Class::Wizard:
case Class::Magician:
case Class::Enchanter:
case Class::ShadowKnightGM:
case Class::BardGM:
case Class::NecromancerGM:
case Class::WizardGM:
case Class::MagicianGM:
case Class::EnchanterGM:
return 'I';
break;
@@ -1022,42 +1022,42 @@ char Mob::GetCasterClass() const {
uint8 Mob::GetArchetype() const {
switch(class_)
{
case PALADIN:
case RANGER:
case SHADOWKNIGHT:
case BARD:
case BEASTLORD:
case PALADINGM:
case RANGERGM:
case SHADOWKNIGHTGM:
case BARDGM:
case BEASTLORDGM:
case Class::Paladin:
case Class::Ranger:
case Class::ShadowKnight:
case Class::Bard:
case Class::Beastlord:
case Class::PaladinGM:
case Class::RangerGM:
case Class::ShadowKnightGM:
case Class::BardGM:
case Class::BeastlordGM:
return ARCHETYPE_HYBRID;
break;
case CLERIC:
case DRUID:
case SHAMAN:
case NECROMANCER:
case WIZARD:
case MAGICIAN:
case ENCHANTER:
case CLERICGM:
case DRUIDGM:
case SHAMANGM:
case NECROMANCERGM:
case WIZARDGM:
case MAGICIANGM:
case ENCHANTERGM:
case Class::Cleric:
case Class::Druid:
case Class::Shaman:
case Class::Necromancer:
case Class::Wizard:
case Class::Magician:
case Class::Enchanter:
case Class::ClericGM:
case Class::DruidGM:
case Class::ShamanGM:
case Class::NecromancerGM:
case Class::WizardGM:
case Class::MagicianGM:
case Class::EnchanterGM:
return ARCHETYPE_CASTER;
break;
case WARRIOR:
case MONK:
case ROGUE:
case BERSERKER:
case WARRIORGM:
case MONKGM:
case ROGUEGM:
case BERSERKERGM:
case Class::Warrior:
case Class::Monk:
case Class::Rogue:
case Class::Berserker:
case Class::WarriorGM:
case Class::MonkGM:
case Class::RogueGM:
case Class::BerserkerGM:
return ARCHETYPE_MELEE;
break;
default:
@@ -1069,73 +1069,73 @@ uint8 Mob::GetArchetype() const {
void Mob::SetSpawnLastNameByClass(NewSpawn_Struct* ns)
{
switch (ns->spawn.class_) {
case TRIBUTE_MASTER:
case Class::TributeMaster:
strcpy(ns->spawn.lastName, "Tribute Master");
break;
case GUILD_TRIBUTE_MASTER:
case Class::GuildTributeMaster:
strcpy(ns->spawn.lastName, "Guild Tribute Master");
break;
case GUILD_BANKER:
case Class::GuildBanker:
strcpy(ns->spawn.lastName, "Guild Banker");
break;
case ADVENTURE_RECRUITER:
case Class::AdventureRecruiter:
strcpy(ns->spawn.lastName, "Adventure Recruiter");
break;
case ADVENTURE_MERCHANT:
case Class::AdventureMerchant:
strcpy(ns->spawn.lastName, "Adventure Merchant");
break;
case BANKER:
case Class::Banker:
strcpy(ns->spawn.lastName, "Banker");
break;
case WARRIORGM:
case Class::WarriorGM:
strcpy(ns->spawn.lastName, "Warrior Guildmaster");
break;
case CLERICGM:
case Class::ClericGM:
strcpy(ns->spawn.lastName, "Cleric Guildmaster");
break;
case PALADINGM:
case Class::PaladinGM:
strcpy(ns->spawn.lastName, "Paladin Guildmaster");
break;
case RANGERGM:
case Class::RangerGM:
strcpy(ns->spawn.lastName, "Ranger Guildmaster");
break;
case SHADOWKNIGHTGM:
case Class::ShadowKnightGM:
strcpy(ns->spawn.lastName, "Shadow Knight Guildmaster");
break;
case DRUIDGM:
case Class::DruidGM:
strcpy(ns->spawn.lastName, "Druid Guildmaster");
break;
case MONKGM:
case Class::MonkGM:
strcpy(ns->spawn.lastName, "Monk Guildmaster");
break;
case BARDGM:
case Class::BardGM:
strcpy(ns->spawn.lastName, "Bard Guildmaster");
break;
case ROGUEGM:
case Class::RogueGM:
strcpy(ns->spawn.lastName, "Rogue Guildmaster");
break;
case SHAMANGM:
case Class::ShamanGM:
strcpy(ns->spawn.lastName, "Shaman Guildmaster");
break;
case NECROMANCERGM:
case Class::NecromancerGM:
strcpy(ns->spawn.lastName, "Necromancer Guildmaster");
break;
case WIZARDGM:
case Class::WizardGM:
strcpy(ns->spawn.lastName, "Wizard Guildmaster");
break;
case MAGICIANGM:
case Class::MagicianGM:
strcpy(ns->spawn.lastName, "Magician Guildmaster");
break;
case ENCHANTERGM:
case Class::EnchanterGM:
strcpy(ns->spawn.lastName, "Enchanter Guildmaster");
break;
case BEASTLORDGM:
case Class::BeastlordGM:
strcpy(ns->spawn.lastName, "Beastlord Guildmaster");
break;
case BERSERKERGM:
case Class::BerserkerGM:
strcpy(ns->spawn.lastName, "Berserker Guildmaster");
break;
case MERCENARY_MASTER:
case Class::MercenaryLiaison:
strcpy(ns->spawn.lastName, "Mercenary Liaison");
break;
default:
@@ -1346,8 +1346,8 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
}
if (RuleB(Character, AllowCrossClassTrainers) && ForWho) {
if (ns->spawn.class_ >= WARRIORGM && ns->spawn.class_ <= BERSERKERGM) {
int trainer_class = WARRIORGM + (ForWho->GetClass() - 1);
if (ns->spawn.class_ >= Class::WarriorGM && ns->spawn.class_ <= Class::BerserkerGM) {
int trainer_class = Class::WarriorGM + (ForWho->GetClass() - 1);
ns->spawn.class_ = trainer_class;
}
}
@@ -2118,7 +2118,7 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
std::string bard_info;
if (GetClass() == BARD) {
if (GetClass() == Class::Bard) {
const auto brass_mod = IsBot() ? CastToBot()->GetBrassMod() : CastToClient()->GetBrassMod();
const auto perc_mod = IsBot() ? CastToBot()->GetPercMod() : CastToClient()->GetPercMod();
const auto sing_mod = IsBot() ? CastToBot()->GetSingMod() : CastToClient()->GetSingMod();
@@ -2419,7 +2419,7 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
}
// Bard Modifiers
if (GetClass() == BARD) {
if (GetClass() == Class::Bard) {
final_string += bard_info + DialogueWindow::Break(1);
}
@@ -2688,7 +2688,7 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
);
}
if (GetClass() == BARD) {
if (GetClass() == Class::Bard) {
const auto brass_mod = IsBot() ? CastToBot()->GetBrassMod() : CastToClient()->GetBrassMod();
const auto perc_mod = IsBot() ? CastToBot()->GetPercMod() : CastToClient()->GetPercMod();
const auto sing_mod = IsBot() ? CastToBot()->GetSingMod() : CastToClient()->GetSingMod();
@@ -3511,14 +3511,14 @@ void Mob::GMMove(float x, float y, float z, float heading, bool save_guard_spot)
}
}
void Mob::GMMove(const glm::vec4 &position) {
void Mob::GMMove(const glm::vec4 &position, bool save_guard_spot) {
m_Position.x = position.x;
m_Position.y = position.y;
m_Position.z = position.z;
SetHeading(position.w);
mMovementManager->SendCommandToClients(this, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeAny);
if (IsNPC()) {
if (IsNPC() && save_guard_spot) {
CastToNPC()->SaveGuardSpot(position);
}
}
@@ -4531,7 +4531,7 @@ bool Mob::CanThisClassDualWield(void) const {
// Dual-Wielding Empty Fists
if(!pinst && !sinst)
if(class_ != MONK && class_ != MONKGM && class_ != BEASTLORD && class_ != BEASTLORDGM)
if(class_ != Class::Monk && class_ != Class::MonkGM && class_ != Class::Beastlord && class_ != Class::BeastlordGM)
return false;
return true;
@@ -4564,24 +4564,24 @@ bool Mob::IsWarriorClass(void) const
{
switch(GetClass())
{
case WARRIOR:
case WARRIORGM:
case ROGUE:
case ROGUEGM:
case MONK:
case MONKGM:
case PALADIN:
case PALADINGM:
case SHADOWKNIGHT:
case SHADOWKNIGHTGM:
case RANGER:
case RANGERGM:
case BEASTLORD:
case BEASTLORDGM:
case BERSERKER:
case BERSERKERGM:
case BARD:
case BARDGM:
case Class::Warrior:
case Class::WarriorGM:
case Class::Rogue:
case Class::RogueGM:
case Class::Monk:
case Class::MonkGM:
case Class::Paladin:
case Class::PaladinGM:
case Class::ShadowKnight:
case Class::ShadowKnightGM:
case Class::Ranger:
case Class::RangerGM:
case Class::Beastlord:
case Class::BeastlordGM:
case Class::Berserker:
case Class::BerserkerGM:
case Class::Bard:
case Class::BardGM:
{
return true;
}
@@ -5185,7 +5185,7 @@ int32 Mob::GetActSpellCasttime(uint16 spell_id, int32 casttime)
int32 cast_reducer_no_limit = GetFocusEffect(focusFcCastTimeMod2, spell_id);
if (level > 50 && casttime >= 3000 && !spells[spell_id].good_effect &&
(GetClass() == RANGER || GetClass() == SHADOWKNIGHT || GetClass() == PALADIN || GetClass() == BEASTLORD)) {
(GetClass() == Class::Ranger || GetClass() == Class::ShadowKnight || GetClass() == Class::Paladin || GetClass() == Class::Beastlord)) {
int level_mod = std::min(15, GetLevel() - 50);
cast_reducer += level_mod * 3;
}
@@ -7520,29 +7520,23 @@ int32 Mob::GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot)
bool Mob::CanClassEquipItem(uint32 item_id)
{
const EQ::ItemData* itm = nullptr;
itm = database.GetItem(item_id);
if (!itm) {
const auto *item = database.GetItem(item_id);
if (!item) {
return false;
}
auto item_classes = itm->Classes;
if(item_classes == PLAYER_CLASS_ALL_MASK) {
const uint16 item_classes = item->Classes;
if (item_classes == Class::ALL_CLASSES_BITMASK) {
return true;
}
auto class_id = GetClass();
if (class_id > BERSERKER) {
const uint8 class_id = GetClass();
if (!IsPlayerClass(class_id)) {
return false;
}
int class_bitmask = GetPlayerClassBit(class_id);
if(!(item_classes & class_bitmask)) {
return false;
} else {
return true;
}
const uint16 class_bitmask = GetPlayerClassBit(class_id);
return (item_classes & class_bitmask);
}
bool Mob::CanRaceEquipItem(uint32 item_id)
@@ -8264,37 +8258,37 @@ std::string Mob::GetRacePlural()
std::string Mob::GetClassPlural()
{
switch (GetClass()) {
case WARRIOR:
case Class::Warrior:
return "Warriors";
case CLERIC:
case Class::Cleric:
return "Clerics";
case PALADIN:
case Class::Paladin:
return "Paladins";
case RANGER:
case Class::Ranger:
return "Rangers";
case SHADOWKNIGHT:
return "Shadowknights";
case DRUID:
case Class::ShadowKnight:
return fmt::format("{}s", shadow_knight_class_name);
case Class::Druid:
return "Druids";
case MONK:
case Class::Monk:
return "Monks";
case BARD:
case Class::Bard:
return "Bards";
case ROGUE:
case Class::Rogue:
return "Rogues";
case SHAMAN:
case Class::Shaman:
return "Shamans";
case NECROMANCER:
case Class::Necromancer:
return "Necromancers";
case WIZARD:
case Class::Wizard:
return "Wizards";
case MAGICIAN:
case Class::Magician:
return "Magicians";
case ENCHANTER:
case Class::Enchanter:
return "Enchanters";
case BEASTLORD:
case Class::Beastlord:
return "Beastlords";
case BERSERKER:
case Class::Berserker:
return "Berserkers";
default:
return "Classes";
+1 -1
View File
@@ -714,7 +714,7 @@ public:
bool IsRunning() const { return m_is_running; }
void SetRunning(bool val) { m_is_running = val; }
virtual void GMMove(float x, float y, float z, float heading = 0.01, bool save_guard_spot = true);
virtual void GMMove(const glm::vec4 &position);
virtual void GMMove(const glm::vec4 &position, bool save_guard_spot = true);
void SetDelta(const glm::vec4& delta);
void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu);
void MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu);
+5 -5
View File
@@ -448,7 +448,7 @@ void Mob::AI_Start(uint32 iMoveDelay) {
hate_list_cleanup_timer.Disable();
}
if (CastToNPC()->WillAggroNPCs())
if (CastToNPC()->GetNPCAggro())
AI_scan_area_timer = std::make_unique<Timer>(RandomTimer(RuleI(NPC, NPCToNPCAggroTimerMin), RuleI(NPC, NPCToNPCAggroTimerMax)));
AI_check_signal_timer = std::make_unique<Timer>(AI_check_signal_timer_delay);
@@ -1066,7 +1066,7 @@ void Mob::AI_Process() {
IsNPC() &&
!CastToNPC()->GetSwarmInfo() &&
(!IsPet() || (HasOwner() && GetOwner()->IsNPC())) &&
!CastToNPC()->WillAggroNPCs()
!CastToNPC()->GetNPCAggro()
) {
WipeHateList(true); // wipe NPCs from hate list to prevent faction war
}
@@ -1330,7 +1330,7 @@ void Mob::AI_Process() {
// Now pursue
// TODO: Check here for another person on hate list with close hate value
if (AI_PursueCastCheck()) {
if (IsCasting() && GetClass() != BARD) {
if (IsCasting() && GetClass() != Class::Bard) {
StopNavigation();
FaceTarget();
}
@@ -1382,11 +1382,11 @@ void Mob::AI_Process() {
}
}
if (AI_IdleCastCheck()) {
if (IsCasting() && GetClass() != BARD) {
if (IsCasting() && GetClass() != Class::Bard) {
StopNavigation();
}
}
else if (zone->CanDoCombat() && CastToNPC()->WillAggroNPCs() && AI_scan_area_timer->Check()) {
else if (zone->CanDoCombat() && CastToNPC()->GetNPCAggro() && AI_scan_area_timer->Check()) {
/**
* NPC to NPC aggro (npc_aggro flag set)
+9 -9
View File
@@ -245,12 +245,12 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi
MerchantType = npc_type_data->merchanttype;
merchant_open = (
GetClass() == MERCHANT ||
GetClass() == DISCORD_MERCHANT ||
GetClass() == ADVENTURE_MERCHANT ||
GetClass() == NORRATHS_KEEPERS_MERCHANT ||
GetClass() == DARK_REIGN_MERCHANT ||
GetClass() == ALT_CURRENCY_MERCHANT
GetClass() == Class::Merchant ||
GetClass() == Class::DiscordMerchant ||
GetClass() == Class::AdventureMerchant ||
GetClass() == Class::NorrathsKeepersMerchant ||
GetClass() == Class::DarkReignMerchant ||
GetClass() == Class::AlternateCurrencyMerchant
);
adventure_template_id = npc_type_data->adventure_template;
flymode = iflymode;
@@ -294,7 +294,7 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi
innate_proc_spell_id = 0;
m_record_loot_stats = false;
if (GetClass() == MERCENARY_MASTER && RuleB(Mercs, AllowMercs)) {
if (GetClass() == Class::MercenaryLiaison && RuleB(Mercs, AllowMercs)) {
LoadMercTypes();
LoadMercs();
}
@@ -364,10 +364,10 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi
// There are some known low level SHM/BST pets that do not follow this, which supports
// the theory of needing to be able to set skills for each mob separately
if (IsBot()) {
if (GetClass() != PALADIN && GetClass() != SHADOWKNIGHT) {
if (GetClass() != Class::Paladin && GetClass() != Class::ShadowKnight) {
knightattack_timer.Disable();
}
else if (GetClass() != MONK || GetLevel() < 10) {
else if (GetClass() != Class::Monk || GetLevel() < 10) {
monkattack_timer.Disable();
}
}
+21 -10
View File
@@ -192,10 +192,20 @@ public:
virtual void SpellProcess();
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
void AddItem(const EQ::ItemData* item, uint16 charges, bool equipitem = true);
void AddItem(uint32 itemid, uint16 charges, bool equipitem = true, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0);
void AddItem(const EQ::ItemData *item, uint16 charges, bool equip_item = true);
void AddItem(
uint32 item_id,
uint16 charges,
bool equip_item = true,
uint32 augment_one = 0,
uint32 augment_two = 0,
uint32 augment_three = 0,
uint32 augment_four = 0,
uint32 augment_five = 0,
uint32 augment_six = 0
);
void AddLootTable();
void AddLootTable(uint32 ldid);
void AddLootTable(uint32 loottable_id);
void CheckGlobalLootTables();
void DescribeAggro(Client *to_who, Mob *mob, bool verbose);
void RemoveItem(uint32 item_id, uint16 quantity = 0, uint16 slot = 0);
@@ -314,12 +324,12 @@ public:
ItemList *itemlist,
LootDropEntries_Struct loot_drop,
bool wear_change = false,
uint32 aug1 = 0,
uint32 aug2 = 0,
uint32 aug3 = 0,
uint32 aug4 = 0,
uint32 aug5 = 0,
uint32 aug6 = 0
uint32 augment_one = 0,
uint32 augment_two = 0,
uint32 augment_three = 0,
uint32 augment_four = 0,
uint32 augment_five = 0,
uint32 augment_six = 0
);
bool MeetsLootDropLevelRequirements(LootDropEntries_Struct loot_drop, bool verbose=false);
@@ -384,7 +394,8 @@ public:
int GetNumMercs() { return static_cast<int>(mercDataList.size()); };
int GetNumMercs( uint32 expansion );
inline bool WillAggroNPCs() const { return(npc_aggro); }
inline bool GetNPCAggro() const { return npc_aggro; }
inline void SetNPCAggro(bool in_npc_aggro) { npc_aggro = in_npc_aggro; }
inline void GiveNPCTypeData(NPCType *ours) { NPCTypedata_ours = ours; }
inline const uint32 GetNPCSpellsID() const { return npc_spells_id; }
+16 -16
View File
@@ -417,7 +417,7 @@ uint32 NpcScaleManager::GetClassLevelDamageMod(uint32 level, uint32 npc_class)
uint32 multiplier;
switch (npc_class) {
case WARRIOR: {
case Class::Warrior: {
if (level < 20) {
multiplier = 220;
}
@@ -444,9 +444,9 @@ uint32 NpcScaleManager::GetClassLevelDamageMod(uint32 level, uint32 npc_class)
}
break;
}
case DRUID:
case CLERIC:
case SHAMAN: {
case Class::Druid:
case Class::Cleric:
case Class::Shaman: {
if (level < 70) {
multiplier = 150;
}
@@ -455,9 +455,9 @@ uint32 NpcScaleManager::GetClassLevelDamageMod(uint32 level, uint32 npc_class)
}
break;
}
case BERSERKER:
case PALADIN:
case SHADOWKNIGHT: {
case Class::Berserker:
case Class::Paladin:
case Class::ShadowKnight: {
if (level < 35) {
multiplier = 210;
}
@@ -481,10 +481,10 @@ uint32 NpcScaleManager::GetClassLevelDamageMod(uint32 level, uint32 npc_class)
}
break;
}
case MONK:
case BARD:
case ROGUE:
case BEASTLORD: {
case Class::Monk:
case Class::Bard:
case Class::Rogue:
case Class::Beastlord: {
if (level < 51) {
multiplier = 180;
}
@@ -499,7 +499,7 @@ uint32 NpcScaleManager::GetClassLevelDamageMod(uint32 level, uint32 npc_class)
}
break;
}
case RANGER: {
case Class::Ranger: {
if (level < 58) {
multiplier = 200;
}
@@ -511,10 +511,10 @@ uint32 NpcScaleManager::GetClassLevelDamageMod(uint32 level, uint32 npc_class)
}
break;
}
case MAGICIAN:
case WIZARD:
case NECROMANCER:
case ENCHANTER: {
case Class::Magician:
case Class::Wizard:
case Class::Necromancer:
case Class::Enchanter: {
if (level < 70) {
multiplier = 120;
}
+110 -1
View File
@@ -255,11 +255,101 @@ void Perl_Bot_Stand(Bot* self) // @categories Script Utility
self->Stand();
}
uint32 Perl_Bot_GetSpellRecastTimer(Bot* self)
{
return self->GetSpellRecastRemainingTime();
}
uint32 Perl_Bot_GetSpellRecastTimer(Bot* self, uint16 spell_id)
{
return self->GetSpellRecastRemainingTime(spell_id);
}
void Perl_Bot_ClearSpellRecastTimer(Bot* self)
{
return self->ClearSpellRecastTimer();
}
void Perl_Bot_ClearSpellRecastTimer(Bot* self, uint16 spell_id)
{
return self->ClearSpellRecastTimer(spell_id);
}
uint32 Perl_Bot_GetDisciplineReuseTimer(Bot* self)
{
return self->GetDisciplineReuseRemainingTime();
}
uint32 Perl_Bot_GetDisciplineReuseTimer(Bot* self, uint16 spell_id)
{
return self->GetDisciplineReuseRemainingTime(spell_id);
}
void Perl_Bot_ClearDisciplineReuseTimer(Bot* self)
{
return self->ClearDisciplineReuseTimer();
}
void Perl_Bot_ClearDisciplineReuseTimer(Bot* self, uint16 spell_id)
{
return self->ClearDisciplineReuseTimer(spell_id);
}
void Perl_Bot_SetDisciplineReuseTimer(Bot* self, uint16 spell_id)
{
return self->SetDisciplineReuseTimer(spell_id);
}
void Perl_Bot_SetDisciplineReuseTimer(Bot* self, uint16 spell_id, uint32 recast_delay)
{
return self->SetDisciplineReuseTimer(spell_id);
}
void Perl_Bot_SetItemReuseTimer(Bot* self, uint32 item_id)
{
return self->SetItemReuseTimer(item_id);
}
void Perl_Bot_SetItemReuseTimer(Bot* self, uint32 item_id, uint32 reuse_timer)
{
return self->SetItemReuseTimer(item_id, reuse_timer);
}
void Perl_Bot_SetSpellRecastTimer(Bot* self, uint16 spell_id)
{
return self->SetSpellRecastTimer(spell_id);
}
void Perl_Bot_SetSpellRecastTimer(Bot* self, uint16 spell_id, uint32 recast_delay)
{
return self->SetSpellRecastTimer(spell_id, recast_delay);
}
int Perl_Bot_GetItemIDAt(Bot* self, int16 slot_id) // @categories Inventory and Items
{
return self->GetItemIDAt(slot_id);
}
uint32 Perl_Bot_GetItemReuseTimer(Bot* self)
{
return self->GetItemReuseRemainingTime();
}
uint32 Perl_Bot_GetItemReuseTimer(Bot* self, uint32 item_id)
{
return self->GetItemReuseRemainingTime(item_id);
}
void Perl_Bot_ClearItemReuseTimer(Bot* self)
{
return self->ClearItemReuseTimer();
}
void Perl_Bot_ClearItemReuseTimer(Bot* self, uint32 item_id)
{
return self->ClearItemReuseTimer(item_id);
}
int Perl_Bot_GetAugmentIDAt(Bot* self, int16 slot_id, uint8 aug_slot) // @categories Inventory and Items
{
return self->GetAugmentIDAt(slot_id, aug_slot);
@@ -555,7 +645,13 @@ void perl_register_bot()
package.add("ApplySpellRaid", (void(*)(Bot*, int, int, int, bool))&Perl_Bot_ApplySpellRaid);
package.add("ApplySpellRaid", (void(*)(Bot*, int, int, int, bool, bool))&Perl_Bot_ApplySpellRaid);
package.add("Camp", (void(*)(Bot*))&Perl_Bot_Camp);
package.add("Camp", (void(*)(Bot*, bool))&Perl_Bot_Camp);
package.add("Camp", (void(*)(Bot*, bool))&Perl_Bot_Camp);
package.add("ClearDisciplineReuseTimer", (void(*)(Bot*))&Perl_Bot_ClearDisciplineReuseTimer);
package.add("ClearDisciplineReuseTimer", (void(*)(Bot*, uint16))&Perl_Bot_ClearDisciplineReuseTimer);
package.add("ClearItemReuseTimer", (void(*)(Bot*))&Perl_Bot_ClearItemReuseTimer);
package.add("ClearItemReuseTimer", (void(*)(Bot*, uint32))&Perl_Bot_ClearItemReuseTimer);
package.add("ClearSpellRecastTimer", (void(*)(Bot*))&Perl_Bot_ClearSpellRecastTimer);
package.add("ClearSpellRecastTimer", (void(*)(Bot*, uint16))&Perl_Bot_ClearSpellRecastTimer);
package.add("CountAugmentEquippedByID", &Perl_Bot_CountAugmentEquippedByID);
package.add("CountBotItem", &Perl_Bot_CountBotItem);
package.add("CountItemEquippedByID", &Perl_Bot_CountItemEquippedByID);
@@ -594,6 +690,13 @@ void perl_register_bot()
package.add("HasBotItem", &Perl_Bot_HasBotItem);
package.add("HasBotSpellEntry", &Perl_Bot_HasBotSpellEntry);
package.add("HasItemEquippedByID", &Perl_Bot_HasItemEquippedByID);
package.add("GetDisciplineReuseTimer", (uint32(*)(Bot*))&Perl_Bot_GetDisciplineReuseTimer);
package.add("GetDisciplineReuseTimer", (uint32(*)(Bot*, uint16))&Perl_Bot_GetDisciplineReuseTimer);
package.add("GetItemEquippedByID", &Perl_Bot_HasItemEquippedByID);
package.add("GetItemReuseTimer", (uint32(*)(Bot*))&Perl_Bot_GetItemReuseTimer);
package.add("GetItemReuseTimer", (uint32(*)(Bot*, uint32))&Perl_Bot_GetItemReuseTimer);
package.add("GetSpellRecastTimer", (uint32(*)(Bot*))&Perl_Bot_GetSpellRecastTimer);
package.add("GetSpellRecastTimer", (uint32(*)(Bot*, uint16))&Perl_Bot_GetSpellRecastTimer);
package.add("IsGrouped", &Perl_Bot_IsGrouped);
package.add("IsSitting", &Perl_Bot_IsSitting);
package.add("IsStanding", &Perl_Bot_IsStanding);
@@ -608,6 +711,10 @@ void perl_register_bot()
package.add("SendSpellAnim", &Perl_Bot_SendSpellAnim);
package.add("SetExpansionBitmask", (void(*)(Bot*, int))&Perl_Bot_SetExpansionBitmask);
package.add("SetExpansionBitmask", (void(*)(Bot*, int, bool))&Perl_Bot_SetExpansionBitmask);
package.add("SetDisciplineReuseTimer", (void(*)(Bot*, uint16))&Perl_Bot_SetDisciplineReuseTimer);
package.add("SetDisciplineReuseTimer", (void(*)(Bot*, uint16, uint32))&Perl_Bot_SetDisciplineReuseTimer);
package.add("SetItemReuseTimer", (void(*)(Bot*, uint32))&Perl_Bot_SetItemReuseTimer);
package.add("SetItemReuseTimer", (void(*)(Bot*, uint32, uint32))&Perl_Bot_SetItemReuseTimer);
package.add("SetSpellDuration", (void(*)(Bot*, int))&Perl_Bot_SetSpellDuration);
package.add("SetSpellDuration", (void(*)(Bot*, int, int))&Perl_Bot_SetSpellDuration);
package.add("SetSpellDuration", (void(*)(Bot*, int, int, int))&Perl_Bot_SetSpellDuration);
@@ -621,6 +728,8 @@ void perl_register_bot()
package.add("SetSpellDurationRaid", (void(*)(Bot*, int, int, int))&Perl_Bot_SetSpellDurationRaid);
package.add("SetSpellDurationRaid", (void(*)(Bot*, int, int, int, bool))&Perl_Bot_SetSpellDurationRaid);
package.add("SetSpellDurationRaid", (void(*)(Bot*, int, int, int, bool, bool))&Perl_Bot_SetSpellDurationRaid);
package.add("SetSpellRecastTimer", (void(*)(Bot*, uint16))&Perl_Bot_SetSpellRecastTimer);
package.add("SetSpellRecastTimer", (void(*)(Bot*, uint16, uint32))&Perl_Bot_SetSpellRecastTimer);
package.add("Signal", &Perl_Bot_Signal);
package.add("Sit", &Perl_Bot_Sit);
package.add("Stand", &Perl_Bot_Stand);
+44 -4
View File
@@ -1159,7 +1159,23 @@ void Perl_Client_AddPVPPoints(Client* self, uint32 points) // @categories Curren
void Perl_Client_AddCrystals(Client* self, uint32 radiant_count, uint32 ebon_count) // @categories Currency and Points
{
self->AddCrystals(radiant_count, ebon_count);
if (ebon_count != 0) {
if (ebon_count > 0) {
self->AddEbonCrystals(ebon_count);
return;
}
self->RemoveEbonCrystals(ebon_count);
}
if (radiant_count != 0) {
if (radiant_count > 0) {
self->AddRadiantCrystals(radiant_count);
return;
}
self->RemoveRadiantCrystals(radiant_count);
}
}
void Perl_Client_SetEbonCrystals(Client* self, uint32 value)
@@ -1472,12 +1488,12 @@ void Perl_Client_NotifyNewTitlesAvailable(Client* self) // @categories Account a
self->NotifyNewTitlesAvailable();
}
void Perl_Client_AddAlternateCurrencyValue(Client* self, uint32 currency_id, int32 amount) // @categories Currency and Points
void Perl_Client_AddAlternateCurrencyValue(Client* self, uint32 currency_id, int amount) // @categories Currency and Points
{
self->AddAlternateCurrencyValue(currency_id, amount);
self->AddAlternateCurrencyValue(currency_id, amount, true);
}
void Perl_Client_SetAlternateCurrencyValue(Client* self, uint32 currency_id, int32 amount) // @categories Currency and Points
void Perl_Client_SetAlternateCurrencyValue(Client* self, uint32 currency_id, uint32 amount) // @categories Currency and Points
{
self->SetAlternateCurrencyValue(currency_id, amount);
}
@@ -2992,6 +3008,26 @@ void Perl_Client_GrantAllAAPoints(Client* self, uint8 unlock_level)
self->GrantAllAAPoints(unlock_level);
}
void Perl_Client_AddEbonCrystals(Client* self, uint32 amount)
{
self->AddEbonCrystals(amount);
}
void Perl_Client_AddRadiantCrystals(Client* self, uint32 amount)
{
self->AddRadiantCrystals(amount);
}
void Perl_Client_RemoveEbonCrystals(Client* self, uint32 amount)
{
self->RemoveEbonCrystals(amount);
}
void Perl_Client_RemoveRadiantCrystals(Client* self, uint32 amount)
{
self->RemoveRadiantCrystals(amount);
}
void perl_register_client()
{
perl::interpreter perl(PERL_GET_THX);
@@ -3006,6 +3042,7 @@ void perl_register_client()
package.add("AddEXP", (void(*)(Client*, uint32))&Perl_Client_AddEXP);
package.add("AddEXP", (void(*)(Client*, uint32, uint8))&Perl_Client_AddEXP);
package.add("AddEXP", (void(*)(Client*, uint32, uint8, bool))&Perl_Client_AddEXP);
package.add("AddEbonCrystals", &Perl_Client_AddEbonCrystals);
package.add("AddExpeditionLockout", (void(*)(Client*, std::string, std::string, uint32))&Perl_Client_AddExpeditionLockout);
package.add("AddExpeditionLockout", (void(*)(Client*, std::string, std::string, uint32, std::string))&Perl_Client_AddExpeditionLockout);
package.add("AddExpeditionLockoutDuration", (void(*)(Client*, std::string, std::string, int))&Perl_Client_AddExpeditionLockoutDuration);
@@ -3021,6 +3058,7 @@ void perl_register_client()
package.add("AddPlatinum", (void(*)(Client*, uint32))&Perl_Client_AddPlatinum);
package.add("AddPlatinum", (void(*)(Client*, uint32, bool))&Perl_Client_AddPlatinum);
package.add("AddPVPPoints", &Perl_Client_AddPVPPoints);
package.add("AddRadiantCrystals", &Perl_Client_AddRadiantCrystals);
package.add("AddSkill", &Perl_Client_AddSkill);
package.add("Admin", &Perl_Client_Admin);
package.add("ApplySpell", (void(*)(Client*, int))&Perl_Client_ApplySpell);
@@ -3352,6 +3390,7 @@ void perl_register_client()
package.add("ReloadDataBuckets", &Perl_Client_ReloadDataBuckets);
package.add("RemoveAllExpeditionLockouts", (void(*)(Client*))&Perl_Client_RemoveAllExpeditionLockouts);
package.add("RemoveAllExpeditionLockouts", (void(*)(Client*, std::string))&Perl_Client_RemoveAllExpeditionLockouts);
package.add("RemoveEbonCrystals", &Perl_Client_RemoveEbonCrystals);
package.add("RemoveExpeditionLockout", &Perl_Client_RemoveExpeditionLockout);
package.add("RemoveFromInstance", &Perl_Client_RemoveFromInstance);
package.add("RemoveItem", (void(*)(Client*, uint32))&Perl_Client_RemoveItem);
@@ -3359,6 +3398,7 @@ void perl_register_client()
package.add("RemoveLDoNLoss", &Perl_Client_RemoveLDoNLoss);
package.add("RemoveLDoNWin", &Perl_Client_RemoveLDoNWin);
package.add("RemoveNoRent", &Perl_Client_RemoveNoRent);
package.add("RemoveRadiantCrystals", &Perl_Client_RemoveRadiantCrystals);
package.add("ResetAA", &Perl_Client_ResetAA);
package.add("ResetAllDisciplineTimers", &Perl_Client_ResetAllDisciplineTimers);
package.add("ResetAllCastbarCooldowns", &Perl_Client_ResetAllCastbarCooldowns);
+13
View File
@@ -775,6 +775,17 @@ bool Perl_NPC_HasSpecialAbilities(NPC* self) // @categories Script Utility
return self->HasSpecialAbilities();
}
bool Perl_NPC_GetNPCAggro(NPC* self) // @categories Script Utility
{
return self->GetNPCAggro();
}
void Perl_NPC_SetNPCAggro(NPC* self, bool in_npc_aggro) // @categories Script Utility
{
self->SetNPCAggro(in_npc_aggro);
}
void perl_register_npc()
{
perl::interpreter perl(PERL_GET_THX);
@@ -836,6 +847,7 @@ void perl_register_npc()
package.add("GetMaxDamage", &Perl_NPC_GetMaxDamage);
package.add("GetMaxWp", &Perl_NPC_GetMaxWp);
package.add("GetMinDMG", &Perl_NPC_GetMinDMG);
package.add("GetNPCAggro", &Perl_NPC_GetNPCAggro);
package.add("GetNPCFactionID", &Perl_NPC_GetNPCFactionID);
package.add("GetNPCHate", &Perl_NPC_GetNPCHate);
package.add("GetNPCSpellsID", &Perl_NPC_GetNPCSpellsID);
@@ -911,6 +923,7 @@ void perl_register_npc()
package.add("SetLDoNTrapDetected", &Perl_NPC_SetLDoNTrapDetected);
package.add("SetLDoNTrapSpellID", &Perl_NPC_SetLDoNTrapSpellID);
package.add("SetLDoNTrapType", &Perl_NPC_SetLDoNTrapType);
package.add("SetNPCAggro", &Perl_NPC_SetNPCAggro);
package.add("SetGold", &Perl_NPC_SetGold);
package.add("SetGrid", &Perl_NPC_SetGrid);
package.add("SetNPCFactionID", &Perl_NPC_SetNPCFactionID);
+1 -1
View File
@@ -70,7 +70,7 @@ void Petition::SendPetitionToPlayer(Client* clientto) {
Petition::Petition(uint32 id)
{
petid = id;
charclass = NO_CLASS;
charclass = Class::None;
charrace = RACE_DOUG_0;
charlevel = 0;
checkouts = 0;
+11 -11
View File
@@ -1029,10 +1029,10 @@ bool QuestManager::isdisctome(uint32 item_id) {
//we know for sure none of the int casters get disciplines
uint32 class_bit = 0;
class_bit |= 1 << (WIZARD - 1);
class_bit |= 1 << (ENCHANTER - 1);
class_bit |= 1 << (MAGICIAN - 1);
class_bit |= 1 << (NECROMANCER - 1);
class_bit |= 1 << (Class::Wizard - 1);
class_bit |= 1 << (Class::Enchanter - 1);
class_bit |= 1 << (Class::Magician - 1);
class_bit |= 1 << (Class::Necromancer - 1);
if (item->Classes & class_bit) {
return false;
}
@@ -1045,10 +1045,10 @@ bool QuestManager::isdisctome(uint32 item_id) {
//we know for sure none of the int casters get disciplines
const auto& spell = spells[spell_id];
if(
spell.classes[WIZARD - 1] != 255 &&
spell.classes[ENCHANTER - 1] != 255 &&
spell.classes[MAGICIAN - 1] != 255 &&
spell.classes[NECROMANCER - 1] != 255
spell.classes[Class::Wizard - 1] != 255 &&
spell.classes[Class::Enchanter - 1] != 255 &&
spell.classes[Class::Magician - 1] != 255 &&
spell.classes[Class::Necromancer - 1] != 255
) {
return false;
}
@@ -1526,7 +1526,7 @@ void QuestManager::CreateGuild(const char *guild_name, const char *leader) {
void QuestManager::settime(uint8 new_hour, uint8 new_min, bool update_world /*= true*/)
{
if (zone)
zone->SetTime(new_hour + 1, new_min, update_world);
zone->SetTime(new_hour, new_min, update_world);
}
void QuestManager::itemlink(int item_id) {
@@ -3128,7 +3128,7 @@ void QuestManager::UpdateSpawnTimer(uint32 id, uint32 newTime)
void QuestManager::MerchantSetItem(uint32 NPCid, uint32 itemid, uint32 quantity) {
Mob* merchant = entity_list.GetMobByNpcTypeID(NPCid);
if (merchant == 0 || !merchant->IsNPC() || (merchant->GetClass() != MERCHANT))
if (merchant == 0 || !merchant->IsNPC() || (merchant->GetClass() != Class::Merchant))
return; // don't do anything if NPCid isn't a merchant
const EQ::ItemData* item = nullptr;
@@ -3141,7 +3141,7 @@ void QuestManager::MerchantSetItem(uint32 NPCid, uint32 itemid, uint32 quantity)
uint32 QuestManager::MerchantCountItem(uint32 NPCid, uint32 itemid) {
Mob* merchant = entity_list.GetMobByNpcTypeID(NPCid);
if (merchant == 0 || !merchant->IsNPC() || (merchant->GetClass() != MERCHANT))
if (merchant == 0 || !merchant->IsNPC() || (merchant->GetClass() != Class::Merchant))
return 0; // if it isn't a merchant, it doesn't have any items
const EQ::ItemData* item = nullptr;
+2 -2
View File
@@ -365,8 +365,8 @@ public:
std::string GetEncounter() const;
inline bool ProximitySayInUse() { return HaveProximitySays; }
int createbotcount(uint8 class_id = NO_CLASS);
int spawnbotcount(uint8 class_id = NO_CLASS);
int createbotcount(uint8 class_id = Class::None);
int spawnbotcount(uint8 class_id = Class::None);
bool botquest();
bool createBot(const char *name, const char *lastname, uint8 level, uint16 race, uint8 botclass, uint8 gender);
+31 -31
View File
@@ -287,7 +287,7 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk)
// make sure were actually able to use such an attack. (Bards can throw while casting. ~Kayen confirmed on live 1/22)
if (
(spellend_timer.Enabled() && GetClass() != BARD) ||
(spellend_timer.Enabled() && GetClass() != Class::Bard) ||
IsFeared() ||
IsStunned() ||
IsMezzed() ||
@@ -420,7 +420,7 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk)
CheckIncreaseSkill(EQ::skills::SkillFrenzy, GetTarget(), 10);
DoAnim(anim1HWeapon, 0, false);
if (GetClass() == BERSERKER) {
if (GetClass() == Class::Berserker) {
int chance = GetLevel() * 2 + GetSkill(EQ::skills::SkillFrenzy);
if (zone->random.Roll0(450) < chance) {
@@ -461,11 +461,11 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk)
const uint32 allowed_kick_classes = RuleI(Combat, ExtraAllowedKickClassesBitmask);
const bool can_use_kick = (
class_id == WARRIOR ||
class_id == RANGER ||
class_id == MONK ||
class_id == BEASTLORD ||
class_id == BERSERKER ||
class_id == Class::Warrior ||
class_id == Class::Ranger ||
class_id == Class::Monk ||
class_id == Class::Beastlord ||
class_id == Class::Berserker ||
allowed_kick_classes & GetPlayerClassBit(class_id)
);
@@ -494,7 +494,7 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk)
}
}
if (class_id == MONK) {
if (class_id == Class::Monk) {
reuse_time = MonkSpecialAttack(GetTarget(), ca_atk->m_skill) - 1 - skill_reduction;
// Live AA - Technique of Master Wu
@@ -559,7 +559,7 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk)
if (
ca_atk->m_atk == 100 &&
ca_atk->m_skill == EQ::skills::SkillBackstab &&
class_id == ROGUE
class_id == Class::Rogue
) {
reuse_time = BackstabReuseTime - 1 - skill_reduction;
TryBackstab(GetTarget(), reuse_time);
@@ -1495,7 +1495,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51
}
if(!IsAttackAllowed(other) ||
(IsCasting() && GetClass() != BARD) ||
(IsCasting() && GetClass() != Class::Bard) ||
IsSitting() ||
(DivineAura() && !GetGM()) ||
IsStunned() ||
@@ -1779,13 +1779,13 @@ void NPC::DoClassAttacks(Mob *target) {
int knightreuse = 1000; //lets give it a small cooldown actually.
switch(GetClass()){
case SHADOWKNIGHT: case SHADOWKNIGHTGM:{
case Class::ShadowKnight: case Class::ShadowKnightGM:{
if (CastSpell(SPELL_NPC_HARM_TOUCH, target->GetID())) {
knightreuse = HarmTouchReuseTime * 1000;
}
break;
}
case PALADIN: case PALADINGM:{
case Class::Paladin: case Class::PaladinGM:{
if(GetHPRatio() < 20) {
if (CastSpell(SPELL_LAY_ON_HANDS, GetID())) {
knightreuse = LayOnHandsReuseTime * 1000;
@@ -1822,14 +1822,14 @@ void NPC::DoClassAttacks(Mob *target) {
bool did_attack = false;
//class specific stuff...
switch(GetClass()) {
case ROGUE: case ROGUEGM:
case Class::Rogue: case Class::RogueGM:
if(level >= 10) {
reuse = BackstabReuseTime * 1000;
TryBackstab(target, reuse);
did_attack = true;
}
break;
case MONK: case MONKGM: {
case Class::Monk: case Class::MonkGM: {
uint8 satype = EQ::skills::SkillKick;
if (level > 29) { satype = EQ::skills::SkillFlyingKick; }
else if (level > 24) { satype = EQ::skills::SkillDragonPunch; }
@@ -1842,7 +1842,7 @@ void NPC::DoClassAttacks(Mob *target) {
did_attack = true;
break;
}
case WARRIOR: case WARRIORGM:{
case Class::Warrior: case Class::WarriorGM:{
if(level >= RuleI(Combat, NPCBashKickLevel)){
if(zone->random.Roll(75)) { //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference.
DoAnim(animKick, 0, false);
@@ -1870,12 +1870,12 @@ void NPC::DoClassAttacks(Mob *target) {
}
break;
}
case BERSERKER: case BERSERKERGM:{
case Class::Berserker: case Class::BerserkerGM:{
int AtkRounds = 1;
int32 max_dmg = GetBaseSkillDamage(EQ::skills::SkillFrenzy);
DoAnim(anim2HSlashing, 0, false);
if (GetClass() == BERSERKER) {
if (GetClass() == Class::Berserker) {
int chance = GetLevel() * 2 + GetSkill(EQ::skills::SkillFrenzy);
if (zone->random.Roll0(450) < chance)
AtkRounds++;
@@ -1892,8 +1892,8 @@ void NPC::DoClassAttacks(Mob *target) {
did_attack = true;
break;
}
case RANGER: case RANGERGM:
case BEASTLORD: case BEASTLORDGM: {
case Class::Ranger: case Class::RangerGM:
case Class::Beastlord: case Class::BeastlordGM: {
//kick
if(level >= RuleI(Combat, NPCBashKickLevel)){
DoAnim(animKick, 0, false);
@@ -1908,9 +1908,9 @@ void NPC::DoClassAttacks(Mob *target) {
}
break;
}
case CLERIC: case CLERICGM: //clerics can bash too.
case SHADOWKNIGHT: case SHADOWKNIGHTGM:
case PALADIN: case PALADINGM:{
case Class::Cleric: case Class::ClericGM: //clerics can bash too.
case Class::ShadowKnight: case Class::ShadowKnightGM:
case Class::Paladin: case Class::PaladinGM:{
if(level >= RuleI(Combat, NPCBashKickLevel)){
DoAnim(animTailRake, 0, false);
int64 dmg = GetBaseSkillDamage(EQ::skills::SkillBash);
@@ -1957,19 +1957,19 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
if (skill == -1){
switch(GetClass()){
case WARRIOR:
case RANGER:
case BEASTLORD:
case Class::Warrior:
case Class::Ranger:
case Class::Beastlord:
skill_to_use = EQ::skills::SkillKick;
break;
case BERSERKER:
case Class::Berserker:
skill_to_use = EQ::skills::SkillFrenzy;
break;
case SHADOWKNIGHT:
case PALADIN:
case Class::ShadowKnight:
case Class::Paladin:
skill_to_use = EQ::skills::SkillBash;
break;
case MONK:
case Class::Monk:
if(GetLevel() >= 30)
{
skill_to_use = EQ::skills::SkillFlyingKick;
@@ -1995,7 +1995,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
skill_to_use = EQ::skills::SkillKick;
}
break;
case ROGUE:
case Class::Rogue:
skill_to_use = EQ::skills::SkillBackstab;
break;
}
@@ -2035,7 +2035,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
ReuseTime = (FrenzyReuseTime - 1) / HasteMod;
// bards can do riposte frenzy for some reason
if (!IsRiposte && GetClass() == BERSERKER) {
if (!IsRiposte && GetClass() == Class::Berserker) {
int chance = GetLevel() * 2 + GetSkill(EQ::skills::SkillFrenzy);
if (zone->random.Roll0(450) < chance)
AtkRounds++;
+33 -33
View File
@@ -441,7 +441,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
case SE_CurrentMana:
{
// Bards don't get mana from effects, good or bad.
if(GetClass() == BARD)
if(GetClass() == Class::Bard)
break;
if(IsManaTapSpell(spell_id)) {
if(GetCasterClass() != 'N') {
@@ -478,7 +478,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
case SE_CurrentManaOnce:
{
// Bards don't get mana from effects, good or bad.
if(GetClass() == BARD)
if(GetClass() == Class::Bard)
break;
#ifdef SPELL_EFFECT_SPAM
snprintf(effect_desc, _EDLEN, "Current Mana Once: %+i", effect_value);
@@ -3432,7 +3432,7 @@ int64 Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level
*/
//This is checked from Mob::SpellEffects and applied to instant spells and runes.
if (caster && caster->GetClass() != BARD && caster->HasBaseEffectFocus()) {
if (caster && caster->GetClass() != Class::Bard && caster->HasBaseEffectFocus()) {
oval = effect_value;
int mod = caster->GetFocusEffect(focusFcBaseEffects, spell_id);
@@ -3445,7 +3445,7 @@ int64 Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level
else if (caster_id && instrument_mod > 10) {
Mob* buff_caster = entity_list.GetMob(caster_id);//If targeted bard song needed to confirm caster is not bard.
if (buff_caster && buff_caster->GetClass() != BARD) {
if (buff_caster && buff_caster->GetClass() != Class::Bard) {
oval = effect_value;
effect_value = effect_value * static_cast<int>(instrument_mod) / 10;
@@ -3991,7 +3991,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster)
case SE_Charm: {
if (!caster || !PassCharismaCheck(caster, buff.spellid)) {
BuffFadeByEffect(SE_Charm);
// Remove from hate list of any NPC's hate list and remove all NPCs this hate list
if (IsNPC()) {
entity_list.RemoveFromHateLists(this);
@@ -7248,7 +7248,7 @@ bool Mob::PassLimitClass(uint32 Classes_, uint16 Class_)
return false;
Class_ += 1;
for (int CurrentClass = 1; CurrentClass <= PLAYER_CLASS_COUNT; ++CurrentClass){
for (int CurrentClass = 1; CurrentClass <= Class::PLAYER_CLASS_COUNT; ++CurrentClass){
if (Classes_ % 2 == 1){
if (CurrentClass == Class_)
return true;
@@ -7481,7 +7481,7 @@ bool Mob::PassCastRestriction(int value)
case IS_CLASS_WIZARD:
case IS_WIZARD_USED_ON_MAGE_FIRE_PET:
if (GetClass() == WIZARD)
if (GetClass() == Class::Wizard)
return true;
break;
@@ -7521,12 +7521,12 @@ bool Mob::PassCastRestriction(int value)
break;
case IS_CLASS_MELEE_THAT_CAN_BASH_OR_KICK_EXCEPT_BARD:
if ((GetClass() != BARD) && (GetClass() != ROGUE) && IsFighterClass(GetClass()))
if ((GetClass() != Class::Bard) && (GetClass() != Class::Rogue) && IsFighterClass(GetClass()))
return true;
break;
case IS_CLASS_PURE_MELEE:
if (GetClass() == ROGUE || GetClass() == WARRIOR || GetClass() == BERSERKER || GetClass() == MONK)
if (GetClass() == Class::Rogue || GetClass() == Class::Warrior || GetClass() == Class::Berserker || GetClass() == Class::Monk)
return true;
break;
@@ -7541,78 +7541,78 @@ bool Mob::PassCastRestriction(int value)
break;
case IS_CLASS_WARRIOR:
if (GetClass() == WARRIOR)
if (GetClass() == Class::Warrior)
return true;
break;
case IS_CLASS_CLERIC:
if (GetClass() == CLERIC)
if (GetClass() == Class::Cleric)
return true;
break;
case IS_CLASS_PALADIN:
if (GetClass() == PALADIN)
if (GetClass() == Class::Paladin)
return true;
break;
case IS_CLASS_RANGER:
if (GetClass() == RANGER)
if (GetClass() == Class::Ranger)
return true;
break;
case IS_CLASS_SHADOWKNIGHT:
if (GetClass() == SHADOWKNIGHT)
if (GetClass() == Class::ShadowKnight)
return true;
break;
case IS_CLASS_DRUID:
if (GetClass() == DRUID)
if (GetClass() == Class::Druid)
return true;
break;
case IS_CLASS_MONK:
if (GetClass() == MONK)
if (GetClass() == Class::Monk)
return true;
break;
case IS_CLASS_BARD2:
case IS_CLASS_BARD:
if (GetClass() == BARD)
if (GetClass() == Class::Bard)
return true;
break;
case IS_CLASS_ROGUE:
if (GetClass() == ROGUE)
if (GetClass() == Class::Rogue)
return true;
break;
case IS_CLASS_SHAMAN:
if (GetClass() == SHAMAN)
if (GetClass() == Class::Shaman)
return true;
break;
case IS_CLASS_NECRO:
if (GetClass() == NECROMANCER)
if (GetClass() == Class::Necromancer)
return true;
break;
case IS_CLASS_MAGE:
if (GetClass() == MAGICIAN)
if (GetClass() == Class::Magician)
return true;
break;
case IS_CLASS_ENCHANTER:
if (GetClass() == ENCHANTER)
if (GetClass() == Class::Enchanter)
return true;
break;
case IS_CLASS_BEASTLORD:
if (GetClass() == BEASTLORD)
if (GetClass() == Class::Beastlord)
return true;
break;
case IS_CLASS_BERSERKER:
if (GetClass() == BERSERKER)
if (GetClass() == Class::Berserker)
return true;
break;
@@ -7622,7 +7622,7 @@ bool Mob::PassCastRestriction(int value)
break;
case IS_CLASS_NOT_WAR_PAL_SK:
if ((GetClass() != WARRIOR) && (GetClass() != PALADIN) && (GetClass() != SHADOWKNIGHT))
if ((GetClass() != Class::Warrior) && (GetClass() != Class::Paladin) && (GetClass() != Class::ShadowKnight))
return true;
break;
@@ -7722,8 +7722,8 @@ bool Mob::PassCastRestriction(int value)
}
case IS_CLASS_CHAIN_OR_PLATE:
if ((GetClass() == WARRIOR) || (GetClass() == BARD) || (GetClass() == SHADOWKNIGHT) || (GetClass() == PALADIN) || (GetClass() == CLERIC)
|| (GetClass() == RANGER) || (GetClass() == SHAMAN) || (GetClass() == ROGUE) || (GetClass() == BERSERKER)) {
if ((GetClass() == Class::Warrior) || (GetClass() == Class::Bard) || (GetClass() == Class::ShadowKnight) || (GetClass() == Class::Paladin) || (GetClass() == Class::Cleric)
|| (GetClass() == Class::Ranger) || (GetClass() == Class::Shaman) || (GetClass() == Class::Rogue) || (GetClass() == Class::Berserker)) {
return true;
}
break;
@@ -7914,7 +7914,7 @@ bool Mob::PassCastRestriction(int value)
break;
case IS_CLASS_WARRIOR_CASTER_PRIEST:
if (IsCasterClass(GetClass()) || GetClass() == WARRIOR)
if (IsCasterClass(GetClass()) || GetClass() == Class::Warrior)
return true;
break;
@@ -8082,13 +8082,13 @@ bool Mob::PassCastRestriction(int value)
break;
case IS_CLEINT_AND_MALE_DRUID_ENCHANTER_MAGICIAN_NECROANCER_SHAMAN_OR_WIZARD:
if (IsClient() && GetGender() == MALE && (IsCasterClass(GetClass()) && GetClass() != CLERIC))
if (IsClient() && GetGender() == MALE && (IsCasterClass(GetClass()) && GetClass() != Class::Cleric))
return true;
break;
case IS_CLIENT_AND_MALE_BEASTLORD_BERSERKER_MONK_RANGER_OR_ROGUE:
if (IsClient() && GetGender() == MALE &&
(GetClass() == BEASTLORD || GetClass() == BERSERKER || GetClass() == MONK || GetClass() == RANGER || GetClass() == ROGUE))
(GetClass() == Class::Beastlord || GetClass() == Class::Berserker || GetClass() == Class::Monk || GetClass() == Class::Ranger || GetClass() == Class::Rogue))
return true;
break;
@@ -8098,13 +8098,13 @@ bool Mob::PassCastRestriction(int value)
break;
case IS_CLIENT_AND_FEMALE_DRUID_ENCHANTER_MAGICIAN_NECROANCER_SHAMAN_OR_WIZARD:
if (IsClient() && GetGender() == FEMALE && (IsCasterClass(GetClass()) && GetClass() != CLERIC))
if (IsClient() && GetGender() == FEMALE && (IsCasterClass(GetClass()) && GetClass() != Class::Cleric))
return true;
break;
case IS_CLIENT_AND_FEMALE_BEASTLORD_BERSERKER_MONK_RANGER_OR_ROGUE:
if (IsClient() && GetGender() == FEMALE &&
(GetClass() == BEASTLORD || GetClass() == BERSERKER || GetClass() == MONK || GetClass() == RANGER || GetClass() == ROGUE))
(GetClass() == Class::Beastlord || GetClass() == Class::Berserker || GetClass() == Class::Monk || GetClass() == Class::Ranger || GetClass() == Class::Rogue))
return true;
break;
@@ -8177,7 +8177,7 @@ bool Mob::PassCastRestriction(int value)
}
case IS_NOT_CLASS_BARD:
if (GetClass() != BARD)
if (GetClass() != Class::Bard)
return true;
break;
+85 -15
View File
@@ -402,7 +402,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
}
}
//must use SPA 415 with focus (SPA 127/500/501) to reduce item recast
else if (cast_time && IsClient() && slot == CastingSlot::Item && item_slot != 0xFFFFFFFF) {
else if (cast_time && IsOfClientBot() && slot == CastingSlot::Item && item_slot != 0xFFFFFFFF) {
orgcasttime = cast_time;
if (cast_time) {
cast_time = GetActSpellCasttime(spell_id, cast_time);
@@ -1094,7 +1094,7 @@ bool Client::CheckFizzle(uint16 spell_id)
float diff = par_skill + static_cast<float>(spells[spell_id].base_difficulty) - act_skill;
// if you have high int/wis you fizzle less, you fizzle more if you are stupid
if(GetClass() == BARD)
if(GetClass() == Class::Bard)
{
diff -= (GetCHA() - 110) / 20.0;
}
@@ -1381,7 +1381,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo
Mob *spell_target = entity_list.GetMob(target_id);
// here we do different things if this is a bard casting a bard song from
// a spell bar slot
if(GetClass() == BARD) // bard's can move when casting any spell...
if(GetClass() == Class::Bard) // bard's can move when casting any spell...
{
if (IsBardSong(spell_id) && slot < CastingSlot::MaxGems) {
if (spells[spell_id].buff_duration == 0xFFFF) {
@@ -1643,6 +1643,10 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo
{
DeleteChargeFromSlot = GetItemSlotToConsumeCharge(spell_id, inventory_slot);
}
if (IsBot() && slot == CastingSlot::Item && inventory_slot != 0xFFFFFFFF) // 10 is an item
{
DeleteChargeFromSlot = GetItemSlotToConsumeCharge(spell_id, inventory_slot);
}
// we're done casting, now try to apply the spell
if(!SpellFinished(spell_id, spell_target, slot, mana_used, inventory_slot, resist_adjust, false,-1, 0xFFFFFFFF, 0, true))
{
@@ -1661,9 +1665,23 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo
TryTriggerOnCastFocusEffect(focusTriggerOnCast, spell_id);
if (DeleteChargeFromSlot >= 0) {
if (IsClient() && DeleteChargeFromSlot >= 0) {
CastToClient()->DeleteItemInInventory(DeleteChargeFromSlot, 1, true);
}
else if (IsBot() && DeleteChargeFromSlot >= 0) {
EQ::ItemInstance* inst = CastToBot()->GetBotItem(DeleteChargeFromSlot);
if (inst) {
inst->SetCharges((inst->GetCharges() - 1));
if (!database.botdb.SaveItemBySlot(CastToBot(), DeleteChargeFromSlot, inst)) {
GetOwner()->Message(Chat::Red, "%s says, 'Failed to save item [%i] slot [%i] for [%s].", inst->GetID(), DeleteChargeFromSlot, GetCleanName());
return;
}
}
else {
GetOwner()->Message(Chat::Red, "%s says, 'Failed to update item charges.", GetCleanName());
LogError("Failed to update item charges for {}.", GetCleanName());
}
}
//
// at this point the spell has successfully been cast
@@ -1938,7 +1956,7 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce
return false;
}
if(spell_target->GetClass() != LDON_TREASURE)
if(spell_target->GetClass() != Class::LDoNTreasure)
{
LogSpells("Spell [{}] canceled: invalid target (normal)", spell_id);
MessageString(Chat::Red,SPELL_NEED_TAR);
@@ -2301,14 +2319,21 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, in
return false;
//Death Touch targets the pet owner instead of the pet when said pet is tanking.
if ((RuleB(Spells, CazicTouchTargetsPetOwner) && spell_target && spell_target->HasOwner()) && (spell_id == SPELL_CAZIC_TOUCH || spell_id == SPELL_TOUCH_OF_VINITRAS)) {
Mob* owner = spell_target->GetOwner();
if ((RuleB(Spells, CazicTouchTargetsPetOwner) && spell_target && spell_target->HasOwner()) && !spell_target->IsBot() && (spell_id == SPELL_CAZIC_TOUCH || spell_id == SPELL_TOUCH_OF_VINITRAS)) {
Mob* owner = spell_target->GetOwner();
if (owner) {
spell_target = owner;
}
}
if ((RuleB(Bots, CazicTouchBotsOwner) && spell_target && spell_target->IsBot()) && spell_id == (SPELL_CAZIC_TOUCH || spell_id == SPELL_TOUCH_OF_VINITRAS)) {
auto bot_owner = spell_target->GetOwner();
if (bot_owner) {
spell_target = bot_owner;
}
}
//Guard Assist Code
if (RuleB(Character, PVPEnableGuardFactionAssist) && spell_target && IsDetrimentalSpell(spell_id) && spell_target != this) {
if (IsClient() && spell_target->IsClient()|| (HasOwner() && GetOwner()->IsClient() && spell_target->IsClient())) {
@@ -2687,7 +2712,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, in
}
}
//handle bard AA and Discipline recast timers when singing
if (GetClass() == BARD && spell_id != casting_spell_id && timer != 0xFFFFFFFF) {
if (GetClass() == Class::Bard && spell_id != casting_spell_id && timer != 0xFFFFFFFF) {
CastToClient()->GetPTimers().Start(timer, timer_duration);
LogSpells("Spell [{}]: Setting BARD custom reuse timer [{}] to [{}]", spell_id, casting_spell_timer, casting_spell_timer_duration);
}
@@ -2732,6 +2757,18 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, in
if(IsClient() && (slot == CastingSlot::Item || slot == CastingSlot::PotionBelt)){
CastToClient()->SetItemRecastTimer(spell_id, inventory_slot);
}
else if (IsBot() && CastToBot()->GetIsUsingItemClick() && slot == CastingSlot::Item) {
EQ::ItemInstance* inst = CastToBot()->GetBotItem(inventory_slot);
const EQ::ItemData* item = nullptr;
if (inst && inst->GetItem()) {
item = inst->GetItem();
CastToBot()->SetItemReuseTimer(item->ID);
CastToBot()->SetIsUsingItemClick(false);
}
else {
GetOwner()->Message(Chat::Red, "%s says, 'Failed to set item reuse timer for %s.", GetCleanName());
}
}
if (IsNPC()) {
CastToNPC()->AI_Event_SpellCastFinished(true, static_cast<uint16>(slot));
@@ -3143,8 +3180,8 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2,
if(effect1 != effect2)
continue;
if (IsBardOnlyStackEffect(effect1) && GetSpellLevel(spellid1, BARD) != 255 &&
GetSpellLevel(spellid2, BARD) != 255)
if (IsBardOnlyStackEffect(effect1) && GetSpellLevel(spellid1, Class::Bard) != 255 &&
GetSpellLevel(spellid2, Class::Bard) != 255)
continue;
// big ol' list according to the client, wasn't that nice!
@@ -6199,7 +6236,7 @@ bool Mob::UseBardSpellLogic(uint16 spell_id, int slot)
(
IsValidSpell(spell_id) &&
slot != -1 &&
GetClass() == BARD &&
GetClass() == Class::Bard &&
slot <= EQ::spells::SPELL_GEM_COUNT &&
IsBardSong(spell_id)
);
@@ -6964,7 +7001,11 @@ void Mob::DoBardCastingFromItemClick(bool is_casting_bard_song, uint32 cast_time
}
if (cast_time != 0) {
CastSpell(spell_id, target_id, CastingSlot::Item, cast_time, 0, 0, item_slot);
if (!CastSpell(spell_id, target_id, CastingSlot::Item, cast_time, 0, 0, item_slot)) {
if (IsBot()) {
GetOwner()->Message(Chat::Red, "%s says, 'Casting failed for %s. This could be due to zone restrictions, target restrictions or other limiting factors.", GetCleanName(), CastToBot()->GetBotItem(item_slot)->GetItem()->Name);
}
}
}
//Instant cast items do not stop bard songs or interrupt casting.
else if (CheckItemRaceClassDietyRestrictionsOnCast(item_slot) && DoCastingChecksOnCaster(spell_id, CastingSlot::Item)) {
@@ -6973,6 +7014,25 @@ void Mob::DoBardCastingFromItemClick(bool is_casting_bard_song, uint32 cast_time
if (IsClient() && DeleteChargeFromSlot >= 0) {
CastToClient()->DeleteItemInInventory(DeleteChargeFromSlot, 1, true);
}
else if (IsBot() && DeleteChargeFromSlot >= 0) {
EQ::ItemInstance* inst = CastToBot()->GetBotItem(DeleteChargeFromSlot);
if (inst) {
inst->SetCharges((inst->GetCharges() - 1));
if (!database.botdb.SaveItemBySlot(CastToBot(), DeleteChargeFromSlot, inst)) {
GetOwner()->Message(Chat::Red, "%s says, 'Failed to save item [%i] slot [%i] for [%s].", inst->GetID(), DeleteChargeFromSlot, GetCleanName());
return;
}
}
else {
GetOwner()->Message(Chat::Red, "%s says, 'Failed to update item charges.", GetCleanName());
LogError("Failed to update item charges for {}.", GetCleanName());
}
}
}
else {
if (IsBot()) {
GetOwner()->Message(Chat::Red, "%s says, 'Casting failed for %s. This could be due to zone restrictions, target restrictions or other limiting factors.", GetCleanName(), CastToBot()->GetBotItem(item_slot)->GetItem()->Name);
}
}
}
}
@@ -6981,12 +7041,17 @@ int16 Mob::GetItemSlotToConsumeCharge(int32 spell_id, uint32 inventory_slot)
{
int16 DeleteChargeFromSlot = -1;
if (!IsClient() || inventory_slot == 0xFFFFFFFF) {
if (!IsOfClientBot() || inventory_slot == 0xFFFFFFFF) {
return DeleteChargeFromSlot;
}
EQ::ItemInstance *item = nullptr;
item = CastToClient()->GetInv().GetItem(inventory_slot);
if (IsClient()) {
item = CastToClient()->GetInv().GetItem(inventory_slot);
}
else if (IsBot()) {
item = CastToBot()->GetBotItem(inventory_slot);
}
bool fromaug = false;
EQ::ItemData* augitem = nullptr;
@@ -7029,7 +7094,12 @@ int16 Mob::GetItemSlotToConsumeCharge(int32 spell_id, uint32 inventory_slot)
}
else{
LogSpells("Item used to cast spell [{}] was missing from inventory slot [{}] after casting!", spell_id, inventory_slot);
Message(Chat::Red, "Casting Error: Active casting item not found in inventory slot %i", inventory_slot);
if (IsClient()) {
Message(Chat::Red, "Casting Error: Active casting item not found in inventory slot %i", inventory_slot);
}
else if (IsBot()) {
CastToBot()->GetOwner()->Message(Chat::Red, "Casting Error: Active casting item not found in inventory slot %i for %s", inventory_slot, GetCleanName());
}
InterruptSpell();
return DeleteChargeFromSlot;
}
+2 -2
View File
@@ -1101,9 +1101,9 @@ void ClientTaskState::RewardTask(Client *c, const TaskInformation *ti, ClientTas
if (ti->reward_points > 0) {
if (ti->reward_point_type == static_cast<int32_t>(zone->GetCurrencyID(RADIANT_CRYSTAL))) {
c->AddCrystals(ti->reward_points, 0);
c->AddRadiantCrystals(ti->reward_points);
} else if (ti->reward_point_type == static_cast<int32_t>(zone->GetCurrencyID(EBON_CRYSTAL))) {
c->AddCrystals(0, ti->reward_points);
c->AddEbonCrystals(ti->reward_points);
} else {
for (const auto& ac : zone->AlternateCurrencies) {
if (ti->reward_point_type == ac.id) {
+2 -2
View File
@@ -448,7 +448,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob
//changing from a switch to string of if's since we don't need to iterate through all of the skills in the SkillType enum
if (spec.tradeskill == EQ::skills::SkillAlchemy) {
if (user_pp.class_ != SHAMAN) {
if (user_pp.class_ != Class::Shaman) {
user->Message(Chat::Red, "This tradeskill can only be performed by a shaman.");
auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0);
user->QueuePacket(outapp);
@@ -473,7 +473,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob
}
}
else if (spec.tradeskill == EQ::skills::SkillMakePoison) {
if (user_pp.class_ != ROGUE) {
if (user_pp.class_ != Class::Rogue) {
user->Message(Chat::Red, "Only rogues can mix poisons.");
auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0);
user->QueuePacket(outapp);
+5 -5
View File
@@ -1068,14 +1068,14 @@ int64 Mob::TuneACSum(bool skip_caps, int ac_override, int add_ac)
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;
@@ -1423,7 +1423,7 @@ void Mob::TuneCommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraA
// 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)
@@ -1436,7 +1436,7 @@ void Mob::TuneCommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraA
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);
@@ -1461,7 +1461,7 @@ void Mob::TuneCommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraA
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
View File
@@ -183,7 +183,7 @@ bool Zone::LoadZoneObjects()
)
);
if (l.empty()) {
LogError("Error Loading Objects for Zone [{}] Version [{}]", zoneid, instanceversion);
LogWarning("No Objects to load for Zone [{}] Version [{}]", zoneid, instanceversion);
return false;
}
@@ -1941,7 +1941,7 @@ void Zone::SetTime(uint8 hour, uint8 minute, bool update_world /*= true*/)
zone_time.GetCurrentEQTimeOfDay(time(0), &eq_time_of_day->start_eqtime);
eq_time_of_day->start_eqtime.minute = minute;
eq_time_of_day->start_eqtime.hour = hour;
eq_time_of_day->start_eqtime.hour = hour + 1;
eq_time_of_day->start_realtime = time(0);
/* By Default we update worlds time, but we can optionally no update world which updates the rest of the zone servers */