mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-30 03:25:44 +00:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 703862d977 | |||
| 6e325c1ee3 | |||
| 933b83add6 | |||
| b3cd4e63f1 | |||
| 3c894cb533 | |||
| b19ad64800 | |||
| 2cd3d27c67 | |||
| d3b46becd0 | |||
| 286479198f | |||
| 21ec832ca6 | |||
| bdf5f8b4a3 | |||
| 4ca6485398 | |||
| 0c9c2e25c1 | |||
| 7e651877c7 | |||
| 9739c1c8ef | |||
| 8aae59eebe | |||
| c1b07afae9 | |||
| 9c238cd08d | |||
| 33adb9bcc1 | |||
| 2e8bf82861 | |||
| 4d118ab978 | |||
| fcb40daaf1 | |||
| 553bafdbe1 | |||
| d0443db199 | |||
| 9206163190 | |||
| e504482b94 | |||
| 77b88e3dec | |||
| aeeb350068 | |||
| df83113cea | |||
| 940abfaf7a | |||
| a46443b95e |
+1
-1
@@ -15,7 +15,7 @@ volumes:
|
||||
|
||||
steps:
|
||||
- name: Build Linux X64
|
||||
image: akkadius/eqemu-server:v13
|
||||
image: akkadius/eqemu-server:v14
|
||||
environment:
|
||||
GITHUB_TOKEN:
|
||||
from_secret: GH_RELEASE_GITHUB_API_TOKEN
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -792,5 +792,8 @@ IF (UNIX)
|
||||
SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0)
|
||||
ENDIF (UNIX)
|
||||
|
||||
IF (WIN32 AND EQEMU_BUILD_PCH)
|
||||
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/pch.h)
|
||||
ENDIF()
|
||||
|
||||
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
||||
|
||||
+296
-473
File diff suppressed because it is too large
Load Diff
+96
-93
@@ -19,99 +19,106 @@
|
||||
#define CLASSES_CH
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#define NO_CLASS 0
|
||||
#define WARRIOR 1
|
||||
#define CLERIC 2
|
||||
#define PALADIN 3
|
||||
#define RANGER 4
|
||||
#define SHADOWKNIGHT 5
|
||||
#define DRUID 6
|
||||
#define MONK 7
|
||||
#define BARD 8
|
||||
#define ROGUE 9
|
||||
#define SHAMAN 10
|
||||
#define NECROMANCER 11
|
||||
#define WIZARD 12
|
||||
#define MAGICIAN 13
|
||||
#define ENCHANTER 14
|
||||
#define BEASTLORD 15
|
||||
#define BERSERKER 16
|
||||
#define WARRIORGM 20
|
||||
#define CLERICGM 21
|
||||
#define PALADINGM 22
|
||||
#define RANGERGM 23
|
||||
#define SHADOWKNIGHTGM 24
|
||||
#define DRUIDGM 25
|
||||
#define MONKGM 26
|
||||
#define BARDGM 27
|
||||
#define ROGUEGM 28
|
||||
#define SHAMANGM 29
|
||||
#define NECROMANCERGM 30
|
||||
#define WIZARDGM 31
|
||||
#define MAGICIANGM 32
|
||||
#define ENCHANTERGM 33
|
||||
#define BEASTLORDGM 34
|
||||
#define BERSERKERGM 35
|
||||
#define BANKER 40
|
||||
#define MERCHANT 41
|
||||
#define DISCORD_MERCHANT 59
|
||||
#define ADVENTURE_RECRUITER 60
|
||||
#define ADVENTURE_MERCHANT 61
|
||||
#define LDON_TREASURE 62 // objects you can use /open on first seen in LDONs, seen on Danvi's Corpse in Akheva
|
||||
#define TRIBUTE_MASTER 63
|
||||
#define GUILD_TRIBUTE_MASTER 64 // not sure
|
||||
#define GUILD_BANKER 66
|
||||
#define NORRATHS_KEEPERS_MERCHANT 67
|
||||
#define DARK_REIGN_MERCHANT 68
|
||||
#define FELLOWSHIP_MASTER 69
|
||||
#define ALT_CURRENCY_MERCHANT 70
|
||||
#define MERCENARY_MASTER 71
|
||||
namespace Class {
|
||||
constexpr uint8 None = 0;
|
||||
constexpr uint8 Warrior = 1;
|
||||
constexpr uint8 Cleric = 2;
|
||||
constexpr uint8 Paladin = 3;
|
||||
constexpr uint8 Ranger = 4;
|
||||
constexpr uint8 ShadowKnight = 5;
|
||||
constexpr uint8 Druid = 6;
|
||||
constexpr uint8 Monk = 7;
|
||||
constexpr uint8 Bard = 8;
|
||||
constexpr uint8 Rogue = 9;
|
||||
constexpr uint8 Shaman = 10;
|
||||
constexpr uint8 Necromancer = 11;
|
||||
constexpr uint8 Wizard = 12;
|
||||
constexpr uint8 Magician = 13;
|
||||
constexpr uint8 Enchanter = 14;
|
||||
constexpr uint8 Beastlord = 15;
|
||||
constexpr uint8 Berserker = 16;
|
||||
constexpr uint8 WarriorGM = 20;
|
||||
constexpr uint8 ClericGM = 21;
|
||||
constexpr uint8 PaladinGM = 22;
|
||||
constexpr uint8 RangerGM = 23;
|
||||
constexpr uint8 ShadowKnightGM = 24;
|
||||
constexpr uint8 DruidGM = 25;
|
||||
constexpr uint8 MonkGM = 26;
|
||||
constexpr uint8 BardGM = 27;
|
||||
constexpr uint8 RogueGM = 28;
|
||||
constexpr uint8 ShamanGM = 29;
|
||||
constexpr uint8 NecromancerGM = 30;
|
||||
constexpr uint8 WizardGM = 31;
|
||||
constexpr uint8 MagicianGM = 32;
|
||||
constexpr uint8 EnchanterGM = 33;
|
||||
constexpr uint8 BeastlordGM = 34;
|
||||
constexpr uint8 BerserkerGM = 35;
|
||||
constexpr uint8 Banker = 40;
|
||||
constexpr uint8 Merchant = 41;
|
||||
constexpr uint8 DiscordMerchant = 59;
|
||||
constexpr uint8 AdventureRecruiter = 60;
|
||||
constexpr uint8 AdventureMerchant = 61;
|
||||
constexpr uint8 LDoNTreasure = 62;
|
||||
constexpr uint8 TributeMaster = 63;
|
||||
constexpr uint8 GuildTributeMaster = 64;
|
||||
constexpr uint8 GuildBanker = 66;
|
||||
constexpr uint8 NorrathsKeepersMerchant = 67;
|
||||
constexpr uint8 DarkReignMerchant = 68;
|
||||
constexpr uint8 FellowshipMaster = 69;
|
||||
constexpr uint8 AlternateCurrencyMerchant = 70;
|
||||
constexpr uint8 MercenaryLiaison = 71;
|
||||
|
||||
constexpr uint8 PLAYER_CLASS_COUNT = 16;
|
||||
constexpr uint16 ALL_CLASSES_BITMASK = 65535;
|
||||
};
|
||||
|
||||
// player class values
|
||||
#define PLAYER_CLASS_UNKNOWN 0
|
||||
#define PLAYER_CLASS_WARRIOR 1
|
||||
#define PLAYER_CLASS_CLERIC 2
|
||||
#define PLAYER_CLASS_PALADIN 3
|
||||
#define PLAYER_CLASS_RANGER 4
|
||||
#define PLAYER_CLASS_SHADOWKNIGHT 5
|
||||
#define PLAYER_CLASS_DRUID 6
|
||||
#define PLAYER_CLASS_MONK 7
|
||||
#define PLAYER_CLASS_BARD 8
|
||||
#define PLAYER_CLASS_ROGUE 9
|
||||
#define PLAYER_CLASS_SHAMAN 10
|
||||
#define PLAYER_CLASS_NECROMANCER 11
|
||||
#define PLAYER_CLASS_WIZARD 12
|
||||
#define PLAYER_CLASS_MAGICIAN 13
|
||||
#define PLAYER_CLASS_ENCHANTER 14
|
||||
#define PLAYER_CLASS_BEASTLORD 15
|
||||
#define PLAYER_CLASS_BERSERKER 16
|
||||
static std::map<uint8, uint16> player_class_bitmasks = {
|
||||
{Class::Warrior, 1},
|
||||
{Class::Cleric, 2},
|
||||
{Class::Paladin, 4},
|
||||
{Class::Ranger, 8},
|
||||
{Class::ShadowKnight, 16},
|
||||
{Class::Druid, 32},
|
||||
{Class::Monk, 64},
|
||||
{Class::Bard, 128},
|
||||
{Class::Rogue, 256},
|
||||
{Class::Shaman, 512},
|
||||
{Class::Necromancer, 1024},
|
||||
{Class::Wizard, 2048},
|
||||
{Class::Magician, 4096},
|
||||
{Class::Enchanter, 8192},
|
||||
{Class::Beastlord, 16384},
|
||||
{Class::Berserker, 32768},
|
||||
};
|
||||
|
||||
#define PLAYER_CLASS_COUNT 16
|
||||
static std::string shadow_knight_class_name = (
|
||||
RuleB(World, UseOldShadowKnightClassExport) ?
|
||||
"Shadowknight" :
|
||||
"Shadow Knight"
|
||||
);
|
||||
|
||||
|
||||
// player class bits
|
||||
#define PLAYER_CLASS_UNKNOWN_BIT 0
|
||||
#define PLAYER_CLASS_WARRIOR_BIT 1
|
||||
#define PLAYER_CLASS_CLERIC_BIT 2
|
||||
#define PLAYER_CLASS_PALADIN_BIT 4
|
||||
#define PLAYER_CLASS_RANGER_BIT 8
|
||||
#define PLAYER_CLASS_SHADOWKNIGHT_BIT 16
|
||||
#define PLAYER_CLASS_DRUID_BIT 32
|
||||
#define PLAYER_CLASS_MONK_BIT 64
|
||||
#define PLAYER_CLASS_BARD_BIT 128
|
||||
#define PLAYER_CLASS_ROGUE_BIT 256
|
||||
#define PLAYER_CLASS_SHAMAN_BIT 512
|
||||
#define PLAYER_CLASS_NECROMANCER_BIT 1024
|
||||
#define PLAYER_CLASS_WIZARD_BIT 2048
|
||||
#define PLAYER_CLASS_MAGICIAN_BIT 4096
|
||||
#define PLAYER_CLASS_ENCHANTER_BIT 8192
|
||||
#define PLAYER_CLASS_BEASTLORD_BIT 16384
|
||||
#define PLAYER_CLASS_BERSERKER_BIT 32768
|
||||
|
||||
#define PLAYER_CLASS_ALL_MASK 65535 // was 65536
|
||||
static std::map<uint8, std::string> class_names = {
|
||||
{Class::Warrior, "Warrior"},
|
||||
{Class::Cleric, "Cleric"},
|
||||
{Class::Paladin, "Paladin"},
|
||||
{Class::Ranger, "Ranger"},
|
||||
{Class::ShadowKnight, shadow_knight_class_name},
|
||||
{Class::Druid, "Druid"},
|
||||
{Class::Monk, "Monk"},
|
||||
{Class::Bard, "Bard"},
|
||||
{Class::Rogue, "Rogue"},
|
||||
{Class::Shaman, "Shaman"},
|
||||
{Class::Necromancer, "Necromancer"},
|
||||
{Class::Wizard, "Wizard"},
|
||||
{Class::Magician, "Magician"},
|
||||
{Class::Enchanter, "Enchanter"},
|
||||
{Class::Beastlord, "Beastlord"},
|
||||
{Class::Berserker, "Berserker"},
|
||||
};
|
||||
|
||||
|
||||
#define ARMOR_TYPE_UNKNOWN 0
|
||||
@@ -126,16 +133,12 @@
|
||||
|
||||
|
||||
const char* GetClassIDName(uint8 class_id, uint8 level = 0);
|
||||
const char* GetPlayerClassName(uint32 player_class_value, uint8 level = 0);
|
||||
|
||||
bool IsPlayerClass(uint8 class_id);
|
||||
const std::string GetPlayerClassAbbreviation(uint8 class_id);
|
||||
|
||||
uint32 GetPlayerClassValue(uint8 class_id);
|
||||
uint32 GetPlayerClassBit(uint8 class_id);
|
||||
|
||||
uint8 GetClassIDFromPlayerClassValue(uint32 player_class_value);
|
||||
uint8 GetClassIDFromPlayerClassBit(uint32 player_class_bit);
|
||||
uint8 GetPlayerClassValue(uint8 class_id);
|
||||
uint16 GetPlayerClassBit(uint8 class_id);
|
||||
|
||||
bool IsFighterClass(uint8 class_id);
|
||||
bool IsSpellFighterClass(uint8 class_id);
|
||||
|
||||
@@ -322,6 +322,10 @@ void DatabaseDumpService::DatabaseDump()
|
||||
pipe_file
|
||||
);
|
||||
|
||||
LogInfo("Backing up database [{}]", execute_command);
|
||||
LogInfo("This can take a few minutes depending on the size of your database");
|
||||
LogInfo("LOADING... PLEASE WAIT...");
|
||||
|
||||
BuildCredentialsFile();
|
||||
std::string execution_result = Process::execute(execute_command);
|
||||
if (!execution_result.empty() && IsDumpOutputToConsole()) {
|
||||
|
||||
@@ -274,9 +274,9 @@ bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
|
||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||
|
||||
// server database version is required
|
||||
bool server_up_to_date = v.server_database_version == b.server_database_version;
|
||||
bool server_up_to_date = v.server_database_version >= b.server_database_version;
|
||||
// bots database version is optional, if not enabled then it is always up-to-date
|
||||
bool bots_up_to_date = RuleB(Bots, Enabled) ? v.bots_database_version == b.bots_database_version : true;
|
||||
bool bots_up_to_date = RuleB(Bots, Enabled) ? v.bots_database_version >= b.bots_database_version : true;
|
||||
|
||||
return server_up_to_date && bots_up_to_date;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -124,6 +124,12 @@ struct LDoNTrapTemplate
|
||||
uint8 locked;
|
||||
};
|
||||
|
||||
enum CrystalReclaimTypes
|
||||
{
|
||||
Ebon = 5,
|
||||
Radiant = 4,
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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] : "";
|
||||
|
||||
@@ -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
@@ -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
@@ -666,7 +666,7 @@ bool IsBardSong(uint16 spell_id)
|
||||
const auto& spell = spells[spell_id];
|
||||
|
||||
if (
|
||||
spell.classes[BARD - 1] < UINT8_MAX &&
|
||||
spell.classes[Class::Bard - 1] < UINT8_MAX &&
|
||||
!spell.is_discipline
|
||||
) {
|
||||
return true;
|
||||
@@ -780,7 +780,7 @@ uint8 GetSpellMinimumLevel(uint16 spell_id)
|
||||
|
||||
const auto& spell = spells[spell_id];
|
||||
|
||||
for (int i = 0; i < PLAYER_CLASS_COUNT; i++) {
|
||||
for (int i = 0; i < Class::PLAYER_CLASS_COUNT; i++) {
|
||||
if (spell.classes[i] < minimum_level) {
|
||||
minimum_level = spell.classes[i];
|
||||
}
|
||||
@@ -798,7 +798,7 @@ uint8 GetSpellLevel(uint16 spell_id, uint8 class_id)
|
||||
return UINT8_MAX;
|
||||
}
|
||||
|
||||
if (class_id >= PLAYER_CLASS_COUNT) {
|
||||
if (class_id >= Class::PLAYER_CLASS_COUNT) {
|
||||
return UINT8_MAX;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1369,7 +1369,7 @@ struct SPDat_Spell_Struct
|
||||
/* 101 */ int8 zone_type; // 01=Outdoors, 02=dungeons, ff=Any -- ZONETYPE
|
||||
/* 102 */ int8 environment_type; // -- ENVIRONMENTTYPE
|
||||
/* 103 */ int8 time_of_day; // -- TIMEOFDAY
|
||||
/* 104 */ uint8 classes[PLAYER_CLASS_COUNT]; // Classes, and their min levels -- WARRIORMIN ... BERSERKERMIN
|
||||
/* 104 */ uint8 classes[Class::PLAYER_CLASS_COUNT]; // Classes, and their min levels -- WARRIORMIN ... BERSERKERMIN
|
||||
/* 120 */ uint8 casting_animation; // -- CASTINGANIM
|
||||
/* 121 */ //uint8 TargetAnim; // -- TARGETANIM
|
||||
/* 122 */ //uint32 TravelType; // -- TRAVELTYPE
|
||||
|
||||
+3
-3
@@ -25,7 +25,7 @@
|
||||
|
||||
// Build variables
|
||||
// these get injected during the build pipeline
|
||||
#define CURRENT_VERSION "22.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
@@ -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"
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -78,6 +78,10 @@ ADD_EXECUTABLE(world ${world_sources} ${world_headers})
|
||||
|
||||
INSTALL(TARGETS world RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
|
||||
IF (WIN32 AND EQEMU_BUILD_PCH)
|
||||
TARGET_PRECOMPILE_HEADERS(world PRIVATE ../common/pch/pch.h)
|
||||
ENDIF ()
|
||||
|
||||
ADD_DEFINITIONS(-DWORLD)
|
||||
|
||||
TARGET_LINK_LIBRARIES(world ${SERVER_LIBS})
|
||||
|
||||
+5
-5
@@ -1966,7 +1966,7 @@ bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc)
|
||||
{ /*Drakkin*/ 70, 80, 85, 75, 80, 85, 75}
|
||||
};
|
||||
|
||||
static const int BaseClass[PLAYER_CLASS_COUNT][8] =
|
||||
static const int BaseClass[Class::PLAYER_CLASS_COUNT][8] =
|
||||
{ /* STR STA AGI DEX WIS INT CHR ADD*/
|
||||
{ /*Warrior*/ 10, 10, 5, 0, 0, 0, 0, 25},
|
||||
{ /*Cleric*/ 5, 5, 0, 0, 10, 0, 0, 30},
|
||||
@@ -1986,7 +1986,7 @@ bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc)
|
||||
{ /*Berserker*/ 10, 5, 0, 10, 0, 0, 0, 25}
|
||||
};
|
||||
|
||||
static const bool ClassRaceLookupTable[PLAYER_CLASS_COUNT][_TABLE_RACES]=
|
||||
static const bool ClassRaceLookupTable[Class::PLAYER_CLASS_COUNT][_TABLE_RACES]=
|
||||
{ /*Human Barbarian Erudite Woodelf Highelf Darkelf Halfelf Dwarf Troll Ogre Halfling Gnome Iksar Vahshir Froglok Drakkin*/
|
||||
{ /*Warrior*/ true, true, false, true, false, true, true, true, true, true, true, true, true, true, true, true},
|
||||
{ /*Cleric*/ true, false, true, false, true, true, true, true, false, false, true, true, false, false, true, true},
|
||||
@@ -2021,7 +2021,7 @@ bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc)
|
||||
|
||||
// if out of range looking it up in the table would crash stuff
|
||||
// so we return from these
|
||||
if (classtemp >= PLAYER_CLASS_COUNT) {
|
||||
if (classtemp >= Class::PLAYER_CLASS_COUNT) {
|
||||
LogInfo(" class is out of range");
|
||||
return false;
|
||||
}
|
||||
@@ -2114,7 +2114,7 @@ void Client::SetClassStartingSkills(PlayerProfile_Struct *pp)
|
||||
}
|
||||
}
|
||||
|
||||
if (cle->GetClientVersion() < static_cast<uint8>(EQ::versions::ClientVersion::RoF2) && pp->class_ == BERSERKER) {
|
||||
if (cle->GetClientVersion() < static_cast<uint8>(EQ::versions::ClientVersion::RoF2) && pp->class_ == Class::Berserker) {
|
||||
pp->skills[EQ::skills::Skill1HPiercing] = pp->skills[EQ::skills::Skill2HPiercing];
|
||||
pp->skills[EQ::skills::Skill2HPiercing] = 0;
|
||||
}
|
||||
@@ -2299,7 +2299,7 @@ void Client::SetClassLanguages(PlayerProfile_Struct *pp)
|
||||
{
|
||||
// we only need to handle one class, but custom server might want to do more
|
||||
switch(pp->class_) {
|
||||
case ROGUE:
|
||||
case Class::Rogue:
|
||||
pp->languages[LANG_THIEVES_CANT] = 100;
|
||||
break;
|
||||
default:
|
||||
|
||||
+2
-2
@@ -33,7 +33,7 @@ GroupLFP::GroupLFP(uint32 inLeaderID) {
|
||||
LeaderID = inLeaderID;
|
||||
for (auto &member : Members) {
|
||||
member.Name[0] = '\0';
|
||||
member.Class = NO_CLASS;
|
||||
member.Class = Class::None;
|
||||
member.Level = 0;
|
||||
member.Zone = 0;
|
||||
}
|
||||
@@ -77,7 +77,7 @@ void GroupLFP::SetDetails(ServerLFPUpdate_Struct *Update) {
|
||||
Members[i].GuildID = CLE->GuildID();
|
||||
}
|
||||
else {
|
||||
Members[i].Class = NO_CLASS;
|
||||
Members[i].Class = Class::None;
|
||||
Members[i].Level = 0;
|
||||
Members[i].Zone = 0;
|
||||
Members[i].GuildID = 0xFFFF;
|
||||
|
||||
+1
-1
@@ -434,7 +434,7 @@ int main(int argc, char **argv)
|
||||
tod.year,
|
||||
tod.month,
|
||||
tod.day,
|
||||
tod.hour,
|
||||
tod.hour - 1,
|
||||
tod.minute
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+35
-17
@@ -42,13 +42,12 @@ constexpr uint32 BOT_FOLLOW_DISTANCE_DEFAULT_MAX = 2500; // as DSq value (50 uni
|
||||
|
||||
constexpr uint32 BOT_KEEP_ALIVE_INTERVAL = 5000; // 5 seconds
|
||||
|
||||
constexpr uint32 MAG_EPIC_1_0 = 28034;
|
||||
|
||||
extern WorldServer worldserver;
|
||||
|
||||
constexpr int BotAISpellRange = 100; // TODO: Write a method that calcs what the bot's spell range is based on spell, equipment, AA, whatever and replace this
|
||||
constexpr int MaxSpellTimer = 15;
|
||||
constexpr int MaxDisciplineTimer = 10;
|
||||
constexpr int DisciplineReuseStart = MaxSpellTimer + 1;
|
||||
constexpr int MaxTimer = MaxSpellTimer + MaxDisciplineTimer;
|
||||
constexpr int NegativeItemReuse = -1; // Unlinked timer for items
|
||||
|
||||
// nHSND negative Healer/Slower/Nuker/Doter
|
||||
// pH positive Healer
|
||||
@@ -222,6 +221,8 @@ public:
|
||||
void SetPullFlag(bool flag = true) { m_pull_flag = flag; }
|
||||
bool GetPullingFlag() const { return m_pulling_flag; }
|
||||
bool GetReturningFlag() const { return m_returning_flag; }
|
||||
bool GetIsUsingItemClick() { return is_using_item_click; }
|
||||
void SetIsUsingItemClick(bool flag = true) { is_using_item_click = flag; }
|
||||
bool UseDiscipline(uint32 spell_id, uint32 target);
|
||||
uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets, Raid* raid);
|
||||
uint8 GetNumberNeedingHealedInRaidGroup(uint8& need_healed, uint8 hpr, bool includePets, Raid* raid);
|
||||
@@ -286,6 +287,10 @@ public:
|
||||
void SetEndurance(int32 newEnd) override;
|
||||
void DoEnduranceUpkeep();
|
||||
|
||||
void TryItemClick(uint16 slot_id);
|
||||
EQ::ItemInstance* GetClickItem(uint16 slot_id);
|
||||
void DoItemClick(const EQ::ItemData* inst, uint16 slot_id);
|
||||
|
||||
bool AI_AddBotSpells(uint32 bot_spell_id);
|
||||
void AddSpellToBotList(
|
||||
int16 iPriority,
|
||||
@@ -394,25 +399,20 @@ public:
|
||||
|
||||
// Static Class Methods
|
||||
static Bot* LoadBot(uint32 botID);
|
||||
static uint32 SpawnedBotCount(const uint32 owner_id, uint8 class_id = NO_CLASS);
|
||||
static uint32 SpawnedBotCount(const uint32 owner_id, uint8 class_id = Class::None);
|
||||
static void LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp);
|
||||
|
||||
static bool IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined);
|
||||
static Bot* GetBotByBotClientOwnerAndBotName(Client* c, const std::string& botName);
|
||||
static void ProcessBotGroupInvite(Client* c, std::string const& botName);
|
||||
static void ProcessBotGroupDisband(Client* c, const std::string& botName);
|
||||
static void BotOrderCampAll(Client* c, uint8 class_id = NO_CLASS);
|
||||
static void BotOrderCampAll(Client* c, uint8 class_id = Class::None);
|
||||
static void ProcessBotInspectionRequest(Bot* inspectedBot, Client* client);
|
||||
static void LoadAndSpawnAllZonedBots(Client* bot_owner);
|
||||
static bool GroupHasBot(Group* group);
|
||||
static Bot* GetFirstBotInGroup(Group* group);
|
||||
static void ProcessClientZoneChange(Client* botOwner);
|
||||
static void ProcessBotOwnerRefDelete(Mob* botOwner); // Removes a Client* reference when the Client object is destroyed
|
||||
static int32 GetSpellRecastTimer(Bot *caster, int timer_index);
|
||||
static bool CheckSpellRecastTimers(Bot *caster, int SpellIndex);
|
||||
static int32 GetDisciplineRecastTimer(Bot *caster, int timer_index);
|
||||
static bool CheckDisciplineRecastTimers(Bot *caster, int timer_index);
|
||||
static uint32 GetDisciplineRemainingTime(Bot *caster, int timer_index);
|
||||
|
||||
//Raid methods
|
||||
static void ProcessRaidInvite(Mob* invitee, Client* invitor, bool group_invite = false);
|
||||
@@ -604,7 +604,7 @@ public:
|
||||
void SetBotCharmer(bool c) { _botCharmer = c; }
|
||||
void SetPetChooser(bool p) { _petChooser = p; }
|
||||
void SetBotOwner(Mob* botOwner) { this->_botOwner = botOwner; }
|
||||
void SetRangerAutoWeaponSelect(bool enable) { GetClass() == RANGER ? _rangerAutoWeaponSelect = enable : _rangerAutoWeaponSelect = false; }
|
||||
void SetRangerAutoWeaponSelect(bool enable) { GetClass() == Class::Ranger ? _rangerAutoWeaponSelect = enable : _rangerAutoWeaponSelect = false; }
|
||||
void SetBotStance(EQ::constants::StanceType botStance) {
|
||||
if (botStance >= EQ::constants::stancePassive && botStance <= EQ::constants::stanceBurnAE)
|
||||
_botStance = botStance;
|
||||
@@ -612,8 +612,23 @@ public:
|
||||
_botStance = EQ::constants::stancePassive;
|
||||
}
|
||||
void SetBotCasterRange(uint32 bot_caster_range) { m_bot_caster_range = bot_caster_range; }
|
||||
void SetSpellRecastTimer(int timer_index, int32 recast_delay);
|
||||
void SetDisciplineRecastTimer(int timer_index, int32 recast_delay);
|
||||
uint32 GetSpellRecastTimer(uint16 spell_id = 0);
|
||||
bool CheckSpellRecastTimer(uint16 spell_id = 0);
|
||||
uint32 GetSpellRecastRemainingTime(uint16 spell_id = 0);
|
||||
void SetSpellRecastTimer(uint16 spell_id, int32 recast_delay = 0);
|
||||
uint32 CalcSpellRecastTimer(uint16 spell_id);
|
||||
uint32 GetDisciplineReuseTimer(uint16 spell_id = 0);
|
||||
bool CheckDisciplineReuseTimer(uint16 spell_id = 0);
|
||||
uint32 GetDisciplineReuseRemainingTime(uint16 spell_id = 0);
|
||||
void SetDisciplineReuseTimer(uint16 spell_id, int32 reuse_timer = 0);
|
||||
uint32 GetItemReuseTimer(uint32 item_id = 0);
|
||||
bool CheckItemReuseTimer(uint32 item_id = 0);
|
||||
void SetItemReuseTimer(uint32 item_id, uint32 reuse_timer = 0);
|
||||
void ClearDisciplineReuseTimer(uint16 spell_id = 0);
|
||||
void ClearItemReuseTimer(uint32 item_id = 0);
|
||||
void ClearSpellRecastTimer(uint16 spell_id = 0);
|
||||
uint32 GetItemReuseRemainingTime(uint32 item_id = 0);
|
||||
void ClearExpiredTimers();
|
||||
void SetAltOutOfCombatBehavior(bool behavior_flag) { _altoutofcombatbehavior = behavior_flag;}
|
||||
void SetShowHelm(bool showhelm) { _showhelm = showhelm; }
|
||||
void SetBeardColor(uint8 value) { beardcolor = value; }
|
||||
@@ -713,7 +728,8 @@ public:
|
||||
|
||||
// New accessors for BotDatabase access
|
||||
bool DeleteBot();
|
||||
uint32* GetTimers() { return timers; }
|
||||
std::vector<BotTimer_Struct> GetBotTimers() { return bot_timers; }
|
||||
void SetBotTimers(std::vector<BotTimer_Struct> timers) { bot_timers = timers; }
|
||||
uint32 GetLastZoneID() const { return _lastZoneId; }
|
||||
int32 GetBaseAC() const { return _baseAC; }
|
||||
int32 GetBaseATK() const { return _baseATK; }
|
||||
@@ -738,7 +754,7 @@ public:
|
||||
//Raid additions
|
||||
Raid* p_raid_instance;
|
||||
|
||||
static uint8 spell_casting_chances[SPELL_TYPE_COUNT][PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND];
|
||||
static uint8 spell_casting_chances[SPELL_TYPE_COUNT][Class::PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND];
|
||||
|
||||
bool BotCastMez(Mob* tar, uint8 botLevel, bool checked_los, BotSpell& botSpell, Raid* raid);
|
||||
bool BotCastHeal(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpell, Raid* raid);
|
||||
@@ -828,6 +844,7 @@ protected:
|
||||
|
||||
std::vector<BotSpells_Struct> AIBot_spells;
|
||||
std::vector<BotSpells_Struct> AIBot_spells_enforced;
|
||||
std::vector<BotTimer_Struct> bot_timers;
|
||||
|
||||
private:
|
||||
// Class Members
|
||||
@@ -861,11 +878,11 @@ private:
|
||||
int32 cur_end;
|
||||
int32 max_end;
|
||||
int32 end_regen;
|
||||
uint32 timers[MaxTimer];
|
||||
|
||||
Timer m_evade_timer; // can be moved to pTimers at some point
|
||||
Timer m_alt_combat_hate_timer;
|
||||
Timer m_auto_defend_timer;
|
||||
Timer auto_save_timer;
|
||||
bool m_dirtyautohaters;
|
||||
bool m_guard_flag;
|
||||
bool m_hold_flag;
|
||||
@@ -874,6 +891,7 @@ private:
|
||||
bool m_pull_flag;
|
||||
bool m_pulling_flag;
|
||||
bool m_returning_flag;
|
||||
bool is_using_item_click;
|
||||
eStandingPetOrder m_previous_pet_order;
|
||||
uint32 m_bot_caster_range;
|
||||
BotCastingRoles m_CastingRoles;
|
||||
|
||||
+435
-98
@@ -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
@@ -554,6 +554,7 @@ void bot_command_bind_affinity(Client *c, const Seperator *sep);
|
||||
void bot_command_bot(Client *c, const Seperator *sep);
|
||||
void bot_command_caster_range(Client* c, const Seperator* sep);
|
||||
void bot_command_charm(Client *c, const Seperator *sep);
|
||||
void bot_command_click_item(Client* c, const Seperator* sep);
|
||||
void bot_command_cure(Client *c, const Seperator *sep);
|
||||
void bot_command_defensive(Client *c, const Seperator *sep);
|
||||
void bot_command_depart(Client *c, const Seperator *sep);
|
||||
@@ -595,6 +596,7 @@ void bot_command_enforce_spell_list(Client* c, const Seperator* sep);
|
||||
void bot_command_summon_corpse(Client *c, const Seperator *sep);
|
||||
void bot_command_suspend(Client *c, const Seperator *sep);
|
||||
void bot_command_taunt(Client *c, const Seperator *sep);
|
||||
void bot_command_timer(Client* c, const Seperator* sep);
|
||||
void bot_command_track(Client *c, const Seperator *sep);
|
||||
void bot_command_view_combos(Client *c, const Seperator *sep);
|
||||
void bot_command_water_breathing(Client *c, const Seperator *sep);
|
||||
@@ -677,7 +679,7 @@ void helper_command_depart_list(Client* bot_owner, Bot* druid_bot, Bot* wizard_b
|
||||
bool helper_is_help_or_usage(const char* arg);
|
||||
bool helper_no_available_bots(Client *bot_owner, Bot *my_bot = nullptr);
|
||||
void helper_send_available_subcommands(Client *bot_owner, const char* command_simile, const std::list<const char*>& subcommand_list);
|
||||
void helper_send_usage_required_bots(Client *bot_owner, BCEnum::SpType spell_type, uint8 bot_class = NO_CLASS);
|
||||
void helper_send_usage_required_bots(Client *bot_owner, BCEnum::SpType spell_type, uint8 bot_class = Class::None);
|
||||
bool helper_spell_check_fail(STBaseEntry* local_entry);
|
||||
bool helper_spell_list_fail(Client *bot_owner, bcst_list* spell_list, BCEnum::SpType spell_type);
|
||||
#endif
|
||||
|
||||
+79
-56
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "../common/repositories/bot_data_repository.h"
|
||||
#include "../common/repositories/bot_inventories_repository.h"
|
||||
#include "../common/repositories/bot_timers_repository.h"
|
||||
|
||||
#include "zonedb.h"
|
||||
#include "bot.h"
|
||||
@@ -141,7 +142,7 @@ bool BotDatabase::LoadBotSpellCastingChances()
|
||||
if (spell_type_index >= Bot::SPELL_TYPE_COUNT)
|
||||
continue;
|
||||
uint8 class_index = Strings::ToInt(row[1]);
|
||||
if (class_index < WARRIOR || class_index > BERSERKER)
|
||||
if (class_index < Class::Warrior || class_index > Class::Berserker)
|
||||
continue;
|
||||
--class_index;
|
||||
uint8 stance_index = Strings::ToInt(row[2]);
|
||||
@@ -224,7 +225,7 @@ bool BotDatabase::QueryBotCount(const uint32 owner_id, int class_id, uint32& bot
|
||||
auto row = results.begin();
|
||||
bot_count = Strings::ToUnsignedInt(row[0]);
|
||||
|
||||
if (EQ::ValueWithin(class_id, WARRIOR, BERSERKER)) {
|
||||
if (EQ::ValueWithin(class_id, Class::Warrior, Class::Berserker)) {
|
||||
query = fmt::format(
|
||||
"SELECT COUNT(`bot_id`) FROM `bot_data` WHERE `owner_id` = {} AND `class` = {}",
|
||||
owner_id,
|
||||
@@ -917,45 +918,39 @@ bool BotDatabase::LoadTimers(Bot* bot_inst)
|
||||
if (!bot_inst)
|
||||
return false;
|
||||
|
||||
query = StringFormat(
|
||||
"SELECT"
|
||||
" IfNull(bt.`timer_id`, '0') As timer_id,"
|
||||
" IfNull(bt.`timer_value`, '0') As timer_value,"
|
||||
" IfNull(MAX(sn.`recast_time`), '0') AS MaxTimer"
|
||||
" FROM `bot_timers` bt, `spells_new` sn"
|
||||
" WHERE bt.`bot_id` = '%u' AND sn.`EndurTimerIndex` = ("
|
||||
"SELECT case"
|
||||
" WHEN timer_id > '%i' THEN timer_id - '%i'"
|
||||
" ELSE timer_id END AS timer_id"
|
||||
" FROM `bot_timers` WHERE `timer_id` = bt.`timer_id` AND `bot_id` = bt.`bot_id`" // double-check validity
|
||||
")"
|
||||
" AND sn.`classes%i` <= '%i'",
|
||||
bot_inst->GetBotID(),
|
||||
(DisciplineReuseStart - 1),
|
||||
(DisciplineReuseStart - 1),
|
||||
bot_inst->GetClass(),
|
||||
bot_inst->GetLevel()
|
||||
auto timers = BotTimersRepository::GetWhere(
|
||||
database,
|
||||
fmt::format("bot_id = {}", bot_inst->GetBotID())
|
||||
);
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
if (!results.RowCount())
|
||||
return true;
|
||||
|
||||
uint32* bot_timers = bot_inst->GetTimers();
|
||||
if (!bot_timers)
|
||||
return false;
|
||||
std::vector<BotTimer_Struct> bot_timers;
|
||||
|
||||
int timer_id = 0;
|
||||
uint32 timer_value = 0;
|
||||
uint32 max_value = 0;
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
timer_id = Strings::ToInt(row[0]) - 1;
|
||||
timer_value = Strings::ToInt(row[1]);
|
||||
max_value = Strings::ToInt(row[2]);
|
||||
BotTimer_Struct t{};
|
||||
t.timer_id = 0;
|
||||
t.timer_value = 0;
|
||||
t.recast_time = 0;
|
||||
t.is_spell = false;
|
||||
t.is_disc = false;
|
||||
t.spell_id = 0;
|
||||
t.is_item = false;
|
||||
t.item_id = 0;
|
||||
|
||||
if (timer_id >= 0 && timer_id < MaxTimer && timer_value < (Timer::GetCurrentTime() + max_value))
|
||||
bot_timers[timer_id] = timer_value;
|
||||
for (auto& timer : timers) {
|
||||
if (t.timer_value < (Timer::GetCurrentTime() + t.recast_time)) {
|
||||
t.timer_id = timer.timer_id;
|
||||
t.timer_value = timer.timer_value;
|
||||
t.recast_time = timer.recast_time;
|
||||
t.is_spell = timer.is_spell ? true : false;
|
||||
t.is_disc = timer.is_disc ? true : false;
|
||||
t.spell_id = timer.spell_id;
|
||||
t.is_item = timer.is_item ? true : false;
|
||||
t.item_id = timer.item_id;
|
||||
bot_timers.push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
if (!bot_timers.empty()) {
|
||||
bot_inst->SetBotTimers(bot_timers);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -963,26 +958,56 @@ bool BotDatabase::LoadTimers(Bot* bot_inst)
|
||||
|
||||
bool BotDatabase::SaveTimers(Bot* bot_inst)
|
||||
{
|
||||
if (!bot_inst)
|
||||
if (!bot_inst) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DeleteTimers(bot_inst->GetBotID()))
|
||||
if (!DeleteTimers(bot_inst->GetBotID())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32* bot_timers = bot_inst->GetTimers();
|
||||
if (!bot_timers)
|
||||
return false;
|
||||
std::vector<BotTimer_Struct> bot_timers = bot_inst->GetBotTimers();
|
||||
|
||||
for (int timer_index = 0; timer_index < MaxTimer; ++timer_index) {
|
||||
if (bot_timers[timer_index] <= Timer::GetCurrentTime())
|
||||
continue;
|
||||
if (bot_timers.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
query = fmt::format(
|
||||
"REPLACE INTO `bot_timers` (`bot_id`, `timer_id`, `timer_value`) VALUES ('{}', '{}', '{}')",
|
||||
bot_inst->GetBotID(), (timer_index + 1), bot_timers[timer_index]
|
||||
std::vector<BotTimersRepository::BotTimers> timers;
|
||||
|
||||
if (!bot_timers.empty()) {
|
||||
for (auto & bot_timer : bot_timers) {
|
||||
if (bot_timer.timer_value <= Timer::GetCurrentTime()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto t = BotTimersRepository::BotTimers{
|
||||
.bot_id = bot_inst->GetBotID(),
|
||||
.timer_id = bot_timer.timer_id,
|
||||
.timer_value = bot_timer.timer_value,
|
||||
.recast_time = bot_timer.recast_time,
|
||||
.is_spell = bot_timer.is_spell ? true : false,
|
||||
.is_disc = bot_timer.is_disc ? true : false,
|
||||
.spell_id = bot_timer.spell_id,
|
||||
.is_item = bot_timer.is_item ? true : false,
|
||||
.item_id = bot_timer.item_id
|
||||
};
|
||||
|
||||
timers.push_back(t);
|
||||
}
|
||||
|
||||
if (timers.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// delete existing
|
||||
BotTimersRepository::DeleteWhere(
|
||||
database,
|
||||
fmt::format("bot_id = {}", bot_inst->GetBotID())
|
||||
);
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
|
||||
// bulk insert current
|
||||
auto success = BotTimersRepository::InsertMany(database, timers);
|
||||
if (!success) {
|
||||
DeleteTimers(bot_inst->GetBotID());
|
||||
return false;
|
||||
}
|
||||
@@ -993,13 +1018,11 @@ bool BotDatabase::SaveTimers(Bot* bot_inst)
|
||||
|
||||
bool BotDatabase::DeleteTimers(const uint32 bot_id)
|
||||
{
|
||||
if (!bot_id)
|
||||
if (!bot_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
query = StringFormat("DELETE FROM `bot_timers` WHERE `bot_id` = '%u'", bot_id);
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
BotTimersRepository::DeleteWhere(database, fmt::format("bot_id = {}", bot_id));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -2517,7 +2540,7 @@ uint8 BotDatabase::GetSpellCastingChance(uint8 spell_type_index, uint8 class_ind
|
||||
{
|
||||
if (spell_type_index >= Bot::SPELL_TYPE_COUNT)
|
||||
return 0;
|
||||
if (class_index >= PLAYER_CLASS_COUNT)
|
||||
if (class_index >= Class::PLAYER_CLASS_COUNT)
|
||||
return 0;
|
||||
if (stance_index >= EQ::constants::STANCE_TYPE_COUNT)
|
||||
return 0;
|
||||
|
||||
@@ -81,4 +81,15 @@ struct BotSpells_Struct {
|
||||
uint8 bucket_comparison;
|
||||
};
|
||||
|
||||
struct BotTimer_Struct {
|
||||
uint32 timer_id;
|
||||
uint32 timer_value;
|
||||
uint32 recast_time;
|
||||
bool is_spell;
|
||||
bool is_disc;
|
||||
uint16 spell_id;
|
||||
bool is_item;
|
||||
uint32 item_id;
|
||||
};
|
||||
|
||||
#endif // BOT_STRUCTS
|
||||
|
||||
+112
-177
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -529,8 +529,8 @@ public:
|
||||
inline const std::unordered_map<uint16, Merc *> &GetMercList() { return merc_list; }
|
||||
inline const std::unordered_map<uint16, Client *> &GetClientList() { return client_list; }
|
||||
inline const std::list<Bot *> &GetBotList() { return bot_list; }
|
||||
std::vector<Bot *> GetBotListByCharacterID(uint32 character_id, uint8 class_id = NO_CLASS);
|
||||
std::vector<Bot *> GetBotListByClientName(std::string client_name, uint8 class_id = NO_CLASS);
|
||||
std::vector<Bot *> GetBotListByCharacterID(uint32 character_id, uint8 class_id = Class::None);
|
||||
std::vector<Bot *> GetBotListByClientName(std::string client_name, uint8 class_id = Class::None);
|
||||
void SignalAllBotsByOwnerCharacterID(uint32 character_id, int signal_id);
|
||||
void SignalAllBotsByOwnerName(std::string owner_name, int signal_id);
|
||||
void SignalBotByBotID(uint32 bot_id, int signal_id);
|
||||
|
||||
@@ -128,6 +128,14 @@ typedef enum {
|
||||
EVENT_UNMEMORIZE_SPELL,
|
||||
EVENT_SCRIBE_SPELL,
|
||||
EVENT_UNSCRIBE_SPELL,
|
||||
EVENT_LOOT_ADDED,
|
||||
EVENT_LDON_POINTS_GAIN,
|
||||
EVENT_LDON_POINTS_LOSS,
|
||||
EVENT_ALT_CURRENCY_GAIN,
|
||||
EVENT_ALT_CURRENCY_LOSS,
|
||||
EVENT_CRYSTAL_GAIN,
|
||||
EVENT_CRYSTAL_LOSS,
|
||||
|
||||
// Add new events before these or Lua crashes
|
||||
EVENT_SPELL_EFFECT_BOT,
|
||||
EVENT_SPELL_EFFECT_BUFF_TIC_BOT,
|
||||
|
||||
+9
-9
@@ -128,8 +128,8 @@ uint64 Client::CalcEXP(uint8 consider_level, bool ignore_modifiers) {
|
||||
|
||||
if (RuleB(Character, UseRaceClassExpBonuses)) {
|
||||
if (
|
||||
GetClass() == WARRIOR ||
|
||||
GetClass() == ROGUE ||
|
||||
GetClass() == Class::Warrior ||
|
||||
GetClass() == Class::Rogue ||
|
||||
GetBaseRace() == HALFLING
|
||||
) {
|
||||
total_modifier *= 1.05;
|
||||
@@ -295,7 +295,7 @@ void Client::CalculateStandardAAExp(uint64 &add_aaxp, uint8 conlevel, bool resex
|
||||
aatotalmod *= 1.05;
|
||||
}
|
||||
|
||||
if (GetClass() == ROGUE || GetClass() == WARRIOR) {
|
||||
if (GetClass() == Class::Rogue || GetClass() == Class::Warrior) {
|
||||
aatotalmod *= 1.05;
|
||||
}
|
||||
}
|
||||
@@ -443,7 +443,7 @@ void Client::CalculateExp(uint64 in_add_exp, uint64 &add_exp, uint64 &add_aaxp,
|
||||
totalmod *= 1.05;
|
||||
}
|
||||
|
||||
if (GetClass() == ROGUE || GetClass() == WARRIOR) {
|
||||
if (GetClass() == Class::Rogue || GetClass() == Class::Warrior) {
|
||||
totalmod *= 1.05;
|
||||
}
|
||||
}
|
||||
@@ -1051,15 +1051,15 @@ uint32 Client::GetEXPForLevel(uint16 check_level)
|
||||
if(RuleB(Character,UseOldClassExpPenalties))
|
||||
{
|
||||
float classmod = 1.0;
|
||||
if(GetClass() == PALADIN || GetClass() == SHADOWKNIGHT || GetClass() == RANGER || GetClass() == BARD) {
|
||||
if(GetClass() == Class::Paladin || GetClass() == Class::ShadowKnight || GetClass() == Class::Ranger || GetClass() == Class::Bard) {
|
||||
classmod = 1.4;
|
||||
} else if(GetClass() == MONK) {
|
||||
} else if(GetClass() == Class::Monk) {
|
||||
classmod = 1.2;
|
||||
} else if(GetClass() == WIZARD || GetClass() == ENCHANTER || GetClass() == MAGICIAN || GetClass() == NECROMANCER) {
|
||||
} else if(GetClass() == Class::Wizard || GetClass() == Class::Enchanter || GetClass() == Class::Magician || GetClass() == Class::Necromancer) {
|
||||
classmod = 1.1;
|
||||
} else if(GetClass() == ROGUE) {
|
||||
} else if(GetClass() == Class::Rogue) {
|
||||
classmod = 0.91;
|
||||
} else if(GetClass() == WARRIOR) {
|
||||
} else if(GetClass() == Class::Warrior) {
|
||||
classmod = 0.9;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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,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
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
)];
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user