mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-23 00:42:27 +00:00
Compare commits
202 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 79f250da2d | |||
| 752e6c89f3 | |||
| e962ad3a35 | |||
| 872d494bb6 | |||
| 8a48473dbc | |||
| a208801d1f | |||
| a5d8a64792 | |||
| ee1f0ea91f | |||
| 7c20a86f23 | |||
| dbe6adbed0 | |||
| d300e78b39 | |||
| 0400504adc | |||
| 5ce2889210 | |||
| cc0371c16e | |||
| 4e297f3d96 | |||
| e9f48d5fba | |||
| 00c41dda8c | |||
| 7b235a6ede | |||
| 58d5983ef1 | |||
| 7749c626f0 | |||
| a6cd0bc33a | |||
| cba95851a2 | |||
| 7f5706abcf | |||
| 44b8c9203a | |||
| afdbc0ce80 | |||
| e850d80656 | |||
| b9722c6d28 | |||
| 5a7ee28740 | |||
| e4f2aec11e | |||
| e99c8dafc5 | |||
| 936043a53c | |||
| 3c09448e90 | |||
| e09a8f8f8f | |||
| 804f0681a9 | |||
| 71c53cb18b | |||
| 176bfc8524 | |||
| 28b1abe1a7 | |||
| 3a94132749 | |||
| 5ebbbf647b | |||
| 5f482a9b30 | |||
| 91aa950304 | |||
| 613066976d | |||
| 1a556f4451 | |||
| d10145fc6f | |||
| f3002d9656 | |||
| 59c373bcff | |||
| ae8273e0b1 | |||
| 10083387b6 | |||
| 7e065ad966 | |||
| ffa968f64f | |||
| 6bf5608cf3 | |||
| 3853c4f150 | |||
| d6d4c458e7 | |||
| 26b160c59b | |||
| d107ff3069 | |||
| 220d8497dd | |||
| 645251992d | |||
| 9815f50efa | |||
| c0f57bed1f | |||
| d280d54446 | |||
| c99c5c1f1c | |||
| e45f02af95 | |||
| 323b35989c | |||
| 7f23c93ce5 | |||
| 6a7782ab8d | |||
| 5457f30659 | |||
| 652ea89dea | |||
| c79fbb99aa | |||
| 4f0e9945c6 | |||
| 4fbb98a5f7 | |||
| 8c78a19c95 | |||
| 6a77764f8b | |||
| d0ec0872b9 | |||
| 724d47432b | |||
| f26d56d6d5 | |||
| 886b321e66 | |||
| 85971590c8 | |||
| 898b1ea4d1 | |||
| d460fb3db8 | |||
| fbc5d045de | |||
| 3414d3a1ae | |||
| feed584a41 | |||
| 119b2d023f | |||
| 73acc3310c | |||
| 6da7116c66 | |||
| 26b21673ad | |||
| ef1f6adf18 | |||
| 1c2e1ea228 | |||
| 7cf66a2daa | |||
| 91c958ae63 | |||
| 8de410ebb7 | |||
| 550485ba33 | |||
| eb2b4fd9e0 | |||
| 42f439c4b7 | |||
| 294e51fca7 | |||
| 94166e0f95 | |||
| 1a1c3abc24 | |||
| 0f4f5d7046 | |||
| 8ec4afe721 | |||
| aa4536e1ef | |||
| 01a671918a | |||
| e09f28c62c | |||
| 82000949e3 | |||
| 4a154686e1 | |||
| 29dfe9d404 | |||
| 9a0c98397e | |||
| bc0795bb48 | |||
| d972183a79 | |||
| f70b4a79b2 | |||
| 7cac2e2bc3 | |||
| 2be1321aa9 | |||
| ba5bb09af7 | |||
| 5ab9b941e2 | |||
| d28f902ecc | |||
| fd862d16bb | |||
| a6e5534b64 | |||
| 225497337c | |||
| a5348e207b | |||
| c4c5256438 | |||
| b3b9899a23 | |||
| 7d1d385418 | |||
| 96cdf1b076 | |||
| 8688e9c9fa | |||
| 6a28828e08 | |||
| 8566662d56 | |||
| 298ae3e3ba | |||
| 4507b063f5 | |||
| 774e0c7faa | |||
| 8b54bb34e4 | |||
| e87b8e2682 | |||
| 2dc3ca52db | |||
| 514029a6bb | |||
| b29f398239 | |||
| e474b2a280 | |||
| d38b8a4867 | |||
| 1a5f48521d | |||
| ba427c64ba | |||
| 9d59b3def4 | |||
| a6f5bf72be | |||
| 6ff7f7aa53 | |||
| 1a2897c423 | |||
| 8b5b19ae2c | |||
| 6fa41a3b73 | |||
| 6496690123 | |||
| a11482ff23 | |||
| 4672e48fbd | |||
| 8f3cce6585 | |||
| 8d3a179ecc | |||
| 2cbcefd9a0 | |||
| ef06a0d0b6 | |||
| 1935ea60d0 | |||
| 8c7e1be344 | |||
| 9240497cbc | |||
| 0da4610249 | |||
| 26c7287997 | |||
| cece66adc6 | |||
| d29993fafa | |||
| 39c27c987d | |||
| 5470ec6293 | |||
| 1acdc6034b | |||
| e9fc80815a | |||
| a84536cd05 | |||
| 0a34809bb3 | |||
| 03847fb1ac | |||
| 8a27fce3a8 | |||
| 6a42639386 | |||
| b9214bfdee | |||
| 04fda24c8e | |||
| 446c5d90ec | |||
| 80f15ed04a | |||
| 51fb46556d | |||
| d73194c1f6 | |||
| ec1cf68ce2 | |||
| 39b39970f6 | |||
| 40edefa6f4 | |||
| 7154d5b841 | |||
| dfe43ce189 | |||
| 69d5fee471 | |||
| f1d9221b4c | |||
| fb2f901539 | |||
| 7c12c5d5ef | |||
| 7559732408 | |||
| fac0d795f2 | |||
| 3efd9c7f60 | |||
| bf8a0328b3 | |||
| 0ebb1cc54c | |||
| a111668888 | |||
| 0550fcfd3f | |||
| 293361a1f7 | |||
| 5d75b7b365 | |||
| 6400e2f8bc | |||
| 76b0183a0f | |||
| b3471c51df | |||
| b2c86f5571 | |||
| 264c6cb019 | |||
| 9bcb617f90 | |||
| f5d37a9959 | |||
| c44b82500d | |||
| 4f550fcbf3 | |||
| 1103d50733 | |||
| ddcb184183 | |||
| 90bcc5f03c |
@@ -54,3 +54,5 @@ bin/
|
||||
/Win32
|
||||
/x64
|
||||
/client_files/**/CMakeFiles/
|
||||
|
||||
.idea
|
||||
|
||||
@@ -18,16 +18,16 @@
|
||||
|**Install Count**|||
|
||||
### > Windows
|
||||
|
||||
* [Install Guide](https://eqemu.gitbook.io/server/categories/installation/server-installation-windows)
|
||||
* [Install Guide](https://docs.eqemu.io/server/installation/server-installation-windows/)
|
||||
|
||||
### > Debian/Ubuntu/CentOS/Fedora
|
||||
|
||||
* [Install Guide](https://eqemu.gitbook.io/server/categories/installation/server-installation-linux)
|
||||
* [Install Guide](https://docs.eqemu.io/server/installation/server-installation-linux/)
|
||||
|
||||
* You can use curl or wget to kick off the installer (whichever your OS has)
|
||||
> curl -O https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh install.sh && chmod 755 install.sh && ./install.sh
|
||||
|
||||
> wget --no-check-certificate https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh -O install.sh && chmod 755 install.sh && ./install.sh
|
||||
> wget --no-check-certificate https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh -O install.sh && chmod 755 install.sh && ./install.sh
|
||||
|
||||
## Supported Clients
|
||||
|
||||
@@ -56,7 +56,7 @@ forum, although pull requests will be much quicker and easier on all parties.
|
||||
|
||||
## Resources
|
||||
- [EQEmulator Forums](http://www.eqemulator.org/forums)
|
||||
- [EQEmulator Wiki](https://eqemu.gitbook.io/)
|
||||
- [EQEmulator Wiki](https://docs.eqemu.io/)
|
||||
|
||||
## Related Repositories
|
||||
* [ProjectEQ Quests](https://github.com/ProjectEQ/projecteqquests)
|
||||
|
||||
@@ -35,8 +35,12 @@ int WorldContentService::GetCurrentExpansion() const
|
||||
return current_expansion;
|
||||
}
|
||||
|
||||
void WorldContentService::SetExpansionContext()
|
||||
WorldContentService *WorldContentService::SetExpansionContext()
|
||||
{
|
||||
// do a rule manager reload until where we store expansion is changed to somewhere else
|
||||
RuleManager::Instance()->LoadRules(GetDatabase(), "default", true);
|
||||
|
||||
// pull expansion from rules
|
||||
int expansion = RuleI(Expansion, CurrentExpansion);
|
||||
if (expansion >= Expansion::Classic && expansion <= Expansion::MaxId) {
|
||||
content_service.SetCurrentExpansion(expansion);
|
||||
@@ -47,6 +51,8 @@ void WorldContentService::SetExpansionContext()
|
||||
GetCurrentExpansion(),
|
||||
GetCurrentExpansionName()
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
std::string WorldContentService::GetCurrentExpansionName()
|
||||
@@ -73,15 +79,47 @@ void WorldContentService::SetCurrentExpansion(int current_expansion)
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
const std::vector<std::string> &WorldContentService::GetContentFlags() const
|
||||
const std::vector<ContentFlagsRepository::ContentFlags> &WorldContentService::GetContentFlags() const
|
||||
{
|
||||
return content_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
std::vector<std::string> WorldContentService::GetContentFlagsEnabled()
|
||||
{
|
||||
std::vector<std::string> enabled_flags;
|
||||
|
||||
for (auto &f: GetContentFlags()) {
|
||||
if (f.enabled) {
|
||||
enabled_flags.emplace_back(f.flag_name);
|
||||
}
|
||||
}
|
||||
|
||||
return enabled_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
std::vector<std::string> WorldContentService::GetContentFlagsDisabled()
|
||||
{
|
||||
std::vector<std::string> disabled_flags;
|
||||
|
||||
for (auto &f: GetContentFlags()) {
|
||||
if (!f.enabled) {
|
||||
disabled_flags.emplace_back(f.flag_name);
|
||||
}
|
||||
}
|
||||
|
||||
return disabled_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param content_flags
|
||||
*/
|
||||
void WorldContentService::SetContentFlags(std::vector<std::string> content_flags)
|
||||
void WorldContentService::SetContentFlags(std::vector<ContentFlagsRepository::ContentFlags> content_flags)
|
||||
{
|
||||
WorldContentService::content_flags = content_flags;
|
||||
}
|
||||
@@ -90,10 +128,10 @@ void WorldContentService::SetContentFlags(std::vector<std::string> content_flags
|
||||
* @param content_flag
|
||||
* @return
|
||||
*/
|
||||
bool WorldContentService::IsContentFlagEnabled(const std::string& content_flag)
|
||||
bool WorldContentService::IsContentFlagEnabled(const std::string &content_flag)
|
||||
{
|
||||
for (auto &flag : GetContentFlags()) {
|
||||
if (flag == content_flag) {
|
||||
for (auto &f: GetContentFlags()) {
|
||||
if (f.flag_name == content_flag && f.enabled == true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -101,20 +139,58 @@ bool WorldContentService::IsContentFlagEnabled(const std::string& content_flag)
|
||||
return false;
|
||||
}
|
||||
|
||||
void WorldContentService::ReloadContentFlags(Database &db)
|
||||
void WorldContentService::ReloadContentFlags()
|
||||
{
|
||||
std::vector<std::string> set_content_flags;
|
||||
auto content_flags = ContentFlagsRepository::GetWhere(db, "enabled = 1");
|
||||
std::vector<ContentFlagsRepository::ContentFlags> set_content_flags;
|
||||
auto flags = ContentFlagsRepository::All(*GetDatabase());
|
||||
|
||||
set_content_flags.reserve(content_flags.size());
|
||||
for (auto &flags: content_flags) {
|
||||
set_content_flags.push_back(flags.flag_name);
|
||||
set_content_flags.reserve(flags.size());
|
||||
for (auto &f: flags) {
|
||||
set_content_flags.push_back(f);
|
||||
|
||||
LogInfo(
|
||||
"Loaded content flag [{}] [{}]",
|
||||
f.flag_name,
|
||||
(f.enabled ? "Enabled" : "Disabled")
|
||||
);
|
||||
}
|
||||
|
||||
LogInfo(
|
||||
"Enabled content flags [{}]",
|
||||
implode(", ", set_content_flags)
|
||||
);
|
||||
|
||||
SetContentFlags(set_content_flags);
|
||||
}
|
||||
|
||||
Database *WorldContentService::GetDatabase() const
|
||||
{
|
||||
return m_database;
|
||||
}
|
||||
|
||||
WorldContentService *WorldContentService::SetDatabase(Database *database)
|
||||
{
|
||||
WorldContentService::m_database = database;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
void WorldContentService::SetContentFlag(const std::string &content_flag_name, bool enabled)
|
||||
{
|
||||
auto flags = ContentFlagsRepository::GetWhere(
|
||||
*GetDatabase(),
|
||||
fmt::format("flag_name = '{}'", content_flag_name)
|
||||
);
|
||||
|
||||
auto f = ContentFlagsRepository::NewEntity();
|
||||
if (!flags.empty()) {
|
||||
f = flags.front();
|
||||
}
|
||||
|
||||
f.enabled = enabled ? 1 : 0;
|
||||
f.flag_name = content_flag_name;
|
||||
|
||||
if (!flags.empty()) {
|
||||
ContentFlagsRepository::UpdateOne(*GetDatabase(), f);
|
||||
}
|
||||
else {
|
||||
ContentFlagsRepository::InsertOne(*GetDatabase(), f);
|
||||
}
|
||||
|
||||
ReloadContentFlags();
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "../repositories/content_flags_repository.h"
|
||||
|
||||
class Database;
|
||||
|
||||
@@ -160,15 +161,25 @@ public:
|
||||
bool IsCurrentExpansionTheBurningLands() { return current_expansion == Expansion::ExpansionNumber::TheBurningLands; }
|
||||
bool IsCurrentExpansionTormentOfVelious() { return current_expansion == Expansion::ExpansionNumber::TormentOfVelious; }
|
||||
|
||||
const std::vector<ContentFlagsRepository::ContentFlags> &GetContentFlags() const;
|
||||
std::vector<std::string> GetContentFlagsEnabled();
|
||||
std::vector<std::string> GetContentFlagsDisabled();
|
||||
bool IsContentFlagEnabled(const std::string& content_flag);
|
||||
void SetContentFlags(std::vector<ContentFlagsRepository::ContentFlags> content_flags);
|
||||
void ReloadContentFlags();
|
||||
WorldContentService * SetExpansionContext();
|
||||
|
||||
WorldContentService * SetDatabase(Database *database);
|
||||
Database *GetDatabase() const;
|
||||
|
||||
void SetContentFlag(const std::string &content_flag_name, bool enabled);
|
||||
|
||||
private:
|
||||
int current_expansion{};
|
||||
std::vector<std::string> content_flags;
|
||||
public:
|
||||
const std::vector<std::string> &GetContentFlags() const;
|
||||
bool IsContentFlagEnabled(const std::string& content_flag);
|
||||
void SetContentFlags(std::vector<std::string> content_flags);
|
||||
void ReloadContentFlags(Database &db);
|
||||
void SetExpansionContext();
|
||||
std::vector<ContentFlagsRepository::ContentFlags> content_flags;
|
||||
|
||||
// reference to database
|
||||
Database *m_database;
|
||||
};
|
||||
|
||||
extern WorldContentService content_service;
|
||||
|
||||
+1
-1
@@ -716,7 +716,7 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
|
||||
/* HoTT Ability */
|
||||
if(RuleB(Character, GrantHoTTOnCreate))
|
||||
{
|
||||
query = StringFormat("INSERT INTO `character_leadership_abilities` (id, slot, rank) VALUES (%u, %i, %i)", character_id, 14, 1);
|
||||
query = StringFormat("INSERT INTO `character_leadership_abilities` (id, slot, `rank`) VALUES (%u, %i, %i)", character_id, 14, 1);
|
||||
results = QueryDatabase(query);
|
||||
}
|
||||
|
||||
|
||||
@@ -1452,7 +1452,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
for (i = 0; i < MAX_LEADERSHIP_AA_ARRAY; i++){
|
||||
if (pp->leader_abilities.ranks[i] > 0 && pp->leader_abilities.ranks[i] < 6){
|
||||
if (first_entry != 1){
|
||||
rquery = StringFormat("REPLACE INTO `character_leadership_abilities` (id, slot, rank) VALUES (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]);
|
||||
rquery = StringFormat("REPLACE INTO `character_leadership_abilities` (id, slot, `rank`) VALUES (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]);
|
||||
first_entry = 1;
|
||||
}
|
||||
rquery = rquery + StringFormat(", (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]);
|
||||
|
||||
@@ -82,7 +82,6 @@ namespace DatabaseSchema {
|
||||
{"player_titlesets", "char_id"},
|
||||
{"quest_globals", "charid"},
|
||||
{"timers", "char_id"},
|
||||
{"titles", "char_id"},
|
||||
{"trader", "char_id"},
|
||||
{"zone_flags", "charID"}
|
||||
};
|
||||
@@ -158,7 +157,6 @@ namespace DatabaseSchema {
|
||||
"spell_buckets",
|
||||
"spell_globals",
|
||||
"timers",
|
||||
"titles",
|
||||
"trader",
|
||||
"trader_audit",
|
||||
"zone_flags"
|
||||
@@ -270,6 +268,7 @@ namespace DatabaseSchema {
|
||||
"perl_event_export_settings",
|
||||
"profanity_list",
|
||||
"rule_sets",
|
||||
"titles",
|
||||
"rule_values",
|
||||
"variables",
|
||||
};
|
||||
|
||||
+142
-2
@@ -19,6 +19,8 @@
|
||||
|
||||
#include "emu_constants.h"
|
||||
#include "languages.h"
|
||||
#include "data_verification.h"
|
||||
#include "bodytypes.h"
|
||||
|
||||
|
||||
int16 EQ::invtype::GetInvTypeSize(int16 inv_type) {
|
||||
@@ -148,8 +150,9 @@ const char *EQ::constants::GetStanceName(StanceType stance_type) {
|
||||
}
|
||||
|
||||
int EQ::constants::ConvertStanceTypeToIndex(StanceType stance_type) {
|
||||
if (stance_type >= EQ::constants::stancePassive && stance_type <= EQ::constants::stanceBurnAE)
|
||||
if (EQ::ValueWithin(stance_type, EQ::constants::stancePassive, EQ::constants::stanceBurnAE)) {
|
||||
return (stance_type - EQ::constants::stancePassive);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -191,9 +194,146 @@ const std::map<int, std::string>& EQ::constants::GetLanguageMap()
|
||||
|
||||
std::string EQ::constants::GetLanguageName(int language_id)
|
||||
{
|
||||
if (language_id >= LANG_COMMON_TONGUE && language_id <= LANG_UNKNOWN) {
|
||||
if (EQ::ValueWithin(language_id, LANG_COMMON_TONGUE, LANG_UNKNOWN)) {
|
||||
auto languages = EQ::constants::GetLanguageMap();
|
||||
return languages[language_id];
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::map<uint32, std::string>& EQ::constants::GetLDoNThemeMap()
|
||||
{
|
||||
static const std::map<uint32, std::string> ldon_theme_map = {
|
||||
{ LDoNThemes::Unused, "Unused" },
|
||||
{ LDoNThemes::GUK, "Deepest Guk" },
|
||||
{ LDoNThemes::MIR, "Miragul's Menagerie" },
|
||||
{ LDoNThemes::MMC, "Mistmoore Catacombs" },
|
||||
{ LDoNThemes::RUJ, "Rujarkian Hills" },
|
||||
{ LDoNThemes::TAK, "Takish-Hiz" },
|
||||
};
|
||||
return ldon_theme_map;
|
||||
}
|
||||
|
||||
std::string EQ::constants::GetLDoNThemeName(uint32 theme_id)
|
||||
{
|
||||
if (EQ::ValueWithin(theme_id, LDoNThemes::Unused, LDoNThemes::TAK)) {
|
||||
auto ldon_themes = EQ::constants::GetLDoNThemeMap();
|
||||
return ldon_themes[theme_id];
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::map<uint8, std::string>& EQ::constants::GetFlyModeMap()
|
||||
{
|
||||
static const std::map<uint8, std::string> flymode_map = {
|
||||
{ EQ::constants::GravityBehavior::Ground, "Ground" },
|
||||
{ EQ::constants::GravityBehavior::Flying, "Flying" },
|
||||
{ EQ::constants::GravityBehavior::Levitating, "Levitating" },
|
||||
{ EQ::constants::GravityBehavior::Water, "Water" },
|
||||
{ EQ::constants::GravityBehavior::Floating, "Floating" },
|
||||
{ EQ::constants::GravityBehavior::LevitateWhileRunning, "Levitating While Running" },
|
||||
};
|
||||
return flymode_map;
|
||||
}
|
||||
|
||||
std::string EQ::constants::GetFlyModeName(uint8 flymode_id)
|
||||
{
|
||||
if (EQ::ValueWithin(flymode_id, GravityBehavior::Ground, GravityBehavior::LevitateWhileRunning)) {
|
||||
auto flymodes = EQ::constants::GetFlyModeMap();
|
||||
return flymodes[flymode_id];
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::map<bodyType, std::string>& EQ::constants::GetBodyTypeMap()
|
||||
{
|
||||
static const std::map<bodyType, std::string> bodytype_map = {
|
||||
{ BT_Humanoid, "Humanoid" },
|
||||
{ BT_Lycanthrope, "Lycanthrope" },
|
||||
{ BT_Undead, "Undead" },
|
||||
{ BT_Giant, "Giant" },
|
||||
{ BT_Construct, "Construct" },
|
||||
{ BT_Extraplanar, "Extraplanar" },
|
||||
{ BT_Magical, "Magical" },
|
||||
{ BT_SummonedUndead, "Summoned Undead" },
|
||||
{ BT_RaidGiant, "Raid Giant" },
|
||||
{ BT_RaidColdain, "Raid Coldain" },
|
||||
{ BT_NoTarget, "Untargetable" },
|
||||
{ BT_Vampire, "Vampire" },
|
||||
{ BT_Atenha_Ra, "Aten Ha Ra" },
|
||||
{ BT_Greater_Akheva, "Greater Akheva" },
|
||||
{ BT_Khati_Sha, "Khati Sha" },
|
||||
{ BT_Seru, "Seru" },
|
||||
{ BT_Grieg_Veneficus, "Grieg Veneficus" },
|
||||
{ BT_Draz_Nurakk, "Draz Nurakk" },
|
||||
{ BT_Zek, "Zek" },
|
||||
{ BT_Luggald, "Luggald" },
|
||||
{ BT_Animal, "Animal" },
|
||||
{ BT_Insect, "Insect" },
|
||||
{ BT_Monster, "Monster" },
|
||||
{ BT_Summoned, "Summoned" },
|
||||
{ BT_Plant, "Plant" },
|
||||
{ BT_Dragon, "Dragon" },
|
||||
{ BT_Summoned2, "Summoned 2" },
|
||||
{ BT_Summoned3, "Summoned 3" },
|
||||
{ BT_Dragon2, "Dragon 2" },
|
||||
{ BT_VeliousDragon, "Velious Dragon" },
|
||||
{ BT_Familiar, "Familiar" },
|
||||
{ BT_Dragon3, "Dragon 3" },
|
||||
{ BT_Boxes, "Boxes" },
|
||||
{ BT_Muramite, "Muramite" },
|
||||
{ BT_NoTarget2, "Untargetable 2" },
|
||||
{ BT_SwarmPet, "Swarm Pet" },
|
||||
{ BT_MonsterSummon, "Monster Summon" },
|
||||
{ BT_InvisMan, "Invisible Man" },
|
||||
{ BT_Special, "Special" },
|
||||
};
|
||||
return bodytype_map;
|
||||
}
|
||||
|
||||
std::string EQ::constants::GetBodyTypeName(bodyType bodytype_id)
|
||||
{
|
||||
auto bodytypes = EQ::constants::GetBodyTypeMap();
|
||||
if (!bodytypes[bodytype_id].empty()) {
|
||||
return bodytypes[bodytype_id];
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::map<uint8, std::string>& EQ::constants::GetAccountStatusMap()
|
||||
{
|
||||
static const std::map<uint8, std::string> account_status_map = {
|
||||
{ AccountStatus::Player, "Player" },
|
||||
{ AccountStatus::Steward, "Steward" },
|
||||
{ AccountStatus::ApprenticeGuide, "Apprentice Guide" },
|
||||
{ AccountStatus::Guide, "Guide" },
|
||||
{ AccountStatus::QuestTroupe, "Quest Troupe" },
|
||||
{ AccountStatus::SeniorGuide, "Senior Guide" },
|
||||
{ AccountStatus::GMTester, "GM Tester" },
|
||||
{ AccountStatus::EQSupport, "EQ Support" },
|
||||
{ AccountStatus::GMStaff, "GM Staff" },
|
||||
{ AccountStatus::GMAdmin, "GM Admin" },
|
||||
{ AccountStatus::GMLeadAdmin, "GM Lead Admin" },
|
||||
{ AccountStatus::QuestMaster, "Quest Master" },
|
||||
{ AccountStatus::GMAreas, "GM Areas" },
|
||||
{ AccountStatus::GMCoder, "GM Coder" },
|
||||
{ AccountStatus::GMMgmt, "GM Mgmt" },
|
||||
{ AccountStatus::GMImpossible, "GM Impossible" },
|
||||
{ AccountStatus::Max, "GM Max" }
|
||||
};
|
||||
return account_status_map;
|
||||
}
|
||||
|
||||
std::string EQ::constants::GetAccountStatusName(uint8 account_status)
|
||||
{
|
||||
auto account_statuses = EQ::constants::GetAccountStatusMap();
|
||||
std::string status_name;
|
||||
for (auto status_level = account_statuses.rbegin(); status_level != account_statuses.rend(); ++status_level) {
|
||||
if (account_status >= status_level->first) {
|
||||
status_name = status_level->second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return status_name;
|
||||
}
|
||||
|
||||
+61
-7
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "eq_limits.h"
|
||||
#include "emu_versions.h"
|
||||
#include "bodytypes.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -220,12 +221,33 @@ namespace EQ
|
||||
stanceBurnAE
|
||||
};
|
||||
|
||||
enum GravityBehavior : uint8 {
|
||||
Ground,
|
||||
Flying,
|
||||
Levitating,
|
||||
Water,
|
||||
Floating,
|
||||
LevitateWhileRunning
|
||||
};
|
||||
|
||||
const char *GetStanceName(StanceType stance_type);
|
||||
int ConvertStanceTypeToIndex(StanceType stance_type);
|
||||
|
||||
extern const std::map<int, std::string>& GetLanguageMap();
|
||||
std::string GetLanguageName(int language_id);
|
||||
|
||||
extern const std::map<uint32, std::string>& GetLDoNThemeMap();
|
||||
std::string GetLDoNThemeName(uint32 theme_id);
|
||||
|
||||
extern const std::map<uint8, std::string>& GetFlyModeMap();
|
||||
std::string GetFlyModeName(uint8 flymode_id);
|
||||
|
||||
extern const std::map<bodyType, std::string>& GetBodyTypeMap();
|
||||
std::string GetBodyTypeName(bodyType bodytype_id);
|
||||
|
||||
extern const std::map<uint8, std::string>& GetAccountStatusMap();
|
||||
std::string GetAccountStatusName(uint8 account_status);
|
||||
|
||||
const int STANCE_TYPE_FIRST = stancePassive;
|
||||
const int STANCE_TYPE_LAST = stanceBurnAE;
|
||||
const int STANCE_TYPE_COUNT = stanceBurnAE;
|
||||
@@ -328,13 +350,45 @@ namespace EQ
|
||||
Guild
|
||||
};
|
||||
}; // namespace consent
|
||||
|
||||
} /*EQEmu*/
|
||||
|
||||
enum ServerLockType : int {
|
||||
List,
|
||||
Lock,
|
||||
Unlock
|
||||
};
|
||||
|
||||
enum AccountStatus : uint8 {
|
||||
Player = 0,
|
||||
Steward = 10,
|
||||
ApprenticeGuide = 20,
|
||||
Guide = 50,
|
||||
QuestTroupe = 80,
|
||||
SeniorGuide = 81,
|
||||
GMTester = 85,
|
||||
EQSupport = 90,
|
||||
GMStaff = 95,
|
||||
GMAdmin = 100,
|
||||
GMLeadAdmin = 150,
|
||||
QuestMaster = 160,
|
||||
GMAreas = 170,
|
||||
GMCoder = 180,
|
||||
GMMgmt = 200,
|
||||
GMImpossible = 250,
|
||||
Max = 255
|
||||
};
|
||||
|
||||
enum Invisibility : uint8 {
|
||||
Visible,
|
||||
Invisible,
|
||||
Special = 255
|
||||
};
|
||||
|
||||
enum AugmentActions : int {
|
||||
Insert,
|
||||
Remove,
|
||||
Swap,
|
||||
Destroy
|
||||
};
|
||||
|
||||
#endif /*COMMON_EMU_CONSTANTS_H*/
|
||||
|
||||
/* hack list to prevent circular references
|
||||
|
||||
eq_limits.h:EQ::inventory::LookupEntry::InventoryTypeSize[n];
|
||||
|
||||
*/
|
||||
|
||||
+2
-2
@@ -129,8 +129,8 @@ N(OP_DisciplineTimer),
|
||||
N(OP_DisciplineUpdate),
|
||||
N(OP_DiscordMerchantInventory),
|
||||
N(OP_DoGroupLeadershipAbility),
|
||||
N(OP_DuelResponse),
|
||||
N(OP_DuelResponse2),
|
||||
N(OP_DuelDecline),
|
||||
N(OP_DuelAccept),
|
||||
N(OP_DumpName),
|
||||
N(OP_Dye),
|
||||
N(OP_DynamicWall),
|
||||
|
||||
@@ -448,6 +448,7 @@ struct ManaChange_Struct
|
||||
/*08*/ uint32 spell_id;
|
||||
/*12*/ uint8 keepcasting; // won't stop the cast. Change mana while casting?
|
||||
/*13*/ uint8 padding[3]; // client doesn't read it, garbage data seems like
|
||||
/*16*/ int32 slot; // -1 normal, otherwise clear ETA and GCD
|
||||
};
|
||||
|
||||
struct SwapSpell_Struct
|
||||
|
||||
+22
-22
@@ -20,31 +20,31 @@
|
||||
#include "races.h"
|
||||
#include "rulesys.h"
|
||||
|
||||
const char *FactionValueToString(FACTION_VALUE fv)
|
||||
const char *FactionValueToString(FACTION_VALUE faction_value)
|
||||
{
|
||||
switch (fv) {
|
||||
switch (faction_value) {
|
||||
case FACTION_ALLY:
|
||||
return ("Ally");
|
||||
return "Ally";
|
||||
case FACTION_WARMLY:
|
||||
return ("Warmly");
|
||||
return "Warmly";
|
||||
case FACTION_KINDLY:
|
||||
return ("Kindly");
|
||||
case FACTION_AMIABLE:
|
||||
return ("Amiable");
|
||||
case FACTION_INDIFFERENT:
|
||||
return ("Indifferent");
|
||||
case FACTION_APPREHENSIVE:
|
||||
return ("Apprehensive");
|
||||
case FACTION_DUBIOUS:
|
||||
return ("Dubious");
|
||||
case FACTION_THREATENLY:
|
||||
return ("Threatenly");
|
||||
return "Kindly";
|
||||
case FACTION_AMIABLY:
|
||||
return "Amiably";
|
||||
case FACTION_INDIFFERENTLY:
|
||||
return "Indifferently";
|
||||
case FACTION_APPREHENSIVELY:
|
||||
return "Apprehensively";
|
||||
case FACTION_DUBIOUSLY:
|
||||
return "Dubiously";
|
||||
case FACTION_THREATENINGLY:
|
||||
return "Threateningly";
|
||||
case FACTION_SCOWLS:
|
||||
return ("Scowls, ready to attack.");
|
||||
return "Scowls";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ("Unknown Faction Con");
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
|
||||
@@ -70,19 +70,19 @@ FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value)
|
||||
return FACTION_KINDLY;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, AmiablyFactionMinimum)) {
|
||||
return FACTION_AMIABLE;
|
||||
return FACTION_AMIABLY;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, IndifferentlyFactionMinimum)) {
|
||||
return FACTION_INDIFFERENT;
|
||||
return FACTION_INDIFFERENTLY;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, ApprehensivelyFactionMinimum)) {
|
||||
return FACTION_APPREHENSIVE;
|
||||
return FACTION_APPREHENSIVELY;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, DubiouslyFactionMinimum)) {
|
||||
return FACTION_DUBIOUS;
|
||||
return FACTION_DUBIOUSLY;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, ThreateninglyFactionMinimum)) {
|
||||
return FACTION_THREATENLY;
|
||||
return FACTION_THREATENINGLY;
|
||||
}
|
||||
return FACTION_SCOWLS;
|
||||
}
|
||||
|
||||
+6
-6
@@ -27,13 +27,13 @@ enum FACTION_VALUE {
|
||||
FACTION_ALLY = 1,
|
||||
FACTION_WARMLY = 2,
|
||||
FACTION_KINDLY = 3,
|
||||
FACTION_AMIABLE = 4,
|
||||
FACTION_AMIABLY = 4,
|
||||
|
||||
FACTION_INDIFFERENT = 5,
|
||||
FACTION_INDIFFERENTLY = 5,
|
||||
|
||||
FACTION_APPREHENSIVE = 6,
|
||||
FACTION_DUBIOUS = 7,
|
||||
FACTION_THREATENLY = 8,
|
||||
FACTION_APPREHENSIVELY = 6,
|
||||
FACTION_DUBIOUSLY = 7,
|
||||
FACTION_THREATENINGLY = 8,
|
||||
FACTION_SCOWLS = 9
|
||||
};
|
||||
|
||||
@@ -75,6 +75,6 @@ struct NPCFaction
|
||||
uint8 temp;
|
||||
};
|
||||
|
||||
const char *FactionValueToString(FACTION_VALUE fv);
|
||||
const char *FactionValueToString(FACTION_VALUE faction_value);
|
||||
FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value);
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -204,7 +204,7 @@ enum { //some random constants
|
||||
#define MIN_LEVEL_ALCHEMY 25
|
||||
|
||||
//chance ratio that a
|
||||
#define THREATENLY_ARRGO_CHANCE 32 // 32/128 (25%) chance that a mob will arrgo on con Threatenly
|
||||
#define THREATENINGLY_AGGRO_CHANCE 32 // 32/128 (25%) chance that a mob will arrgo on con Threatenly
|
||||
|
||||
//max factions per npc faction list
|
||||
#define MAX_NPC_FACTIONS 20
|
||||
|
||||
@@ -64,4 +64,9 @@ void FileUtil::mkdir(const std::string& directory_name)
|
||||
}
|
||||
::mkdir(directory_name.c_str(), 0755);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool file_exists(const std::string& name) {
|
||||
std::ifstream f(name.c_str());
|
||||
return f.good();
|
||||
}
|
||||
|
||||
@@ -28,5 +28,6 @@ public:
|
||||
static void mkdir(const std::string& directory_name);
|
||||
};
|
||||
|
||||
bool file_exists(const std::string& name);
|
||||
|
||||
#endif //EQEMU_FILE_UTIL_H
|
||||
|
||||
+66
-6
@@ -63,7 +63,7 @@ bool BaseGuildManager::LoadGuilds() {
|
||||
for (auto row=results.begin();row!=results.end();++row)
|
||||
_CreateGuild(atoi(row[0]), row[1], atoi(row[2]), atoi(row[3]), row[4], row[5], row[6], row[7]);
|
||||
|
||||
query = "SELECT guild_id,rank,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace FROM guild_ranks";
|
||||
query = "SELECT guild_id,`rank`,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace FROM guild_ranks";
|
||||
results = m_db->QueryDatabase(query);
|
||||
|
||||
if (!results.Success())
|
||||
@@ -131,7 +131,7 @@ bool BaseGuildManager::RefreshGuild(uint32 guild_id) {
|
||||
|
||||
info = _CreateGuild(guild_id, row[0], atoi(row[1]), atoi(row[2]), row[3], row[4], row[5], row[6]);
|
||||
|
||||
query = StringFormat("SELECT guild_id, rank, title, can_hear, can_speak, can_invite, can_remove, can_promote, can_demote, can_motd, can_warpeace "
|
||||
query = StringFormat("SELECT guild_id, `rank`, title, can_hear, can_speak, can_invite, can_remove, can_promote, can_demote, can_motd, can_warpeace "
|
||||
"FROM guild_ranks WHERE guild_id=%lu", (unsigned long)guild_id);
|
||||
results = m_db->QueryDatabase(query);
|
||||
|
||||
@@ -268,7 +268,7 @@ bool BaseGuildManager::_StoreGuildDB(uint32 guild_id) {
|
||||
m_db->DoEscapeString(title_esc, rankInfo.name.c_str(), rankInfo.name.length());
|
||||
|
||||
query = StringFormat("INSERT INTO guild_ranks "
|
||||
"(guild_id,rank,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace)"
|
||||
"(guild_id,`rank`,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace)"
|
||||
" VALUES(%d,%d,'%s',%d,%d,%d,%d,%d,%d,%d,%d)",
|
||||
guild_id, rank, title_esc,
|
||||
rankInfo.permissions[GUILD_HEAR],
|
||||
@@ -738,7 +738,7 @@ bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank) {
|
||||
std::string query;
|
||||
|
||||
if(guild_id != GUILD_NONE) {
|
||||
query = StringFormat("REPLACE INTO guild_members (char_id,guild_id,rank,public_note) VALUES(%d,%d,%d,'')", charid, guild_id, rank);
|
||||
query = StringFormat("REPLACE INTO guild_members (char_id,guild_id,`rank`,public_note) VALUES(%d,%d,%d,'')", charid, guild_id, rank);
|
||||
auto results = m_db->QueryDatabase(query);
|
||||
|
||||
if (!results.Success()) {
|
||||
@@ -758,7 +758,7 @@ bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank) {
|
||||
}
|
||||
|
||||
bool BaseGuildManager::DBSetGuildRank(uint32 charid, uint8 rank) {
|
||||
std::string query = StringFormat("UPDATE guild_members SET rank=%d WHERE char_id=%d", rank, charid);
|
||||
std::string query = StringFormat("UPDATE guild_members SET `rank`=%d WHERE char_id=%d", rank, charid);
|
||||
return(QueryWithLogging(query, "setting a guild member's rank"));
|
||||
}
|
||||
|
||||
@@ -1208,7 +1208,7 @@ BaseGuildManager::RankInfo::RankInfo() {
|
||||
|
||||
BaseGuildManager::GuildInfo::GuildInfo() {
|
||||
leader_char_id = 0;
|
||||
minstatus = 0;
|
||||
minstatus = AccountStatus::Player;
|
||||
}
|
||||
|
||||
uint32 BaseGuildManager::DoesAccountContainAGuildLeader(uint32 AccountID)
|
||||
@@ -1225,6 +1225,66 @@ uint32 BaseGuildManager::DoesAccountContainAGuildLeader(uint32 AccountID)
|
||||
return results.RowCount();
|
||||
}
|
||||
|
||||
std::string BaseGuildManager::GetGuildNameByID(uint32 guild_id) const {
|
||||
if(guild_id == GUILD_NONE) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::map<uint32, GuildInfo *>::const_iterator res;
|
||||
res = m_guilds.find(guild_id);
|
||||
if(res == m_guilds.end()) {
|
||||
return "Invalid Guild";
|
||||
}
|
||||
|
||||
return res->second->name;
|
||||
}
|
||||
|
||||
std::string BaseGuildManager::GetGuildRankName(uint32 guild_id, uint8 rank) const
|
||||
{
|
||||
if(rank > GUILD_MAX_RANK) {
|
||||
return "Invalid Rank";
|
||||
}
|
||||
|
||||
std::map<uint32, GuildInfo *>::const_iterator res;
|
||||
res = m_guilds.find(guild_id);
|
||||
if(res == m_guilds.end()) {
|
||||
return "Invalid Guild Rank";
|
||||
}
|
||||
|
||||
return res->second->ranks[rank].name;
|
||||
}
|
||||
|
||||
uint32 BaseGuildManager::GetGuildIDByCharacterID(uint32 character_id)
|
||||
{
|
||||
if(!m_db) {
|
||||
return GUILD_NONE;
|
||||
}
|
||||
|
||||
std::string query = fmt::format(
|
||||
"SELECT `guild_id` FROM `guild_members` WHERE char_id = {} LIMIT 1",
|
||||
character_id
|
||||
);
|
||||
auto results = m_db->QueryDatabase(query);
|
||||
if(!results.Success() || !results.RowCount()) {
|
||||
return GUILD_NONE;
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
auto guild_id = std::stoul(row[0]);
|
||||
return guild_id;
|
||||
}
|
||||
|
||||
bool BaseGuildManager::IsCharacterInGuild(uint32 character_id, uint32 guild_id)
|
||||
{
|
||||
auto current_guild_id = GetGuildIDByCharacterID(character_id);
|
||||
|
||||
if (current_guild_id == GUILD_NONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (guild_id && current_guild_id != guild_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -76,8 +76,12 @@ class BaseGuildManager
|
||||
bool GetGuildChannel(uint32 GuildID, char *ChannelBuffer) const;
|
||||
const char *GetRankName(uint32 guild_id, uint8 rank) const;
|
||||
const char *GetGuildName(uint32 guild_id) const;
|
||||
std::string GetGuildNameByID(uint32 guild_id) const;
|
||||
std::string GetGuildRankName(uint32 guild_id, uint8 rank) const;
|
||||
bool IsCharacterInGuild(uint32 character_id, uint32 guild_id = 0);
|
||||
bool GetGuildNameByID(uint32 guild_id, std::string &into) const;
|
||||
uint32 GetGuildIDByName(const char *GuildName);
|
||||
uint32 GetGuildIDByCharacterID(uint32 character_id);
|
||||
bool IsGuildLeader(uint32 guild_id, uint32 char_id) const;
|
||||
uint8 GetDisplayedRank(uint32 guild_id, uint8 rank, uint32 char_id) const;
|
||||
bool CheckGMStatus(uint32 guild_id, uint8 status) const;
|
||||
|
||||
@@ -399,7 +399,7 @@ bool EQ::InventoryProfile::SwapItem(
|
||||
}
|
||||
|
||||
// Remove item from inventory (with memory delete)
|
||||
bool EQ::InventoryProfile::DeleteItem(int16 slot_id, uint8 quantity) {
|
||||
bool EQ::InventoryProfile::DeleteItem(int16 slot_id, int16 quantity) {
|
||||
// Pop item out of inventory map (or queue)
|
||||
ItemInstance *item_to_delete = PopItem(slot_id);
|
||||
|
||||
@@ -590,6 +590,68 @@ bool EQ::InventoryProfile::HasSpaceForItem(const ItemData *ItemToTry, int16 Quan
|
||||
// Checks that user has at least 'quantity' number of items in a given inventory slot
|
||||
// Returns first slot it was found in, or SLOT_INVALID if not found
|
||||
|
||||
bool EQ::InventoryProfile::HasAugmentEquippedByID(uint32 item_id)
|
||||
{
|
||||
bool has_equipped = false;
|
||||
ItemInstance* item = nullptr;
|
||||
|
||||
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
|
||||
item = GetItem(slot_id);
|
||||
if (item && item->ContainsAugmentByID(item_id)) {
|
||||
has_equipped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return has_equipped;
|
||||
}
|
||||
|
||||
int EQ::InventoryProfile::CountAugmentEquippedByID(uint32 item_id)
|
||||
{
|
||||
int quantity = 0;
|
||||
ItemInstance* item = nullptr;
|
||||
|
||||
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
|
||||
item = GetItem(slot_id);
|
||||
if (item && item->ContainsAugmentByID(item_id)) {
|
||||
quantity += item->CountAugmentByID(item_id);
|
||||
}
|
||||
}
|
||||
|
||||
return quantity;
|
||||
}
|
||||
|
||||
bool EQ::InventoryProfile::HasItemEquippedByID(uint32 item_id)
|
||||
{
|
||||
bool has_equipped = false;
|
||||
ItemInstance* item = nullptr;
|
||||
|
||||
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
|
||||
item = GetItem(slot_id);
|
||||
if (item && item->GetID() == item_id) {
|
||||
has_equipped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return has_equipped;
|
||||
}
|
||||
|
||||
int EQ::InventoryProfile::CountItemEquippedByID(uint32 item_id)
|
||||
{
|
||||
int quantity = 0;
|
||||
ItemInstance* item = nullptr;
|
||||
|
||||
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
|
||||
item = GetItem(slot_id);
|
||||
if (item && item->GetID() == item_id) {
|
||||
quantity += item->IsStackable() ? item->GetCharges() : 1;
|
||||
}
|
||||
}
|
||||
|
||||
return quantity;
|
||||
}
|
||||
|
||||
//This function has a flaw in that it only returns the last stack that it looked at
|
||||
//when quantity is greater than 1 and not all of quantity can be found in 1 stack.
|
||||
int16 EQ::InventoryProfile::HasItem(uint32 item_id, uint8 quantity, uint8 where)
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace EQ
|
||||
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = 0, uint8 class_id = 0, uint16 deity_id = 0, uint8 level = 0);
|
||||
|
||||
// Remove item from inventory
|
||||
bool DeleteItem(int16 slot_id, uint8 quantity = 0);
|
||||
bool DeleteItem(int16 slot_id, int16 quantity = 0);
|
||||
|
||||
// Checks All items in a bag for No Drop
|
||||
bool CheckNoDrop(int16 slot_id, bool recurse = true);
|
||||
@@ -140,6 +140,18 @@ namespace EQ
|
||||
// Remove item from inventory (and take control of memory)
|
||||
ItemInstance* PopItem(int16 slot_id);
|
||||
|
||||
// Check if player has a specific item equipped by Item ID
|
||||
bool HasItemEquippedByID(uint32 item_id);
|
||||
|
||||
// Check how many of a specific item the player has equipped by Item ID
|
||||
int CountItemEquippedByID(uint32 item_id);
|
||||
|
||||
// Check if player has a specific augment equipped by Item ID
|
||||
bool HasAugmentEquippedByID(uint32 item_id);
|
||||
|
||||
// Check how many of a specific augment the player has equipped by Item ID
|
||||
int CountAugmentEquippedByID(uint32 item_id);
|
||||
|
||||
// Check whether there is space for the specified number of the specified item.
|
||||
bool HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity);
|
||||
|
||||
|
||||
@@ -689,6 +689,45 @@ bool EQ::ItemInstance::IsAugmented()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQ::ItemInstance::ContainsAugmentByID(uint32 item_id)
|
||||
{
|
||||
if (!m_item || !m_item->IsClassCommon()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!item_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint8 augment_slot = invaug::SOCKET_BEGIN; augment_slot <= invaug::SOCKET_END; ++augment_slot) {
|
||||
if (GetAugmentItemID(augment_slot) == item_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int EQ::ItemInstance::CountAugmentByID(uint32 item_id)
|
||||
{
|
||||
int quantity = 0;
|
||||
if (!m_item || !m_item->IsClassCommon()) {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
if (!item_id) {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
for (uint8 augment_slot = invaug::SOCKET_BEGIN; augment_slot <= invaug::SOCKET_END; ++augment_slot) {
|
||||
if (GetAugmentItemID(augment_slot) == item_id) {
|
||||
quantity++;
|
||||
}
|
||||
}
|
||||
|
||||
return quantity;
|
||||
}
|
||||
|
||||
// Has attack/delay?
|
||||
bool EQ::ItemInstance::IsWeapon() const
|
||||
{
|
||||
@@ -1706,4 +1745,4 @@ EvolveInfo::EvolveInfo(uint32 first, uint8 max, bool allkills, uint32 L2, uint32
|
||||
|
||||
EvolveInfo::~EvolveInfo() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -132,6 +132,8 @@ namespace EQ
|
||||
void DeleteAugment(uint8 slot);
|
||||
ItemInstance* RemoveAugment(uint8 index);
|
||||
bool IsAugmented();
|
||||
bool ContainsAugmentByID(uint32 item_id);
|
||||
int CountAugmentByID(uint32 item_id);
|
||||
ItemInstance* GetOrnamentationAug(int32 ornamentationAugtype) const;
|
||||
bool UpdateOrnamentationInfo();
|
||||
static bool CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll = false);
|
||||
|
||||
@@ -15,7 +15,7 @@ EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent,
|
||||
memset(m_line, 0, MaxConsoleLineLength);
|
||||
m_accept_messages = false;
|
||||
m_user_id = 0;
|
||||
m_admin = 0;
|
||||
m_admin = AccountStatus::Player;
|
||||
|
||||
m_connection->OnRead(std::bind(&ConsoleServerConnection::OnRead, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
m_connection->OnDisconnect(std::bind(&ConsoleServerConnection::OnDisconnect, this, std::placeholders::_1));
|
||||
@@ -29,7 +29,7 @@ EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent,
|
||||
if (addr.find("127.0.0.1") != std::string::npos || addr.find("::0") != std::string::npos) {
|
||||
SendLine("Connection established from localhost, assuming admin");
|
||||
m_status = ConsoleStatusLoggedIn;
|
||||
m_admin = 255;
|
||||
m_admin = AccountStatus::Max;
|
||||
SendPrompt();
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include <array>
|
||||
#include "../emu_constants.h"
|
||||
|
||||
struct MethodHandlerEntry
|
||||
{
|
||||
@@ -174,13 +175,13 @@ Json::Value EQ::Net::WebsocketServer::Login(WebsocketServerConnection *connectio
|
||||
auto r = _impl->login_handler(connection, user, pass);
|
||||
|
||||
if (r.logged_in) {
|
||||
connection->SetAuthorized(true, r.account_name, r.account_id, 255);
|
||||
connection->SetAuthorized(true, r.account_name, r.account_id, AccountStatus::Max);
|
||||
ret["status"] = "Ok";
|
||||
}
|
||||
else if (user == "admin" && (connection->RemoteIP() == "127.0.0.1" || connection->RemoteIP() == "::")) {
|
||||
r.logged_in = true;
|
||||
r.account_id = 0;
|
||||
connection->SetAuthorized(true, r.account_name, r.account_id, 255);
|
||||
connection->SetAuthorized(true, r.account_name, r.account_id, AccountStatus::Max);
|
||||
ret["status"] = "Ok";
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -115,8 +115,8 @@ IN(OP_GMTraining, GMTrainee_Struct);
|
||||
IN(OP_GMEndTraining, GMTrainEnd_Struct);
|
||||
IN(OP_GMTrainSkill, GMSkillChange_Struct);
|
||||
IN(OP_RequestDuel, Duel_Struct);
|
||||
IN(OP_DuelResponse, DuelResponse_Struct);
|
||||
IN(OP_DuelResponse2, Duel_Struct);
|
||||
IN(OP_DuelDecline, DuelResponse_Struct);
|
||||
IN(OP_DuelAccept, Duel_Struct);
|
||||
IN(OP_SpawnAppearance, SpawnAppearance_Struct);
|
||||
IN(OP_BazaarInspect, BazaarInspect_Struct);
|
||||
IN(OP_Death, Death_Struct);
|
||||
|
||||
@@ -240,8 +240,8 @@ void load_opcode_names()
|
||||
opcode_map[0x00a1] = "LiveOP_SaveOnZoneReq";
|
||||
opcode_map[0x0185] = "LiveOP_Logout";
|
||||
opcode_map[0x0298] = "LiveOP_RequestDuel";
|
||||
opcode_map[0x0a5d] = "LiveOP_DuelResponse";
|
||||
opcode_map[0x016e] = "LiveOP_DuelResponse2";
|
||||
opcode_map[0x0a5d] = "LiveOP_DuelDecline";
|
||||
opcode_map[0x016e] = "LiveOP_DuelAccept";
|
||||
opcode_map[0x007c] = "LiveOP_InstillDoubt";
|
||||
opcode_map[0x00ac] = "LiveOP_SafeFallSuccess";
|
||||
opcode_map[0x02fb] = "LiveOP_DisciplineUpdate";
|
||||
|
||||
@@ -1634,20 +1634,6 @@ namespace RoF
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ManaChange)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ManaChange_Struct);
|
||||
SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct);
|
||||
|
||||
OUT(new_mana);
|
||||
OUT(stamina);
|
||||
OUT(spell_id);
|
||||
OUT(keepcasting);
|
||||
eq->slot = -1; // this is spell gem slot. It's -1 in normal operation
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_MercenaryDataResponse)
|
||||
{
|
||||
//consume the packet
|
||||
|
||||
@@ -1683,20 +1683,6 @@ namespace RoF2
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ManaChange)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ManaChange_Struct);
|
||||
SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct);
|
||||
|
||||
OUT(new_mana);
|
||||
OUT(stamina);
|
||||
OUT(spell_id);
|
||||
OUT(keepcasting);
|
||||
eq->slot = -1; // this is spell gem slot. It's -1 in normal operation
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_MercenaryDataResponse)
|
||||
{
|
||||
//consume the packet
|
||||
|
||||
@@ -93,7 +93,6 @@ E(OP_ItemVerifyReply)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_LogServer)
|
||||
E(OP_LootItem)
|
||||
E(OP_ManaChange)
|
||||
E(OP_MercenaryDataResponse)
|
||||
E(OP_MercenaryDataUpdate)
|
||||
E(OP_MoveItem)
|
||||
|
||||
@@ -79,7 +79,6 @@ E(OP_ItemVerifyReply)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_LogServer)
|
||||
E(OP_LootItem)
|
||||
E(OP_ManaChange)
|
||||
E(OP_MercenaryDataResponse)
|
||||
E(OP_MercenaryDataUpdate)
|
||||
E(OP_MoveItem)
|
||||
|
||||
@@ -1170,20 +1170,6 @@ namespace SoD
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ManaChange)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ManaChange_Struct);
|
||||
SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct);
|
||||
|
||||
OUT(new_mana);
|
||||
OUT(stamina);
|
||||
OUT(spell_id);
|
||||
OUT(keepcasting);
|
||||
eq->slot = -1; // this is spell gem slot. It's -1 in normal operation
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_MercenaryDataResponse)
|
||||
{
|
||||
//consume the packet
|
||||
|
||||
@@ -63,7 +63,6 @@ E(OP_ItemVerifyReply)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_LogServer)
|
||||
E(OP_LootItem)
|
||||
E(OP_ManaChange)
|
||||
E(OP_MercenaryDataResponse)
|
||||
E(OP_MercenaryDataUpdate)
|
||||
E(OP_MoveItem)
|
||||
|
||||
@@ -966,20 +966,6 @@ namespace SoF
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ManaChange)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ManaChange_Struct);
|
||||
SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct);
|
||||
|
||||
OUT(new_mana);
|
||||
OUT(stamina);
|
||||
OUT(spell_id);
|
||||
OUT(keepcasting);
|
||||
eq->slot = -1; // this is spell gem slot. It's -1 in normal operation
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_MemorizeSpell)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(MemorizeSpell_Struct);
|
||||
|
||||
@@ -59,7 +59,6 @@ E(OP_ItemVerifyReply)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_LogServer)
|
||||
E(OP_LootItem)
|
||||
E(OP_ManaChange)
|
||||
E(OP_MemorizeSpell)
|
||||
E(OP_MoveItem)
|
||||
E(OP_NewSpawn)
|
||||
|
||||
@@ -932,6 +932,19 @@ namespace Titanium
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ManaChange)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ManaChange_Struct);
|
||||
SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct);
|
||||
|
||||
OUT(new_mana);
|
||||
OUT(stamina);
|
||||
OUT(spell_id);
|
||||
OUT(keepcasting);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_MemorizeSpell)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(MemorizeSpell_Struct);
|
||||
|
||||
@@ -55,6 +55,7 @@ E(OP_ItemPacket)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_LFGuild)
|
||||
E(OP_LootItem)
|
||||
E(OP_ManaChange)
|
||||
E(OP_MemorizeSpell)
|
||||
E(OP_MoveItem)
|
||||
E(OP_OnLevelMessage)
|
||||
|
||||
@@ -1390,20 +1390,6 @@ namespace UF
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ManaChange)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ManaChange_Struct);
|
||||
SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct);
|
||||
|
||||
OUT(new_mana);
|
||||
OUT(stamina);
|
||||
OUT(spell_id);
|
||||
OUT(keepcasting);
|
||||
eq->slot = -1; // this is spell gem slot. It's -1 in normal operation
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_MercenaryDataResponse)
|
||||
{
|
||||
//consume the packet
|
||||
|
||||
@@ -68,7 +68,6 @@ E(OP_ItemVerifyReply)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_LogServer)
|
||||
E(OP_LootItem)
|
||||
E(OP_ManaChange)
|
||||
E(OP_MercenaryDataResponse)
|
||||
E(OP_MercenaryDataUpdate)
|
||||
E(OP_MoveItem)
|
||||
|
||||
@@ -40,43 +40,48 @@ namespace ContentFilterCriteria {
|
||||
}
|
||||
|
||||
criteria += fmt::format(
|
||||
" AND ({}min_expansion <= {} OR {}min_expansion = 0)",
|
||||
" AND ({}min_expansion <= {} OR {}min_expansion = -1)",
|
||||
table_prefix,
|
||||
current_expansion_filter_criteria,
|
||||
table_prefix
|
||||
);
|
||||
|
||||
criteria += fmt::format(
|
||||
" AND ({}max_expansion >= {} OR {}max_expansion = 0)",
|
||||
" AND ({}max_expansion >= {} OR {}max_expansion = -1)",
|
||||
table_prefix,
|
||||
current_expansion_filter_criteria,
|
||||
table_prefix
|
||||
);
|
||||
|
||||
std::vector<std::string> flags = content_service.GetContentFlags();
|
||||
std::vector<std::string> flags_disabled = content_service.GetContentFlagsDisabled();
|
||||
std::vector<std::string> flags_enabled = content_service.GetContentFlagsEnabled();
|
||||
std::string flags_in_filter_enabled;
|
||||
std::string flags_in_filter_disabled;
|
||||
if (!flags.empty()) {
|
||||
if (!flags_enabled.empty()) {
|
||||
flags_in_filter_enabled = fmt::format(
|
||||
" OR CONCAT(',', {}content_flags, ',') REGEXP ',({}),' ",
|
||||
table_prefix,
|
||||
implode("|", flags)
|
||||
implode("|", flags_enabled)
|
||||
);
|
||||
}
|
||||
if (!flags_disabled.empty()) {
|
||||
flags_in_filter_disabled = fmt::format(
|
||||
" OR CONCAT(',', {}content_flags_disabled, ',') NOT REGEXP ',({}),' ",
|
||||
" OR CONCAT(',', {}content_flags_disabled, ',') REGEXP ',({}),' ",
|
||||
table_prefix,
|
||||
implode("|", flags)
|
||||
implode("|", flags_disabled)
|
||||
);
|
||||
}
|
||||
|
||||
criteria += fmt::format(
|
||||
" AND ({}content_flags IS NULL{}) ",
|
||||
" AND (({}content_flags IS NULL OR {}content_flags = ''){}) ",
|
||||
table_prefix,
|
||||
table_prefix,
|
||||
flags_in_filter_enabled
|
||||
);
|
||||
|
||||
criteria += fmt::format(
|
||||
" AND ({}content_flags_disabled IS NULL{}) ",
|
||||
" AND (({}content_flags_disabled IS NULL OR {}content_flags_disabled = ''){}) ",
|
||||
table_prefix,
|
||||
table_prefix,
|
||||
flags_in_filter_disabled
|
||||
);
|
||||
|
||||
+27
-1
@@ -174,6 +174,24 @@ RULE_INT(Character, ResurrectionSicknessSpellID, 756, "756 is Default Resurrecti
|
||||
RULE_BOOL(Character, EnableBardMelody, true, "Enable Bard /melody by default, to disable change to false for a classic experience.")
|
||||
RULE_BOOL(Character, EnableRangerAutoFire, true, "Enable Ranger /autofire by default, to disable change to false for a classic experience.")
|
||||
RULE_BOOL(Character, EnableTGB, true, "Enable /tgb (Target Group Buff) by default, to disable change to false for a classic experience.")
|
||||
RULE_INT(Character, SkillUpMaximumChancePercentage, 25, "Maximum chance to improve a combat skill, before skill-specific modifiers. This should be greater than SkillUpMinimumChancePercentage.")
|
||||
RULE_INT(Character, SkillUpMinimumChancePercentage, 2, "Minimum chance to improve a combat skill, after skill-specific modifiers. This should be lesser than SkillUpMaximumChancePercentage.")
|
||||
RULE_INT(Character, WarriorTrackingDistanceMultiplier, 0, "If you want warriors to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, ClericTrackingDistanceMultiplier, 0, "If you want clerics to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, PaladinTrackingDistanceMultiplier, 0, "If you want paladins to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, RangerTrackingDistanceMultiplier, 12, "If you want rangers to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, ShadowKnightTrackingDistanceMultiplier, 0, "If you want shadow knights to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, DruidTrackingDistanceMultiplier, 10, "If you want druids to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, MonkTrackingDistanceMultiplier, 0, "If you want monks to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, BardTrackingDistanceMultiplier, 7, "If you want bards to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, RogueTrackingDistanceMultiplier, 0, "If you want rogues to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, ShamanTrackingDistanceMultiplier, 0, "If you want shaman to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, NecromancerTrackingDistanceMultiplier, 0, "If you want necromancers to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, WizardTrackingDistanceMultiplier, 0, "If you want wizards to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, MagicianTrackingDistanceMultiplier, 0, "If you want magicians to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, EnchanterTrackingDistanceMultiplier, 0, "If you want enchanters to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, BeastlordTrackingDistanceMultiplier, 0, "If you want beastlords to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, BerserkerTrackingDistanceMultiplier, 0, "If you want berserkers to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Mercs)
|
||||
@@ -263,10 +281,11 @@ RULE_INT(Zone, ClientLinkdeadMS, 90000, "The time a client remains link dead on
|
||||
RULE_INT(Zone, GraveyardTimeMS, 1200000, "Time until a player corpse is moved to a zone's graveyard, if one is specified for the zone (milliseconds)")
|
||||
RULE_BOOL(Zone, EnableShadowrest, 1, "Enables or disables the Shadowrest zone feature for player corpses. Default is turned on")
|
||||
RULE_INT(Zone, AutoShutdownDelay, 5000, "How long a dynamic zone stays loaded while empty (milliseconds)")
|
||||
RULE_INT(Zone, PEQZoneReuseTime, 900, "Time between two uses of the #peqzone command (seconds)")
|
||||
RULE_INT(Zone, PEQZoneReuseTime, 900, "Seconds between two uses of the #peqzone command (Set to 0 to disable)")
|
||||
RULE_INT(Zone, PEQZoneDebuff1, 4454, "First debuff casted by #peqzone Default is Cursed Keeper's Blight")
|
||||
RULE_INT(Zone, PEQZoneDebuff2, 2209, "Second debuff casted by #peqzone Default is Tendrils of Apathy")
|
||||
RULE_BOOL(Zone, UsePEQZoneDebuffs, true, "Setting if the command #peqzone applies the defined debuffs")
|
||||
RULE_INT(Zone, PEQZoneHPRatio, 75, "Required HP Ratio to use #peqzone")
|
||||
RULE_REAL(Zone, HotZoneBonus, 0.75, "Value which is added to the experience multiplier. This also applies to AA experience.")
|
||||
RULE_INT(Zone, EbonCrystalItemID, 40902, "Item ID for Ebon Crystal")
|
||||
RULE_INT(Zone, RadiantCrystalItemID, 40903, "Item ID for Radiant Crystal")
|
||||
@@ -491,6 +510,7 @@ RULE_INT(Combat, SneakPullAssistRange, 400, "Modified range of assist for sneak
|
||||
RULE_BOOL(Combat, Classic2HBAnimation, false, "2HB will use the 2 hand piercing animation instead of the overhead slashing animation")
|
||||
RULE_BOOL(Combat, ArcheryConsumesAmmo, true, "Set to false to disable Archery Ammo Consumption")
|
||||
RULE_BOOL(Combat, ThrowingConsumesAmmo, true, "Set to false to disable Throwing Ammo Consumption")
|
||||
RULE_BOOL(Combat, UseLiveRiposteMechanics, false, "Set to true to disable SPA 173 SE_RiposteChance from making those with the effect on them immune to enrage, can longer riposte from a riposte.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(NPC)
|
||||
@@ -726,6 +746,7 @@ RULE_BOOL(Inventory, EnforceAugmentWear, true, "Forces augment wear slot validat
|
||||
RULE_BOOL(Inventory, DeleteTransformationMold, true, "False if you want mold to last forever")
|
||||
RULE_BOOL(Inventory, AllowAnyWeaponTransformation, false, "Weapons can use any weapon transformation")
|
||||
RULE_BOOL(Inventory, TransformSummonedBags, false, "Transforms summoned bags into disenchanted ones instead of deleting")
|
||||
RULE_BOOL(Inventory, AllowMultipleOfSameAugment, false, "Allows multiple of the same augment to be placed in an item via #augmentitem or MQ2, set to true to allow")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Client)
|
||||
@@ -764,6 +785,7 @@ RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Expansion)
|
||||
RULE_INT(Expansion, CurrentExpansion, -1, "The current expansion enabled for the server [-1 = ALL, 0 = Classic, 1 = Kunark etc.]")
|
||||
RULE_BOOL(Expansion, UseCurrentExpansionAAOnly, false, "When true will only load AA ranks that match CurrentExpansion rule")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Instances)
|
||||
@@ -806,6 +828,10 @@ RULE_CATEGORY(Command)
|
||||
RULE_BOOL(Command, DyeCommandRequiresDyes, false, "Enable this to require a Prismatic Dye (32557) each time someone uses #dye.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Doors)
|
||||
RULE_BOOL(Doors, RequireKeyOnCursor, false, "Enable this to require pre-keyring keys to be on player cursor to open doors.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
#undef RULE_CATEGORY
|
||||
#undef RULE_INT
|
||||
#undef RULE_REAL
|
||||
|
||||
@@ -226,6 +226,7 @@
|
||||
#define ServerOP_UCSServerStatusReply 0x4010
|
||||
#define ServerOP_HotReloadQuests 0x4011
|
||||
#define ServerOP_UpdateSchedulerEvents 0x4012
|
||||
#define ServerOP_ReloadContentFlags 0x4013
|
||||
|
||||
#define ServerOP_CZDialogueWindow 0x4500
|
||||
#define ServerOP_CZLDoNUpdate 0x4501
|
||||
|
||||
+79
-12
@@ -1239,10 +1239,10 @@ bool IsEffectIgnoredInStacking(int spa)
|
||||
case SE_GravityEffect:
|
||||
case 425:
|
||||
//Spell effects implemented after ROF2, following same pattern, lets assume these should go here.
|
||||
case SE_Fc_Spell_Damage_Pct_IncomingPC:
|
||||
case SE_Fc_Spell_Damage_Pct_IncomingPC:
|
||||
case SE_Fc_Spell_Damage_Amt_IncomingPC:
|
||||
case SE_Ff_CasterClass:
|
||||
case SE_Ff_Same_Caster:
|
||||
case SE_Ff_Same_Caster:
|
||||
case SE_Proc_Timer_Modifier:
|
||||
case SE_Weapon_Stance:
|
||||
case SE_TwinCastBlocker:
|
||||
@@ -1417,8 +1417,8 @@ bool IsInstrumentModAppliedToSpellEffect(int32 spell_id, int effect)
|
||||
case SE_MinDamageModifier:
|
||||
case SE_ProcChance:
|
||||
case SE_PetFlurry: // ? Need verified
|
||||
case SE_DiseaseCounter:
|
||||
case SE_PoisonCounter:
|
||||
case SE_DiseaseCounter:
|
||||
case SE_PoisonCounter:
|
||||
case SE_CurseCounter:
|
||||
case SE_CorruptionCounter:
|
||||
return true;
|
||||
@@ -1462,6 +1462,23 @@ bool IsInstrumentModAppliedToSpellEffect(int32 spell_id, int effect)
|
||||
//Allowing anything not confirmed to be restricted / allowed to receive modifiers, as to not inhbit anyone making custom bard songs.
|
||||
}
|
||||
|
||||
bool IsPulsingBardSong(int32 spell_id)
|
||||
{
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (spells[spell_id].buff_duration == 0xFFFF ||
|
||||
spells[spell_id].recast_time> 0 ||
|
||||
spells[spell_id].mana > 0 ||
|
||||
IsEffectInSpell(spell_id, SE_TemporaryPets) ||
|
||||
IsEffectInSpell(spell_id, SE_Familiar)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int GetSpellStatValue(uint32 spell_id, const char* stat_identifier, uint8 slot)
|
||||
{
|
||||
if (!IsValidSpell(spell_id))
|
||||
@@ -1576,7 +1593,7 @@ int GetSpellStatValue(uint32 spell_id, const char* stat_identifier, uint8 slot)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool IsVirusSpell(int32 spell_id)
|
||||
bool IsVirusSpell(int32 spell_id)
|
||||
{
|
||||
if (GetViralMinSpreadTime(spell_id) && GetViralMaxSpreadTime(spell_id) && GetViralSpreadRange(spell_id)){
|
||||
return true;
|
||||
@@ -1584,17 +1601,17 @@ bool IsVirusSpell(int32 spell_id)
|
||||
return false;
|
||||
}
|
||||
|
||||
int32 GetViralMinSpreadTime(int32 spell_id)
|
||||
int32 GetViralMinSpreadTime(int32 spell_id)
|
||||
{
|
||||
return spells[spell_id].viral_targets;
|
||||
}
|
||||
|
||||
int32 GetViralMaxSpreadTime(int32 spell_id)
|
||||
int32 GetViralMaxSpreadTime(int32 spell_id)
|
||||
{
|
||||
return spells[spell_id].viral_timer;
|
||||
}
|
||||
|
||||
int32 GetViralSpreadRange(int32 spell_id)
|
||||
int32 GetViralSpreadRange(int32 spell_id)
|
||||
{
|
||||
return spells[spell_id].viral_range;
|
||||
}
|
||||
@@ -1605,23 +1622,23 @@ uint32 GetProcLimitTimer(int32 spell_id, int proc_type) {
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool use_next_timer = false;
|
||||
for (int i = 0; i < EFFECT_COUNT; ++i) {
|
||||
|
||||
if (proc_type == SE_WeaponProc) {
|
||||
if (proc_type == ProcType::MELEE_PROC) {
|
||||
if (spells[spell_id].effect_id[i] == SE_WeaponProc || spells[spell_id].effect_id[i] == SE_AddMeleeProc) {
|
||||
use_next_timer = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (proc_type == SE_RangedProc) {
|
||||
if (proc_type == ProcType::RANGED_PROC) {
|
||||
if (spells[spell_id].effect_id[i] == SE_RangedProc) {
|
||||
use_next_timer = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (proc_type == SE_DefensiveProc) {
|
||||
if (proc_type == ProcType::DEFENSIVE_PROC) {
|
||||
if (spells[spell_id].effect_id[i] == SE_DefensiveProc) {
|
||||
use_next_timer = true;
|
||||
}
|
||||
@@ -1633,3 +1650,53 @@ uint32 GetProcLimitTimer(int32 spell_id, int proc_type) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CastRestrictedSpell(int spellid)
|
||||
{
|
||||
switch (spellid) {
|
||||
case SPELL_TOUCH_OF_VINITRAS:
|
||||
case SPELL_DESPERATE_HOPE:
|
||||
case SPELL_CHARM:
|
||||
case SPELL_METAMORPHOSIS65:
|
||||
case SPELL_JT_BUFF:
|
||||
case SPELL_CAN_O_WHOOP_ASS:
|
||||
case SPELL_PHOENIX_CHARM:
|
||||
case SPELL_CAZIC_TOUCH:
|
||||
case SPELL_AVATAR_KNOCKBACK:
|
||||
case SPELL_SHAPECHANGE65:
|
||||
case SPELL_SUNSET_HOME1218:
|
||||
case SPELL_SUNSET_HOME819:
|
||||
case SPELL_SHAPECHANGE75:
|
||||
case SPELL_SHAPECHANGE80:
|
||||
case SPELL_SHAPECHANGE85:
|
||||
case SPELL_SHAPECHANGE90:
|
||||
case SPELL_SHAPECHANGE95:
|
||||
case SPELL_SHAPECHANGE100:
|
||||
case SPELL_SHAPECHANGE25:
|
||||
case SPELL_SHAPECHANGE30:
|
||||
case SPELL_SHAPECHANGE35:
|
||||
case SPELL_SHAPECHANGE40:
|
||||
case SPELL_SHAPECHANGE45:
|
||||
case SPELL_SHAPECHANGE50:
|
||||
case SPELL_NPC_AEGOLISM:
|
||||
case SPELL_SHAPECHANGE55:
|
||||
case SPELL_SHAPECHANGE60:
|
||||
case SPELL_COMMAND_OF_DRUZZIL:
|
||||
case SPELL_SHAPECHANGE70:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool IgnoreCastingRestriction(int32 spell_id) {
|
||||
/*
|
||||
field 'cast_not_standing' allows casting when sitting, stunned, mezed, Divine Aura, through SPA 343 Interrupt casting
|
||||
Likely also allows for casting while feared, but need to confirm. Possibly also while charmed.
|
||||
This field also allows for damage to ignore DA immunity.
|
||||
*/
|
||||
if (spells[spell_id].cast_not_standing) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+306
-283
@@ -26,6 +26,7 @@
|
||||
#define SPELLBOOK_UNKNOWN 0xFFFFFFFF //player profile spells are 32 bit
|
||||
|
||||
//some spell IDs which will prolly change, but are needed
|
||||
#define SPELL_LIFEBURN 2755
|
||||
#define SPELL_LEECH_TOUCH 2766
|
||||
#define SPELL_LAY_ON_HANDS 87
|
||||
#define SPELL_HARM_TOUCH 88
|
||||
@@ -162,6 +163,12 @@
|
||||
#define SPELL_RESURRECTION_SICKNESS3 37624
|
||||
#define SPELL_PACT_OF_HATE_RECOURSE 40375
|
||||
#define SPELL_INCENDIARY_OOZE_BUFF 32513
|
||||
#define SPELL_EYE_OF_ZOMM 323
|
||||
#define SPELL_MINOR_ILLUSION 287
|
||||
#define SPELL_ILLUSION_TREE 601
|
||||
#define SPELL_ILLUSION_FEMALE 1731
|
||||
#define SPELL_ILLUSION_MALE 1732
|
||||
#define SPELL_UNSUMMON_SELF 892
|
||||
|
||||
//spellgroup ids
|
||||
#define SPELLGROUP_FRENZIED_BURNOUT 2754
|
||||
@@ -172,8 +179,6 @@
|
||||
#define SPELLGROUP_FURIOUS_RAMPAGE 38106
|
||||
#define SPELLGROUP_SHROUD_OF_PRAYER 41050
|
||||
|
||||
|
||||
|
||||
#define EFFECT_COUNT 12
|
||||
#define MAX_SPELL_TRIGGER 12 // One for each slot(only 6 for AA since AA use 2)
|
||||
#define MAX_RESISTABLE_EFFECTS 12 // Number of effects that are typcially checked agianst resists.
|
||||
@@ -183,7 +188,14 @@
|
||||
#define MAX_SYMPATHETIC_PROCS 10 // Number of sympathetic procs a client can have (This is arbitrary)
|
||||
#define MAX_FOCUS_PROC_LIMIT_TIMERS 20 //Number of focus recast timers that can be going at same time (This is arbitrary)
|
||||
#define MAX_PROC_LIMIT_TIMERS 8 //Number of proc delay timers that can be going at same time, different proc types get their own timer array. (This is arbitrary)
|
||||
#define MAX_APPEARANCE_EFFECTS 20 //Up to 20 Appearance Effects can be saved to a mobs appearance effect array, these will be sent to other clients when they enter a zone (This is arbitrary)
|
||||
#define MAX_CAST_ON_SKILL_USE 36 //Actual amount is MAX/3
|
||||
|
||||
//instrument item id's used as song components
|
||||
#define INSTRUMENT_HAND_DRUM 13000
|
||||
#define INSTRUMENT_WOODEN_FLUTE 13001
|
||||
#define INSTRUMENT_LUTE 13011
|
||||
#define INSTRUMENT_HORN 13012
|
||||
|
||||
|
||||
const int Z_AGGRO=10;
|
||||
@@ -219,292 +231,292 @@ enum SpellRestriction
|
||||
{
|
||||
UNKNOWN_3 = 3, // | caster restriction | seen in spell 30183 Mind Spiral
|
||||
IS_NOT_ON_HORSE = 5, // | caster restriction |
|
||||
IS_ANIMAL_OR_HUMANOID = 100, // This spell will only work on animals or humanoid creatures.
|
||||
IS_DRAGON = 101, // This spell will only work on dragons.
|
||||
IS_ANIMAL_OR_INSECT = 102, // This spell will only work on animals or insects.
|
||||
IS_BODY_TYPE_MISC = 103, // This spell will only work on humanoids, lycanthropes, giants, Kael Drakkel giants, Coldain, animals, insects, constructs, dragons, Skyshrine dragons, Muramites, or creatures constructed from magic.
|
||||
IS_BODY_TYPE_MISC2 = 104, // This spell will only work on humanoids, lycanthropes, giants, Kael Drakkel giants, Coldain, animals, or insects.
|
||||
IS_PLANT = 105, // This spell will only work on plants.
|
||||
IS_ANIMAL_OR_HUMANOID = 100, // This spell will only work on animals or humanoid creatures.
|
||||
IS_DRAGON = 101, // This spell will only work on dragons.
|
||||
IS_ANIMAL_OR_INSECT = 102, // This spell will only work on animals or insects.
|
||||
IS_BODY_TYPE_MISC = 103, // This spell will only work on humanoids, lycanthropes, giants, Kael Drakkel giants, Coldain, animals, insects, constructs, dragons, Skyshrine dragons, Muramites, or creatures constructed from magic.
|
||||
IS_BODY_TYPE_MISC2 = 104, // This spell will only work on humanoids, lycanthropes, giants, Kael Drakkel giants, Coldain, animals, or insects.
|
||||
IS_PLANT = 105, // This spell will only work on plants.
|
||||
IS_GIANT = 106, // This spell will only work on animals. | Live used to have this on spells restricted to Giants, but those spells were removed... We still have them
|
||||
IS_NOT_ANIMAL_OR_HUMANOID = 108, // This spell will only work on targets that are neither animals or humanoid.
|
||||
IS_BIXIE = 109, // This spell will only work on bixies.
|
||||
IS_HARPY = 110, // This spell will only work on harpies.
|
||||
IS_GNOLL = 111, // This spell will only work on gnolls.
|
||||
IS_SPORALI = 112, // This spell will only work on fungusoids.
|
||||
IS_KOBOLD = 113, // This spell will only work on kobolds.
|
||||
IS_FROSTCRYPT_SHADE = 114, // This spell will only work on undead creatures or the Shades of Frostcrypt.
|
||||
IS_DRAKKIN = 115, // This spell will only work on Drakkin.
|
||||
IS_UNDEAD_OR_VALDEHOLM_GIANT = 116, // This spell will only work on undead creatures or the inhabitants of Valdeholm.
|
||||
IS_ANIMAL_OR_PLANT = 117, // This spell will only work on plants or animals.
|
||||
IS_SUMMONED = 118, // This spell will only work on constructs, elementals, or summoned elemental minions.
|
||||
IS_WIZARD_USED_ON_MAGE_FIRE_PET = 119, // This spell will only work on wizards. | Live uses this on high level mage fire pets, which are wizard class
|
||||
IS_UNDEAD = 120, //
|
||||
IS_NOT_UNDEAD_OR_SUMMONED_OR_VAMPIRE = 121, // This spell will only work on creatures that are not undead, constructs, elementals, or vampires.
|
||||
IS_FAE_OR_PIXIE = 122, // This spell will only work on Fae or pixies.
|
||||
IS_HUMANOID = 123, //
|
||||
IS_UNDEAD_AND_HP_LESS_THAN_10_PCT = 124, // The Essence Extractor whirrs but does not light up.
|
||||
IS_CLOCKWORK_AND_HP_LESS_THAN_45_PCT = 125, // This spell will only work on clockwork gnomes.
|
||||
IS_WISP_AND_HP_LESS_THAN_10_PCT = 126, // This spell will only work on wisps at or below 10% of their maximum HP.
|
||||
IS_CLASS_MELEE_THAT_CAN_BASH_OR_KICK_EXCEPT_BARD = 127, // This spell will only work on non-bard targets that can bash or kick.
|
||||
IS_CLASS_PURE_MELEE = 128, // This spell will only affect melee classes (warriors, monks, rogues, and berserkers).
|
||||
IS_CLASS_PURE_CASTER = 129, // This spell will only affect pure caster classes (necromancers, wizards, magicians, and enchanters).
|
||||
IS_CLASS_HYBRID_CLASS = 130, // This spell will only affect hybrid classes (paladins, rangers, shadow knights, bards, and beastlords).
|
||||
IS_CLASS_WARRIOR = 131, // This spell will only affect Warriors.
|
||||
IS_CLASS_CLERIC = 132, // This spell will only affect Clerics.
|
||||
IS_CLASS_PALADIN = 133, // This spell will only affect Paladins.
|
||||
IS_CLASS_RANGER = 134, // This spell will only affect Rangers.
|
||||
IS_CLASS_SHADOWKNIGHT = 135, // This spell will only affect Shadow Knights.
|
||||
IS_CLASS_DRUID = 136, // This spell will only affect Druids.
|
||||
IS_CLASS_MONK = 137, // This spell will only affect Monks.
|
||||
IS_CLASS_BARD = 138, // This spell will only affect Bards.
|
||||
IS_CLASS_ROGUE = 139, // This spell will only affect Rogues.
|
||||
IS_CLASS_SHAMAN = 140, // This spell will only affect Shamans.
|
||||
IS_CLASS_NECRO = 141, // This spell will only affect Necromancers.
|
||||
IS_CLASS_WIZARD = 142, // This spell will only affect Wizards.
|
||||
IS_CLASS_MAGE = 143, // This spell will only affect Magicians.
|
||||
IS_CLASS_ENCHANTER = 144, // This spell will only affect Enchanters.
|
||||
IS_CLASS_BEASTLORD = 145, // This spell will only affect Beastlords.
|
||||
IS_CLASS_BERSERKER = 146, // This spell will only affect Berserkers.
|
||||
IS_CLASS_CLR_SHM_DRU = 147, // This spell will only affect priest classes (clerics, druids, and shaman).
|
||||
IS_CLASS_NOT_WAR_PAL_SK = 148, // This spell will not affect Warriors, Paladins, or Shadow Knights.
|
||||
IS_LEVEL_UNDER_100 = 150, // This spell will not affect any target over level 100.
|
||||
IS_NOT_RAID_BOSS = 190, // This spell will not affect raid bosses.
|
||||
IS_RAID_BOSS = 191, // This spell will only affect raid bosses.
|
||||
FRENZIED_BURNOUT_ACTIVE = 192, // This spell will only cast if you have Frenzied Burnout active.
|
||||
FRENZIED_BURNOUT_NOT_ACTIVE = 193, // This spell will only cast if you do not have Frenzied Burnout active.
|
||||
IS_NOT_ANIMAL_OR_HUMANOID = 108, // This spell will only work on targets that are neither animals or humanoid.
|
||||
IS_BIXIE = 109, // This spell will only work on bixies.
|
||||
IS_HARPY = 110, // This spell will only work on harpies.
|
||||
IS_GNOLL = 111, // This spell will only work on gnolls.
|
||||
IS_SPORALI = 112, // This spell will only work on fungusoids.
|
||||
IS_KOBOLD = 113, // This spell will only work on kobolds.
|
||||
IS_FROSTCRYPT_SHADE = 114, // This spell will only work on undead creatures or the Shades of Frostcrypt.
|
||||
IS_DRAKKIN = 115, // This spell will only work on Drakkin.
|
||||
IS_UNDEAD_OR_VALDEHOLM_GIANT = 116, // This spell will only work on undead creatures or the inhabitants of Valdeholm.
|
||||
IS_ANIMAL_OR_PLANT = 117, // This spell will only work on plants or animals.
|
||||
IS_SUMMONED = 118, // This spell will only work on constructs, elementals, or summoned elemental minions.
|
||||
IS_WIZARD_USED_ON_MAGE_FIRE_PET = 119, // This spell will only work on wizards. | Live uses this on high level mage fire pets, which are wizard class
|
||||
IS_UNDEAD = 120, //
|
||||
IS_NOT_UNDEAD_OR_SUMMONED_OR_VAMPIRE = 121, // This spell will only work on creatures that are not undead, constructs, elementals, or vampires.
|
||||
IS_FAE_OR_PIXIE = 122, // This spell will only work on Fae or pixies.
|
||||
IS_HUMANOID = 123, //
|
||||
IS_UNDEAD_AND_HP_LESS_THAN_10_PCT = 124, // The Essence Extractor whirrs but does not light up.
|
||||
IS_CLOCKWORK_AND_HP_LESS_THAN_45_PCT = 125, // This spell will only work on clockwork gnomes.
|
||||
IS_WISP_AND_HP_LESS_THAN_10_PCT = 126, // This spell will only work on wisps at or below 10% of their maximum HP.
|
||||
IS_CLASS_MELEE_THAT_CAN_BASH_OR_KICK_EXCEPT_BARD = 127, // This spell will only work on non-bard targets that can bash or kick.
|
||||
IS_CLASS_PURE_MELEE = 128, // This spell will only affect melee classes (warriors, monks, rogues, and berserkers).
|
||||
IS_CLASS_PURE_CASTER = 129, // This spell will only affect pure caster classes (necromancers, wizards, magicians, and enchanters).
|
||||
IS_CLASS_HYBRID_CLASS = 130, // This spell will only affect hybrid classes (paladins, rangers, shadow knights, bards, and beastlords).
|
||||
IS_CLASS_WARRIOR = 131, // This spell will only affect Warriors.
|
||||
IS_CLASS_CLERIC = 132, // This spell will only affect Clerics.
|
||||
IS_CLASS_PALADIN = 133, // This spell will only affect Paladins.
|
||||
IS_CLASS_RANGER = 134, // This spell will only affect Rangers.
|
||||
IS_CLASS_SHADOWKNIGHT = 135, // This spell will only affect Shadow Knights.
|
||||
IS_CLASS_DRUID = 136, // This spell will only affect Druids.
|
||||
IS_CLASS_MONK = 137, // This spell will only affect Monks.
|
||||
IS_CLASS_BARD = 138, // This spell will only affect Bards.
|
||||
IS_CLASS_ROGUE = 139, // This spell will only affect Rogues.
|
||||
IS_CLASS_SHAMAN = 140, // This spell will only affect Shamans.
|
||||
IS_CLASS_NECRO = 141, // This spell will only affect Necromancers.
|
||||
IS_CLASS_WIZARD = 142, // This spell will only affect Wizards.
|
||||
IS_CLASS_MAGE = 143, // This spell will only affect Magicians.
|
||||
IS_CLASS_ENCHANTER = 144, // This spell will only affect Enchanters.
|
||||
IS_CLASS_BEASTLORD = 145, // This spell will only affect Beastlords.
|
||||
IS_CLASS_BERSERKER = 146, // This spell will only affect Berserkers.
|
||||
IS_CLASS_CLR_SHM_DRU = 147, // This spell will only affect priest classes (clerics, druids, and shaman).
|
||||
IS_CLASS_NOT_WAR_PAL_SK = 148, // This spell will not affect Warriors, Paladins, or Shadow Knights.
|
||||
IS_LEVEL_UNDER_100 = 150, // This spell will not affect any target over level 100.
|
||||
IS_NOT_RAID_BOSS = 190, // This spell will not affect raid bosses.
|
||||
IS_RAID_BOSS = 191, // This spell will only affect raid bosses.
|
||||
FRENZIED_BURNOUT_ACTIVE = 192, // This spell will only cast if you have Frenzied Burnout active.
|
||||
FRENZIED_BURNOUT_NOT_ACTIVE = 193, // This spell will only cast if you do not have Frenzied Burnout active.
|
||||
UNKNOWN_199 = 199, //
|
||||
IS_HP_ABOVE_75_PCT = 201, //
|
||||
IS_HP_ABOVE_75_PCT = 201, //
|
||||
IS_HP_LESS_THAN_20_PCT = 203, // Your target's HP must be at 20% of its maximum or below. | caster restriction |
|
||||
IS_HP_LESS_THAN_50_PCT = 204, // Your target's HP must be at 50% of its maximum or below. | caster restriction |
|
||||
IS_HP_LESS_THAN_75_PCT = 205, // Your target's HP must be at 75% of its maximum or below.
|
||||
IS_NOT_IN_COMBAT = 216, // This spell will only affect creatures that are not in combat.
|
||||
HAS_AT_LEAST_1_PET_ON_HATELIST = 221, //
|
||||
HAS_AT_LEAST_2_PETS_ON_HATELIST = 222, //
|
||||
HAS_AT_LEAST_3_PETS_ON_HATELIST = 223, //
|
||||
HAS_AT_LEAST_4_PETS_ON_HATELIST = 224, //
|
||||
HAS_AT_LEAST_5_PETS_ON_HATELIST = 225, //
|
||||
HAS_AT_LEAST_6_PETS_ON_HATELIST = 226, //
|
||||
HAS_AT_LEAST_7_PETS_ON_HATELIST = 227, //
|
||||
HAS_AT_LEAST_8_PETS_ON_HATELIST = 228, //
|
||||
HAS_AT_LEAST_9_PETS_ON_HATELIST = 229, //
|
||||
HAS_AT_LEAST_10_PETS_ON_HATELIST = 230, //
|
||||
HAS_AT_LEAST_11_PETS_ON_HATELIST = 231, //
|
||||
HAS_AT_LEAST_12_PETS_ON_HATELIST = 232, //
|
||||
HAS_AT_LEAST_13_PETS_ON_HATELIST = 233, //
|
||||
HAS_AT_LEAST_14_PETS_ON_HATELIST = 234, //
|
||||
HAS_AT_LEAST_15_PETS_ON_HATELIST = 235, //
|
||||
HAS_AT_LEAST_16_PETS_ON_HATELIST = 236, //
|
||||
HAS_AT_LEAST_17_PETS_ON_HATELIST = 237, //
|
||||
HAS_AT_LEAST_18_PETS_ON_HATELIST = 238, //
|
||||
HAS_AT_LEAST_19_PETS_ON_HATELIST = 239, //
|
||||
HAS_AT_LEAST_20_PETS_ON_HATELIST = 240, //
|
||||
IS_HP_LESS_THAN_75_PCT = 205, // Your target's HP must be at 75% of its maximum or below.
|
||||
IS_NOT_IN_COMBAT = 216, // This spell will only affect creatures that are not in combat.
|
||||
HAS_AT_LEAST_1_PET_ON_HATELIST = 221, //
|
||||
HAS_AT_LEAST_2_PETS_ON_HATELIST = 222, //
|
||||
HAS_AT_LEAST_3_PETS_ON_HATELIST = 223, //
|
||||
HAS_AT_LEAST_4_PETS_ON_HATELIST = 224, //
|
||||
HAS_AT_LEAST_5_PETS_ON_HATELIST = 225, //
|
||||
HAS_AT_LEAST_6_PETS_ON_HATELIST = 226, //
|
||||
HAS_AT_LEAST_7_PETS_ON_HATELIST = 227, //
|
||||
HAS_AT_LEAST_8_PETS_ON_HATELIST = 228, //
|
||||
HAS_AT_LEAST_9_PETS_ON_HATELIST = 229, //
|
||||
HAS_AT_LEAST_10_PETS_ON_HATELIST = 230, //
|
||||
HAS_AT_LEAST_11_PETS_ON_HATELIST = 231, //
|
||||
HAS_AT_LEAST_12_PETS_ON_HATELIST = 232, //
|
||||
HAS_AT_LEAST_13_PETS_ON_HATELIST = 233, //
|
||||
HAS_AT_LEAST_14_PETS_ON_HATELIST = 234, //
|
||||
HAS_AT_LEAST_15_PETS_ON_HATELIST = 235, //
|
||||
HAS_AT_LEAST_16_PETS_ON_HATELIST = 236, //
|
||||
HAS_AT_LEAST_17_PETS_ON_HATELIST = 237, //
|
||||
HAS_AT_LEAST_18_PETS_ON_HATELIST = 238, //
|
||||
HAS_AT_LEAST_19_PETS_ON_HATELIST = 239, //
|
||||
HAS_AT_LEAST_20_PETS_ON_HATELIST = 240, //
|
||||
IS_HP_LESS_THAN_35_PCT = 250, // Your target's HP must be at 35% of its maximum or below.
|
||||
HAS_BETWEEN_1_TO_2_PETS_ON_HATELIST = 260, // between 1 and 2 pets
|
||||
HAS_BETWEEN_3_TO_5_PETS_ON_HATELIST = 261, // between 3 and 5 pets
|
||||
HAS_BETWEEN_6_TO_9_PETS_ON_HATELIST = 262, // between 6 and 9 pets
|
||||
HAS_BETWEEN_10_TO_14_PETS_ON_HATELIST = 263, // between 10 and 14 pets
|
||||
HAS_MORE_THAN_14_PETS_ON_HATELIST = 264, // 15 or more pets
|
||||
IS_CLASS_CHAIN_OR_PLATE = 304, // This spell will only affect plate or chain wearing classes.
|
||||
IS_HP_BETWEEN_5_AND_9_PCT = 350, // Your target's HP must be between 5% and 9% of its maximum.
|
||||
IS_HP_BETWEEN_10_AND_14_PCT = 351, // Your target's HP must be between 10% and 14% of its maximum.
|
||||
IS_HP_BETWEEN_15_AND_19_PCT = 352, // Your target's HP must be between 15% and 19% of its maximum.
|
||||
IS_HP_BETWEEN_20_AND_24_PCT = 353, // Your target's HP must be between 20% and 24% of its maximum.
|
||||
IS_HP_BETWEEN_25_AND_29_PCT = 354, // Your target's HP must be between 25% and 29% of its maximum.
|
||||
IS_HP_BETWEEN_30_AND_34_PCT = 355, // Your target's HP must be between 30% and 34% of its maximum.
|
||||
IS_HP_BETWEEN_35_AND_39_PCT = 356, // Your target's HP must be between 35% and 39% of its maximum.
|
||||
IS_HP_BETWEEN_40_AND_44_PCT = 357, // Your target's HP must be between 40% and 44% of its maximum.
|
||||
IS_HP_BETWEEN_45_AND_49_PCT = 358, // Your target's HP must be between 45% and 49% of its maximum.
|
||||
IS_HP_BETWEEN_50_AND_54_PCT = 359, // Your target's HP must be between 50% and 54% of its maximum.
|
||||
IS_HP_BETWEEN_55_AND_59_PCT = 360, // Your target's HP must be between 55% and 59% of its maximum.
|
||||
IS_HP_BETWEEN_5_AND_15_PCT = 398, // Your target's HP must be between 5% and 15% of its maximum.
|
||||
IS_HP_BETWEEN_15_AND_25_PCT = 399, // Your target's HP must be between 15% and 25% of its maximum.
|
||||
IS_HP_BETWEEN_1_AND_25_PCT = 400, // Your target's HP must be at 25% of its maximum or below.
|
||||
IS_HP_BETWEEN_25_AND_35_PCT = 401, // Your target's HP must be between 25% and 35% of its maximum.
|
||||
IS_HP_BETWEEN_35_AND_45_PCT = 402, // Your target's HP must be between 35% and 45% of its maximum.
|
||||
IS_HP_BETWEEN_45_AND_55_PCT = 403, // Your target's HP must be between 45% and 55% of its maximum.
|
||||
IS_HP_BETWEEN_55_AND_65_PCT = 404, // Your target's HP must be between 55% and 65% of its maximum.
|
||||
IS_HP_BETWEEN_65_AND_75_PCT = 405, // Your target's HP must be between 65% and 75% of its maximum.
|
||||
IS_HP_BETWEEN_75_AND_85_PCT = 406, // Your target's HP must be between 75% and 85% of its maximum.
|
||||
IS_HP_BETWEEN_85_AND_95_PCT = 407, // Your target's HP must be between 85% and 95% of its maximum.
|
||||
IS_HP_ABOVE_45_PCT = 408, // Your target's HP must be at least 45% of its maximum.
|
||||
IS_HP_ABOVE_55_PCT = 409, // Your target's HP must be at least 55% of its maximum.
|
||||
UNKNOWN_TOO_MUCH_HP_410 = 410, // Your target has too much HP to be affected by this spell.
|
||||
UNKNOWN_TOO_MUCH_HP_411 = 411, // Your target has too much HP to be affected by this spell.
|
||||
IS_HP_ABOVE_99_PCT = 412, //
|
||||
IS_MANA_ABOVE_10_PCT = 429, // You must have at least 10% of your maximum mana available to cast this spell. | caster restriction |
|
||||
IS_HP_BELOW_5_PCT = 501, //
|
||||
IS_HP_BELOW_10_PCT = 502, //
|
||||
IS_HP_BELOW_15_PCT = 503, //
|
||||
IS_HP_BELOW_20_PCT = 504, // Your target's HP must be at 20% of its maximum or below.
|
||||
IS_HP_BELOW_25_PCT = 505, //
|
||||
IS_HP_BELOW_30_PCT = 506, //
|
||||
IS_HP_BELOW_35_PCT = 507, //
|
||||
IS_HP_BELOW_40_PCT = 508, //
|
||||
IS_HP_BELOW_45_PCT = 509, // Your target's HP must be at 45% of its maximum or below.
|
||||
IS_HP_BELOW_50_PCT = 510, //
|
||||
IS_HP_BELOW_55_PCT = 511, //
|
||||
IS_HP_BELOW_60_PCT = 512, //
|
||||
IS_HP_BELOW_65_PCT = 513, //
|
||||
IS_HP_BELOW_70_PCT = 514, //
|
||||
IS_HP_BELOW_75_PCT = 515, //
|
||||
IS_HP_BELOW_80_PCT = 516, //
|
||||
IS_HP_BELOW_85_PCT = 517, //
|
||||
HAS_BETWEEN_1_TO_2_PETS_ON_HATELIST = 260, // between 1 and 2 pets
|
||||
HAS_BETWEEN_3_TO_5_PETS_ON_HATELIST = 261, // between 3 and 5 pets
|
||||
HAS_BETWEEN_6_TO_9_PETS_ON_HATELIST = 262, // between 6 and 9 pets
|
||||
HAS_BETWEEN_10_TO_14_PETS_ON_HATELIST = 263, // between 10 and 14 pets
|
||||
HAS_MORE_THAN_14_PETS_ON_HATELIST = 264, // 15 or more pets
|
||||
IS_CLASS_CHAIN_OR_PLATE = 304, // This spell will only affect plate or chain wearing classes.
|
||||
IS_HP_BETWEEN_5_AND_9_PCT = 350, // Your target's HP must be between 5% and 9% of its maximum.
|
||||
IS_HP_BETWEEN_10_AND_14_PCT = 351, // Your target's HP must be between 10% and 14% of its maximum.
|
||||
IS_HP_BETWEEN_15_AND_19_PCT = 352, // Your target's HP must be between 15% and 19% of its maximum.
|
||||
IS_HP_BETWEEN_20_AND_24_PCT = 353, // Your target's HP must be between 20% and 24% of its maximum.
|
||||
IS_HP_BETWEEN_25_AND_29_PCT = 354, // Your target's HP must be between 25% and 29% of its maximum.
|
||||
IS_HP_BETWEEN_30_AND_34_PCT = 355, // Your target's HP must be between 30% and 34% of its maximum.
|
||||
IS_HP_BETWEEN_35_AND_39_PCT = 356, // Your target's HP must be between 35% and 39% of its maximum.
|
||||
IS_HP_BETWEEN_40_AND_44_PCT = 357, // Your target's HP must be between 40% and 44% of its maximum.
|
||||
IS_HP_BETWEEN_45_AND_49_PCT = 358, // Your target's HP must be between 45% and 49% of its maximum.
|
||||
IS_HP_BETWEEN_50_AND_54_PCT = 359, // Your target's HP must be between 50% and 54% of its maximum.
|
||||
IS_HP_BETWEEN_55_AND_59_PCT = 360, // Your target's HP must be between 55% and 59% of its maximum.
|
||||
IS_HP_BETWEEN_5_AND_15_PCT = 398, // Your target's HP must be between 5% and 15% of its maximum.
|
||||
IS_HP_BETWEEN_15_AND_25_PCT = 399, // Your target's HP must be between 15% and 25% of its maximum.
|
||||
IS_HP_BETWEEN_1_AND_25_PCT = 400, // Your target's HP must be at 25% of its maximum or below.
|
||||
IS_HP_BETWEEN_25_AND_35_PCT = 401, // Your target's HP must be between 25% and 35% of its maximum.
|
||||
IS_HP_BETWEEN_35_AND_45_PCT = 402, // Your target's HP must be between 35% and 45% of its maximum.
|
||||
IS_HP_BETWEEN_45_AND_55_PCT = 403, // Your target's HP must be between 45% and 55% of its maximum.
|
||||
IS_HP_BETWEEN_55_AND_65_PCT = 404, // Your target's HP must be between 55% and 65% of its maximum.
|
||||
IS_HP_BETWEEN_65_AND_75_PCT = 405, // Your target's HP must be between 65% and 75% of its maximum.
|
||||
IS_HP_BETWEEN_75_AND_85_PCT = 406, // Your target's HP must be between 75% and 85% of its maximum.
|
||||
IS_HP_BETWEEN_85_AND_95_PCT = 407, // Your target's HP must be between 85% and 95% of its maximum.
|
||||
IS_HP_ABOVE_45_PCT = 408, // Your target's HP must be at least 45% of its maximum.
|
||||
IS_HP_ABOVE_55_PCT = 409, // Your target's HP must be at least 55% of its maximum.
|
||||
UNKNOWN_TOO_MUCH_HP_410 = 410, // Your target has too much HP to be affected by this spell.
|
||||
UNKNOWN_TOO_MUCH_HP_411 = 411, // Your target has too much HP to be affected by this spell.
|
||||
IS_HP_ABOVE_99_PCT = 412, //
|
||||
IS_MANA_ABOVE_10_PCT = 429, // You must have at least 10% of your maximum mana available to cast this spell. | caster restriction |
|
||||
IS_HP_BELOW_5_PCT = 501, //
|
||||
IS_HP_BELOW_10_PCT = 502, //
|
||||
IS_HP_BELOW_15_PCT = 503, //
|
||||
IS_HP_BELOW_20_PCT = 504, // Your target's HP must be at 20% of its maximum or below.
|
||||
IS_HP_BELOW_25_PCT = 505, //
|
||||
IS_HP_BELOW_30_PCT = 506, //
|
||||
IS_HP_BELOW_35_PCT = 507, //
|
||||
IS_HP_BELOW_40_PCT = 508, //
|
||||
IS_HP_BELOW_45_PCT = 509, // Your target's HP must be at 45% of its maximum or below.
|
||||
IS_HP_BELOW_50_PCT = 510, //
|
||||
IS_HP_BELOW_55_PCT = 511, //
|
||||
IS_HP_BELOW_60_PCT = 512, //
|
||||
IS_HP_BELOW_65_PCT = 513, //
|
||||
IS_HP_BELOW_70_PCT = 514, //
|
||||
IS_HP_BELOW_75_PCT = 515, //
|
||||
IS_HP_BELOW_80_PCT = 516, //
|
||||
IS_HP_BELOW_85_PCT = 517, //
|
||||
IS_HP_BELOW_90_PCT = 518, // This ability requires you to be at or below 90% of your maximum HP. | caster restriction |
|
||||
IS_HP_BELOW_95_PCT = 519, //
|
||||
IS_HP_BELOW_95_PCT = 519, //
|
||||
IS_MANA_BELOW_UNKNOWN_PCT = 521, //
|
||||
IS_ENDURANCE_BELOW_40_PCT = 522, //
|
||||
IS_MANA_BELOW_40_PCT = 523, //
|
||||
IS_HP_ABOVE_20_PCT = 524, // Your target's HP must be at least 21% of its maximum.
|
||||
IS_ENDURANCE_BELOW_40_PCT = 522, //
|
||||
IS_MANA_BELOW_40_PCT = 523, //
|
||||
IS_HP_ABOVE_20_PCT = 524, // Your target's HP must be at least 21% of its maximum.
|
||||
IS_BODY_TYPE_UNDEFINED = 600, // This spell will only work on creatures with an undefined body type.
|
||||
IS_BODY_TYPE_HUMANOID = 601, // This spell will only work on humanoid creatures.
|
||||
IS_BODY_TYPE_WEREWOLF = 602, // This spell will only work on lycanthrope creatures.
|
||||
IS_BODY_TYPE_UNDEAD = 603, // This spell will only work on undead creatures.
|
||||
IS_BODY_TYPE_GIANTS = 604, // This spell will only work on giants.
|
||||
IS_BODY_TYPE_CONSTRUCTS = 605, // This spell will only work on constructs.
|
||||
IS_BODY_TYPE_EXTRAPLANAR = 606, // This spell will only work on extraplanar creatures.
|
||||
IS_BODY_TYPE_MAGICAL_CREATURE = 607, // This spell will only work on creatures constructed from magic.
|
||||
IS_BODY_TYPE_UNDEADPET = 608, // This spell will only work on animated undead servants.
|
||||
IS_BODY_TYPE_KAELGIANT = 609, // This spell will only work on the Giants of Kael Drakkal.
|
||||
IS_BODY_TYPE_COLDAIN = 610, // This spell will only work on Coldain Dwarves.
|
||||
IS_BODY_TYPE_VAMPIRE = 612, // This spell will only work on vampires.
|
||||
IS_BODY_TYPE_ATEN_HA_RA = 613, // This spell will only work on Aten Ha Ra.
|
||||
IS_BODY_TYPE_GREATER_AHKEVANS = 614, // This spell will only work on Greater Ahkevans.
|
||||
IS_BODY_TYPE_KHATI_SHA = 615, // This spell will only work on Khati Sha.
|
||||
IS_BODY_TYPE_LORD_INQUISITOR_SERU = 616, // This spell will only work on Lord Inquisitor Seru.
|
||||
IS_BODY_TYPE_GRIEG_VENEFICUS = 617, // This spell will only work on Grieg Veneficus.
|
||||
IS_BODY_TYPE_HUMANOID = 601, // This spell will only work on humanoid creatures.
|
||||
IS_BODY_TYPE_WEREWOLF = 602, // This spell will only work on lycanthrope creatures.
|
||||
IS_BODY_TYPE_UNDEAD = 603, // This spell will only work on undead creatures.
|
||||
IS_BODY_TYPE_GIANTS = 604, // This spell will only work on giants.
|
||||
IS_BODY_TYPE_CONSTRUCTS = 605, // This spell will only work on constructs.
|
||||
IS_BODY_TYPE_EXTRAPLANAR = 606, // This spell will only work on extraplanar creatures.
|
||||
IS_BODY_TYPE_MAGICAL_CREATURE = 607, // This spell will only work on creatures constructed from magic.
|
||||
IS_BODY_TYPE_UNDEADPET = 608, // This spell will only work on animated undead servants.
|
||||
IS_BODY_TYPE_KAELGIANT = 609, // This spell will only work on the Giants of Kael Drakkal.
|
||||
IS_BODY_TYPE_COLDAIN = 610, // This spell will only work on Coldain Dwarves.
|
||||
IS_BODY_TYPE_VAMPIRE = 612, // This spell will only work on vampires.
|
||||
IS_BODY_TYPE_ATEN_HA_RA = 613, // This spell will only work on Aten Ha Ra.
|
||||
IS_BODY_TYPE_GREATER_AHKEVANS = 614, // This spell will only work on Greater Ahkevans.
|
||||
IS_BODY_TYPE_KHATI_SHA = 615, // This spell will only work on Khati Sha.
|
||||
IS_BODY_TYPE_LORD_INQUISITOR_SERU = 616, // This spell will only work on Lord Inquisitor Seru.
|
||||
IS_BODY_TYPE_GRIEG_VENEFICUS = 617, // This spell will only work on Grieg Veneficus.
|
||||
IS_BODY_TYPE_FROM_PLANE_OF_WAR = 619, // This spell will only work on creatures from the Plane of War.
|
||||
IS_BODY_TYPE_LUGGALD = 620, // This spell will only work on Luggalds.
|
||||
IS_BODY_TYPE_ANIMAL = 621, // This spell will only work on animals.
|
||||
IS_BODY_TYPE_INSECT = 622, // This spell will only work on insects.
|
||||
IS_BODY_TYPE_MONSTER = 623, // This spell will only work on monsters.
|
||||
IS_BODY_TYPE_ELEMENTAL = 624, // This spell will only work on elemental creatures.
|
||||
IS_BODY_TYPE_PLANT = 625, // This spell will only work on plants.
|
||||
IS_BODY_TYPE_DRAGON2 = 626, // This spell will only work on dragons.
|
||||
IS_BODY_TYPE_SUMMONED_ELEMENTAL = 627, // This spell will only work on summoned elementals.
|
||||
IS_BODY_TYPE_WARDER = 628, //
|
||||
IS_BODY_TYPE_DRAGON_OF_TOV = 630, // This spell will only work on Dragons of Veeshan's Temple.
|
||||
IS_BODY_TYPE_FAMILIAR = 631, // This spell will only work on familiars.
|
||||
IS_BODY_TYPE_MURAMITE = 634, // This spell will only work on Muramites.
|
||||
IS_NOT_UNDEAD_OR_SUMMONED = 635, //
|
||||
IS_NOT_PLANT = 636, // This spell will not affect plants.
|
||||
IS_NOT_CLIENT = 700, // This spell will not work on adventurers.
|
||||
IS_CLIENT = 701, // This spell will only work on adventurers.
|
||||
IS_BODY_TYPE_LUGGALD = 620, // This spell will only work on Luggalds.
|
||||
IS_BODY_TYPE_ANIMAL = 621, // This spell will only work on animals.
|
||||
IS_BODY_TYPE_INSECT = 622, // This spell will only work on insects.
|
||||
IS_BODY_TYPE_MONSTER = 623, // This spell will only work on monsters.
|
||||
IS_BODY_TYPE_ELEMENTAL = 624, // This spell will only work on elemental creatures.
|
||||
IS_BODY_TYPE_PLANT = 625, // This spell will only work on plants.
|
||||
IS_BODY_TYPE_DRAGON2 = 626, // This spell will only work on dragons.
|
||||
IS_BODY_TYPE_SUMMONED_ELEMENTAL = 627, // This spell will only work on summoned elementals.
|
||||
IS_BODY_TYPE_WARDER = 628, //
|
||||
IS_BODY_TYPE_DRAGON_OF_TOV = 630, // This spell will only work on Dragons of Veeshan's Temple.
|
||||
IS_BODY_TYPE_FAMILIAR = 631, // This spell will only work on familiars.
|
||||
IS_BODY_TYPE_MURAMITE = 634, // This spell will only work on Muramites.
|
||||
IS_NOT_UNDEAD_OR_SUMMONED = 635, //
|
||||
IS_NOT_PLANT = 636, // This spell will not affect plants.
|
||||
IS_NOT_CLIENT = 700, // This spell will not work on adventurers.
|
||||
IS_CLIENT = 701, // This spell will only work on adventurers.
|
||||
IS_LEVEL_ABOVE_42_AND_IS_CLIENT = 800, // This spell will only work on level 43 or higher adventurers.
|
||||
UNKNOWN_812 = 812, // | seen in spell 22616 Thaumatize Pet Mana Regen Base |
|
||||
UNKNOWN_814 = 814, // | seen in spell 22704 Vegetentacles I |
|
||||
IS_TREANT = 815, // This spell will only work on treants.
|
||||
IS_BIXIE2 = 816, // This spell will only work on bixies.
|
||||
IS_SCARECROW = 817, // This spell will only work on scarecrows.
|
||||
IS_VAMPIRE_OR_UNDEAD_OR_UNDEADPET = 818, // This spell will only work on vampires, undead, or animated undead creatures.
|
||||
IS_NOT_VAMPIRE_OR_UNDEAD = 819, // This spell will not work on vampires or undead creatures.
|
||||
IS_CLASS_KNIGHT_HYBRID_MELEE = 820, // This spell will only work on knights, hybrids, or melee classes.
|
||||
IS_CLASS_WARRIOR_CASTER_PRIEST = 821, // This spell will only work on warriors, casters, or priests.
|
||||
IS_TREANT = 815, // This spell will only work on treants.
|
||||
IS_BIXIE2 = 816, // This spell will only work on bixies.
|
||||
IS_SCARECROW = 817, // This spell will only work on scarecrows.
|
||||
IS_VAMPIRE_OR_UNDEAD_OR_UNDEADPET = 818, // This spell will only work on vampires, undead, or animated undead creatures.
|
||||
IS_NOT_VAMPIRE_OR_UNDEAD = 819, // This spell will not work on vampires or undead creatures.
|
||||
IS_CLASS_KNIGHT_HYBRID_MELEE = 820, // This spell will only work on knights, hybrids, or melee classes.
|
||||
IS_CLASS_WARRIOR_CASTER_PRIEST = 821, // This spell will only work on warriors, casters, or priests.
|
||||
UNKNOWN_822 = 822, // | seen in spell 22870 Morell's Distraction 822 |
|
||||
IS_END_BELOW_21_PCT = 825, // This ability requires you to be at or below 21% of your maximum endurance.
|
||||
IS_END_BELOW_25_PCT = 826, // This ability requires you to be at or below 25% of your maximum endurance.
|
||||
IS_END_BELOW_29_PCT = 827, // This ability requires you to be at or below 29% of your maximum endurance.
|
||||
IS_REGULAR_SERVER = 836, //
|
||||
IS_PROGRESSION_SERVER = 837, //
|
||||
IS_END_BELOW_21_PCT = 825, // This ability requires you to be at or below 21% of your maximum endurance.
|
||||
IS_END_BELOW_25_PCT = 826, // This ability requires you to be at or below 25% of your maximum endurance.
|
||||
IS_END_BELOW_29_PCT = 827, // This ability requires you to be at or below 29% of your maximum endurance.
|
||||
IS_REGULAR_SERVER = 836, //
|
||||
IS_PROGRESSION_SERVER = 837, //
|
||||
IS_GOD_EXPANSION_UNLOCKED = 839, //
|
||||
UNKNOWN_840 = 840, // | caster restriction | seen in spell 6883 Expedient Recovery
|
||||
UNKNOWN_841 = 841, // | caster restriction | seen in spell 32192 Merciless Blow
|
||||
IS_HUMANOID_LEVEL_84_MAX = 842, //
|
||||
IS_HUMANOID_LEVEL_86_MAX = 843, //
|
||||
IS_HUMANOID_LEVEL_88_MAX = 844, //
|
||||
IS_HUMANOID_LEVEL_84_MAX = 842, //
|
||||
IS_HUMANOID_LEVEL_86_MAX = 843, //
|
||||
IS_HUMANOID_LEVEL_88_MAX = 844, //
|
||||
HAS_CRYSTALLIZED_FLAME_BUFF = 845, // This spell will only work on targets afflicted by Crystallized Flame. | On live spell does not appear to be a buff
|
||||
HAS_INCENDIARY_OOZE_BUFF = 847, // This spell will only work on targets afflicted by Incendiary Ooze.
|
||||
IS_LEVEL_90_MAX = 860, //
|
||||
IS_LEVEL_92_MAX = 861, //
|
||||
IS_LEVEL_94_MAX = 862, //
|
||||
IS_LEVEL_95_MAX = 863, //
|
||||
IS_LEVEL_97_MAX = 864, //
|
||||
IS_LEVEL_99_MAX = 865, //
|
||||
HAS_INCENDIARY_OOZE_BUFF = 847, // This spell will only work on targets afflicted by Incendiary Ooze.
|
||||
IS_LEVEL_90_MAX = 860, //
|
||||
IS_LEVEL_92_MAX = 861, //
|
||||
IS_LEVEL_94_MAX = 862, //
|
||||
IS_LEVEL_95_MAX = 863, //
|
||||
IS_LEVEL_97_MAX = 864, //
|
||||
IS_LEVEL_99_MAX = 865, //
|
||||
HAS_WEAPONSTANCE_DEFENSIVE_PROFICIENCY = 866, // | caster restriction |
|
||||
HAS_WEAPONSTANCE_TWO_HAND_PROFICIENCY = 867, // | caster restriction |
|
||||
HAS_WEAPONSTANCE_TWO_HAND_PROFICIENCY = 867, // | caster restriction |
|
||||
HAS_WEAPONSTANCE_DUAL_WEILD_PROFICIENCY = 868, // | caster restriction |
|
||||
IS_LEVEL_100_MAX = 869, //
|
||||
IS_LEVEL_102_MAX = 870, //
|
||||
IS_LEVEL_104_MAX = 871, //
|
||||
IS_LEVEL_105_MAX = 872, //
|
||||
IS_LEVEL_107_MAX = 873, //
|
||||
IS_LEVEL_109_MAX = 874, //
|
||||
IS_LEVEL_110_MAX = 875, //
|
||||
IS_LEVEL_112_MAX = 876, //
|
||||
IS_LEVEL_114_MAX = 877, //
|
||||
IS_LEVEL_100_MAX = 869, //
|
||||
IS_LEVEL_102_MAX = 870, //
|
||||
IS_LEVEL_104_MAX = 871, //
|
||||
IS_LEVEL_105_MAX = 872, //
|
||||
IS_LEVEL_107_MAX = 873, //
|
||||
IS_LEVEL_109_MAX = 874, //
|
||||
IS_LEVEL_110_MAX = 875, //
|
||||
IS_LEVEL_112_MAX = 876, //
|
||||
IS_LEVEL_114_MAX = 877, //
|
||||
HAS_TBL_ESIANTI_ACCESS = 997, // This spell will only transport adventurers who have gained access to Esianti: Palace of the Winds. | not implemented
|
||||
HAS_ITEM_CLOCKWORK_SCRAPS = 999, //
|
||||
IS_BETWEEN_LEVEL_1_AND_75 = 1000, //
|
||||
IS_BETWEEN_LEVEL_76_AND_85 = 1001, //
|
||||
IS_BETWEEN_LEVEL_86_AND_95 = 1002, //
|
||||
IS_BETWEEN_LEVEL_96_AND_105 = 1003, //
|
||||
IS_HP_LESS_THAN_80_PCT = 1004, //
|
||||
IS_LEVEL_ABOVE_34 = 1474, // Your target must be level 35 or higher.
|
||||
IN_TWO_HANDED_STANCE = 2000, // You must be in your two-handed stance to use this ability.
|
||||
IN_DUAL_WIELD_HANDED_STANCE = 2001, // You must be in your dual-wielding stance to use this ability.
|
||||
IN_SHIELD_STANCE = 2002, // You must be in your shield stance to use this ability.
|
||||
NOT_IN_TWO_HANDED_STANCE = 2010, // You may not use this ability if you are in your two-handed stance.
|
||||
NOT_IN_DUAL_WIELD_HANDED_STANCE = 2011, // You may not use this ability if you are in your dual-wielding stance.
|
||||
NOT_IN_SHIELD_STANCE = 2012, // You may not use this ability if you are in your shield stance.
|
||||
LEVEL_46_MAX = 2761, //
|
||||
DISABLED_UNTIL_EXPANSION_ROK = 7000, // This ability is disabled until Ruins of Kunark.
|
||||
DISABLED_UNTIL_EXPANSION_SOV = 7001, // This ability is disabled until Scars of Velious.
|
||||
DISABLED_UNTIL_EXPANSION_SOL = 7002, // This ability is disabled until Shadows of Luclin.
|
||||
DISABLED_UNTIL_EXPANSION_POP = 7003, // This ability is disabled until Planes of Power.
|
||||
DISABLED_UNTIL_EXPANSION_LOY = 7004, // This ability is disabled until Legacy of Ykesha.
|
||||
DISABLED_UNTIL_EXPANSION_LDON = 7005, // This ability is disabled until Lost Dungeons of Norrath.
|
||||
DISABLED_UNTIL_EXPANSION_GOD = 7006, // This ability is disabled until Gates of Discord.
|
||||
DISABLED_UNTIL_EXPANSION_OOW = 7007, // This ability is disabled until Omens of War.
|
||||
DISABLED_UNTIL_EXPANSION_DON = 7008, // This ability is disabled until Dragons of Norrath.
|
||||
DISABLED_UNTIL_EXPANSION_DOD = 7009, // This ability is disabled until Depths of Darkhollow.
|
||||
DISABLED_UNTIL_EXPANSION_POR = 7010, // This ability is disabled until Prophecy of Ro.
|
||||
DISABLED_UNTIL_EXPANSION_TSS = 7011, // This ability is disabled until Serpent's Spine.
|
||||
DISABLED_UNTIL_EXPANSION_TBS = 7012, // This ability is disabled until Buried Sea.
|
||||
DISABLED_UNTIL_EXPANSION_SOF = 7013, // This ability is disabled until Secrets of Faydwer.
|
||||
DISABLED_UNTIL_EXPANSION_SOD = 7014, // This ability is disabled until Seeds of Destruction.
|
||||
DISABLED_UNTIL_EXPANSION_UF = 7015, // This ability is disabled until Underfoot.
|
||||
DISABLED_UNTIL_EXPANSION_HOT = 7016, // This ability is disabled until House of Thule.
|
||||
DISABLED_UNTIL_EXPANSION_VOA = 7017, // This ability is disabled until Veil of Alaris.
|
||||
DISABLED_UNTIL_EXPANSION_ROF = 7018, // This ability is disabled until Rain of Fear.
|
||||
DISABLED_UNTIL_EXPANSION_COF = 7019, // This ability is disabled until Call of the Forsaken.
|
||||
DISABLED_UNTIL_EXPANSION_TDS = 7020, // This ability is disabled until Darkened Sea.
|
||||
DISABLED_UNTIL_EXPANSION_TBM = 7021, // This ability is disabled until Broken Mirror.
|
||||
DISABLED_UNTIL_EXPANSION_EOK = 7022, // This ability is disabled until Empires of Kunark.
|
||||
DISABLED_UNTIL_EXPANSION_ROS = 7023, // This ability is disabled until Ring of Scale.
|
||||
DISABLED_UNTIL_EXPANSION_TBL = 7024, // This ability is disabled until The Burning Lands.
|
||||
DISABLED_UNTIL_EXPANSION_TOV = 7025, // This ability is disabled until Torment of Velious.
|
||||
DISABLED_UNTIL_EXPANSION_COV = 7026, // This ability is disabled until Claws of Veeshan.
|
||||
HAS_NO_MANA_BURN_BUFF = 8450, // This spell will not take hold until the effects of the previous Mana Burn have expired.
|
||||
HAS_ITEM_CLOCKWORK_SCRAPS = 999, //
|
||||
IS_BETWEEN_LEVEL_1_AND_75 = 1000, //
|
||||
IS_BETWEEN_LEVEL_76_AND_85 = 1001, //
|
||||
IS_BETWEEN_LEVEL_86_AND_95 = 1002, //
|
||||
IS_BETWEEN_LEVEL_96_AND_105 = 1003, //
|
||||
IS_HP_LESS_THAN_80_PCT = 1004, //
|
||||
IS_LEVEL_ABOVE_34 = 1474, // Your target must be level 35 or higher.
|
||||
IN_TWO_HANDED_STANCE = 2000, // You must be in your two-handed stance to use this ability.
|
||||
IN_DUAL_WIELD_HANDED_STANCE = 2001, // You must be in your dual-wielding stance to use this ability.
|
||||
IN_SHIELD_STANCE = 2002, // You must be in your shield stance to use this ability.
|
||||
NOT_IN_TWO_HANDED_STANCE = 2010, // You may not use this ability if you are in your two-handed stance.
|
||||
NOT_IN_DUAL_WIELD_HANDED_STANCE = 2011, // You may not use this ability if you are in your dual-wielding stance.
|
||||
NOT_IN_SHIELD_STANCE = 2012, // You may not use this ability if you are in your shield stance.
|
||||
LEVEL_46_MAX = 2761, //
|
||||
DISABLED_UNTIL_EXPANSION_ROK = 7000, // This ability is disabled until Ruins of Kunark.
|
||||
DISABLED_UNTIL_EXPANSION_SOV = 7001, // This ability is disabled until Scars of Velious.
|
||||
DISABLED_UNTIL_EXPANSION_SOL = 7002, // This ability is disabled until Shadows of Luclin.
|
||||
DISABLED_UNTIL_EXPANSION_POP = 7003, // This ability is disabled until Planes of Power.
|
||||
DISABLED_UNTIL_EXPANSION_LOY = 7004, // This ability is disabled until Legacy of Ykesha.
|
||||
DISABLED_UNTIL_EXPANSION_LDON = 7005, // This ability is disabled until Lost Dungeons of Norrath.
|
||||
DISABLED_UNTIL_EXPANSION_GOD = 7006, // This ability is disabled until Gates of Discord.
|
||||
DISABLED_UNTIL_EXPANSION_OOW = 7007, // This ability is disabled until Omens of War.
|
||||
DISABLED_UNTIL_EXPANSION_DON = 7008, // This ability is disabled until Dragons of Norrath.
|
||||
DISABLED_UNTIL_EXPANSION_DOD = 7009, // This ability is disabled until Depths of Darkhollow.
|
||||
DISABLED_UNTIL_EXPANSION_POR = 7010, // This ability is disabled until Prophecy of Ro.
|
||||
DISABLED_UNTIL_EXPANSION_TSS = 7011, // This ability is disabled until Serpent's Spine.
|
||||
DISABLED_UNTIL_EXPANSION_TBS = 7012, // This ability is disabled until Buried Sea.
|
||||
DISABLED_UNTIL_EXPANSION_SOF = 7013, // This ability is disabled until Secrets of Faydwer.
|
||||
DISABLED_UNTIL_EXPANSION_SOD = 7014, // This ability is disabled until Seeds of Destruction.
|
||||
DISABLED_UNTIL_EXPANSION_UF = 7015, // This ability is disabled until Underfoot.
|
||||
DISABLED_UNTIL_EXPANSION_HOT = 7016, // This ability is disabled until House of Thule.
|
||||
DISABLED_UNTIL_EXPANSION_VOA = 7017, // This ability is disabled until Veil of Alaris.
|
||||
DISABLED_UNTIL_EXPANSION_ROF = 7018, // This ability is disabled until Rain of Fear.
|
||||
DISABLED_UNTIL_EXPANSION_COF = 7019, // This ability is disabled until Call of the Forsaken.
|
||||
DISABLED_UNTIL_EXPANSION_TDS = 7020, // This ability is disabled until Darkened Sea.
|
||||
DISABLED_UNTIL_EXPANSION_TBM = 7021, // This ability is disabled until Broken Mirror.
|
||||
DISABLED_UNTIL_EXPANSION_EOK = 7022, // This ability is disabled until Empires of Kunark.
|
||||
DISABLED_UNTIL_EXPANSION_ROS = 7023, // This ability is disabled until Ring of Scale.
|
||||
DISABLED_UNTIL_EXPANSION_TBL = 7024, // This ability is disabled until The Burning Lands.
|
||||
DISABLED_UNTIL_EXPANSION_TOV = 7025, // This ability is disabled until Torment of Velious.
|
||||
DISABLED_UNTIL_EXPANSION_COV = 7026, // This ability is disabled until Claws of Veeshan.
|
||||
HAS_NO_MANA_BURN_BUFF = 8450, // This spell will not take hold until the effects of the previous Mana Burn have expired.
|
||||
IS_RACE_FIRST_CUSTOM = 10000, // | custom range to restrict targets or casters by race *not on live* |
|
||||
IS_RACE_LAST_CUSTOM = 11000, // | custom range to restrict targets or casters by race *not on live* |
|
||||
IS_CLIENT_AND_MALE_PLATE_USER = 11044, // Your target wouldn't look right as that Jann.
|
||||
IS_CLEINT_AND_MALE_DRUID_ENCHANTER_MAGICIAN_NECROANCER_SHAMAN_OR_WIZARD = 11090, // Your target wouldn't look right as that Jann.
|
||||
IS_CLIENT_AND_MALE_BEASTLORD_BERSERKER_MONK_RANGER_OR_ROGUE = 11209, // Your target wouldn't look right as that Jann.
|
||||
IS_CLIENT_AND_FEMALE_PLATE_USER = 11210, // Your target wouldn't look right as that Jann.
|
||||
IS_CLIENT_AND_FEMALE_DRUID_ENCHANTER_MAGICIAN_NECROANCER_SHAMAN_OR_WIZARD = 11211, // Your target wouldn't look right as that Jann.
|
||||
IS_CLIENT_AND_FEMALE_BEASTLORD_BERSERKER_MONK_RANGER_OR_ROGUE = 11248, // Your target wouldn't look right as that Jann.
|
||||
HAS_TRAVELED_TO_STRATOS = 11260, // You must travel to Stratos at least once before wishing to go there.
|
||||
HAS_TRAVELED_TO_AALISHAI = 11261, // You must travel to Aalishai at least once before wishing to go there.
|
||||
HAS_TRAVELED_TO_MEARATS = 11268, // You must travel to Mearatas at least once before wishing to go there.
|
||||
HAS_NO_ILLUSIONS_OF_GRANDEUR_BUFF = 12519, //
|
||||
IS_HP_ABOVE_50_PCT = 16010, //
|
||||
IS_HP_UNDER_50_PCT = 16031, //
|
||||
IS_OFF_HAND_EQUIPED = 27672, // You must be wielding a weapon or shield in your offhand to use this ability.
|
||||
IS_CLIENT_AND_MALE_PLATE_USER = 11044, // Your target wouldn't look right as that Jann.
|
||||
IS_CLEINT_AND_MALE_DRUID_ENCHANTER_MAGICIAN_NECROANCER_SHAMAN_OR_WIZARD = 11090, // Your target wouldn't look right as that Jann.
|
||||
IS_CLIENT_AND_MALE_BEASTLORD_BERSERKER_MONK_RANGER_OR_ROGUE = 11209, // Your target wouldn't look right as that Jann.
|
||||
IS_CLIENT_AND_FEMALE_PLATE_USER = 11210, // Your target wouldn't look right as that Jann.
|
||||
IS_CLIENT_AND_FEMALE_DRUID_ENCHANTER_MAGICIAN_NECROANCER_SHAMAN_OR_WIZARD = 11211, // Your target wouldn't look right as that Jann.
|
||||
IS_CLIENT_AND_FEMALE_BEASTLORD_BERSERKER_MONK_RANGER_OR_ROGUE = 11248, // Your target wouldn't look right as that Jann.
|
||||
HAS_TRAVELED_TO_STRATOS = 11260, // You must travel to Stratos at least once before wishing to go there.
|
||||
HAS_TRAVELED_TO_AALISHAI = 11261, // You must travel to Aalishai at least once before wishing to go there.
|
||||
HAS_TRAVELED_TO_MEARATS = 11268, // You must travel to Mearatas at least once before wishing to go there.
|
||||
HAS_NO_ILLUSIONS_OF_GRANDEUR_BUFF = 12519, //
|
||||
IS_HP_ABOVE_50_PCT = 16010, //
|
||||
IS_HP_UNDER_50_PCT = 16031, //
|
||||
IS_OFF_HAND_EQUIPED = 27672, // You must be wielding a weapon or shield in your offhand to use this ability.
|
||||
HAS_NO_PACT_OF_FATE_RECOURSE_BUFF = 29556, // This spell will not work while Pact of Fate Recourse is active. | caster restriction |
|
||||
HAS_NO_SHROUD_OF_PRAYER_BUFF = 32339, // Your target cannot receive another Quiet Prayer this soon.
|
||||
IS_MANA_BELOW_20_PCT = 38311, // This ability requires you to be at or below 20% of your maximum mana.
|
||||
IS_MANA_ABOVE_50_PCT = 38312, // This ability requires you to be at or above 50% of your maximum mana.
|
||||
COMPLETED_ACHIEVEMENT_LEGENDARY_ANSWERER = 39281, // You have completed Legendary Answerer.
|
||||
HAS_NO_SHROUD_OF_PRAYER_BUFF = 32339, // Your target cannot receive another Quiet Prayer this soon.
|
||||
IS_MANA_BELOW_20_PCT = 38311, // This ability requires you to be at or below 20% of your maximum mana.
|
||||
IS_MANA_ABOVE_50_PCT = 38312, // This ability requires you to be at or above 50% of your maximum mana.
|
||||
COMPLETED_ACHIEVEMENT_LEGENDARY_ANSWERER = 39281, // You have completed Legendary Answerer.
|
||||
HAS_NO_ROGUES_FURY_BUFF = 40297, // This spell will not affect anyone that currently has Rogue's Fury active. | caster restriction |
|
||||
NOT_COMPLETED_ACHIEVEMENT_LEGENDARY_ANSWERER = 42280, // You must complete Legendary Answerer.
|
||||
IS_SUMMONED_OR_UNDEAD = 49326, //
|
||||
IS_CLASS_CASTER_PRIEST = 49529, //
|
||||
NOT_COMPLETED_ACHIEVEMENT_LEGENDARY_ANSWERER = 42280, // You must complete Legendary Answerer.
|
||||
IS_SUMMONED_OR_UNDEAD = 49326, //
|
||||
IS_CLASS_CASTER_PRIEST = 49529, //
|
||||
IS_END_OR_MANA_ABOVE_20_PCT = 49543, // You must have at least 20% of your maximum mana and endurance to use this ability. //pure melee class check end, other check mana
|
||||
IS_END_OR_MANA_BELOW_30_PCT = 49573, // Your target already has 30% or more of their maximum mana or endurance. //pure melee class check the, other check more
|
||||
IS_CLASS_BARD2 = 49574, //
|
||||
IS_NOT_CLASS_BARD = 49575, //
|
||||
HAS_NO_FURIOUS_RAMPAGE_BUFF = 49612, // This ability cannot be activated while Furious Rampage is active.
|
||||
IS_END_OR_MANA_BELOW_30_PCT2 = 49809, // You can only perform this solo if you have less than 30% mana or endurance.
|
||||
HAS_NO_HARMONIOUS_PRECISION_BUFF = 50003, // This spell will not work if you have the Harmonious Precision line active.
|
||||
IS_CLASS_BARD2 = 49574, //
|
||||
IS_NOT_CLASS_BARD = 49575, //
|
||||
HAS_NO_FURIOUS_RAMPAGE_BUFF = 49612, // This ability cannot be activated while Furious Rampage is active.
|
||||
IS_END_OR_MANA_BELOW_30_PCT2 = 49809, // You can only perform this solo if you have less than 30% mana or endurance.
|
||||
HAS_NO_HARMONIOUS_PRECISION_BUFF = 50003, // This spell will not work if you have the Harmonious Precision line active.
|
||||
HAS_NO_HARMONIOUS_EXPANSE_BUFF = 50009, // This spell will not work if you have the Harmonious Expanse line active.
|
||||
UNKNOWN_99999 = 99999, // | caster restriction | works will spell 27672 Strike of Ire
|
||||
};
|
||||
@@ -528,6 +540,15 @@ enum ReflectSpellType
|
||||
RELFECT_ALL_SINGLE_TARGET_SPELLS = 3,
|
||||
REFLECT_ALL_SPELLS = 4,
|
||||
};
|
||||
//For better organizing in proc effects, not used in spells.
|
||||
enum ProcType
|
||||
{
|
||||
MELEE_PROC = 1,
|
||||
RANGED_PROC = 2,
|
||||
DEFENSIVE_PROC = 3,
|
||||
SKILL_PROC = 4,
|
||||
SKILL_PROC_SUCCESS = 5,
|
||||
};
|
||||
|
||||
enum SpellTypes : uint32
|
||||
{
|
||||
@@ -775,7 +796,7 @@ typedef enum {
|
||||
//#define SE_CorpseBomb 70 // not used
|
||||
#define SE_NecPet 71 // implemented
|
||||
//#define SE_PreserveCorpse 72 // not used
|
||||
#define SE_BindSight 73 // implemented
|
||||
#define SE_BindSight 73 // implemented, @Vision, see through the eyes of your target, click off buff to end effect, base: 1, limit: none, max: none
|
||||
#define SE_FeignDeath 74 // implemented
|
||||
#define SE_VoiceGraft 75 // implemented
|
||||
#define SE_Sentinel 76 // *not implemented?(just seems to send a message)
|
||||
@@ -863,7 +884,7 @@ typedef enum {
|
||||
#define SE_Reflect 158 // implemented, @SpellMisc, reflect casted detrimental spell back at caster, base: chance pct, limit: resist modifier (positive value reduces resists), max: pct of base dmg mod (50=50pct of base)
|
||||
#define SE_AllStats 159 // implemented
|
||||
//#define SE_MakeDrunk 160 // *not implemented - Effect works entirely client side (Should check against tolerance)
|
||||
#define SE_MitigateSpellDamage 161 // implemented - rune with max value
|
||||
#define SE_MitigateSpellDamage 161 // implemented, @Runes, mitigate incoming spell damage by percentage until rune fades, base: percent mitigation, limit: max dmg absorbed per hit, max: rune amt, Note: If placed on item or AA, will provide stackable percent mitigation.
|
||||
#define SE_MitigateMeleeDamage 162 // implemented - rune with max value
|
||||
#define SE_NegateAttacks 163 // implemented
|
||||
#define SE_AppraiseLDonChest 164 // implemented
|
||||
@@ -907,12 +928,12 @@ typedef enum {
|
||||
#define SE_IllusionOther 202 // implemented - Project Illusion
|
||||
#define SE_MassGroupBuff 203 // implemented
|
||||
#define SE_GroupFearImmunity 204 // implemented - (Does not use bonus)
|
||||
#define SE_Rampage 205 // implemented
|
||||
#define SE_Rampage 205 // implemented, @Combat Instant, Perform a primary slot combat rounds on all creatures within a 40 foot radius, base: number of attack rounds, limit: max entities hit per round, max: none, Note: AE range is 40 by default. Custom: Set field 'aoe_range' to override default. Adding additional attacks and hit count limit.
|
||||
#define SE_AETaunt 206 // implemented
|
||||
#define SE_FleshToBone 207 // implemented
|
||||
//#define SE_PurgePoison 208 // not used
|
||||
#define SE_DispelBeneficial 209 // implemented, @Dispel, removes only beneficial effects on a target, base: pct chance (950=95%), limit: none, max: none
|
||||
#define SE_PetShield 210 // implmented, @ShieldAbility, allows pet to 'shield' owner for 50 pct of damage taken for a duration, base: Time multiplier 1=12 seconds, 2=24 ect, limit: mitigation on pet owner override (not on live), max: mitigation on pet overide (not on live)
|
||||
#define SE_PetShield 210 // implmented, @ShieldAbility, allows pet to 'shield' owner for 50 pct of damage taken for a duration, base: Time multiplier 1=12 seconds, 2=24 ect, limit: mitigation on pet owner override (not on live), max: mitigation on pet overide (not on live)
|
||||
#define SE_AEMelee 211 // implemented TO DO: Implement to allow NPC use (client only atm).
|
||||
#define SE_FrenziedDevastation 212 // implemented - increase spell criticals + all DD spells cast 2x mana.
|
||||
#define SE_PetMaxHP 213 // implemented[AA] - increases the maximum hit points of your pet
|
||||
@@ -947,7 +968,7 @@ typedef enum {
|
||||
#define SE_IncreaseChanceMemwipe 242 // implemented - @Memblur, increases the chance to wipe hate with memory blurr, base: chance pct, limit: none, max: none, Note: Mods final blur chance after other bonuses added.
|
||||
#define SE_CharmBreakChance 243 // implemented - Total Domination
|
||||
#define SE_RootBreakChance 244 // implemented[AA] reduce the chance that your root will break.
|
||||
#define SE_TrapCircumvention 245 // *not implemented[AA] - decreases the chance that you will set off a trap when opening a chest
|
||||
#define SE_TrapCircumvention 245 // implemented, @Traps, decreases the chance that you will set off a trap when opening a chest or other similar container by percentage, base: chance modifer, limit: none, max: none
|
||||
#define SE_SetBreathLevel 246 // *not implemented as bonus
|
||||
#define SE_RaiseSkillCap 247 // implemented[AA] - adds skill over the skill cap.
|
||||
#define SE_SecondaryForte 248 // not implemented as bonus(gives you a 2nd specialize skill that can go past 50 to 100)
|
||||
@@ -983,17 +1004,17 @@ typedef enum {
|
||||
#define SE_FinishingBlow 278 // implemented[AA] - chance to do massive damage under 10% HP (base1 = chance, base2 = damage)
|
||||
#define SE_Flurry 279 // implemented
|
||||
#define SE_PetFlurry 280 // implemented[AA]
|
||||
#define SE_FeignedMinion 281 // *not implemented[AA] ability allows you to instruct your pet to feign death via the '/pet feign' command. value = succeed chance
|
||||
#define SE_FeignedMinion 281 // implemented, ability allows you to instruct your pet to feign death via the '/pet feign' command, base: succeed chance, limit: none, max: none, Note: Only implemented as an AA.
|
||||
#define SE_ImprovedBindWound 282 // implemented[AA] - increase bind wound amount by percent.
|
||||
#define SE_DoubleSpecialAttack 283 // implemented[AA] - Chance to perform second special attack as monk
|
||||
//#define SE_LoHSetHeal 284 // not used
|
||||
#define SE_NimbleEvasion 285 // *not implemented - base1 = 100 for max
|
||||
#define SE_FcDamageAmt 286 // implemented, @Fc, On Caster, spell damage mod flat amt, base: amt
|
||||
#define SE_SpellDurationIncByTic 287 // implemented, @Fc, SPA: 287, SE_SpellDurationIncByTic, On Caster, spell buff duration mod, base: tics
|
||||
#define SE_SkillAttackProc 288 // implemented[AA] - Chance to proc spell on skill attack usage (ex. Dragon Punch)
|
||||
#define SE_SkillAttackProc 288 // implemented, @Procs, chance to cast a spell when using a skill, base: chance, limit: skill, max: spellid, note: if used in AA the spell id is set in aa_ranks spell field, chance is calculated as 100% = value 1000.
|
||||
#define SE_CastOnFadeEffect 289 // implemented - Triggers only if fades after natural duration.
|
||||
#define SE_IncreaseRunSpeedCap 290 // implemented[AA] - increases run speed over the hard cap
|
||||
#define SE_Purify 291 // implemented, @Dispel, remove up specified amount of detiremental spells, base: amt removed, limit: none, max: none, Note: excluding charm, fear, resurrection, and revival sickness
|
||||
#define SE_Purify 291 // implemented, @Dispel, remove up specified amount of detiremental spells, base: amt removed, limit: none, max: none, Note: excluding charm, fear, resurrection, and revival sickness
|
||||
#define SE_StrikeThrough2 292 // implemented[AA] - increasing chance of bypassing an opponent's special defenses, such as dodge, block, parry, and riposte.
|
||||
#define SE_FrontalStunResist 293 // implemented[AA] - Reduce chance to be stunned from front. -- live descriptions sounds like this isn't limited to frontal anymore
|
||||
#define SE_CriticalSpellChance 294 // implemented - increase chance to critical hit and critical damage modifier.
|
||||
@@ -1001,19 +1022,19 @@ typedef enum {
|
||||
#define SE_FcSpellVulnerability 296 // implemented, @Fc, On Target, spell damage taken mod pct, base: min pct, limit: max pct
|
||||
#define SE_FcDamageAmtIncoming 297 // implemetned, @Fc, On Target, damage taken flat amt, base: amt
|
||||
#define SE_ChangeHeight 298 // implemented
|
||||
#define SE_WakeTheDead 299 // implemented
|
||||
#define SE_WakeTheDead 299 // implemented, @Pets, summon one temporary pet from nearby corpses that last a set duration, base: none, limit: none, max: duration (seconds). Note: max range of corpse is 250.
|
||||
#define SE_Doppelganger 300 // implemented
|
||||
#define SE_ArcheryDamageModifier 301 // implemented[AA] - increase archery damage by percent
|
||||
#define SE_FcDamagePctCrit 302 // implemented, @Fc, On Caster, spell damage mod pct, base: min pct, limit: max pct, Note: applied after critical hits has been calculated.
|
||||
#define SE_FcDamageAmtCrit 303 // implemented, @Fc, On Caster, spell damage mod flat amt, base: amt
|
||||
#define SE_OffhandRiposteFail 304 // implemented as bonus - enemy cannot riposte offhand attacks
|
||||
#define SE_MitigateDamageShield 305 // implemented - off hand attacks only (Shielding Resistance)
|
||||
//#define SE_ArmyOfTheDead 306 // *not implemented NecroAA - This ability calls up to five shades of nearby corpses back to life to serve the necromancer. The soulless abominations will mindlessly fight the target until called back to the afterlife some time later. The first rank summons up to three shades that serve for 60 seconds, and each additional rank adds one more possible shade and increases their duration by 15 seconds
|
||||
#define SE_ArmyOfTheDead 306 // implemented, @Pets, summon multiple temporary pets from nearby corpses that last a set duration, base: amount of corpses that a pet can summon from, limit: none, max: duration (seconds). Note: max range of corpse is 250.
|
||||
//#define SE_Appraisal 307 // *not implemented Rogue AA - This ability allows you to estimate the selling price of an item you are holding on your cursor.
|
||||
#define SE_ZoneSuspendMinion 308 // implemented, @Pet, allow suspended pets to be resummoned upon zoning, base: 1, limit: none, max: none, Calc: Bool
|
||||
#define SE_GateCastersBindpoint 309 // implemented - Gate to casters bind point
|
||||
#define SE_ReduceReuseTimer 310 // implemented, @Fc, On Caster, disc reuse time mod, base: milliseconds
|
||||
#define SE_LimitCombatSkills 311 // implemented, @Ff, Include or exclude combat skills or procs (non-memorizable spells) from being focused, base1: 0=Exclude if proc 1=Allow only if proc
|
||||
#define SE_ReduceReuseTimer 310 // implemented, @Fc, On Caster, spell and disc reuse time mod by amount, base: milliseconds
|
||||
#define SE_LimitCombatSkills 311 // implemented, @Ff, Include or exclude combat skills or procs from being focused, base1: 0=Exclude if proc 1=Allow only if proc.
|
||||
#define SE_Sanctuary 312 // implemented - Places caster at bottom hate list, effect fades if cast cast spell on targets other than self.
|
||||
#define SE_ForageAdditionalItems 313 // implemented[AA] - chance to forage additional items
|
||||
#define SE_Invisibility2 314 // implemented - fixed duration invisible
|
||||
@@ -1041,7 +1062,7 @@ typedef enum {
|
||||
//#define SE_IllusionaryTarget 336 // not used
|
||||
#define SE_PercentXPIncrease 337 // implemented
|
||||
#define SE_SummonAndResAllCorpses 338 // implemented
|
||||
#define SE_TriggerOnCast 339 // implemented, @Fc, On Caster, cast on spell use, base: chance pct limit: spellid
|
||||
#define SE_TriggerOnCast 339 // implemented, @Fc, On Caster, cast on spell use, base: chance pct limit: spellid
|
||||
#define SE_SpellTrigger 340 // implemented - chance to trigger spell [Share rolls with 469] All base2 spells share roll chance, only 1 cast.
|
||||
#define SE_ItemAttackCapIncrease 341 // implemented[AA] - increases the maximum amount of attack you can gain from items.
|
||||
#define SE_ImmuneFleeing 342 // implemented - stop mob from fleeing
|
||||
@@ -1129,8 +1150,8 @@ typedef enum {
|
||||
#define SE_GravityEffect 424 // implemented - Pulls/pushes you toward/away the mob at a set pace
|
||||
//#define SE_Display 425 // *not implemented - Illusion: Flying Dragon(21626)
|
||||
#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window
|
||||
#define SE_SkillProc 427 // implemented - chance to proc when using a skill(ie taunt)
|
||||
#define SE_LimitToSkill 428 // implemented - limits what skills will effect a skill proc
|
||||
#define SE_SkillProcAttempt 427 // implemented - chance to proc when using a skill(ie taunt)
|
||||
#define SE_LimitToSkill 428 // implemented, @Procs, limits what combat skills will effect a skill proc, base: skill value, limit: none, max: none
|
||||
#define SE_SkillProcSuccess 429 // implemented - chance to proc when tje skill in use successfully fires.
|
||||
//#define SE_PostEffect 430 // *not implemented - Fear of the Dark(27641) - Alters vision
|
||||
//#define SE_PostEffectData 431 // *not implemented - Fear of the Dark(27641) - Alters vision
|
||||
@@ -1152,7 +1173,7 @@ typedef enum {
|
||||
#define SE_BStacker 447 // implemented
|
||||
#define SE_CStacker 448 // implemented
|
||||
#define SE_DStacker 449 // implemented
|
||||
#define SE_MitigateDotDamage 450 // implemented DOT spell mitigation rune with max value
|
||||
#define SE_MitigateDotDamage 450 // implemented, @Runes, mitigate incoming dot damage by percentage until rune fades, base: percent mitigation, limit: max dmg absorbed per hit, max: rune amt, Note: If placed on item or AA, will provide stackable percent mitigation.
|
||||
#define SE_MeleeThresholdGuard 451 // implemented Partial Melee Rune that only is lowered if melee hits are over X amount of damage
|
||||
#define SE_SpellThresholdGuard 452 // implemented Partial Spell Rune that only is lowered if spell hits are over X amount of damage
|
||||
#define SE_TriggerMeleeThreshold 453 // implemented Trigger effect on X amount of melee damage taken in a single hit
|
||||
@@ -1186,14 +1207,14 @@ typedef enum {
|
||||
#define SE_Fc_Cast_Spell_On_Land 481 // implemented, @Fc, On Target, cast spell if hit by spell, base: chance pct, limit: spellid
|
||||
#define SE_Skill_Base_Damage_Mod 482 // implemented, @OffBonus, modify base melee damage by percent, base: pct, limit: skill(-1=ALL), max: none
|
||||
#define SE_Fc_Spell_Damage_Pct_IncomingPC 483 // implemented, @Fc, On Target, spell damage taken mod pct, base: min pct, limit: max pct
|
||||
#define SE_Fc_Spell_Damage_Amt_IncomingPC 484 // implemented, @Fc, On Target, damage taken flat amt, base: amt
|
||||
#define SE_Fc_Spell_Damage_Amt_IncomingPC 484 // implemented, @Fc, On Target, damage taken flat amt, base: amt
|
||||
#define SE_Ff_CasterClass 485 // implemented, @Ff, Caster of spell on target with a focus effect that is checked by incoming spells must be specified class(es). base1: class(es), Note: Set multiple classes same as would for items
|
||||
#define SE_Ff_Same_Caster 486 // implemented, @Ff, Caster of spell on target with a focus effect that is checked by incoming spells, base1: 0=Must be different caster 1=Must be same caster
|
||||
//#define SE_Extend_Tradeskill_Cap 487 //
|
||||
//#define SE_Defender_Melee_Force_Pct_PC 488 //
|
||||
#define SE_Worn_Endurance_Regen_Cap 489 // implemented, modify worn regen cap, base: amt, limit: none, max: none
|
||||
#define SE_Ff_ReuseTimeMin 490 // implemented, @Ff, Minimum recast time of a spell that can be focused, base: recast time
|
||||
#define SE_Ff_ReuseTimeMax 491 // implemented, @Ff, Max recast time of a spell that can be focused, base: recast time
|
||||
#define SE_Ff_ReuseTimeMax 491 // implemented, @Ff, Max recast time of a spell that can be focused, base: recast time
|
||||
#define SE_Ff_Endurance_Min 492 // implemented, @Ff, Minimum endurance cost of a spell that can be focused, base: endurance cost
|
||||
#define SE_Ff_Endurance_Max 493 // implemented, @Ff, Max endurance cost of a spell that can be focused, base: endurance cost
|
||||
#define SE_Pet_Add_Atk 494 // implemented - Bonus on pet owner which gives their pet increased attack stat
|
||||
@@ -1213,7 +1234,7 @@ typedef enum {
|
||||
#define SE_Fc_Amplify_Amt 508 // implemented, @Fc, On Caster, damage-heal-dot mod flat amt, base: amt
|
||||
#define SE_Health_Transfer 509 // implemented - exchange health for damage or healing on a target. ie Lifeburn/Act of Valor
|
||||
#define SE_Fc_ResistIncoming 510 // implemented, @Fc, On Target, resist modifier, base: amt
|
||||
#define SE_Ff_FocusTimerMin 511 // implemented, @Ff, sets a recast time until focus can be used again, base: 1, limit: time ms, Note: ie. limit to 1 trigger every 1.5 seconds
|
||||
#define SE_Ff_FocusTimerMin 511 // implemented, @Ff, sets a recast time until focus can be used again, base: 1, limit: time ms, Note: ie. limit to 1 trigger every 1.5 seconds
|
||||
#define SE_Proc_Timer_Modifier 512 // implemented - limits procs per amount of a time based on timer value, base: 1, limit: time ms, Note:, ie limit to 1 proc every 55 seconds)
|
||||
//#define SE_Mana_Max_Percent 513 //
|
||||
//#define SE_Endurance_Max_Percent 514 //
|
||||
@@ -1340,7 +1361,7 @@ struct SPDat_Spell_Struct
|
||||
/* 181 */ int pvp_duration; // buffdurationformula for PvP -- PVP_DURATION
|
||||
/* 182 */ int pvp_duration_cap; // buffduration for PvP -- PVP_DURATION_CAP
|
||||
/* 183 */ int pcnpc_only_flag; // valid values are 0, 1 = PCs (and mercs), and 2 = NPCs (and not mercs) -- PCNPC_ONLY_FLAG
|
||||
/* 184 */ bool cast_not_standing; // this is checked in the client's EQ_Spell::IsCastWhileInvisSpell, this also blocks SE_InterruptCasting from affecting this spell -- CAST_NOT_STANDING
|
||||
/* 184 */ bool cast_not_standing; // this is checked in the client's EQ_Spell::IsCastWhileInvisSpell, this also blocks SE_InterruptCasting from affecting this spell -- CAST_NOT_STANDING (Allows casting if DA, stun, mezed, charm? fear?, damage to invul targets)
|
||||
/* 185 */ bool can_mgb; // 0=no, -1 or 1 = yes -- CAN_MGB
|
||||
/* 186 */ int dispel_flag; // -- NO_DISPELL
|
||||
/* 187 */ //int npc_category; // -- NPC_MEM_CATEGORY
|
||||
@@ -1519,8 +1540,9 @@ int GetViralMinSpreadTime(int32 spell_id);
|
||||
int GetViralMaxSpreadTime(int32 spell_id);
|
||||
int GetViralSpreadRange(int32 spell_id);
|
||||
bool IsInstrumentModAppliedToSpellEffect(int32 spell_id, int effect);
|
||||
bool IsPulsingBardSong(int32 spell_id);
|
||||
uint32 GetProcLimitTimer(int32 spell_id, int proc_type);
|
||||
|
||||
bool IgnoreCastingRestriction(int32 spell_id);
|
||||
int CalcPetHp(int levelb, int classb, int STA = 75);
|
||||
int GetSpellEffectDescNum(uint16 spell_id);
|
||||
DmgShieldType GetDamageShieldType(uint16 spell_id, int32 DSType = 0);
|
||||
@@ -1531,5 +1553,6 @@ bool IsShortDurationBuff(uint16 spell_id);
|
||||
bool IsSpellUsableThisZoneType(uint16 spell_id, uint8 zone_type);
|
||||
const char *GetSpellName(uint16 spell_id);
|
||||
int GetSpellStatValue(uint32 spell_id, const char* stat_identifier, uint8 slot = 0);
|
||||
bool CastRestrictedSpell(int spellid);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "string_util.h"
|
||||
#include <fmt/format.h>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
|
||||
@@ -1019,3 +1020,243 @@ std::vector<std::string> GetBadWords()
|
||||
"zoophilia"
|
||||
};
|
||||
}
|
||||
|
||||
std::string ConvertSecondsToTime(int duration, bool is_milliseconds)
|
||||
{
|
||||
if (duration <= 0) {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
if (is_milliseconds && duration < 1000) {
|
||||
return fmt::format(
|
||||
"{} Millisecond{}",
|
||||
duration,
|
||||
duration != 1 ? "s" : ""
|
||||
);
|
||||
}
|
||||
|
||||
int timer_length = (
|
||||
is_milliseconds ?
|
||||
static_cast<int>(std::ceil(static_cast<float>(duration) / 1000.0f)) :
|
||||
duration
|
||||
);
|
||||
|
||||
int days = int(timer_length / 86400);
|
||||
timer_length %= 86400;
|
||||
int hours = int(timer_length / 3600);
|
||||
timer_length %= 3600;
|
||||
int minutes = int(timer_length / 60);
|
||||
timer_length %= 60;
|
||||
int seconds = timer_length;
|
||||
std::string time_string = "Unknown";
|
||||
std::string day_string = (days == 1 ? "Day" : "Days");
|
||||
std::string hour_string = (hours == 1 ? "Hour" : "Hours");
|
||||
std::string minute_string = (minutes == 1 ? "Minute" : "Minutes");
|
||||
std::string second_string = (seconds == 1 ? "Second" : "Seconds");
|
||||
if (days && hours && minutes && seconds) { // DHMS
|
||||
time_string = fmt::format(
|
||||
"{} {}, {} {}, {} {}, and {} {}",
|
||||
days,
|
||||
day_string,
|
||||
hours,
|
||||
hour_string,
|
||||
minutes,
|
||||
minute_string,
|
||||
seconds,
|
||||
second_string
|
||||
);
|
||||
} else if (days && hours && minutes && !seconds) { // DHM
|
||||
time_string = fmt::format(
|
||||
"{} {}, {} {}, and {} {}",
|
||||
days,
|
||||
day_string,
|
||||
hours,
|
||||
hour_string,
|
||||
minutes,
|
||||
minute_string
|
||||
);
|
||||
} else if (days && hours && !minutes && seconds) { // DHS
|
||||
time_string = fmt::format(
|
||||
"{} {}, {} {}, and {} {}",
|
||||
days,
|
||||
day_string,
|
||||
hours,
|
||||
hour_string,
|
||||
seconds,
|
||||
second_string
|
||||
);
|
||||
} else if (days && hours && !minutes && !seconds) { // DH
|
||||
time_string = fmt::format(
|
||||
"{} {} and {} {}",
|
||||
days,
|
||||
day_string,
|
||||
hours,
|
||||
hour_string
|
||||
);
|
||||
} else if (days && !hours && minutes && seconds) { // DMS
|
||||
time_string = fmt::format(
|
||||
"{} {}, {} {}, and {} {}",
|
||||
days,
|
||||
day_string,
|
||||
minutes,
|
||||
minute_string,
|
||||
seconds,
|
||||
second_string
|
||||
);
|
||||
} else if (days && !hours && minutes && !seconds) { // DM
|
||||
time_string = fmt::format(
|
||||
"{} {} and {} {}",
|
||||
days,
|
||||
day_string,
|
||||
minutes,
|
||||
minute_string
|
||||
);
|
||||
} else if (days && !hours && !minutes && seconds) { // DS
|
||||
time_string = fmt::format(
|
||||
"{} {} and {} {}",
|
||||
days,
|
||||
day_string,
|
||||
seconds,
|
||||
second_string
|
||||
);
|
||||
} else if (days && !hours && !minutes && !seconds) { // D
|
||||
time_string = fmt::format(
|
||||
"{} {}",
|
||||
days,
|
||||
day_string
|
||||
);
|
||||
} else if (!days && hours && minutes && seconds) { // HMS
|
||||
time_string = fmt::format(
|
||||
"{} {}, {} {}, and {} {}",
|
||||
hours,
|
||||
hour_string,
|
||||
minutes,
|
||||
minute_string,
|
||||
seconds,
|
||||
second_string
|
||||
);
|
||||
} else if (!days && hours && minutes && !seconds) { // HM
|
||||
time_string = fmt::format(
|
||||
"{} {} and {} {}",
|
||||
hours,
|
||||
hour_string,
|
||||
minutes,
|
||||
minute_string
|
||||
);
|
||||
} else if (!days && hours && !minutes && seconds) { // HS
|
||||
time_string = fmt::format(
|
||||
"{} {} and {} {}",
|
||||
hours,
|
||||
hour_string,
|
||||
seconds,
|
||||
second_string
|
||||
);
|
||||
} else if (!days && hours && !minutes && !seconds) { // H
|
||||
time_string = fmt::format(
|
||||
"{} {}",
|
||||
hours,
|
||||
hour_string
|
||||
);
|
||||
} else if (!days && !hours && minutes && seconds) { // MS
|
||||
time_string = fmt::format(
|
||||
"{} {} and {} {}",
|
||||
minutes,
|
||||
minute_string,
|
||||
seconds,
|
||||
second_string
|
||||
);
|
||||
} else if (!days && !hours && minutes && !seconds) { // M
|
||||
time_string = fmt::format(
|
||||
"{} {}",
|
||||
minutes,
|
||||
minute_string
|
||||
);
|
||||
} else if (!days && !hours && !minutes && seconds) { // S
|
||||
time_string = fmt::format(
|
||||
"{} {}",
|
||||
seconds,
|
||||
second_string
|
||||
);
|
||||
}
|
||||
return time_string;
|
||||
}
|
||||
|
||||
std::string ConvertMoneyToString(uint32 platinum, uint32 gold, uint32 silver, uint32 copper)
|
||||
{
|
||||
std::string money_string = "Unknown";
|
||||
if (copper && silver && gold && platinum) { // CSGP
|
||||
money_string = fmt::format(
|
||||
"{} Platinum, {} Gold, {} Silver, and {} Copper",
|
||||
platinum,
|
||||
gold,
|
||||
silver,
|
||||
copper
|
||||
);
|
||||
} else if (copper && silver && gold && !platinum) { // CSG
|
||||
money_string = fmt::format(
|
||||
"{} Gold, {} Silver, and {} Copper",
|
||||
gold,
|
||||
silver,
|
||||
copper
|
||||
);
|
||||
} else if (copper && silver && !gold && !platinum) { // CS
|
||||
money_string = fmt::format(
|
||||
"{} Silver and {} Copper",
|
||||
silver,
|
||||
copper
|
||||
);
|
||||
} else if (!copper && silver && gold && platinum) { // SGP
|
||||
money_string = fmt::format(
|
||||
"{} Platinum, {} Gold, and {} Silver",
|
||||
platinum,
|
||||
gold,
|
||||
silver
|
||||
);
|
||||
} else if (!copper && silver && gold && !platinum) { // SG
|
||||
money_string = fmt::format(
|
||||
"{} Gold and {} Silver",
|
||||
gold,
|
||||
silver
|
||||
);
|
||||
} else if (copper && !silver && gold && platinum) { // CGP
|
||||
money_string = fmt::format(
|
||||
"{} Platinum, {} Gold, and {} Copper",
|
||||
platinum,
|
||||
gold,
|
||||
copper
|
||||
);
|
||||
} else if (copper && !silver && gold && !platinum) { // CG
|
||||
money_string = fmt::format(
|
||||
"{} Gold and {} Copper",
|
||||
gold,
|
||||
copper
|
||||
);
|
||||
} else if (!copper && !silver && gold && platinum) { // GP
|
||||
money_string = fmt::format(
|
||||
"{} Platinum and {} Gold",
|
||||
platinum,
|
||||
gold
|
||||
);
|
||||
} else if (!copper && !silver && !gold && platinum) { // P
|
||||
money_string = fmt::format(
|
||||
"{} Platinum",
|
||||
platinum
|
||||
);
|
||||
} else if (!copper && !silver && gold && !platinum) { // G
|
||||
money_string = fmt::format(
|
||||
"{} Gold",
|
||||
gold
|
||||
);
|
||||
} else if (!copper && silver && !gold && !platinum) { // S
|
||||
money_string = fmt::format(
|
||||
"{} Silver",
|
||||
silver
|
||||
);
|
||||
} else if (copper && !silver && !gold && !platinum) { // C
|
||||
money_string = fmt::format(
|
||||
"{} Copper",
|
||||
copper
|
||||
);
|
||||
}
|
||||
return money_string;
|
||||
}
|
||||
@@ -45,6 +45,11 @@ std::vector<std::string> wrap(std::vector<std::string> &src, std::string charact
|
||||
std::string implode(std::string glue, std::vector<std::string> src);
|
||||
std::string convert2digit(int n, std::string suffix);
|
||||
std::string numberToWords(unsigned long long int n);
|
||||
std::string ConvertMoneyToString(uint32 platinum, uint32 gold = 0, uint32 silver = 0, uint32 copper = 0);
|
||||
std::string ConvertSecondsToTime(int duration, bool is_milliseconds = false);
|
||||
inline std::string ConvertMillisecondsToTime(int duration) {
|
||||
return ConvertSecondsToTime(duration, true);
|
||||
}
|
||||
|
||||
// For converstion of numerics into English
|
||||
// Used for grid nodes, as NPC names remove numerals.
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@
|
||||
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9174
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9175
|
||||
|
||||
#ifdef BOTS
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9028
|
||||
|
||||
@@ -5,7 +5,7 @@ CREATE TABLE `login_accounts` (
|
||||
`account_password` text NOT NULL,
|
||||
`account_email` varchar(100) NOT NULL,
|
||||
`source_loginserver` varchar(64) DEFAULT NULL,
|
||||
`last_ip_address` varchar(30) NOT NULL,
|
||||
`last_ip_address` varchar(80) NOT NULL,
|
||||
`last_login_date` datetime NOT NULL,
|
||||
`created_at` datetime DEFAULT NULL,
|
||||
`updated_at` datetime DEFAULT current_timestamp(),
|
||||
@@ -22,7 +22,7 @@ CREATE TABLE `login_server_admins` (
|
||||
`last_name` varchar(50) NOT NULL,
|
||||
`email` varchar(100) NOT NULL,
|
||||
`registration_date` datetime NOT NULL,
|
||||
`registration_ip_address` varchar(30) NOT NULL,
|
||||
`registration_ip_address` varchar(80) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
|
||||
|
||||
@@ -45,7 +45,7 @@ CREATE TABLE `login_world_servers` (
|
||||
`tag_description` varchar(50) NOT NULL DEFAULT '',
|
||||
`login_server_list_type_id` int(11) NOT NULL,
|
||||
`last_login_date` datetime DEFAULT NULL,
|
||||
`last_ip_address` varchar(30) DEFAULT NULL,
|
||||
`last_ip_address` varchar(80) DEFAULT NULL,
|
||||
`login_server_admin_id` int(11) NOT NULL,
|
||||
`is_server_trusted` int(11) NOT NULL,
|
||||
`note` varchar(255) DEFAULT NULL,
|
||||
|
||||
@@ -167,6 +167,9 @@ int main(int argc, char **argv)
|
||||
|
||||
|
||||
content_service.SetCurrentExpansion(RuleI(Expansion, CurrentExpansion));
|
||||
content_service.SetDatabase(&database)
|
||||
->SetExpansionContext()
|
||||
->ReloadContentFlags();
|
||||
|
||||
LogInfo(
|
||||
"Current expansion is [{}] ({})",
|
||||
|
||||
@@ -20,7 +20,7 @@ SET(tests_headers
|
||||
|
||||
ADD_EXECUTABLE(tests ${tests_sources} ${tests_headers})
|
||||
|
||||
TARGET_LINK_LIBRARIES(tests common cppunit)
|
||||
TARGET_LINK_LIBRARIES(tests common cppunit fmt)
|
||||
|
||||
INSTALL(TARGETS tests RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"server": {
|
||||
"world": {
|
||||
"shortname": "setme",
|
||||
"longname": "I Forgot To Edit My Config"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
{
|
||||
"server": {
|
||||
"zones": {
|
||||
"defaultstatus": "20",
|
||||
"ports": {
|
||||
"low": "7000",
|
||||
"high": "7100"
|
||||
}
|
||||
},
|
||||
"database": {
|
||||
"password": "eq",
|
||||
"db": "eq",
|
||||
"host": "127.0.0.1",
|
||||
"port": "3306",
|
||||
"username": "eq"
|
||||
},
|
||||
"world": {
|
||||
"shortname": "setme",
|
||||
"longname": "I Forgot To Edit My Config",
|
||||
"loginserver": {
|
||||
"password": "",
|
||||
"host": "login.eqemulator.net",
|
||||
"port": "5998",
|
||||
"account": ""
|
||||
},
|
||||
"tcp": {
|
||||
"port": "9000",
|
||||
"telnet": "disable",
|
||||
"ip": "127.0.0.1"
|
||||
},
|
||||
"key": "some long random string",
|
||||
"http": {
|
||||
"mimefile": "mime.types",
|
||||
"port": "9080",
|
||||
"enabled": "false"
|
||||
}
|
||||
},
|
||||
"mailserver": {
|
||||
"host": "channels.eqemulator.net",
|
||||
"port": "7778"
|
||||
},
|
||||
"chatserver": {
|
||||
"host": "channels.eqemulator.net",
|
||||
"port": "7778"
|
||||
},
|
||||
"qsdatabase": {
|
||||
"host": "127.0.0.1",
|
||||
"port": "3306",
|
||||
"username": "eq",
|
||||
"password": "eq",
|
||||
"db": "eq"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<server>
|
||||
<world>
|
||||
<shortname>setme</shortname>
|
||||
<longname>I Forgot To Edit My Config</longname>
|
||||
</world>
|
||||
</server>
|
||||
@@ -1,95 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<server>
|
||||
<world>
|
||||
<shortname>setme</shortname>
|
||||
<longname>I Forgot To Edit My Config</longname>
|
||||
|
||||
<!-- Only specify these two if you really think you need to. (read: You don't) -->
|
||||
<!-- <address>some.server.com</address> -->
|
||||
<!-- <localaddress>192.168.0.5</localaddress> -->
|
||||
|
||||
<!-- Loginserver information. Defaults shown -->
|
||||
<loginserver>
|
||||
<host>login.eqemulator.net</host>
|
||||
<port>5998</port>
|
||||
<account></account>
|
||||
<password></password>
|
||||
</loginserver>
|
||||
|
||||
<!-- Server status. Default is unlocked -->
|
||||
<!--<locked/>-->
|
||||
<!-- <unlocked/> -->
|
||||
|
||||
<!-- Sets the ip/port for the tcp connections. Both zones and console (if enabled). Defaults are shown -->
|
||||
<tcp ip="127.0.0.1" port="9000" telnet="disable"/>
|
||||
|
||||
<!-- Sets the shared key used by zone/launcher to connect to world -->
|
||||
<key>some long random string</key>
|
||||
|
||||
<!-- Enable and set the port for the HTTP service. Defaults are shown -->
|
||||
<http port="9080" enabled="false" mimefile="mime.types" />
|
||||
</world>
|
||||
|
||||
<!-- Chatserver (channels) information. Defaults shown -->
|
||||
<chatserver>
|
||||
<host>channels.eqemulator.net</host>
|
||||
<port>7778</port>
|
||||
</chatserver>
|
||||
|
||||
<!-- Mailserver (in-game mail) information. Defaults shown -->
|
||||
<mailserver>
|
||||
<host>channels.eqemulator.net</host>
|
||||
<port>7778</port>
|
||||
</mailserver>
|
||||
|
||||
<zones>
|
||||
<defaultstatus>20</defaultstatus>
|
||||
|
||||
<!-- Sets port range for world to use to auto configure zones -->
|
||||
<ports low="7000" high="7100"/>
|
||||
</zones>
|
||||
|
||||
<!-- Database configuration, replaces db.ini. Defaults shown -->
|
||||
<database>
|
||||
<host>127.0.0.1</host>
|
||||
<port>3306</port>
|
||||
<username>eq</username>
|
||||
<password>eq</password>
|
||||
<db>eq</db>
|
||||
</database>
|
||||
|
||||
<qsdatabase>
|
||||
<host>127.0.0.1</host>
|
||||
<port>3306</port>
|
||||
<username>eq</username>
|
||||
<password>eq</password>
|
||||
<db>eq</db>
|
||||
</qsdatabase>
|
||||
|
||||
<!-- Launcher Configuration -->
|
||||
<launcher>
|
||||
<!-- <logprefix>zone-</logprefix> -->
|
||||
<!-- <logsuffix>.log</logsuffix> -->
|
||||
<!-- <exe>zone.exe or ./zone</exe> -->
|
||||
<!-- <timers restart="10000" reterminate="10000"> -->
|
||||
</launcher>
|
||||
|
||||
<!-- File locations. Defaults shown -->
|
||||
<files>
|
||||
<!-- <spells>spells_us.txt</spells> -->
|
||||
<!-- <opcodes>opcodes.conf</opcodes> -->
|
||||
<!-- <logsettings>log.ini</logsettings> -->
|
||||
<!-- <eqtime>eqtime.cfg</eqtime> -->
|
||||
<!-- <plugin.pl>plugin.pl</plugin.pl> -->
|
||||
</files>
|
||||
<!-- Directory locations. Defaults shown -->
|
||||
<directories>
|
||||
<!-- <maps>Maps/</maps> -->
|
||||
<!-- <quests>quests/</quests> -->
|
||||
<!-- <plugins>plugins/</plugins> -->
|
||||
<!-- <lua_modules>lua_modules/</lua_modules> -->
|
||||
<!-- <patches>./</patches> -->
|
||||
<!-- <shared_memory>shared/</shared_memory> -->
|
||||
<!-- <logs>logs/</logs> -->
|
||||
</directories>
|
||||
</server>
|
||||
@@ -0,0 +1,183 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// zone/command.cpp
|
||||
commands, err := os.ReadFile("./zone/command.cpp")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
commandsString := string(commands)
|
||||
|
||||
s := strings.Split(commandsString, "void command_")
|
||||
commandFiles := []string{}
|
||||
if len(s) > 1 {
|
||||
startListing := false
|
||||
for i, chunk := range s {
|
||||
if strings.Contains(chunk, "logcommand(Client *c") {
|
||||
startListing = true
|
||||
}
|
||||
|
||||
// get function name
|
||||
functionName := ""
|
||||
nameSplit := strings.Split(chunk, "(Client")
|
||||
if len(nameSplit) > 0 {
|
||||
functionName = strings.TrimSpace(nameSplit[0])
|
||||
}
|
||||
|
||||
if startListing &&
|
||||
len(s[i-1]) > 0 &&
|
||||
!strings.Contains(s[i-1], "#ifdef") &&
|
||||
!strings.Contains(chunk, "#ifdef") &&
|
||||
!strings.Contains(chunk, "#ifdef BOTS") &&
|
||||
!strings.Contains(chunk, "#ifdef EQPROFILE") &&
|
||||
!strings.Contains(functionName, "bot") &&
|
||||
!strings.Contains(functionName, "help") &&
|
||||
!strings.Contains(functionName, "findaliases") {
|
||||
|
||||
fmt.Println(functionName)
|
||||
|
||||
// build command file name
|
||||
commandFile := fmt.Sprintf("zone/gm_commands/%v.cpp", functionName)
|
||||
|
||||
// append command file nam eto list
|
||||
commandFiles = append(commandFiles, commandFile)
|
||||
|
||||
includes := ""
|
||||
if strings.Contains(chunk, "Client") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../client.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "parse->") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../quest_parser_collection.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "worldserver.") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../worldserver.h\"")
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "extern WorldServer worldserver;")
|
||||
}
|
||||
if strings.Contains(chunk, "RegionType") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../water_map.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "Corpse") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../corpse.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "Object") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../object.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "DoorManipulation") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"door_manipulation.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "Group") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../groups.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "httplib") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/http/httplib.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "guild_mgr") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../guild_mgr.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "expedition") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../expedition.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "DataBucket::") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../data_bucket.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "file_exists") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/file_util.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "std::thread") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include <thread>")
|
||||
}
|
||||
if strings.Contains(chunk, "Door") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../doors.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "NOW_INVISIBLE") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../string_ids.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "Expansion::") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/content/world_content_service.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "MobMovementManager::") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../mob_movement_manager.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "MobStuckBehavior::") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../mob_movement_manager.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "ReloadAllPatches") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/patches/patches.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "ProfanityManager") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/profanity_manager.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "npc_scale_manager") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../npc_scale_manager.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "g_Math") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../fastmath.h\"")
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "extern FastMath g_Math;")
|
||||
}
|
||||
if strings.Contains(chunk, "raid") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../raids.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "Raid") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../raids.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "GetOS") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/serverinfo.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "LANG_") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/languages.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "ServerOP_Shared") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/shared_tasks.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "title_manager") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../titles.h\"")
|
||||
}
|
||||
if strings.Contains(chunk, "CatchSignal") {
|
||||
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../world/main.h\"")
|
||||
}
|
||||
|
||||
// build the contents of the command file
|
||||
commandString := fmt.Sprintf("%v\nvoid command_%v", includes, chunk)
|
||||
|
||||
//write file contents
|
||||
err := ioutil.WriteFile(commandFile, []byte(commandString), 0777)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
commandOnly := fmt.Sprintf("void command_%v", chunk)
|
||||
commandsString = strings.ReplaceAll(commandsString, commandOnly, "")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// rewrite commands.cpp with functions removed
|
||||
err := ioutil.WriteFile("zone/command.cpp", []byte(commandsString), 0777)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
fmt.Println("# CmakeLists")
|
||||
|
||||
// sort a-z
|
||||
sort.Slice(commandFiles, func(i, j int) bool {
|
||||
return commandFiles[i] < commandFiles[j]
|
||||
})
|
||||
|
||||
for _, file := range commandFiles {
|
||||
file = strings.ReplaceAll(file, "zone/", "")
|
||||
fmt.Println(file)
|
||||
}
|
||||
}
|
||||
|
||||
//fmt.Print(string(commands))
|
||||
}
|
||||
@@ -962,15 +962,14 @@ function CommonOutgoingHitSuccess(e)
|
||||
)
|
||||
);
|
||||
|
||||
e.hit.damage_done = e.hit.damage_done + (e.hit.damage_done * e.other:GetSkillDmgTaken(e.hit.skill) / 100) + (e.self:GetSkillDmgAmt(e.hit.skill) + e.other:GetFcDamageAmtIncoming(e.self, 0, true, e.hit.skill));
|
||||
e.hit.damage_done = e.hit.damage_done + (e.hit.damage_done * e.other:GetSkillDmgTaken(e.hit.skill) / 100) + e.self:GetSkillDmgAmt(e.hit.skill);
|
||||
|
||||
eq.log_combat(
|
||||
string.format("[%s] [Mob::CommonOutgoingHitSuccess] Dmg [%i] SkillDmgTaken [%i] SkillDmgtAmt [%i] FcDmgAmtIncoming [%i] Post DmgCalcs",
|
||||
string.format("[%s] [Mob::CommonOutgoingHitSuccess] Dmg [%i] SkillDmgTaken [%i] SkillDmgtAmt [%i] Post DmgCalcs",
|
||||
e.self:GetCleanName(),
|
||||
e.hit.damage_done,
|
||||
e.other:GetSkillDmgTaken(e.hit.skill),
|
||||
e.self:GetSkillDmgAmt(e.hit.skill),
|
||||
e.other:GetFcDamageAmtIncoming(e.self, 0, true, e.hit.skill)
|
||||
e.self:GetSkillDmgAmt(e.hit.skill)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -997,4 +996,4 @@ function ApplyMeleeDamageBonus(e)
|
||||
|
||||
e.hit.damage_done = e.hit.damage_done + (e.hit.damage_done * dmgbonusmod / 100);
|
||||
return e;
|
||||
end
|
||||
end
|
||||
|
||||
@@ -307,8 +307,8 @@ OP_RecipeAutoCombine=0x0353
|
||||
OP_TradeSkillCombine=0x0b40
|
||||
|
||||
OP_RequestDuel=0x0000
|
||||
OP_DuelResponse=0x0000
|
||||
OP_DuelResponse2=0x0000 #when accepted
|
||||
OP_DuelDecline=0x0000
|
||||
OP_DuelAccept=0x0000 #when accepted
|
||||
|
||||
OP_RezzComplete=0x0000 #packet wrong on this
|
||||
OP_RezzRequest=0x0000 #packet wrong on this
|
||||
|
||||
@@ -288,8 +288,8 @@ OP_YellForHelp=0x0017
|
||||
OP_LoadSpellSet=0x38b4
|
||||
OP_Bandolier=0x2b6f
|
||||
OP_PotionBelt=0x2d1b # Was 0x4d3b
|
||||
OP_DuelResponse=0x0dee
|
||||
OP_DuelResponse2=0x5e04
|
||||
OP_DuelDecline=0x0dee
|
||||
OP_DuelAccept=0x5e04
|
||||
OP_SaveOnZoneReq=0x36b1
|
||||
OP_ReadBook=0x383c
|
||||
OP_Dye=0x62d8
|
||||
|
||||
@@ -287,8 +287,8 @@ OP_YellForHelp=0x4e56
|
||||
OP_LoadSpellSet=0x261d
|
||||
OP_Bandolier=0x7677
|
||||
OP_PotionBelt=0x1a3e
|
||||
OP_DuelResponse=0x6a46
|
||||
OP_DuelResponse2=0x68d3
|
||||
OP_DuelDecline=0x6a46
|
||||
OP_DuelAccept=0x68d3
|
||||
OP_SaveOnZoneReq=0x600d
|
||||
OP_ReadBook=0x72df
|
||||
OP_Dye=0x23b9
|
||||
|
||||
@@ -281,7 +281,7 @@ OP_YellForHelp=0x6f79 # C
|
||||
OP_LoadSpellSet=0x7113 # C
|
||||
OP_Bandolier=0x441c # C
|
||||
OP_PotionBelt=0x5db5 # C
|
||||
OP_DuelResponse=0x1ebb # C
|
||||
OP_DuelDecline=0x1ebb # C
|
||||
OP_SaveOnZoneReq=0x6eff # C
|
||||
OP_ReadBook=0x2444 # C
|
||||
OP_Dye=0x3672 # C
|
||||
@@ -299,7 +299,7 @@ OP_DoGroupLeadershipAbility=0x540b # C
|
||||
OP_GroupLeadershipAAUpdate=0x0c33
|
||||
OP_DelegateAbility=0x0322 # C
|
||||
OP_SetGroupTarget=0x521c # C
|
||||
OP_DuelResponse2=0x52b5 # C
|
||||
OP_DuelAccept=0x52b5 # C
|
||||
OP_Charm=0x7108 # C
|
||||
OP_Stun=0x2a6d # C
|
||||
OP_SendFindableNPCs=0x5360
|
||||
|
||||
@@ -275,7 +275,7 @@ OP_YellForHelp=0x4F4A #Trevius 03/19/09
|
||||
OP_LoadSpellSet=0x05B5 #Trevius 03/19/09
|
||||
OP_Bandolier=0x3FD4 #Trevius 03/19/09
|
||||
OP_PotionBelt=0x16F3 #Trevius 03/19/09
|
||||
OP_DuelResponse=0x5E59 #Derision 2009
|
||||
OP_DuelDecline=0x5E59 #Derision 2009
|
||||
OP_SaveOnZoneReq=0x1103 #Trevius 03/20/09
|
||||
OP_ReadBook=0x424a #Xinu 03/19/09
|
||||
OP_Dye=0x3611 #Xinu 03/19/09
|
||||
@@ -292,7 +292,7 @@ OP_ClearRaidNPCMarks=0x56a9 #
|
||||
OP_DoGroupLeadershipAbility=0x5a64 #Derision 2009
|
||||
OP_DelegateAbility=0x57e3 #Derision 2009
|
||||
OP_SetGroupTarget=0x1651 #Derision 2009
|
||||
OP_DuelResponse2=0x2A85 #Derision 2009
|
||||
OP_DuelAccept=0x2A85 #Derision 2009
|
||||
OP_Charm=0x2F32 #Derision 2009
|
||||
OP_Stun=0x55BF #Derision 2009
|
||||
OP_FindPersonRequest=0x07F0 #Derision 2009
|
||||
|
||||
@@ -356,8 +356,8 @@ OP_RecipeAutoCombine=0x0353
|
||||
OP_TradeSkillCombine=0x0b40
|
||||
|
||||
OP_RequestDuel=0x28e1
|
||||
OP_DuelResponse=0x3bad
|
||||
OP_DuelResponse2=0x1b09 #when accepted
|
||||
OP_DuelDecline=0x3bad
|
||||
OP_DuelAccept=0x1b09 #when accepted
|
||||
|
||||
OP_RezzComplete=0x4b05
|
||||
OP_RezzRequest=0x1035
|
||||
|
||||
@@ -290,8 +290,8 @@ OP_YellForHelp=0x55a8 # C
|
||||
OP_LoadSpellSet=0x6617 # C
|
||||
OP_Bandolier=0x510c # C
|
||||
OP_PotionBelt=0x0651 # C
|
||||
OP_DuelResponse=0x41a6 # C
|
||||
OP_DuelResponse2=0x6d60 # C
|
||||
OP_DuelDecline=0x41a6 # C
|
||||
OP_DuelAccept=0x6d60 # C
|
||||
OP_SaveOnZoneReq=0x2913 # C
|
||||
OP_ReadBook=0x465e # C
|
||||
OP_Dye=0x2137 # C
|
||||
|
||||
@@ -1911,7 +1911,7 @@ sub fetch_peq_db_full
|
||||
sub map_files_fetch_bulk
|
||||
{
|
||||
print "[Install] Fetching Latest Maps... (This could take a few minutes...)\n";
|
||||
get_remote_file("http://github.com/Akkadius/EQEmuMaps/archive/master.zip", "maps/maps.zip", 1);
|
||||
get_remote_file("http://analytics.akkadius.com/maps.zip", "maps/maps.zip", 1);
|
||||
unzip('maps/maps.zip', 'maps/');
|
||||
my @files;
|
||||
my $start_dir = "maps/EQEmuMaps-master/";
|
||||
|
||||
@@ -428,6 +428,7 @@
|
||||
9172|2021_05_21_shared_tasks.sql|SHOW TABLES LIKE 'shared_tasks'|empty|
|
||||
9173|2021_09_14_zone_lava_damage.sql|SHOW COLUMNS FROM `zone` LIKE 'lava_damage'|empty|
|
||||
9174|2021_10_09_not_null_door_columns.sql|SELECT * FROM db_version WHERE version >= 9174|empty|
|
||||
9175|2022_01_02_expansion_default_value_all.sql|SHOW COLUMNS FROM `forage` LIKE 'min_expansion'|contains|unsigned
|
||||
|
||||
# Upgrade conditions:
|
||||
# This won't be needed after this system is implemented, but it is used database that are not
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
ALTER TABLE login_accounts MODIFY COLUMN last_ip_address VARCHAR(30) NOT NULL;
|
||||
ALTER TABLE login_server_admins MODIFY COLUMN registration_ip_address VARCHAR(30) NOT NULL;
|
||||
ALTER TABLE login_world_servers MODIFY COLUMN last_ip_address VARCHAR(30) DEFAULT NULL;
|
||||
ALTER TABLE login_accounts MODIFY COLUMN last_ip_address VARCHAR(80) NOT NULL;
|
||||
ALTER TABLE login_server_admins MODIFY COLUMN registration_ip_address VARCHAR(80) NOT NULL;
|
||||
ALTER TABLE login_world_servers MODIFY COLUMN last_ip_address VARCHAR(80) DEFAULT NULL;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
UPDATE doors SET lockpick=1 WHERE doorid=46 AND zone="potranquility";
|
||||
@@ -0,0 +1,117 @@
|
||||
-- forage
|
||||
|
||||
ALTER TABLE `forage` CHANGE `max_expansion` `max_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
ALTER TABLE `forage` CHANGE `min_expansion` `min_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
UPDATE forage set min_expansion = -1 where min_expansion = 0;
|
||||
UPDATE forage set max_expansion = -1 where max_expansion = 0;
|
||||
|
||||
-- tradeskill_recipe
|
||||
|
||||
ALTER TABLE `tradeskill_recipe` CHANGE `max_expansion` `max_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
ALTER TABLE `tradeskill_recipe` CHANGE `min_expansion` `min_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
UPDATE tradeskill_recipe set min_expansion = -1 where min_expansion = 0;
|
||||
UPDATE tradeskill_recipe set max_expansion = -1 where max_expansion = 0;
|
||||
|
||||
-- fishing
|
||||
|
||||
ALTER TABLE `fishing` CHANGE `max_expansion` `max_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
ALTER TABLE `fishing` CHANGE `min_expansion` `min_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
UPDATE fishing set min_expansion = -1 where min_expansion = 0;
|
||||
UPDATE fishing set max_expansion = -1 where max_expansion = 0;
|
||||
|
||||
-- zone
|
||||
|
||||
ALTER TABLE `zone` CHANGE `max_expansion` `max_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
ALTER TABLE `zone` CHANGE `min_expansion` `min_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
UPDATE zone set min_expansion = -1 where min_expansion = 0;
|
||||
UPDATE zone set max_expansion = -1 where max_expansion = 0;
|
||||
|
||||
-- traps
|
||||
|
||||
ALTER TABLE `traps` CHANGE `max_expansion` `max_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
ALTER TABLE `traps` CHANGE `min_expansion` `min_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
UPDATE traps set min_expansion = -1 where min_expansion = 0;
|
||||
UPDATE traps set max_expansion = -1 where max_expansion = 0;
|
||||
|
||||
-- loottable
|
||||
|
||||
ALTER TABLE `loottable` CHANGE `max_expansion` `max_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
ALTER TABLE `loottable` CHANGE `min_expansion` `min_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
UPDATE loottable set min_expansion = -1 where min_expansion = 0;
|
||||
UPDATE loottable set max_expansion = -1 where max_expansion = 0;
|
||||
|
||||
-- ground_spawns
|
||||
|
||||
ALTER TABLE `ground_spawns` CHANGE `max_expansion` `max_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
ALTER TABLE `ground_spawns` CHANGE `min_expansion` `min_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
UPDATE ground_spawns set min_expansion = -1 where min_expansion = 0;
|
||||
UPDATE ground_spawns set max_expansion = -1 where max_expansion = 0;
|
||||
|
||||
-- starting_items
|
||||
|
||||
ALTER TABLE `starting_items` CHANGE `max_expansion` `max_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
ALTER TABLE `starting_items` CHANGE `min_expansion` `min_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
UPDATE starting_items set min_expansion = -1 where min_expansion = 0;
|
||||
UPDATE starting_items set max_expansion = -1 where max_expansion = 0;
|
||||
|
||||
-- spawn2
|
||||
|
||||
ALTER TABLE `spawn2` CHANGE `max_expansion` `max_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
ALTER TABLE `spawn2` CHANGE `min_expansion` `min_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
UPDATE spawn2 set min_expansion = -1 where min_expansion = 0;
|
||||
UPDATE spawn2 set max_expansion = -1 where max_expansion = 0;
|
||||
|
||||
-- zone_points
|
||||
|
||||
ALTER TABLE `zone_points` CHANGE `max_expansion` `max_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
ALTER TABLE `zone_points` CHANGE `min_expansion` `min_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
UPDATE zone_points set min_expansion = -1 where min_expansion = 0;
|
||||
UPDATE zone_points set max_expansion = -1 where max_expansion = 0;
|
||||
|
||||
-- lootdrop
|
||||
|
||||
ALTER TABLE `lootdrop` CHANGE `max_expansion` `max_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
ALTER TABLE `lootdrop` CHANGE `min_expansion` `min_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
UPDATE lootdrop set min_expansion = -1 where min_expansion = 0;
|
||||
UPDATE lootdrop set max_expansion = -1 where max_expansion = 0;
|
||||
|
||||
-- global_loot
|
||||
|
||||
ALTER TABLE `global_loot` CHANGE `max_expansion` `max_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
ALTER TABLE `global_loot` CHANGE `min_expansion` `min_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
UPDATE global_loot set min_expansion = -1 where min_expansion = 0;
|
||||
UPDATE global_loot set max_expansion = -1 where max_expansion = 0;
|
||||
|
||||
-- doors
|
||||
|
||||
ALTER TABLE `doors` CHANGE `max_expansion` `max_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
ALTER TABLE `doors` CHANGE `min_expansion` `min_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
UPDATE doors set min_expansion = -1 where min_expansion = 0;
|
||||
UPDATE doors set max_expansion = -1 where max_expansion = 0;
|
||||
|
||||
-- object
|
||||
|
||||
ALTER TABLE `object` CHANGE `max_expansion` `max_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
ALTER TABLE `object` CHANGE `min_expansion` `min_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
UPDATE object set min_expansion = -1 where min_expansion = 0;
|
||||
UPDATE object set max_expansion = -1 where max_expansion = 0;
|
||||
|
||||
-- start_zones
|
||||
|
||||
ALTER TABLE `start_zones` CHANGE `max_expansion` `max_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
ALTER TABLE `start_zones` CHANGE `min_expansion` `min_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
UPDATE start_zones set min_expansion = -1 where min_expansion = 0;
|
||||
UPDATE start_zones set max_expansion = -1 where max_expansion = 0;
|
||||
|
||||
-- merchantlist
|
||||
|
||||
ALTER TABLE `merchantlist` CHANGE `max_expansion` `max_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
ALTER TABLE `merchantlist` CHANGE `min_expansion` `min_expansion` tinyint(4) NOT NULL DEFAULT -1 COMMENT '';
|
||||
UPDATE merchantlist set min_expansion = -1 where min_expansion = 0;
|
||||
UPDATE merchantlist set max_expansion = -1 where max_expansion = 0;
|
||||
|
||||
-- spawnentry
|
||||
ALTER TABLE `spawnentry` ADD `min_expansion` tinyint(4) NOT NULL DEFAULT -1;
|
||||
ALTER TABLE `spawnentry` ADD `max_expansion` tinyint(4) NOT NULL DEFAULT -1;
|
||||
ALTER TABLE `spawnentry` ADD `content_flags` varchar(100) NULL;
|
||||
ALTER TABLE `spawnentry` ADD `content_flags_disabled` varchar(100) NULL;
|
||||
@@ -274,7 +274,7 @@ void ClientListEntry::ClearVars(bool iAll)
|
||||
|
||||
paccountid = 0;
|
||||
memset(paccountname, 0, sizeof(paccountname));
|
||||
padmin = 0;
|
||||
padmin = AccountStatus::Player;
|
||||
}
|
||||
pzoneserver = 0;
|
||||
pzone = 0;
|
||||
@@ -365,7 +365,7 @@ bool ClientListEntry::CheckAuth(uint32 loginserver_account_id, const char *key_p
|
||||
}
|
||||
std::string lsworldadmin;
|
||||
if (database.GetVariable("honorlsworldadmin", lsworldadmin)) {
|
||||
if (atoi(lsworldadmin.c_str()) == 1 && pworldadmin != 0 && (padmin < pworldadmin || padmin == 0)) {
|
||||
if (atoi(lsworldadmin.c_str()) == 1 && pworldadmin != 0 && (padmin < pworldadmin || padmin == AccountStatus::Player)) {
|
||||
padmin = pworldadmin;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ public:
|
||||
* @param scl
|
||||
* @param iOnline
|
||||
*/
|
||||
ClientListEntry(uint32 id, uint32 iAccID, const char* iAccName, MD5& iMD5Pass, int16 iAdmin = 0);
|
||||
ClientListEntry(uint32 id, uint32 iAccID, const char* iAccName, MD5& iMD5Pass, int16 iAdmin = AccountStatus::Player);
|
||||
ClientListEntry(uint32 id, ZoneServer* iZS, ServerClientList_Struct* scl, CLE_Status iOnline);
|
||||
~ClientListEntry();
|
||||
bool CheckStale();
|
||||
|
||||
+103
-79
@@ -296,7 +296,13 @@ void ClientList::SendCLEList(const int16& admin, const char* to, WorldTCPConnect
|
||||
fmt:format_to(out, "{} CharID: {} CharName: {} Zone: {} ({})", newline, cle->CharID(), cle->name(), ZoneName(cle->zone()), cle->zone());
|
||||
if (out.size() >= 3072) {
|
||||
auto output = fmt::to_string(out);
|
||||
connection->SendEmoteMessageRaw(to, 0, 0, 10, output.c_str());
|
||||
connection->SendEmoteMessageRaw(
|
||||
to,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::NPCQuestSay,
|
||||
output.c_str()
|
||||
);
|
||||
addnewline = false;
|
||||
out.clear();
|
||||
} else {
|
||||
@@ -309,7 +315,13 @@ void ClientList::SendCLEList(const int16& admin, const char* to, WorldTCPConnect
|
||||
}
|
||||
fmt::format_to(out, "{}{} CLEs in memory. {} CLEs listed. numplayers = {}.", newline, x, y, numplayers);
|
||||
auto output = fmt::to_string(out);
|
||||
connection->SendEmoteMessageRaw(to, 0, 0, 10, output.c_str());
|
||||
connection->SendEmoteMessageRaw(
|
||||
to,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::NPCQuestSay,
|
||||
output.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -558,7 +570,7 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
|
||||
(countcle->Online() >= CLE_Status::Zoning) &&
|
||||
(!countcle->GetGM() || countcle->Anon() != 1 || admin >= countcle->Admin()) &&
|
||||
(whom == 0 || (
|
||||
((countcle->Admin() >= 80 && countcle->GetGM()) || whom->gmlookup == 0xFFFF) &&
|
||||
((countcle->Admin() >= AccountStatus::QuestTroupe && countcle->GetGM()) || whom->gmlookup == 0xFFFF) &&
|
||||
(whom->lvllow == 0xFFFF || (countcle->level() >= whom->lvllow && countcle->level() <= whom->lvlhigh && (countcle->Anon()==0 || admin > countcle->Admin()))) &&
|
||||
(whom->wclass == 0xFFFF || (countcle->class_() == whom->wclass && (countcle->Anon()==0 || admin > countcle->Admin()))) &&
|
||||
(whom->wrace == 0xFFFF || (countcle->race() == whom->wrace && (countcle->Anon()==0 || admin > countcle->Admin()))) &&
|
||||
@@ -566,18 +578,18 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
|
||||
(tmpZone != 0 && strncasecmp(tmpZone, whom->whom, whomlen) == 0) ||
|
||||
strncasecmp(countcle->name(),whom->whom, whomlen) == 0 ||
|
||||
(strncasecmp(guild_mgr.GetGuildName(countcle->GuildID()), whom->whom, whomlen) == 0) ||
|
||||
(admin >= 100 && strncasecmp(countcle->AccountName(), whom->whom, whomlen) == 0)
|
||||
(admin >= AccountStatus::GMAdmin && strncasecmp(countcle->AccountName(), whom->whom, whomlen) == 0)
|
||||
))
|
||||
))
|
||||
) {
|
||||
if((countcle->Anon()>0 && admin>=countcle->Admin() && admin>0) || countcle->Anon()==0 ){
|
||||
if((countcle->Anon()>0 && admin >= countcle->Admin() && admin > AccountStatus::Player) || countcle->Anon()==0 ){
|
||||
totalusers++;
|
||||
if(totalusers<=20 || admin>=100)
|
||||
if(totalusers<=20 || admin >= AccountStatus::GMAdmin)
|
||||
totallength=totallength+strlen(countcle->name())+strlen(countcle->AccountName())+strlen(guild_mgr.GetGuildName(countcle->GuildID()))+5;
|
||||
}
|
||||
else if((countcle->Anon()>0 && admin<=countcle->Admin()) || (countcle->Anon()==0 && !countcle->GetGM())) {
|
||||
totalusers++;
|
||||
if(totalusers<=20 || admin>=100)
|
||||
if(totalusers<=20 || admin >= AccountStatus::GMAdmin)
|
||||
totallength=totallength+strlen(countcle->name())+strlen(guild_mgr.GetGuildName(countcle->GuildID()))+5;
|
||||
}
|
||||
}
|
||||
@@ -589,7 +601,7 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
|
||||
uint8 unknown35=0x0A;
|
||||
uint32 unknown36=0;
|
||||
uint32 playersinzonestring=5028;
|
||||
if(totalusers>20 && admin<100){
|
||||
if(totalusers>20 && admin<AccountStatus::GMAdmin){
|
||||
totalusers=20;
|
||||
playersinzonestring=5033;
|
||||
}
|
||||
@@ -638,7 +650,7 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
|
||||
(cle->Online() >= CLE_Status::Zoning) &&
|
||||
(!cle->GetGM() || cle->Anon() != 1 || admin >= cle->Admin()) &&
|
||||
(whom == 0 || (
|
||||
((cle->Admin() >= 80 && cle->GetGM()) || whom->gmlookup == 0xFFFF) &&
|
||||
((cle->Admin() >= AccountStatus::QuestTroupe && cle->GetGM()) || whom->gmlookup == 0xFFFF) &&
|
||||
(whom->lvllow == 0xFFFF || (cle->level() >= whom->lvllow && cle->level() <= whom->lvlhigh && (cle->Anon()==0 || admin>cle->Admin()))) &&
|
||||
(whom->wclass == 0xFFFF || (cle->class_() == whom->wclass && (cle->Anon()==0 || admin>cle->Admin()))) &&
|
||||
(whom->wrace == 0xFFFF || (cle->race() == whom->wrace && (cle->Anon()==0 || admin>cle->Admin()))) &&
|
||||
@@ -646,60 +658,60 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
|
||||
(tmpZone != 0 && strncasecmp(tmpZone, whom->whom, whomlen) == 0) ||
|
||||
strncasecmp(cle->name(),whom->whom, whomlen) == 0 ||
|
||||
(strncasecmp(guild_mgr.GetGuildName(cle->GuildID()), whom->whom, whomlen) == 0) ||
|
||||
(admin >= 100 && strncasecmp(cle->AccountName(), whom->whom, whomlen) == 0)
|
||||
(admin >= AccountStatus::GMAdmin && strncasecmp(cle->AccountName(), whom->whom, whomlen) == 0)
|
||||
))
|
||||
))
|
||||
) {
|
||||
line[0] = 0;
|
||||
uint32 rankstring=0xFFFFFFFF;
|
||||
if((cle->Anon()==1 && cle->GetGM() && cle->Admin()>admin) || (idx>=20 && admin<100)){ //hide gms that are anon from lesser gms and normal players, cut off at 20
|
||||
rankstring=0;
|
||||
uint32 rankstring = 0xFFFFFFFF;
|
||||
if((cle->Anon()==1 && cle->GetGM() && cle->Admin()>admin) || (idx>=20 && admin < AccountStatus::GMAdmin)){ //hide gms that are anon from lesser gms and normal players, cut off at 20
|
||||
rankstring = 0;
|
||||
iterator.Advance();
|
||||
continue;
|
||||
} else if (cle->GetGM()) {
|
||||
if (cle->Admin() >=250)
|
||||
rankstring=5021;
|
||||
else if (cle->Admin() >= 200)
|
||||
rankstring=5020;
|
||||
else if (cle->Admin() >= 180)
|
||||
rankstring=5019;
|
||||
else if (cle->Admin() >= 170)
|
||||
rankstring=5018;
|
||||
else if (cle->Admin() >= 160)
|
||||
rankstring=5017;
|
||||
else if (cle->Admin() >= 150)
|
||||
rankstring=5016;
|
||||
else if (cle->Admin() >= 100)
|
||||
rankstring=5015;
|
||||
else if (cle->Admin() >= 95)
|
||||
rankstring=5014;
|
||||
else if (cle->Admin() >= 90)
|
||||
rankstring=5013;
|
||||
else if (cle->Admin() >= 85)
|
||||
rankstring=5012;
|
||||
else if (cle->Admin() >= 81)
|
||||
rankstring=5011;
|
||||
else if (cle->Admin() >= 80)
|
||||
rankstring=5010;
|
||||
else if (cle->Admin() >= 50)
|
||||
rankstring=5009;
|
||||
else if (cle->Admin() >= 20)
|
||||
rankstring=5008;
|
||||
else if (cle->Admin() >= 10)
|
||||
rankstring=5007;
|
||||
if (cle->Admin() >= AccountStatus::GMImpossible)
|
||||
rankstring = 5021;
|
||||
else if (cle->Admin() >= AccountStatus::GMMgmt)
|
||||
rankstring = 5020;
|
||||
else if (cle->Admin() >= AccountStatus::GMCoder)
|
||||
rankstring = 5019;
|
||||
else if (cle->Admin() >= AccountStatus::GMAreas)
|
||||
rankstring = 5018;
|
||||
else if (cle->Admin() >= AccountStatus::QuestMaster)
|
||||
rankstring = 5017;
|
||||
else if (cle->Admin() >= AccountStatus::GMLeadAdmin)
|
||||
rankstring = 5016;
|
||||
else if (cle->Admin() >= AccountStatus::GMAdmin)
|
||||
rankstring = 5015;
|
||||
else if (cle->Admin() >= AccountStatus::GMStaff)
|
||||
rankstring = 5014;
|
||||
else if (cle->Admin() >= AccountStatus::EQSupport)
|
||||
rankstring = 5013;
|
||||
else if (cle->Admin() >= AccountStatus::GMTester)
|
||||
rankstring = 5012;
|
||||
else if (cle->Admin() >= AccountStatus::SeniorGuide)
|
||||
rankstring = 5011;
|
||||
else if (cle->Admin() >= AccountStatus::QuestTroupe)
|
||||
rankstring = 5010;
|
||||
else if (cle->Admin() >= AccountStatus::Guide)
|
||||
rankstring = 5009;
|
||||
else if (cle->Admin() >= AccountStatus::ApprenticeGuide)
|
||||
rankstring = 5008;
|
||||
else if (cle->Admin() >= AccountStatus::Steward)
|
||||
rankstring = 5007;
|
||||
}
|
||||
idx++;
|
||||
char guildbuffer[67]={0};
|
||||
if (cle->GuildID() != GUILD_NONE && cle->GuildID()>0)
|
||||
sprintf(guildbuffer,"<%s>", guild_mgr.GetGuildName(cle->GuildID()));
|
||||
uint32 formatstring=5025;
|
||||
if(cle->Anon()==1 && (admin<cle->Admin() || admin==0))
|
||||
if(cle->Anon()==1 && (admin<cle->Admin() || admin == AccountStatus::Player))
|
||||
formatstring=5024;
|
||||
else if(cle->Anon()==1 && admin>=cle->Admin() && admin>0)
|
||||
else if(cle->Anon()==1 && admin>=cle->Admin() && admin > AccountStatus::Player)
|
||||
formatstring=5022;
|
||||
else if(cle->Anon()==2 && (admin<cle->Admin() || admin==0))
|
||||
else if(cle->Anon()==2 && (admin<cle->Admin() || admin == AccountStatus::Player))
|
||||
formatstring=5023;//display guild
|
||||
else if(cle->Anon()==2 && admin>=cle->Admin() && admin>0)
|
||||
else if(cle->Anon()==2 && admin>=cle->Admin() && admin > AccountStatus::Player)
|
||||
formatstring=5022;//display everything
|
||||
|
||||
//war* wars2 = (war*)pack2->pBuffer;
|
||||
@@ -711,10 +723,10 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
|
||||
uint32 zonestring=0xFFFFFFFF;
|
||||
uint32 plzone=0;
|
||||
uint32 unknown80[2];
|
||||
if(cle->Anon()==0 || (admin>=cle->Admin() && admin>0)){
|
||||
if(cle->Anon()==0 || (admin>=cle->Admin() && admin> AccountStatus::Player)){
|
||||
plclass_=cle->class_();
|
||||
pllevel=cle->level();
|
||||
if(admin>=100)
|
||||
if(admin>=AccountStatus::GMAdmin)
|
||||
pidstring=5003;
|
||||
plrace=cle->race();
|
||||
zonestring=5006;
|
||||
@@ -722,7 +734,7 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
|
||||
}
|
||||
|
||||
|
||||
if(admin>=cle->Admin() && admin>0)
|
||||
if(admin>=cle->Admin() && admin > AccountStatus::Player)
|
||||
unknown80[0]=cle->Admin();
|
||||
else
|
||||
unknown80[0]=0xFFFFFFFF;
|
||||
@@ -735,7 +747,7 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
|
||||
strcpy(plname,cle->name());
|
||||
|
||||
char placcount[30]={0};
|
||||
if(admin>=cle->Admin() && admin>0)
|
||||
if(admin>=cle->Admin() && admin > AccountStatus::Player)
|
||||
strcpy(placcount,cle->AccountName());
|
||||
|
||||
memcpy(bufptr,&formatstring, sizeof(uint32));
|
||||
@@ -1020,7 +1032,7 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
|
||||
if (
|
||||
(cle->Online() >= CLE_Status::Zoning)
|
||||
&& (whom == 0 || (
|
||||
((cle->Admin() >= 80 && cle->GetGM()) || whom->gmlookup == 0xFFFF) &&
|
||||
((cle->Admin() >= AccountStatus::QuestTroupe && cle->GetGM()) || whom->gmlookup == 0xFFFF) &&
|
||||
(whom->lvllow == 0xFFFF || (cle->level() >= whom->lvllow && cle->level() <= whom->lvlhigh)) &&
|
||||
(whom->wclass == 0xFFFF || cle->class_() == whom->wclass) &&
|
||||
(whom->wrace == 0xFFFF || cle->race() == whom->wrace) &&
|
||||
@@ -1028,41 +1040,41 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
|
||||
(tmpZone != 0 && strncasecmp(tmpZone, whom->whom, whomlen) == 0) ||
|
||||
strncasecmp(cle->name(), whom->whom, whomlen) == 0 ||
|
||||
(strncasecmp(guild_mgr.GetGuildName(cle->GuildID()), whom->whom, whomlen) == 0) ||
|
||||
(admin >= 100 && strncasecmp(cle->AccountName(), whom->whom, whomlen) == 0)
|
||||
(admin >= AccountStatus::GMAdmin && strncasecmp(cle->AccountName(), whom->whom, whomlen) == 0)
|
||||
))
|
||||
))
|
||||
) {
|
||||
line[0] = 0;
|
||||
// MYRA - use new (5.x) Status labels in who for telnet connection
|
||||
if (cle->Admin() >= 250)
|
||||
if (cle->Admin() >= AccountStatus::GMImpossible)
|
||||
strcpy(tmpgm, "* GM-Impossible * ");
|
||||
else if (cle->Admin() >= 200)
|
||||
else if (cle->Admin() >= AccountStatus::GMMgmt)
|
||||
strcpy(tmpgm, "* GM-Mgmt * ");
|
||||
else if (cle->Admin() >= 180)
|
||||
else if (cle->Admin() >= AccountStatus::GMCoder)
|
||||
strcpy(tmpgm, "* GM-Coder * ");
|
||||
else if (cle->Admin() >= 170)
|
||||
else if (cle->Admin() >= AccountStatus::GMAreas)
|
||||
strcpy(tmpgm, "* GM-Areas * ");
|
||||
else if (cle->Admin() >= 160)
|
||||
else if (cle->Admin() >= AccountStatus::QuestMaster)
|
||||
strcpy(tmpgm, "* QuestMaster * ");
|
||||
else if (cle->Admin() >= 150)
|
||||
else if (cle->Admin() >= AccountStatus::GMLeadAdmin)
|
||||
strcpy(tmpgm, "* GM-Lead Admin * ");
|
||||
else if (cle->Admin() >= 100)
|
||||
else if (cle->Admin() >= AccountStatus::GMAdmin)
|
||||
strcpy(tmpgm, "* GM-Admin * ");
|
||||
else if (cle->Admin() >= 95)
|
||||
else if (cle->Admin() >= AccountStatus::GMStaff)
|
||||
strcpy(tmpgm, "* GM-Staff * ");
|
||||
else if (cle->Admin() >= 90)
|
||||
else if (cle->Admin() >= AccountStatus::EQSupport)
|
||||
strcpy(tmpgm, "* EQ Support * ");
|
||||
else if (cle->Admin() >= 85)
|
||||
else if (cle->Admin() >= AccountStatus::GMTester)
|
||||
strcpy(tmpgm, "* GM-Tester * ");
|
||||
else if (cle->Admin() >= 81)
|
||||
else if (cle->Admin() >= AccountStatus::SeniorGuide)
|
||||
strcpy(tmpgm, "* Senior Guide * ");
|
||||
else if (cle->Admin() >= 80)
|
||||
else if (cle->Admin() >= AccountStatus::QuestTroupe)
|
||||
strcpy(tmpgm, "* QuestTroupe * ");
|
||||
else if (cle->Admin() >= 50)
|
||||
else if (cle->Admin() >= AccountStatus::Guide)
|
||||
strcpy(tmpgm, "* Guide * ");
|
||||
else if (cle->Admin() >= 20)
|
||||
else if (cle->Admin() >= AccountStatus::ApprenticeGuide)
|
||||
strcpy(tmpgm, "* Apprentice Guide * ");
|
||||
else if (cle->Admin() >= 10)
|
||||
else if (cle->Admin() >= AccountStatus::Steward)
|
||||
strcpy(tmpgm, "* Steward * ");
|
||||
else
|
||||
tmpgm[0] = 0;
|
||||
@@ -1079,16 +1091,16 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
|
||||
else
|
||||
LFG[0] = 0;
|
||||
|
||||
if (admin >= 150 && admin >= cle->Admin()) {
|
||||
if (admin >= AccountStatus::GMLeadAdmin && admin >= cle->Admin()) {
|
||||
sprintf(accinfo, " AccID: %i AccName: %s LSID: %i Status: %i", cle->AccountID(), cle->AccountName(), cle->LSAccountID(), cle->Admin());
|
||||
}
|
||||
else
|
||||
accinfo[0] = 0;
|
||||
|
||||
if (cle->Anon() == 2) { // Roleplay
|
||||
if (admin >= 100 && admin >= cle->Admin())
|
||||
if (admin >= AccountStatus::GMAdmin && admin >= cle->Admin())
|
||||
sprintf(line, " %s[RolePlay %i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetClassIDName(cle->class_(), cle->level()), cle->name(), GetRaceIDName(cle->race()), tmpguild, tmpZone, LFG, accinfo);
|
||||
else if (cle->Admin() >= 80 && admin < 80 && cle->GetGM()) {
|
||||
else if (cle->Admin() >= AccountStatus::QuestTroupe && admin < AccountStatus::QuestTroupe && cle->GetGM()) {
|
||||
iterator.Advance();
|
||||
continue;
|
||||
}
|
||||
@@ -1096,9 +1108,9 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
|
||||
sprintf(line, " %s[ANONYMOUS] %s%s%s%s", tmpgm, cle->name(), tmpguild, LFG, accinfo);
|
||||
}
|
||||
else if (cle->Anon() == 1) { // Anon
|
||||
if (admin >= 100 && admin >= cle->Admin())
|
||||
if (admin >= AccountStatus::GMAdmin && admin >= cle->Admin())
|
||||
sprintf(line, " %s[ANON %i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetClassIDName(cle->class_(), cle->level()), cle->name(), GetRaceIDName(cle->race()), tmpguild, tmpZone, LFG, accinfo);
|
||||
else if (cle->Admin() >= 80 && cle->GetGM()) {
|
||||
else if (cle->Admin() >= AccountStatus::QuestTroupe && cle->GetGM()) {
|
||||
iterator.Advance();
|
||||
continue;
|
||||
}
|
||||
@@ -1111,7 +1123,13 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
|
||||
fmt::format_to(out, line);
|
||||
if (out.size() >= 3584) {
|
||||
auto output = fmt::to_string(out);
|
||||
connection->SendEmoteMessageRaw(to, 0, 0, 10, output.c_str());
|
||||
connection->SendEmoteMessageRaw(
|
||||
to,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::NPCQuestSay,
|
||||
output.c_str()
|
||||
);
|
||||
out.clear();
|
||||
}
|
||||
else {
|
||||
@@ -1121,17 +1139,17 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
|
||||
fmt::format_to(out, "\n");
|
||||
}
|
||||
x++;
|
||||
if (x >= 20 && admin < 80)
|
||||
if (x >= 20 && admin < AccountStatus::QuestTroupe)
|
||||
break;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
if (x >= 20 && admin < 80)
|
||||
if (x >= 20 && admin < AccountStatus::QuestTroupe)
|
||||
fmt::format_to(out, "too many results...20 players shown");
|
||||
else
|
||||
fmt::format_to(out, "{} players online", x);
|
||||
if (admin >= 150 && (whom == 0 || whom->gmlookup != 0xFFFF)) {
|
||||
if (admin >= AccountStatus::GMAdmin && (whom == 0 || whom->gmlookup != 0xFFFF)) {
|
||||
if (connection->IsConsole())
|
||||
fmt::format_to(out, "\r\n");
|
||||
else
|
||||
@@ -1140,7 +1158,13 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
|
||||
//console_list.SendConsoleWho(connection, to, admin, &output, &outsize, &outlen);
|
||||
}
|
||||
auto output = fmt::to_string(out);
|
||||
connection->SendEmoteMessageRaw(to, 0, 0, 10, output.c_str());
|
||||
connection->SendEmoteMessageRaw(
|
||||
to,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::NPCQuestSay,
|
||||
output.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
void ClientList::Add(Client* client) {
|
||||
@@ -1386,7 +1410,7 @@ void ClientList::SendClientVersionSummary(const char *Name)
|
||||
zoneserver_list.SendEmoteMessage(
|
||||
Name,
|
||||
0,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"There {} {} Titanium, {} SoF, {} SoD, {} UF, {} RoF, and {} RoF2 Client{} currently connected for a total of {} Client{} and {} Unique IP{} connected.",
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ public:
|
||||
void DisconnectByIP(uint32 iIP);
|
||||
void CLCheckStale();
|
||||
void CLEKeepAlive(uint32 numupdates, uint32* wid);
|
||||
void CLEAdd(uint32 iLSID, const char* iLoginServerName, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin = 0, uint32 ip = 0, uint8 local=0);
|
||||
void CLEAdd(uint32 iLSID, const char* iLoginServerName, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin = AccountStatus::Player, uint32 ip = 0, uint8 local=0);
|
||||
void UpdateClientGuild(uint32 char_id, uint32 guild_id);
|
||||
void RemoveCLEByLSID(uint32 iLSID);
|
||||
bool IsAccountInGame(uint32 iLSID);
|
||||
|
||||
+38
-7
@@ -280,20 +280,33 @@ void ConsoleEmote(
|
||||
join_args.erase(join_args.begin(), join_args.begin() + 2);
|
||||
|
||||
if (strcasecmp(args[0].c_str(), "world") == 0) {
|
||||
zoneserver_list.SendEmoteMessageRaw(0, 0, 0, atoi(args[1].c_str()), JoinString(join_args, " ").c_str());
|
||||
zoneserver_list.SendEmoteMessageRaw(
|
||||
0,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
atoi(args[1].c_str()),
|
||||
JoinString(join_args, " ").c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
ZoneServer *zs = zoneserver_list.FindByName(args[0].c_str());
|
||||
if (zs != 0) {
|
||||
zs->SendEmoteMessageRaw(0, 0, 0, atoi(args[1].c_str()), JoinString(join_args, " ").c_str());
|
||||
zs->SendEmoteMessageRaw(
|
||||
0,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
atoi(args[1].c_str()),
|
||||
JoinString(join_args, " ").c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
zoneserver_list.SendEmoteMessageRaw(
|
||||
args[0].c_str(),
|
||||
0,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
atoi(args[1].c_str()),
|
||||
JoinString(join_args, " ").c_str());
|
||||
JoinString(join_args, " ").c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -637,7 +650,16 @@ void ConsoleZoneLock(
|
||||
uint16 tmp = ZoneID(args[1].c_str());
|
||||
if (tmp) {
|
||||
if (zoneserver_list.SetLockedZone(tmp, true)) {
|
||||
zoneserver_list.SendEmoteMessage(0, 0, 80, 15, "Zone locked: %s", ZoneName(tmp));
|
||||
zoneserver_list.SendEmoteMessage(
|
||||
0,
|
||||
0,
|
||||
AccountStatus::QuestTroupe,
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Zone locked: {}",
|
||||
ZoneName(tmp)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
connection->SendLine("Failed to change lock");
|
||||
@@ -655,7 +677,16 @@ void ConsoleZoneLock(
|
||||
uint16 tmp = ZoneID(args[1].c_str());
|
||||
if (tmp) {
|
||||
if (zoneserver_list.SetLockedZone(tmp, false)) {
|
||||
zoneserver_list.SendEmoteMessage(0, 0, 80, 15, "Zone unlocked: %s", ZoneName(tmp));
|
||||
zoneserver_list.SendEmoteMessage(
|
||||
0,
|
||||
0,
|
||||
AccountStatus::QuestTroupe,
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Zone unlocked: {}",
|
||||
ZoneName(tmp)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
connection->SendLine("Failed to change lock");
|
||||
@@ -782,7 +813,7 @@ void ConsoleWorldShutdown(
|
||||
zoneserver_list.SendEmoteMessage(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::Yellow,
|
||||
"[SYSTEM] World shutdown has been aborted."
|
||||
);
|
||||
|
||||
@@ -481,10 +481,10 @@ void Console::ProcessCommand(const char* command) {
|
||||
SendMessage(1, " version");
|
||||
SendMessage(1, " worldshutdown");
|
||||
}
|
||||
if (admin >= 201) {
|
||||
if (admin >= AccountStatus::GMMgmt) {
|
||||
SendMessage(1, " IPLookup [name]");
|
||||
}
|
||||
if (admin >= 100) {
|
||||
if (admin >= AccountStatus::GMAdmin) {
|
||||
SendMessage(1, " LSReconnect");
|
||||
SendMessage(1, " signalcharbyname charname ID");
|
||||
SendMessage(1, " reloadworld");
|
||||
@@ -799,7 +799,7 @@ void Console::ProcessCommand(const char* command) {
|
||||
SendMessage(1, " Compiled on: %s at %s", COMPILE_DATE, COMPILE_TIME);
|
||||
SendMessage(1, " Last modified on: %s", LAST_MODIFIED);
|
||||
}
|
||||
else if (strcasecmp(sep.arg[0], "serverinfo") == 0 && admin >= 200) {
|
||||
else if (strcasecmp(sep.arg[0], "serverinfo") == 0 && admin >= AccountStatus::GMMgmt) {
|
||||
if (strcasecmp(sep.arg[1], "os") == 0) {
|
||||
#ifdef _WINDOWS
|
||||
GetOS();
|
||||
@@ -821,10 +821,10 @@ void Console::ProcessCommand(const char* command) {
|
||||
SendMessage(1, " OS - Operating system version information.");
|
||||
}
|
||||
}
|
||||
else if (strcasecmp(sep.arg[0], "IPLookup") == 0 && admin >= 201) {
|
||||
else if (strcasecmp(sep.arg[0], "IPLookup") == 0 && admin >= AccountStatus::GMMgmt) {
|
||||
client_list.SendCLEList(admin, 0, this, sep.argplus[1]);
|
||||
}
|
||||
else if (strcasecmp(sep.arg[0], "LSReconnect") == 0 && admin >= 100) {
|
||||
else if (strcasecmp(sep.arg[0], "LSReconnect") == 0 && admin >= AccountStatus::GMAdmin) {
|
||||
#ifdef _WINDOWS
|
||||
_beginthread(AutoInitLoginServer, 0, nullptr);
|
||||
#else
|
||||
@@ -839,7 +839,7 @@ void Console::ProcessCommand(const char* command) {
|
||||
if (strcasecmp(sep.arg[1], "list") == 0) {
|
||||
zoneserver_list.ListLockedZones(0, this);
|
||||
}
|
||||
else if (strcasecmp(sep.arg[1], "lock") == 0 && admin >= 101) {
|
||||
else if (strcasecmp(sep.arg[1], "lock") == 0 && admin >= AccountStatus::GMAdmin) {
|
||||
uint16 tmp = ZoneID(sep.arg[2]);
|
||||
if (tmp) {
|
||||
if (zoneserver_list.SetLockedZone(tmp, true))
|
||||
@@ -850,7 +850,7 @@ void Console::ProcessCommand(const char* command) {
|
||||
else
|
||||
SendMessage(1, "Usage: #zonelock lock [zonename]");
|
||||
}
|
||||
else if (strcasecmp(sep.arg[1], "unlock") == 0 && admin >= 101) {
|
||||
else if (strcasecmp(sep.arg[1], "unlock") == 0 && admin >= AccountStatus::GMAdmin) {
|
||||
uint16 tmp = ZoneID(sep.arg[2]);
|
||||
if (tmp) {
|
||||
if (zoneserver_list.SetLockedZone(tmp, false))
|
||||
@@ -864,13 +864,13 @@ void Console::ProcessCommand(const char* command) {
|
||||
else {
|
||||
SendMessage(1, "#zonelock sub-commands");
|
||||
SendMessage(1, " list");
|
||||
if (admin >= 101) {
|
||||
if (admin >= AccountStatus::GMAdmin) {
|
||||
SendMessage(1, " lock [zonename]");
|
||||
SendMessage(1, " unlock [zonename]");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (strcasecmp(sep.arg[0], "reloadworld") == 0 && admin > 101)
|
||||
else if (strcasecmp(sep.arg[0], "reloadworld") == 0 && admin > AccountStatus::GMAdmin)
|
||||
{
|
||||
SendEmoteMessage(0,0,0,15,"Reloading World...");
|
||||
auto pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct));
|
||||
|
||||
+8
-1
@@ -37,6 +37,7 @@
|
||||
#include "launcher_list.h"
|
||||
#include "launcher_link.h"
|
||||
#include "wguild_mgr.h"
|
||||
#include "../common/emu_constants.h"
|
||||
|
||||
#ifdef seed
|
||||
#undef seed
|
||||
@@ -360,7 +361,13 @@ void EQW::ResolveBug(const char *id) {
|
||||
}
|
||||
|
||||
void EQW::SendMessage(uint32 type, const char *msg) {
|
||||
zoneserver_list.SendEmoteMessage(0, 0, 0, type, msg);
|
||||
zoneserver_list.SendEmoteMessage(
|
||||
0,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
type,
|
||||
msg
|
||||
);
|
||||
}
|
||||
|
||||
void EQW::WorldShutDown(uint32 time, uint32 interval) {
|
||||
|
||||
@@ -306,7 +306,13 @@ void LoginServer::ProcessSystemwideMessage(uint16_t opcode, EQ::Net::Packet &p)
|
||||
LogNetcode("Received ServerPacket from LS OpCode {:#04x}", opcode);
|
||||
|
||||
ServerSystemwideMessage *swm = (ServerSystemwideMessage *) p.Data();
|
||||
zoneserver_list.SendEmoteMessageRaw(0, 0, 0, swm->type, swm->message);
|
||||
zoneserver_list.SendEmoteMessageRaw(
|
||||
0,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
swm->type,
|
||||
swm->message
|
||||
);
|
||||
}
|
||||
|
||||
void LoginServer::ProcessLSRemoteAddr(uint16_t opcode, EQ::Net::Packet &p)
|
||||
|
||||
+14
-8
@@ -119,7 +119,6 @@ EQ::Random emu_random;
|
||||
volatile bool RunLoops = true;
|
||||
uint32 numclients = 0;
|
||||
uint32 numzones = 0;
|
||||
bool holdzones = false;
|
||||
const WorldConfig *Config;
|
||||
EQEmuLogSys LogSys;
|
||||
WorldContentService content_service;
|
||||
@@ -252,13 +251,15 @@ static void GMSayHookCallBackProcessWorld(uint16 log_category, std::string messa
|
||||
|
||||
for (size_t iter = 0; iter < message_split.size(); ++iter) {
|
||||
zoneserver_list.SendEmoteMessage(
|
||||
nullptr,
|
||||
0,
|
||||
80,
|
||||
0,
|
||||
AccountStatus::QuestTroupe,
|
||||
LogSys.GetGMSayColorFromCategory(log_category),
|
||||
" %s%s",
|
||||
(iter == 0 ? " ---" : ""),
|
||||
message_split[iter].c_str()
|
||||
fmt::format(
|
||||
" {}{}",
|
||||
(iter == 0 ? " ---" : ""),
|
||||
message_split[iter]
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -266,9 +267,9 @@ static void GMSayHookCallBackProcessWorld(uint16 log_category, std::string messa
|
||||
}
|
||||
|
||||
zoneserver_list.SendEmoteMessage(
|
||||
nullptr,
|
||||
0,
|
||||
80,
|
||||
0,
|
||||
AccountStatus::QuestTroupe,
|
||||
LogSys.GetGMSayColorFromCategory(log_category),
|
||||
"%s",
|
||||
message.c_str()
|
||||
@@ -502,6 +503,11 @@ int main(int argc, char **argv)
|
||||
LogInfo("Initializing [EventScheduler]");
|
||||
event_scheduler.SetDatabase(&database)->LoadScheduledEvents();
|
||||
|
||||
LogInfo("Initializing [WorldContentService]");
|
||||
content_service.SetDatabase(&database)
|
||||
->SetExpansionContext()
|
||||
->ReloadContentFlags();
|
||||
|
||||
LogInfo("Initializing [SharedTaskManager]");
|
||||
shared_task_manager.SetDatabase(&database)
|
||||
->SetContentDatabase(&content_db)
|
||||
|
||||
@@ -45,7 +45,13 @@ void WorldEventScheduler::Process(ZSList *zs_list)
|
||||
if (ValidateEventReadyToActivate(e)) {
|
||||
if (e.event_type == ServerEvents::EVENT_TYPE_BROADCAST) {
|
||||
LogScheduler("Sending broadcast [{}]", e.event_data.c_str());
|
||||
zs_list->SendEmoteMessage(nullptr, 0, 0, 15, e.event_data.c_str());
|
||||
zs_list->SendEmoteMessage(
|
||||
0,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::Yellow,
|
||||
e.event_data.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
if (e.event_type == ServerEvents::EVENT_TYPE_RELOAD_WORLD) {
|
||||
|
||||
@@ -165,37 +165,37 @@ namespace WorldserverCommandHandler {
|
||||
|
||||
Json::Value player_tables_json;
|
||||
std::vector<std::string> player_tables = DatabaseSchema::GetPlayerTables();
|
||||
for (const auto &table : player_tables) {
|
||||
for (const auto &table: player_tables) {
|
||||
player_tables_json.append(table);
|
||||
}
|
||||
|
||||
Json::Value content_tables_json;
|
||||
std::vector<std::string> content_tables = DatabaseSchema::GetContentTables();
|
||||
for (const auto &table : content_tables) {
|
||||
for (const auto &table: content_tables) {
|
||||
content_tables_json.append(table);
|
||||
}
|
||||
|
||||
Json::Value server_tables_json;
|
||||
std::vector<std::string> server_tables = DatabaseSchema::GetServerTables();
|
||||
for (const auto &table : server_tables) {
|
||||
for (const auto &table: server_tables) {
|
||||
server_tables_json.append(table);
|
||||
}
|
||||
|
||||
Json::Value login_tables_json;
|
||||
std::vector<std::string> login_tables = DatabaseSchema::GetLoginTables();
|
||||
for (const auto &table : login_tables) {
|
||||
for (const auto &table: login_tables) {
|
||||
login_tables_json.append(table);
|
||||
}
|
||||
|
||||
Json::Value state_tables_json;
|
||||
std::vector<std::string> state_tables = DatabaseSchema::GetStateTables();
|
||||
for (const auto &table : state_tables) {
|
||||
for (const auto &table: state_tables) {
|
||||
state_tables_json.append(table);
|
||||
}
|
||||
|
||||
Json::Value version_tables_json;
|
||||
std::vector<std::string> version_tables = DatabaseSchema::GetVersionTables();
|
||||
for (const auto &table : version_tables) {
|
||||
for (const auto &table: version_tables) {
|
||||
version_tables_json.append(table);
|
||||
}
|
||||
|
||||
@@ -313,11 +313,20 @@ namespace WorldserverCommandHandler {
|
||||
|
||||
content_service.SetCurrentExpansion(RuleI(Expansion, CurrentExpansion));
|
||||
|
||||
std::vector<std::string> flags = {
|
||||
std::vector<ContentFlagsRepository::ContentFlags> flags = {};
|
||||
auto f = ContentFlagsRepository::NewEntity();
|
||||
f.enabled = 1;
|
||||
|
||||
std::vector<std::string> flag_names = {
|
||||
"hateplane_enabled",
|
||||
"patch_nerf_7077",
|
||||
};
|
||||
|
||||
for (auto &name: flag_names) {
|
||||
f.flag_name = name;
|
||||
flags.push_back(f);
|
||||
}
|
||||
|
||||
content_service.SetContentFlags(flags);
|
||||
|
||||
LogInfo(
|
||||
|
||||
@@ -85,6 +85,26 @@ std::string WorldStore::GetZoneName(uint32 zone_id)
|
||||
return std::string();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param zone_id
|
||||
* @param error_unknown
|
||||
* @return
|
||||
*/
|
||||
const char *WorldStore::GetZoneLongName(uint32 zone_id, bool error_unknown)
|
||||
{
|
||||
for (auto &z: zones) {
|
||||
if (z.zoneidnumber == zone_id) {
|
||||
return z.long_name.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (error_unknown) {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param zone_id
|
||||
* @return
|
||||
|
||||
+8
-2
@@ -40,7 +40,7 @@ public:
|
||||
std::string GetZoneName(uint32 zone_id);
|
||||
std::string GetZoneLongName(uint32 zone_id);
|
||||
const char *GetZoneName(uint32 zone_id, bool error_unknown = false);
|
||||
|
||||
const char *GetZoneLongName(uint32 zone_id, bool error_unknown = false);
|
||||
};
|
||||
|
||||
extern WorldStore world_store;
|
||||
@@ -57,7 +57,13 @@ inline const char *ZoneName(uint32 zone_id, bool error_unknown = false)
|
||||
error_unknown
|
||||
);
|
||||
}
|
||||
inline const char *ZoneLongName(uint32 zone_id) { return world_store.GetZoneLongName(zone_id).c_str(); }
|
||||
inline const char *ZoneLongName(uint32 zone_id, bool error_unknown = false)
|
||||
{
|
||||
return world_store.GetZoneLongName(
|
||||
zone_id,
|
||||
error_unknown
|
||||
);
|
||||
}
|
||||
inline ZoneRepository::Zone GetZone(uint32 zone_id, int version = 0) { return world_store.GetZone(zone_id, version); };
|
||||
inline ZoneRepository::Zone GetZone(const char *in_zone_name) { return world_store.GetZone(in_zone_name); };
|
||||
|
||||
|
||||
+115
-37
@@ -30,7 +30,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "world_store.h"
|
||||
|
||||
extern uint32 numzones;
|
||||
extern bool holdzones;
|
||||
extern EQ::Random emu_random;
|
||||
extern WebInterfaceList web_interface;
|
||||
volatile bool UCSServerAvailable_ = false;
|
||||
@@ -51,19 +50,17 @@ ZSList::~ZSList() {
|
||||
|
||||
void ZSList::ShowUpTime(WorldTCPConnection* con, const char* adminname) {
|
||||
uint32 ms = Timer::GetCurrentTime();
|
||||
uint32 d = ms / 86400000;
|
||||
ms -= d * 86400000;
|
||||
uint32 h = ms / 3600000;
|
||||
ms -= h * 3600000;
|
||||
uint32 m = ms / 60000;
|
||||
ms -= m * 60000;
|
||||
uint32 s = ms / 1000;
|
||||
if (d)
|
||||
con->SendEmoteMessage(adminname, 0, 0, 0, "Worldserver Uptime: %02id %02ih %02im %02is", d, h, m, s);
|
||||
else if (h)
|
||||
con->SendEmoteMessage(adminname, 0, 0, 0, "Worldserver Uptime: %02ih %02im %02is", h, m, s);
|
||||
else
|
||||
con->SendEmoteMessage(adminname, 0, 0, 0, "Worldserver Uptime: %02im %02is", m, s);
|
||||
std::string time_string = ConvertMillisecondsToTime(ms);
|
||||
con->SendEmoteMessage(
|
||||
adminname,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Worldserver Uptime | {}",
|
||||
time_string
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
void ZSList::Add(ZoneServer* zoneserver) {
|
||||
@@ -113,7 +110,7 @@ void ZSList::Process() {
|
||||
SendEmoteMessage(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"[SYSTEM] World will be shutting down in {} minutes.",
|
||||
@@ -270,14 +267,39 @@ bool ZSList::IsZoneLocked(uint16 iZoneID) {
|
||||
}
|
||||
|
||||
void ZSList::ListLockedZones(const char* to, WorldTCPConnection* connection) {
|
||||
int x = 0;
|
||||
for (auto &zone : pLockedZones) {
|
||||
if (zone) {
|
||||
connection->SendEmoteMessageRaw(to, 0, 0, 0, ZoneName(zone, true));
|
||||
x++;
|
||||
int zone_count = 0;
|
||||
for (const auto& zone_id : pLockedZones) {
|
||||
if (zone_id) {
|
||||
int zone_number = (zone_count + 1);
|
||||
connection->SendEmoteMessageRaw(
|
||||
to,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Zone {} | Name: {} ({}) ID: {}",
|
||||
zone_number,
|
||||
ZoneLongName(zone_id),
|
||||
ZoneName(zone_id),
|
||||
zone_id
|
||||
).c_str()
|
||||
);
|
||||
zone_count++;
|
||||
}
|
||||
}
|
||||
connection->SendEmoteMessage(to, 0, 0, 0, "%i zones locked.", x);
|
||||
|
||||
std::string zone_message = (
|
||||
zone_count ?
|
||||
fmt::format("{} Zones are locked.", zone_count) :
|
||||
"There are no zones locked."
|
||||
);
|
||||
connection->SendEmoteMessage(
|
||||
to,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
zone_message.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* connection) {
|
||||
@@ -330,7 +352,7 @@ void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* con
|
||||
else
|
||||
is_static_string[0] = 'D';
|
||||
|
||||
if (admin >= 150) {
|
||||
if (admin >= AccountStatus::GMLeadAdmin) {
|
||||
if (zone_server_data->GetZoneID()) {
|
||||
snprintf(zone_data_string, sizeof(zone_data_string), "%s (%i)", zone_server_data->GetZoneName(), zone_server_data->GetZoneID());
|
||||
}
|
||||
@@ -356,7 +378,13 @@ void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* con
|
||||
|
||||
if (out.size() >= 3584) {
|
||||
auto output = fmt::to_string(out);
|
||||
connection->SendEmoteMessageRaw(to, 0, 0, 10, output.c_str());
|
||||
connection->SendEmoteMessageRaw(
|
||||
to,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::NPCQuestSay,
|
||||
output.c_str()
|
||||
);
|
||||
out.clear();
|
||||
}
|
||||
else {
|
||||
@@ -375,7 +403,13 @@ void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* con
|
||||
fmt::format_to(out, " #{} {} {}", zone_server_data->GetID(), is_static_string, zone_data_string);
|
||||
if (out.size() >= 3584) {
|
||||
auto output = fmt::to_string(out);
|
||||
connection->SendEmoteMessageRaw(to, 0, 0, 10, output.c_str());
|
||||
connection->SendEmoteMessageRaw(
|
||||
to,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::NPCQuestSay,
|
||||
output.c_str()
|
||||
);
|
||||
out.clear();
|
||||
}
|
||||
else {
|
||||
@@ -402,7 +436,13 @@ void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* con
|
||||
fmt::format_to(out, "{} zones are static zones, {} zones are booted zones, {} zones available.", z, w, v);
|
||||
|
||||
auto output = fmt::to_string(out);
|
||||
connection->SendEmoteMessageRaw(to, 0, 0, 10, output.c_str());
|
||||
connection->SendEmoteMessageRaw(
|
||||
to,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::NPCQuestSay,
|
||||
output.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
void ZSList::SendChannelMessage(const char* from, const char* to, uint8 chan_num, uint8 language, const char* message, ...) {
|
||||
@@ -533,20 +573,52 @@ void ZSList::SOPZoneBootup(const char* adminname, uint32 ZoneServerID, const cha
|
||||
ZoneServer* zs = 0;
|
||||
ZoneServer* zs2 = 0;
|
||||
uint32 zoneid;
|
||||
if (!(zoneid = ZoneID(zonename)))
|
||||
SendEmoteMessage(adminname, 0, 0, 0, "Error: SOP_ZoneBootup: zone '%s' not found in 'zone' table. Typo protection=ON.", zonename);
|
||||
else {
|
||||
if (ZoneServerID != 0)
|
||||
if (!(zoneid = ZoneID(zonename))) {
|
||||
SendEmoteMessage(
|
||||
adminname,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Error: SOP_ZoneBootup: Zone '{}' not found in 'zone' table.",
|
||||
zonename
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
if (ZoneServerID != 0) {
|
||||
zs = FindByID(ZoneServerID);
|
||||
else
|
||||
SendEmoteMessage(adminname, 0, 0, 0, "Error: SOP_ZoneBootup: ServerID must be specified");
|
||||
} else {
|
||||
SendEmoteMessage(
|
||||
adminname,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
"Error: SOP_ZoneBootup: Server ID must be specified."
|
||||
);
|
||||
}
|
||||
|
||||
if (zs == 0)
|
||||
SendEmoteMessage(adminname, 0, 0, 0, "Error: SOP_ZoneBootup: zoneserver not found");
|
||||
else {
|
||||
if (!zs) {
|
||||
SendEmoteMessage(
|
||||
adminname,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
"Error: SOP_ZoneBootup: Zoneserver not found."
|
||||
);
|
||||
} else {
|
||||
zs2 = FindByName(zonename);
|
||||
if (zs2 != 0)
|
||||
SendEmoteMessage(adminname, 0, 0, 0, "Error: SOP_ZoneBootup: zone '%s' already being hosted by ZoneServer #%i", zonename, zs2->GetID());
|
||||
SendEmoteMessage(
|
||||
adminname,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Error: SOP_ZoneBootup: Zone '{}' already being hosted by Zoneserver ID {}.",
|
||||
zonename,
|
||||
zs2->GetID()
|
||||
).c_str()
|
||||
);
|
||||
else {
|
||||
zs->TriggerBootup(zoneid, 0, adminname, iMakeStatic);
|
||||
}
|
||||
@@ -689,7 +761,7 @@ void ZSList::WorldShutDown(uint32 time, uint32 interval)
|
||||
SendEmoteMessage(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"[SYSTEM] World will be shutting down in {} minutes.",
|
||||
@@ -708,7 +780,13 @@ void ZSList::WorldShutDown(uint32 time, uint32 interval)
|
||||
reminder->Start();
|
||||
}
|
||||
else {
|
||||
SendEmoteMessage(0, 0, 0, 15, "[SYSTEM] World is shutting down.");
|
||||
SendEmoteMessage(
|
||||
0,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::Yellow,
|
||||
"[SYSTEM] World is shutting down."
|
||||
);
|
||||
auto pack = new ServerPacket;
|
||||
pack->opcode = ServerOP_ShutdownAll;
|
||||
pack->size = 0;
|
||||
|
||||
+167
-54
@@ -41,6 +41,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "shared_task_world_messaging.h"
|
||||
#include "../common/shared_tasks.h"
|
||||
#include "shared_task_manager.h"
|
||||
#include "../common/content/world_content_service.h"
|
||||
|
||||
extern ClientList client_list;
|
||||
extern GroupLFPList LFPGroupList;
|
||||
@@ -438,7 +439,16 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
safe_delete(pack);
|
||||
}))) && (!scm->noreply))
|
||||
{
|
||||
zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "%s is not online at this time.", scm->to);
|
||||
zoneserver_list.SendEmoteMessage(
|
||||
scm->from,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} is not online at this time.",
|
||||
scm->to
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -446,7 +456,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
|
||||
ClientListEntry* cle = client_list.FindCharacter(scm->deliverto);
|
||||
if (cle == 0 || cle->Online() < CLE_Status::Zoning ||
|
||||
(cle->TellsOff() && ((cle->Anon() == 1 && scm->fromadmin < cle->Admin()) || scm->fromadmin < 80))) {
|
||||
(cle->TellsOff() && ((cle->Anon() == 1 && scm->fromadmin < cle->Admin()) || scm->fromadmin < AccountStatus::QuestTroupe))) {
|
||||
if (!scm->noreply) {
|
||||
ClientListEntry* sender = client_list.FindCharacter(scm->from);
|
||||
if (!sender || !sender->Server())
|
||||
@@ -491,7 +501,17 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
}
|
||||
else if (cle->Server() == 0) {
|
||||
if (!scm->noreply)
|
||||
zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not contactable at this time'", scm->to, scm->to);
|
||||
zoneserver_list.SendEmoteMessage(
|
||||
scm->from,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"You told {}, '{} is not contactable at this time'",
|
||||
scm->to,
|
||||
scm->to
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else
|
||||
cle->Server()->SendPacket(pack);
|
||||
@@ -518,29 +538,36 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
}
|
||||
case ServerOP_EmoteMessage: {
|
||||
ServerEmoteMessage_Struct* sem = (ServerEmoteMessage_Struct*)pack->pBuffer;
|
||||
zoneserver_list.SendEmoteMessageRaw(sem->to, sem->guilddbid, sem->minstatus, sem->type, sem->message);
|
||||
zoneserver_list.SendEmoteMessageRaw(
|
||||
sem->to,
|
||||
sem->guilddbid,
|
||||
sem->minstatus,
|
||||
sem->type,
|
||||
sem->message
|
||||
);
|
||||
break;
|
||||
}
|
||||
case ServerOP_VoiceMacro: {
|
||||
|
||||
ServerVoiceMacro_Struct* svm = (ServerVoiceMacro_Struct*)pack->pBuffer;
|
||||
|
||||
if (svm->Type == VoiceMacroTell) {
|
||||
|
||||
ClientListEntry* cle = client_list.FindCharacter(svm->To);
|
||||
|
||||
if (!cle || (cle->Online() < CLE_Status::Zoning) || !cle->Server()) {
|
||||
|
||||
zoneserver_list.SendEmoteMessage(svm->From, 0, 0, 0, "'%s is not online at this time'", svm->To);
|
||||
|
||||
zoneserver_list.SendEmoteMessage(
|
||||
svm->From,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"'{} is not online at this time'",
|
||||
svm->To
|
||||
).c_str()
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
cle->Server()->SendPacket(pack);
|
||||
}
|
||||
else
|
||||
} else {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -656,17 +683,31 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
case ServerOP_ZoneShutdown: {
|
||||
ServerZoneStateChange_struct* s = (ServerZoneStateChange_struct *)pack->pBuffer;
|
||||
ZoneServer* zs = 0;
|
||||
if (s->ZoneServerID != 0)
|
||||
if (s->ZoneServerID != 0) {
|
||||
zs = zoneserver_list.FindByID(s->ZoneServerID);
|
||||
else if (s->zoneid != 0)
|
||||
} else if (s->zoneid != 0) {
|
||||
zs = zoneserver_list.FindByName(ZoneName(s->zoneid));
|
||||
else
|
||||
zoneserver_list.SendEmoteMessage(s->adminname, 0, 0, 0, "Error: SOP_ZoneShutdown: neither ID nor name specified");
|
||||
} else {
|
||||
zoneserver_list.SendEmoteMessage(
|
||||
s->adminname,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
"Error: SOP_ZoneShutdown: neither ID nor name specified"
|
||||
);
|
||||
}
|
||||
|
||||
if (zs == 0)
|
||||
zoneserver_list.SendEmoteMessage(s->adminname, 0, 0, 0, "Error: SOP_ZoneShutdown: zoneserver not found");
|
||||
else
|
||||
if (!zs) {
|
||||
zoneserver_list.SendEmoteMessage(
|
||||
s->adminname,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
"Error: SOP_ZoneShutdown: zoneserver not found"
|
||||
);
|
||||
} else {
|
||||
zs->SendPacket(pack);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_ZoneBootup: {
|
||||
@@ -717,7 +758,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
if (GetZoneID() == ztz->current_zone_id && GetInstanceID() == ztz->current_instance_id) {
|
||||
LogInfo("Processing ZTZ for egress from zone for client [{}]", ztz->name);
|
||||
|
||||
if (ztz->admin < 80 && ztz->ignorerestrictions < 2 && zoneserver_list.IsZoneLocked(ztz->requested_zone_id)) {
|
||||
if (ztz->admin < AccountStatus::QuestTroupe && ztz->ignorerestrictions < 2 && zoneserver_list.IsZoneLocked(ztz->requested_zone_id)) {
|
||||
ztz->response = 0;
|
||||
SendPacket(pack);
|
||||
break;
|
||||
@@ -828,6 +869,11 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
RuleManager::Instance()->LoadRules(&database, "default", true);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadContentFlags: {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
content_service.SetExpansionContext()->ReloadContentFlags();
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadRulesWorld:
|
||||
{
|
||||
RuleManager::Instance()->LoadRules(&database, "default", true);
|
||||
@@ -909,15 +955,43 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
ServerGMGoto_Struct* gmg = (ServerGMGoto_Struct*)pack->pBuffer;
|
||||
ClientListEntry* cle = client_list.FindCharacter(gmg->gotoname);
|
||||
if (cle != 0) {
|
||||
if (cle->Server() == 0)
|
||||
this->SendEmoteMessage(gmg->myname, 0, 0, 13, "Error: Cannot identify %s's zoneserver.", gmg->gotoname);
|
||||
else if (cle->Anon() == 1 && cle->Admin() > gmg->admin) // no snooping for anon GMs
|
||||
this->SendEmoteMessage(gmg->myname, 0, 0, 13, "Error: %s not found", gmg->gotoname);
|
||||
else
|
||||
if (!cle->Server()) {
|
||||
SendEmoteMessage(
|
||||
gmg->myname,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::Red,
|
||||
fmt::format(
|
||||
"Error: Cannot identify {}'s zoneserver.",
|
||||
gmg->gotoname
|
||||
).c_str()
|
||||
);
|
||||
} else if (cle->Anon() == 1 && cle->Admin() > gmg->admin) { // no snooping for anon GMs
|
||||
SendEmoteMessage(
|
||||
gmg->myname,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::Red,
|
||||
fmt::format(
|
||||
"Error: {} not found.",
|
||||
gmg->gotoname
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
cle->Server()->SendPacket(pack);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this->SendEmoteMessage(gmg->myname, 0, 0, 13, "Error: %s not found", gmg->gotoname);
|
||||
SendEmoteMessage(
|
||||
gmg->myname,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::Red,
|
||||
fmt::format(
|
||||
"Error: {} not found",
|
||||
gmg->gotoname
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -933,16 +1007,28 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
WorldConfig::UnlockWorld();
|
||||
if (loginserverlist.Connected()) {
|
||||
loginserverlist.SendStatus();
|
||||
if (slock->mode >= 1)
|
||||
this->SendEmoteMessage(slock->myname, 0, 0, 13, "World locked");
|
||||
else
|
||||
this->SendEmoteMessage(slock->myname, 0, 0, 13, "World unlocked");
|
||||
SendEmoteMessage(
|
||||
slock->myname,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::Red,
|
||||
fmt::format(
|
||||
"World {}.",
|
||||
slock->mode ? "locked" : "unlocked"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
if (slock->mode >= 1)
|
||||
this->SendEmoteMessage(slock->myname, 0, 0, 13, "World locked, but login server not connected.");
|
||||
else
|
||||
this->SendEmoteMessage(slock->myname, 0, 0, 13, "World unlocked, but login server not conencted.");
|
||||
SendEmoteMessage(
|
||||
slock->myname,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::Red,
|
||||
fmt::format(
|
||||
"World {}, but login server not connected.",
|
||||
slock->mode ? "locked" : "unlocked"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -953,7 +1039,6 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
}
|
||||
ServerMotd_Struct* smotd = (ServerMotd_Struct*)pack->pBuffer;
|
||||
database.SetVariable("MOTD", smotd->motd);
|
||||
//this->SendEmoteMessage(smotd->myname, 0, 0, 13, "Updated Motd.");
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
@@ -1022,22 +1107,44 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
LogInfo("Wrong size on ServerOP_LockZone. Got: [{}], Expected: [{}]", pack->size, sizeof(ServerLockZone_Struct));
|
||||
break;
|
||||
}
|
||||
ServerLockZone_Struct* s = (ServerLockZone_Struct*)pack->pBuffer;
|
||||
switch (s->op) {
|
||||
case 0:
|
||||
zoneserver_list.ListLockedZones(s->adminname, this);
|
||||
|
||||
ServerLockZone_Struct* lock_zone = (ServerLockZone_Struct*) pack->pBuffer;
|
||||
if (lock_zone->op == ServerLockType::List) {
|
||||
zoneserver_list.ListLockedZones(lock_zone->adminname, this);
|
||||
break;
|
||||
case 1:
|
||||
if (zoneserver_list.SetLockedZone(s->zoneID, true))
|
||||
zoneserver_list.SendEmoteMessage(0, 0, 80, 15, "Zone locked: %s", ZoneName(s->zoneID));
|
||||
else
|
||||
this->SendEmoteMessageRaw(s->adminname, 0, 0, 0, "Failed to change lock");
|
||||
break;
|
||||
case 2:
|
||||
if (zoneserver_list.SetLockedZone(s->zoneID, false))
|
||||
zoneserver_list.SendEmoteMessage(0, 0, 80, 15, "Zone unlocked: %s", ZoneName(s->zoneID));
|
||||
else
|
||||
this->SendEmoteMessageRaw(s->adminname, 0, 0, 0, "Failed to change lock");
|
||||
} else if (
|
||||
lock_zone->op == ServerLockType::Lock ||
|
||||
lock_zone->op == ServerLockType::Unlock
|
||||
) {
|
||||
if (zoneserver_list.SetLockedZone(lock_zone->zoneID, lock_zone->op == ServerLockType::Lock)) {
|
||||
zoneserver_list.SendEmoteMessage(
|
||||
0,
|
||||
0,
|
||||
AccountStatus::QuestTroupe,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Zone {} | Name: {} ({}) ID: {}",
|
||||
lock_zone->op == ServerLockType::Lock ? "Locked" : "Unlocked",
|
||||
ZoneLongName(lock_zone->zoneID),
|
||||
ZoneName(lock_zone->zoneID),
|
||||
lock_zone->zoneID
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
SendEmoteMessageRaw(
|
||||
lock_zone->adminname,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Zone Failed to {} | Name: {} ({}) ID: {}",
|
||||
lock_zone->op == ServerLockType::Lock ? "Lock" : "Unlock",
|
||||
ZoneLongName(lock_zone->zoneID),
|
||||
ZoneName(lock_zone->zoneID),
|
||||
lock_zone->zoneID
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -1382,7 +1489,13 @@ void ZoneServer::SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_
|
||||
va_start(argptr, message);
|
||||
vsnprintf(buffer, sizeof(buffer), message, argptr);
|
||||
va_end(argptr);
|
||||
SendEmoteMessageRaw(to, to_guilddbid, to_minstatus, type, buffer);
|
||||
SendEmoteMessageRaw(
|
||||
to,
|
||||
to_guilddbid,
|
||||
to_minstatus,
|
||||
type,
|
||||
buffer
|
||||
);
|
||||
}
|
||||
|
||||
void ZoneServer::SendEmoteMessageRaw(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message) {
|
||||
|
||||
+1
-1
@@ -22,6 +22,7 @@
|
||||
#include "../common/net/servertalk_server.h"
|
||||
#include "../common/event/timer.h"
|
||||
#include "../common/timer.h"
|
||||
#include "../common/emu_constants.h"
|
||||
#include "console.h"
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
@@ -29,7 +30,6 @@
|
||||
class Client;
|
||||
class ServerPacket;
|
||||
|
||||
|
||||
class ZoneServer : public WorldTCPConnection {
|
||||
public:
|
||||
ZoneServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection, EQ::Net::ConsoleServer *console);
|
||||
|
||||
+576
-283
@@ -1,293 +1,586 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
|
||||
|
||||
SET(zone_sources
|
||||
aa.cpp
|
||||
aa_ability.cpp
|
||||
aggro.cpp
|
||||
aggromanager.cpp
|
||||
api_service.cpp
|
||||
attack.cpp
|
||||
aura.cpp
|
||||
beacon.cpp
|
||||
bonuses.cpp
|
||||
bot.cpp
|
||||
bot_command.cpp
|
||||
bot_database.cpp
|
||||
botspellsai.cpp
|
||||
cheat_manager.cpp
|
||||
client.cpp
|
||||
client_mods.cpp
|
||||
client_packet.cpp
|
||||
client_process.cpp
|
||||
command.cpp
|
||||
corpse.cpp
|
||||
data_bucket.cpp
|
||||
doors.cpp
|
||||
dialogue_window.cpp
|
||||
dynamic_zone.cpp
|
||||
effects.cpp
|
||||
embparser.cpp
|
||||
embparser_api.cpp
|
||||
embperl.cpp
|
||||
embxs.cpp
|
||||
encounter.cpp
|
||||
entity.cpp
|
||||
exp.cpp
|
||||
expedition.cpp
|
||||
expedition_database.cpp
|
||||
expedition_request.cpp
|
||||
fastmath.cpp
|
||||
fearpath.cpp
|
||||
forage.cpp
|
||||
groups.cpp
|
||||
guild.cpp
|
||||
guild_mgr.cpp
|
||||
hate_list.cpp
|
||||
heal_rotation.cpp
|
||||
horse.cpp
|
||||
inventory.cpp
|
||||
loottables.cpp
|
||||
lua_bot.cpp
|
||||
lua_bit.cpp
|
||||
lua_corpse.cpp
|
||||
lua_client.cpp
|
||||
lua_door.cpp
|
||||
lua_encounter.cpp
|
||||
lua_entity.cpp
|
||||
lua_entity_list.cpp
|
||||
lua_expedition.cpp
|
||||
lua_general.cpp
|
||||
lua_group.cpp
|
||||
lua_hate_list.cpp
|
||||
lua_inventory.cpp
|
||||
lua_item.cpp
|
||||
lua_iteminst.cpp
|
||||
lua_mob.cpp
|
||||
lua_mod.cpp
|
||||
lua_npc.cpp
|
||||
lua_object.cpp
|
||||
lua_packet.cpp
|
||||
lua_parser.cpp
|
||||
lua_parser_events.cpp
|
||||
lua_raid.cpp
|
||||
lua_spawn.cpp
|
||||
lua_spell.cpp
|
||||
lua_stat_bonuses.cpp
|
||||
embperl.cpp
|
||||
embxs.cpp
|
||||
entity.cpp
|
||||
exp.cpp
|
||||
fearpath.cpp
|
||||
forage.cpp
|
||||
global_loot_manager.cpp
|
||||
gm_commands/door_manipulation.cpp
|
||||
groups.cpp
|
||||
guild.cpp
|
||||
guild_mgr.cpp
|
||||
hate_list.cpp
|
||||
horse.cpp
|
||||
inventory.cpp
|
||||
loottables.cpp
|
||||
main.cpp
|
||||
map.cpp
|
||||
merc.cpp
|
||||
mob.cpp
|
||||
mob_ai.cpp
|
||||
mob_appearance.cpp
|
||||
mob_movement_manager.cpp
|
||||
mob_info.cpp
|
||||
mod_functions.cpp
|
||||
npc.cpp
|
||||
npc_ai.cpp
|
||||
npc_scale_manager.cpp
|
||||
object.cpp
|
||||
oriented_bounding_box.cpp
|
||||
pathfinder_interface.cpp
|
||||
pathfinder_nav_mesh.cpp
|
||||
pathfinder_null.cpp
|
||||
pathing.cpp
|
||||
perl_bot.cpp
|
||||
perl_client.cpp
|
||||
perl_doors.cpp
|
||||
perl_entity.cpp
|
||||
perl_expedition.cpp
|
||||
perl_groups.cpp
|
||||
perl_hateentry.cpp
|
||||
perl_inventory.cpp
|
||||
perl_mob.cpp
|
||||
perl_npc.cpp
|
||||
perl_object.cpp
|
||||
perl_perlpacket.cpp
|
||||
perl_player_corpse.cpp
|
||||
perl_questitem.cpp
|
||||
perl_raids.cpp
|
||||
perl_spell.cpp
|
||||
perlpacket.cpp
|
||||
petitions.cpp
|
||||
pets.cpp
|
||||
position.cpp
|
||||
qglobals.cpp
|
||||
queryserv.cpp
|
||||
questmgr.cpp
|
||||
quest_parser_collection.cpp
|
||||
raids.cpp
|
||||
raycast_mesh.cpp
|
||||
shared_task_zone_messaging.cpp
|
||||
spawn2.cpp
|
||||
spawn2.h
|
||||
spawngroup.cpp
|
||||
special_attacks.cpp
|
||||
spell_effects.cpp
|
||||
spells.cpp
|
||||
task_client_state.cpp
|
||||
task_goal_list_manager.cpp
|
||||
task_manager.cpp
|
||||
task_proximity_manager.cpp
|
||||
tasks.cpp
|
||||
titles.cpp
|
||||
tradeskills.cpp
|
||||
trading.cpp
|
||||
trap.cpp
|
||||
tribute.cpp
|
||||
tune.cpp
|
||||
water_map.cpp
|
||||
water_map_v1.cpp
|
||||
water_map_v2.cpp
|
||||
waypoints.cpp
|
||||
worldserver.cpp
|
||||
xtargetautohaters.cpp
|
||||
zone.cpp
|
||||
zone_config.cpp
|
||||
zonedb.cpp
|
||||
zone_event_scheduler.cpp
|
||||
zone_reload.cpp
|
||||
zone_store.cpp
|
||||
zoning.cpp
|
||||
)
|
||||
aa.cpp
|
||||
aa_ability.cpp
|
||||
aggro.cpp
|
||||
aggromanager.cpp
|
||||
api_service.cpp
|
||||
attack.cpp
|
||||
aura.cpp
|
||||
beacon.cpp
|
||||
bonuses.cpp
|
||||
bot.cpp
|
||||
bot_command.cpp
|
||||
bot_database.cpp
|
||||
botspellsai.cpp
|
||||
cheat_manager.cpp
|
||||
client.cpp
|
||||
client_mods.cpp
|
||||
client_packet.cpp
|
||||
client_process.cpp
|
||||
command.cpp
|
||||
corpse.cpp
|
||||
data_bucket.cpp
|
||||
doors.cpp
|
||||
dialogue_window.cpp
|
||||
dynamic_zone.cpp
|
||||
effects.cpp
|
||||
embparser.cpp
|
||||
embparser_api.cpp
|
||||
embperl.cpp
|
||||
embxs.cpp
|
||||
encounter.cpp
|
||||
entity.cpp
|
||||
exp.cpp
|
||||
expedition.cpp
|
||||
expedition_database.cpp
|
||||
expedition_request.cpp
|
||||
fastmath.cpp
|
||||
fearpath.cpp
|
||||
forage.cpp
|
||||
groups.cpp
|
||||
guild.cpp
|
||||
guild_mgr.cpp
|
||||
hate_list.cpp
|
||||
heal_rotation.cpp
|
||||
horse.cpp
|
||||
inventory.cpp
|
||||
loottables.cpp
|
||||
lua_bot.cpp
|
||||
lua_bit.cpp
|
||||
lua_corpse.cpp
|
||||
lua_client.cpp
|
||||
lua_door.cpp
|
||||
lua_encounter.cpp
|
||||
lua_entity.cpp
|
||||
lua_entity_list.cpp
|
||||
lua_expedition.cpp
|
||||
lua_general.cpp
|
||||
lua_group.cpp
|
||||
lua_hate_list.cpp
|
||||
lua_inventory.cpp
|
||||
lua_item.cpp
|
||||
lua_iteminst.cpp
|
||||
lua_mob.cpp
|
||||
lua_mod.cpp
|
||||
lua_npc.cpp
|
||||
lua_object.cpp
|
||||
lua_packet.cpp
|
||||
lua_parser.cpp
|
||||
lua_parser_events.cpp
|
||||
lua_raid.cpp
|
||||
lua_spawn.cpp
|
||||
lua_spell.cpp
|
||||
lua_stat_bonuses.cpp
|
||||
embperl.cpp
|
||||
embxs.cpp
|
||||
entity.cpp
|
||||
exp.cpp
|
||||
fearpath.cpp
|
||||
forage.cpp
|
||||
global_loot_manager.cpp
|
||||
gm_commands/door_manipulation.cpp
|
||||
groups.cpp
|
||||
guild.cpp
|
||||
guild_mgr.cpp
|
||||
hate_list.cpp
|
||||
horse.cpp
|
||||
inventory.cpp
|
||||
loottables.cpp
|
||||
main.cpp
|
||||
map.cpp
|
||||
merc.cpp
|
||||
mob.cpp
|
||||
mob_ai.cpp
|
||||
mob_appearance.cpp
|
||||
mob_movement_manager.cpp
|
||||
mob_info.cpp
|
||||
mod_functions.cpp
|
||||
npc.cpp
|
||||
npc_ai.cpp
|
||||
npc_scale_manager.cpp
|
||||
object.cpp
|
||||
oriented_bounding_box.cpp
|
||||
pathfinder_interface.cpp
|
||||
pathfinder_nav_mesh.cpp
|
||||
pathfinder_null.cpp
|
||||
pathing.cpp
|
||||
perl_bot.cpp
|
||||
perl_client.cpp
|
||||
perl_doors.cpp
|
||||
perl_entity.cpp
|
||||
perl_expedition.cpp
|
||||
perl_groups.cpp
|
||||
perl_hateentry.cpp
|
||||
perl_inventory.cpp
|
||||
perl_mob.cpp
|
||||
perl_npc.cpp
|
||||
perl_object.cpp
|
||||
perl_perlpacket.cpp
|
||||
perl_player_corpse.cpp
|
||||
perl_questitem.cpp
|
||||
perl_raids.cpp
|
||||
perl_spell.cpp
|
||||
perlpacket.cpp
|
||||
petitions.cpp
|
||||
pets.cpp
|
||||
position.cpp
|
||||
qglobals.cpp
|
||||
queryserv.cpp
|
||||
questmgr.cpp
|
||||
quest_parser_collection.cpp
|
||||
raids.cpp
|
||||
raycast_mesh.cpp
|
||||
shared_task_zone_messaging.cpp
|
||||
spawn2.cpp
|
||||
spawn2.h
|
||||
spawngroup.cpp
|
||||
special_attacks.cpp
|
||||
spell_effects.cpp
|
||||
spells.cpp
|
||||
task_client_state.cpp
|
||||
task_goal_list_manager.cpp
|
||||
task_manager.cpp
|
||||
task_proximity_manager.cpp
|
||||
tasks.cpp
|
||||
titles.cpp
|
||||
tradeskills.cpp
|
||||
trading.cpp
|
||||
trap.cpp
|
||||
tribute.cpp
|
||||
tune.cpp
|
||||
water_map.cpp
|
||||
water_map_v1.cpp
|
||||
water_map_v2.cpp
|
||||
waypoints.cpp
|
||||
worldserver.cpp
|
||||
xtargetautohaters.cpp
|
||||
zone.cpp
|
||||
zone_config.cpp
|
||||
zonedb.cpp
|
||||
zone_event_scheduler.cpp
|
||||
zone_reload.cpp
|
||||
zone_store.cpp
|
||||
zoning.cpp
|
||||
)
|
||||
|
||||
SET(zone_headers
|
||||
aa.h
|
||||
aa_ability.h
|
||||
aggromanager.h
|
||||
api_service.h
|
||||
aura.h
|
||||
basic_functions.h
|
||||
beacon.h
|
||||
bot.h
|
||||
bot_command.h
|
||||
bot_database.h
|
||||
bot_structs.h
|
||||
cheat_manager.h
|
||||
client.h
|
||||
client_packet.h
|
||||
command.h
|
||||
common.h
|
||||
corpse.h
|
||||
data_bucket.h
|
||||
doors.h
|
||||
dialogue_window.h
|
||||
dynamic_zone.h
|
||||
embparser.h
|
||||
embperl.h
|
||||
embxs.h
|
||||
encounter.h
|
||||
entity.h
|
||||
errmsg.h
|
||||
event_codes.h
|
||||
expedition.h
|
||||
expedition_database.h
|
||||
expedition_request.h
|
||||
fastmath.h
|
||||
forage.h
|
||||
global_loot_manager.h
|
||||
gm_commands/door_manipulation.h
|
||||
groups.h
|
||||
guild_mgr.h
|
||||
hate_list.h
|
||||
heal_rotation.h
|
||||
horse.h
|
||||
lua_bot.h
|
||||
lua_bit.h
|
||||
lua_client.h
|
||||
lua_corpse.h
|
||||
lua_door.h
|
||||
lua_encounter.h
|
||||
lua_entity.h
|
||||
lua_entity_list.h
|
||||
lua_expedition.h
|
||||
lua_general.h
|
||||
lua_group.h
|
||||
lua_hate_list.h
|
||||
lua_inventory.h
|
||||
lua_item.h
|
||||
lua_iteminst.h
|
||||
lua_mob.h
|
||||
lua_mod.h
|
||||
lua_npc.h
|
||||
lua_object.h
|
||||
lua_packet.h
|
||||
lua_parser.h
|
||||
lua_parser_events.h
|
||||
lua_ptr.h
|
||||
lua_raid.h
|
||||
lua_spawn.h
|
||||
lua_spell.h
|
||||
lua_stat_bonuses.h
|
||||
map.h
|
||||
masterentity.h
|
||||
maxskill.h
|
||||
message.h
|
||||
merc.h
|
||||
mob.h
|
||||
mob_movement_manager.h
|
||||
npc.h
|
||||
npc_ai.h
|
||||
npc_scale_manager.h
|
||||
object.h
|
||||
oriented_bounding_box.h
|
||||
pathfinder_interface.h
|
||||
pathfinder_nav_mesh.h
|
||||
pathfinder_null.h
|
||||
perlpacket.h
|
||||
petitions.h
|
||||
pets.h
|
||||
position.h
|
||||
qglobals.h
|
||||
quest_interface.h
|
||||
queryserv.h
|
||||
quest_interface.h
|
||||
questmgr.h
|
||||
quest_parser_collection.h
|
||||
raids.h
|
||||
raycast_mesh.h
|
||||
skills.h
|
||||
shared_task_zone_messaging.h
|
||||
spawn2.cpp
|
||||
spawn2.h
|
||||
spawngroup.h
|
||||
string_ids.h
|
||||
task_client_state.h
|
||||
task_goal_list_manager.h
|
||||
task_manager.h
|
||||
task_proximity_manager.h
|
||||
tasks.h
|
||||
titles.h
|
||||
trap.h
|
||||
water_map.h
|
||||
water_map_v1.h
|
||||
water_map_v2.h
|
||||
worldserver.h
|
||||
xtargetautohaters.h
|
||||
zone.h
|
||||
zone_event_scheduler.h
|
||||
zone_config.h
|
||||
zonedb.h
|
||||
zonedump.h
|
||||
zone_reload.h
|
||||
zone_store.h
|
||||
aa.h
|
||||
aa_ability.h
|
||||
aggromanager.h
|
||||
api_service.h
|
||||
aura.h
|
||||
basic_functions.h
|
||||
beacon.h
|
||||
bot.h
|
||||
bot_command.h
|
||||
bot_database.h
|
||||
bot_structs.h
|
||||
cheat_manager.h
|
||||
client.h
|
||||
client_packet.h
|
||||
command.h
|
||||
common.h
|
||||
corpse.h
|
||||
data_bucket.h
|
||||
doors.h
|
||||
dialogue_window.h
|
||||
dynamic_zone.h
|
||||
embparser.h
|
||||
embperl.h
|
||||
embxs.h
|
||||
encounter.h
|
||||
entity.h
|
||||
errmsg.h
|
||||
event_codes.h
|
||||
expedition.h
|
||||
expedition_database.h
|
||||
expedition_request.h
|
||||
fastmath.h
|
||||
forage.h
|
||||
global_loot_manager.h
|
||||
gm_commands/door_manipulation.h
|
||||
groups.h
|
||||
guild_mgr.h
|
||||
hate_list.h
|
||||
heal_rotation.h
|
||||
horse.h
|
||||
lua_bot.h
|
||||
lua_bit.h
|
||||
lua_client.h
|
||||
lua_corpse.h
|
||||
lua_door.h
|
||||
lua_encounter.h
|
||||
lua_entity.h
|
||||
lua_entity_list.h
|
||||
lua_expedition.h
|
||||
lua_general.h
|
||||
lua_group.h
|
||||
lua_hate_list.h
|
||||
lua_inventory.h
|
||||
lua_item.h
|
||||
lua_iteminst.h
|
||||
lua_mob.h
|
||||
lua_mod.h
|
||||
lua_npc.h
|
||||
lua_object.h
|
||||
lua_packet.h
|
||||
lua_parser.h
|
||||
lua_parser_events.h
|
||||
lua_ptr.h
|
||||
lua_raid.h
|
||||
lua_spawn.h
|
||||
lua_spell.h
|
||||
lua_stat_bonuses.h
|
||||
map.h
|
||||
masterentity.h
|
||||
maxskill.h
|
||||
message.h
|
||||
merc.h
|
||||
mob.h
|
||||
mob_movement_manager.h
|
||||
npc.h
|
||||
npc_ai.h
|
||||
npc_scale_manager.h
|
||||
object.h
|
||||
oriented_bounding_box.h
|
||||
pathfinder_interface.h
|
||||
pathfinder_nav_mesh.h
|
||||
pathfinder_null.h
|
||||
perlpacket.h
|
||||
petitions.h
|
||||
pets.h
|
||||
position.h
|
||||
qglobals.h
|
||||
quest_interface.h
|
||||
queryserv.h
|
||||
quest_interface.h
|
||||
questmgr.h
|
||||
quest_parser_collection.h
|
||||
raids.h
|
||||
raycast_mesh.h
|
||||
skills.h
|
||||
shared_task_zone_messaging.h
|
||||
spawn2.cpp
|
||||
spawn2.h
|
||||
spawngroup.h
|
||||
string_ids.h
|
||||
task_client_state.h
|
||||
task_goal_list_manager.h
|
||||
task_manager.h
|
||||
task_proximity_manager.h
|
||||
tasks.h
|
||||
titles.h
|
||||
trap.h
|
||||
water_map.h
|
||||
water_map_v1.h
|
||||
water_map_v2.h
|
||||
worldserver.h
|
||||
xtargetautohaters.h
|
||||
zone.h
|
||||
zone_event_scheduler.h
|
||||
zone_config.h
|
||||
zonedb.h
|
||||
zonedump.h
|
||||
zone_reload.h
|
||||
zone_store.h
|
||||
)
|
||||
|
||||
SET(gm_commands
|
||||
gm_commands/acceptrules.cpp
|
||||
gm_commands/advnpcspawn.cpp
|
||||
gm_commands/aggro.cpp
|
||||
gm_commands/aggrozone.cpp
|
||||
gm_commands/ai.cpp
|
||||
gm_commands/appearance.cpp
|
||||
gm_commands/appearanceeffects.cpp
|
||||
gm_commands/attack.cpp
|
||||
gm_commands/augmentitem.cpp
|
||||
gm_commands/ban.cpp
|
||||
gm_commands/beard.cpp
|
||||
gm_commands/beardcolor.cpp
|
||||
gm_commands/bestz.cpp
|
||||
gm_commands/bind.cpp
|
||||
gm_commands/camerashake.cpp
|
||||
gm_commands/castspell.cpp
|
||||
gm_commands/chat.cpp
|
||||
gm_commands/checklos.cpp
|
||||
gm_commands/copycharacter.cpp
|
||||
gm_commands/corpse.cpp
|
||||
gm_commands/corpsefix.cpp
|
||||
gm_commands/countitem.cpp
|
||||
gm_commands/cvs.cpp
|
||||
gm_commands/damage.cpp
|
||||
gm_commands/databuckets.cpp
|
||||
gm_commands/date.cpp
|
||||
gm_commands/dbspawn2.cpp
|
||||
gm_commands/delacct.cpp
|
||||
gm_commands/deletegraveyard.cpp
|
||||
gm_commands/delpetition.cpp
|
||||
gm_commands/depop.cpp
|
||||
gm_commands/depopzone.cpp
|
||||
gm_commands/details.cpp
|
||||
gm_commands/devtools.cpp
|
||||
gm_commands/disablerecipe.cpp
|
||||
gm_commands/disarmtrap.cpp
|
||||
gm_commands/distance.cpp
|
||||
gm_commands/doanim.cpp
|
||||
gm_commands/door.cpp
|
||||
gm_commands/dye.cpp
|
||||
gm_commands/dz.cpp
|
||||
gm_commands/dzkickplayers.cpp
|
||||
gm_commands/editmassrespawn.cpp
|
||||
gm_commands/emote.cpp
|
||||
gm_commands/emotesearch.cpp
|
||||
gm_commands/emoteview.cpp
|
||||
gm_commands/enablerecipe.cpp
|
||||
gm_commands/endurance.cpp
|
||||
gm_commands/equipitem.cpp
|
||||
gm_commands/face.cpp
|
||||
gm_commands/faction.cpp
|
||||
gm_commands/findclass.cpp
|
||||
gm_commands/findfaction.cpp
|
||||
gm_commands/findnpctype.cpp
|
||||
gm_commands/findrace.cpp
|
||||
gm_commands/findskill.cpp
|
||||
gm_commands/findspell.cpp
|
||||
gm_commands/findtask.cpp
|
||||
gm_commands/findzone.cpp
|
||||
gm_commands/fixmob.cpp
|
||||
gm_commands/flag.cpp
|
||||
gm_commands/flagedit.cpp
|
||||
gm_commands/flags.cpp
|
||||
gm_commands/flymode.cpp
|
||||
gm_commands/fov.cpp
|
||||
gm_commands/freeze.cpp
|
||||
gm_commands/gassign.cpp
|
||||
gm_commands/gearup.cpp
|
||||
gm_commands/gender.cpp
|
||||
gm_commands/getplayerburiedcorpsecount.cpp
|
||||
gm_commands/getvariable.cpp
|
||||
gm_commands/ginfo.cpp
|
||||
gm_commands/giveitem.cpp
|
||||
gm_commands/givemoney.cpp
|
||||
gm_commands/globalview.cpp
|
||||
gm_commands/gm.cpp
|
||||
gm_commands/gmspeed.cpp
|
||||
gm_commands/gmzone.cpp
|
||||
gm_commands/goto.cpp
|
||||
gm_commands/grid.cpp
|
||||
gm_commands/guild.cpp
|
||||
gm_commands/guildapprove.cpp
|
||||
gm_commands/guildcreate.cpp
|
||||
gm_commands/guildlist.cpp
|
||||
gm_commands/hair.cpp
|
||||
gm_commands/haircolor.cpp
|
||||
gm_commands/haste.cpp
|
||||
gm_commands/hatelist.cpp
|
||||
gm_commands/heal.cpp
|
||||
gm_commands/helm.cpp
|
||||
gm_commands/heritage.cpp
|
||||
gm_commands/heromodel.cpp
|
||||
gm_commands/hideme.cpp
|
||||
gm_commands/hp.cpp
|
||||
gm_commands/incstat.cpp
|
||||
gm_commands/instance.cpp
|
||||
gm_commands/interrogateinv.cpp
|
||||
gm_commands/interrupt.cpp
|
||||
gm_commands/invsnapshot.cpp
|
||||
gm_commands/invul.cpp
|
||||
gm_commands/ipban.cpp
|
||||
gm_commands/iplookup.cpp
|
||||
gm_commands/iteminfo.cpp
|
||||
gm_commands/itemsearch.cpp
|
||||
gm_commands/kick.cpp
|
||||
gm_commands/kill.cpp
|
||||
gm_commands/killallnpcs.cpp
|
||||
gm_commands/lastname.cpp
|
||||
gm_commands/list.cpp
|
||||
gm_commands/listpetition.cpp
|
||||
gm_commands/loc.cpp
|
||||
gm_commands/lock.cpp
|
||||
gm_commands/logcommand.cpp
|
||||
gm_commands/logs.cpp
|
||||
gm_commands/makepet.cpp
|
||||
gm_commands/mana.cpp
|
||||
gm_commands/max_all_skills.cpp
|
||||
gm_commands/memspell.cpp
|
||||
gm_commands/merchantcloseshop.cpp
|
||||
gm_commands/merchantopenshop.cpp
|
||||
gm_commands/modifynpcstat.cpp
|
||||
gm_commands/motd.cpp
|
||||
gm_commands/movechar.cpp
|
||||
gm_commands/movement.cpp
|
||||
gm_commands/myskills.cpp
|
||||
gm_commands/mysql.cpp
|
||||
gm_commands/mystats.cpp
|
||||
gm_commands/name.cpp
|
||||
gm_commands/netstats.cpp
|
||||
gm_commands/network.cpp
|
||||
gm_commands/npccast.cpp
|
||||
gm_commands/npcedit.cpp
|
||||
gm_commands/npceditmass.cpp
|
||||
gm_commands/npcemote.cpp
|
||||
gm_commands/npcloot.cpp
|
||||
gm_commands/npcsay.cpp
|
||||
gm_commands/npcshout.cpp
|
||||
gm_commands/npcspawn.cpp
|
||||
gm_commands/npcspecialattk.cpp
|
||||
gm_commands/npcstats.cpp
|
||||
gm_commands/npctype_cache.cpp
|
||||
gm_commands/npctypespawn.cpp
|
||||
gm_commands/nudge.cpp
|
||||
gm_commands/nukebuffs.cpp
|
||||
gm_commands/nukeitem.cpp
|
||||
gm_commands/object.cpp
|
||||
gm_commands/oocmute.cpp
|
||||
gm_commands/opcode.cpp
|
||||
gm_commands/path.cpp
|
||||
gm_commands/peekinv.cpp
|
||||
gm_commands/peqzone.cpp
|
||||
gm_commands/permaclass.cpp
|
||||
gm_commands/permagender.cpp
|
||||
gm_commands/permarace.cpp
|
||||
gm_commands/petitems.cpp
|
||||
gm_commands/petitioninfo.cpp
|
||||
gm_commands/petname.cpp
|
||||
gm_commands/pf.cpp
|
||||
gm_commands/picklock.cpp
|
||||
gm_commands/profanity.cpp
|
||||
gm_commands/proximity.cpp
|
||||
gm_commands/push.cpp
|
||||
gm_commands/pvp.cpp
|
||||
gm_commands/qglobal.cpp
|
||||
gm_commands/questerrors.cpp
|
||||
gm_commands/race.cpp
|
||||
gm_commands/raidloot.cpp
|
||||
gm_commands/randomfeatures.cpp
|
||||
gm_commands/refreshgroup.cpp
|
||||
gm_commands/reloadaa.cpp
|
||||
gm_commands/reloadallrules.cpp
|
||||
gm_commands/reloadcontentflags.cpp
|
||||
gm_commands/reloademote.cpp
|
||||
gm_commands/reloadlevelmods.cpp
|
||||
gm_commands/reloadmerchants.cpp
|
||||
gm_commands/reloadperlexportsettings.cpp
|
||||
gm_commands/reloadqst.cpp
|
||||
gm_commands/reloadstatic.cpp
|
||||
gm_commands/reloadtitles.cpp
|
||||
gm_commands/reloadtraps.cpp
|
||||
gm_commands/reloadworld.cpp
|
||||
gm_commands/reloadworldrules.cpp
|
||||
gm_commands/reloadzps.cpp
|
||||
gm_commands/removeitem.cpp
|
||||
gm_commands/repop.cpp
|
||||
gm_commands/resetaa.cpp
|
||||
gm_commands/resetaa_timer.cpp
|
||||
gm_commands/resetdisc_timer.cpp
|
||||
gm_commands/revoke.cpp
|
||||
gm_commands/roambox.cpp
|
||||
gm_commands/rules.cpp
|
||||
gm_commands/save.cpp
|
||||
gm_commands/scale.cpp
|
||||
gm_commands/scribespell.cpp
|
||||
gm_commands/scribespells.cpp
|
||||
gm_commands/sendzonespawns.cpp
|
||||
gm_commands/sensetrap.cpp
|
||||
gm_commands/serverinfo.cpp
|
||||
gm_commands/serverrules.cpp
|
||||
gm_commands/set_adventure_points.cpp
|
||||
gm_commands/setaapts.cpp
|
||||
gm_commands/setaaxp.cpp
|
||||
gm_commands/setaltcurrency.cpp
|
||||
gm_commands/setanim.cpp
|
||||
gm_commands/setcrystals.cpp
|
||||
gm_commands/setendurance.cpp
|
||||
gm_commands/setfaction.cpp
|
||||
gm_commands/setgraveyard.cpp
|
||||
gm_commands/sethp.cpp
|
||||
gm_commands/setlanguage.cpp
|
||||
gm_commands/setlsinfo.cpp
|
||||
gm_commands/setmana.cpp
|
||||
gm_commands/setpass.cpp
|
||||
gm_commands/setpvppoints.cpp
|
||||
gm_commands/setskill.cpp
|
||||
gm_commands/setskillall.cpp
|
||||
gm_commands/setstartzone.cpp
|
||||
gm_commands/setstat.cpp
|
||||
gm_commands/setxp.cpp
|
||||
gm_commands/showbonusstats.cpp
|
||||
gm_commands/showbuffs.cpp
|
||||
gm_commands/shownpcgloballoot.cpp
|
||||
gm_commands/shownumhits.cpp
|
||||
gm_commands/showskills.cpp
|
||||
gm_commands/showspellslist.cpp
|
||||
gm_commands/showstats.cpp
|
||||
gm_commands/showzonegloballoot.cpp
|
||||
gm_commands/showzonepoints.cpp
|
||||
gm_commands/shutdown.cpp
|
||||
gm_commands/size.cpp
|
||||
gm_commands/spawn.cpp
|
||||
gm_commands/spawnfix.cpp
|
||||
gm_commands/spawnstatus.cpp
|
||||
gm_commands/spellinfo.cpp
|
||||
gm_commands/stun.cpp
|
||||
gm_commands/summon.cpp
|
||||
gm_commands/summonburiedplayercorpse.cpp
|
||||
gm_commands/summonitem.cpp
|
||||
gm_commands/suspend.cpp
|
||||
gm_commands/task.cpp
|
||||
gm_commands/tattoo.cpp
|
||||
gm_commands/tempname.cpp
|
||||
gm_commands/texture.cpp
|
||||
gm_commands/time.cpp
|
||||
gm_commands/timers.cpp
|
||||
gm_commands/timezone.cpp
|
||||
gm_commands/title.cpp
|
||||
gm_commands/titlesuffix.cpp
|
||||
gm_commands/traindisc.cpp
|
||||
gm_commands/trapinfo.cpp
|
||||
gm_commands/tune.cpp
|
||||
gm_commands/ucs.cpp
|
||||
gm_commands/undye.cpp
|
||||
gm_commands/undyeme.cpp
|
||||
gm_commands/unfreeze.cpp
|
||||
gm_commands/unlock.cpp
|
||||
gm_commands/unmemspell.cpp
|
||||
gm_commands/unmemspells.cpp
|
||||
gm_commands/unscribespell.cpp
|
||||
gm_commands/unscribespells.cpp
|
||||
gm_commands/untraindisc.cpp
|
||||
gm_commands/untraindiscs.cpp
|
||||
gm_commands/uptime.cpp
|
||||
gm_commands/version.cpp
|
||||
gm_commands/viewcurrencies.cpp
|
||||
gm_commands/viewnpctype.cpp
|
||||
gm_commands/viewpetition.cpp
|
||||
gm_commands/viewzoneloot.cpp
|
||||
gm_commands/wc.cpp
|
||||
gm_commands/weather.cpp
|
||||
gm_commands/who.cpp
|
||||
gm_commands/worldshutdown.cpp
|
||||
gm_commands/worldwide.cpp
|
||||
gm_commands/wp.cpp
|
||||
gm_commands/wpadd.cpp
|
||||
gm_commands/wpinfo.cpp
|
||||
gm_commands/xtargets.cpp
|
||||
gm_commands/zclip.cpp
|
||||
gm_commands/zcolor.cpp
|
||||
gm_commands/zheader.cpp
|
||||
gm_commands/zonebootup.cpp
|
||||
gm_commands/zonelock.cpp
|
||||
gm_commands/zoneshutdown.cpp
|
||||
gm_commands/zonestatus.cpp
|
||||
gm_commands/zopp.cpp
|
||||
gm_commands/zsafecoords.cpp
|
||||
gm_commands/zsave.cpp
|
||||
gm_commands/zsky.cpp
|
||||
gm_commands/zstats.cpp
|
||||
gm_commands/zunderworld.cpp
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(zone ${zone_sources} ${zone_headers})
|
||||
ADD_EXECUTABLE(zone ${zone_sources} ${zone_headers} ${gm_commands})
|
||||
|
||||
INSTALL(TARGETS zone RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
|
||||
|
||||
+256
-168
@@ -151,10 +151,14 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
|
||||
//give the pets somebody to "love"
|
||||
if (targ != nullptr) {
|
||||
swarm_pet_npc->AddToHateList(targ, 1000, 1000);
|
||||
if (RuleB(Spells, SwarmPetTargetLock) || sticktarg)
|
||||
if (RuleB(Spells, SwarmPetTargetLock) || sticktarg) {
|
||||
swarm_pet_npc->GetSwarmInfo()->target = targ->GetID();
|
||||
else
|
||||
swarm_pet_npc->SetPetTargetLockID(targ->GetID());
|
||||
swarm_pet_npc->SetSpecialAbility(IMMUNE_AGGRO, 1);
|
||||
}
|
||||
else {
|
||||
swarm_pet_npc->GetSwarmInfo()->target = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//we allocated a new NPC type object, give the NPC ownership of that memory
|
||||
@@ -213,7 +217,7 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid
|
||||
glm::vec2(5, 5), glm::vec2(-5, 5), glm::vec2(5, -5), glm::vec2(-5, -5),
|
||||
glm::vec2(10, 10), glm::vec2(-10, 10), glm::vec2(10, -10), glm::vec2(-10, -10),
|
||||
glm::vec2(8, 8), glm::vec2(-8, 8), glm::vec2(8, -8), glm::vec2(-8, -8)
|
||||
};;
|
||||
};
|
||||
|
||||
while(summon_count > 0) {
|
||||
int pet_duration = pet.duration;
|
||||
@@ -255,10 +259,14 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid
|
||||
if(targ != nullptr){
|
||||
swarm_pet_npc->AddToHateList(targ, 1000, 1000);
|
||||
|
||||
if (RuleB(Spells, SwarmPetTargetLock) || sticktarg)
|
||||
if (RuleB(Spells, SwarmPetTargetLock) || sticktarg) {
|
||||
swarm_pet_npc->GetSwarmInfo()->target = targ->GetID();
|
||||
else
|
||||
swarm_pet_npc->SetPetTargetLockID(targ->GetID());
|
||||
swarm_pet_npc->SetSpecialAbility(IMMUNE_AGGRO, 1);
|
||||
}
|
||||
else {
|
||||
swarm_pet_npc->GetSwarmInfo()->target = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//we allocated a new NPC type object, give the NPC ownership of that memory
|
||||
@@ -273,63 +281,94 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid
|
||||
delete made_npc;
|
||||
}
|
||||
|
||||
void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration)
|
||||
{
|
||||
Corpse *CorpseToUse = nullptr;
|
||||
CorpseToUse = entity_list.GetClosestCorpse(this, nullptr);
|
||||
void Mob::WakeTheDead(uint16 spell_id, Corpse *corpse_to_use, Mob *target, uint32 duration) {
|
||||
|
||||
if(!CorpseToUse)
|
||||
/*
|
||||
SPA 299 Wake The Dead, 'animateDead' should be temp pet, always spawns 1 pet from corpse, max value is duration
|
||||
SPA 306 Wake The Dead, 'animateDead#' should be temp pet, base is amount of pets from indivual corpses, max value is duration
|
||||
Max range for closet corpse is 250 units.
|
||||
TODO: Should use temp pets
|
||||
*/
|
||||
|
||||
if (!corpse_to_use) {
|
||||
return;
|
||||
}
|
||||
|
||||
//assuming we have pets in our table; we take the first pet as a base type.
|
||||
const NPCType *base_type = content_db.LoadNPCTypesData(500);
|
||||
auto make_npc = new NPCType;
|
||||
memcpy(make_npc, base_type, sizeof(NPCType));
|
||||
/* TODO: Does WTD use pet focus?
|
||||
int act_power = 0;
|
||||
|
||||
//combat stats
|
||||
make_npc->AC = ((GetLevel() * 7) + 550);
|
||||
make_npc->ATK = GetLevel();
|
||||
make_npc->max_dmg = (GetLevel() * 4) + 2;
|
||||
make_npc->min_dmg = 1;
|
||||
if (IsClient()) {
|
||||
act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id);
|
||||
act_power = CastToClient()->mod_pet_power(act_power, spell_id);
|
||||
}
|
||||
*/
|
||||
|
||||
//base stats
|
||||
make_npc->current_hp = (GetLevel() * 55);
|
||||
make_npc->max_hp = (GetLevel() * 55);
|
||||
make_npc->STR = 85 + (GetLevel() * 3);
|
||||
make_npc->STA = 85 + (GetLevel() * 3);
|
||||
make_npc->DEX = 85 + (GetLevel() * 3);
|
||||
make_npc->AGI = 85 + (GetLevel() * 3);
|
||||
make_npc->INT = 85 + (GetLevel() * 3);
|
||||
make_npc->WIS = 85 + (GetLevel() * 3);
|
||||
make_npc->CHA = 85 + (GetLevel() * 3);
|
||||
make_npc->MR = 25;
|
||||
make_npc->FR = 25;
|
||||
make_npc->CR = 25;
|
||||
make_npc->DR = 25;
|
||||
make_npc->PR = 25;
|
||||
SwarmPet_Struct pet;
|
||||
pet.count = 1;
|
||||
pet.duration = 1;
|
||||
|
||||
//pet.duration += GetFocusEffect(focusSwarmPetDuration, spell_id) / 1000; //TODO: Does WTD use pet focus?
|
||||
|
||||
pet.npc_id = WAKE_THE_DEAD_NPCTYPEID;
|
||||
|
||||
NPCType *made_npc = nullptr;
|
||||
|
||||
const NPCType *npc_type = content_db.LoadNPCTypesData(WAKE_THE_DEAD_NPCTYPEID);
|
||||
if (npc_type == nullptr) {
|
||||
//log write
|
||||
LogError("Unknown npc type for 'Wake the Dead' swarm pet spell id: [{}]", spell_id);
|
||||
Message(0, "Unable to find pet!");
|
||||
return;
|
||||
}
|
||||
|
||||
made_npc = new NPCType;
|
||||
memcpy(made_npc, npc_type, sizeof(NPCType));
|
||||
|
||||
//level class and gender
|
||||
make_npc->level = GetLevel();
|
||||
make_npc->class_ = CorpseToUse->class_;
|
||||
make_npc->race = CorpseToUse->race;
|
||||
make_npc->gender = CorpseToUse->gender;
|
||||
make_npc->loottable_id = 0;
|
||||
//name
|
||||
char NewName[64];
|
||||
sprintf(NewName, "%s`s Animated Corpse", GetCleanName());
|
||||
strcpy(make_npc->name, NewName);
|
||||
strcpy(made_npc->name, NewName);
|
||||
npc_type = made_npc;
|
||||
|
||||
//combat stats
|
||||
made_npc->AC = ((GetLevel() * 7) + 550);
|
||||
made_npc->ATK = GetLevel();
|
||||
made_npc->max_dmg = (GetLevel() * 4) + 2;
|
||||
made_npc->min_dmg = 1;
|
||||
|
||||
//base stats
|
||||
made_npc->current_hp = (GetLevel() * 55);
|
||||
made_npc->max_hp = (GetLevel() * 55);
|
||||
made_npc->STR = 85 + (GetLevel() * 3);
|
||||
made_npc->STA = 85 + (GetLevel() * 3);
|
||||
made_npc->DEX = 85 + (GetLevel() * 3);
|
||||
made_npc->AGI = 85 + (GetLevel() * 3);
|
||||
made_npc->INT = 85 + (GetLevel() * 3);
|
||||
made_npc->WIS = 85 + (GetLevel() * 3);
|
||||
made_npc->CHA = 85 + (GetLevel() * 3);
|
||||
made_npc->MR = 25;
|
||||
made_npc->FR = 25;
|
||||
made_npc->CR = 25;
|
||||
made_npc->DR = 25;
|
||||
made_npc->PR = 25;
|
||||
|
||||
//level class and gender
|
||||
made_npc->level = GetLevel();
|
||||
made_npc->class_ = corpse_to_use->class_;
|
||||
made_npc->race = corpse_to_use->race;
|
||||
made_npc->gender = corpse_to_use->gender;
|
||||
made_npc->loottable_id = 0;
|
||||
|
||||
//appearance
|
||||
make_npc->beard = CorpseToUse->beard;
|
||||
make_npc->beardcolor = CorpseToUse->beardcolor;
|
||||
make_npc->eyecolor1 = CorpseToUse->eyecolor1;
|
||||
make_npc->eyecolor2 = CorpseToUse->eyecolor2;
|
||||
make_npc->haircolor = CorpseToUse->haircolor;
|
||||
make_npc->hairstyle = CorpseToUse->hairstyle;
|
||||
make_npc->helmtexture = CorpseToUse->helmtexture;
|
||||
make_npc->luclinface = CorpseToUse->luclinface;
|
||||
make_npc->size = CorpseToUse->size;
|
||||
make_npc->texture = CorpseToUse->texture;
|
||||
made_npc->beard = corpse_to_use->beard;
|
||||
made_npc->beardcolor = corpse_to_use->beardcolor;
|
||||
made_npc->eyecolor1 = corpse_to_use->eyecolor1;
|
||||
made_npc->eyecolor2 = corpse_to_use->eyecolor2;
|
||||
made_npc->haircolor = corpse_to_use->haircolor;
|
||||
made_npc->hairstyle = corpse_to_use->hairstyle;
|
||||
made_npc->helmtexture = corpse_to_use->helmtexture;
|
||||
made_npc->luclinface = corpse_to_use->luclinface;
|
||||
made_npc->size = corpse_to_use->size;
|
||||
made_npc->texture = corpse_to_use->texture;
|
||||
|
||||
//cast stuff.. based off of PEQ's if you want to change
|
||||
//it you'll have to mod this code, but most likely
|
||||
@@ -337,130 +376,144 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration)
|
||||
//part of their spell list; can't think of any smooth
|
||||
//way to do this
|
||||
//some basic combat mods here too since it's convienent
|
||||
switch(CorpseToUse->class_)
|
||||
switch (corpse_to_use->class_)
|
||||
{
|
||||
case CLERIC:
|
||||
make_npc->npc_spells_id = 1;
|
||||
made_npc->npc_spells_id = 1;
|
||||
break;
|
||||
case WIZARD:
|
||||
make_npc->npc_spells_id = 2;
|
||||
made_npc->npc_spells_id = 2;
|
||||
break;
|
||||
case NECROMANCER:
|
||||
make_npc->npc_spells_id = 3;
|
||||
made_npc->npc_spells_id = 3;
|
||||
break;
|
||||
case MAGICIAN:
|
||||
make_npc->npc_spells_id = 4;
|
||||
made_npc->npc_spells_id = 4;
|
||||
break;
|
||||
case ENCHANTER:
|
||||
make_npc->npc_spells_id = 5;
|
||||
made_npc->npc_spells_id = 5;
|
||||
break;
|
||||
case SHAMAN:
|
||||
make_npc->npc_spells_id = 6;
|
||||
made_npc->npc_spells_id = 6;
|
||||
break;
|
||||
case DRUID:
|
||||
make_npc->npc_spells_id = 7;
|
||||
made_npc->npc_spells_id = 7;
|
||||
break;
|
||||
case PALADIN:
|
||||
//SPECATK_TRIPLE
|
||||
strcpy(make_npc->special_abilities, "6,1");
|
||||
make_npc->current_hp = make_npc->current_hp * 150 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 150 / 100;
|
||||
make_npc->npc_spells_id = 8;
|
||||
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:
|
||||
strcpy(make_npc->special_abilities, "6,1");
|
||||
make_npc->current_hp = make_npc->current_hp * 150 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 150 / 100;
|
||||
make_npc->npc_spells_id = 9;
|
||||
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:
|
||||
strcpy(make_npc->special_abilities, "7,1");
|
||||
make_npc->current_hp = make_npc->current_hp * 135 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 135 / 100;
|
||||
make_npc->npc_spells_id = 10;
|
||||
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:
|
||||
strcpy(make_npc->special_abilities, "6,1");
|
||||
make_npc->current_hp = make_npc->current_hp * 110 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 110 / 100;
|
||||
make_npc->npc_spells_id = 11;
|
||||
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:
|
||||
strcpy(make_npc->special_abilities, "7,1");
|
||||
make_npc->current_hp = make_npc->current_hp * 110 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 110 / 100;
|
||||
make_npc->npc_spells_id = 12;
|
||||
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:
|
||||
strcpy(make_npc->special_abilities, "7,1");
|
||||
make_npc->max_dmg = make_npc->max_dmg * 150 /100;
|
||||
make_npc->current_hp = make_npc->current_hp * 110 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 110 / 100;
|
||||
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:
|
||||
strcpy(make_npc->special_abilities, "7,1");
|
||||
make_npc->max_dmg = make_npc->max_dmg * 150 /100;
|
||||
make_npc->current_hp = make_npc->current_hp * 135 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 135 / 100;
|
||||
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:
|
||||
strcpy(make_npc->special_abilities, "7,1");
|
||||
make_npc->max_dmg = make_npc->max_dmg * 150 /100;
|
||||
make_npc->current_hp = make_npc->current_hp * 175 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 175 / 100;
|
||||
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;
|
||||
made_npc->max_hp = made_npc->max_hp * 175 / 100;
|
||||
break;
|
||||
default:
|
||||
make_npc->npc_spells_id = 0;
|
||||
made_npc->npc_spells_id = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
make_npc->loottable_id = 0;
|
||||
make_npc->merchanttype = 0;
|
||||
make_npc->d_melee_texture1 = 0;
|
||||
make_npc->d_melee_texture2 = 0;
|
||||
made_npc->loottable_id = 0;
|
||||
made_npc->merchanttype = 0;
|
||||
made_npc->d_melee_texture1 = 0;
|
||||
made_npc->d_melee_texture2 = 0;
|
||||
|
||||
auto npca = new NPC(make_npc, 0, GetPosition(), GravityBehavior::Water);
|
||||
|
||||
if(!npca->GetSwarmInfo()){
|
||||
auto nSI = new SwarmPet;
|
||||
npca->SetSwarmInfo(nSI);
|
||||
npca->GetSwarmInfo()->duration = new Timer(duration*1000);
|
||||
}
|
||||
else{
|
||||
npca->GetSwarmInfo()->duration->Start(duration*1000);
|
||||
}
|
||||
int summon_count = 0;
|
||||
summon_count = pet.count;
|
||||
|
||||
npca->StartSwarmTimer(duration * 1000);
|
||||
npca->GetSwarmInfo()->owner_id = GetID();
|
||||
NPC* swarm_pet_npc = nullptr;
|
||||
//TODO: potenitally add support for multiple pets per corpse
|
||||
while (summon_count > 0) {
|
||||
int pet_duration = duration;
|
||||
|
||||
//give the pet somebody to "love"
|
||||
if(target != nullptr){
|
||||
npca->AddToHateList(target, 100000);
|
||||
npca->GetSwarmInfo()->target = target->GetID();
|
||||
}
|
||||
|
||||
//gear stuff, need to make sure there's
|
||||
//no situation where this stuff can be duped
|
||||
for (int x = EQ::invslot::EQUIPMENT_BEGIN; x <= EQ::invslot::EQUIPMENT_END; x++)
|
||||
{
|
||||
uint32 sitem = 0;
|
||||
sitem = CorpseToUse->GetWornItem(x);
|
||||
if(sitem){
|
||||
const EQ::ItemData * itm = database.GetItem(sitem);
|
||||
npca->AddLootDrop(itm, &npca->itemlist, NPC::NewLootDropEntry(), true);
|
||||
NPCType *npc_dup = nullptr;
|
||||
if (made_npc != nullptr) {
|
||||
npc_dup = new NPCType;
|
||||
memcpy(npc_dup, made_npc, sizeof(NPCType));
|
||||
}
|
||||
|
||||
swarm_pet_npc = new NPC(
|
||||
(npc_dup != nullptr) ? npc_dup : npc_type,
|
||||
0, corpse_to_use->GetPosition(),GravityBehavior::Water);
|
||||
|
||||
swarm_pet_npc->SetFollowID(GetID());
|
||||
|
||||
if (!swarm_pet_npc->GetSwarmInfo()) {
|
||||
auto nSI = new SwarmPet;
|
||||
swarm_pet_npc->SetSwarmInfo(nSI);
|
||||
swarm_pet_npc->GetSwarmInfo()->duration = new Timer(pet_duration * 1000);
|
||||
}
|
||||
else {
|
||||
swarm_pet_npc->GetSwarmInfo()->duration->Start(pet_duration * 1000);
|
||||
}
|
||||
|
||||
swarm_pet_npc->StartSwarmTimer(pet_duration * 1000);
|
||||
|
||||
//removing this prevents the pet from attacking
|
||||
swarm_pet_npc->GetSwarmInfo()->owner_id = GetID();
|
||||
|
||||
//give the pets somebody to "love"
|
||||
if (target != nullptr) {
|
||||
swarm_pet_npc->AddToHateList(target, 10000, 1000);
|
||||
swarm_pet_npc->GetSwarmInfo()->target = 0;
|
||||
}
|
||||
|
||||
//we allocated a new NPC type object, give the NPC ownership of that memory
|
||||
if (npc_dup != nullptr)
|
||||
swarm_pet_npc->GiveNPCTypeData(npc_dup);
|
||||
|
||||
entity_list.AddNPC(swarm_pet_npc, true, true);
|
||||
summon_count--;
|
||||
}
|
||||
|
||||
//we allocated a new NPC type object, give the NPC ownership of that memory
|
||||
if(make_npc != nullptr)
|
||||
npca->GiveNPCTypeData(make_npc);
|
||||
|
||||
entity_list.AddNPC(npca, true, true);
|
||||
|
||||
//the target of these swarm pets will take offense to being cast on...
|
||||
if(target != nullptr)
|
||||
if (target != nullptr)
|
||||
target->AddToHateList(this, 1, 0);
|
||||
|
||||
// The other pointers we make are handled elsewhere.
|
||||
delete made_npc;
|
||||
}
|
||||
|
||||
void Client::ResetAA() {
|
||||
@@ -499,9 +552,19 @@ void Client::ResetAA() {
|
||||
|
||||
void Client::SendClearAA()
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_ClearLeadershipAbilities, 0);
|
||||
SendClearLeadershipAA();
|
||||
SendClearPlayerAA();
|
||||
}
|
||||
|
||||
void Client::SendClearPlayerAA()
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_ClearAA, 0);
|
||||
FastQueuePacket(&outapp);
|
||||
outapp = new EQApplicationPacket(OP_ClearAA, 0);
|
||||
}
|
||||
|
||||
void Client::SendClearLeadershipAA()
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_ClearLeadershipAbilities, 0);
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
|
||||
@@ -1164,65 +1227,65 @@ void Client::IncrementAlternateAdvancementRank(int rank_id) {
|
||||
void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) {
|
||||
AA::Rank *rank = zone->GetAlternateAdvancementRank(rank_id);
|
||||
|
||||
if(!rank) {
|
||||
if (!rank) {
|
||||
return;
|
||||
}
|
||||
|
||||
AA::Ability *ability = rank->base_ability;
|
||||
if(!ability) {
|
||||
if (!ability) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!IsValidSpell(rank->spell)) {
|
||||
if (!IsValidSpell(rank->spell)) {
|
||||
return;
|
||||
}
|
||||
//do not allow AA to cast if your actively casting another AA.
|
||||
if (rank->spell == casting_spell_id && rank->id == casting_spell_aa_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!CanUseAlternateAdvancementRank(rank)) {
|
||||
if (!CanUseAlternateAdvancementRank(rank)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool use_toggle_passive_hotkey = UseTogglePassiveHotkey(*rank);
|
||||
|
||||
//make sure it is not a passive
|
||||
if(!rank->effects.empty() && !use_toggle_passive_hotkey) {
|
||||
if (!rank->effects.empty() && !use_toggle_passive_hotkey) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 charges = 0;
|
||||
// We don't have the AA
|
||||
if (!GetAA(rank_id, &charges))
|
||||
if (!GetAA(rank_id, &charges)) {
|
||||
return;
|
||||
}
|
||||
//if expendable make sure we have charges
|
||||
if(ability->charges > 0 && charges < 1)
|
||||
if (ability->charges > 0 && charges < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
//check cooldown
|
||||
if(!p_timers.Expired(&database, rank->spell_type + pTimerAAStart, false)) {
|
||||
if (!p_timers.Expired(&database, rank->spell_type + pTimerAAStart, false)) {
|
||||
uint32 aaremain = p_timers.GetRemainingTime(rank->spell_type + pTimerAAStart);
|
||||
uint32 aaremain_hr = aaremain / (60 * 60);
|
||||
uint32 aaremain_min = (aaremain / 60) % 60;
|
||||
uint32 aaremain_sec = aaremain % 60;
|
||||
|
||||
if(aaremain_hr >= 1) {
|
||||
if (aaremain_hr >= 1) {
|
||||
Message(Chat::Red, "You can use this ability again in %u hour(s) %u minute(s) %u seconds",
|
||||
aaremain_hr, aaremain_min, aaremain_sec);
|
||||
aaremain_hr, aaremain_min, aaremain_sec);
|
||||
}
|
||||
else {
|
||||
Message(Chat::Red, "You can use this ability again in %u minute(s) %u seconds",
|
||||
aaremain_min, aaremain_sec);
|
||||
aaremain_min, aaremain_sec);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//calculate cooldown
|
||||
int cooldown = rank->recast_time - GetAlternateAdvancementCooldownReduction(rank);
|
||||
if(cooldown < 0) {
|
||||
cooldown = 0;
|
||||
}
|
||||
|
||||
if (!IsCastWhileInvis(rank->spell))
|
||||
if (!IsCastWhileInvis(rank->spell)) {
|
||||
CommonBreakInvisible();
|
||||
}
|
||||
|
||||
if (spells[rank->spell].sneak && (!hidden || (hidden && (Timer::GetCurrentTime() - tmHidden) < 4000))) {
|
||||
MessageString(Chat::SpellFailure, SNEAK_RESTRICT);
|
||||
@@ -1230,13 +1293,15 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) {
|
||||
}
|
||||
//
|
||||
// Modern clients don't require pet targeted for AA casts that are ST_Pet
|
||||
if (spells[rank->spell].target_type == ST_Pet || spells[rank->spell].target_type == ST_SummonedPet)
|
||||
if (spells[rank->spell].target_type == ST_Pet || spells[rank->spell].target_type == ST_SummonedPet) {
|
||||
target_id = GetPetID();
|
||||
}
|
||||
|
||||
// extra handling for cast_not_standing spells
|
||||
if (!spells[rank->spell].cast_not_standing) {
|
||||
if (GetAppearance() == eaSitting) // we need to stand!
|
||||
if (!IgnoreCastingRestriction(rank->spell)) {
|
||||
if (GetAppearance() == eaSitting) { // we need to stand!
|
||||
SetAppearance(eaStanding, false);
|
||||
}
|
||||
|
||||
if (GetAppearance() != eaStanding) {
|
||||
MessageString(Chat::SpellFailure, STAND_TO_CAST);
|
||||
@@ -1248,22 +1313,36 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) {
|
||||
TogglePassiveAlternativeAdvancement(*rank, ability->id);
|
||||
}
|
||||
else {
|
||||
// Bards can cast instant cast AAs while they are casting another song
|
||||
if (spells[rank->spell].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) {
|
||||
if (!SpellFinished(rank->spell, entity_list.GetMob(target_id), EQ::spells::CastingSlot::AltAbility, spells[rank->spell].mana, -1, spells[rank->spell].resist_difficulty, false)) {
|
||||
// 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 (!DoCastingChecksOnCaster(rank->spell)) {
|
||||
return;
|
||||
}
|
||||
ExpendAlternateAdvancementCharge(ability->id);
|
||||
SpellFinished(rank->spell, entity_list.GetMob(target_id), EQ::spells::CastingSlot::AltAbility, spells[rank->spell].mana, -1, spells[rank->spell].resist_difficulty, false, -1, false, rank->id);
|
||||
}
|
||||
//Known issue: If you attempt to give a Bard an AA with a cast time, the cast timer will not display on the client (no live bard AA have cast time).
|
||||
else {
|
||||
if (!CastSpell(rank->spell, target_id, EQ::spells::CastingSlot::AltAbility, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, nullptr, rank->id)) {
|
||||
return;
|
||||
}
|
||||
CastSpell(rank->spell, target_id, EQ::spells::CastingSlot::AltAbility, -1, -1, 0, -1, 0xFFFFFFFF, 0, nullptr, rank->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CastToClient()->GetPTimers().Start(rank->spell_type + pTimerAAStart, cooldown);
|
||||
SendAlternateAdvancementTimer(rank->spell_type, 0, 0);
|
||||
void Client::SetAARecastTimer(AA::Rank *rank_in, int32 spell_id) {
|
||||
|
||||
if (!rank_in) {
|
||||
return;
|
||||
}
|
||||
|
||||
//calculate AA cooldown
|
||||
int timer_duration = rank_in->recast_time - GetAlternateAdvancementCooldownReduction(rank_in);
|
||||
|
||||
if (timer_duration <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
CastToClient()->GetPTimers().Start(rank_in->spell_type + pTimerAAStart, timer_duration);
|
||||
CastToClient()->SendAlternateAdvancementTimer(rank_in->spell_type, 0, 0);
|
||||
LogSpells("Spell [{}]: Setting AA reuse timer [{}] to [{}]", spell_id, rank_in->spell_type + pTimerAAStart, timer_duration);
|
||||
}
|
||||
|
||||
int Mob::GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in) {
|
||||
@@ -1276,6 +1355,7 @@ int Mob::GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int total_reduction = 0;
|
||||
for(auto &aa : aa_ranks) {
|
||||
auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa.first, aa.second.first);
|
||||
auto ability = ability_rank.first;
|
||||
@@ -1287,15 +1367,16 @@ int Mob::GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in) {
|
||||
|
||||
for(auto &effect : rank->effects) {
|
||||
if(effect.effect_id == SE_HastenedAASkill && effect.limit_value == ability_in->id) {
|
||||
return effect.base_value;
|
||||
total_reduction += effect.base_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return total_reduction;
|
||||
}
|
||||
|
||||
void Mob::ExpendAlternateAdvancementCharge(uint32 aa_id) {
|
||||
|
||||
for (auto &iter : aa_ranks) {
|
||||
AA::Ability *ability = zone->GetAlternateAdvancementAbility(iter.first);
|
||||
if (ability && aa_id == ability->id) {
|
||||
@@ -1700,11 +1781,18 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map<int, std
|
||||
}
|
||||
|
||||
LogInfo("Loaded [{}] Alternate Advancement Abilities", (int)abilities.size());
|
||||
|
||||
int expansion = RuleI(Expansion, CurrentExpansion);
|
||||
bool use_expansion_aa = RuleB(Expansion, UseCurrentExpansionAAOnly);
|
||||
|
||||
LogInfo("Loading Alternate Advancement Ability Ranks");
|
||||
ranks.clear();
|
||||
query = "SELECT id, upper_hotkey_sid, lower_hotkey_sid, title_sid, desc_sid, cost, level_req, spell, spell_type, recast_time, "
|
||||
if (use_expansion_aa && expansion >= 0) {
|
||||
query = fmt::format("SELECT id, upper_hotkey_sid, lower_hotkey_sid, title_sid, desc_sid, cost, level_req, spell, spell_type, recast_time, "
|
||||
"next_id, expansion FROM aa_ranks WHERE expansion <= {}", expansion);
|
||||
} else {
|
||||
query = "SELECT id, upper_hotkey_sid, lower_hotkey_sid, title_sid, desc_sid, cost, level_req, spell, spell_type, recast_time, "
|
||||
"next_id, expansion FROM aa_ranks";
|
||||
}
|
||||
results = QueryDatabase(query);
|
||||
if(results.Success()) {
|
||||
for(auto row = results.begin(); row != results.end(); ++row) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define AA_H
|
||||
|
||||
#define MAX_SWARM_PETS 12 //this can change as long as you make more coords (swarm_pet_x/swarm_pet_y)
|
||||
#define WAKE_THE_DEAD_NPCTYPEID 500 //We use first pet in pets table as a template
|
||||
|
||||
typedef enum {
|
||||
aaActionNone = 0,
|
||||
|
||||
+437
-231
@@ -38,190 +38,359 @@ extern Zone* zone;
|
||||
//#define LOSDEBUG 6
|
||||
|
||||
void EntityList::DescribeAggro(Client *towho, NPC *from_who, float d, bool verbose) {
|
||||
float d2 = d*d;
|
||||
float distance_squared = (d * d);
|
||||
|
||||
towho->Message(Chat::White, "Describing aggro for %s", from_who->GetName());
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Describing aggro for {} ({}).",
|
||||
from_who->GetCleanName(),
|
||||
from_who->GetID()
|
||||
).c_str()
|
||||
);
|
||||
|
||||
bool engaged = from_who->IsEngaged();
|
||||
if(engaged) {
|
||||
bool is_engaged = from_who->IsEngaged();
|
||||
bool will_aggro_npcs = from_who->WillAggroNPCs();
|
||||
if (is_engaged) {
|
||||
Mob *top = from_who->GetHateTop();
|
||||
towho->Message(Chat::White, ".. I am currently fighting with %s", top == nullptr?"(nullptr)":top->GetName());
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"I am currently engaged with {}.",
|
||||
(
|
||||
!top ?
|
||||
"nothing" :
|
||||
fmt::format(
|
||||
"{} ({})",
|
||||
top->GetCleanName(),
|
||||
top->GetID()
|
||||
)
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
bool check_npcs = from_who->WillAggroNPCs();
|
||||
|
||||
if(verbose) {
|
||||
char namebuf[256];
|
||||
|
||||
int my_primary = from_who->GetPrimaryFaction();
|
||||
Mob *own = from_who->GetOwner();
|
||||
if(own != nullptr)
|
||||
my_primary = own->GetPrimaryFaction();
|
||||
|
||||
if(my_primary == 0) {
|
||||
strcpy(namebuf, "(No faction)");
|
||||
} else if(my_primary < 0) {
|
||||
strcpy(namebuf, "(Special faction)");
|
||||
} else {
|
||||
if(!content_db.GetFactionName(my_primary, namebuf, sizeof(namebuf)))
|
||||
strcpy(namebuf, "(Unknown)");
|
||||
if (verbose) {
|
||||
int faction_id = from_who->GetPrimaryFaction();
|
||||
Mob *owner = from_who->GetOwner();
|
||||
if(owner) {
|
||||
faction_id = owner->GetPrimaryFaction();
|
||||
}
|
||||
towho->Message(Chat::White, ".. I am on faction %s (%d)\n", namebuf, my_primary);
|
||||
|
||||
std::string faction_name = (
|
||||
faction_id > 0 ?
|
||||
content_db.GetFactionName(faction_id) :
|
||||
(
|
||||
faction_id == 0 ?
|
||||
"None" :
|
||||
fmt::format(
|
||||
"Special Faction {}",
|
||||
faction_id
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) is on Faction {} ({}).",
|
||||
from_who->GetCleanName(),
|
||||
from_who->GetID(),
|
||||
faction_name,
|
||||
faction_id
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
for (auto it = mob_list.begin(); it != mob_list.end(); ++it) {
|
||||
Mob *mob = it->second;
|
||||
if (mob->IsClient()) //also ensures that mob != around
|
||||
for (const auto& npc_entity : entity_list.GetNPCList()) {
|
||||
auto entity_id = npc_entity.first;
|
||||
auto npc = npc_entity.second;
|
||||
if (npc == from_who) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (DistanceSquared(mob->GetPosition(), from_who->GetPosition()) > d2)
|
||||
if (DistanceSquared(npc->GetPosition(), from_who->GetPosition()) > distance_squared) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (engaged) {
|
||||
uint32 amm = from_who->GetHateAmount(mob);
|
||||
if (amm == 0)
|
||||
towho->Message(Chat::White, "... %s is not on my hate list.", mob->GetName());
|
||||
else
|
||||
towho->Message(Chat::White, "... %s is on my hate list with value %lu", mob->GetName(), (unsigned long)amm);
|
||||
} else if (!check_npcs && mob->IsNPC()) {
|
||||
towho->Message(Chat::White, "... %s is an NPC and my npc_aggro is disabled.", mob->GetName());
|
||||
if (is_engaged) {
|
||||
uint32 hate_amount = from_who->GetHateAmount(npc);
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) is {}on my hate list{}.",
|
||||
npc->GetCleanName(),
|
||||
npc->GetID(),
|
||||
!hate_amount ? "not " : "",
|
||||
(
|
||||
!hate_amount ?
|
||||
"" :
|
||||
fmt::format(
|
||||
" with a hate amount of {}.",
|
||||
hate_amount
|
||||
)
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
} else if (!will_aggro_npcs) {
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) is an NPC and I cannot aggro NPCs.",
|
||||
npc->GetCleanName(),
|
||||
npc->GetID()
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
from_who->DescribeAggro(towho, mob, verbose);
|
||||
from_who->DescribeAggro(towho, npc, verbose);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) {
|
||||
void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) {
|
||||
//this logic is duplicated from below, try to keep it up to date.
|
||||
float iAggroRange = GetAggroRange();
|
||||
|
||||
float t1, t2, t3;
|
||||
t1 = std::abs(mob->GetX() - GetX());
|
||||
t2 = std::abs(mob->GetY() - GetY());
|
||||
t3 = std::abs(mob->GetZ() - GetZ());
|
||||
|
||||
if(( t1 > iAggroRange)
|
||||
|| ( t2 > iAggroRange)
|
||||
|| ( t3 > iAggroRange) ) {
|
||||
towho->Message(Chat::White, "...%s is out of range (fast). distances (%.3f,%.3f,%.3f), range %.3f", mob->GetName(),
|
||||
t1, t2, t3, iAggroRange);
|
||||
float aggro_range = GetAggroRange();
|
||||
float x_range = std::abs(mob->GetX() - GetX());
|
||||
float y_range = std::abs(mob->GetY() - GetY());
|
||||
float z_range = std::abs(mob->GetZ() - GetZ());
|
||||
if (
|
||||
x_range > aggro_range ||
|
||||
y_range > aggro_range ||
|
||||
z_range > aggro_range
|
||||
) {
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) is out of range. X Range: {} Y Range: {} Z Range: {} Aggro Range: {}",
|
||||
mob->GetCleanName(),
|
||||
mob->GetID(),
|
||||
x_range,
|
||||
y_range,
|
||||
z_range,
|
||||
aggro_range
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if(mob->IsInvisible(this)) {
|
||||
towho->Message(Chat::White, "...%s is invisible to me. ", mob->GetName());
|
||||
if (mob->IsInvisible(this)) {
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) is invisible to me. ",
|
||||
mob->GetCleanName(),
|
||||
mob->GetID()
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
if((mob->IsClient() &&
|
||||
(!mob->CastToClient()->Connected()
|
||||
|| mob->CastToClient()->IsLD()
|
||||
|| mob->CastToClient()->IsBecomeNPC()
|
||||
|| mob->CastToClient()->GetGM()
|
||||
|
||||
if (
|
||||
mob->IsClient() &&
|
||||
(
|
||||
!mob->CastToClient()->Connected() ||
|
||||
mob->CastToClient()->IsLD() ||
|
||||
mob->CastToClient()->IsBecomeNPC() ||
|
||||
mob->CastToClient()->GetGM()
|
||||
)
|
||||
))
|
||||
{
|
||||
towho->Message(Chat::White, "...%s is my owner. ", mob->GetName());
|
||||
) {
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) is a GM or is not connected. ",
|
||||
mob->GetCleanName(),
|
||||
mob->GetID()
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(mob == GetOwner()) {
|
||||
towho->Message(Chat::White, "...%s a GM or is not connected. ", mob->GetName());
|
||||
if (mob == GetOwner()) {
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) is my owner. ",
|
||||
mob->GetCleanName(),
|
||||
mob->GetID()
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
float dist2 = DistanceSquared(mob->GetPosition(), m_Position);
|
||||
|
||||
float iAggroRange2 = iAggroRange*iAggroRange;
|
||||
if( dist2 > iAggroRange2 ) {
|
||||
towho->Message(Chat::White, "...%s is out of range. %.3f > %.3f ", mob->GetName(),
|
||||
dist2, iAggroRange2);
|
||||
float distance_squared = DistanceSquared(mob->GetPosition(), m_Position);
|
||||
float aggro_range_squared = (aggro_range * aggro_range);
|
||||
if (distance_squared > aggro_range_squared) {
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) is out of range. Distance: {:.2f} Aggro Range: {:.2f}",
|
||||
mob->GetCleanName(),
|
||||
mob->GetID(),
|
||||
distance_squared,
|
||||
aggro_range_squared
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (RuleB(Aggro, UseLevelAggro))
|
||||
{
|
||||
if (GetLevel() < RuleI(Aggro, MinAggroLevel) && mob->GetLevelCon(GetLevel()) == CON_GRAY && GetBodyType() != 3 && !AlwaysAggro())
|
||||
{
|
||||
towho->Message(Chat::White, "...%s is red to me (basically)", mob->GetName(), dist2, iAggroRange2);
|
||||
if (RuleB(Aggro, UseLevelAggro)) {
|
||||
if (
|
||||
GetLevel() < RuleI(Aggro, MinAggroLevel) &&
|
||||
mob->GetLevelCon(GetLevel()) == CON_GRAY &&
|
||||
GetBodyType() != BT_Undead &&
|
||||
!AlwaysAggro()
|
||||
) {
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) considers Red to me.",
|
||||
mob->GetCleanName(),
|
||||
mob->GetID()
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(GetINT() > RuleI(Aggro, IntAggroThreshold) && mob->GetLevelCon(GetLevel()) == CON_GRAY && !AlwaysAggro()) {
|
||||
towho->Message(Chat::White, "...%s is red to me (basically)", mob->GetName(),
|
||||
dist2, iAggroRange2);
|
||||
} else {
|
||||
if (
|
||||
GetINT() > RuleI(Aggro, IntAggroThreshold) &&
|
||||
mob->GetLevelCon(GetLevel()) == CON_GRAY &&
|
||||
!AlwaysAggro()
|
||||
) {
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) considers Red to me.",
|
||||
mob->GetCleanName(),
|
||||
mob->GetID()
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(verbose) {
|
||||
int my_primary = GetPrimaryFaction();
|
||||
int mob_primary = mob->GetPrimaryFaction();
|
||||
Mob *own = GetOwner();
|
||||
if(own != nullptr)
|
||||
my_primary = own->GetPrimaryFaction();
|
||||
own = mob->GetOwner();
|
||||
if(mob_primary > 0 && own != nullptr)
|
||||
mob_primary = own->GetPrimaryFaction();
|
||||
if (verbose) {
|
||||
int faction_id = GetPrimaryFaction();
|
||||
int mob_faction_id = mob->GetPrimaryFaction();
|
||||
Mob *owner = GetOwner();
|
||||
if (owner) {
|
||||
faction_id = owner->GetPrimaryFaction();
|
||||
}
|
||||
|
||||
if(mob_primary == 0) {
|
||||
towho->Message(Chat::White, "...%s has no primary faction", mob->GetName());
|
||||
} else if(mob_primary < 0) {
|
||||
towho->Message(Chat::White, "...%s is on special faction %d", mob->GetName(), mob_primary);
|
||||
owner = mob->GetOwner();
|
||||
if (mob_faction_id && owner) {
|
||||
mob_faction_id = owner->GetPrimaryFaction();
|
||||
}
|
||||
|
||||
if (!mob_faction_id) {
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) has no primary Faction.",
|
||||
mob->GetCleanName(),
|
||||
mob->GetID()
|
||||
).c_str()
|
||||
);
|
||||
} else if (mob_faction_id < 0) {
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) is on special Faction {}.",
|
||||
mob->GetCleanName(),
|
||||
mob->GetID(),
|
||||
mob_faction_id
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
char namebuf[256];
|
||||
if(!content_db.GetFactionName(mob_primary, namebuf, sizeof(namebuf)))
|
||||
strcpy(namebuf, "(Unknown)");
|
||||
std::list<struct NPCFaction*>::iterator cur,end;
|
||||
cur = faction_list.begin();
|
||||
end = faction_list.end();
|
||||
bool res = false;
|
||||
for(; cur != end; ++cur) {
|
||||
struct NPCFaction* fac = *cur;
|
||||
if ((int32)fac->factionID == mob_primary) {
|
||||
if (fac->npc_value > 0) {
|
||||
towho->Message(Chat::White, "...%s is on ALLY faction %s (%d) with %d", mob->GetName(), namebuf, mob_primary, fac->npc_value);
|
||||
res = true;
|
||||
break;
|
||||
} else if (fac->npc_value < 0) {
|
||||
towho->Message(Chat::White, "...%s is on ENEMY faction %s (%d) with %d", mob->GetName(), namebuf, mob_primary, fac->npc_value);
|
||||
res = true;
|
||||
break;
|
||||
} else {
|
||||
towho->Message(Chat::White, "...%s is on NEUTRAL faction %s (%d) with 0", mob->GetName(), namebuf, mob_primary);
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
auto faction_name = content_db.GetFactionName(mob_faction_id);
|
||||
bool has_entry = false;
|
||||
for (auto faction : faction_list) {
|
||||
if (static_cast<int>(faction->factionID) == mob_faction_id) {
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) has {} standing with Faction {} ({}) with their Faction Level of {}",
|
||||
mob->GetCleanName(),
|
||||
mob->GetID(),
|
||||
(
|
||||
faction->npc_value != 0 ?
|
||||
(
|
||||
faction->npc_value > 0 ?
|
||||
"positive" :
|
||||
"negative"
|
||||
) :
|
||||
"neutral"
|
||||
),
|
||||
faction_name,
|
||||
faction->factionID,
|
||||
faction->npc_value
|
||||
).c_str()
|
||||
);
|
||||
has_entry = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!res) {
|
||||
towho->Message(Chat::White, "...%s is on faction %s (%d), which I have no entry for.", mob->GetName(), namebuf, mob_primary);
|
||||
|
||||
if (!has_entry) {
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) is on Faction {} ({}), for which I do not have an entry.",
|
||||
mob->GetCleanName(),
|
||||
mob->GetID(),
|
||||
faction_name,
|
||||
mob_faction_id
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FACTION_VALUE fv = mob->GetReverseFactionCon(this);
|
||||
auto faction_value = mob->GetReverseFactionCon(this);
|
||||
|
||||
if(!(
|
||||
fv == FACTION_SCOWLS
|
||||
||
|
||||
(mob->GetPrimaryFaction() != GetPrimaryFaction() && mob->GetPrimaryFaction() == -4 && GetOwner() == nullptr)
|
||||
||
|
||||
fv == FACTION_THREATENLY
|
||||
)) {
|
||||
towho->Message(Chat::White, "...%s faction not low enough. value='%s'", mob->GetName(), FactionValueToString(fv));
|
||||
if(
|
||||
!(
|
||||
faction_value == FACTION_THREATENINGLY ||
|
||||
faction_value == FACTION_SCOWLS ||
|
||||
(
|
||||
mob->GetPrimaryFaction() != GetPrimaryFaction() &&
|
||||
mob->GetPrimaryFaction() == -4 &&
|
||||
!GetOwner()
|
||||
)
|
||||
)
|
||||
) {
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) does not have low enough faction, their Faction Level is {} ({}).",
|
||||
mob->GetCleanName(),
|
||||
mob->GetID(),
|
||||
FactionValueToString(faction_value),
|
||||
faction_value
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
if(fv == FACTION_THREATENLY) {
|
||||
towho->Message(Chat::White, "...%s threatening to me, so they only have a %d chance per check of attacking.", mob->GetName());
|
||||
}
|
||||
|
||||
if(!CheckLosFN(mob)) {
|
||||
towho->Message(Chat::White, "...%s is out of sight.", mob->GetName());
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) is out of sight.",
|
||||
mob->GetCleanName(),
|
||||
mob->GetID()
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
towho->Message(Chat::White, "...%s meets all conditions, I should be attacking them.", mob->GetName());
|
||||
towho->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) meets all conditions, I should be attacking them.",
|
||||
mob->GetCleanName(),
|
||||
mob->GetID()
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -229,65 +398,87 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) {
|
||||
to keep the #aggro command accurate.
|
||||
*/
|
||||
bool Mob::CheckWillAggro(Mob *mob) {
|
||||
if(!mob)
|
||||
if(!mob) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//sometimes if a client has some lag while zoning into a dangerous place while either invis or a GM
|
||||
//they will aggro mobs even though it's supposed to be impossible, to lets make sure we've finished connecting
|
||||
if (mob->IsClient()) {
|
||||
if (!mob->CastToClient()->ClientFinishedLoading() || mob->CastToClient()->IsHoveringForRespawn() || mob->CastToClient()->bZoning)
|
||||
if (
|
||||
!mob->CastToClient()->ClientFinishedLoading() ||
|
||||
mob->CastToClient()->IsHoveringForRespawn() ||
|
||||
mob->CastToClient()->bZoning
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// We don't want to aggro clients outside of water if we're water only.
|
||||
if (mob->IsClient() && mob->CastToClient()->GetLastRegion() != RegionTypeWater && IsUnderwaterOnly()) {
|
||||
if (
|
||||
mob->IsClient() &&
|
||||
mob->CastToClient()->GetLastRegion() != RegionTypeWater &&
|
||||
IsUnderwaterOnly()
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pets shouldn't scan for aggro
|
||||
*/
|
||||
if (this->GetOwner()) {
|
||||
if (GetOwner()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Mob *pet_owner = mob->GetOwner();
|
||||
if (pet_owner && pet_owner->IsClient() && (!RuleB(Aggro, AggroPlayerPets) || pet_owner->CastToClient()->GetGM())) {
|
||||
if (
|
||||
pet_owner &&
|
||||
pet_owner->IsClient() &&
|
||||
(
|
||||
!RuleB(Aggro, AggroPlayerPets) ||
|
||||
pet_owner->CastToClient()->GetGM()
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float iAggroRange = GetAggroRange();
|
||||
|
||||
// Check If it's invisible and if we can see invis
|
||||
// Check if it's a client, and that the client is connected and not linkdead,
|
||||
// and that the client isn't Playing an NPC, with thier gm flag on
|
||||
// Check if it's not a Interactive NPC
|
||||
// Trumpcard: The 1st 3 checks are low cost calcs to filter out unnessecary distance checks. Leave them at the beginning, they are the most likely occurence.
|
||||
// Image: I moved this up by itself above faction and distance checks because if one of these return true, theres no reason to go through the other information
|
||||
|
||||
float aggro_range = GetAggroRange();
|
||||
float x_range = std::abs(mob->GetX() - GetX());
|
||||
float y_range = std::abs(mob->GetY() - GetY());
|
||||
float z_range = std::abs(mob->GetZ() - GetZ());
|
||||
|
||||
float t1, t2, t3;
|
||||
t1 = std::abs(mob->GetX() - GetX());
|
||||
t2 = std::abs(mob->GetY() - GetY());
|
||||
t3 = std::abs(mob->GetZ() - GetZ());
|
||||
|
||||
if(( t1 > iAggroRange)
|
||||
|| ( t2 > iAggroRange)
|
||||
|| ( t3 > iAggroRange)
|
||||
|| (mob->IsInvisible(this))
|
||||
|| (mob->IsClient() &&
|
||||
(!mob->CastToClient()->Connected()
|
||||
if (
|
||||
x_range > aggro_range ||
|
||||
y_range > aggro_range ||
|
||||
z_range > aggro_range ||
|
||||
mob->IsInvisible(this) ||
|
||||
(
|
||||
mob->IsClient() &&
|
||||
(
|
||||
!mob->CastToClient()->Connected()
|
||||
|| mob->CastToClient()->IsLD()
|
||||
|| mob->CastToClient()->IsBecomeNPC()
|
||||
|| mob->CastToClient()->GetGM()
|
||||
)
|
||||
))
|
||||
{
|
||||
return(false);
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't aggro new clients if we are already engaged unless PROX_AGGRO is set
|
||||
if (IsEngaged() && (!GetSpecialAbility(PROX_AGGRO) || (GetSpecialAbility(PROX_AGGRO) && !CombatRange(mob)))) {
|
||||
LogAggro("[{}] is in combat, and does not have prox_aggro, or does and is out of combat range with [{}]", GetName(), mob->GetName());
|
||||
LogAggro(
|
||||
"[{}] is in combat, and does not have prox_aggro, or does and is out of combat range with [{}]",
|
||||
GetName(),
|
||||
mob->GetName()
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -296,105 +487,100 @@ bool Mob::CheckWillAggro(Mob *mob) {
|
||||
//aggro this mob...???
|
||||
//changed to be 'if I have an owner and this is it'
|
||||
if(mob == GetOwner()) {
|
||||
return(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
float dist2 = DistanceSquared(mob->GetPosition(), m_Position);
|
||||
float iAggroRange2 = iAggroRange*iAggroRange;
|
||||
float distance_squared = DistanceSquared(mob->GetPosition(), m_Position);
|
||||
float aggro_range_squared = (aggro_range * aggro_range);
|
||||
|
||||
if( dist2 > iAggroRange2 ) {
|
||||
if (distance_squared > aggro_range_squared ) {
|
||||
// Skip it, out of range
|
||||
return(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Image: Get their current target and faction value now that its required
|
||||
//this function call should seem backwards
|
||||
FACTION_VALUE fv = mob->GetReverseFactionCon(this);
|
||||
FACTION_VALUE faction_value = mob->GetReverseFactionCon(this);
|
||||
|
||||
// Make sure they're still in the zone
|
||||
// Are they in range?
|
||||
// Are they kos?
|
||||
// Are we stupid or are they green
|
||||
// and they don't have their gm flag on
|
||||
int heroicCHA_mod = mob->itembonuses.HeroicCHA/25; // 800 Heroic CHA cap
|
||||
if(heroicCHA_mod > THREATENLY_ARRGO_CHANCE)
|
||||
heroicCHA_mod = THREATENLY_ARRGO_CHANCE;
|
||||
if (RuleB(Aggro, UseLevelAggro) &&
|
||||
(
|
||||
//old InZone check taken care of above by !mob->CastToClient()->Connected()
|
||||
(
|
||||
( GetLevel() >= RuleI(Aggro, MinAggroLevel))
|
||||
||(GetBodyType() == 3) || AlwaysAggro()
|
||||
||( mob->IsClient() && mob->CastToClient()->IsSitting() )
|
||||
||( mob->GetLevelCon(GetLevel()) != CON_GRAY)
|
||||
int heroic_cha_mod = (mob->itembonuses.HeroicCHA / 25); // 800 Heroic CHA cap
|
||||
if(heroic_cha_mod > THREATENINGLY_AGGRO_CHANCE) {
|
||||
heroic_cha_mod = THREATENINGLY_AGGRO_CHANCE;
|
||||
}
|
||||
|
||||
)
|
||||
&&
|
||||
(
|
||||
if (
|
||||
RuleB(Aggro, UseLevelAggro) &&
|
||||
(
|
||||
fv == FACTION_SCOWLS
|
||||
||
|
||||
(mob->GetPrimaryFaction() != GetPrimaryFaction() && mob->GetPrimaryFaction() == -4 && GetOwner() == nullptr)
|
||||
||
|
||||
GetLevel() >= RuleI(Aggro, MinAggroLevel) ||
|
||||
GetBodyType() == BT_Undead ||
|
||||
AlwaysAggro() ||
|
||||
(
|
||||
fv == FACTION_THREATENLY
|
||||
&& zone->random.Roll(THREATENLY_ARRGO_CHANCE - heroicCHA_mod)
|
||||
mob->IsClient() &&
|
||||
mob->CastToClient()->IsSitting()
|
||||
) ||
|
||||
mob->GetLevelCon(GetLevel()) != CON_GRAY
|
||||
) &&
|
||||
(
|
||||
faction_value == FACTION_SCOWLS ||
|
||||
(
|
||||
mob->GetPrimaryFaction() != GetPrimaryFaction() &&
|
||||
mob->GetPrimaryFaction() == -4 &&
|
||||
!GetOwner()
|
||||
) ||
|
||||
(
|
||||
faction_value == FACTION_THREATENINGLY &&
|
||||
zone->random.Roll(THREATENINGLY_AGGRO_CHANCE - heroic_cha_mod)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
{
|
||||
//FatherNiwtit: make sure we can see them. last since it is very expensive
|
||||
) {
|
||||
if(CheckLosFN(mob)) {
|
||||
LogAggro("Check aggro for [{}] target [{}]", GetName(), mob->GetName());
|
||||
return( mod_will_aggro(mob, this) );
|
||||
return mod_will_aggro(mob, this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if
|
||||
(
|
||||
//old InZone check taken care of above by !mob->CastToClient()->Connected()
|
||||
(
|
||||
( GetINT() <= RuleI(Aggro, IntAggroThreshold) )
|
||||
|| AlwaysAggro()
|
||||
||( mob->IsClient() && mob->CastToClient()->IsSitting() )
|
||||
||( mob->GetLevelCon(GetLevel()) != CON_GRAY)
|
||||
|
||||
)
|
||||
&&
|
||||
(
|
||||
} else {
|
||||
if (
|
||||
(
|
||||
fv == FACTION_SCOWLS
|
||||
||
|
||||
(mob->GetPrimaryFaction() != GetPrimaryFaction() && mob->GetPrimaryFaction() == -4 && GetOwner() == nullptr)
|
||||
||
|
||||
GetINT() <= RuleI(Aggro, IntAggroThreshold) ||
|
||||
AlwaysAggro() ||
|
||||
(
|
||||
fv == FACTION_THREATENLY
|
||||
&& zone->random.Roll(THREATENLY_ARRGO_CHANCE - heroicCHA_mod)
|
||||
mob->IsClient() &&
|
||||
mob->CastToClient()->IsSitting()
|
||||
) ||
|
||||
mob->GetLevelCon(GetLevel()) != CON_GRAY
|
||||
) &&
|
||||
(
|
||||
faction_value == FACTION_SCOWLS ||
|
||||
(
|
||||
mob->GetPrimaryFaction() != GetPrimaryFaction() &&
|
||||
mob->GetPrimaryFaction() == -4 &&
|
||||
!GetOwner()
|
||||
) ||
|
||||
(
|
||||
faction_value == FACTION_THREATENINGLY
|
||||
&& zone->random.Roll(THREATENINGLY_AGGRO_CHANCE - heroic_cha_mod)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
{
|
||||
//FatherNiwtit: make sure we can see them. last since it is very expensive
|
||||
) {
|
||||
if(CheckLosFN(mob)) {
|
||||
LogAggro("Check aggro for [{}] target [{}]", GetName(), mob->GetName());
|
||||
return( mod_will_aggro(mob, this) );
|
||||
return mod_will_aggro(mob, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogAggro("Is In zone?:[{}]\n", mob->InZone());
|
||||
LogAggro("Dist^2: [{}]\n", dist2);
|
||||
LogAggro("Range^2: [{}]\n", iAggroRange2);
|
||||
LogAggro("Faction: [{}]\n", fv);
|
||||
LogAggro("Dist^2: [{}]\n", distance_squared);
|
||||
LogAggro("Range^2: [{}]\n", aggro_range_squared);
|
||||
LogAggro("Faction: [{}]\n", faction_value);
|
||||
LogAggro("AlwaysAggroFlag: [{}]\n", AlwaysAggro());
|
||||
LogAggro("Int: [{}]\n", GetINT());
|
||||
LogAggro("Con: [{}]\n", GetLevelCon(mob->GetLevel()));
|
||||
|
||||
return(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
int EntityList::GetHatedCount(Mob *attacker, Mob *exclude, bool inc_gray_con)
|
||||
@@ -474,6 +660,9 @@ bool Mob::IsAttackAllowed(Mob *target, bool isSpellAttack)
|
||||
if (target->GetSpecialAbility(IMMUNE_DAMAGE_NPC) && IsNPC())
|
||||
return false;
|
||||
|
||||
if (target->IsHorse())
|
||||
return false;
|
||||
|
||||
// can't damage own pet (applies to everthing)
|
||||
Mob *target_owner = target->GetOwner();
|
||||
Mob *our_owner = GetOwner();
|
||||
@@ -1133,10 +1322,10 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc)
|
||||
if (dispel && target && target->GetHateAmount(this) < 100)
|
||||
AggroAmount += 50;
|
||||
|
||||
if (spells[spell_id].hate_added > 0) // overrides the hate (ex. tash)
|
||||
if (spells[spell_id].hate_added != 0) // overrides the hate (ex. tash), can be negative.
|
||||
AggroAmount = spells[spell_id].hate_added;
|
||||
|
||||
if (GetOwner() && IsPet())
|
||||
if (GetOwner() && IsPet() && AggroAmount > 0)
|
||||
AggroAmount = AggroAmount * RuleI(Aggro, PetSpellAggroMod) / 100;
|
||||
|
||||
// hate focus ignored on first action for some reason
|
||||
@@ -1216,45 +1405,62 @@ int32 Mob::CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possib
|
||||
return std::max(0, AggroAmount);
|
||||
}
|
||||
|
||||
void Mob::AddFeignMemory(Client* attacker) {
|
||||
if(feign_memory_list.empty() && AI_feign_remember_timer != nullptr)
|
||||
void Mob::AddFeignMemory(Mob* attacker) {
|
||||
if (feign_memory_list.empty() && AI_feign_remember_timer != nullptr) {
|
||||
AI_feign_remember_timer->Start(AIfeignremember_delay);
|
||||
feign_memory_list.insert(attacker->CharacterID());
|
||||
}
|
||||
|
||||
if (attacker) {
|
||||
feign_memory_list.insert(attacker->GetID());
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::RemoveFromFeignMemory(Client* attacker) {
|
||||
feign_memory_list.erase(attacker->CharacterID());
|
||||
if(feign_memory_list.empty() && AI_feign_remember_timer != nullptr)
|
||||
void Mob::RemoveFromFeignMemory(Mob* attacker) {
|
||||
|
||||
if (!attacker) {
|
||||
return;
|
||||
}
|
||||
|
||||
feign_memory_list.erase(attacker->GetID());
|
||||
if (feign_memory_list.empty() && AI_feign_remember_timer != nullptr) {
|
||||
AI_feign_remember_timer->Disable();
|
||||
}
|
||||
if(feign_memory_list.empty())
|
||||
{
|
||||
minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin);
|
||||
maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax);
|
||||
if(AI_feign_remember_timer != nullptr)
|
||||
if (AI_feign_remember_timer != nullptr) {
|
||||
AI_feign_remember_timer->Disable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::ClearFeignMemory() {
|
||||
auto RememberedCharID = feign_memory_list.begin();
|
||||
while (RememberedCharID != feign_memory_list.end())
|
||||
auto remembered_feigned_mobid = feign_memory_list.begin();
|
||||
while (remembered_feigned_mobid != feign_memory_list.end())
|
||||
{
|
||||
Client* remember_client = entity_list.GetClientByCharID(*RememberedCharID);
|
||||
if(remember_client != nullptr) //Still in zone
|
||||
remember_client->RemoveXTarget(this, false);
|
||||
++RememberedCharID;
|
||||
Mob* remembered_mob = entity_list.GetMob(*remembered_feigned_mobid);
|
||||
if (remembered_mob->IsClient() && remembered_mob != nullptr) { //Still in zone
|
||||
remembered_mob->CastToClient()->RemoveXTarget(this, false);
|
||||
}
|
||||
++remembered_feigned_mobid;
|
||||
}
|
||||
|
||||
feign_memory_list.clear();
|
||||
minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin);
|
||||
maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax);
|
||||
if(AI_feign_remember_timer != nullptr)
|
||||
if (AI_feign_remember_timer != nullptr) {
|
||||
AI_feign_remember_timer->Disable();
|
||||
}
|
||||
}
|
||||
|
||||
bool Mob::IsOnFeignMemory(Client *attacker) const
|
||||
bool Mob::IsOnFeignMemory(Mob *attacker) const
|
||||
{
|
||||
return feign_memory_list.find(attacker->CharacterID()) != feign_memory_list.end();
|
||||
if (!attacker) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return feign_memory_list.find(attacker->GetID()) != feign_memory_list.end();
|
||||
}
|
||||
|
||||
bool Mob::PassCharismaCheck(Mob* caster, uint16 spell_id) {
|
||||
|
||||
@@ -436,7 +436,6 @@ Json::Value ApiGetMobListDetail(EQ::Net::WebsocketServerConnection *connection,
|
||||
row["cwp"] = mob->GetCWP();
|
||||
row["cwpp"] = mob->GetCWPP();
|
||||
row["divine_aura"] = mob->DivineAura();
|
||||
row["do_casting_checks"] = mob->DoCastingChecks();
|
||||
row["dont_buff_me_before"] = mob->DontBuffMeBefore();
|
||||
row["dont_cure_me_before"] = mob->DontCureMeBefore();
|
||||
row["dont_dot_me_before"] = mob->DontDotMeBefore();
|
||||
|
||||
+230
-113
@@ -432,7 +432,22 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit)
|
||||
}
|
||||
|
||||
// riposte -- it may seem crazy, but if the attacker has SPA 173 on them, they are immune to Ripo
|
||||
bool ImmuneRipo = attacker->aabonuses.RiposteChance || attacker->spellbonuses.RiposteChance || attacker->itembonuses.RiposteChance || attacker->IsEnraged();
|
||||
bool ImmuneRipo = false;
|
||||
if (!RuleB(Combat, UseLiveRiposteMechanics)) {
|
||||
ImmuneRipo = attacker->aabonuses.RiposteChance || attacker->spellbonuses.RiposteChance || attacker->itembonuses.RiposteChance || attacker->IsEnraged();
|
||||
}
|
||||
/*
|
||||
Live Riposte Mechanics (~Kayen updated 1/22)
|
||||
-Ripostes can not trigger another riposte. (Ie. Riposte from defender can't then trigger the attacker to riposte)
|
||||
-Ripostes can not be 'avoided', only hit or miss.
|
||||
-Attacker with SPA 173 is not immune to riposte. The defender can riposte against the attackers melee hits.
|
||||
|
||||
Legacy Riposte Mechanics
|
||||
-Ripostes can trigger another riposte
|
||||
-Attacker with SPA 173 is immune to riposte
|
||||
-Attacker that is enraged is immune to riposte
|
||||
*/
|
||||
|
||||
// Need to check if we have something in MainHand to actually attack with (or fists)
|
||||
if (hit.hand != EQ::invslot::slotRange && (CanThisClassRiposte() || IsEnraged()) && InFront && !ImmuneRipo) {
|
||||
if (IsEnraged()) {
|
||||
@@ -1369,25 +1384,27 @@ int Client::DoDamageCaps(int base_damage)
|
||||
|
||||
// other is the defender, this is the attacker
|
||||
//SYNC WITH: tune.cpp, mob.h TuneDoAttack
|
||||
void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts)
|
||||
void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts, bool FromRiposte)
|
||||
{
|
||||
if (!other)
|
||||
return;
|
||||
LogCombat("[{}]::DoAttack vs [{}] base [{}] min [{}] offense [{}] tohit [{}] skill [{}]", GetName(),
|
||||
other->GetName(), hit.base_damage, hit.min_damage, hit.offense, hit.tohit, hit.skill);
|
||||
|
||||
// check to see if we hit..
|
||||
if (other->AvoidDamage(this, hit)) {
|
||||
if (!RuleB(Combat, UseLiveRiposteMechanics)) {
|
||||
FromRiposte = false;
|
||||
}
|
||||
|
||||
// check to see if we hit..
|
||||
if (!FromRiposte && other->AvoidDamage(this, hit)) {
|
||||
int strike_through = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough;
|
||||
if (strike_through && zone->random.Roll(strike_through)) {
|
||||
MessageString(Chat::StrikeThrough,
|
||||
STRIKETHROUGH_STRING); // You strike through your opponents defenses!
|
||||
hit.damage_done = 1; // set to one, we will check this to continue
|
||||
}
|
||||
// I'm pretty sure you can riposte a riposte
|
||||
if (hit.damage_done == DMG_RIPOSTED) {
|
||||
DoRiposte(other);
|
||||
//if (IsDead())
|
||||
return;
|
||||
}
|
||||
LogCombat("Avoided/strikethrough damage with code [{}]", hit.damage_done);
|
||||
@@ -1570,7 +1587,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
||||
|
||||
my_hit.tohit = GetTotalToHit(my_hit.skill, hit_chance_bonus);
|
||||
|
||||
DoAttack(other, my_hit, opts);
|
||||
DoAttack(other, my_hit, opts, bRiposte);
|
||||
}
|
||||
else {
|
||||
my_hit.damage_done = DMG_INVULNERABLE;
|
||||
@@ -1603,32 +1620,26 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
||||
///////////////////////////////////////////////////////////
|
||||
////// Send Attack Damage
|
||||
///////////////////////////////////////////////////////////
|
||||
if (my_hit.damage_done > 0 && aabonuses.SkillAttackProc[SBIndex::SKILLPROC_CHANCE] && aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SKILL] == my_hit.skill &&
|
||||
IsValidSpell(aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID])) {
|
||||
float chance = aabonuses.SkillAttackProc[SBIndex::SKILLPROC_CHANCE] / 1000.0f;
|
||||
if (zone->random.Roll(chance))
|
||||
SpellFinished(aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID], other, EQ::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID]].resist_difficulty);
|
||||
}
|
||||
other->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, my_hit.skill, true, -1, false, m_specialattacks);
|
||||
|
||||
if (IsDead()) return false;
|
||||
if (IsDead()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MeleeLifeTap(my_hit.damage_done);
|
||||
|
||||
if (my_hit.damage_done > 0 && HasSkillProcSuccess() && other && other->GetHP() > 0)
|
||||
TrySkillProc(other, my_hit.skill, 0, true, Hand);
|
||||
|
||||
CommonBreakInvisibleFromCombat();
|
||||
|
||||
if (GetTarget())
|
||||
if (GetTarget()) {
|
||||
TriggerDefensiveProcs(other, Hand, true, my_hit.damage_done);
|
||||
}
|
||||
|
||||
if (my_hit.damage_done > 0)
|
||||
if (my_hit.damage_done > 0) {
|
||||
return true;
|
||||
|
||||
else
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//used by complete heal and #heal
|
||||
@@ -1880,6 +1891,8 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQ::skills::Skill
|
||||
//m_epp.perAA = 0; //reset to no AA exp on death.
|
||||
}
|
||||
|
||||
int32 illusion_spell_id = spellbonuses.Illusion;
|
||||
|
||||
//this generates a lot of 'updates' to the client that the client does not need
|
||||
BuffFadeNonPersistDeath();
|
||||
if (RuleB(Character, UnmemSpellsOnDeath)) {
|
||||
@@ -1925,13 +1938,12 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQ::skills::Skill
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entity_list.AddCorpse(new_corpse, GetID());
|
||||
SetID(0);
|
||||
|
||||
//send the become corpse packet to everybody else in the zone.
|
||||
entity_list.QueueClients(this, &app2, true);
|
||||
|
||||
ApplyIllusionToCorpse(illusion_spell_id, new_corpse);
|
||||
LeftCorpse = true;
|
||||
}
|
||||
}
|
||||
@@ -2168,7 +2180,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
|
||||
my_hit.offense = offense(my_hit.skill);
|
||||
my_hit.tohit = GetTotalToHit(my_hit.skill, hit_chance_bonus);
|
||||
|
||||
DoAttack(other, my_hit, opts);
|
||||
DoAttack(other, my_hit, opts, bRiposte);
|
||||
|
||||
other->AddToHateList(this, hate);
|
||||
|
||||
@@ -2329,6 +2341,8 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQ::skills::SkillTy
|
||||
if (p_depop == true)
|
||||
return false;
|
||||
|
||||
int32 illusion_spell_id = spellbonuses.Illusion;
|
||||
|
||||
HasAISpellEffects = false;
|
||||
BuffFadeAll();
|
||||
uint8 killed_level = GetLevel();
|
||||
@@ -2400,7 +2414,7 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQ::skills::SkillTy
|
||||
give_exp_client = give_exp->CastToClient();
|
||||
|
||||
//do faction hits even if we are a merchant, so long as a player killed us
|
||||
if (give_exp_client && !RuleB(NPC, EnableMeritBasedFaction))
|
||||
if (!IsCharmed() && give_exp_client && !RuleB(NPC, EnableMeritBasedFaction))
|
||||
hate_list.DoFactionHits(GetNPCFactionID());
|
||||
|
||||
bool IsLdonTreasure = (this->GetClass() == LDON_TREASURE);
|
||||
@@ -2571,6 +2585,7 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQ::skills::SkillTy
|
||||
}
|
||||
|
||||
entity_list.RemoveFromAutoXTargets(this);
|
||||
|
||||
uint16 emoteid = this->GetEmoteID();
|
||||
auto corpse = new Corpse(this, &itemlist, GetNPCTypeID(), &NPCTypedata,
|
||||
level > 54 ? RuleI(NPC, MajorNPCCorpseDecayTimeMS)
|
||||
@@ -2583,8 +2598,8 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQ::skills::SkillTy
|
||||
|
||||
// entity_list.RemoveMobFromCloseLists(this);
|
||||
close_mobs.clear();
|
||||
|
||||
this->SetID(0);
|
||||
ApplyIllusionToCorpse(illusion_spell_id, corpse);
|
||||
|
||||
if (killer != 0 && emoteid != 0)
|
||||
corpse->CastToNPC()->DoNPCEmote(AFTERDEATH, emoteid);
|
||||
@@ -2815,7 +2830,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
||||
|
||||
hate_list.AddEntToHateList(other, hate, damage, bFrenzy, !iBuffTic);
|
||||
|
||||
if (other->IsClient() && !on_hatelist && !IsOnFeignMemory(other->CastToClient()))
|
||||
if (other->IsClient() && !on_hatelist && !IsOnFeignMemory(other))
|
||||
other->CastToClient()->AddAutoXTarget(this);
|
||||
|
||||
#ifdef BOTS
|
||||
@@ -2857,7 +2872,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
||||
}
|
||||
} //MERC
|
||||
|
||||
// then add pet owner if there's one
|
||||
//if I am a pet, then add pet owner if there's one
|
||||
if (owner) { // Other is a pet, add him and it
|
||||
// EverHood 6/12/06
|
||||
// Can't add a feigned owner to hate list
|
||||
@@ -2872,8 +2887,9 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
||||
!(this->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && owner->IsClient()) &&
|
||||
!(this->GetSpecialAbility(IMMUNE_AGGRO_NPC) && owner->IsNPC())
|
||||
) {
|
||||
if (owner->IsClient() && !CheckAggro(owner))
|
||||
if (owner->IsClient() && !CheckAggro(owner)) {
|
||||
owner->CastToClient()->AddAutoXTarget(this);
|
||||
}
|
||||
hate_list.AddEntToHateList(owner, 0, 0, false, !iBuffTic);
|
||||
}
|
||||
}
|
||||
@@ -2900,8 +2916,10 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
||||
}
|
||||
}
|
||||
|
||||
if (other->GetTempPetCount())
|
||||
entity_list.AddTempPetsToHateList(other, this, bFrenzy);
|
||||
//I have a swarm pet, add other to it.
|
||||
if (GetTempPetCount()) {
|
||||
entity_list.AddTempPetsToHateList(this, other, bFrenzy);
|
||||
}
|
||||
|
||||
if (!wasengaged) {
|
||||
if (IsNPC() && other->IsClient() && other->CastToClient())
|
||||
@@ -3298,7 +3316,8 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
|
||||
// If this is a DoT, use DoT Shielding...
|
||||
if (iBuffTic) {
|
||||
damage -= (damage * itembonuses.DoTShielding / 100);
|
||||
int total_dotshielding = itembonuses.DoTShielding + itembonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_PERCENT] + aabonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_PERCENT];
|
||||
damage -= (damage * total_dotshielding / 100);
|
||||
|
||||
if (spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_PERCENT]) {
|
||||
slot = spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_BUFFSLOT];
|
||||
@@ -3330,8 +3349,9 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
else
|
||||
{
|
||||
// Reduce damage by the Spell Shielding first so that the runes don't take the raw damage.
|
||||
damage -= (damage * itembonuses.SpellShield / 100);
|
||||
|
||||
int total_spellshielding = itembonuses.SpellShield + itembonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_PERCENT] + aabonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_PERCENT];
|
||||
damage -= (damage * total_spellshielding / 100);
|
||||
|
||||
//Only mitigate if damage is above the minimium specified.
|
||||
if (spellbonuses.SpellThresholdGuard[SBIndex::THRESHOLDGUARD_MITIGATION_PERCENT]) {
|
||||
slot = spellbonuses.SpellThresholdGuard[SBIndex::THRESHOLDGUARD_BUFFSLOT];
|
||||
@@ -3469,7 +3489,6 @@ bool Mob::HasDefensiveProcs() const
|
||||
|
||||
bool Mob::HasSkillProcs() const
|
||||
{
|
||||
|
||||
for (int i = 0; i < MAX_SKILL_PROCS; i++) {
|
||||
if (spellbonuses.SkillProc[i] || itembonuses.SkillProc[i] || aabonuses.SkillProc[i])
|
||||
return true;
|
||||
@@ -3683,6 +3702,10 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
|
||||
}
|
||||
}
|
||||
|
||||
if (GetTempPetCount()) {
|
||||
entity_list.AddTempPetsToHateListOnOwnerDamage(this, attacker, spell_id);
|
||||
}
|
||||
|
||||
//see if any runes want to reduce this damage
|
||||
if (spell_id == SPELL_UNKNOWN) {
|
||||
damage = ReduceDamage(damage);
|
||||
@@ -4162,12 +4185,12 @@ void Mob::TryDefensiveProc(Mob *on, uint16 hand) {
|
||||
//Spell Procs and Quest added procs
|
||||
for (int i = 0; i < MAX_PROCS; i++) {
|
||||
if (IsValidSpell(DefensiveProcs[i].spellID)) {
|
||||
if (!IsProcLimitTimerActive(DefensiveProcs[i].base_spellID, DefensiveProcs[i].proc_reuse_time, SE_DefensiveProc)) {
|
||||
if (!IsProcLimitTimerActive(DefensiveProcs[i].base_spellID, DefensiveProcs[i].proc_reuse_time, ProcType::DEFENSIVE_PROC)) {
|
||||
float chance = ProcChance * (static_cast<float>(DefensiveProcs[i].chance) / 100.0f);
|
||||
if (zone->random.Roll(chance)) {
|
||||
ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on);
|
||||
CheckNumHitsRemaining(NumHit::DefensiveSpellProcs, 0, DefensiveProcs[i].base_spellID);
|
||||
SetProcLimitTimer(DefensiveProcs[i].base_spellID, DefensiveProcs[i].proc_reuse_time, SE_DefensiveProc);
|
||||
SetProcLimitTimer(DefensiveProcs[i].base_spellID, DefensiveProcs[i].proc_reuse_time, ProcType::DEFENSIVE_PROC);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4176,17 +4199,17 @@ void Mob::TryDefensiveProc(Mob *on, uint16 hand) {
|
||||
//AA Procs
|
||||
if (IsClient()){
|
||||
for (int i = 0; i < MAX_AA_PROCS; i += 4) {
|
||||
int32 aa_rank_id = aabonuses.DefensiveProc[i];
|
||||
int32 aa_spell_id = aabonuses.DefensiveProc[i + 1];
|
||||
int32 aa_proc_chance = 100 + aabonuses.DefensiveProc[i + 2];
|
||||
uint32 aa_proc_reuse_timer = aabonuses.DefensiveProc[i + 3];
|
||||
int32 aa_rank_id = aabonuses.DefensiveProc[i + +SBIndex::COMBAT_PROC_ORIGIN_ID];
|
||||
int32 aa_spell_id = aabonuses.DefensiveProc[i + SBIndex::COMBAT_PROC_SPELL_ID];
|
||||
int32 aa_proc_chance = 100 + aabonuses.DefensiveProc[i + SBIndex::COMBAT_PROC_RATE_MOD];
|
||||
uint32 aa_proc_reuse_timer = aabonuses.DefensiveProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER];
|
||||
|
||||
if (aa_rank_id) {
|
||||
if (!IsProcLimitTimerActive(-aa_rank_id, aa_proc_reuse_timer, SE_DefensiveProc)) {
|
||||
if (!IsProcLimitTimerActive(-aa_rank_id, aa_proc_reuse_timer, ProcType::DEFENSIVE_PROC)) {
|
||||
float chance = ProcChance * (static_cast<float>(aa_proc_chance) / 100.0f);
|
||||
if (zone->random.Roll(chance) && IsValidSpell(aa_spell_id)) {
|
||||
ExecWeaponProc(nullptr, aa_spell_id, on);
|
||||
SetProcLimitTimer(-aa_rank_id, aa_proc_reuse_timer, SE_DefensiveProc);
|
||||
SetProcLimitTimer(-aa_rank_id, aa_proc_reuse_timer, ProcType::DEFENSIVE_PROC);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4195,7 +4218,8 @@ void Mob::TryDefensiveProc(Mob *on, uint16 hand) {
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::TryWeaponProc(const EQ::ItemInstance* weapon_g, Mob *on, uint16 hand) {
|
||||
void Mob::TryCombatProcs(const EQ::ItemInstance* weapon_g, Mob *on, uint16 hand, const EQ::ItemData* weapon_data) {
|
||||
|
||||
if (!on) {
|
||||
SetTarget(nullptr);
|
||||
LogError("A null Mob object was passed to Mob::TryWeaponProc for evaluation!");
|
||||
@@ -4212,6 +4236,13 @@ void Mob::TryWeaponProc(const EQ::ItemInstance* weapon_g, Mob *on, uint16 hand)
|
||||
return;
|
||||
}
|
||||
|
||||
//used for special case when checking last ammo item on projectile hit.
|
||||
if (!weapon_g && weapon_data) {
|
||||
TryWeaponProc(nullptr, weapon_data, on, hand);
|
||||
TrySpellProc(nullptr, weapon_data, on, hand);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!weapon_g) {
|
||||
TrySpellProc(nullptr, (const EQ::ItemData*)nullptr, on);
|
||||
return;
|
||||
@@ -4251,7 +4282,7 @@ void Mob::TryWeaponProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon
|
||||
// Try innate proc on weapon
|
||||
// We can proc once here, either weapon or one aug
|
||||
bool proced = false; // silly bool to prevent augs from going if weapon does
|
||||
skillinuse = GetSkillByItemType(weapon->ItemType);
|
||||
|
||||
if (weapon->Proc.Type == EQ::item::ItemEffectCombatProc && IsValidSpell(weapon->Proc.Effect)) {
|
||||
float WPC = ProcChance * (100.0f + // Proc chance for this weapon
|
||||
static_cast<float>(weapon->ProcRate)) / 100.0f;
|
||||
@@ -4328,8 +4359,16 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon,
|
||||
float ProcChance = 0.0f;
|
||||
ProcChance = GetProcChances(ProcBonus, hand);
|
||||
|
||||
if (hand == EQ::invslot::slotSecondary)
|
||||
bool passed_skill_limit_check = true;
|
||||
EQ::skills::SkillType skillinuse = EQ::skills::SkillHandtoHand;
|
||||
|
||||
if (weapon){
|
||||
skillinuse = GetSkillByItemType(weapon->ItemType);
|
||||
}
|
||||
|
||||
if (hand == EQ::invslot::slotSecondary) {
|
||||
ProcChance /= 2;
|
||||
}
|
||||
|
||||
bool rangedattk = false;
|
||||
if (weapon && hand == EQ::invslot::slotRange) {
|
||||
@@ -4341,8 +4380,9 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon,
|
||||
}
|
||||
}
|
||||
|
||||
if (!weapon && hand == EQ::invslot::slotRange && GetSpecialAbility(SPECATK_RANGED_ATK))
|
||||
if (!weapon && hand == EQ::invslot::slotRange && GetSpecialAbility(SPECATK_RANGED_ATK)) {
|
||||
rangedattk = true;
|
||||
}
|
||||
|
||||
int16 poison_slot=-1;
|
||||
|
||||
@@ -4351,8 +4391,9 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon,
|
||||
continue; // If pets ever can proc from off hand, this will need to change
|
||||
|
||||
if (SpellProcs[i].base_spellID == POISON_PROC &&
|
||||
(!weapon || weapon->ItemType != EQ::item::ItemType1HPiercing))
|
||||
(!weapon || weapon->ItemType != EQ::item::ItemType1HPiercing)) {
|
||||
continue; // Old school poison will only proc with 1HP equipped.
|
||||
}
|
||||
|
||||
// Not ranged
|
||||
if (!rangedattk) {
|
||||
@@ -4373,14 +4414,16 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon,
|
||||
poison_slot=i;
|
||||
continue; // Process the poison proc last per @mackal
|
||||
}
|
||||
|
||||
if (!IsProcLimitTimerActive(SpellProcs[i].base_spellID, SpellProcs[i].proc_reuse_time, SE_WeaponProc)) {
|
||||
|
||||
passed_skill_limit_check = PassLimitToSkill(skillinuse, SpellProcs[i].base_spellID, ProcType::MELEE_PROC);
|
||||
|
||||
if (passed_skill_limit_check && !IsProcLimitTimerActive(SpellProcs[i].base_spellID, SpellProcs[i].proc_reuse_time, ProcType::MELEE_PROC)) {
|
||||
float chance = ProcChance * (static_cast<float>(SpellProcs[i].chance) / 100.0f);
|
||||
if (zone->random.Roll(chance)) {
|
||||
LogCombat("Spell proc [{}] procing spell [{}] ([{}] percent chance)", i, SpellProcs[i].spellID, chance);
|
||||
SendBeginCast(SpellProcs[i].spellID, 0);
|
||||
ExecWeaponProc(nullptr, SpellProcs[i].spellID, on, SpellProcs[i].level_override);
|
||||
SetProcLimitTimer(SpellProcs[i].base_spellID, SpellProcs[i].proc_reuse_time, SE_WeaponProc);
|
||||
SetProcLimitTimer(SpellProcs[i].base_spellID, SpellProcs[i].proc_reuse_time, ProcType::MELEE_PROC);
|
||||
CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0, SpellProcs[i].base_spellID);
|
||||
}
|
||||
else {
|
||||
@@ -4393,13 +4436,15 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon,
|
||||
// ranged spell procs (buffs)
|
||||
if (RangedProcs[i].spellID != SPELL_UNKNOWN) {
|
||||
|
||||
if (!IsProcLimitTimerActive(RangedProcs[i].base_spellID, RangedProcs[i].proc_reuse_time, SE_RangedProc)) {
|
||||
passed_skill_limit_check = PassLimitToSkill(skillinuse, RangedProcs[i].base_spellID, ProcType::RANGED_PROC);
|
||||
|
||||
if (passed_skill_limit_check && !IsProcLimitTimerActive(RangedProcs[i].base_spellID, RangedProcs[i].proc_reuse_time, ProcType::RANGED_PROC)) {
|
||||
float chance = ProcChance * (static_cast<float>(RangedProcs[i].chance) / 100.0f);
|
||||
if (zone->random.Roll(chance)) {
|
||||
LogCombat("Ranged proc [{}] procing spell [{}] ([{}] percent chance)", i, RangedProcs[i].spellID, chance);
|
||||
ExecWeaponProc(nullptr, RangedProcs[i].spellID, on);
|
||||
CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0, RangedProcs[i].base_spellID);
|
||||
SetProcLimitTimer(RangedProcs[i].base_spellID, RangedProcs[i].proc_reuse_time, SE_RangedProc);
|
||||
SetProcLimitTimer(RangedProcs[i].base_spellID, RangedProcs[i].proc_reuse_time, ProcType::RANGED_PROC);
|
||||
}
|
||||
else {
|
||||
LogCombat("Ranged proc [{}] failed to proc [{}] ([{}] percent chance)", i, RangedProcs[i].spellID, chance);
|
||||
@@ -4409,7 +4454,7 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon,
|
||||
}
|
||||
}
|
||||
|
||||
//AA Procs
|
||||
//AA Melee and Ranged Procs
|
||||
if (IsClient()) {
|
||||
for (int i = 0; i < MAX_AA_PROCS; i += 4) {
|
||||
|
||||
@@ -4421,22 +4466,25 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon,
|
||||
|
||||
if (!rangedattk) {
|
||||
|
||||
aa_rank_id = aabonuses.SpellProc[i];
|
||||
aa_spell_id = aabonuses.SpellProc[i + 1];
|
||||
aa_proc_chance += aabonuses.SpellProc[i + 2];
|
||||
aa_proc_reuse_timer = aabonuses.SpellProc[i + 3];
|
||||
proc_type = SE_WeaponProc;
|
||||
aa_rank_id = aabonuses.SpellProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID];
|
||||
aa_spell_id = aabonuses.SpellProc[i + SBIndex::COMBAT_PROC_SPELL_ID];
|
||||
aa_proc_chance += aabonuses.SpellProc[i + SBIndex::COMBAT_PROC_RATE_MOD];
|
||||
aa_proc_reuse_timer = aabonuses.SpellProc[i + SBIndex::COMBAT_PROC_RATE_MOD];
|
||||
proc_type = ProcType::MELEE_PROC;
|
||||
}
|
||||
else {
|
||||
aa_rank_id = aabonuses.RangedProc[i];
|
||||
aa_spell_id = aabonuses.RangedProc[i + 1];
|
||||
aa_proc_chance += aabonuses.RangedProc[i + 2];
|
||||
aa_proc_reuse_timer = aabonuses.RangedProc[i + 3];
|
||||
proc_type = SE_RangedProc;
|
||||
aa_rank_id = aabonuses.RangedProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID];
|
||||
aa_spell_id = aabonuses.RangedProc[i + SBIndex::COMBAT_PROC_SPELL_ID];
|
||||
aa_proc_chance += aabonuses.RangedProc[i + SBIndex::COMBAT_PROC_RATE_MOD];
|
||||
aa_proc_reuse_timer = aabonuses.RangedProc[i + SBIndex::COMBAT_PROC_RATE_MOD];
|
||||
proc_type = ProcType::RANGED_PROC;
|
||||
}
|
||||
|
||||
if (aa_rank_id) {
|
||||
if (!IsProcLimitTimerActive(-aa_rank_id, aa_proc_reuse_timer, proc_type)) {
|
||||
|
||||
passed_skill_limit_check = PassLimitToSkill(skillinuse, 0, proc_type, aa_rank_id);
|
||||
|
||||
if (passed_skill_limit_check && !IsProcLimitTimerActive(-aa_rank_id, aa_proc_reuse_timer, proc_type)) {
|
||||
float chance = ProcChance * (static_cast<float>(aa_proc_chance) / 100.0f);
|
||||
if (zone->random.Roll(chance) && IsValidSpell(aa_spell_id)) {
|
||||
LogCombat("AA proc [{}] procing spell [{}] ([{}] percent chance)", aa_rank_id, aa_spell_id, chance);
|
||||
@@ -4466,14 +4514,15 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon,
|
||||
}
|
||||
}
|
||||
|
||||
if (HasSkillProcs() && hand != EQ::invslot::slotRange) { //We check ranged skill procs within the attack functions.
|
||||
uint16 skillinuse = 28;
|
||||
if (weapon)
|
||||
skillinuse = GetSkillByItemType(weapon->ItemType);
|
||||
TryCastOnSkillUse(on, skillinuse);
|
||||
|
||||
if (HasSkillProcs() && hand != EQ::invslot::slotRange) { //We check ranged skill procs within the attack functions.
|
||||
TrySkillProc(on, skillinuse, 0, false, hand);
|
||||
}
|
||||
|
||||
if (HasSkillProcSuccess() && hand != EQ::invslot::slotRange) { //We check ranged skill procs within the attack functions.
|
||||
TrySkillProc(on, skillinuse, 0, true, hand);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4736,8 +4785,13 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
|
||||
|
||||
bool Mob::TryFinishingBlow(Mob *defender, int &damage)
|
||||
{
|
||||
// base2 of FinishingBlowLvl is the HP limit (cur / max) * 1000, 10% is listed as 100
|
||||
if (defender && !defender->IsClient() && defender->GetHPRatio() < 10) {
|
||||
float hp_limit = 10.0f;
|
||||
auto fb_hp_limit = std::max({ aabonuses.FinishingBlowLvl[SBIndex::FINISHING_BLOW_LEVEL_HP_RATIO], spellbonuses.FinishingBlowLvl[SBIndex::FINISHING_BLOW_LEVEL_HP_RATIO], itembonuses.FinishingBlowLvl[SBIndex::FINISHING_BLOW_LEVEL_HP_RATIO] });
|
||||
|
||||
if (fb_hp_limit) {
|
||||
hp_limit = fb_hp_limit/10.0f;
|
||||
}
|
||||
if (defender && !defender->IsClient() && defender->GetHPRatio() < hp_limit) {
|
||||
|
||||
uint32 FB_Dmg =
|
||||
aabonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG] + spellbonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG] + itembonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG];
|
||||
@@ -4788,6 +4842,7 @@ void Mob::DoRiposte(Mob *defender)
|
||||
}
|
||||
|
||||
defender->Attack(this, EQ::invslot::slotPrimary, true);
|
||||
|
||||
if (HasDied())
|
||||
return;
|
||||
|
||||
@@ -5038,7 +5093,7 @@ void Mob::ApplyDamageTable(DamageHitInfo &hit)
|
||||
Log(Logs::Detail, Logs::Attack, "Damage table applied %d (max %d)", percent, damage_table.max_extra);
|
||||
}
|
||||
|
||||
void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, uint16 hand, bool IsDefensive)
|
||||
void Mob::TrySkillProc(Mob *on, EQ::skills::SkillType skill, uint16 ReuseTime, bool Success, uint16 hand, bool IsDefensive)
|
||||
{
|
||||
|
||||
if (!on) {
|
||||
@@ -5047,12 +5102,19 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
|
||||
return;
|
||||
}
|
||||
|
||||
if (!spellbonuses.LimitToSkill[skill] && !itembonuses.LimitToSkill[skill] && !aabonuses.LimitToSkill[skill])
|
||||
if (on->HasDied()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*Allow one proc from each (Spell/Item/AA)
|
||||
Kayen: Due to limited avialability of effects on live it is too difficult
|
||||
to confirm how they stack at this time, will adjust formula when more data is avialablle to test.*/
|
||||
if (!spellbonuses.LimitToSkill[skill] && !itembonuses.LimitToSkill[skill] && !aabonuses.LimitToSkill[skill]) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Allow one proc from each (Spell/Item/AA)
|
||||
Kayen: Due to limited avialability of effects on live it is too difficult
|
||||
to confirm how they stack at this time, will adjust formula when more data is avialablle to test.
|
||||
*/
|
||||
bool CanProc = true;
|
||||
|
||||
uint16 base_spell_id = 0;
|
||||
@@ -5067,22 +5129,24 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
|
||||
|
||||
if (spellbonuses.LimitToSkill[skill]) {
|
||||
|
||||
for (int e = 0; e < MAX_SKILL_PROCS; e++) {
|
||||
for (int i = 0; i < MAX_SKILL_PROCS; i++) {
|
||||
if (CanProc &&
|
||||
((!Success && spellbonuses.SkillProc[e] && IsValidSpell(spellbonuses.SkillProc[e]))
|
||||
|| (Success && spellbonuses.SkillProcSuccess[e] && IsValidSpell(spellbonuses.SkillProcSuccess[e])))) {
|
||||
((!Success && spellbonuses.SkillProc[i] && IsValidSpell(spellbonuses.SkillProc[i]))
|
||||
|| (Success && spellbonuses.SkillProcSuccess[i] && IsValidSpell(spellbonuses.SkillProcSuccess[i])))) {
|
||||
|
||||
if (Success)
|
||||
base_spell_id = spellbonuses.SkillProcSuccess[e];
|
||||
else
|
||||
base_spell_id = spellbonuses.SkillProc[e];
|
||||
if (Success) {
|
||||
base_spell_id = spellbonuses.SkillProcSuccess[i];
|
||||
}
|
||||
else {
|
||||
base_spell_id = spellbonuses.SkillProc[i];
|
||||
}
|
||||
|
||||
proc_spell_id = 0;
|
||||
ProcMod = 0;
|
||||
|
||||
for (int i = 0; i < EFFECT_COUNT; i++) {
|
||||
|
||||
if (spells[base_spell_id].effect_id[i] == SE_SkillProc || spells[base_spell_id].effect_id[i] == SE_SkillProcSuccess) {
|
||||
if (spells[base_spell_id].effect_id[i] == SE_SkillProcAttempt || spells[base_spell_id].effect_id[i] == SE_SkillProcSuccess) {
|
||||
proc_spell_id = spells[base_spell_id].base_value[i];
|
||||
ProcMod = static_cast<float>(spells[base_spell_id].limit_value[i]);
|
||||
}
|
||||
@@ -5093,8 +5157,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
|
||||
float final_chance = chance * (ProcMod / 100.0f);
|
||||
if (zone->random.Roll(final_chance)) {
|
||||
ExecWeaponProc(nullptr, proc_spell_id, on);
|
||||
CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0,
|
||||
base_spell_id);
|
||||
CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0, base_spell_id);
|
||||
CanProc = false;
|
||||
break;
|
||||
}
|
||||
@@ -5112,21 +5175,23 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
|
||||
|
||||
if (itembonuses.LimitToSkill[skill]) {
|
||||
CanProc = true;
|
||||
for (int e = 0; e < MAX_SKILL_PROCS; e++) {
|
||||
for (int i = 0; i < MAX_SKILL_PROCS; i++) {
|
||||
if (CanProc &&
|
||||
((!Success && itembonuses.SkillProc[e] && IsValidSpell(itembonuses.SkillProc[e]))
|
||||
|| (Success && itembonuses.SkillProcSuccess[e] && IsValidSpell(itembonuses.SkillProcSuccess[e])))) {
|
||||
((!Success && itembonuses.SkillProc[i] && IsValidSpell(itembonuses.SkillProc[i]))
|
||||
|| (Success && itembonuses.SkillProcSuccess[i] && IsValidSpell(itembonuses.SkillProcSuccess[i])))) {
|
||||
|
||||
if (Success)
|
||||
base_spell_id = itembonuses.SkillProcSuccess[e];
|
||||
else
|
||||
base_spell_id = itembonuses.SkillProc[e];
|
||||
if (Success) {
|
||||
base_spell_id = itembonuses.SkillProcSuccess[i];
|
||||
}
|
||||
else {
|
||||
base_spell_id = itembonuses.SkillProc[i];
|
||||
}
|
||||
|
||||
proc_spell_id = 0;
|
||||
ProcMod = 0;
|
||||
|
||||
for (int i = 0; i < EFFECT_COUNT; i++) {
|
||||
if (spells[base_spell_id].effect_id[i] == SE_SkillProc || spells[base_spell_id].effect_id[i] == SE_SkillProcSuccess) {
|
||||
if (spells[base_spell_id].effect_id[i] == SE_SkillProcAttempt || spells[base_spell_id].effect_id[i] == SE_SkillProcSuccess) {
|
||||
proc_spell_id = spells[base_spell_id].base_value[i];
|
||||
ProcMod = static_cast<float>(spells[base_spell_id].limit_value[i]);
|
||||
}
|
||||
@@ -5159,16 +5224,16 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
|
||||
int32 limit_value = 0;
|
||||
uint32 slot = 0;
|
||||
|
||||
for (int e = 0; e < MAX_SKILL_PROCS; e++) {
|
||||
for (int i = 0; i < MAX_SKILL_PROCS; i++) {
|
||||
if (CanProc &&
|
||||
((!Success && aabonuses.SkillProc[e])
|
||||
|| (Success && aabonuses.SkillProcSuccess[e]))) {
|
||||
((!Success && aabonuses.SkillProc[i])
|
||||
|| (Success && aabonuses.SkillProcSuccess[i]))) {
|
||||
int aaid = 0;
|
||||
|
||||
if (Success)
|
||||
base_spell_id = aabonuses.SkillProcSuccess[e];
|
||||
base_spell_id = aabonuses.SkillProcSuccess[i];
|
||||
else
|
||||
base_spell_id = aabonuses.SkillProc[e];
|
||||
base_spell_id = aabonuses.SkillProc[i];
|
||||
|
||||
proc_spell_id = 0;
|
||||
ProcMod = 0;
|
||||
@@ -5188,7 +5253,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
|
||||
limit_value = effect.limit_value;
|
||||
slot = effect.slot;
|
||||
|
||||
if (effect_id == SE_SkillProc || effect_id == SE_SkillProcSuccess) {
|
||||
if (effect_id == SE_SkillProcAttempt || effect_id == SE_SkillProcSuccess) {
|
||||
proc_spell_id = base_value;
|
||||
ProcMod = static_cast<float>(limit_value);
|
||||
}
|
||||
@@ -5223,16 +5288,65 @@ float Mob::GetSkillProcChances(uint16 ReuseTime, uint16 hand) {
|
||||
if (!ReuseTime && hand) {
|
||||
weapon_speed = GetWeaponSpeedbyHand(hand);
|
||||
ProcChance = static_cast<float>(weapon_speed) * (RuleR(Combat, AvgProcsPerMinute) / 60000.0f);
|
||||
if (hand == EQ::invslot::slotSecondary)
|
||||
if (hand == EQ::invslot::slotSecondary) {
|
||||
ProcChance /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
else {
|
||||
ProcChance = static_cast<float>(ReuseTime) * (RuleR(Combat, AvgProcsPerMinute) / 60000.0f);
|
||||
}
|
||||
|
||||
return ProcChance;
|
||||
}
|
||||
|
||||
void Mob::TryCastOnSkillUse(Mob *on, EQ::skills::SkillType skill) {
|
||||
|
||||
if (!spellbonuses.HasSkillAttackProc[skill] && !itembonuses.HasSkillAttackProc[skill] && !aabonuses.HasSkillAttackProc[skill]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!on) {
|
||||
SetTarget(nullptr);
|
||||
LogError("A null Mob object was passed to Mob::TryCastOnSkillUse for evaluation!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (on->HasDied()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (spellbonuses.HasSkillAttackProc[skill]) {
|
||||
for (int i = 0; i < MAX_CAST_ON_SKILL_USE; i += 3) {
|
||||
if (spellbonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID] && skill == spellbonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SKILL]) {
|
||||
if (IsValidSpell(spellbonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]) && zone->random.Int(1, 1000) <= spellbonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_CHANCE]) {
|
||||
SpellFinished(spellbonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID], on, EQ::spells::CastingSlot::Item, 0, -1, spells[spellbonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]].resist_difficulty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (itembonuses.HasSkillAttackProc[skill]) {
|
||||
for (int i = 0; i < MAX_CAST_ON_SKILL_USE; i += 3) {
|
||||
if (itembonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID] && skill == itembonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SKILL]) {
|
||||
if (IsValidSpell(itembonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]) && zone->random.Int(1, 1000) <= spellbonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_CHANCE]) {
|
||||
SpellFinished(itembonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID], on, EQ::spells::CastingSlot::Item, 0, -1, spells[itembonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]].resist_difficulty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aabonuses.HasSkillAttackProc[skill]) {
|
||||
for (int i = 0; i < MAX_CAST_ON_SKILL_USE; i += 3) {
|
||||
if (IsValidSpell(aabonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]) && aabonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID] && skill == aabonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SKILL]) {
|
||||
if (zone->random.Int(1, 1000) <= aabonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_CHANCE]) {
|
||||
SpellFinished(aabonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID], on, EQ::spells::CastingSlot::Item, 0, -1, spells[aabonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]].resist_difficulty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) {
|
||||
|
||||
/*Dev Quote 2010: http://forums.station.sony.com/eq/posts/list.m?topic_id=161443
|
||||
@@ -5247,28 +5361,31 @@ bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) {
|
||||
- Root break chance values obtained from live parses.
|
||||
*/
|
||||
|
||||
if (!attacker || !spellbonuses.Root[SBIndex::ROOT_EXISTS] || spellbonuses.Root[SBIndex::ROOT_BUFFSLOT] < 0)
|
||||
if (!attacker || !spellbonuses.Root[SBIndex::ROOT_EXISTS] || spellbonuses.Root[SBIndex::ROOT_BUFFSLOT] < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsDetrimentalSpell(buffs[spellbonuses.Root[SBIndex::ROOT_BUFFSLOT]].spellid) && spellbonuses.Root[SBIndex::ROOT_BUFFSLOT] != buffslot) {
|
||||
|
||||
if (IsDetrimentalSpell(spellbonuses.Root[SBIndex::ROOT_BUFFSLOT]) && spellbonuses.Root[SBIndex::ROOT_BUFFSLOT] != buffslot) {
|
||||
int BreakChance = RuleI(Spells, RootBreakFromSpells);
|
||||
|
||||
BreakChance -= BreakChance * buffs[spellbonuses.Root[SBIndex::ROOT_BUFFSLOT]].RootBreakChance / 100;
|
||||
int level_diff = attacker->GetLevel() - GetLevel();
|
||||
|
||||
//Use baseline if level difference <= 1 (ie. If target is (1) level less than you, or equal or greater level)
|
||||
|
||||
if (level_diff == 2)
|
||||
if (level_diff == 2) {
|
||||
BreakChance = (BreakChance * 80) / 100; //Decrease by 20%;
|
||||
|
||||
else if (level_diff >= 3 && level_diff <= 20)
|
||||
}
|
||||
else if (level_diff >= 3 && level_diff <= 20) {
|
||||
BreakChance = (BreakChance * 60) / 100; //Decrease by 40%;
|
||||
|
||||
else if (level_diff > 21)
|
||||
}
|
||||
else if (level_diff > 21) {
|
||||
BreakChance = (BreakChance * 20) / 100; //Decrease by 80%;
|
||||
}
|
||||
|
||||
if (BreakChance < 1)
|
||||
if (BreakChance < 1) {
|
||||
BreakChance = 1;
|
||||
}
|
||||
|
||||
if (zone->random.Roll(BreakChance)) {
|
||||
|
||||
@@ -5456,7 +5573,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
|
||||
|
||||
int pct_damage_reduction = defender->GetSkillDmgTaken(hit.skill, opts) + defender->GetPositionalDmgTaken(this);
|
||||
|
||||
hit.damage_done += (hit.damage_done * pct_damage_reduction / 100) + (defender->GetFcDamageAmtIncoming(this, 0, true, hit.skill)) + defender->GetPositionalDmgTakenAmt(this);
|
||||
hit.damage_done += (hit.damage_done * pct_damage_reduction / 100) + defender->GetPositionalDmgTakenAmt(this);
|
||||
|
||||
if (defender->GetShielderID()) {
|
||||
DoShieldDamageOnShielder(defender, hit.damage_done, hit.skill);
|
||||
|
||||
+117
-55
@@ -674,7 +674,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
|
||||
uint8 focus = IsFocusEffect(0, 0, true, effect);
|
||||
if (focus) {
|
||||
newbon->FocusEffects[focus] = static_cast<uint8>(effect);
|
||||
newbon->FocusEffects[focus] = effect;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1074,11 +1074,11 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
case SE_WeaponProc:
|
||||
case SE_AddMeleeProc:
|
||||
for (int i = 0; i < MAX_AA_PROCS; i += 4) {
|
||||
if (!newbon->SpellProc[i]) {
|
||||
newbon->SpellProc[i] = rank.id; //aa rank id
|
||||
newbon->SpellProc[i + 1] = base_value; //proc spell id
|
||||
newbon->SpellProc[i + 2] = limit_value; //proc rate modifer
|
||||
newbon->SpellProc[i + 3] = 0; //Lock out Timer
|
||||
if (!newbon->SpellProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID]) {
|
||||
newbon->SpellProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID] = rank.id; //aa rank id
|
||||
newbon->SpellProc[i + SBIndex::COMBAT_PROC_SPELL_ID] = base_value; //proc spell id
|
||||
newbon->SpellProc[i + SBIndex::COMBAT_PROC_RATE_MOD] = limit_value; //proc rate modifer
|
||||
newbon->SpellProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER] = 0; //Lock out Timer
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1086,11 +1086,11 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
|
||||
case SE_RangedProc:
|
||||
for (int i = 0; i < MAX_AA_PROCS; i += 4) {
|
||||
if (!newbon->RangedProc[i]) {
|
||||
newbon->RangedProc[i] = rank.id; //aa rank id
|
||||
newbon->RangedProc[i + 1] = base_value; //proc spell id
|
||||
newbon->RangedProc[i + 2] = limit_value; //proc rate modifer
|
||||
newbon->RangedProc[i + 3] = 0; //Lock out Timer
|
||||
if (!newbon->RangedProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID]) {
|
||||
newbon->RangedProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID] = rank.id; //aa rank id
|
||||
newbon->RangedProc[i + SBIndex::COMBAT_PROC_SPELL_ID] = base_value; //proc spell id
|
||||
newbon->RangedProc[i + SBIndex::COMBAT_PROC_RATE_MOD] = limit_value; //proc rate modifer
|
||||
newbon->RangedProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER] = 0; //Lock out Timer
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1098,11 +1098,11 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
|
||||
case SE_DefensiveProc:
|
||||
for (int i = 0; i < MAX_AA_PROCS; i += 4) {
|
||||
if (!newbon->DefensiveProc[i]) {
|
||||
newbon->DefensiveProc[i] = rank.id; //aa rank id
|
||||
newbon->DefensiveProc[i + 1] = base_value; //proc spell id
|
||||
newbon->DefensiveProc[i + 2] = limit_value; //proc rate modifer
|
||||
newbon->DefensiveProc[i + 3] = 0; //Lock out Timer
|
||||
if (!newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID]) {
|
||||
newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID] = rank.id; //aa rank id
|
||||
newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_SPELL_ID] = base_value; //proc spell id
|
||||
newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_RATE_MOD] = limit_value; //proc rate modifer
|
||||
newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER] = 0; //Lock out Timer
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1118,23 +1118,23 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
newbon->Proc_Timer_Modifier = true;
|
||||
|
||||
for (int i = 0; i < MAX_AA_PROCS; i += 4) {
|
||||
if (newbon->SpellProc[i] == rank.id) {
|
||||
if (!newbon->SpellProc[i + 3]) {
|
||||
newbon->SpellProc[i + 3] = limit_value;//Lock out Timer
|
||||
if (newbon->SpellProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID] == rank.id) {
|
||||
if (!newbon->SpellProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER]) {
|
||||
newbon->SpellProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER] = limit_value;//Lock out Timer
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (newbon->RangedProc[i] == rank.id) {
|
||||
if (!newbon->RangedProc[i + 3]) {
|
||||
newbon->RangedProc[i + 3] = limit_value;//Lock out Timer
|
||||
if (newbon->RangedProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID] == rank.id) {
|
||||
if (!newbon->RangedProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER]) {
|
||||
newbon->RangedProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER] = limit_value;//Lock out Timer
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (newbon->DefensiveProc[i] == rank.id) {
|
||||
if (!newbon->DefensiveProc[i + 3]) {
|
||||
newbon->DefensiveProc[i + 3] = limit_value;//Lock out Timer
|
||||
if (newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID] == rank.id) {
|
||||
if (!newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER]) {
|
||||
newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER] = limit_value;//Lock out Timer
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1207,11 +1207,18 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
}
|
||||
|
||||
case SE_SkillAttackProc: {
|
||||
// You can only have one of these per client. [AA Dragon Punch]
|
||||
newbon->SkillAttackProc[SBIndex::SKILLPROC_CHANCE] = base_value; // Chance base 1000 = 100% proc rate
|
||||
newbon->SkillAttackProc[SBIndex::SKILLPROC_SKILL] = limit_value; // Skill to Proc Off
|
||||
newbon->SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID] = rank.spell; // spell to proc
|
||||
break;
|
||||
for (int i = 0; i < MAX_CAST_ON_SKILL_USE; i += 3) {
|
||||
if (!newbon->SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]) { // spell id
|
||||
newbon->SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID] = rank.spell; // spell to proc
|
||||
newbon->SkillAttackProc[i + SBIndex::SKILLATK_PROC_CHANCE] = base_value; // Chance base 1000 = 100% proc rate
|
||||
newbon->SkillAttackProc[i + SBIndex::SKILLATK_PROC_SKILL] = limit_value; // Skill to Proc Offr
|
||||
|
||||
if (limit_value < EQ::skills::HIGHEST_SKILL) {
|
||||
newbon->HasSkillAttackProc[limit_value] = true; //check first before looking for any effects.
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case SE_DamageModifier: {
|
||||
@@ -1349,7 +1356,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
// base1 = level, base2 = ??? (Set to 200 in AA data, possible proc rate mod?)
|
||||
if (newbon->FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] < base_value) {
|
||||
newbon->FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = base_value;
|
||||
newbon->FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = limit_value;
|
||||
newbon->FinishingBlowLvl[SBIndex::FINISHING_BLOW_LEVEL_HP_RATIO] = limit_value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1453,20 +1460,28 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_Illusion:
|
||||
newbon->Illusion = true;
|
||||
break;
|
||||
|
||||
case SE_IllusionPersistence:
|
||||
newbon->IllusionPersistence = true;
|
||||
newbon->IllusionPersistence = base_value;
|
||||
break;
|
||||
|
||||
case SE_LimitToSkill: {
|
||||
|
||||
// Bad data or unsupported new skill
|
||||
if (limit_value > EQ::skills::HIGHEST_SKILL)
|
||||
if (base_value > EQ::skills::HIGHEST_SKILL) {
|
||||
break;
|
||||
if (base_value <= EQ::skills::HIGHEST_SKILL)
|
||||
}
|
||||
if (base_value <= EQ::skills::HIGHEST_SKILL) {
|
||||
newbon->LimitToSkill[base_value] = true;
|
||||
newbon->LimitToSkill[EQ::skills::HIGHEST_SKILL + 3] = true; //Used as a general exists check
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_SkillProc: {
|
||||
case SE_SkillProcAttempt: {
|
||||
for (int e = 0; e < MAX_SKILL_PROCS; e++) {
|
||||
if (newbon->SkillProc[e] && newbon->SkillProc[e] == rank.id)
|
||||
break; // Do not use the same aa id more than once.
|
||||
@@ -1560,8 +1575,10 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
break;
|
||||
|
||||
case SE_FeignedMinion:
|
||||
if (newbon->FeignedMinionChance < base_value)
|
||||
if (newbon->FeignedMinionChance < base_value) {
|
||||
newbon->FeignedMinionChance = base_value;
|
||||
}
|
||||
newbon->PetCommands[PET_FEIGN] = true;
|
||||
break;
|
||||
|
||||
case SE_AdditionalAura:
|
||||
@@ -1761,6 +1778,22 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
newbon->Amplification += base_value;
|
||||
break;
|
||||
|
||||
case SE_MitigateSpellDamage:
|
||||
{
|
||||
newbon->MitigateSpellRune[SBIndex::MITIGATION_RUNE_PERCENT] += base_value;
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_MitigateDotDamage:
|
||||
{
|
||||
newbon->MitigateDotRune[SBIndex::MITIGATION_RUNE_PERCENT] += base_value;
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_TrapCircumvention:
|
||||
newbon->TrapCircumvention += base_value;
|
||||
break;
|
||||
|
||||
// to do
|
||||
case SE_PetDiscipline:
|
||||
break;
|
||||
@@ -1772,9 +1805,6 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
break;
|
||||
case SE_NimbleEvasion:
|
||||
break;
|
||||
case SE_TrapCircumvention:
|
||||
break;
|
||||
|
||||
|
||||
// not handled here
|
||||
case SE_HastenedAASkill:
|
||||
@@ -1874,7 +1904,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
}
|
||||
}
|
||||
else {
|
||||
new_bonus->FocusEffects[focus] = static_cast<uint8>(spells[spell_id].effect_id[i]);
|
||||
new_bonus->FocusEffects[focus] = spells[spell_id].effect_id[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -3019,6 +3049,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
|
||||
case SE_MitigateSpellDamage:
|
||||
{
|
||||
if (WornType) {
|
||||
new_bonus->MitigateSpellRune[SBIndex::MITIGATION_RUNE_PERCENT] += effect_value;
|
||||
}
|
||||
|
||||
if (new_bonus->MitigateSpellRune[SBIndex::MITIGATION_RUNE_PERCENT] < effect_value){
|
||||
new_bonus->MitigateSpellRune[SBIndex::MITIGATION_RUNE_PERCENT] = effect_value;
|
||||
new_bonus->MitigateSpellRune[SBIndex::MITIGATION_RUNE_BUFFSLOT] = buffslot;
|
||||
@@ -3030,6 +3064,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
|
||||
case SE_MitigateDotDamage:
|
||||
{
|
||||
if (WornType) {
|
||||
new_bonus->MitigateDotRune[SBIndex::MITIGATION_RUNE_PERCENT] += effect_value;
|
||||
}
|
||||
|
||||
if (new_bonus->MitigateDotRune[SBIndex::MITIGATION_RUNE_PERCENT] < effect_value){
|
||||
new_bonus->MitigateDotRune[SBIndex::MITIGATION_RUNE_PERCENT] = effect_value;
|
||||
new_bonus->MitigateDotRune[SBIndex::MITIGATION_RUNE_BUFFSLOT] = buffslot;
|
||||
@@ -3482,10 +3520,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
|
||||
case SE_FinishingBlowLvl:
|
||||
{
|
||||
//base1 = level, base2 = ??? (Set to 200 in AA data, possible proc rate mod?)
|
||||
if (new_bonus->FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] < effect_value){
|
||||
new_bonus->FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value;
|
||||
new_bonus->FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = limit_value;
|
||||
new_bonus->FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value;
|
||||
new_bonus->FinishingBlowLvl[SBIndex::FINISHING_BLOW_LEVEL_HP_RATIO] = limit_value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -3508,21 +3545,27 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_Illusion:
|
||||
new_bonus->Illusion = spell_id;
|
||||
break;
|
||||
|
||||
case SE_IllusionPersistence:
|
||||
new_bonus->IllusionPersistence = true;
|
||||
new_bonus->IllusionPersistence = effect_value;
|
||||
break;
|
||||
|
||||
case SE_LimitToSkill:{
|
||||
// Bad data or unsupported new skill
|
||||
if (limit_value > EQ::skills::HIGHEST_SKILL)
|
||||
if (effect_value > EQ::skills::HIGHEST_SKILL) {
|
||||
break;
|
||||
}
|
||||
if (effect_value <= EQ::skills::HIGHEST_SKILL){
|
||||
new_bonus->LimitToSkill[effect_value] = true;
|
||||
new_bonus->LimitToSkill[EQ::skills::HIGHEST_SKILL + 3] = true; //Used as a general exists check
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_SkillProc:{
|
||||
case SE_SkillProcAttempt:{
|
||||
|
||||
for(int e = 0; e < MAX_SKILL_PROCS; e++)
|
||||
{
|
||||
@@ -3552,6 +3595,21 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_SkillAttackProc: {
|
||||
for (int i = 0; i < MAX_CAST_ON_SKILL_USE; i += 3) {
|
||||
if (!new_bonus->SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]) { // spell id
|
||||
new_bonus->SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID] = max_value; // spell to proc
|
||||
new_bonus->SkillAttackProc[i + SBIndex::SKILLATK_PROC_CHANCE] = effect_value; // Chance base 1000 = 100% proc rate
|
||||
new_bonus->SkillAttackProc[i + SBIndex::SKILLATK_PROC_SKILL] = limit_value; // Skill to Proc Offr
|
||||
|
||||
if (limit_value < EQ::skills::HIGHEST_SKILL) {
|
||||
new_bonus->HasSkillAttackProc[limit_value] = true; //check first before looking for any effects.
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case SE_PC_Pet_Rampage: {
|
||||
new_bonus->PC_Pet_Rampage[SBIndex::PET_RAMPAGE_CHANCE] += effect_value; //Chance to rampage
|
||||
if (new_bonus->PC_Pet_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] < limit_value)
|
||||
@@ -3774,6 +3832,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
new_bonus->CompleteHealBuffBlocker = true;
|
||||
break;
|
||||
|
||||
case SE_TrapCircumvention:
|
||||
new_bonus->TrapCircumvention += effect_value;
|
||||
break;
|
||||
|
||||
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
|
||||
if (IsAISpellEffect) {
|
||||
|
||||
@@ -4088,9 +4150,9 @@ uint8 Mob::IsFocusEffect(uint16 spell_id,int effect_index, bool AA,uint32 aa_eff
|
||||
case SE_Fc_ResistIncoming:
|
||||
focusFcResistIncoming;
|
||||
case SE_Fc_Amplify_Mod:
|
||||
focusFcResistIncoming;
|
||||
focusFcAmplifyMod;
|
||||
case SE_Fc_Amplify_Amt:
|
||||
focusFcResistIncoming;
|
||||
focusFcAmplifyAmt;
|
||||
case SE_SpellHateMod:
|
||||
return focusSpellHateMod;
|
||||
case SE_ReduceReuseTimer:
|
||||
@@ -5374,9 +5436,9 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
if (negate_spellbonus) { spellbonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.FinishingBlowLvl[SBIndex::FINISHING_BLOW_LEVEL_HP_RATIO] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.FinishingBlowLvl[SBIndex::FINISHING_BLOW_LEVEL_HP_RATIO] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.FinishingBlowLvl[SBIndex::FINISHING_BLOW_LEVEL_HP_RATIO] = effect_value; }
|
||||
break;
|
||||
|
||||
case SE_Sanctuary:
|
||||
@@ -5390,9 +5452,9 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
break;
|
||||
|
||||
case SE_IllusionPersistence:
|
||||
if (negate_spellbonus) { spellbonuses.IllusionPersistence = false; }
|
||||
if (negate_itembonus) { itembonuses.IllusionPersistence = false; }
|
||||
if (negate_aabonus) { aabonuses.IllusionPersistence = false; }
|
||||
if (negate_spellbonus) { spellbonuses.IllusionPersistence = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.IllusionPersistence = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.IllusionPersistence = effect_value; }
|
||||
break;
|
||||
|
||||
case SE_Attack_Accuracy_Max_Percent:
|
||||
@@ -5503,7 +5565,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
}
|
||||
}
|
||||
|
||||
case SE_SkillProc: {
|
||||
case SE_SkillProcAttempt: {
|
||||
for (int e = 0; e < MAX_SKILL_PROCS; e++)
|
||||
{
|
||||
if (negate_spellbonus) { spellbonuses.SkillProc[e] = effect_value; }
|
||||
|
||||
+13
-6
@@ -3248,7 +3248,7 @@ void Bot::AI_Process()
|
||||
TriggerDefensiveProcs(tar, EQ::invslot::slotPrimary, false);
|
||||
|
||||
TEST_COMBATANTS();
|
||||
TryWeaponProc(p_item, tar, EQ::invslot::slotPrimary);
|
||||
TryCombatProcs(p_item, tar, EQ::invslot::slotPrimary);
|
||||
|
||||
// bool tripleSuccess = false;
|
||||
|
||||
@@ -3337,7 +3337,7 @@ void Bot::AI_Process()
|
||||
Attack(tar, EQ::invslot::slotSecondary); // Single attack with offhand
|
||||
|
||||
TEST_COMBATANTS();
|
||||
TryWeaponProc(s_item, tar, EQ::invslot::slotSecondary);
|
||||
TryCombatProcs(s_item, tar, EQ::invslot::slotSecondary);
|
||||
|
||||
TEST_COMBATANTS();
|
||||
if (CanThisClassDoubleAttack() && CheckBotDoubleAttack()) {
|
||||
@@ -4906,7 +4906,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
|
||||
|
||||
my_hit.tohit = GetTotalToHit(my_hit.skill, hit_chance_bonus);
|
||||
|
||||
DoAttack(other, my_hit, opts);
|
||||
DoAttack(other, my_hit, opts, FromRiposte);
|
||||
|
||||
LogCombat("Final damage after all reductions: [{}]", my_hit.damage_done);
|
||||
} else {
|
||||
@@ -7349,7 +7349,7 @@ void Bot::GenerateSpecialAttacks() {
|
||||
|
||||
bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool& stopLogic) {
|
||||
if(GetClass() == BARD) {
|
||||
if(!ApplyNextBardPulse(bardsong, this, bardsong_slot))
|
||||
if(!ApplyBardPulse(bardsong, this, bardsong_slot))
|
||||
InterruptSpell(SONG_ENDS_ABRUPTLY, 0x121, bardsong);
|
||||
|
||||
stopLogic = true;
|
||||
@@ -9549,8 +9549,15 @@ bool Bot::UseDiscipline(uint32 spell_id, uint32 target) {
|
||||
if(spells[spell_id].timer_id > 0 && spells[spell_id].timer_id < MAX_DISCIPLINE_TIMERS)
|
||||
SetDisciplineRecastTimer(spells[spell_id].timer_id, spell.recast_time);
|
||||
} else {
|
||||
uint32 remain = (GetDisciplineRemainingTime(this, spells[spell_id].timer_id) / 1000);
|
||||
GetOwner()->Message(Chat::White, "%s can use this discipline in %d minutes %d seconds.", GetCleanName(), (remain / 60), (remain % 60));
|
||||
uint32 remaining_time = (GetDisciplineRemainingTime(this, spells[spell_id].timer_id) / 1000);
|
||||
GetOwner()->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} can use this discipline in {}.",
|
||||
GetCleanName(),
|
||||
ConvertSecondsToTime(remaining_time)
|
||||
).c_str()
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+60
-39
@@ -1652,47 +1652,68 @@ int bot_command_real_dispatch(Client *c, const char *message)
|
||||
|
||||
void bot_command_log_command(Client *c, const char *message)
|
||||
{
|
||||
int admin = c->Admin();
|
||||
int admin = c->Admin();
|
||||
|
||||
bool continueevents = false;
|
||||
switch (zone->loglevelvar) { //catch failsafe
|
||||
case 9: // log only LeadGM
|
||||
if ((admin >= 150) && (admin <200))
|
||||
switch (zone->loglevelvar){ //catch failsafe
|
||||
case 9: { // log only LeadGM
|
||||
if (
|
||||
admin >= AccountStatus::GMLeadAdmin &&
|
||||
admin < AccountStatus::GMMgmt
|
||||
) {
|
||||
continueevents = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 8: { // log only GM
|
||||
if (
|
||||
admin >= AccountStatus::GMAdmin &&
|
||||
admin < AccountStatus::GMLeadAdmin
|
||||
) {
|
||||
continueevents = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
if (admin >= AccountStatus::GMMgmt) {
|
||||
continueevents = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
if (admin >= AccountStatus::GMLeadAdmin) {
|
||||
continueevents = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
if (admin >= AccountStatus::GMAdmin) {
|
||||
continueevents = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
if (admin >= AccountStatus::QuestTroupe) {
|
||||
continueevents = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
if (admin >= AccountStatus::ApprenticeGuide) {
|
||||
continueevents = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
if (admin >= AccountStatus::Steward) {
|
||||
continueevents = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 7: {
|
||||
continueevents = true;
|
||||
break;
|
||||
case 8: // log only GM
|
||||
if ((admin >= 100) && (admin <150))
|
||||
continueevents = true;
|
||||
break;
|
||||
case 1:
|
||||
if ((admin >= 200))
|
||||
continueevents = true;
|
||||
break;
|
||||
case 2:
|
||||
if ((admin >= 150))
|
||||
continueevents = true;
|
||||
break;
|
||||
case 3:
|
||||
if ((admin >= 100))
|
||||
continueevents = true;
|
||||
break;
|
||||
case 4:
|
||||
if ((admin >= 80))
|
||||
continueevents = true;
|
||||
break;
|
||||
case 5:
|
||||
if ((admin >= 20))
|
||||
continueevents = true;
|
||||
break;
|
||||
case 6:
|
||||
if ((admin >= 10))
|
||||
continueevents = true;
|
||||
break;
|
||||
case 7:
|
||||
continueevents = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (continueevents)
|
||||
@@ -3382,7 +3403,7 @@ void bot_command_heal_rotation(Client *c, const Seperator *sep)
|
||||
return;
|
||||
|
||||
#if (EQDEBUG >= 12)
|
||||
while (c->Admin() >= 250) {
|
||||
while (c->Admin() >= AccountStatus::GMImpossible) {
|
||||
if (strcasecmp(sep->arg[1], "shone")) { break; }
|
||||
Bot* my_bot = ActionableBots::AsTarget_ByBot(c);
|
||||
if (!my_bot || !(my_bot->IsHealRotationMember())) { break; }
|
||||
|
||||
+236
-147
@@ -145,7 +145,6 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
global_channel_timer(1000),
|
||||
fishing_timer(8000),
|
||||
endupkeep_timer(1000),
|
||||
forget_timer(0),
|
||||
autosave_timer(RuleI(Character, AutosaveIntervalS) * 1000),
|
||||
client_scan_npc_aggro_timer(RuleI(Aggro, ClientAggroCheckIdleInterval)),
|
||||
client_zone_wide_full_position_update_timer(5 * 60 * 1000),
|
||||
@@ -154,6 +153,7 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
TaskPeriodic_Timer(RuleI(TaskSystem, PeriodicCheckTimer) * 1000),
|
||||
charm_update_timer(6000),
|
||||
rest_timer(1),
|
||||
pick_lock_timer(1000),
|
||||
charm_class_attacks_timer(3000),
|
||||
charm_cast_timer(3500),
|
||||
qglobal_purge_timer(30000),
|
||||
@@ -185,7 +185,6 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
character_id = 0;
|
||||
conn_state = NoPacketsReceived;
|
||||
client_data_loaded = false;
|
||||
feigned = false;
|
||||
berserk = false;
|
||||
dead = false;
|
||||
eqs = ieqs;
|
||||
@@ -200,7 +199,7 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
TrackingID = 0;
|
||||
WID = 0;
|
||||
account_id = 0;
|
||||
admin = 0;
|
||||
admin = AccountStatus::Player;
|
||||
lsaccountid = 0;
|
||||
guild_id = GUILD_NONE;
|
||||
guildrank = 0;
|
||||
@@ -270,6 +269,8 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
if (RuleI(World, PVPMinLevel) > 0 && level >= RuleI(World, PVPMinLevel) && m_pp.pvp == 0) SetPVP(true, false);
|
||||
dynamiczone_removal_timer.Disable();
|
||||
|
||||
heroforge_wearchange_timer.Disable();
|
||||
|
||||
//for good measure:
|
||||
memset(&m_pp, 0, sizeof(m_pp));
|
||||
memset(&m_epp, 0, sizeof(m_epp));
|
||||
@@ -1013,7 +1014,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
else
|
||||
return;
|
||||
}
|
||||
if(worldserver.IsOOCMuted() && admin < 100)
|
||||
if(worldserver.IsOOCMuted() && admin < AccountStatus::GMAdmin)
|
||||
{
|
||||
Message(0,"OOC has been muted. Try again later.");
|
||||
return;
|
||||
@@ -1052,7 +1053,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
}
|
||||
case ChatChannel_Broadcast: /* Broadcast */
|
||||
case ChatChannel_GMSAY: { /* GM Say */
|
||||
if (!(admin >= 80))
|
||||
if (!(admin >= AccountStatus::QuestTroupe))
|
||||
Message(0, "Error: Only GMs can use this channel");
|
||||
else if (!worldserver.SendChannelMessage(this, targetname, chan_num, 0, language, lang_skill, message))
|
||||
Message(0, "Error: World server disconnected");
|
||||
@@ -1230,7 +1231,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
}
|
||||
|
||||
void Client::ChannelMessageSend(const char* from, const char* to, uint8 chan_num, uint8 language, uint8 lang_skill, const char* message, ...) {
|
||||
if ((chan_num==11 && !(this->GetGM())) || (chan_num==10 && this->Admin()<80)) // dont need to send /pr & /petition to everybody
|
||||
if ((chan_num==11 && !(this->GetGM())) || (chan_num==10 && this->Admin() < AccountStatus::QuestTroupe)) // dont need to send /pr & /petition to everybody
|
||||
return;
|
||||
va_list argptr;
|
||||
char buffer[4096];
|
||||
@@ -1869,9 +1870,7 @@ void Client::CheckManaEndUpdate() {
|
||||
mana_change->stamina = current_endurance;
|
||||
mana_change->spell_id = casting_spell_id;
|
||||
mana_change->keepcasting = 1;
|
||||
mana_change->padding[0] = 0;
|
||||
mana_change->padding[1] = 0;
|
||||
mana_change->padding[2] = 0;
|
||||
mana_change->slot = -1;
|
||||
outapp->priority = 6;
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
@@ -2076,7 +2075,13 @@ bool Client::ChangeFirstName(const char* in_firstname, const char* gmname)
|
||||
void Client::SetGM(bool toggle) {
|
||||
m_pp.gm = toggle ? 1 : 0;
|
||||
m_inv.SetGMInventory((bool)m_pp.gm);
|
||||
Message(Chat::Red, "You are %s a GM.", m_pp.gm ? "now" : "no longer");
|
||||
Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"You are {} flagged as a GM.",
|
||||
m_pp.gm ? "now" : "no longer"
|
||||
).c_str()
|
||||
);
|
||||
SendAppearancePacket(AT_GM, m_pp.gm);
|
||||
Save();
|
||||
UpdateWho();
|
||||
@@ -2417,7 +2422,7 @@ bool Client::CheckIncreaseSkill(EQ::skills::SkillType skillid, Mob *against_who,
|
||||
return false;
|
||||
if (skillid > EQ::skills::HIGHEST_SKILL)
|
||||
return false;
|
||||
int skillval = GetRawSkill(skillid);
|
||||
int skillval = GetRawSkill(skillid);
|
||||
int maxskill = GetMaxSkillAfterSpecializationRules(skillid, MaxSkill(skillid));
|
||||
std::string export_string = fmt::format(
|
||||
"{} {}",
|
||||
@@ -2442,23 +2447,26 @@ bool Client::CheckIncreaseSkill(EQ::skills::SkillType skillid, Mob *against_who,
|
||||
// Make sure we're not already at skill cap
|
||||
if (skillval < maxskill)
|
||||
{
|
||||
// the higher your current skill level, the harder it is
|
||||
int32 Chance = 10 + chancemodi + ((252 - skillval) / 20);
|
||||
|
||||
Chance = (Chance * RuleI(Character, SkillUpModifier) / 100);
|
||||
|
||||
Chance = mod_increase_skill_chance(Chance, against_who);
|
||||
|
||||
if(Chance < 1)
|
||||
Chance = 1; // Make it always possible
|
||||
double Chance = 0;
|
||||
if (RuleI(Character, SkillUpMaximumChancePercentage) + chancemodi - RuleI(Character, SkillUpMinimumChancePercentage) <= RuleI(Character, SkillUpMinimumChancePercentage)) {
|
||||
Chance = RuleI(Character, SkillUpMinimumChancePercentage);
|
||||
}
|
||||
else {
|
||||
// f(x) = (max - min + modification) * .99^skillval + min
|
||||
// This results in a exponential decay where as you skill up, you lose a slight chance to skill up, ranging from your modified maximum to approaching your minimum
|
||||
// This result is increased by the existing SkillUpModifier rule
|
||||
double working_chance = (((RuleI(Character, SkillUpMaximumChancePercentage) - RuleI(Character, SkillUpMinimumChancePercentage) + chancemodi) * (pow(0.99, skillval))) + RuleI(Character, SkillUpMinimumChancePercentage));
|
||||
Chance = (working_chance * RuleI(Character, SkillUpModifier) / 100);
|
||||
Chance = mod_increase_skill_chance(Chance, against_who);
|
||||
}
|
||||
|
||||
if(zone->random.Real(0, 99) < Chance)
|
||||
{
|
||||
SetSkill(skillid, GetRawSkill(skillid) + 1);
|
||||
LogSkills("Skill [{}] at value [{}] successfully gain with [{}]% chance (mod [{}])", skillid, skillval, Chance, chancemodi);
|
||||
LogSkills("Skill [{}] at value [{}] successfully gain with [{}] chance (mod [{}])", skillid, skillval, Chance, chancemodi);
|
||||
return true;
|
||||
} else {
|
||||
LogSkills("Skill [{}] at value [{}] failed to gain with [{}]% chance (mod [{}])", skillid, skillval, Chance, chancemodi);
|
||||
LogSkills("Skill [{}] at value [{}] failed to gain with [{}] chance (mod [{}])", skillid, skillval, Chance, chancemodi);
|
||||
}
|
||||
} else {
|
||||
LogSkills("Skill [{}] at value [{}] cannot increase due to maxmum [{}]", skillid, skillval, maxskill);
|
||||
@@ -2613,10 +2621,11 @@ void Client::SetPVP(bool toggle, bool message) {
|
||||
m_pp.pvp = toggle ? 1 : 0;
|
||||
|
||||
if (message) {
|
||||
if(GetPVP())
|
||||
this->MessageString(Chat::Shout,PVP_ON);
|
||||
else
|
||||
Message(Chat::Red, "You no longer follow the ways of discord.");
|
||||
if(GetPVP()) {
|
||||
MessageString(Chat::Shout, PVP_ON);
|
||||
} else {
|
||||
Message(Chat::Shout, "You now follow the ways of Order.");
|
||||
}
|
||||
}
|
||||
|
||||
SendAppearancePacket(AT_PVP, GetPVP());
|
||||
@@ -2647,44 +2656,28 @@ void Client::GMKill() {
|
||||
}
|
||||
|
||||
bool Client::CheckAccess(int16 iDBLevel, int16 iDefaultLevel) {
|
||||
if ((admin >= iDBLevel) || (iDBLevel == 255 && admin >= iDefaultLevel))
|
||||
if ((admin >= iDBLevel) || (iDBLevel == AccountStatus::Max && admin >= iDefaultLevel))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void Client::MemorizeSpell(uint32 slot,uint32 spellid,uint32 scribing){
|
||||
void Client::MemorizeSpell(uint32 slot,uint32 spellid,uint32 scribing, uint32 reduction){
|
||||
if (slot < 0 || slot >= EQ::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize)
|
||||
return;
|
||||
if ((spellid < 3 || spellid > EQ::spells::DynamicLookup(ClientVersion(), GetGM())->SpellIdMax) && spellid != 0xFFFFFFFF)
|
||||
return;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_MemorizeSpell, sizeof(MemorizeSpell_Struct));
|
||||
MemorizeSpell_Struct* mss=(MemorizeSpell_Struct*)outapp->pBuffer;
|
||||
mss->scribing=scribing;
|
||||
mss->slot=slot;
|
||||
mss->spell_id=spellid;
|
||||
mss->reduction = reduction;
|
||||
outapp->priority = 5;
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Client::SetFeigned(bool in_feigned) {
|
||||
if (in_feigned)
|
||||
{
|
||||
if(RuleB(Character, FeignKillsPet))
|
||||
{
|
||||
SetPet(0);
|
||||
}
|
||||
SetHorseId(0);
|
||||
entity_list.ClearFeignAggro(this);
|
||||
forget_timer.Start(FeignMemoryDuration);
|
||||
} else {
|
||||
forget_timer.Disable();
|
||||
}
|
||||
feigned=in_feigned;
|
||||
}
|
||||
|
||||
void Client::LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQ::ItemData* item, bool buying)
|
||||
{
|
||||
if(!player || !merchant || !item)
|
||||
@@ -3460,7 +3453,7 @@ uint8 Client::SlotConvert2(uint8 slot){
|
||||
void Client::Escape()
|
||||
{
|
||||
entity_list.RemoveFromTargets(this, true);
|
||||
SetInvisible(1);
|
||||
SetInvisible(Invisibility::Invisible);
|
||||
|
||||
MessageString(Chat::Skills, ESCAPE);
|
||||
}
|
||||
@@ -3471,7 +3464,7 @@ float Client::CalcPriceMod(Mob* other, bool reverse)
|
||||
if (other)
|
||||
{
|
||||
int factionlvl = GetFactionLevel(CharacterID(), other->CastToNPC()->GetNPCTypeID(), GetFactionRace(), GetClass(), GetDeity(), other->CastToNPC()->GetPrimaryFaction(), other);
|
||||
if (factionlvl >= FACTION_APPREHENSIVE) // Apprehensive or worse.
|
||||
if (factionlvl >= FACTION_APPREHENSIVELY) // Apprehensive or worse.
|
||||
{
|
||||
if (GetCHA() > 103)
|
||||
{
|
||||
@@ -3486,7 +3479,7 @@ float Client::CalcPriceMod(Mob* other, bool reverse)
|
||||
chaformula = 1*(RuleI(Merchant, PricePenaltyPct));
|
||||
}
|
||||
}
|
||||
if (factionlvl <= FACTION_INDIFFERENT) // Indifferent or better.
|
||||
if (factionlvl <= FACTION_INDIFFERENTLY) // Indifferent or better.
|
||||
{
|
||||
if (GetCHA() > 75)
|
||||
{
|
||||
@@ -5321,31 +5314,72 @@ uint32 Client::GetStartZone()
|
||||
|
||||
void Client::ShowSkillsWindow()
|
||||
{
|
||||
const char *WindowTitle = "Skills";
|
||||
std::string WindowText;
|
||||
std::map<EQ::skills::SkillType, std::string> Skills = EQ::skills::GetSkillTypeMap();
|
||||
std::string popup_text;
|
||||
std::map<EQ::skills::SkillType, std::string> skills_map = EQ::skills::GetSkillTypeMap();
|
||||
|
||||
if (ClientVersion() < EQ::versions::ClientVersion::RoF2)
|
||||
Skills[EQ::skills::Skill1HPiercing] = "Piercing";
|
||||
|
||||
// print out all available skills
|
||||
for (auto skills_iter : Skills) {
|
||||
if (skills_iter.first == EQ::skills::Skill2HPiercing && ClientVersion() < EQ::versions::ClientVersion::RoF2)
|
||||
continue;
|
||||
if (!GetSkill(skills_iter.first) && !MaxSkill(skills_iter.first))
|
||||
continue;
|
||||
|
||||
WindowText += skills_iter.second;
|
||||
// line up the values
|
||||
WindowText += " ";
|
||||
WindowText += itoa(this->GetSkill(skills_iter.first));
|
||||
if (MaxSkill(skills_iter.first) > 0) {
|
||||
WindowText += "/";
|
||||
WindowText += itoa(this->GetMaxSkillAfterSpecializationRules(skills_iter.first, this->MaxSkill(skills_iter.first)));
|
||||
}
|
||||
WindowText += "<br>";
|
||||
if (ClientVersion() < EQ::versions::ClientVersion::RoF2) {
|
||||
skills_map[EQ::skills::Skill1HPiercing] = "Piercing";
|
||||
}
|
||||
this->SendPopupToClient(WindowTitle, WindowText.c_str());
|
||||
|
||||
// Table Start
|
||||
popup_text += "<table>";
|
||||
|
||||
for (const auto& skill : skills_map) {
|
||||
auto skill_id = skill.first;
|
||||
auto skill_name = skill.second;
|
||||
auto can_have_skill = CanHaveSkill(skill_id);
|
||||
auto current_skill = GetSkill(skill_id);
|
||||
auto max_skill = MaxSkill(skill_id);
|
||||
auto skill_maxed = current_skill >= max_skill;
|
||||
if (
|
||||
skill_id == EQ::skills::Skill2HPiercing &&
|
||||
ClientVersion() < EQ::versions::ClientVersion::RoF2
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
!can_have_skill ||
|
||||
!current_skill ||
|
||||
!max_skill
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Row Start
|
||||
popup_text += "<tr>";
|
||||
|
||||
// Skill Name
|
||||
popup_text += fmt::format(
|
||||
"<td>{}</td>",
|
||||
skill_name
|
||||
);
|
||||
|
||||
// Current Skill Level out of Max Skill Level or a Check Mark for Maxed
|
||||
popup_text += fmt::format(
|
||||
"<td>{}</td>",
|
||||
(
|
||||
skill_maxed ?
|
||||
"<c \"#00FF00\">✔</c>" :
|
||||
fmt::format(
|
||||
"{}/{}",
|
||||
current_skill,
|
||||
max_skill
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Row End
|
||||
popup_text += "</tr>";
|
||||
}
|
||||
|
||||
// Table End
|
||||
popup_text += "</table>";
|
||||
|
||||
SendPopupToClient(
|
||||
"Skills",
|
||||
popup_text.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
void Client::Signal(uint32 data)
|
||||
@@ -6228,36 +6262,44 @@ void Client::LocateCorpse()
|
||||
|
||||
void Client::NPCSpawn(NPC *target_npc, const char *identifier, uint32 extra)
|
||||
{
|
||||
if (!target_npc || !identifier)
|
||||
if (!target_npc || !identifier) {
|
||||
return;
|
||||
|
||||
std::string id = identifier;
|
||||
for(int i = 0; i < id.length(); ++i)
|
||||
{
|
||||
id[i] = tolower(id[i]);
|
||||
}
|
||||
|
||||
if (id == "create") {
|
||||
// extra tries to create the npc_type ID within the range for the current zone (zone_id * 1000)
|
||||
content_db.NPCSpawnDB(0, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC(), extra);
|
||||
}
|
||||
else if (id == "add") {
|
||||
// extra sets the respawn timer for add
|
||||
content_db.NPCSpawnDB(1, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC(), extra);
|
||||
}
|
||||
else if (id == "update") {
|
||||
content_db.NPCSpawnDB(2, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC());
|
||||
}
|
||||
else if (id == "remove") {
|
||||
content_db.NPCSpawnDB(3, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC());
|
||||
target_npc->Depop(false);
|
||||
}
|
||||
else if (id == "delete") {
|
||||
content_db.NPCSpawnDB(4, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC());
|
||||
target_npc->Depop(false);
|
||||
}
|
||||
else {
|
||||
return;
|
||||
std::string spawn_type = str_tolower(identifier);
|
||||
bool is_add = spawn_type.find("add") != std::string::npos;
|
||||
bool is_create = spawn_type.find("create") != std::string::npos;
|
||||
bool is_delete = spawn_type.find("delete") != std::string::npos;
|
||||
bool is_remove = spawn_type.find("remove") != std::string::npos;
|
||||
bool is_update = spawn_type.find("update") != std::string::npos;
|
||||
if (is_add || is_create) {
|
||||
// Add: extra tries to create the NPC ID within the range for the current Zone (Zone ID * 1000)
|
||||
// Create: extra sets the Respawn Timer for add
|
||||
content_db.NPCSpawnDB(
|
||||
is_add ? NPCSpawnTypes::AddNewSpawngroup : NPCSpawnTypes::CreateNewSpawn,
|
||||
zone->GetShortName(),
|
||||
zone->GetInstanceVersion(),
|
||||
this,
|
||||
target_npc->CastToNPC(),
|
||||
extra
|
||||
);
|
||||
} else if (is_delete || is_remove || is_update) {
|
||||
uint8 spawn_update_type = (
|
||||
is_delete ?
|
||||
NPCSpawnTypes::DeleteSpawn :
|
||||
(
|
||||
is_remove ?
|
||||
NPCSpawnTypes::RemoveSpawn :
|
||||
NPCSpawnTypes::UpdateAppearance
|
||||
)
|
||||
);
|
||||
content_db.NPCSpawnDB(
|
||||
spawn_update_type,
|
||||
zone->GetShortName(),
|
||||
zone->GetInstanceVersion(),
|
||||
this,
|
||||
target_npc->CastToNPC()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6443,11 +6485,12 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid
|
||||
swarm_pet_npc->StartSwarmTimer(pet_duration * 1000);
|
||||
|
||||
swarm_pet_npc->GetSwarmInfo()->owner_id = GetID();
|
||||
swarm_pet_npc->SetFollowID(GetID());
|
||||
|
||||
// Give the pets alittle more agro than the caster and then agro them on the target
|
||||
target->AddToHateList(swarm_pet_npc, (target->GetHateAmount(this) + 100), (target->GetDamageAmount(this) + 100));
|
||||
swarm_pet_npc->AddToHateList(target, 1000, 1000);
|
||||
swarm_pet_npc->GetSwarmInfo()->target = target->GetID();
|
||||
swarm_pet_npc->GetSwarmInfo()->target = 0;
|
||||
|
||||
//we allocated a new NPC type object, give the NPC ownership of that memory
|
||||
if(npc_dup != nullptr)
|
||||
@@ -6882,7 +6925,7 @@ void Client::SendStatsWindow(Client* client, bool use_window)
|
||||
for (auto iter = item_faction_bonuses.begin(); iter != item_faction_bonuses.end(); ++iter) {
|
||||
memset(&faction_buf, 0, sizeof(faction_buf));
|
||||
|
||||
if(!content_db.GetFactionName((int32)((*iter).first), faction_buf, sizeof(faction_buf)))
|
||||
if(!content_db.GetFactionName((int)((*iter).first), faction_buf, sizeof(faction_buf)))
|
||||
strcpy(faction_buf, "Not in DB");
|
||||
|
||||
if((*iter).second > 0) {
|
||||
@@ -6999,7 +7042,7 @@ void Client::SendStatsWindow(Client* client, bool use_window)
|
||||
Extra_Info:
|
||||
|
||||
client->Message(Chat::White, " BaseRace: %i Gender: %i BaseGender: %i Texture: %i HelmTexture: %i", GetBaseRace(), GetGender(), GetBaseGender(), GetTexture(), GetHelmTexture());
|
||||
if (client->Admin() >= 100) {
|
||||
if (client->Admin() >= AccountStatus::GMAdmin) {
|
||||
client->Message(Chat::White, " CharID: %i EntityID: %i PetID: %i OwnerID: %i AIControlled: %i Targetted: %i", CharacterID(), GetID(), GetPetID(), GetOwnerID(), IsAIControlled(), targeted);
|
||||
}
|
||||
}
|
||||
@@ -7018,23 +7061,16 @@ void Client::SendAltCurrencies() {
|
||||
altc->opcode = ALT_CURRENCY_OP_POPULATE;
|
||||
altc->count = count;
|
||||
|
||||
uint32 i = 0;
|
||||
auto iter = zone->AlternateCurrencies.begin();
|
||||
while(iter != zone->AlternateCurrencies.end()) {
|
||||
const EQ::ItemData* item = database.GetItem((*iter).item_id);
|
||||
altc->entries[i].currency_number = (*iter).id;
|
||||
altc->entries[i].unknown00 = 1;
|
||||
altc->entries[i].currency_number2 = (*iter).id;
|
||||
altc->entries[i].item_id = (*iter).item_id;
|
||||
if(item) {
|
||||
altc->entries[i].item_icon = item->Icon;
|
||||
altc->entries[i].stack_size = item->StackSize;
|
||||
} else {
|
||||
altc->entries[i].item_icon = 1000;
|
||||
altc->entries[i].stack_size = 1000;
|
||||
}
|
||||
i++;
|
||||
++iter;
|
||||
uint32 currency_id = 0;
|
||||
for (const auto& alternate_currency : zone->AlternateCurrencies) {
|
||||
const EQ::ItemData* item = database.GetItem(alternate_currency.item_id);
|
||||
altc->entries[currency_id].currency_number = alternate_currency.id;
|
||||
altc->entries[currency_id].unknown00 = 1;
|
||||
altc->entries[currency_id].currency_number2 = alternate_currency.id;
|
||||
altc->entries[currency_id].item_id = alternate_currency.item_id;
|
||||
altc->entries[currency_id].item_icon = item ? item->Icon : 1000;
|
||||
altc->entries[currency_id].stack_size = item ? item->StackSize : 1000;
|
||||
currency_id++;
|
||||
}
|
||||
|
||||
FastQueuePacket(&outapp);
|
||||
@@ -7089,10 +7125,8 @@ void Client::AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 me
|
||||
|
||||
void Client::SendAlternateCurrencyValues()
|
||||
{
|
||||
auto iter = zone->AlternateCurrencies.begin();
|
||||
while(iter != zone->AlternateCurrencies.end()) {
|
||||
SendAlternateCurrencyValue((*iter).id, false);
|
||||
++iter;
|
||||
for (const auto& alternate_currency : zone->AlternateCurrencies) {
|
||||
SendAlternateCurrencyValue(alternate_currency.id, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7396,7 +7430,7 @@ void Client::ProcessXTargetAutoHaters()
|
||||
std::queue<int> empty_slots;
|
||||
for (int i = 0; i < GetMaxXTargets(); ++i) {
|
||||
if (XTargets[i].Type != Auto)
|
||||
continue;
|
||||
continue;
|
||||
|
||||
if (XTargets[i].ID != 0 && !GetXTargetAutoMgr()->contains_mob(XTargets[i].ID)) {
|
||||
XTargets[i].ID = 0;
|
||||
@@ -7435,6 +7469,7 @@ void Client::ProcessXTargetAutoHaters()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_dirtyautohaters = false;
|
||||
SendXTargetUpdates();
|
||||
}
|
||||
@@ -7801,7 +7836,7 @@ FACTION_VALUE Client::GetReverseFactionCon(Mob* iOther) {
|
||||
return GetSpecialFactionCon(iOther);
|
||||
|
||||
if (iOther->GetPrimaryFaction() == 0)
|
||||
return FACTION_INDIFFERENT;
|
||||
return FACTION_INDIFFERENTLY;
|
||||
|
||||
return GetFactionLevel(CharacterID(), 0, GetFactionRace(), GetClass(), GetDeity(), iOther->GetPrimaryFaction(), iOther);
|
||||
}
|
||||
@@ -7824,25 +7859,25 @@ FACTION_VALUE Client::GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 p_ra
|
||||
{
|
||||
if (pFaction < 0)
|
||||
return GetSpecialFactionCon(tnpc);
|
||||
FACTION_VALUE fac = FACTION_INDIFFERENT;
|
||||
FACTION_VALUE fac = FACTION_INDIFFERENTLY;
|
||||
int32 tmpFactionValue;
|
||||
FactionMods fmods;
|
||||
|
||||
// few optimizations
|
||||
if (GetFeigned())
|
||||
return FACTION_INDIFFERENT;
|
||||
return FACTION_INDIFFERENTLY;
|
||||
if(!zone->CanDoCombat())
|
||||
return FACTION_INDIFFERENT;
|
||||
return FACTION_INDIFFERENTLY;
|
||||
if (invisible_undead && tnpc && !tnpc->SeeInvisibleUndead())
|
||||
return FACTION_INDIFFERENT;
|
||||
return FACTION_INDIFFERENTLY;
|
||||
if (IsInvisible(tnpc))
|
||||
return FACTION_INDIFFERENT;
|
||||
return FACTION_INDIFFERENTLY;
|
||||
if (tnpc && tnpc->GetOwnerID() != 0) // pets con amiably to owner and indiff to rest
|
||||
{
|
||||
if (char_id == tnpc->GetOwner()->CastToClient()->CharacterID())
|
||||
return FACTION_AMIABLE;
|
||||
return FACTION_AMIABLY;
|
||||
else
|
||||
return FACTION_INDIFFERENT;
|
||||
return FACTION_INDIFFERENTLY;
|
||||
}
|
||||
|
||||
//First get the NPC's Primary faction
|
||||
@@ -7862,15 +7897,15 @@ FACTION_VALUE Client::GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 p_ra
|
||||
}
|
||||
else
|
||||
{
|
||||
return(FACTION_INDIFFERENT);
|
||||
return(FACTION_INDIFFERENTLY);
|
||||
}
|
||||
|
||||
// merchant fix
|
||||
if (tnpc && tnpc->IsNPC() && tnpc->CastToNPC()->MerchantType && (fac == FACTION_THREATENLY || fac == FACTION_SCOWLS))
|
||||
fac = FACTION_DUBIOUS;
|
||||
if (tnpc && tnpc->IsNPC() && tnpc->CastToNPC()->MerchantType && (fac == FACTION_THREATENINGLY || fac == FACTION_SCOWLS))
|
||||
fac = FACTION_DUBIOUSLY;
|
||||
|
||||
if (tnpc != 0 && fac != FACTION_SCOWLS && tnpc->CastToNPC()->CheckAggro(this))
|
||||
fac = FACTION_THREATENLY;
|
||||
fac = FACTION_THREATENINGLY;
|
||||
|
||||
return fac;
|
||||
}
|
||||
@@ -8493,7 +8528,7 @@ void Client::Consume(const EQ::ItemData *item, uint8 type, int16 slot, bool auto
|
||||
|
||||
LogFood("Consuming food, points added to hunger_level: [{}] - current_hunger: [{}]", increase, m_pp.hunger_level);
|
||||
|
||||
DeleteItemInInventory(slot, 1, false);
|
||||
DeleteItemInInventory(slot, 1);
|
||||
|
||||
if (!auto_consume) // no message if the client consumed for us
|
||||
entity_list.MessageCloseString(this, true, 50, 0, EATING_MESSAGE, GetName(), item->Name);
|
||||
@@ -8508,7 +8543,7 @@ void Client::Consume(const EQ::ItemData *item, uint8 type, int16 slot, bool auto
|
||||
|
||||
m_pp.thirst_level += increase;
|
||||
|
||||
DeleteItemInInventory(slot, 1, false);
|
||||
DeleteItemInInventory(slot, 1);
|
||||
|
||||
LogFood("Consuming drink, points added to thirst_level: [{}] current_thirst: [{}]", increase, m_pp.thirst_level);
|
||||
|
||||
@@ -8558,14 +8593,25 @@ void Client::ExpeditionSay(const char *str, int ExpID) {
|
||||
return;
|
||||
|
||||
if(results.RowCount() == 0) {
|
||||
this->Message(Chat::Lime, "You say to the expedition, '%s'", str);
|
||||
Message(Chat::Lime, "You say to the expedition, '%s'", str);
|
||||
return;
|
||||
}
|
||||
|
||||
for(auto row = results.begin(); row != results.end(); ++row) {
|
||||
const char* charName = row[0];
|
||||
if(strcmp(charName, this->GetCleanName()) != 0)
|
||||
worldserver.SendEmoteMessage(charName, 0, 0, 14, "%s says to the expedition, '%s'", this->GetCleanName(), str);
|
||||
if(strcmp(charName, GetCleanName()) != 0) {
|
||||
worldserver.SendEmoteMessage(
|
||||
charName,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::Lime,
|
||||
fmt::format(
|
||||
"{} says to the expedition, '{}'",
|
||||
GetCleanName(),
|
||||
str
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
// ChannelList->CreateChannel(ChannelName, ChannelOwner, ChannelPassword, true, atoi(row[3]));
|
||||
}
|
||||
|
||||
@@ -8635,7 +8681,7 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
|
||||
|
||||
if (faction)
|
||||
{
|
||||
if (target && target->IsNPC())
|
||||
if (target && target->IsNPC() && !target->IsCharmed())
|
||||
{
|
||||
int32 nfl_id = target->CastToNPC()->GetNPCFactionID();
|
||||
SetFactionLevel(CharacterID(), nfl_id, GetBaseClass(), GetBaseRace(), GetDeity(), true);
|
||||
@@ -8671,7 +8717,7 @@ void Client::QuestReward(Mob* target, const QuestReward_Struct &reward, bool fac
|
||||
|
||||
if (faction)
|
||||
{
|
||||
if (target && target->IsNPC())
|
||||
if (target && target->IsNPC() && !target->IsCharmed())
|
||||
{
|
||||
int32 nfl_id = target->CastToNPC()->GetNPCFactionID();
|
||||
SetFactionLevel(CharacterID(), nfl_id, GetBaseClass(), GetBaseRace(), GetDeity(), true);
|
||||
@@ -9388,7 +9434,7 @@ void Client::CheckVirtualZoneLines()
|
||||
LogZonePoints(
|
||||
"Virtual Zone Box Sending player [{}] to [{}]",
|
||||
GetCleanName(),
|
||||
zone_store.GetZoneLongName(virtual_zone_point.target_zone_id)
|
||||
ZoneLongName(virtual_zone_point.target_zone_id)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -10266,7 +10312,7 @@ void Client::RemoveItem(uint32 item_id, uint32 quantity)
|
||||
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
|
||||
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
|
||||
};
|
||||
int removed_count = 0;
|
||||
int16 removed_count = 0;
|
||||
const size_t size = sizeof(slots) / sizeof(slots[0]);
|
||||
for (int slot_index = 0; slot_index < size; ++slot_index) {
|
||||
for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) {
|
||||
@@ -10276,13 +10322,13 @@ void Client::RemoveItem(uint32 item_id, uint32 quantity)
|
||||
|
||||
item = GetInv().GetItem(slot_id);
|
||||
if (item && item->GetID() == item_id) {
|
||||
int charges = item->IsStackable() ? item->GetCharges() : 0;
|
||||
int stack_size = std::max(charges, 1);
|
||||
int16 charges = item->IsStackable() ? item->GetCharges() : 0;
|
||||
int16 stack_size = std::max(charges, static_cast<int16>(1));
|
||||
if ((removed_count + stack_size) <= quantity) {
|
||||
removed_count += stack_size;
|
||||
DeleteItemInInventory(slot_id, charges, true);
|
||||
} else {
|
||||
int amount_left = (quantity - removed_count);
|
||||
int16 amount_left = (quantity - removed_count);
|
||||
if (amount_left > 0 && stack_size >= amount_left) {
|
||||
removed_count += amount_left;
|
||||
DeleteItemInInventory(slot_id, amount_left, true);
|
||||
@@ -10810,3 +10856,46 @@ uint16 Client::LearnDisciplines(uint8 min_level, uint8 max_level)
|
||||
|
||||
return learned_disciplines;
|
||||
}
|
||||
|
||||
uint16 Client::GetClassTrackingDistanceMultiplier(uint16 class_) {
|
||||
switch (class_) {
|
||||
case WARRIOR:
|
||||
return RuleI(Character, WarriorTrackingDistanceMultiplier);
|
||||
case CLERIC:
|
||||
return RuleI(Character, ClericTrackingDistanceMultiplier);
|
||||
case PALADIN:
|
||||
return RuleI(Character, PaladinTrackingDistanceMultiplier);
|
||||
case RANGER:
|
||||
return RuleI(Character, RangerTrackingDistanceMultiplier);
|
||||
case SHADOWKNIGHT:
|
||||
return RuleI(Character, ShadowKnightTrackingDistanceMultiplier);
|
||||
case DRUID:
|
||||
return RuleI(Character, DruidTrackingDistanceMultiplier);
|
||||
case MONK:
|
||||
return RuleI(Character, MonkTrackingDistanceMultiplier);
|
||||
case BARD:
|
||||
return RuleI(Character, BardTrackingDistanceMultiplier);
|
||||
case ROGUE:
|
||||
return RuleI(Character, RogueTrackingDistanceMultiplier);
|
||||
case SHAMAN:
|
||||
return RuleI(Character, ShamanTrackingDistanceMultiplier);
|
||||
case NECROMANCER:
|
||||
return RuleI(Character, NecromancerTrackingDistanceMultiplier);
|
||||
case WIZARD:
|
||||
return RuleI(Character, WizardTrackingDistanceMultiplier);
|
||||
case MAGICIAN:
|
||||
return RuleI(Character, MagicianTrackingDistanceMultiplier);
|
||||
case ENCHANTER:
|
||||
return RuleI(Character, EnchanterTrackingDistanceMultiplier);
|
||||
case BEASTLORD:
|
||||
return RuleI(Character, BeastlordTrackingDistanceMultiplier);
|
||||
case BERSERKER:
|
||||
return RuleI(Character, BerserkerTrackingDistanceMultiplier);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool Client::CanThisClassTrack() {
|
||||
return (GetClassTrackingDistanceMultiplier(GetClass()) > 0) ? true : false;
|
||||
}
|
||||
|
||||
+33
-14
@@ -301,8 +301,8 @@ public:
|
||||
uint16 FindTraderItem(int32 SerialNumber,uint16 Quantity);
|
||||
uint32 FindTraderItemSerialNumber(int32 ItemID);
|
||||
EQ::ItemInstance* FindTraderItemBySerialNumber(int32 SerialNumber);
|
||||
void FindAndNukeTraderItem(int32 item_id,uint16 quantity,Client* customer,uint16 traderslot);
|
||||
void NukeTraderItem(uint16 slot, int16 charges, uint16 quantity, Client* customer, uint16 traderslot, int32 uniqueid, int32 itemid = 0);
|
||||
void FindAndNukeTraderItem(int32 item_id,int16 quantity,Client* customer,uint16 traderslot);
|
||||
void NukeTraderItem(uint16 slot, int16 charges, int16 quantity, Client* customer, uint16 traderslot, int32 uniqueid, int32 itemid = 0);
|
||||
void ReturnTraderReq(const EQApplicationPacket* app,int16 traderitemcharges, uint32 itemid = 0);
|
||||
void TradeRequestFailed(const EQApplicationPacket* app);
|
||||
void BuyTraderItem(TraderBuy_Struct* tbs,Client* trader,const EQApplicationPacket* app);
|
||||
@@ -783,16 +783,18 @@ public:
|
||||
|
||||
void GMKill();
|
||||
inline bool IsMedding() const {return medding;}
|
||||
inline uint16 GetDuelTarget() const { return duel_target; }
|
||||
inline uint32 GetDuelTarget() const { return duel_target; }
|
||||
inline bool IsDueling() const { return duelaccepted; }
|
||||
inline void SetDuelTarget(uint16 set_id) { duel_target=set_id; }
|
||||
inline void SetDuelTarget(uint32 set_id) { duel_target = set_id; }
|
||||
inline void SetDueling(bool duel) { duelaccepted = duel; }
|
||||
// use this one instead
|
||||
void MemSpell(uint16 spell_id, int slot, bool update_client = true);
|
||||
void UnmemSpell(int slot, bool update_client = true);
|
||||
void UnmemSpellBySpellID(int32 spell_id);
|
||||
void UnmemSpellAll(bool update_client = true);
|
||||
int FindEmptyMemSlot();
|
||||
uint16 FindMemmedSpellBySlot(int slot);
|
||||
int FindMemmedSpellBySpellID(uint16 spell_id);
|
||||
int MemmedCount();
|
||||
std::vector<int> GetLearnableDisciplines(uint8 min_level = 1, uint8 max_level = 0);
|
||||
std::vector<int> GetLearnedDisciplines();
|
||||
@@ -808,6 +810,11 @@ public:
|
||||
uint16 ScribeSpells(uint8 min_level, uint8 max_level);
|
||||
uint16 LearnDisciplines(uint8 min_level, uint8 max_level);
|
||||
|
||||
// Configurable Tracking Skill
|
||||
uint16 GetClassTrackingDistanceMultiplier(uint16 class_);
|
||||
|
||||
bool CanThisClassTrack();
|
||||
|
||||
// defer save used when bulk saving
|
||||
void UnscribeSpell(int slot, bool update_client = true, bool defer_save = false);
|
||||
void UnscribeSpellAll(bool update_client = true);
|
||||
@@ -828,9 +835,6 @@ public:
|
||||
inline uint8 GetBecomeNPCLevel() const { return npclevel; }
|
||||
inline void SetBecomeNPC(bool flag) { npcflag = flag; }
|
||||
inline void SetBecomeNPCLevel(uint8 level) { npclevel = level; }
|
||||
void SetFeigned(bool in_feigned);
|
||||
/// this cures timing issues cuz dead animation isn't done but server side feigning is?
|
||||
inline bool GetFeigned() const { return(feigned); }
|
||||
EQStreamInterface* Connection() { return eqs; }
|
||||
#ifdef PACKET_PROFILER
|
||||
void DumpPacketProfile() { if(eqs) eqs->DumpPacketProfile(); }
|
||||
@@ -847,6 +851,7 @@ public:
|
||||
void SummonHorse(uint16 spell_id);
|
||||
void SetHorseId(uint16 horseid_in);
|
||||
inline void SetControlledMobId(uint16 mob_id_in) { controlled_mob_id = mob_id_in; }
|
||||
uint16 GetControlledMobId() const{ return controlled_mob_id; }
|
||||
uint16 GetHorseId() const { return horseId; }
|
||||
bool CanMedOnHorse();
|
||||
|
||||
@@ -897,12 +902,14 @@ public:
|
||||
void ResetAA();
|
||||
void RefundAA();
|
||||
void SendClearAA();
|
||||
void SendClearLeadershipAA();
|
||||
void SendClearPlayerAA();
|
||||
inline uint32 GetAAXP() const { return m_pp.expAA; }
|
||||
inline uint32 GetAAPercent() const { return m_epp.perAA; }
|
||||
int32 CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id);
|
||||
void SetAATitle(const char *Title);
|
||||
void SetTitleSuffix(const char *txt);
|
||||
void MemorizeSpell(uint32 slot, uint32 spellid, uint32 scribing);
|
||||
void MemorizeSpell(uint32 slot, uint32 spellid, uint32 scribing, uint32 reduction = 0);
|
||||
|
||||
// Item methods
|
||||
void EVENT_ITEM_ScriptStopReturn();
|
||||
@@ -917,7 +924,7 @@ public:
|
||||
bool PutItemInInventory(int16 slot_id, const EQ::ItemInstance& inst, bool client_update = false);
|
||||
bool PushItemOnCursor(const EQ::ItemInstance& inst, bool client_update = false);
|
||||
void SendCursorBuffer();
|
||||
void DeleteItemInInventory(int16 slot_id, int8 quantity = 0, bool client_update = false, bool update_db = true);
|
||||
void DeleteItemInInventory(int16 slot_id, int16 quantity = 0, bool client_update = false, bool update_db = true);
|
||||
int CountItem(uint32 item_id);
|
||||
void RemoveItem(uint32 item_id, uint32 quantity = 1);
|
||||
bool SwapItem(MoveItem_Struct* move_in);
|
||||
@@ -971,7 +978,7 @@ public:
|
||||
|
||||
//remove charges/multiple objects from inventory:
|
||||
//bool DecreaseByType(uint32 type, uint8 amt);
|
||||
bool DecreaseByID(uint32 type, uint8 amt);
|
||||
bool DecreaseByID(uint32 type, int16 quantity);
|
||||
uint8 SlotConvert2(uint8 slot); //Maybe not needed.
|
||||
void Escape(); //AA Escape
|
||||
void DisenchantSummonedBags(bool client_update = true);
|
||||
@@ -1009,6 +1016,10 @@ public:
|
||||
|
||||
void SetLinkedSpellReuseTimer(uint32 timer_id, uint32 duration);
|
||||
bool IsLinkedSpellReuseTimerReady(uint32 timer_id);
|
||||
|
||||
void ResetCastbarCooldownBySlot(int slot);
|
||||
void ResetAllCastbarCooldowns();
|
||||
void ResetCastbarCooldownBySpellID(uint32 spell_id);
|
||||
|
||||
bool CheckTitle(int titleset);
|
||||
void EnableTitle(int titleset);
|
||||
@@ -1481,6 +1492,12 @@ public:
|
||||
bool GroupFollow(Client* inviter);
|
||||
inline bool GetRunMode() const { return runmode; }
|
||||
|
||||
void SendItemRecastTimer(int32 recast_type, uint32 recast_delay = 0);
|
||||
void SetItemRecastTimer(int32 spell_id, uint32 inventory_slot);
|
||||
bool HasItemRecastTimer(int32 spell_id, uint32 inventory_slot);
|
||||
void SetDisciplineRecastTimer(int32 spell_id);
|
||||
void SetAARecastTimer(AA::Rank *rank_in, int32 spell_id);
|
||||
|
||||
inline bool AggroMeterAvailable() const { return ((m_ClientVersionBit & EQ::versions::maskRoF2AndLater)) && RuleB(Character, EnableAggroMeter); } // RoF untested
|
||||
inline void SetAggroMeterLock(int in) { m_aggrometer.set_lock_id(in); }
|
||||
|
||||
@@ -1519,6 +1536,7 @@ public:
|
||||
void UpdateMercLevel();
|
||||
void CheckMercSuspendTimer();
|
||||
Timer* GetMercTimer() { return &merc_timer; };
|
||||
Timer* GetPickLockTimer() { return &pick_lock_timer; };
|
||||
|
||||
const char* GetRacePlural(Client* client);
|
||||
const char* GetClassPlural(Client* client);
|
||||
@@ -1553,7 +1571,7 @@ public:
|
||||
int mod_client_damage(int damage, EQ::skills::SkillType skillinuse, int hand, const EQ::ItemInstance* weapon, Mob* other);
|
||||
bool mod_client_message(char* message, uint8 chan_num);
|
||||
bool mod_can_increase_skill(EQ::skills::SkillType skillid, Mob* against_who);
|
||||
int16 mod_increase_skill_chance(int16 chance, Mob* against_who);
|
||||
double mod_increase_skill_chance(double chance, Mob* against_who);
|
||||
int mod_bindwound_percent(int max_percent, Mob* bindmob);
|
||||
int mod_bindwound_hp(int bindhps, Mob* bindmob);
|
||||
int mod_client_haste(int h);
|
||||
@@ -1631,7 +1649,7 @@ protected:
|
||||
void MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message = true);
|
||||
bool client_data_loaded;
|
||||
|
||||
int32 GetFocusEffect(focusType type, uint16 spell_id);
|
||||
int32 GetFocusEffect(focusType type, uint16 spell_id, Mob *caster = nullptr);
|
||||
uint16 GetSympatheticFocusEffect(focusType type, uint16 spell_id);
|
||||
|
||||
void FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost);
|
||||
@@ -1835,7 +1853,6 @@ private:
|
||||
Timer global_channel_timer;
|
||||
Timer fishing_timer;
|
||||
Timer endupkeep_timer;
|
||||
Timer forget_timer; // our 2 min everybody forgets you timer
|
||||
Timer autosave_timer;
|
||||
Timer client_scan_npc_aggro_timer;
|
||||
Timer client_zone_wide_full_position_update_timer;
|
||||
@@ -1860,7 +1877,10 @@ private:
|
||||
Timer consent_throttle_timer;
|
||||
Timer dynamiczone_removal_timer;
|
||||
Timer task_request_timer;
|
||||
Timer pick_lock_timer;
|
||||
|
||||
Timer heroforge_wearchange_timer;
|
||||
|
||||
glm::vec3 m_Proximity;
|
||||
glm::vec4 last_position_before_bulk_update;
|
||||
|
||||
@@ -1872,7 +1892,6 @@ private:
|
||||
|
||||
bool npcflag;
|
||||
uint8 npclevel;
|
||||
bool feigned;
|
||||
bool bZoning;
|
||||
bool tgb;
|
||||
bool instalog;
|
||||
|
||||
@@ -1517,6 +1517,11 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id)
|
||||
}
|
||||
return 10;
|
||||
}
|
||||
|
||||
//AA's click effects that use instrument/singing skills don't apply modifiers (Confirmed on live 11/24/21 ~Kayen)
|
||||
if (casting_spell_aa_id) {
|
||||
return 10;
|
||||
}
|
||||
|
||||
uint32 effectmod = 10;
|
||||
int effectmodcap = 0;
|
||||
|
||||
+561
-595
File diff suppressed because it is too large
Load Diff
@@ -97,8 +97,8 @@
|
||||
void Handle_OP_Disarm(const EQApplicationPacket *app);
|
||||
void Handle_OP_DisarmTraps(const EQApplicationPacket *app);
|
||||
void Handle_OP_DoGroupLeadershipAbility(const EQApplicationPacket *app);
|
||||
void Handle_OP_DuelResponse(const EQApplicationPacket *app);
|
||||
void Handle_OP_DuelResponse2(const EQApplicationPacket *app);
|
||||
void Handle_OP_DuelDecline(const EQApplicationPacket *app);
|
||||
void Handle_OP_DuelAccept(const EQApplicationPacket *app);
|
||||
void Handle_OP_DumpName(const EQApplicationPacket *app);
|
||||
void Handle_OP_Dye(const EQApplicationPacket *app);
|
||||
void Handle_OP_DzAddPlayer(const EQApplicationPacket *app);
|
||||
|
||||
+30
-7
@@ -199,6 +199,25 @@ bool Client::Process() {
|
||||
instalog = true;
|
||||
}
|
||||
|
||||
if (heroforge_wearchange_timer.Check()) {
|
||||
/*
|
||||
This addresses bug where on zone in heroforge models would not be sent to other clients when this was
|
||||
in Client::CompleteConnect(). Sending after a small 250 ms delay after that function resolves the issue.
|
||||
Unclear the underlying reason for this, if a better solution can be found then can move this back.
|
||||
*/
|
||||
if (queue_wearchange_slot >= 0) { //Resend slot from Client::SwapItem if heroforge item is swapped.
|
||||
SendWearChange(static_cast<uint8>(queue_wearchange_slot));
|
||||
}
|
||||
else { //Send from Client::CompleteConnect()
|
||||
SendWearChangeAndLighting(EQ::textures::LastTexture);
|
||||
Mob *pet = GetPet();
|
||||
if (pet) {
|
||||
pet->SendWearChangeAndLighting(EQ::textures::LastTexture);
|
||||
}
|
||||
}
|
||||
heroforge_wearchange_timer.Disable();
|
||||
}
|
||||
|
||||
if (IsStunned() && stunned_timer.Check())
|
||||
Mob::UnStun();
|
||||
|
||||
@@ -219,9 +238,9 @@ bool Client::Process() {
|
||||
InterruptSpell(SONG_ENDS_ABRUPTLY, 0x121, bardsong);
|
||||
}
|
||||
else {
|
||||
if (!ApplyNextBardPulse(bardsong, song_target, bardsong_slot))
|
||||
if (!ApplyBardPulse(bardsong, song_target, bardsong_slot)) {
|
||||
InterruptSpell(SONG_ENDS_ABRUPTLY, 0x121, bardsong);
|
||||
//SpellFinished(bardsong, bardsong_target, bardsong_slot, spells[bardsong].mana);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,6 +321,10 @@ bool Client::Process() {
|
||||
}
|
||||
|
||||
if (AutoFireEnabled()) {
|
||||
if (GetTarget() == this) {
|
||||
MessageString(Chat::TooFarAway, TRY_ATTACKING_SOMEONE);
|
||||
auto_fire = false;
|
||||
}
|
||||
EQ::ItemInstance *ranged = GetInv().GetItem(EQ::invslot::slotRange);
|
||||
if (ranged)
|
||||
{
|
||||
@@ -391,7 +414,7 @@ bool Client::Process() {
|
||||
else if (auto_attack_target->GetHP() > -10) // -10 so we can watch people bleed in PvP
|
||||
{
|
||||
EQ::ItemInstance *wpn = GetInv().GetItem(EQ::invslot::slotPrimary);
|
||||
TryWeaponProc(wpn, auto_attack_target, EQ::invslot::slotPrimary);
|
||||
TryCombatProcs(wpn, auto_attack_target, EQ::invslot::slotPrimary);
|
||||
TriggerDefensiveProcs(auto_attack_target, EQ::invslot::slotPrimary, false);
|
||||
|
||||
DoAttackRounds(auto_attack_target, EQ::invslot::slotPrimary);
|
||||
@@ -401,7 +424,7 @@ bool Client::Process() {
|
||||
}
|
||||
|
||||
if (CheckAATimer(aaTimerRampage)) {
|
||||
entity_list.AEAttack(this, 30);
|
||||
entity_list.AEAttack(this, 40);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -437,7 +460,7 @@ bool Client::Process() {
|
||||
CheckIncreaseSkill(EQ::skills::SkillDualWield, auto_attack_target, -10);
|
||||
if (CheckDualWield()) {
|
||||
EQ::ItemInstance *wpn = GetInv().GetItem(EQ::invslot::slotSecondary);
|
||||
TryWeaponProc(wpn, auto_attack_target, EQ::invslot::slotSecondary);
|
||||
TryCombatProcs(wpn, auto_attack_target, EQ::invslot::slotSecondary);
|
||||
|
||||
DoAttackRounds(auto_attack_target, EQ::invslot::slotSecondary);
|
||||
}
|
||||
@@ -533,7 +556,7 @@ bool Client::Process() {
|
||||
OnDisconnect(true);
|
||||
LogInfo("Client linkdead: {}", name);
|
||||
|
||||
if (Admin() > 100) {
|
||||
if (Admin() > AccountStatus::GMAdmin) {
|
||||
if (GetMerc()) {
|
||||
GetMerc()->Save();
|
||||
GetMerc()->Depop();
|
||||
@@ -1729,7 +1752,7 @@ void Client::OPGMSummon(const EQApplicationPacket *app)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(admin < 80)
|
||||
if(admin < AccountStatus::QuestTroupe)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
+333
-15087
File diff suppressed because it is too large
Load Diff
+36
-43
@@ -1,22 +1,3 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef COMMAND_H
|
||||
#define COMMAND_H
|
||||
|
||||
@@ -25,18 +6,18 @@ class Seperator;
|
||||
|
||||
#include "../common/types.h"
|
||||
|
||||
#define COMMAND_CHAR '#'
|
||||
#define COMMAND_CHAR '#'
|
||||
|
||||
typedef void (*CmdFuncPtr)(Client *,const Seperator *);
|
||||
typedef void (*CmdFuncPtr)(Client *, const Seperator *);
|
||||
|
||||
typedef struct {
|
||||
int access;
|
||||
const char *desc; // description of command
|
||||
CmdFuncPtr function; // null means perl function
|
||||
} CommandRecord;
|
||||
int access;
|
||||
const char *desc; // description of command
|
||||
CmdFuncPtr function; // null means perl function
|
||||
} CommandRecord;
|
||||
|
||||
extern int (*command_dispatch)(Client *,char const*);
|
||||
extern int commandcount; // number of commands loaded
|
||||
extern int (*command_dispatch)(Client *, char const *);
|
||||
extern int commandcount; // number of commands loaded
|
||||
|
||||
// the command system:
|
||||
int command_init(void);
|
||||
@@ -53,13 +34,14 @@ void command_aggro(Client *c, const Seperator *sep);
|
||||
void command_aggrozone(Client *c, const Seperator *sep);
|
||||
void command_ai(Client *c, const Seperator *sep);
|
||||
void command_appearance(Client *c, const Seperator *sep);
|
||||
void command_appearanceeffects(Client *c, const Seperator *sep);
|
||||
void command_apply_shared_memory(Client *c, const Seperator *sep);
|
||||
void command_attack(Client *c, const Seperator *sep);
|
||||
void command_augmentitem(Client *c, const Seperator *sep);
|
||||
void command_ban(Client *c, const Seperator *sep);
|
||||
void command_beard(Client *c, const Seperator *sep);
|
||||
void command_beardcolor(Client *c, const Seperator *sep);
|
||||
void command_bind(Client* c, const Seperator *sep);
|
||||
void command_bind(Client *c, const Seperator *sep);
|
||||
void command_camerashake(Client *c, const Seperator *sep);
|
||||
void command_castspell(Client *c, const Seperator *sep);
|
||||
void command_chat(Client *c, const Seperator *sep);
|
||||
@@ -67,6 +49,7 @@ void command_checklos(Client *c, const Seperator *sep);
|
||||
void command_copycharacter(Client *c, const Seperator *sep);
|
||||
void command_corpse(Client *c, const Seperator *sep);
|
||||
void command_corpsefix(Client *c, const Seperator *sep);
|
||||
void command_countitem(Client *c, const Seperator *sep);
|
||||
void command_cvs(Client *c, const Seperator *sep);
|
||||
void command_damage(Client *c, const Seperator *sep);
|
||||
void command_databuckets(Client *c, const Seperator *sep);
|
||||
@@ -87,10 +70,10 @@ void command_doanim(Client *c, const Seperator *sep);
|
||||
void command_dye(Client *c, const Seperator *sep);
|
||||
void command_dz(Client *c, const Seperator *sep);
|
||||
void command_dzkickplayers(Client *c, const Seperator *sep);
|
||||
void command_editmassrespawn(Client* c, const Seperator* sep);
|
||||
void command_editmassrespawn(Client *c, const Seperator *sep);
|
||||
void command_emote(Client *c, const Seperator *sep);
|
||||
void command_emotesearch(Client* c, const Seperator *sep);
|
||||
void command_emoteview(Client* c, const Seperator *sep);
|
||||
void command_emotesearch(Client *c, const Seperator *sep);
|
||||
void command_emoteview(Client *c, const Seperator *sep);
|
||||
void command_emptyinventory(Client *c, const Seperator *sep);
|
||||
void command_enablerecipe(Client *c, const Seperator *sep);
|
||||
void command_endurance(Client *c, const Seperator *sep);
|
||||
@@ -121,14 +104,14 @@ void command_getvariable(Client *c, const Seperator *sep);
|
||||
void command_ginfo(Client *c, const Seperator *sep);
|
||||
void command_giveitem(Client *c, const Seperator *sep);
|
||||
void command_givemoney(Client *c, const Seperator *sep);
|
||||
void command_globalview(Client* c, const Seperator *sep);
|
||||
void command_globalview(Client *c, const Seperator *sep);
|
||||
void command_gm(Client *c, const Seperator *sep);
|
||||
void command_gmspeed(Client *c, const Seperator *sep);
|
||||
void command_gmzone(Client *c, const Seperator *sep);
|
||||
void command_goto(Client *c, const Seperator *sep);
|
||||
void command_grid(Client *c, const Seperator *sep);
|
||||
void command_guild(Client *c, const Seperator *sep);
|
||||
bool helper_guild_edit(Client *c, uint32 dbid, uint32 eqid, uint8 rank, const char* what, const char* value);
|
||||
bool helper_guild_edit(Client *c, uint32 dbid, uint32 eqid, uint8 rank, const char *what, const char *value);
|
||||
void command_guildapprove(Client *c, const Seperator *sep);
|
||||
void command_guildcreate(Client *c, const Seperator *sep);
|
||||
void command_guildlist(Client *c, const Seperator *sep);
|
||||
@@ -193,12 +176,14 @@ void command_npcspecialattk(Client *c, const Seperator *sep);
|
||||
void command_npcstats(Client *c, const Seperator *sep);
|
||||
void command_npctype_cache(Client *c, const Seperator *sep);
|
||||
void command_npctypespawn(Client *c, const Seperator *sep);
|
||||
void command_nudge(Client* c, const Seperator* sep);
|
||||
void command_nudge(Client *c, const Seperator *sep);
|
||||
void command_nukebuffs(Client *c, const Seperator *sep);
|
||||
void command_nukeitem(Client *c, const Seperator *sep);
|
||||
void command_object(Client* c, const Seperator *sep);
|
||||
void command_object(Client *c, const Seperator *sep);
|
||||
void command_oocmute(Client *c, const Seperator *sep);
|
||||
void command_opcode(Client *c, const Seperator *sep);
|
||||
void command_bestz(Client *c, const Seperator *message);
|
||||
void command_pf(Client *c, const Seperator *message);
|
||||
|
||||
#ifdef PACKET_PROFILER
|
||||
void command_packetprofile(Client *c, const Seperator *sep);
|
||||
@@ -210,6 +195,7 @@ void command_peqzone(Client *c, const Seperator *sep);
|
||||
void command_permaclass(Client *c, const Seperator *sep);
|
||||
void command_permagender(Client *c, const Seperator *sep);
|
||||
void command_permarace(Client *c, const Seperator *sep);
|
||||
void command_petitems(Client *c, const Seperator *sep);
|
||||
void command_petitioninfo(Client *c, const Seperator *sep);
|
||||
void command_picklock(Client *c, const Seperator *sep);
|
||||
void command_profanity(Client *c, const Seperator *sep);
|
||||
@@ -225,24 +211,26 @@ void command_pvp(Client *c, const Seperator *sep);
|
||||
void command_qglobal(Client *c, const Seperator *sep);
|
||||
void command_questerrors(Client *c, const Seperator *sep);
|
||||
void command_race(Client *c, const Seperator *sep);
|
||||
void command_raidloot(Client* c, const Seperator *sep);
|
||||
void command_raidloot(Client *c, const Seperator *sep);
|
||||
void command_randomfeatures(Client *c, const Seperator *sep);
|
||||
void command_refreshgroup(Client *c, const Seperator *sep);
|
||||
void command_reloadaa(Client *c, const Seperator *sep);
|
||||
void command_reloadallrules(Client *c, const Seperator *sep);
|
||||
void command_reloademote(Client* c, const Seperator *sep);
|
||||
void command_reloadcontentflags(Client *c, const Seperator *sep);
|
||||
void command_reloademote(Client *c, const Seperator *sep);
|
||||
void command_reloadlevelmods(Client *c, const Seperator *sep);
|
||||
void command_reloadmerchants(Client *c, const Seperator *sep);
|
||||
void command_reloadperlexportsettings(Client *c, const Seperator *sep);
|
||||
void command_reloadqst(Client *c, const Seperator *sep);
|
||||
void command_reloadstatic(Client *c, const Seperator *sep);
|
||||
void command_reloadtitles(Client *c, const Seperator *sep);
|
||||
void command_reloadtraps(Client* c, const Seperator *sep);
|
||||
void command_reloadtraps(Client *c, const Seperator *sep);
|
||||
void command_reloadworld(Client *c, const Seperator *sep);
|
||||
void command_reloadworldrules(Client *c, const Seperator *sep);
|
||||
void command_reloadzps(Client *c, const Seperator *sep);
|
||||
void command_removeitem(Client *c, const Seperator *sep);
|
||||
void command_repop(Client *c, const Seperator *sep);
|
||||
void command_resetaa(Client* c,const Seperator *sep);
|
||||
void command_resetaa(Client *c, const Seperator *sep);
|
||||
void command_resetaa_timer(Client *c, const Seperator *sep);
|
||||
void command_resetdisc_timer(Client *c, const Seperator *sep);
|
||||
void command_revoke(Client *c, const Seperator *sep);
|
||||
@@ -259,12 +247,16 @@ void command_serverrules(Client *c, const Seperator *sep);
|
||||
void command_set_adventure_points(Client *c, const Seperator *sep);
|
||||
void command_setaapts(Client *c, const Seperator *sep);
|
||||
void command_setaaxp(Client *c, const Seperator *sep);
|
||||
void command_setaltcurrency(Client *c, const Seperator *sep);
|
||||
void command_setanim(Client *c, const Seperator *sep);
|
||||
void command_setcrystals(Client *c, const Seperator *sep);
|
||||
void command_setendurance(Client *c, const Seperator *sep);
|
||||
void command_setfaction(Client *c, const Seperator *sep);
|
||||
void command_setgraveyard(Client *c, const Seperator *sep);
|
||||
void command_sethp(Client *c, const Seperator *sep);
|
||||
void command_setlanguage(Client *c, const Seperator *sep);
|
||||
void command_setlsinfo(Client *c, const Seperator *sep);
|
||||
void command_setmana(Client *c, const Seperator *sep);
|
||||
void command_setpass(Client *c, const Seperator *sep);
|
||||
void command_setpvppoints(Client *c, const Seperator *sep);
|
||||
void command_setskill(Client *c, const Seperator *sep);
|
||||
@@ -305,21 +297,25 @@ void command_timezone(Client *c, const Seperator *sep);
|
||||
void command_title(Client *c, const Seperator *sep);
|
||||
void command_titlesuffix(Client *c, const Seperator *sep);
|
||||
void command_traindisc(Client *c, const Seperator *sep);
|
||||
void command_trapinfo(Client* c, const Seperator *sep);
|
||||
void command_trapinfo(Client *c, const Seperator *sep);
|
||||
void command_tune(Client *c, const Seperator *sep);
|
||||
void command_ucs(Client *c, const Seperator *sep);
|
||||
void command_undye(Client *c, const Seperator *sep);
|
||||
void command_undyeme(Client *c, const Seperator *sep);
|
||||
void command_unfreeze(Client *c, const Seperator *sep);
|
||||
void command_unlock(Client *c, const Seperator *sep);
|
||||
void command_unmemspell(Client *c, const Seperator *sep);
|
||||
void command_unmemspells(Client *c, const Seperator *sep);
|
||||
void command_unscribespell(Client *c, const Seperator *sep);
|
||||
void command_unscribespells(Client *c, const Seperator *sep);
|
||||
void command_untraindisc(Client *c, const Seperator *sep);
|
||||
void command_untraindiscs(Client *c, const Seperator *sep);
|
||||
void command_uptime(Client *c, const Seperator *sep);
|
||||
void command_version(Client *c, const Seperator *sep);
|
||||
void command_viewcurrencies(Client *c, const Seperator *sep);
|
||||
void command_viewnpctype(Client *c, const Seperator *sep);
|
||||
void command_viewpetition(Client *c, const Seperator *sep);
|
||||
void command_viewzoneloot(Client *c, const Seperator *sep);
|
||||
void command_wc(Client *c, const Seperator *sep);
|
||||
void command_weather(Client *c, const Seperator *sep);
|
||||
void command_who(Client *c, const Seperator *sep);
|
||||
@@ -336,9 +332,7 @@ void command_zone(Client *c, const Seperator *sep);
|
||||
void command_zone_instance(Client *c, const Seperator *sep);
|
||||
void command_zonebootup(Client *c, const Seperator *sep);
|
||||
void command_zonelock(Client *c, const Seperator *sep);
|
||||
void command_viewzoneloot(Client *c, const Seperator *sep);
|
||||
void command_zoneshutdown(Client *c, const Seperator *sep);
|
||||
void command_zonespawn(Client *c, const Seperator *sep);
|
||||
void command_zonestatus(Client *c, const Seperator *sep);
|
||||
void command_zopp(Client *c, const Seperator *sep);
|
||||
void command_zsafecoords(Client *c, const Seperator *sep);
|
||||
@@ -346,7 +340,6 @@ void command_zsave(Client *c, const Seperator *sep);
|
||||
void command_zsky(Client *c, const Seperator *sep);
|
||||
void command_zstats(Client *c, const Seperator *sep);
|
||||
void command_zunderworld(Client *c, const Seperator *sep);
|
||||
void command_zuwcoords(Client *c, const Seperator *sep);
|
||||
|
||||
#ifdef BOTS
|
||||
#include "bot.h"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user