mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 18:51:29 +00:00
Merge branch 'master' into movement_manager
This commit is contained in:
commit
0681e6dbb2
@ -1,5 +1,43 @@
|
|||||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
== 12/16/2018 ==
|
||||||
|
Akkadius:
|
||||||
|
- Implemented: Global Base Scaling: https://github.com/EQEmu/Server/wiki/NPC-Scaling
|
||||||
|
- Implemented: Beginning of DevTools - more to be added over time (Status >= 200)
|
||||||
|
- Display NPC info on target
|
||||||
|
- Display Client info on target
|
||||||
|
- Display NPC show commands on target
|
||||||
|
- Loot
|
||||||
|
- Grids
|
||||||
|
- Emotes
|
||||||
|
- Implemented: Support for saylinks to be used in GM commands
|
||||||
|
- Deprecated: Commands
|
||||||
|
- #listnpcs
|
||||||
|
- Implemented: Commands
|
||||||
|
- #list [npcs|players|corpses|doors|objects] [search]
|
||||||
|
- Provides clickable saylinks to go to entities
|
||||||
|
- #scale [static/dynamic] (With targeted NPC)
|
||||||
|
- #scale [npc_name_search] [static/dynamic] (To make zone-wide changes)
|
||||||
|
- #scale all [static/dynamic]
|
||||||
|
- #devtools (alias #dev)
|
||||||
|
- Implemented: New Logging categories automatically injected into `logsys_categories` table
|
||||||
|
- Fixed an issue where newly injected categories were turned on by default
|
||||||
|
|
||||||
|
== 12/15/2018 ==
|
||||||
|
Kinglykrab: Added multiple new instance related quest functions.
|
||||||
|
1. quest::GetInstanceIDByCharID(const char *zone, int16 version, uint32 char_id)
|
||||||
|
- Allows you to pull the instance ID of a client by character ID.
|
||||||
|
2. quest::AssignToInstanceByCharID(uint16 instance_id, uint32 char_id)
|
||||||
|
- Allows you to assign an instance to a client by character ID.
|
||||||
|
3. quest::RemoveFromInstanceByCharID(uint16 instance_id, uint32 char_id)
|
||||||
|
- Allows you to remove a client from an instance by character ID.
|
||||||
|
|
||||||
|
Added spell buckets, similar to spell globals.
|
||||||
|
- Uses a new spell_buckets table and the Spells:EnableSpellBuckets rule.
|
||||||
|
|
||||||
|
Added max level by data bucket.
|
||||||
|
- Uses data bucket char_id-CharMaxLevel and Character:PerCharacterBucketMaxLevel rule.
|
||||||
|
|
||||||
== 10/09/2018 ==
|
== 10/09/2018 ==
|
||||||
Uleat: Added bot owner options
|
Uleat: Added bot owner options
|
||||||
- usage: ^owneroption [option] (or aliased as: ^oo [option])
|
- usage: ^owneroption [option] (or aliased as: ^oo [option])
|
||||||
|
|||||||
@ -77,6 +77,11 @@ namespace EQEmu
|
|||||||
|
|
||||||
} // namespace invtype
|
} // namespace invtype
|
||||||
|
|
||||||
|
namespace popupresponse {
|
||||||
|
const int32 SERVER_INTERNAL_USE_BASE = 2000000000;
|
||||||
|
const int32 MOB_INFO_DISMISS = 2000000001;
|
||||||
|
}
|
||||||
|
|
||||||
namespace invslot {
|
namespace invslot {
|
||||||
using namespace RoF2::invslot::enum_;
|
using namespace RoF2::invslot::enum_;
|
||||||
|
|
||||||
|
|||||||
@ -306,7 +306,6 @@ union
|
|||||||
uint32 DestructibleUnk9;
|
uint32 DestructibleUnk9;
|
||||||
bool targetable_with_hotkey;
|
bool targetable_with_hotkey;
|
||||||
bool show_name;
|
bool show_name;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlayerState_Struct {
|
struct PlayerState_Struct {
|
||||||
|
|||||||
@ -122,11 +122,6 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
|
|||||||
|
|
||||||
file_logs_enabled = false;
|
file_logs_enabled = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* Zero out Array
|
|
||||||
*/
|
|
||||||
memset(log_settings, 0, sizeof(LogSettings) * Logs::LogCategory::MaxCategoryID);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set Defaults
|
* Set Defaults
|
||||||
*/
|
*/
|
||||||
@ -138,17 +133,20 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
|
|||||||
log_settings[Logs::MySQLError].log_to_console = Logs::General;
|
log_settings[Logs::MySQLError].log_to_console = Logs::General;
|
||||||
log_settings[Logs::Login_Server].log_to_console = Logs::General;
|
log_settings[Logs::Login_Server].log_to_console = Logs::General;
|
||||||
log_settings[Logs::Headless_Client].log_to_console = Logs::General;
|
log_settings[Logs::Headless_Client].log_to_console = Logs::General;
|
||||||
|
log_settings[Logs::NPCScaling].log_to_gmsay = Logs::General;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set Category enabled status on defaults
|
* Set Category enabled status on defaults
|
||||||
*/
|
*/
|
||||||
log_settings[Logs::World_Server].is_category_enabled = 1;
|
for (int log_category_id = Logs::AA; log_category_id != Logs::MaxCategoryID; log_category_id++) {
|
||||||
log_settings[Logs::Zone_Server].is_category_enabled = 1;
|
const bool log_to_console = log_settings[log_category_id].log_to_console > 0;
|
||||||
log_settings[Logs::QS_Server].is_category_enabled = 1;
|
const bool log_to_file = log_settings[log_category_id].log_to_file > 0;
|
||||||
log_settings[Logs::UCS_Server].is_category_enabled = 1;
|
const bool log_to_gmsay = log_settings[log_category_id].log_to_gmsay > 0;
|
||||||
log_settings[Logs::Crash].is_category_enabled = 1;
|
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay;
|
||||||
log_settings[Logs::MySQLError].is_category_enabled = 1;
|
if (is_category_enabled) {
|
||||||
log_settings[Logs::Login_Server].is_category_enabled = 1;
|
log_settings[log_category_id].is_category_enabled = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Declare process file names for log writing=
|
* Declare process file names for log writing=
|
||||||
|
|||||||
@ -272,10 +272,6 @@ enum {
|
|||||||
commandInvSnapshot = 150 //ability to clear/restore snapshots
|
commandInvSnapshot = 150 //ability to clear/restore snapshots
|
||||||
};
|
};
|
||||||
|
|
||||||
//default states for logging flag on NPCs and clients (having NPCs on by default is prolly a bad idea)
|
|
||||||
#define CLIENT_DEFAULT_LOGGING_ENABLED true
|
|
||||||
#define NPC_DEFAULT_LOGGING_ENABLED false
|
|
||||||
|
|
||||||
|
|
||||||
// This is the item ID we use for say links, we use the max that fits in 5 ASCII chars
|
// This is the item ID we use for say links, we use the max that fits in 5 ASCII chars
|
||||||
#define SAYLINK_ITEM_ID 0xFFFFF
|
#define SAYLINK_ITEM_ID 0xFFFFF
|
||||||
|
|||||||
@ -350,4 +350,5 @@ bool EQ::Net::StaticPacket::Resize(size_t new_size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_data_length = new_size;
|
m_data_length = new_size;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
@ -382,15 +382,18 @@ bool RuleManager::ListRulesets(Database *database, std::map<int, std::string> &i
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 RuleManager::GetIntRule(RuleManager::IntType t) const{
|
int32 RuleManager::GetIntRule(RuleManager::IntType t) const
|
||||||
return(m_RuleIntValues[t]);
|
{
|
||||||
|
return (m_RuleIntValues[t]);
|
||||||
}
|
}
|
||||||
|
|
||||||
float RuleManager::GetRealRule(RuleManager::RealType t) const{
|
float RuleManager::GetRealRule(RuleManager::RealType t) const
|
||||||
return(m_RuleRealValues[t]);
|
{
|
||||||
|
return (m_RuleRealValues[t]);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RuleManager::GetBoolRule(RuleManager::BoolType t) const{
|
bool RuleManager::GetBoolRule(RuleManager::BoolType t) const
|
||||||
|
{
|
||||||
return (m_RuleBoolValues[t] == 1);
|
return (m_RuleBoolValues[t] == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -38,6 +38,7 @@
|
|||||||
RULE_CATEGORY(Character)
|
RULE_CATEGORY(Character)
|
||||||
RULE_INT(Character, MaxLevel, 65)
|
RULE_INT(Character, MaxLevel, 65)
|
||||||
RULE_BOOL(Character, PerCharacterQglobalMaxLevel, false) // This will check for qglobal 'CharMaxLevel' character qglobal (Type 5), if player tries to level beyond that point, it will not go beyond that level
|
RULE_BOOL(Character, PerCharacterQglobalMaxLevel, false) // This will check for qglobal 'CharMaxLevel' character qglobal (Type 5), if player tries to level beyond that point, it will not go beyond that level
|
||||||
|
RULE_BOOL(Character, PerCharacterBucketMaxLevel, false) // This will check for data bucket 'CharMaxLevel', if player tries to level beyond that point, it will not go beyond that level
|
||||||
RULE_INT(Character, MaxExpLevel, 0) //Sets the Max Level attainable via Experience
|
RULE_INT(Character, MaxExpLevel, 0) //Sets the Max Level attainable via Experience
|
||||||
RULE_INT(Character, DeathExpLossLevel, 10) // Any level greater than this will lose exp on death
|
RULE_INT(Character, DeathExpLossLevel, 10) // Any level greater than this will lose exp on death
|
||||||
RULE_INT(Character, DeathExpLossMaxLevel, 255) // Any level greater than this will no longer lose exp on death
|
RULE_INT(Character, DeathExpLossMaxLevel, 255) // Any level greater than this will no longer lose exp on death
|
||||||
@ -343,7 +344,8 @@ RULE_INT(Spells, TranslocateTimeLimit, 0) // If not zero, time in seconds to acc
|
|||||||
RULE_INT(Spells, SacrificeMinLevel, 46) //first level Sacrifice will work on
|
RULE_INT(Spells, SacrificeMinLevel, 46) //first level Sacrifice will work on
|
||||||
RULE_INT(Spells, SacrificeMaxLevel, 69) //last level Sacrifice will work on
|
RULE_INT(Spells, SacrificeMaxLevel, 69) //last level Sacrifice will work on
|
||||||
RULE_INT(Spells, SacrificeItemID, 9963) //Item ID of the item Sacrifice will return (defaults to an EE)
|
RULE_INT(Spells, SacrificeItemID, 9963) //Item ID of the item Sacrifice will return (defaults to an EE)
|
||||||
RULE_BOOL(Spells, EnableSpellGlobals, false) // If Enabled, spells check the spell_globals table and compare character data from the quest globals before allowing that spell to scribe with scribespells
|
RULE_BOOL(Spells, EnableSpellGlobals, false) // If Enabled, spells check the spell_globals table and compare character data from their quest globals before allowing the spell to scribe with scribespells/traindiscs
|
||||||
|
RULE_BOOL(Spells, EnableSpellBuckets, false) // If Enabled, spells check the spell_buckets table and compare character data from their data buckets before allowing the spell to scribe with scribespells/traindiscs
|
||||||
RULE_INT(Spells, MaxBuffSlotsNPC, 60) // default to Tit's limit
|
RULE_INT(Spells, MaxBuffSlotsNPC, 60) // default to Tit's limit
|
||||||
RULE_INT(Spells, MaxSongSlotsNPC, 0) // NPCs don't have songs ...
|
RULE_INT(Spells, MaxSongSlotsNPC, 0) // NPCs don't have songs ...
|
||||||
RULE_INT(Spells, MaxDiscSlotsNPC, 0) // NPCs don't have discs ...
|
RULE_INT(Spells, MaxDiscSlotsNPC, 0) // NPCs don't have discs ...
|
||||||
@ -510,6 +512,7 @@ RULE_BOOL(Combat, UseRevampHandToHand, false) // use h2h revamped dmg/delays I b
|
|||||||
RULE_BOOL(Combat, ClassicMasterWu, false) // classic master wu uses a random special, modern doesn't
|
RULE_BOOL(Combat, ClassicMasterWu, false) // classic master wu uses a random special, modern doesn't
|
||||||
RULE_INT(Combat, LevelToStopDamageCaps, 0) // 1 will effectively disable them, 20 should give basically same results as old incorrect system
|
RULE_INT(Combat, LevelToStopDamageCaps, 0) // 1 will effectively disable them, 20 should give basically same results as old incorrect system
|
||||||
RULE_BOOL(Combat, ClassicNPCBackstab, false) // true disables npc facestab - npcs get normal attack if not behind
|
RULE_BOOL(Combat, ClassicNPCBackstab, false) // true disables npc facestab - npcs get normal attack if not behind
|
||||||
|
RULE_BOOL(Combat, UseNPCDamageClassLevelMods, true) // Uses GetClassLevelDamageMod calc in npc_scale_manager
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(NPC)
|
RULE_CATEGORY(NPC)
|
||||||
|
|||||||
@ -26,30 +26,31 @@
|
|||||||
#include "../zone/zonedb.h"
|
#include "../zone/zonedb.h"
|
||||||
|
|
||||||
|
|
||||||
bool EQEmu::saylink::DegenerateLinkBody(SayLinkBody_Struct& say_link_body_struct, const std::string& say_link_body)
|
bool EQEmu::saylink::DegenerateLinkBody(SayLinkBody_Struct &say_link_body_struct, const std::string &say_link_body)
|
||||||
{
|
{
|
||||||
memset(&say_link_body_struct, 0, sizeof(say_link_body_struct));
|
memset(&say_link_body_struct, 0, sizeof(say_link_body_struct));
|
||||||
if (say_link_body.length() != EQEmu::constants::SAY_LINK_BODY_SIZE)
|
if (say_link_body.length() != EQEmu::constants::SAY_LINK_BODY_SIZE) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
say_link_body_struct.action_id = (uint8)strtol(say_link_body.substr(0, 1).c_str(), nullptr, 16);
|
say_link_body_struct.action_id = (uint8) strtol(say_link_body.substr(0, 1).c_str(), nullptr, 16);
|
||||||
say_link_body_struct.item_id = (uint32)strtol(say_link_body.substr(1, 5).c_str(), nullptr, 16);
|
say_link_body_struct.item_id = (uint32) strtol(say_link_body.substr(1, 5).c_str(), nullptr, 16);
|
||||||
say_link_body_struct.augment_1 = (uint32)strtol(say_link_body.substr(6, 5).c_str(), nullptr, 16);
|
say_link_body_struct.augment_1 = (uint32) strtol(say_link_body.substr(6, 5).c_str(), nullptr, 16);
|
||||||
say_link_body_struct.augment_2 = (uint32)strtol(say_link_body.substr(11, 5).c_str(), nullptr, 16);
|
say_link_body_struct.augment_2 = (uint32) strtol(say_link_body.substr(11, 5).c_str(), nullptr, 16);
|
||||||
say_link_body_struct.augment_3 = (uint32)strtol(say_link_body.substr(16, 5).c_str(), nullptr, 16);
|
say_link_body_struct.augment_3 = (uint32) strtol(say_link_body.substr(16, 5).c_str(), nullptr, 16);
|
||||||
say_link_body_struct.augment_4 = (uint32)strtol(say_link_body.substr(21, 5).c_str(), nullptr, 16);
|
say_link_body_struct.augment_4 = (uint32) strtol(say_link_body.substr(21, 5).c_str(), nullptr, 16);
|
||||||
say_link_body_struct.augment_5 = (uint32)strtol(say_link_body.substr(26, 5).c_str(), nullptr, 16);
|
say_link_body_struct.augment_5 = (uint32) strtol(say_link_body.substr(26, 5).c_str(), nullptr, 16);
|
||||||
say_link_body_struct.augment_6 = (uint32)strtol(say_link_body.substr(31, 5).c_str(), nullptr, 16);
|
say_link_body_struct.augment_6 = (uint32) strtol(say_link_body.substr(31, 5).c_str(), nullptr, 16);
|
||||||
say_link_body_struct.is_evolving = (uint8)strtol(say_link_body.substr(36, 1).c_str(), nullptr, 16);
|
say_link_body_struct.is_evolving = (uint8) strtol(say_link_body.substr(36, 1).c_str(), nullptr, 16);
|
||||||
say_link_body_struct.evolve_group = (uint32)strtol(say_link_body.substr(37, 4).c_str(), nullptr, 16);
|
say_link_body_struct.evolve_group = (uint32) strtol(say_link_body.substr(37, 4).c_str(), nullptr, 16);
|
||||||
say_link_body_struct.evolve_level = (uint8)strtol(say_link_body.substr(41, 2).c_str(), nullptr, 16);
|
say_link_body_struct.evolve_level = (uint8) strtol(say_link_body.substr(41, 2).c_str(), nullptr, 16);
|
||||||
say_link_body_struct.ornament_icon = (uint32)strtol(say_link_body.substr(43, 5).c_str(), nullptr, 16);
|
say_link_body_struct.ornament_icon = (uint32) strtol(say_link_body.substr(43, 5).c_str(), nullptr, 16);
|
||||||
say_link_body_struct.hash = (uint32)strtol(say_link_body.substr(48, 8).c_str(), nullptr, 16);
|
say_link_body_struct.hash = (uint32) strtol(say_link_body.substr(48, 8).c_str(), nullptr, 16);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EQEmu::saylink::GenerateLinkBody(std::string& say_link_body, const SayLinkBody_Struct& say_link_body_struct)
|
bool EQEmu::saylink::GenerateLinkBody(std::string &say_link_body, const SayLinkBody_Struct &say_link_body_struct)
|
||||||
{
|
{
|
||||||
say_link_body = StringFormat(
|
say_link_body = StringFormat(
|
||||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X",
|
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X",
|
||||||
@ -68,8 +69,9 @@ bool EQEmu::saylink::GenerateLinkBody(std::string& say_link_body, const SayLinkB
|
|||||||
(0xFFFFFFFF & say_link_body_struct.hash)
|
(0xFFFFFFFF & say_link_body_struct.hash)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (say_link_body.length() != EQEmu::constants::SAY_LINK_BODY_SIZE)
|
if (say_link_body.length() != EQEmu::constants::SAY_LINK_BODY_SIZE) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -79,7 +81,7 @@ EQEmu::SayLinkEngine::SayLinkEngine()
|
|||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& EQEmu::SayLinkEngine::GenerateLink()
|
const std::string &EQEmu::SayLinkEngine::GenerateLink()
|
||||||
{
|
{
|
||||||
m_Link.clear();
|
m_Link.clear();
|
||||||
m_LinkBody.clear();
|
m_LinkBody.clear();
|
||||||
@ -145,7 +147,7 @@ void EQEmu::SayLinkEngine::generate_body()
|
|||||||
|
|
||||||
memset(&m_LinkBodyStruct, 0, sizeof(SayLinkBody_Struct));
|
memset(&m_LinkBodyStruct, 0, sizeof(SayLinkBody_Struct));
|
||||||
|
|
||||||
const EQEmu::ItemData* item_data = nullptr;
|
const EQEmu::ItemData *item_data = nullptr;
|
||||||
|
|
||||||
switch (m_LinkType) {
|
switch (m_LinkType) {
|
||||||
case saylink::SayLinkBlank:
|
case saylink::SayLinkBlank:
|
||||||
@ -192,36 +194,50 @@ void EQEmu::SayLinkEngine::generate_body()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_LinkProxyStruct.action_id)
|
if (m_LinkProxyStruct.action_id) {
|
||||||
m_LinkBodyStruct.action_id = m_LinkProxyStruct.action_id;
|
m_LinkBodyStruct.action_id = m_LinkProxyStruct.action_id;
|
||||||
if (m_LinkProxyStruct.item_id)
|
}
|
||||||
|
if (m_LinkProxyStruct.item_id) {
|
||||||
m_LinkBodyStruct.item_id = m_LinkProxyStruct.item_id;
|
m_LinkBodyStruct.item_id = m_LinkProxyStruct.item_id;
|
||||||
if (m_LinkProxyStruct.augment_1)
|
}
|
||||||
|
if (m_LinkProxyStruct.augment_1) {
|
||||||
m_LinkBodyStruct.augment_1 = m_LinkProxyStruct.augment_1;
|
m_LinkBodyStruct.augment_1 = m_LinkProxyStruct.augment_1;
|
||||||
if (m_LinkProxyStruct.augment_2)
|
}
|
||||||
|
if (m_LinkProxyStruct.augment_2) {
|
||||||
m_LinkBodyStruct.augment_2 = m_LinkProxyStruct.augment_2;
|
m_LinkBodyStruct.augment_2 = m_LinkProxyStruct.augment_2;
|
||||||
if (m_LinkProxyStruct.augment_3)
|
}
|
||||||
|
if (m_LinkProxyStruct.augment_3) {
|
||||||
m_LinkBodyStruct.augment_3 = m_LinkProxyStruct.augment_3;
|
m_LinkBodyStruct.augment_3 = m_LinkProxyStruct.augment_3;
|
||||||
if (m_LinkProxyStruct.augment_4)
|
}
|
||||||
|
if (m_LinkProxyStruct.augment_4) {
|
||||||
m_LinkBodyStruct.augment_4 = m_LinkProxyStruct.augment_4;
|
m_LinkBodyStruct.augment_4 = m_LinkProxyStruct.augment_4;
|
||||||
if (m_LinkProxyStruct.augment_5)
|
}
|
||||||
|
if (m_LinkProxyStruct.augment_5) {
|
||||||
m_LinkBodyStruct.augment_5 = m_LinkProxyStruct.augment_5;
|
m_LinkBodyStruct.augment_5 = m_LinkProxyStruct.augment_5;
|
||||||
if (m_LinkProxyStruct.augment_6)
|
}
|
||||||
|
if (m_LinkProxyStruct.augment_6) {
|
||||||
m_LinkBodyStruct.augment_6 = m_LinkProxyStruct.augment_6;
|
m_LinkBodyStruct.augment_6 = m_LinkProxyStruct.augment_6;
|
||||||
if (m_LinkProxyStruct.is_evolving)
|
}
|
||||||
|
if (m_LinkProxyStruct.is_evolving) {
|
||||||
m_LinkBodyStruct.is_evolving = m_LinkProxyStruct.is_evolving;
|
m_LinkBodyStruct.is_evolving = m_LinkProxyStruct.is_evolving;
|
||||||
if (m_LinkProxyStruct.evolve_group)
|
}
|
||||||
|
if (m_LinkProxyStruct.evolve_group) {
|
||||||
m_LinkBodyStruct.evolve_group = m_LinkProxyStruct.evolve_group;
|
m_LinkBodyStruct.evolve_group = m_LinkProxyStruct.evolve_group;
|
||||||
if (m_LinkProxyStruct.evolve_level)
|
}
|
||||||
|
if (m_LinkProxyStruct.evolve_level) {
|
||||||
m_LinkBodyStruct.evolve_level = m_LinkProxyStruct.evolve_level;
|
m_LinkBodyStruct.evolve_level = m_LinkProxyStruct.evolve_level;
|
||||||
if (m_LinkProxyStruct.ornament_icon)
|
}
|
||||||
|
if (m_LinkProxyStruct.ornament_icon) {
|
||||||
m_LinkBodyStruct.ornament_icon = m_LinkProxyStruct.ornament_icon;
|
m_LinkBodyStruct.ornament_icon = m_LinkProxyStruct.ornament_icon;
|
||||||
if (m_LinkProxyStruct.hash)
|
}
|
||||||
|
if (m_LinkProxyStruct.hash) {
|
||||||
m_LinkBodyStruct.hash = m_LinkProxyStruct.hash;
|
m_LinkBodyStruct.hash = m_LinkProxyStruct.hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (m_TaskUse)
|
if (m_TaskUse) {
|
||||||
m_LinkBodyStruct.hash = 0x14505DC2;
|
m_LinkBodyStruct.hash = 0x14505DC2;
|
||||||
|
}
|
||||||
|
|
||||||
m_LinkBody = StringFormat(
|
m_LinkBody = StringFormat(
|
||||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X",
|
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X",
|
||||||
@ -248,7 +264,7 @@ void EQEmu::SayLinkEngine::generate_text()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EQEmu::ItemData* item_data = nullptr;
|
const EQEmu::ItemData *item_data = nullptr;
|
||||||
|
|
||||||
switch (m_LinkType) {
|
switch (m_LinkType) {
|
||||||
case saylink::SayLinkBlank:
|
case saylink::SayLinkBlank:
|
||||||
@ -274,3 +290,53 @@ void EQEmu::SayLinkEngine::generate_text()
|
|||||||
|
|
||||||
m_LinkText = "null";
|
m_LinkText = "null";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string EQEmu::SayLinkEngine::GenerateQuestSaylink(std::string saylink_text, bool silent, std::string link_name)
|
||||||
|
{
|
||||||
|
uint32 saylink_id = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query for an existing phrase and id in the saylink table
|
||||||
|
*/
|
||||||
|
std::string query = StringFormat(
|
||||||
|
"SELECT `id` FROM `saylink` WHERE `phrase` = '%s' LIMIT 1",
|
||||||
|
EscapeString(saylink_text).c_str());
|
||||||
|
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
|
||||||
|
if (results.Success()) {
|
||||||
|
if (results.RowCount() >= 1) {
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row)
|
||||||
|
saylink_id = static_cast<uint32>(atoi(row[0]));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::string insert_query = StringFormat(
|
||||||
|
"INSERT INTO `saylink` (`phrase`) VALUES ('%s')",
|
||||||
|
EscapeString(saylink_text).c_str());
|
||||||
|
|
||||||
|
results = database.QueryDatabase(insert_query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
Log(Logs::General, Logs::Error, "Error in saylink phrase queries %s", results.ErrorMessage().c_str());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
saylink_id = results.LastInsertedID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the actual link
|
||||||
|
*/
|
||||||
|
EQEmu::SayLinkEngine linker;
|
||||||
|
linker.SetProxyItemID(SAYLINK_ITEM_ID);
|
||||||
|
if (silent) {
|
||||||
|
linker.SetProxyAugment2ID(saylink_id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
linker.SetProxyAugment1ID(saylink_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
linker.SetProxyText(link_name.c_str());
|
||||||
|
|
||||||
|
return linker.GenerateLink();
|
||||||
|
}
|
||||||
@ -101,6 +101,8 @@ namespace EQEmu
|
|||||||
const std::string& LinkBody() { return m_LinkBody; } // contains string format: '<LinkBody>'
|
const std::string& LinkBody() { return m_LinkBody; } // contains string format: '<LinkBody>'
|
||||||
const std::string& LinkText() { return m_LinkText; } // contains string format: '<LinkText>'
|
const std::string& LinkText() { return m_LinkText; } // contains string format: '<LinkText>'
|
||||||
|
|
||||||
|
static std::string GenerateQuestSaylink(std::string saylink_text, bool silent, std::string link_name);
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@ -1175,19 +1175,17 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const EQEmu::ItemData* SharedDatabase::GetItem(uint32 id) {
|
const EQEmu::ItemData *SharedDatabase::GetItem(uint32 id)
|
||||||
if (id == 0)
|
{
|
||||||
{
|
if (id == 0) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!items_hash || id > items_hash->max_key())
|
if (!items_hash || id > items_hash->max_key()) {
|
||||||
{
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(items_hash->exists(id))
|
if (items_hash->exists(id)) {
|
||||||
{
|
|
||||||
return &(items_hash->at(id));
|
return &(items_hash->at(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1122,6 +1122,20 @@ bool IsStackableDot(uint16 spell_id)
|
|||||||
return IsEffectInSpell(spell_id, SE_CurrentHP) || IsEffectInSpell(spell_id, SE_GravityEffect);
|
return IsEffectInSpell(spell_id, SE_CurrentHP) || IsEffectInSpell(spell_id, SE_GravityEffect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsBardOnlyStackEffect(int effect)
|
||||||
|
{
|
||||||
|
switch(effect) {
|
||||||
|
case SE_CurrentMana:
|
||||||
|
case SE_ManaRegen_v2:
|
||||||
|
case SE_CurrentHP:
|
||||||
|
case SE_HealOverTime:
|
||||||
|
case SE_BardAEDot:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool IsCastWhileInvis(uint16 spell_id)
|
bool IsCastWhileInvis(uint16 spell_id)
|
||||||
{
|
{
|
||||||
if (!IsValidSpell(spell_id))
|
if (!IsValidSpell(spell_id))
|
||||||
|
|||||||
@ -968,6 +968,7 @@ uint32 GetPartialMeleeRuneAmount(uint32 spell_id);
|
|||||||
uint32 GetPartialMagicRuneAmount(uint32 spell_id);
|
uint32 GetPartialMagicRuneAmount(uint32 spell_id);
|
||||||
bool NoDetrimentalSpellAggro(uint16 spell_id);
|
bool NoDetrimentalSpellAggro(uint16 spell_id);
|
||||||
bool IsStackableDot(uint16 spell_id);
|
bool IsStackableDot(uint16 spell_id);
|
||||||
|
bool IsBardOnlyStackEffect(int effect);
|
||||||
bool IsCastWhileInvis(uint16 spell_id);
|
bool IsCastWhileInvis(uint16 spell_id);
|
||||||
bool IsEffectIgnoredInStacking(int spa);
|
bool IsEffectIgnoredInStacking(int spa);
|
||||||
|
|
||||||
|
|||||||
@ -63,11 +63,50 @@ const std::string vStringFormat(const char* format, va_list args)
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string StringFormat(const char* format, ...)
|
const std::string str_tolower(std::string s)
|
||||||
|
{
|
||||||
|
std::transform(
|
||||||
|
s.begin(), s.end(), s.begin(),
|
||||||
|
[](unsigned char c) { return ::tolower(c); }
|
||||||
|
);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> split(std::string str_to_split, char delimiter)
|
||||||
|
{
|
||||||
|
std::stringstream ss(str_to_split);
|
||||||
|
std::string item;
|
||||||
|
std::vector<std::string> exploded_values;
|
||||||
|
while (std::getline(ss, item, delimiter)) {
|
||||||
|
exploded_values.push_back(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return exploded_values;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string str_toupper(std::string s)
|
||||||
|
{
|
||||||
|
std::transform(
|
||||||
|
s.begin(), s.end(), s.begin(),
|
||||||
|
[](unsigned char c) { return ::toupper(c); }
|
||||||
|
);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string ucfirst(std::string s)
|
||||||
|
{
|
||||||
|
std::string output = s;
|
||||||
|
if (!s.empty())
|
||||||
|
output[0] = static_cast<char>(::toupper(s[0]));
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string StringFormat(const char *format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
std::string output = vStringFormat(format,args);
|
std::string output = vStringFormat(format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@ -188,12 +227,18 @@ std::string JoinString(const std::vector<std::string>& ar, const std::string &de
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string) {
|
void find_replace(std::string &string_subject, const std::string &search_string, const std::string &replace_string)
|
||||||
auto index = string_subject.find_first_of(search_string);
|
{
|
||||||
while (index != std::string::npos) {
|
if (string_subject.find(search_string) == std::string::npos) {
|
||||||
string_subject.replace(index, index + 1, replace_string);
|
return;
|
||||||
index = string_subject.find_first_of(search_string);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t start_pos = 0;
|
||||||
|
while((start_pos = string_subject.find(search_string, start_pos)) != std::string::npos) {
|
||||||
|
string_subject.replace(start_pos, search_string.length(), replace_string);
|
||||||
|
start_pos += replace_string.length();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Const char based
|
//Const char based
|
||||||
|
|||||||
@ -24,6 +24,10 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
//std::string based
|
//std::string based
|
||||||
|
const std::string str_tolower(std::string s);
|
||||||
|
const std::string str_toupper(std::string s);
|
||||||
|
const std::string ucfirst(std::string s);
|
||||||
|
std::vector<std::string> split(std::string str_to_split, char delimiter);
|
||||||
const std::string StringFormat(const char* format, ...);
|
const std::string StringFormat(const char* format, ...);
|
||||||
const std::string vStringFormat(const char* format, va_list args);
|
const std::string vStringFormat(const char* format, va_list args);
|
||||||
std::vector<std::string> SplitString(const std::string &s, char delim);
|
std::vector<std::string> SplitString(const std::string &s, char delim);
|
||||||
|
|||||||
@ -30,7 +30,7 @@
|
|||||||
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CURRENT_BINARY_DATABASE_VERSION 9130
|
#define CURRENT_BINARY_DATABASE_VERSION 9133
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9021
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9021
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -116,17 +116,17 @@ public:
|
|||||||
inline void AccountTable(std::string t) { account_table = t; }
|
inline void AccountTable(std::string t) { account_table = t; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the value of local_network.
|
* Return the value of world account table.
|
||||||
*/
|
*/
|
||||||
inline std::string GetAccountTable() const { return account_table; }
|
inline std::string GetAccountTable() const { return account_table; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets world account table.
|
* Sets world registration table.
|
||||||
*/
|
*/
|
||||||
inline void WorldRegistrationTable(std::string t) { world_registration_table = t; }
|
inline void WorldRegistrationTable(std::string t) { world_registration_table = t; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the value of world account table.
|
* Return the value of world registration table.
|
||||||
*/
|
*/
|
||||||
inline std::string GetWorldRegistrationTable() const { return world_registration_table; }
|
inline std::string GetWorldRegistrationTable() const { return world_registration_table; }
|
||||||
|
|
||||||
@ -146,7 +146,7 @@ public:
|
|||||||
inline void WorldServerTypeTable(std::string t) { world_server_type_table = t; }
|
inline void WorldServerTypeTable(std::string t) { world_server_type_table = t; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the value of world admin account table.
|
* Return the value of world server type table.
|
||||||
*/
|
*/
|
||||||
inline std::string GetWorldServerTypeTable() const { return world_server_type_table; }
|
inline std::string GetWorldServerTypeTable() const { return world_server_type_table; }
|
||||||
|
|
||||||
|
|||||||
@ -383,8 +383,10 @@
|
|||||||
9127|2018_09_07_NPCMaxAggroDist.sql|SHOW COLUMNS FROM `zone` LIKE 'npc_max_aggro_dist'|empty|
|
9127|2018_09_07_NPCMaxAggroDist.sql|SHOW COLUMNS FROM `zone` LIKE 'npc_max_aggro_dist'|empty|
|
||||||
9128|2018_08_13_inventory_version_update.sql|SHOW TABLES LIKE 'inventory_version'|not_empty|
|
9128|2018_08_13_inventory_version_update.sql|SHOW TABLES LIKE 'inventory_version'|not_empty|
|
||||||
9129|2018_08_13_inventory_update.sql|SHOW TABLES LIKE 'inventory_versions'|empty|
|
9129|2018_08_13_inventory_update.sql|SHOW TABLES LIKE 'inventory_versions'|empty|
|
||||||
9130|2018_11_25_name_filter_update.sql|SHOW COLUMS FROM `name_filter` LIKE 'id'|empty|
|
9130|2018_11_25_name_filter_update.sql|SHOW COLUMNS FROM `name_filter` LIKE 'id'|empty|
|
||||||
9131|2018_11_25_StuckBehavior.sql|SHOW COLUMNS FROM `npc_types` LIKE 'stuck_behavior'|empty|
|
9131|2018_12_13_spell_buckets.sql|SHOW TABLES LIKE 'spell_buckets'|empty|
|
||||||
|
9132|2018_12_16_global_base_scaling.sql|SHOW TABLES LIKE 'npc_scale_global_base'|empty|
|
||||||
|
9133|2018_11_25_StuckBehavior.sql|SHOW COLUMNS FROM `npc_types` LIKE 'stuck_behavior'|empty|
|
||||||
|
|
||||||
# Upgrade conditions:
|
# Upgrade conditions:
|
||||||
# This won't be needed after this system is implemented, but it is used database that are not
|
# This won't be needed after this system is implemented, but it is used database that are not
|
||||||
|
|||||||
10
utils/sql/git/required/2018_12_13_spell_buckets.sql
Normal file
10
utils/sql/git/required/2018_12_13_spell_buckets.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
CREATE TABLE `spell_buckets` (
|
||||||
|
`spellid` bigint(11) unsigned NOT NULL,
|
||||||
|
`key` varchar(100) DEFAULT NULL,
|
||||||
|
`value` text,
|
||||||
|
PRIMARY KEY (`spellid`),
|
||||||
|
KEY `key_index` (`key`) USING BTREE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Spells:EnableSpellBuckets', 'false', 'Enables spell buckets');
|
||||||
|
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Character:PerCharacterBucketMaxLevel', 'false', 'Enables data bucket-based max level.');
|
||||||
314
utils/sql/git/required/2018_12_16_global_base_scaling.sql
Normal file
314
utils/sql/git/required/2018_12_16_global_base_scaling.sql
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
-- INSERT #devtools / #dev command
|
||||||
|
|
||||||
|
INSERT INTO `command_settings` (`command`, `access`, `aliases`)
|
||||||
|
VALUES
|
||||||
|
('devtools', 200, 'dev');
|
||||||
|
|
||||||
|
-- CREATE 'npc_scale_global_base'
|
||||||
|
|
||||||
|
CREATE TABLE `npc_scale_global_base` (
|
||||||
|
`type` int(11) NOT NULL DEFAULT '0',
|
||||||
|
`level` int(11) NOT NULL,
|
||||||
|
`ac` int(11) DEFAULT NULL,
|
||||||
|
`hp` int(11) DEFAULT NULL,
|
||||||
|
`accuracy` int(11) DEFAULT NULL,
|
||||||
|
`slow_mitigation` int(11) DEFAULT NULL,
|
||||||
|
`attack` int(11) DEFAULT NULL,
|
||||||
|
`strength` int(11) DEFAULT NULL,
|
||||||
|
`stamina` int(11) DEFAULT NULL,
|
||||||
|
`dexterity` int(11) DEFAULT NULL,
|
||||||
|
`agility` int(11) DEFAULT NULL,
|
||||||
|
`intelligence` int(11) DEFAULT NULL,
|
||||||
|
`wisdom` int(11) DEFAULT NULL,
|
||||||
|
`charisma` int(11) DEFAULT NULL,
|
||||||
|
`magic_resist` int(11) DEFAULT NULL,
|
||||||
|
`cold_resist` int(11) DEFAULT NULL,
|
||||||
|
`fire_resist` int(11) DEFAULT NULL,
|
||||||
|
`poison_resist` int(11) DEFAULT NULL,
|
||||||
|
`disease_resist` int(11) DEFAULT NULL,
|
||||||
|
`corruption_resist` int(11) DEFAULT NULL,
|
||||||
|
`physical_resist` int(11) DEFAULT NULL,
|
||||||
|
`min_dmg` int(11) DEFAULT NULL,
|
||||||
|
`max_dmg` int(11) DEFAULT NULL,
|
||||||
|
`hp_regen_rate` int(11) DEFAULT NULL,
|
||||||
|
`attack_delay` int(11) DEFAULT NULL,
|
||||||
|
`spell_scale` int(11) DEFAULT '100',
|
||||||
|
`heal_scale` int(11) DEFAULT '100',
|
||||||
|
`special_abilities` text,
|
||||||
|
PRIMARY KEY (`type`,`level`) USING BTREE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- INSERT 'npc_scale_global_base'
|
||||||
|
|
||||||
|
INSERT INTO `npc_scale_global_base` (`type`, `level`, `ac`, `hp`, `accuracy`, `slow_mitigation`, `attack`, `strength`, `stamina`, `dexterity`, `agility`, `intelligence`, `wisdom`, `charisma`, `magic_resist`, `cold_resist`, `fire_resist`, `poison_resist`, `disease_resist`, `corruption_resist`, `physical_resist`, `min_dmg`, `max_dmg`, `hp_regen_rate`, `attack_delay`, `spell_scale`, `heal_scale`, `special_abilities`)
|
||||||
|
VALUES
|
||||||
|
(0,1,8,11,0,0,0,8,8,8,8,8,8,8,1,1,1,1,1,1,10,1,6,1,30,100,100,''),
|
||||||
|
(0,2,11,27,0,0,0,11,11,11,11,11,11,11,1,1,1,1,1,2,10,1,8,2,30,100,100,''),
|
||||||
|
(0,3,14,43,0,0,0,14,14,14,14,14,14,14,2,2,2,2,2,2,10,1,10,3,30,100,100,''),
|
||||||
|
(0,4,16,59,0,0,0,17,17,17,17,17,17,17,2,2,2,2,2,3,10,1,12,4,30,100,100,''),
|
||||||
|
(0,5,19,75,0,0,0,20,20,20,20,20,20,20,2,2,2,2,2,3,10,1,14,5,30,100,100,''),
|
||||||
|
(0,6,22,100,0,0,0,23,23,23,23,23,23,23,2,2,2,2,2,4,10,1,16,6,30,100,100,''),
|
||||||
|
(0,7,25,125,0,0,0,26,26,26,26,26,26,26,3,3,3,3,3,4,10,1,18,7,30,100,100,''),
|
||||||
|
(0,8,28,150,0,0,0,29,29,29,29,29,29,29,3,3,3,3,3,5,10,1,20,8,30,100,100,''),
|
||||||
|
(0,9,31,175,0,0,0,32,32,32,32,32,32,32,4,4,4,4,4,5,10,1,22,9,30,100,100,''),
|
||||||
|
(0,10,34,200,0,0,0,35,35,35,35,35,35,35,4,4,4,4,4,6,10,1,24,10,30,100,100,''),
|
||||||
|
(0,11,37,234,0,0,0,38,38,38,38,38,38,38,5,5,5,5,5,7,10,3,27,11,30,100,100,''),
|
||||||
|
(0,12,40,268,0,0,0,42,42,42,42,42,42,42,5,5,5,5,5,8,10,4,30,12,30,100,100,''),
|
||||||
|
(0,13,43,302,0,0,0,45,45,45,45,45,45,45,6,6,6,6,6,8,10,6,32,13,30,100,100,''),
|
||||||
|
(0,14,46,336,0,0,0,48,48,48,48,48,48,48,6,6,6,6,6,9,10,7,35,14,30,100,100,''),
|
||||||
|
(0,15,52,381,0,0,0,51,51,51,51,51,51,51,6,6,6,6,6,10,10,7,37,15,30,100,100,''),
|
||||||
|
(0,16,59,426,0,0,0,54,54,54,54,54,54,54,7,7,7,7,7,10,10,8,39,16,30,100,100,''),
|
||||||
|
(0,17,65,471,0,0,0,57,57,57,57,57,57,57,7,7,7,7,7,11,10,8,41,17,30,100,100,''),
|
||||||
|
(0,18,72,516,0,0,0,60,60,60,60,60,60,60,7,7,7,7,7,11,10,9,42,18,30,100,100,''),
|
||||||
|
(0,19,78,561,0,0,0,63,63,63,63,63,63,63,7,7,7,7,7,12,10,9,44,19,30,100,100,''),
|
||||||
|
(0,20,85,606,0,0,0,66,66,66,66,66,66,66,8,8,8,8,8,12,10,10,46,20,30,100,100,''),
|
||||||
|
(0,21,91,651,0,0,0,69,69,69,69,69,69,69,8,8,8,8,8,13,10,10,48,21,30,100,100,''),
|
||||||
|
(0,22,95,712,0,0,0,72,72,72,72,72,72,72,8,8,8,8,8,14,10,10,50,22,30,100,100,''),
|
||||||
|
(0,23,99,773,0,0,0,75,75,75,75,75,75,75,9,9,9,9,9,14,10,10,52,23,30,100,100,''),
|
||||||
|
(0,24,103,834,0,0,0,78,78,78,78,78,78,78,9,9,9,9,9,15,10,11,55,24,30,100,100,''),
|
||||||
|
(0,25,107,895,0,0,0,81,81,81,81,81,81,81,10,10,10,10,10,16,10,11,57,25,30,100,100,''),
|
||||||
|
(0,26,111,956,0,0,0,85,85,85,85,85,85,85,10,10,10,10,10,16,10,11,59,26,30,100,100,''),
|
||||||
|
(0,27,115,1017,0,0,0,88,88,88,88,88,88,88,11,11,11,11,11,17,10,11,61,27,30,100,100,''),
|
||||||
|
(0,28,119,1078,0,0,0,91,91,91,91,91,91,91,11,11,11,11,11,18,10,12,64,28,30,100,100,''),
|
||||||
|
(0,29,123,1139,0,0,0,94,94,94,94,94,94,94,12,12,12,12,12,18,10,12,66,29,30,100,100,''),
|
||||||
|
(0,30,127,1200,0,0,0,97,97,97,97,97,97,97,12,12,12,12,12,19,10,12,68,30,30,100,100,''),
|
||||||
|
(0,31,135,1580,4,0,4,104,104,104,104,104,104,104,13,13,13,13,13,20,10,14,74,31,30,100,100,''),
|
||||||
|
(0,32,142,1960,8,0,8,110,110,110,110,110,110,110,14,14,14,14,14,22,10,16,79,32,30,100,100,''),
|
||||||
|
(0,33,150,2340,12,0,12,117,117,117,117,117,117,117,15,15,15,15,15,23,10,18,85,33,29,100,100,''),
|
||||||
|
(0,34,158,2720,16,0,16,123,123,123,123,123,123,123,16,16,16,16,16,25,10,20,90,34,28,100,100,''),
|
||||||
|
(0,35,166,3100,20,0,20,130,130,130,130,130,130,130,17,17,17,17,17,26,10,22,96,35,27,100,100,''),
|
||||||
|
(0,36,173,3480,24,0,24,137,137,137,137,137,137,137,17,17,17,17,17,27,10,24,102,36,25,100,100,''),
|
||||||
|
(0,37,181,3860,28,0,28,143,143,143,143,143,143,143,18,18,18,18,18,29,10,26,107,37,24,100,100,''),
|
||||||
|
(0,38,189,4240,32,0,32,150,150,150,150,150,150,150,19,19,19,19,19,30,10,28,113,38,23,100,100,''),
|
||||||
|
(0,39,196,4620,36,0,36,156,156,156,156,156,156,156,20,20,20,20,20,32,10,30,118,39,22,100,100,''),
|
||||||
|
(0,40,204,5000,40,0,40,163,163,163,163,163,163,163,21,21,21,21,21,33,10,32,124,40,21,100,100,''),
|
||||||
|
(0,41,208,5300,42,0,42,166,166,166,166,166,166,166,22,22,22,22,22,34,10,33,127,41,21,100,100,''),
|
||||||
|
(0,42,212,5600,44,0,44,169,169,169,169,169,169,169,22,22,22,22,22,35,10,34,130,42,21,100,100,''),
|
||||||
|
(0,43,217,5900,46,0,46,173,173,173,173,173,173,173,23,23,23,23,23,35,10,34,133,43,21,100,100,''),
|
||||||
|
(0,44,221,6200,48,0,48,176,176,176,176,176,176,176,23,23,23,23,23,36,10,35,136,44,21,100,100,''),
|
||||||
|
(0,45,225,6500,50,0,50,179,179,179,179,179,179,179,24,24,24,24,24,37,10,36,139,45,21,100,100,''),
|
||||||
|
(0,46,229,7200,50,0,50,182,182,182,182,182,182,182,24,24,24,24,24,38,10,44,152,46,21,100,100,''),
|
||||||
|
(0,47,233,7900,50,0,50,185,185,185,185,185,185,185,25,25,25,25,25,39,10,51,165,47,21,100,100,''),
|
||||||
|
(0,48,237,8600,50,0,50,188,188,188,188,188,188,188,25,25,25,25,25,39,10,59,178,48,21,100,100,''),
|
||||||
|
(0,49,241,9300,50,0,50,191,191,191,191,191,191,191,26,26,26,26,26,40,10,66,191,49,21,100,100,''),
|
||||||
|
(0,50,245,10000,50,0,50,194,194,194,194,194,194,194,26,26,26,26,26,41,10,74,204,50,21,100,100,''),
|
||||||
|
(0,51,249,11700,53,0,53,197,197,197,197,197,197,197,27,27,27,27,27,42,11,78,231,51,20,100,100,''),
|
||||||
|
(0,52,253,13400,56,0,56,200,200,200,200,200,200,200,27,27,27,27,27,43,12,81,258,52,20,100,100,''),
|
||||||
|
(0,53,257,15100,59,0,59,203,203,203,203,203,203,203,28,28,28,28,28,43,13,85,284,53,20,100,100,''),
|
||||||
|
(0,54,261,16800,62,10,62,206,206,206,206,206,206,206,28,28,28,28,28,44,14,89,311,54,20,100,100,''),
|
||||||
|
(0,55,266,18500,65,10,65,210,210,210,210,210,210,210,29,29,29,29,29,45,15,93,338,55,20,100,100,''),
|
||||||
|
(0,56,270,20200,68,10,68,213,213,213,213,213,213,213,29,29,29,29,29,46,16,96,365,56,20,100,100,''),
|
||||||
|
(0,57,274,21900,71,10,71,216,216,216,216,216,216,216,30,30,30,30,30,47,17,100,392,57,19,100,100,''),
|
||||||
|
(0,58,278,23600,74,10,74,219,219,219,219,219,219,219,30,30,30,30,30,47,18,104,418,58,19,100,100,'8,1'),
|
||||||
|
(0,59,282,25300,77,10,77,222,222,222,222,222,222,222,31,31,31,31,31,48,19,107,445,59,19,100,100,'8,1'),
|
||||||
|
(0,60,286,27000,80,20,80,225,225,225,225,225,225,225,31,31,31,31,31,49,20,111,472,60,19,100,100,'8,1^21,1'),
|
||||||
|
(0,61,290,28909,85,20,84,228,228,228,228,228,228,228,32,32,32,32,32,50,24,128,536,61,19,100,100,'8,1^21,1'),
|
||||||
|
(0,62,294,30818,91,20,87,231,231,231,231,231,231,231,32,32,32,32,32,51,28,145,599,62,18,100,100,'8,1^21,1'),
|
||||||
|
(0,63,299,32727,96,20,91,234,234,234,234,234,234,234,33,33,33,33,33,51,32,162,663,63,18,100,100,'8,1^21,1'),
|
||||||
|
(0,64,303,34636,102,20,95,237,237,237,237,237,237,237,33,33,33,33,33,52,36,179,727,64,18,100,100,'8,1^21,1'),
|
||||||
|
(0,65,307,36545,107,25,98,240,240,240,240,240,240,240,34,34,34,34,34,53,40,196,790,65,18,100,100,'8,1^21,1'),
|
||||||
|
(0,66,311,38455,113,25,102,244,244,244,244,244,244,244,34,34,34,34,34,54,44,213,854,66,18,100,100,'8,1^21,1'),
|
||||||
|
(0,67,315,40364,118,25,105,247,247,247,247,247,247,247,35,35,35,35,35,55,48,230,917,67,17,100,100,'8,1^21,1'),
|
||||||
|
(0,68,319,42273,124,25,109,250,250,250,250,250,250,250,35,35,35,35,35,56,52,247,981,68,17,100,100,'8,1^21,1'),
|
||||||
|
(0,69,324,44182,129,25,113,253,253,253,253,253,253,253,36,36,36,36,36,56,56,264,1045,69,17,100,100,'8,1^21,1'),
|
||||||
|
(0,70,328,46091,135,30,116,256,256,256,256,256,256,256,36,36,36,36,36,57,60,281,1108,70,17,100,100,'8,1^21,1'),
|
||||||
|
(0,71,332,48000,140,30,120,259,259,259,259,259,259,259,37,37,37,37,37,58,64,298,1172,71,17,100,100,'8,1^21,1'),
|
||||||
|
(0,72,336,49909,143,30,128,262,262,262,262,262,262,262,38,38,38,38,38,59,68,305,1193,72,17,100,100,'8,1^21,1'),
|
||||||
|
(0,73,340,51818,145,30,135,265,265,265,265,265,265,265,39,39,39,39,39,60,72,312,1214,73,17,100,100,'8,1^21,1'),
|
||||||
|
(0,74,344,53727,148,30,143,268,268,268,268,268,268,268,39,39,39,39,39,61,76,318,1235,74,17,100,100,'8,1^21,1'),
|
||||||
|
(0,75,348,55636,150,30,150,271,271,271,271,271,271,271,40,40,40,40,40,62,80,325,1256,75,17,100,100,'8,1^21,1'),
|
||||||
|
(0,76,352,75000,160,30,160,274,274,274,274,274,274,274,41,41,41,41,41,63,84,400,1600,76,17,100,100,'8,1^21,1'),
|
||||||
|
(0,77,356,90000,170,30,170,277,277,277,277,277,277,277,42,42,42,42,42,64,88,500,2050,77,17,100,100,'8,1^21,1'),
|
||||||
|
(0,78,360,113000,180,30,180,280,280,280,280,280,280,280,43,43,43,43,43,65,92,594,2323,120,17,100,100,'8,1^21,1'),
|
||||||
|
(0,79,364,130000,190,30,190,283,283,283,283,283,283,283,44,44,44,44,44,66,96,650,2500,130,17,100,100,'8,1^21,1'),
|
||||||
|
(0,80,368,140000,200,30,200,286,286,286,286,286,286,286,45,45,45,45,45,67,100,720,2799,140,16,100,100,'8,1^21,1'),
|
||||||
|
(0,81,372,240000,300,30,300,289,289,289,289,289,289,289,46,46,46,46,46,68,104,800,3599,240,16,100,100,'8,1^21,1'),
|
||||||
|
(0,82,376,340000,400,30,400,292,292,292,292,292,292,292,47,47,47,47,47,69,108,900,4599,340,16,100,100,'8,1^21,1'),
|
||||||
|
(0,83,380,440000,410,30,410,295,295,295,295,295,295,295,48,48,48,48,48,70,112,1275,4904,440,16,100,100,'8,1^21,1'),
|
||||||
|
(0,84,384,445000,420,30,420,298,298,298,298,298,298,298,49,49,49,49,49,71,116,1300,5100,445,16,100,100,'8,1^21,1'),
|
||||||
|
(0,85,388,450000,430,30,430,301,301,301,301,301,301,301,50,50,50,50,50,72,120,1359,5292,450,16,100,100,'8,1^21,1'),
|
||||||
|
(0,86,392,455000,440,30,440,304,304,304,304,304,304,304,51,51,51,51,51,73,124,1475,5578,455,16,100,100,'8,1^21,1'),
|
||||||
|
(0,87,396,460000,450,30,450,307,307,307,307,307,307,307,52,52,52,52,52,74,128,1510,5918,460,16,100,100,'8,1^21,1'),
|
||||||
|
(0,88,400,465000,460,30,460,310,310,310,310,310,310,310,53,53,53,53,53,75,132,1610,6200,465,16,100,100,'8,1^21,1'),
|
||||||
|
(0,89,404,470000,470,30,470,313,313,313,313,313,313,313,54,54,54,54,54,76,136,1650,6275,470,16,100,100,'8,1^21,1'),
|
||||||
|
(0,90,408,475000,480,30,480,316,316,316,316,316,316,316,55,55,55,55,55,77,140,1700,6350,475,16,100,100,'8,1^21,1'),
|
||||||
|
(1,1,10,13,0,0,0,10,10,10,10,10,10,10,1,1,1,1,1,1,12,1,7,1,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,2,13,32,0,0,0,13,13,13,13,13,13,13,1,1,1,1,1,2,12,1,10,2,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,3,17,52,0,0,0,17,17,17,17,17,17,17,2,2,2,2,2,2,12,1,12,4,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,4,19,71,0,0,0,20,20,20,20,20,20,20,2,2,2,2,2,4,12,1,14,5,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,5,23,90,0,0,0,24,24,24,24,24,24,24,2,2,2,2,2,4,12,1,17,6,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,6,26,120,0,0,0,28,28,28,28,28,28,28,2,2,2,2,2,5,12,1,19,7,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,7,30,150,0,0,0,31,31,31,31,31,31,31,4,4,4,4,4,5,12,1,22,8,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,8,34,180,0,0,0,35,35,35,35,35,35,35,4,4,4,4,4,6,12,1,24,10,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,9,37,210,0,0,0,38,38,38,38,38,38,38,5,5,5,5,5,6,12,1,26,11,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,10,41,240,0,0,0,42,42,42,42,42,42,42,5,5,5,5,5,7,12,1,29,12,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,11,44,281,0,0,0,46,46,46,46,46,46,46,6,6,6,6,6,8,12,4,32,13,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,12,48,322,0,0,0,50,50,50,50,50,50,50,6,6,6,6,6,10,12,5,36,14,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,13,52,362,0,0,0,54,54,54,54,54,54,54,7,7,7,7,7,10,12,7,38,16,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,14,55,403,0,0,0,58,58,58,58,58,58,58,7,7,7,7,7,11,12,8,42,17,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,15,62,457,0,0,0,61,61,61,61,61,61,61,7,7,7,7,7,12,12,8,44,18,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,16,71,511,0,0,0,65,65,65,65,65,65,65,8,8,8,8,8,12,12,10,47,19,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,17,78,565,0,0,0,68,68,68,68,68,68,68,8,8,8,8,8,13,12,10,49,20,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,18,86,619,0,0,0,72,72,72,72,72,72,72,8,8,8,8,8,13,12,11,50,22,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,19,94,673,0,0,0,76,76,76,76,76,76,76,8,8,8,8,8,14,12,11,53,23,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,20,102,727,0,0,0,79,79,79,79,79,79,79,10,10,10,10,10,14,12,12,55,24,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,21,109,781,0,0,0,83,83,83,83,83,83,83,10,10,10,10,10,16,12,12,58,25,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,22,114,854,0,0,0,86,86,86,86,86,86,86,10,10,10,10,10,17,12,12,60,26,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,23,119,928,0,0,0,90,90,90,90,90,90,90,11,11,11,11,11,17,12,12,62,28,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,24,124,1001,0,0,0,94,94,94,94,94,94,94,11,11,11,11,11,18,12,13,66,29,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,25,128,1074,0,0,0,97,97,97,97,97,97,97,12,12,12,12,12,19,12,13,68,30,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,26,133,1147,0,0,0,102,102,102,102,102,102,102,12,12,12,12,12,19,12,13,71,31,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,27,138,1220,0,0,0,106,106,106,106,106,106,106,13,13,13,13,13,20,12,13,73,32,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,28,143,1294,0,0,0,109,109,109,109,109,109,109,13,13,13,13,13,22,12,14,77,34,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,29,148,1367,0,0,0,113,113,113,113,113,113,113,14,14,14,14,14,22,12,14,79,35,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,30,152,1440,0,0,0,116,116,116,116,116,116,116,14,14,14,14,14,23,12,14,82,36,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,31,162,1896,5,0,5,125,125,125,125,125,125,125,16,16,16,16,16,24,12,17,89,37,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,32,170,2352,10,0,10,132,132,132,132,132,132,132,17,17,17,17,17,26,12,19,95,38,30,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,33,180,2808,14,0,14,140,140,140,140,140,140,140,18,18,18,18,18,28,12,22,102,40,29,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,34,190,3264,19,0,19,148,148,148,148,148,148,148,19,19,19,19,19,30,12,24,108,41,28,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,35,199,3720,24,0,24,156,156,156,156,156,156,156,20,20,20,20,20,31,12,26,115,42,27,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,36,208,4176,29,0,29,164,164,164,164,164,164,164,20,20,20,20,20,32,12,29,122,43,25,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,37,217,4632,34,0,34,172,172,172,172,172,172,172,22,22,22,22,22,35,12,31,128,44,24,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,38,227,5088,38,0,38,180,180,180,180,180,180,180,23,23,23,23,23,36,12,34,136,46,23,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,39,235,5544,43,0,43,187,187,187,187,187,187,187,24,24,24,24,24,38,12,36,142,47,22,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,40,245,6000,48,0,48,196,196,196,196,196,196,196,25,25,25,25,25,40,12,38,149,48,21,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,41,250,6360,50,0,50,199,199,199,199,199,199,199,26,26,26,26,26,41,12,40,152,49,21,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,42,254,6720,53,0,53,203,203,203,203,203,203,203,26,26,26,26,26,42,12,41,156,50,21,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,43,260,7080,55,0,55,208,208,208,208,208,208,208,28,28,28,28,28,42,12,41,160,52,21,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,44,265,7440,58,0,58,211,211,211,211,211,211,211,28,28,28,28,28,43,12,42,163,53,21,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,45,270,7800,60,0,60,215,215,215,215,215,215,215,29,29,29,29,29,44,12,43,167,54,21,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,46,275,8640,60,0,60,218,218,218,218,218,218,218,29,29,29,29,29,46,12,53,182,55,21,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,47,280,9480,60,0,60,222,222,222,222,222,222,222,30,30,30,30,30,47,12,61,198,56,21,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,48,284,10320,60,0,60,226,226,226,226,226,226,226,30,30,30,30,30,47,12,71,214,58,21,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,49,289,11160,60,0,60,229,229,229,229,229,229,229,31,31,31,31,31,48,12,79,229,59,21,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,50,294,12000,60,0,60,233,233,233,233,233,233,233,31,31,31,31,31,49,12,89,245,60,21,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,51,299,14040,64,0,64,236,236,236,236,236,236,236,32,32,32,32,32,50,13,94,277,61,20,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,52,304,16080,67,0,67,240,240,240,240,240,240,240,32,32,32,32,32,52,14,97,310,62,20,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,53,308,18120,71,0,71,244,244,244,244,244,244,244,34,34,34,34,34,52,16,102,341,64,20,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,54,313,20160,74,0,74,247,247,247,247,247,247,247,34,34,34,34,34,53,17,107,373,65,20,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,55,319,22200,78,0,78,252,252,252,252,252,252,252,35,35,35,35,35,54,18,112,406,66,20,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,56,324,24240,82,0,82,256,256,256,256,256,256,256,35,35,35,35,35,55,19,115,438,67,20,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,57,329,26280,85,0,85,259,259,259,259,259,259,259,36,36,36,36,36,56,20,120,470,68,19,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,58,334,28320,89,0,89,263,263,263,263,263,263,263,36,36,36,36,36,56,22,125,502,70,19,100,100,'13,1^14,1^21,1'),
|
||||||
|
(1,59,338,30360,92,0,92,266,266,266,266,266,266,266,37,37,37,37,37,58,23,128,534,71,19,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,60,343,32400,96,30,96,270,270,270,270,270,270,270,37,37,37,37,37,59,24,133,566,72,19,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,61,348,34691,102,30,101,274,274,274,274,274,274,274,38,38,38,38,38,60,29,154,643,73,19,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,62,353,36982,109,30,104,277,277,277,277,277,277,277,38,38,38,38,38,61,34,174,719,74,18,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,63,359,39272,115,30,109,281,281,281,281,281,281,281,40,40,40,40,40,61,38,194,796,76,18,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,64,364,41563,122,30,114,284,284,284,284,284,284,284,40,40,40,40,40,62,43,215,872,77,18,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,65,368,43854,128,35,118,288,288,288,288,288,288,288,41,41,41,41,41,64,48,235,948,78,18,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,66,373,46146,136,35,122,293,293,293,293,293,293,293,41,41,41,41,41,65,53,256,1025,79,18,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,67,378,48437,142,35,126,296,296,296,296,296,296,296,42,42,42,42,42,66,58,276,1100,80,17,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,68,383,50728,149,35,131,300,300,300,300,300,300,300,42,42,42,42,42,67,62,296,1177,82,17,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,69,389,53018,155,35,136,304,304,304,304,304,304,304,43,43,43,43,43,67,67,317,1254,83,17,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,70,394,55309,162,40,139,307,307,307,307,307,307,307,43,43,43,43,43,68,72,337,1330,84,17,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,71,398,57600,168,40,144,311,311,311,311,311,311,311,44,44,44,44,44,70,77,358,1406,85,17,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,72,403,57600,172,40,154,314,314,314,314,314,314,314,46,46,46,46,46,71,82,366,1432,86,17,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,73,408,57600,174,40,162,318,318,318,318,318,318,318,47,47,47,47,47,72,86,374,1457,88,17,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,74,413,57600,178,40,172,322,322,322,322,322,322,322,47,47,47,47,47,73,91,382,1482,89,17,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,75,418,57600,180,40,180,325,325,325,325,325,325,325,48,48,48,48,48,74,96,390,1507,90,17,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,76,423,90000,192,45,192,329,329,329,329,329,329,329,49,49,49,49,49,76,101,480,1920,91,17,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,77,428,108000,204,45,204,332,332,332,332,332,332,332,50,50,50,50,50,77,106,600,2460,92,17,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,78,433,135600,216,45,216,336,336,336,336,336,336,336,52,52,52,52,52,78,110,713,2788,144,17,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,79,438,156000,228,45,228,340,340,340,340,340,340,340,53,53,53,53,53,79,115,780,3000,156,17,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,80,443,168000,240,45,240,343,343,343,343,343,343,343,54,54,54,54,54,80,120,864,3359,168,16,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,81,448,288000,360,45,360,347,347,347,347,347,347,347,55,55,55,55,55,82,125,960,4319,288,16,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,82,453,408000,480,45,480,350,350,350,350,350,350,350,56,56,56,56,56,83,130,1080,5519,408,16,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,83,458,528000,492,45,492,354,354,354,354,354,354,354,58,58,58,58,58,84,134,1530,5885,528,16,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,84,463,534000,504,45,504,358,358,358,358,358,358,358,59,59,59,59,59,85,139,1560,6120,534,16,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,85,468,540000,516,45,516,361,361,361,361,361,361,361,60,60,60,60,60,86,144,1631,6350,540,16,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,86,473,546000,528,45,528,365,365,365,365,365,365,365,61,61,61,61,61,88,149,1770,6694,546,16,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,87,478,552000,540,45,540,368,368,368,368,368,368,368,62,62,62,62,62,89,154,1812,7102,552,16,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,88,483,558000,552,45,552,372,372,372,372,372,372,372,64,64,64,64,64,90,158,1932,7440,558,16,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,89,488,564000,564,45,564,376,376,376,376,376,376,376,65,65,65,65,65,91,163,1980,7530,564,16,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(1,90,490,570000,576,45,576,379,379,379,379,379,379,379,66,66,66,66,66,92,168,2040,7620,570,16,100,100,'1,1^8,1^13,1^14,1^21,1'),
|
||||||
|
(2,1,12,17,0,0,0,12,12,12,12,12,12,12,2,2,2,2,2,2,15,2,9,2,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,2,17,41,0,0,0,17,17,17,17,17,17,17,4,4,4,4,4,4,15,2,12,3,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,3,21,65,0,0,0,21,21,21,21,21,21,21,6,6,6,6,6,6,15,2,15,5,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,4,24,89,0,0,0,26,26,26,26,26,26,26,8,8,8,8,8,8,15,2,18,6,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,5,29,113,0,0,0,30,30,30,30,30,30,30,10,10,10,10,10,10,15,2,21,8,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,6,33,150,0,0,0,35,35,35,35,35,35,35,12,12,12,12,12,12,15,2,24,9,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,7,38,188,0,0,0,39,39,39,39,39,39,39,14,14,14,14,14,14,15,2,27,11,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,8,42,225,0,0,0,44,44,44,44,44,44,44,16,16,16,16,16,16,15,2,30,12,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,9,47,263,0,0,0,48,48,48,48,48,48,48,18,18,18,18,18,18,15,2,33,14,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,10,51,300,0,0,0,53,53,53,53,53,53,53,20,20,20,20,20,20,15,2,36,15,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,11,56,351,0,0,0,57,57,57,57,57,57,57,22,22,22,22,22,22,15,5,41,17,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,12,60,402,0,0,0,63,63,63,63,63,63,63,24,24,24,24,24,24,15,6,45,18,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,13,65,453,0,0,0,68,68,68,68,68,68,68,26,26,26,26,26,26,15,9,48,20,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,14,69,504,0,0,0,72,72,72,72,72,72,72,28,28,28,28,28,28,15,11,53,21,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,15,78,572,0,0,0,77,77,77,77,77,77,77,30,30,30,30,30,30,15,11,56,23,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,16,89,639,0,0,0,81,81,81,81,81,81,81,32,32,32,32,32,32,15,12,59,24,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,17,98,707,0,0,0,86,86,86,86,86,86,86,34,34,34,34,34,34,15,12,62,26,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,18,108,774,0,0,0,90,90,90,90,90,90,90,36,36,36,36,36,36,15,14,63,27,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,19,117,842,0,0,0,95,95,95,95,95,95,95,38,38,38,38,38,38,15,14,66,29,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,20,128,909,0,0,0,99,99,99,99,99,99,99,40,40,40,40,40,40,15,15,69,30,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,21,137,977,0,0,0,104,104,104,104,104,104,104,42,42,42,42,42,42,15,15,72,32,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,22,143,1068,0,0,0,108,108,108,108,108,108,108,44,44,44,44,44,44,15,15,75,33,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,23,149,1160,0,0,0,113,113,113,113,113,113,113,46,46,46,46,46,46,15,15,78,35,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,24,155,1251,0,0,0,117,117,117,117,117,117,117,48,48,48,48,48,48,15,17,83,36,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,25,161,1343,0,0,0,122,122,122,122,122,122,122,50,50,50,50,50,50,15,17,86,38,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,26,167,1434,0,0,0,128,128,128,128,128,128,128,52,52,52,52,52,52,15,17,89,39,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,27,173,1526,0,0,0,132,132,132,132,132,132,132,54,54,54,54,54,54,15,17,92,41,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,28,179,1617,0,0,0,137,137,137,137,137,137,137,56,56,56,56,56,56,15,18,96,42,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,29,185,1709,0,0,0,141,141,141,141,141,141,141,58,58,58,58,58,58,15,18,99,44,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,30,191,1800,0,0,0,146,146,146,146,146,146,146,60,60,60,60,60,60,15,18,102,45,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,31,203,2370,6,0,6,156,156,156,156,156,156,156,62,62,62,62,62,62,15,21,111,47,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,32,213,2940,12,0,12,165,165,165,165,165,165,165,64,64,64,64,64,64,15,24,119,48,30,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,33,225,3510,18,0,18,176,176,176,176,176,176,176,66,66,66,66,66,66,15,27,128,50,29,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,34,237,4080,24,0,24,185,185,185,185,185,185,185,68,68,68,68,68,68,15,30,135,51,28,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,35,249,4650,30,0,30,195,195,195,195,195,195,195,70,70,70,70,70,70,15,33,144,53,27,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,36,260,5220,36,0,36,206,206,206,206,206,206,206,72,72,72,72,72,72,15,36,153,54,25,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,37,272,5790,42,0,42,215,215,215,215,215,215,215,74,74,74,74,74,74,15,39,161,56,24,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,38,284,6360,48,0,48,225,225,225,225,225,225,225,76,76,76,76,76,76,15,42,170,57,23,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,39,294,6930,54,0,54,234,234,234,234,234,234,234,78,78,78,78,78,78,15,45,177,59,22,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,40,306,7500,60,0,60,245,245,245,245,245,245,245,80,80,80,80,80,80,15,48,186,60,21,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,41,312,7950,63,0,63,249,249,249,249,249,249,249,82,82,82,82,82,82,15,50,191,62,21,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,42,318,8400,66,0,66,254,254,254,254,254,254,254,84,84,84,84,84,84,15,51,195,63,21,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,43,326,11000,69,0,69,260,260,260,260,260,260,260,86,86,86,86,86,86,15,51,200,65,21,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,44,332,25000,72,0,72,264,264,264,264,264,264,264,88,88,88,88,88,88,15,53,204,66,21,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,45,338,35000,75,0,75,269,269,269,269,269,269,269,90,90,90,90,90,90,15,54,209,68,21,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,46,344,45000,75,0,75,273,273,273,273,273,273,273,92,92,92,92,92,92,15,66,228,69,21,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,47,350,55000,75,0,75,278,278,278,278,278,278,278,94,94,94,94,94,94,15,77,248,71,21,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,48,356,70000,75,0,75,282,282,282,282,282,282,282,96,96,96,96,96,96,15,89,267,72,21,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,49,362,85000,75,0,75,287,287,287,287,287,287,287,98,98,98,98,98,98,15,99,287,74,21,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,50,368,100000,75,0,75,291,291,291,291,291,291,291,100,100,100,100,100,100,15,111,306,75,21,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,51,374,130000,80,0,80,296,296,296,296,296,296,296,102,102,102,102,102,102,17,117,347,77,20,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,52,380,140000,84,0,84,300,300,300,300,300,300,300,104,104,104,104,104,104,18,122,387,78,20,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,53,386,150000,89,0,89,305,305,305,305,305,305,305,106,106,106,106,106,106,20,128,426,80,19,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,54,392,160000,93,0,93,309,309,309,309,309,309,309,108,108,108,108,108,108,21,134,467,81,19,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,55,399,170000,98,0,98,315,315,315,315,315,315,315,110,110,110,110,110,110,23,140,507,83,18,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,56,405,180000,102,0,102,320,320,320,320,320,320,320,112,112,112,112,112,112,24,144,548,84,17,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,57,411,190000,107,0,107,324,324,324,324,324,324,324,114,114,114,114,114,114,26,150,588,86,17,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,58,417,200000,111,0,111,329,329,329,329,329,329,329,116,116,116,116,116,116,27,156,627,87,16,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,59,434,400750,130,0,125,253,253,253,253,253,253,253,118,118,118,118,118,118,19,170,700,141,16,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,60,476,450813,140,0,129,258,258,258,258,258,258,258,120,120,120,120,120,120,22,185,740,194,15,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,61,517,500875,145,0,130,263,263,263,263,263,263,263,122,122,122,122,122,122,26,195,780,246,15,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,62,559,550938,150,0,140,268,268,268,268,268,268,268,124,124,124,124,124,124,29,210,800,299,15,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,63,600,601000,155,0,160,273,273,273,273,273,273,273,126,126,126,126,126,126,32,220,825,351,15,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,64,563,734167,160,0,170,277,277,277,277,277,277,277,128,128,128,128,128,128,50,241,850,401,15,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,65,525,867333,165,0,180,281,281,281,281,281,281,281,130,130,130,130,130,130,67,262,875,450,14,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,66,488,1000500,170,0,190,285,285,285,285,285,285,285,132,132,132,132,132,132,85,283,904,500,14,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,67,498,1013841,175,10,200,292,292,292,292,292,292,292,134,134,134,134,134,134,81,312,1071,600,14,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,68,508,1027182,180,20,225,300,300,300,300,300,300,300,136,136,136,136,136,136,77,341,1238,700,14,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,69,519,1040522,185,30,239,307,307,307,307,307,307,307,138,138,138,138,138,138,72,369,1404,800,14,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,70,529,1053863,190,40,245,315,315,315,315,315,315,315,140,140,140,140,140,140,68,398,1571,900,14,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,71,539,1067204,200,50,255,322,322,322,322,322,322,322,142,142,142,142,142,142,64,427,1738,1000,14,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,72,547,1262903,220,56,265,327,327,327,327,327,327,327,144,144,144,144,144,144,68,520,1979,1125,14,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,73,556,1458602,253,63,285,332,332,332,332,332,332,332,146,146,146,146,146,146,72,614,2219,1250,13,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,74,564,1654301,306,69,300,337,337,337,337,337,337,337,148,148,148,148,148,148,76,707,2460,1375,13,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,75,572,1850000,330,75,310,342,342,342,342,342,342,342,150,150,150,150,150,150,80,725,2700,1500,13,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,76,579,1900000,348,77,320,346,346,346,346,346,346,346,152,152,152,152,152,152,84,750,2960,1600,13,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,77,586,1950000,355,79,330,350,350,350,350,350,350,350,154,154,154,154,154,154,88,775,3000,1700,13,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,78,594,2000000,365,81,340,354,354,354,354,354,354,354,156,156,156,156,156,156,92,800,3100,1800,13,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,79,601,2050000,375,83,350,358,358,358,358,358,358,358,158,158,158,158,158,158,96,825,3200,1900,13,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,80,608,2100000,380,85,360,362,362,362,362,362,362,362,160,160,160,160,160,160,100,850,3300,2000,13,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,81,615,2480000,385,83,370,366,366,366,366,366,366,366,162,162,162,162,162,162,104,875,3350,3000,13,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,82,622,2860000,390,81,380,370,370,370,370,370,370,370,164,164,164,164,164,164,108,900,3400,4000,13,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,83,629,3240000,395,79,390,375,375,375,375,375,375,375,166,166,166,166,166,166,112,925,3450,5000,13,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,84,636,3620000,400,77,400,379,379,379,379,379,379,379,168,168,168,168,168,168,116,940,3500,6000,13,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,85,643,4000000,405,75,410,383,383,383,383,383,383,383,170,170,170,170,170,170,120,960,3550,7000,12,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,86,650,4800000,410,77,420,387,387,387,387,387,387,387,172,172,172,172,172,172,124,980,3600,8000,12,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,87,657,5600000,415,79,430,391,391,391,391,391,391,391,174,174,174,174,174,174,128,1000,3650,9000,12,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,88,665,6400000,420,81,440,395,395,395,395,395,395,395,176,176,176,176,176,176,132,1010,3700,10000,12,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,89,672,7200000,420,83,445,399,399,399,399,399,399,399,178,178,178,178,178,178,136,1018,3800,11000,12,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1'),
|
||||||
|
(2,90,679,8000000,420,85,450,403,403,403,403,403,403,403,180,180,180,180,180,180,140,1050,3900,12000,12,100,100,'1,1^2,1^8,1^13,1^14,1^15,1^16,1^17,1^21,1^31,1');
|
||||||
@ -60,9 +60,11 @@ merc_types
|
|||||||
merc_weaponinfo
|
merc_weaponinfo
|
||||||
merchantlist
|
merchantlist
|
||||||
mercs
|
mercs
|
||||||
|
name_filter
|
||||||
npc_emotes
|
npc_emotes
|
||||||
npc_faction
|
npc_faction
|
||||||
npc_faction_entries
|
npc_faction_entries
|
||||||
|
npc_scale_global_base
|
||||||
npc_spells
|
npc_spells
|
||||||
npc_spells_effects
|
npc_spells_effects
|
||||||
npc_spells_effects_entries
|
npc_spells_effects_entries
|
||||||
|
|||||||
@ -59,7 +59,6 @@ launcher_zones
|
|||||||
lfguild
|
lfguild
|
||||||
mail
|
mail
|
||||||
merchantlist_temp
|
merchantlist_temp
|
||||||
name_filter
|
|
||||||
object_contents
|
object_contents
|
||||||
petitions
|
petitions
|
||||||
player_titlesets
|
player_titlesets
|
||||||
@ -86,6 +85,7 @@ reports
|
|||||||
respawn_times
|
respawn_times
|
||||||
sharedbank
|
sharedbank
|
||||||
spell_globals
|
spell_globals
|
||||||
|
spell_buckets
|
||||||
timers
|
timers
|
||||||
trader
|
trader
|
||||||
trader_audit
|
trader_audit
|
||||||
|
|||||||
@ -83,10 +83,12 @@ SET(zone_sources
|
|||||||
mob.cpp
|
mob.cpp
|
||||||
mob_ai.cpp
|
mob_ai.cpp
|
||||||
mob_movement_manager.cpp
|
mob_movement_manager.cpp
|
||||||
|
mob_info.cpp
|
||||||
mod_functions.cpp
|
mod_functions.cpp
|
||||||
net.cpp
|
net.cpp
|
||||||
npc.cpp
|
npc.cpp
|
||||||
npc_ai.cpp
|
npc_ai.cpp
|
||||||
|
npc_scale_manager.cpp
|
||||||
object.cpp
|
object.cpp
|
||||||
oriented_bounding_box.cpp
|
oriented_bounding_box.cpp
|
||||||
pathfinder_interface.cpp
|
pathfinder_interface.cpp
|
||||||
@ -138,8 +140,7 @@ SET(zone_sources
|
|||||||
zone.cpp
|
zone.cpp
|
||||||
zone_config.cpp
|
zone_config.cpp
|
||||||
zonedb.cpp
|
zonedb.cpp
|
||||||
zoning.cpp
|
zoning.cpp)
|
||||||
)
|
|
||||||
|
|
||||||
SET(zone_headers
|
SET(zone_headers
|
||||||
aa.h
|
aa.h
|
||||||
@ -209,6 +210,7 @@ SET(zone_headers
|
|||||||
net.h
|
net.h
|
||||||
npc.h
|
npc.h
|
||||||
npc_ai.h
|
npc_ai.h
|
||||||
|
npc_scale_manager.h
|
||||||
object.h
|
object.h
|
||||||
oriented_bounding_box.h
|
oriented_bounding_box.h
|
||||||
pathfinder_interface.h
|
pathfinder_interface.h
|
||||||
@ -244,8 +246,7 @@ SET(zone_headers
|
|||||||
zone.h
|
zone.h
|
||||||
zone_config.h
|
zone_config.h
|
||||||
zonedb.h
|
zonedb.h
|
||||||
zonedump.h
|
zonedump.h)
|
||||||
)
|
|
||||||
|
|
||||||
IF(EQEMU_DEPOP_INVALIDATES_CACHE)
|
IF(EQEMU_DEPOP_INVALIDATES_CACHE)
|
||||||
ADD_DEFINITIONS(-DDEPOP_INVALIDATES_NPC_TYPES_CACHE)
|
ADD_DEFINITIONS(-DDEPOP_INVALIDATES_NPC_TYPES_CACHE)
|
||||||
|
|||||||
@ -37,6 +37,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <boost/concept_check.hpp>
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
#include "bot.h"
|
#include "bot.h"
|
||||||
@ -5457,3 +5458,13 @@ bool Mob::GetWasSpawnedInWater() const {
|
|||||||
void Mob::SetSpawnedInWater(bool spawned_in_water) {
|
void Mob::SetSpawnedInWater(bool spawned_in_water) {
|
||||||
Mob::spawned_in_water = spawned_in_water;
|
Mob::spawned_in_water = spawned_in_water;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 Mob::GetHPRegen() const
|
||||||
|
{
|
||||||
|
return hp_regen;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 Mob::GetManaRegen() const
|
||||||
|
{
|
||||||
|
return mana_regen;
|
||||||
|
}
|
||||||
@ -58,12 +58,12 @@ void Mob::CalcBonuses()
|
|||||||
void NPC::CalcBonuses()
|
void NPC::CalcBonuses()
|
||||||
{
|
{
|
||||||
memset(&itembonuses, 0, sizeof(StatBonuses));
|
memset(&itembonuses, 0, sizeof(StatBonuses));
|
||||||
if(RuleB(NPC, UseItemBonusesForNonPets)){
|
if (RuleB(NPC, UseItemBonusesForNonPets)) {
|
||||||
memset(&itembonuses, 0, sizeof(StatBonuses));
|
memset(&itembonuses, 0, sizeof(StatBonuses));
|
||||||
CalcItemBonuses(&itembonuses);
|
CalcItemBonuses(&itembonuses);
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
if(GetOwner()){
|
if (GetOwner()) {
|
||||||
memset(&itembonuses, 0, sizeof(StatBonuses));
|
memset(&itembonuses, 0, sizeof(StatBonuses));
|
||||||
CalcItemBonuses(&itembonuses);
|
CalcItemBonuses(&itembonuses);
|
||||||
}
|
}
|
||||||
|
|||||||
149
zone/client.cpp
149
zone/client.cpp
@ -38,6 +38,7 @@ extern volatile bool RunLoops;
|
|||||||
#include "../common/rulesys.h"
|
#include "../common/rulesys.h"
|
||||||
#include "../common/string_util.h"
|
#include "../common/string_util.h"
|
||||||
#include "../common/data_verification.h"
|
#include "../common/data_verification.h"
|
||||||
|
#include "data_bucket.h"
|
||||||
#include "position.h"
|
#include "position.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "worldserver.h"
|
#include "worldserver.h"
|
||||||
@ -254,7 +255,6 @@ Client::Client(EQStreamInterface* ieqs)
|
|||||||
InitializeMercInfo();
|
InitializeMercInfo();
|
||||||
SetMerc(0);
|
SetMerc(0);
|
||||||
if (RuleI(World, PVPMinLevel) > 0 && level >= RuleI(World, PVPMinLevel) && m_pp.pvp == 0) SetPVP(true, false);
|
if (RuleI(World, PVPMinLevel) > 0 && level >= RuleI(World, PVPMinLevel) && m_pp.pvp == 0) SetPVP(true, false);
|
||||||
logging_enabled = CLIENT_DEFAULT_LOGGING_ENABLED;
|
|
||||||
|
|
||||||
//for good measure:
|
//for good measure:
|
||||||
memset(&m_pp, 0, sizeof(m_pp));
|
memset(&m_pp, 0, sizeof(m_pp));
|
||||||
@ -263,6 +263,16 @@ Client::Client(EQStreamInterface* ieqs)
|
|||||||
PendingSacrifice = false;
|
PendingSacrifice = false;
|
||||||
controlling_boat_id = 0;
|
controlling_boat_id = 0;
|
||||||
|
|
||||||
|
if (!RuleB(Character, PerCharacterQglobalMaxLevel) && !RuleB(Character, PerCharacterBucketMaxLevel)) {
|
||||||
|
SetClientMaxLevel(0);
|
||||||
|
} else if (RuleB(Character, PerCharacterQglobalMaxLevel)) {
|
||||||
|
int client_max_level = GetCharMaxLevelFromQGlobal();
|
||||||
|
SetClientMaxLevel(client_max_level);
|
||||||
|
} else if (RuleB(Character, PerCharacterBucketMaxLevel)) {
|
||||||
|
int client_max_level = GetCharMaxLevelFromBucket();
|
||||||
|
SetClientMaxLevel(client_max_level);
|
||||||
|
}
|
||||||
|
|
||||||
KarmaUpdateTimer = new Timer(RuleI(Chat, KarmaUpdateIntervalMS));
|
KarmaUpdateTimer = new Timer(RuleI(Chat, KarmaUpdateIntervalMS));
|
||||||
GlobalChatLimiterTimer = new Timer(RuleI(Chat, IntervalDurationMS));
|
GlobalChatLimiterTimer = new Timer(RuleI(Chat, IntervalDurationMS));
|
||||||
AttemptedMessages = 0;
|
AttemptedMessages = 0;
|
||||||
@ -327,6 +337,12 @@ Client::Client(EQStreamInterface* ieqs)
|
|||||||
temp_pvp = false;
|
temp_pvp = false;
|
||||||
is_client_moving = false;
|
is_client_moving = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GM
|
||||||
|
*/
|
||||||
|
display_mob_info_window = true;
|
||||||
|
dev_tools_window_enabled = true;
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
bot_owner_options = DefaultBotOwnerOptions;
|
bot_owner_options = DefaultBotOwnerOptions;
|
||||||
#endif
|
#endif
|
||||||
@ -1642,7 +1658,6 @@ void Client::FriendsWho(char *FriendsString) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Client::UpdateAdmin(bool iFromDB) {
|
void Client::UpdateAdmin(bool iFromDB) {
|
||||||
int16 tmp = admin;
|
int16 tmp = admin;
|
||||||
if (iFromDB)
|
if (iFromDB)
|
||||||
@ -1960,7 +1975,6 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
|
|||||||
// ns->spawn.pvp = GetPVP(false) ? 1 : 0;
|
// ns->spawn.pvp = GetPVP(false) ? 1 : 0;
|
||||||
ns->spawn.show_name = true;
|
ns->spawn.show_name = true;
|
||||||
|
|
||||||
|
|
||||||
strcpy(ns->spawn.title, m_pp.title);
|
strcpy(ns->spawn.title, m_pp.title);
|
||||||
strcpy(ns->spawn.suffix, m_pp.suffix);
|
strcpy(ns->spawn.suffix, m_pp.suffix);
|
||||||
|
|
||||||
@ -4026,9 +4040,9 @@ void Client::SetHoTT(uint32 mobid) {
|
|||||||
|
|
||||||
void Client::SendPopupToClient(const char *Title, const char *Text, uint32 PopupID, uint32 Buttons, uint32 Duration)
|
void Client::SendPopupToClient(const char *Title, const char *Text, uint32 PopupID, uint32 Buttons, uint32 Duration)
|
||||||
{
|
{
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct));
|
auto outapp = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct));
|
||||||
OnLevelMessage_Struct *olms = (OnLevelMessage_Struct *)outapp->pBuffer;
|
|
||||||
|
OnLevelMessage_Struct *olms = (OnLevelMessage_Struct *) outapp->pBuffer;
|
||||||
|
|
||||||
if ((strlen(Title) > (sizeof(olms->Title) - 1)) || (strlen(Text) > (sizeof(olms->Text) - 1))) {
|
if ((strlen(Title) > (sizeof(olms->Title) - 1)) || (strlen(Text) > (sizeof(olms->Text) - 1))) {
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
@ -4040,10 +4054,12 @@ void Client::SendPopupToClient(const char *Title, const char *Text, uint32 Popup
|
|||||||
|
|
||||||
olms->Buttons = Buttons;
|
olms->Buttons = Buttons;
|
||||||
|
|
||||||
if (Duration > 0)
|
if (Duration > 0) {
|
||||||
olms->Duration = Duration * 1000;
|
olms->Duration = Duration * 1000;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
olms->Duration = 0xffffffff;
|
olms->Duration = 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
olms->PopupID = PopupID;
|
olms->PopupID = PopupID;
|
||||||
olms->NegativeID = 0;
|
olms->NegativeID = 0;
|
||||||
@ -4054,16 +4070,29 @@ void Client::SendPopupToClient(const char *Title, const char *Text, uint32 Popup
|
|||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::SendFullPopup(const char *Title, const char *Text, uint32 PopupID, uint32 NegativeID, uint32 Buttons, uint32 Duration, const char *ButtonName0, const char *ButtonName1, uint32 SoundControls) {
|
void Client::SendFullPopup(
|
||||||
|
const char *Title,
|
||||||
|
const char *Text,
|
||||||
|
uint32 PopupID,
|
||||||
|
uint32 NegativeID,
|
||||||
|
uint32 Buttons,
|
||||||
|
uint32 Duration,
|
||||||
|
const char *ButtonName0,
|
||||||
|
const char *ButtonName1,
|
||||||
|
uint32 SoundControls
|
||||||
|
)
|
||||||
|
{
|
||||||
auto outapp = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct));
|
auto outapp = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct));
|
||||||
OnLevelMessage_Struct *olms = (OnLevelMessage_Struct *)outapp->pBuffer;
|
|
||||||
|
|
||||||
if((strlen(Text) > (sizeof(olms->Text)-1)) || (strlen(Title) > (sizeof(olms->Title) - 1)) ) {
|
OnLevelMessage_Struct *olms = (OnLevelMessage_Struct *) outapp->pBuffer;
|
||||||
|
|
||||||
|
if ((strlen(Text) > (sizeof(olms->Text) - 1)) || (strlen(Title) > (sizeof(olms->Title) - 1))) {
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ButtonName0 && ButtonName1 && ( (strlen(ButtonName0) > (sizeof(olms->ButtonName0) - 1)) || (strlen(ButtonName1) > (sizeof(olms->ButtonName1) - 1)) ) ) {
|
if (ButtonName0 && ButtonName1 && ((strlen(ButtonName0) > (sizeof(olms->ButtonName0) - 1)) ||
|
||||||
|
(strlen(ButtonName1) > (sizeof(olms->ButtonName1) - 1)))) {
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -4073,18 +4102,21 @@ void Client::SendFullPopup(const char *Title, const char *Text, uint32 PopupID,
|
|||||||
|
|
||||||
olms->Buttons = Buttons;
|
olms->Buttons = Buttons;
|
||||||
|
|
||||||
if (ButtonName0 == NULL || ButtonName1 == NULL) {
|
if (ButtonName0 == nullptr || ButtonName1 == nullptr) {
|
||||||
sprintf(olms->ButtonName0, "%s", "Yes");
|
sprintf(olms->ButtonName0, "%s", "Yes");
|
||||||
sprintf(olms->ButtonName1, "%s", "No");
|
sprintf(olms->ButtonName1, "%s", "No");
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
strcpy(olms->ButtonName0, ButtonName0);
|
strcpy(olms->ButtonName0, ButtonName0);
|
||||||
strcpy(olms->ButtonName1, ButtonName1);
|
strcpy(olms->ButtonName1, ButtonName1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Duration > 0)
|
if (Duration > 0) {
|
||||||
olms->Duration = Duration * 1000;
|
olms->Duration = Duration * 1000;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
olms->Duration = 0xffffffff;
|
olms->Duration = 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
olms->PopupID = PopupID;
|
olms->PopupID = PopupID;
|
||||||
olms->NegativeID = NegativeID;
|
olms->NegativeID = NegativeID;
|
||||||
@ -4094,7 +4126,20 @@ void Client::SendFullPopup(const char *Title, const char *Text, uint32 PopupID,
|
|||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::SendWindow(uint32 PopupID, uint32 NegativeID, uint32 Buttons, const char *ButtonName0, const char *ButtonName1, uint32 Duration, int title_type, Client* target, const char *Title, const char *Text, ...) {
|
void Client::SendWindow(
|
||||||
|
uint32 PopupID,
|
||||||
|
uint32 NegativeID,
|
||||||
|
uint32 Buttons,
|
||||||
|
const char *ButtonName0,
|
||||||
|
const char *ButtonName1,
|
||||||
|
uint32 Duration,
|
||||||
|
int title_type,
|
||||||
|
Client *target,
|
||||||
|
const char *Title,
|
||||||
|
const char *Text,
|
||||||
|
...
|
||||||
|
)
|
||||||
|
{
|
||||||
va_list argptr;
|
va_list argptr;
|
||||||
char buffer[4096];
|
char buffer[4096];
|
||||||
|
|
||||||
@ -4105,22 +4150,22 @@ void Client::SendWindow(uint32 PopupID, uint32 NegativeID, uint32 Buttons, const
|
|||||||
size_t len = strlen(buffer);
|
size_t len = strlen(buffer);
|
||||||
|
|
||||||
auto app = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct));
|
auto app = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct));
|
||||||
OnLevelMessage_Struct* olms=(OnLevelMessage_Struct*)app->pBuffer;
|
OnLevelMessage_Struct *olms = (OnLevelMessage_Struct *) app->pBuffer;
|
||||||
|
|
||||||
if(strlen(Text) > (sizeof(olms->Text)-1)) {
|
if (strlen(Text) > (sizeof(olms->Text) - 1)) {
|
||||||
safe_delete(app);
|
safe_delete(app);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!target)
|
if (!target) {
|
||||||
title_type = 0;
|
title_type = 0;
|
||||||
|
}
|
||||||
|
|
||||||
switch (title_type)
|
switch (title_type) {
|
||||||
{
|
|
||||||
case 1: {
|
case 1: {
|
||||||
char name[64] = "";
|
char name[64] = "";
|
||||||
strcpy(name, target->GetName());
|
strcpy(name, target->GetName());
|
||||||
if(target->GetLastName()) {
|
if (target->GetLastName()) {
|
||||||
char last_name[64] = "";
|
char last_name[64] = "";
|
||||||
strcpy(last_name, target->GetLastName());
|
strcpy(last_name, target->GetLastName());
|
||||||
strcat(name, " ");
|
strcat(name, " ");
|
||||||
@ -4130,8 +4175,8 @@ void Client::SendWindow(uint32 PopupID, uint32 NegativeID, uint32 Buttons, const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2: {
|
case 2: {
|
||||||
if(target->GuildID()) {
|
if (target->GuildID()) {
|
||||||
char *guild_name = (char*)guild_mgr.GetGuildName(target->GuildID());
|
char *guild_name = (char *) guild_mgr.GetGuildName(target->GuildID());
|
||||||
strcpy(olms->Title, guild_name);
|
strcpy(olms->Title, guild_name);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -4145,17 +4190,19 @@ void Client::SendWindow(uint32 PopupID, uint32 NegativeID, uint32 Buttons, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(olms->Text, buffer, len+1);
|
memcpy(olms->Text, buffer, len + 1);
|
||||||
|
|
||||||
olms->Buttons = Buttons;
|
olms->Buttons = Buttons;
|
||||||
|
|
||||||
sprintf(olms->ButtonName0, "%s", ButtonName0);
|
sprintf(olms->ButtonName0, "%s", ButtonName0);
|
||||||
sprintf(olms->ButtonName1, "%s", ButtonName1);
|
sprintf(olms->ButtonName1, "%s", ButtonName1);
|
||||||
|
|
||||||
if(Duration > 0)
|
if (Duration > 0) {
|
||||||
olms->Duration = Duration * 1000;
|
olms->Duration = Duration * 1000;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
olms->Duration = 0xffffffff;
|
olms->Duration = 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
olms->PopupID = PopupID;
|
olms->PopupID = PopupID;
|
||||||
olms->NegativeID = NegativeID;
|
olms->NegativeID = NegativeID;
|
||||||
@ -6341,30 +6388,13 @@ void Client::SendStatsWindow(Client* client, bool use_window)
|
|||||||
std::string class_Name = itoa(GetClass());
|
std::string class_Name = itoa(GetClass());
|
||||||
std::string class_List[] = { "WAR", "CLR", "PAL", "RNG", "SHD", "DRU", "MNK", "BRD", "ROG", "SHM", "NEC", "WIZ", "MAG", "ENC", "BST", "BER" };
|
std::string class_List[] = { "WAR", "CLR", "PAL", "RNG", "SHD", "DRU", "MNK", "BRD", "ROG", "SHM", "NEC", "WIZ", "MAG", "ENC", "BST", "BER" };
|
||||||
|
|
||||||
if(GetClass() < 17 && GetClass() > 0) { class_Name = class_List[GetClass()-1]; }
|
if (GetClass() < 17 && GetClass() > 0) {
|
||||||
|
class_Name = class_List[GetClass() - 1];
|
||||||
|
}
|
||||||
|
|
||||||
// Race
|
// Race
|
||||||
std::string race_Name = itoa(GetRace());
|
std::string race_name = GetRaceIDName(GetRace());
|
||||||
switch(GetRace())
|
|
||||||
{
|
|
||||||
case 1: race_Name = "Human"; break;
|
|
||||||
case 2: race_Name = "Barbarian"; break;
|
|
||||||
case 3: race_Name = "Erudite"; break;
|
|
||||||
case 4: race_Name = "Wood Elf"; break;
|
|
||||||
case 5: race_Name = "High Elf"; break;
|
|
||||||
case 6: race_Name = "Dark Elf"; break;
|
|
||||||
case 7: race_Name = "Half Elf"; break;
|
|
||||||
case 8: race_Name = "Dwarf"; break;
|
|
||||||
case 9: race_Name = "Troll"; break;
|
|
||||||
case 10: race_Name = "Ogre"; break;
|
|
||||||
case 11: race_Name = "Halfing"; break;
|
|
||||||
case 12: race_Name = "Gnome"; break;
|
|
||||||
case 128: race_Name = "Iksar"; break;
|
|
||||||
case 130: race_Name = "Vah Shir"; break;
|
|
||||||
case 330: race_Name = "Froglok"; break;
|
|
||||||
case 522: race_Name = "Drakkin"; break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
/*##########################################################
|
/*##########################################################
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
H/M/E String
|
H/M/E String
|
||||||
@ -6793,7 +6823,7 @@ void Client::SendStatsWindow(Client* client, bool use_window)
|
|||||||
|
|
||||||
std::ostringstream final_string;
|
std::ostringstream final_string;
|
||||||
final_string <<
|
final_string <<
|
||||||
/* C/L/R */ indP << "Class: " << class_Name << indS << "Level: " << static_cast<int>(GetLevel()) << indS << "Race: " << race_Name << "<br>" <<
|
/* C/L/R */ indP << "Class: " << class_Name << indS << "Level: " << static_cast<int>(GetLevel()) << indS << "Race: " << race_name << "<br>" <<
|
||||||
/* Runes */ indP << "Rune: " << rune_number << indL << indS << "Spell Rune: " << magic_rune_number << "<br>" <<
|
/* Runes */ indP << "Rune: " << rune_number << indL << indS << "Spell Rune: " << magic_rune_number << "<br>" <<
|
||||||
/* HP/M/E */ HME_row <<
|
/* HP/M/E */ HME_row <<
|
||||||
/* DS */ indP << "DS: " << (itembonuses.DamageShield + spellbonuses.DamageShield*-1) << " (Spell: " << (spellbonuses.DamageShield*-1) << " + Item: " << itembonuses.DamageShield << " / " << RuleI(Character, ItemDamageShieldCap) << ")<br>" <<
|
/* DS */ indP << "DS: " << (itembonuses.DamageShield + spellbonuses.DamageShield*-1) << " (Spell: " << (spellbonuses.DamageShield*-1) << " + Item: " << itembonuses.DamageShield << " / " << RuleI(Character, ItemDamageShieldCap) << ")<br>" <<
|
||||||
@ -8977,3 +9007,22 @@ void Client::InitInnates()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Client::GetDisplayMobInfoWindow() const
|
||||||
|
{
|
||||||
|
return display_mob_info_window;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::SetDisplayMobInfoWindow(bool display_mob_info_window)
|
||||||
|
{
|
||||||
|
Client::display_mob_info_window = display_mob_info_window;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Client::IsDevToolsWindowEnabled() const
|
||||||
|
{
|
||||||
|
return dev_tools_window_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::SetDevToolsWindowEnabled(bool in_dev_tools_window_enabled)
|
||||||
|
{
|
||||||
|
Client::dev_tools_window_enabled = in_dev_tools_window_enabled;
|
||||||
|
}
|
||||||
@ -246,6 +246,12 @@ public:
|
|||||||
std::unordered_map<Mob *, float> close_mobs;
|
std::unordered_map<Mob *, float> close_mobs;
|
||||||
bool is_client_moving;
|
bool is_client_moving;
|
||||||
|
|
||||||
|
void SetDisplayMobInfoWindow(bool display_mob_info_window);
|
||||||
|
bool GetDisplayMobInfoWindow() const;
|
||||||
|
|
||||||
|
bool IsDevToolsWindowEnabled() const;
|
||||||
|
void SetDevToolsWindowEnabled(bool dev_tools_window_enabled);
|
||||||
|
|
||||||
//abstract virtual function implementations required by base abstract class
|
//abstract virtual function implementations required by base abstract class
|
||||||
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill);
|
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill);
|
||||||
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None);
|
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None);
|
||||||
@ -697,6 +703,8 @@ public:
|
|||||||
void SendGuildJoin(GuildJoin_Struct* gj);
|
void SendGuildJoin(GuildJoin_Struct* gj);
|
||||||
void RefreshGuildInfo();
|
void RefreshGuildInfo();
|
||||||
|
|
||||||
|
int GetClientMaxLevel() const { return client_max_level; }
|
||||||
|
void SetClientMaxLevel(int max_level) { client_max_level = max_level; }
|
||||||
|
|
||||||
void CheckManaEndUpdate();
|
void CheckManaEndUpdate();
|
||||||
void SendManaUpdate();
|
void SendManaUpdate();
|
||||||
@ -773,8 +781,10 @@ public:
|
|||||||
void UnscribeSpellAll(bool update_client = true);
|
void UnscribeSpellAll(bool update_client = true);
|
||||||
void UntrainDisc(int slot, bool update_client = true);
|
void UntrainDisc(int slot, bool update_client = true);
|
||||||
void UntrainDiscAll(bool update_client = true);
|
void UntrainDiscAll(bool update_client = true);
|
||||||
bool SpellGlobalCheck(uint16 Spell_ID, uint32 Char_ID);
|
bool SpellGlobalCheck(uint16 spell_id, uint32 char_id);
|
||||||
|
bool SpellBucketCheck(uint16 spell_id, uint32 char_id);
|
||||||
uint32 GetCharMaxLevelFromQGlobal();
|
uint32 GetCharMaxLevelFromQGlobal();
|
||||||
|
uint32 GetCharMaxLevelFromBucket();
|
||||||
|
|
||||||
inline bool IsSitting() const {return (playeraction == 1);}
|
inline bool IsSitting() const {return (playeraction == 1);}
|
||||||
inline bool IsBecomeNPC() const { return npcflag; }
|
inline bool IsBecomeNPC() const { return npcflag; }
|
||||||
@ -851,7 +861,6 @@ public:
|
|||||||
void SetAATitle(const char *Title);
|
void SetAATitle(const char *Title);
|
||||||
void SetTitleSuffix(const char *txt);
|
void SetTitleSuffix(const char *txt);
|
||||||
void MemorizeSpell(uint32 slot, uint32 spellid, uint32 scribing);
|
void MemorizeSpell(uint32 slot, uint32 spellid, uint32 scribing);
|
||||||
int32 acmod();
|
|
||||||
|
|
||||||
// Item methods
|
// Item methods
|
||||||
void EVENT_ITEM_ScriptStopReturn();
|
void EVENT_ITEM_ScriptStopReturn();
|
||||||
@ -1442,6 +1451,9 @@ private:
|
|||||||
int Haste; //precalced value
|
int Haste; //precalced value
|
||||||
uint32 tmSitting; // time stamp started sitting, used for HP regen bonus added on MAY 5, 2004
|
uint32 tmSitting; // time stamp started sitting, used for HP regen bonus added on MAY 5, 2004
|
||||||
|
|
||||||
|
bool display_mob_info_window;
|
||||||
|
bool dev_tools_window_enabled;
|
||||||
|
|
||||||
int32 max_end;
|
int32 max_end;
|
||||||
int32 current_endurance;
|
int32 current_endurance;
|
||||||
|
|
||||||
@ -1616,6 +1628,8 @@ private:
|
|||||||
void InterrogateInventory_(bool errorcheck, Client* requester, int16 head, int16 index, const EQEmu::ItemInstance* inst, const EQEmu::ItemInstance* parent, bool log, bool silent, bool &error, int depth);
|
void InterrogateInventory_(bool errorcheck, Client* requester, int16 head, int16 index, const EQEmu::ItemInstance* inst, const EQEmu::ItemInstance* parent, bool log, bool silent, bool &error, int depth);
|
||||||
bool InterrogateInventory_error(int16 head, int16 index, const EQEmu::ItemInstance* inst, const EQEmu::ItemInstance* parent, int depth);
|
bool InterrogateInventory_error(int16 head, int16 index, const EQEmu::ItemInstance* inst, const EQEmu::ItemInstance* parent, int depth);
|
||||||
|
|
||||||
|
int client_max_level;
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
struct BotOwnerOptions {
|
struct BotOwnerOptions {
|
||||||
bool death_marquee;
|
bool death_marquee;
|
||||||
|
|||||||
@ -275,9 +275,10 @@ int32 Client::CalcHPRegen(bool bCombat)
|
|||||||
if (!skip_innate && m_pp.InnateSkills[InnateRegen] != InnateDisabled) {
|
if (!skip_innate && m_pp.InnateSkills[InnateRegen] != InnateDisabled) {
|
||||||
if (level >= 50) {
|
if (level >= 50) {
|
||||||
++base;
|
++base;
|
||||||
if (level >= 55)
|
if (level >= 55) {
|
||||||
++base;
|
++base;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
base *= 2;
|
base *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,6 +332,7 @@ int32 Client::CalcMaxHP()
|
|||||||
if (hp_perc_cap) {
|
if (hp_perc_cap) {
|
||||||
int curHP_cap = (max_hp * hp_perc_cap) / 100;
|
int curHP_cap = (max_hp * hp_perc_cap) / 100;
|
||||||
if (cur_hp > curHP_cap || (spellbonuses.HPPercCap[1] && cur_hp > spellbonuses.HPPercCap[1])) {
|
if (cur_hp > curHP_cap || (spellbonuses.HPPercCap[1] && cur_hp > spellbonuses.HPPercCap[1])) {
|
||||||
|
|
||||||
cur_hp = curHP_cap;
|
cur_hp = curHP_cap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -470,6 +472,7 @@ uint32 Mob::GetClassLevelFactor()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return multiplier;
|
return multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -560,537 +563,6 @@ int32 Client::GetRawItemAC()
|
|||||||
return Total;
|
return Total;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 Client::acmod()
|
|
||||||
{
|
|
||||||
int agility = GetAGI();
|
|
||||||
int level = GetLevel();
|
|
||||||
if (agility < 1 || level < 1) {
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
if (agility <= 74) {
|
|
||||||
if (agility == 1) {
|
|
||||||
return -24;
|
|
||||||
}
|
|
||||||
else if (agility <= 3) {
|
|
||||||
return -23;
|
|
||||||
}
|
|
||||||
else if (agility == 4) {
|
|
||||||
return -22;
|
|
||||||
}
|
|
||||||
else if (agility <= 6) {
|
|
||||||
return -21;
|
|
||||||
}
|
|
||||||
else if (agility <= 8) {
|
|
||||||
return -20;
|
|
||||||
}
|
|
||||||
else if (agility == 9) {
|
|
||||||
return -19;
|
|
||||||
}
|
|
||||||
else if (agility <= 11) {
|
|
||||||
return -18;
|
|
||||||
}
|
|
||||||
else if (agility == 12) {
|
|
||||||
return -17;
|
|
||||||
}
|
|
||||||
else if (agility <= 14) {
|
|
||||||
return -16;
|
|
||||||
}
|
|
||||||
else if (agility <= 16) {
|
|
||||||
return -15;
|
|
||||||
}
|
|
||||||
else if (agility == 17) {
|
|
||||||
return -14;
|
|
||||||
}
|
|
||||||
else if (agility <= 19) {
|
|
||||||
return -13;
|
|
||||||
}
|
|
||||||
else if (agility == 20) {
|
|
||||||
return -12;
|
|
||||||
}
|
|
||||||
else if (agility <= 22) {
|
|
||||||
return -11;
|
|
||||||
}
|
|
||||||
else if (agility <= 24) {
|
|
||||||
return -10;
|
|
||||||
}
|
|
||||||
else if (agility == 25) {
|
|
||||||
return -9;
|
|
||||||
}
|
|
||||||
else if (agility <= 27) {
|
|
||||||
return -8;
|
|
||||||
}
|
|
||||||
else if (agility == 28) {
|
|
||||||
return -7;
|
|
||||||
}
|
|
||||||
else if (agility <= 30) {
|
|
||||||
return -6;
|
|
||||||
}
|
|
||||||
else if (agility <= 32) {
|
|
||||||
return -5;
|
|
||||||
}
|
|
||||||
else if (agility == 33) {
|
|
||||||
return -4;
|
|
||||||
}
|
|
||||||
else if (agility <= 35) {
|
|
||||||
return -3;
|
|
||||||
}
|
|
||||||
else if (agility == 36) {
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
else if (agility <= 38) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else if (agility <= 65) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (agility <= 70) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (agility <= 74) {
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (agility <= 137) {
|
|
||||||
if (agility == 75) {
|
|
||||||
if (level <= 6) {
|
|
||||||
return 9;
|
|
||||||
}
|
|
||||||
else if (level <= 19) {
|
|
||||||
return 23;
|
|
||||||
}
|
|
||||||
else if (level <= 39) {
|
|
||||||
return 33;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 39;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (agility >= 76 && agility <= 79) {
|
|
||||||
if (level <= 6) {
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
else if (level <= 19) {
|
|
||||||
return 23;
|
|
||||||
}
|
|
||||||
else if (level <= 39) {
|
|
||||||
return 33;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 40;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (agility == 80) {
|
|
||||||
if (level <= 6) {
|
|
||||||
return 11;
|
|
||||||
}
|
|
||||||
else if (level <= 19) {
|
|
||||||
return 24;
|
|
||||||
}
|
|
||||||
else if (level <= 39) {
|
|
||||||
return 34;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 41;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (agility >= 81 && agility <= 85) {
|
|
||||||
if (level <= 6) {
|
|
||||||
return 12;
|
|
||||||
}
|
|
||||||
else if (level <= 19) {
|
|
||||||
return 25;
|
|
||||||
}
|
|
||||||
else if (level <= 39) {
|
|
||||||
return 35;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 42;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (agility >= 86 && agility <= 90) {
|
|
||||||
if (level <= 6) {
|
|
||||||
return 12;
|
|
||||||
}
|
|
||||||
else if (level <= 19) {
|
|
||||||
return 26;
|
|
||||||
}
|
|
||||||
else if (level <= 39) {
|
|
||||||
return 36;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 42;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (agility >= 91 && agility <= 95) {
|
|
||||||
if (level <= 6) {
|
|
||||||
return 13;
|
|
||||||
}
|
|
||||||
else if (level <= 19) {
|
|
||||||
return 26;
|
|
||||||
}
|
|
||||||
else if (level <= 39) {
|
|
||||||
return 36;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 43;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (agility >= 96 && agility <= 99) {
|
|
||||||
if (level <= 6) {
|
|
||||||
return 14;
|
|
||||||
}
|
|
||||||
else if (level <= 19) {
|
|
||||||
return 27;
|
|
||||||
}
|
|
||||||
else if (level <= 39) {
|
|
||||||
return 37;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 44;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (agility == 100 && level >= 7) {
|
|
||||||
if (level <= 19) {
|
|
||||||
return 28;
|
|
||||||
}
|
|
||||||
else if (level <= 39) {
|
|
||||||
return 38;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 45;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (level <= 6) {
|
|
||||||
return 15;
|
|
||||||
}
|
|
||||||
//level is >6
|
|
||||||
else if (agility >= 101 && agility <= 105) {
|
|
||||||
if (level <= 19) {
|
|
||||||
return 29;
|
|
||||||
}
|
|
||||||
else if (level <= 39) {
|
|
||||||
return 39; // not verified
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 45;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (agility >= 106 && agility <= 110) {
|
|
||||||
if (level <= 19) {
|
|
||||||
return 29;
|
|
||||||
}
|
|
||||||
else if (level <= 39) {
|
|
||||||
return 39; // not verified
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 46;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (agility >= 111 && agility <= 115) {
|
|
||||||
if (level <= 19) {
|
|
||||||
return 30;
|
|
||||||
}
|
|
||||||
else if (level <= 39) {
|
|
||||||
return 40; // not verified
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 47;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (agility >= 116 && agility <= 119) {
|
|
||||||
if (level <= 19) {
|
|
||||||
return 31;
|
|
||||||
}
|
|
||||||
else if (level <= 39) {
|
|
||||||
return 41;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 47;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (level <= 19) {
|
|
||||||
return 32;
|
|
||||||
}
|
|
||||||
//level is > 19
|
|
||||||
else if (agility == 120) {
|
|
||||||
if (level <= 39) {
|
|
||||||
return 42;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 48;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (agility <= 125) {
|
|
||||||
if (level <= 39) {
|
|
||||||
return 42;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 49;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (agility <= 135) {
|
|
||||||
if (level <= 39) {
|
|
||||||
return 42;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 50;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (level <= 39) {
|
|
||||||
return 42;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 51;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (agility <= 300) {
|
|
||||||
if (level <= 6) {
|
|
||||||
if (agility <= 139) {
|
|
||||||
return (21);
|
|
||||||
}
|
|
||||||
else if (agility == 140) {
|
|
||||||
return (22);
|
|
||||||
}
|
|
||||||
else if (agility <= 145) {
|
|
||||||
return (23);
|
|
||||||
}
|
|
||||||
else if (agility <= 150) {
|
|
||||||
return (23);
|
|
||||||
}
|
|
||||||
else if (agility <= 155) {
|
|
||||||
return (24);
|
|
||||||
}
|
|
||||||
else if (agility <= 159) {
|
|
||||||
return (25);
|
|
||||||
}
|
|
||||||
else if (agility == 160) {
|
|
||||||
return (26);
|
|
||||||
}
|
|
||||||
else if (agility <= 165) {
|
|
||||||
return (26);
|
|
||||||
}
|
|
||||||
else if (agility <= 170) {
|
|
||||||
return (27);
|
|
||||||
}
|
|
||||||
else if (agility <= 175) {
|
|
||||||
return (28);
|
|
||||||
}
|
|
||||||
else if (agility <= 179) {
|
|
||||||
return (28);
|
|
||||||
}
|
|
||||||
else if (agility == 180) {
|
|
||||||
return (29);
|
|
||||||
}
|
|
||||||
else if (agility <= 185) {
|
|
||||||
return (30);
|
|
||||||
}
|
|
||||||
else if (agility <= 190) {
|
|
||||||
return (31);
|
|
||||||
}
|
|
||||||
else if (agility <= 195) {
|
|
||||||
return (31);
|
|
||||||
}
|
|
||||||
else if (agility <= 199) {
|
|
||||||
return (32);
|
|
||||||
}
|
|
||||||
else if (agility <= 219) {
|
|
||||||
return (33);
|
|
||||||
}
|
|
||||||
else if (agility <= 239) {
|
|
||||||
return (34);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return (35);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (level <= 19) {
|
|
||||||
if (agility <= 139) {
|
|
||||||
return (34);
|
|
||||||
}
|
|
||||||
else if (agility == 140) {
|
|
||||||
return (35);
|
|
||||||
}
|
|
||||||
else if (agility <= 145) {
|
|
||||||
return (36);
|
|
||||||
}
|
|
||||||
else if (agility <= 150) {
|
|
||||||
return (37);
|
|
||||||
}
|
|
||||||
else if (agility <= 155) {
|
|
||||||
return (37);
|
|
||||||
}
|
|
||||||
else if (agility <= 159) {
|
|
||||||
return (38);
|
|
||||||
}
|
|
||||||
else if (agility == 160) {
|
|
||||||
return (39);
|
|
||||||
}
|
|
||||||
else if (agility <= 165) {
|
|
||||||
return (40);
|
|
||||||
}
|
|
||||||
else if (agility <= 170) {
|
|
||||||
return (40);
|
|
||||||
}
|
|
||||||
else if (agility <= 175) {
|
|
||||||
return (41);
|
|
||||||
}
|
|
||||||
else if (agility <= 179) {
|
|
||||||
return (42);
|
|
||||||
}
|
|
||||||
else if (agility == 180) {
|
|
||||||
return (43);
|
|
||||||
}
|
|
||||||
else if (agility <= 185) {
|
|
||||||
return (43);
|
|
||||||
}
|
|
||||||
else if (agility <= 190) {
|
|
||||||
return (44);
|
|
||||||
}
|
|
||||||
else if (agility <= 195) {
|
|
||||||
return (45);
|
|
||||||
}
|
|
||||||
else if (agility <= 199) {
|
|
||||||
return (45);
|
|
||||||
}
|
|
||||||
else if (agility <= 219) {
|
|
||||||
return (46);
|
|
||||||
}
|
|
||||||
else if (agility <= 239) {
|
|
||||||
return (47);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return (48);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (level <= 39) {
|
|
||||||
if (agility <= 139) {
|
|
||||||
return (44);
|
|
||||||
}
|
|
||||||
else if (agility == 140) {
|
|
||||||
return (45);
|
|
||||||
}
|
|
||||||
else if (agility <= 145) {
|
|
||||||
return (46);
|
|
||||||
}
|
|
||||||
else if (agility <= 150) {
|
|
||||||
return (47);
|
|
||||||
}
|
|
||||||
else if (agility <= 155) {
|
|
||||||
return (47);
|
|
||||||
}
|
|
||||||
else if (agility <= 159) {
|
|
||||||
return (48);
|
|
||||||
}
|
|
||||||
else if (agility == 160) {
|
|
||||||
return (49);
|
|
||||||
}
|
|
||||||
else if (agility <= 165) {
|
|
||||||
return (50);
|
|
||||||
}
|
|
||||||
else if (agility <= 170) {
|
|
||||||
return (50);
|
|
||||||
}
|
|
||||||
else if (agility <= 175) {
|
|
||||||
return (51);
|
|
||||||
}
|
|
||||||
else if (agility <= 179) {
|
|
||||||
return (52);
|
|
||||||
}
|
|
||||||
else if (agility == 180) {
|
|
||||||
return (53);
|
|
||||||
}
|
|
||||||
else if (agility <= 185) {
|
|
||||||
return (53);
|
|
||||||
}
|
|
||||||
else if (agility <= 190) {
|
|
||||||
return (54);
|
|
||||||
}
|
|
||||||
else if (agility <= 195) {
|
|
||||||
return (55);
|
|
||||||
}
|
|
||||||
else if (agility <= 199) {
|
|
||||||
return (55);
|
|
||||||
}
|
|
||||||
else if (agility <= 219) {
|
|
||||||
return (56);
|
|
||||||
}
|
|
||||||
else if (agility <= 239) {
|
|
||||||
return (57);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return (58);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { //lvl >= 40
|
|
||||||
if (agility <= 139) {
|
|
||||||
return (51);
|
|
||||||
}
|
|
||||||
else if (agility == 140) {
|
|
||||||
return (52);
|
|
||||||
}
|
|
||||||
else if (agility <= 145) {
|
|
||||||
return (53);
|
|
||||||
}
|
|
||||||
else if (agility <= 150) {
|
|
||||||
return (53);
|
|
||||||
}
|
|
||||||
else if (agility <= 155) {
|
|
||||||
return (54);
|
|
||||||
}
|
|
||||||
else if (agility <= 159) {
|
|
||||||
return (55);
|
|
||||||
}
|
|
||||||
else if (agility == 160) {
|
|
||||||
return (56);
|
|
||||||
}
|
|
||||||
else if (agility <= 165) {
|
|
||||||
return (56);
|
|
||||||
}
|
|
||||||
else if (agility <= 170) {
|
|
||||||
return (57);
|
|
||||||
}
|
|
||||||
else if (agility <= 175) {
|
|
||||||
return (58);
|
|
||||||
}
|
|
||||||
else if (agility <= 179) {
|
|
||||||
return (58);
|
|
||||||
}
|
|
||||||
else if (agility == 180) {
|
|
||||||
return (59);
|
|
||||||
}
|
|
||||||
else if (agility <= 185) {
|
|
||||||
return (60);
|
|
||||||
}
|
|
||||||
else if (agility <= 190) {
|
|
||||||
return (61);
|
|
||||||
}
|
|
||||||
else if (agility <= 195) {
|
|
||||||
return (61);
|
|
||||||
}
|
|
||||||
else if (agility <= 199) {
|
|
||||||
return (62);
|
|
||||||
}
|
|
||||||
else if (agility <= 219) {
|
|
||||||
return (63);
|
|
||||||
}
|
|
||||||
else if (agility <= 239) {
|
|
||||||
return (64);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return (65);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//seems about 21 agil per extra AC pt over 300...
|
|
||||||
return (65 + ((agility - 300) / 21));
|
|
||||||
}
|
|
||||||
Log(Logs::Detail, Logs::Error, "Error in Client::acmod(): Agility: %i, Level: %i", agility, level);
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
int32 Client::CalcMaxMana()
|
int32 Client::CalcMaxMana()
|
||||||
{
|
{
|
||||||
switch (GetCasterClass()) {
|
switch (GetCasterClass()) {
|
||||||
|
|||||||
@ -47,6 +47,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "../common/spdat.h"
|
#include "../common/spdat.h"
|
||||||
#include "../common/string_util.h"
|
#include "../common/string_util.h"
|
||||||
#include "../common/zone_numbers.h"
|
#include "../common/zone_numbers.h"
|
||||||
|
#include "data_bucket.h"
|
||||||
#include "event_codes.h"
|
#include "event_codes.h"
|
||||||
#include "guild_mgr.h"
|
#include "guild_mgr.h"
|
||||||
#include "merc.h"
|
#include "merc.h"
|
||||||
@ -1316,6 +1317,15 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
|||||||
drakkin_tattoo = m_pp.drakkin_tattoo;
|
drakkin_tattoo = m_pp.drakkin_tattoo;
|
||||||
drakkin_details = m_pp.drakkin_details;
|
drakkin_details = m_pp.drakkin_details;
|
||||||
|
|
||||||
|
// Max Level for Character:PerCharacterQglobalMaxLevel and Character:PerCharacterBucketMaxLevel
|
||||||
|
int client_max_level = 0;
|
||||||
|
if (RuleB(Character, PerCharacterQglobalMaxLevel)) {
|
||||||
|
client_max_level = GetCharMaxLevelFromQGlobal();
|
||||||
|
} else if (RuleB(Character, PerCharacterBucketMaxLevel)) {
|
||||||
|
client_max_level = GetCharMaxLevelFromBucket();
|
||||||
|
}
|
||||||
|
SetClientMaxLevel(client_max_level);
|
||||||
|
|
||||||
// we know our class now, so we might have to fix our consume timer!
|
// we know our class now, so we might have to fix our consume timer!
|
||||||
if (class_ == MONK)
|
if (class_ == MONK)
|
||||||
consume_food_timer.SetTimer(CONSUMPTION_MNK_TIMER);
|
consume_food_timer.SetTimer(CONSUMPTION_MNK_TIMER);
|
||||||
@ -1643,6 +1653,15 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
|||||||
/* Task Packets */
|
/* Task Packets */
|
||||||
LoadClientTaskState();
|
LoadClientTaskState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DevTools Load Settings
|
||||||
|
*/
|
||||||
|
if (Admin() >= 200) {
|
||||||
|
std::string dev_tools_window_key = StringFormat("%i-dev-tools-window-disabled", AccountID());
|
||||||
|
if (DataBucket::GetData(dev_tools_window_key) == "true") {
|
||||||
|
dev_tools_window_enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) {
|
if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) {
|
||||||
outapp = new EQApplicationPacket(OP_XTargetResponse, 8);
|
outapp = new EQApplicationPacket(OP_XTargetResponse, 8);
|
||||||
@ -10678,33 +10697,46 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app)
|
|||||||
{
|
{
|
||||||
|
|
||||||
if (app->size != sizeof(PopupResponse_Struct)) {
|
if (app->size != sizeof(PopupResponse_Struct)) {
|
||||||
Log(Logs::General, Logs::None, "Size mismatch in OP_PopupResponse expected %i got %i",
|
Log(Logs::General,
|
||||||
sizeof(PopupResponse_Struct), app->size);
|
Logs::None,
|
||||||
|
"Size mismatch in OP_PopupResponse expected %i got %i",
|
||||||
|
sizeof(PopupResponse_Struct),
|
||||||
|
app->size);
|
||||||
|
|
||||||
DumpPacket(app);
|
DumpPacket(app);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PopupResponse_Struct *prs = (PopupResponse_Struct*)app->pBuffer;
|
|
||||||
|
|
||||||
// Handle any EQEmu defined popup Ids first
|
PopupResponse_Struct *popup_response = (PopupResponse_Struct *) app->pBuffer;
|
||||||
switch (prs->popupid)
|
|
||||||
{
|
/**
|
||||||
|
* Handle any EQEmu defined popup Ids first
|
||||||
|
*/
|
||||||
|
switch (popup_response->popupid) {
|
||||||
case POPUPID_UPDATE_SHOWSTATSWINDOW:
|
case POPUPID_UPDATE_SHOWSTATSWINDOW:
|
||||||
if (GetTarget() && GetTarget()->IsClient())
|
if (GetTarget() && GetTarget()->IsClient()) {
|
||||||
GetTarget()->CastToClient()->SendStatsWindow(this, true);
|
GetTarget()->CastToClient()->SendStatsWindow(this, true);
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
SendStatsWindow(this, true);
|
SendStatsWindow(this, true);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EQEmu::popupresponse::MOB_INFO_DISMISS:
|
||||||
|
this->SetDisplayMobInfoWindow(false);
|
||||||
|
this->Message(15, "[DevTools] Window snoozed in this zone...");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
char buf[16];
|
char buf[16];
|
||||||
sprintf(buf, "%d\0", prs->popupid);
|
sprintf(buf, "%d\0", popup_response->popupid);
|
||||||
|
|
||||||
parse->EventPlayer(EVENT_POPUP_RESPONSE, this, buf, 0);
|
parse->EventPlayer(EVENT_POPUP_RESPONSE, this, buf, 0);
|
||||||
|
|
||||||
Mob* Target = GetTarget();
|
Mob *Target = GetTarget();
|
||||||
if (Target && Target->IsNPC()) {
|
if (Target && Target->IsNPC()) {
|
||||||
parse->EventNPC(EVENT_POPUP_RESPONSE, Target->CastToNPC(), this, buf, 0);
|
parse->EventNPC(EVENT_POPUP_RESPONSE, Target->CastToNPC(), this, buf, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
486
zone/command.cpp
Normal file → Executable file
486
zone/command.cpp
Normal file → Executable file
@ -55,7 +55,7 @@
|
|||||||
#include "../say_link.h"
|
#include "../say_link.h"
|
||||||
#include "../common/eqemu_logsys.h"
|
#include "../common/eqemu_logsys.h"
|
||||||
|
|
||||||
|
#include "data_bucket.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "guild_mgr.h"
|
#include "guild_mgr.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
@ -68,6 +68,7 @@
|
|||||||
#include "worldserver.h"
|
#include "worldserver.h"
|
||||||
#include "fastmath.h"
|
#include "fastmath.h"
|
||||||
#include "mob_movement_manager.h"
|
#include "mob_movement_manager.h"
|
||||||
|
#include "npc_scale_manager.h"
|
||||||
|
|
||||||
extern QueryServ* QServ;
|
extern QueryServ* QServ;
|
||||||
extern WorldServer worldserver;
|
extern WorldServer worldserver;
|
||||||
@ -185,6 +186,7 @@ int command_init(void)
|
|||||||
command_add("delpetition", "[petition number] - Delete a petition", 20, command_delpetition) ||
|
command_add("delpetition", "[petition number] - Delete a petition", 20, command_delpetition) ||
|
||||||
command_add("depop", "- Depop your NPC target", 50, command_depop) ||
|
command_add("depop", "- Depop your NPC target", 50, command_depop) ||
|
||||||
command_add("depopzone", "- Depop the zone", 100, command_depopzone) ||
|
command_add("depopzone", "- Depop the zone", 100, command_depopzone) ||
|
||||||
|
command_add("devtools", "- Manages devtools", 200, command_devtools) ||
|
||||||
command_add("details", "- Change the details of your target (Drakkin Only)", 80, command_details) ||
|
command_add("details", "- Change the details of your target (Drakkin Only)", 80, command_details) ||
|
||||||
command_add("disablerecipe", "[recipe_id] - Disables a recipe using the recipe id.", 80, command_disablerecipe) ||
|
command_add("disablerecipe", "[recipe_id] - Disables a recipe using the recipe id.", 80, command_disablerecipe) ||
|
||||||
command_add("disarmtrap", "Analog for ldon disarm trap for the newer clients since we still don't have it working.", 80, command_disarmtrap) ||
|
command_add("disarmtrap", "Analog for ldon disarm trap for the newer clients since we still don't have it working.", 80, command_disarmtrap) ||
|
||||||
@ -250,6 +252,7 @@ int command_init(void)
|
|||||||
command_add("lastname", "[new lastname] - Set your or your player target's lastname", 50, command_lastname) ||
|
command_add("lastname", "[new lastname] - Set your or your player target's lastname", 50, command_lastname) ||
|
||||||
command_add("level", "[level] - Set your or your target's level", 10, command_level) ||
|
command_add("level", "[level] - Set your or your target's level", 10, command_level) ||
|
||||||
command_add("listnpcs", "[name/range] - Search NPCs", 20, command_listnpcs) ||
|
command_add("listnpcs", "[name/range] - Search NPCs", 20, command_listnpcs) ||
|
||||||
|
command_add("list", "[npcs|players|corpses|doors|objects] [search] - Search entities", 20, command_list) ||
|
||||||
command_add("listpetition", "- List petitions", 50, command_listpetition) ||
|
command_add("listpetition", "- List petitions", 50, command_listpetition) ||
|
||||||
command_add("load_shared_memory", "[shared_memory_name] - Reloads shared memory and uses the input as output", 250, command_load_shared_memory) ||
|
command_add("load_shared_memory", "[shared_memory_name] - Reloads shared memory and uses the input as output", 250, command_load_shared_memory) ||
|
||||||
command_add("loc", "- Print out your or your target's current location and heading", 0, command_loc) ||
|
command_add("loc", "- Print out your or your target's current location and heading", 0, command_loc) ||
|
||||||
@ -336,6 +339,7 @@ int command_init(void)
|
|||||||
command_add("revoke", "[charname] [1/0] - Makes charname unable to talk on OOC", 200, command_revoke) ||
|
command_add("revoke", "[charname] [1/0] - Makes charname unable to talk on OOC", 200, command_revoke) ||
|
||||||
command_add("rules", "(subcommand) - Manage server rules", 250, command_rules) ||
|
command_add("rules", "(subcommand) - Manage server rules", 250, command_rules) ||
|
||||||
command_add("save", "- Force your player or player corpse target to be saved to the database", 50, command_save) ||
|
command_add("save", "- Force your player or player corpse target to be saved to the database", 50, command_save) ||
|
||||||
|
command_add("scale", "- Handles npc scaling", 150, command_scale) ||
|
||||||
command_add("scribespell", "[spellid] - Scribe specified spell in your target's spell book.", 180, command_scribespell) ||
|
command_add("scribespell", "[spellid] - Scribe specified spell in your target's spell book.", 180, command_scribespell) ||
|
||||||
command_add("scribespells", "[max level] [min level] - Scribe all spells for you or your player target that are usable by them, up to level specified. (may freeze client for a few seconds)", 150, command_scribespells) ||
|
command_add("scribespells", "[max level] [min level] - Scribe all spells for you or your player target that are usable by them, up to level specified. (may freeze client for a few seconds)", 150, command_scribespells) ||
|
||||||
command_add("sendzonespawns", "- Refresh spawn list for all clients in zone", 150, command_sendzonespawns) ||
|
command_add("sendzonespawns", "- Refresh spawn list for all clients in zone", 150, command_sendzonespawns) ||
|
||||||
@ -1402,16 +1406,266 @@ void command_delpetition(Client *c, const Seperator *sep)
|
|||||||
|
|
||||||
void command_listnpcs(Client *c, const Seperator *sep)
|
void command_listnpcs(Client *c, const Seperator *sep)
|
||||||
{
|
{
|
||||||
if (strcasecmp(sep->arg[1], "all") == 0)
|
c->Message(0, "Deprecated, use the #list command (#list npcs <search>)");
|
||||||
entity_list.ListNPCs(c,sep->arg[1],sep->arg[2],0);
|
}
|
||||||
else if(sep->IsNumber(1) && sep->IsNumber(2))
|
|
||||||
entity_list.ListNPCs(c,sep->arg[1],sep->arg[2],2);
|
void command_list(Client *c, const Seperator *sep)
|
||||||
else if(sep->arg[1][0] != 0)
|
{
|
||||||
entity_list.ListNPCs(c,sep->arg[1],sep->arg[2],1);
|
std::string search_type;
|
||||||
|
if (strcasecmp(sep->arg[1], "npcs") == 0) {
|
||||||
|
search_type = "npcs";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(sep->arg[1], "players") == 0) {
|
||||||
|
search_type = "players";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(sep->arg[1], "corpses") == 0) {
|
||||||
|
search_type = "corpses";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(sep->arg[1], "doors") == 0) {
|
||||||
|
search_type = "doors";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(sep->arg[1], "objects") == 0) {
|
||||||
|
search_type = "objects";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (search_type.length() > 0) {
|
||||||
|
|
||||||
|
int entity_count = 0;
|
||||||
|
int found_count = 0;
|
||||||
|
|
||||||
|
std::string search_string;
|
||||||
|
|
||||||
|
if (sep->arg[2]) {
|
||||||
|
search_string = sep->arg[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NPC
|
||||||
|
*/
|
||||||
|
if (search_type.find("npcs") != std::string::npos) {
|
||||||
|
auto &entity_list_search = entity_list.GetMobList();
|
||||||
|
|
||||||
|
for (auto &itr : entity_list_search) {
|
||||||
|
Mob *entity = itr.second;
|
||||||
|
if (!entity->IsNPC()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_count++;
|
||||||
|
|
||||||
|
std::string entity_name = entity->GetName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter by name
|
||||||
|
*/
|
||||||
|
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string saylink = StringFormat(
|
||||||
|
"#goto %.0f %0.f %.0f",
|
||||||
|
entity->GetX(),
|
||||||
|
entity->GetY(),
|
||||||
|
entity->GetZ());
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
0,
|
||||||
|
"| %s | ID %5d | %s | x %.0f | y %0.f | z %.0f",
|
||||||
|
EQEmu::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Goto").c_str(),
|
||||||
|
entity->GetID(),
|
||||||
|
entity->GetName(),
|
||||||
|
entity->GetX(),
|
||||||
|
entity->GetY(),
|
||||||
|
entity->GetZ()
|
||||||
|
);
|
||||||
|
|
||||||
|
found_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client
|
||||||
|
*/
|
||||||
|
if (search_type.find("players") != std::string::npos) {
|
||||||
|
auto &entity_list_search = entity_list.GetClientList();
|
||||||
|
|
||||||
|
for (auto &itr : entity_list_search) {
|
||||||
|
Client *entity = itr.second;
|
||||||
|
|
||||||
|
entity_count++;
|
||||||
|
|
||||||
|
std::string entity_name = entity->GetName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter by name
|
||||||
|
*/
|
||||||
|
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string saylink = StringFormat(
|
||||||
|
"#goto %.0f %0.f %.0f",
|
||||||
|
entity->GetX(),
|
||||||
|
entity->GetY(),
|
||||||
|
entity->GetZ());
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
0,
|
||||||
|
"| %s | ID %5d | %s | x %.0f | y %0.f | z %.0f",
|
||||||
|
EQEmu::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Goto").c_str(),
|
||||||
|
entity->GetID(),
|
||||||
|
entity->GetName(),
|
||||||
|
entity->GetX(),
|
||||||
|
entity->GetY(),
|
||||||
|
entity->GetZ()
|
||||||
|
);
|
||||||
|
|
||||||
|
found_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Corpse
|
||||||
|
*/
|
||||||
|
if (search_type.find("corpses") != std::string::npos) {
|
||||||
|
auto &entity_list_search = entity_list.GetCorpseList();
|
||||||
|
|
||||||
|
for (auto &itr : entity_list_search) {
|
||||||
|
Corpse *entity = itr.second;
|
||||||
|
|
||||||
|
entity_count++;
|
||||||
|
|
||||||
|
std::string entity_name = entity->GetName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter by name
|
||||||
|
*/
|
||||||
|
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string saylink = StringFormat(
|
||||||
|
"#goto %.0f %0.f %.0f",
|
||||||
|
entity->GetX(),
|
||||||
|
entity->GetY(),
|
||||||
|
entity->GetZ());
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
0,
|
||||||
|
"| %s | ID %5d | %s | x %.0f | y %0.f | z %.0f",
|
||||||
|
EQEmu::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Goto").c_str(),
|
||||||
|
entity->GetID(),
|
||||||
|
entity->GetName(),
|
||||||
|
entity->GetX(),
|
||||||
|
entity->GetY(),
|
||||||
|
entity->GetZ()
|
||||||
|
);
|
||||||
|
|
||||||
|
found_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Doors
|
||||||
|
*/
|
||||||
|
if (search_type.find("doors") != std::string::npos) {
|
||||||
|
auto &entity_list_search = entity_list.GetDoorsList();
|
||||||
|
|
||||||
|
for (auto &itr : entity_list_search) {
|
||||||
|
Doors * entity = itr.second;
|
||||||
|
|
||||||
|
entity_count++;
|
||||||
|
|
||||||
|
std::string entity_name = entity->GetDoorName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter by name
|
||||||
|
*/
|
||||||
|
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string saylink = StringFormat(
|
||||||
|
"#goto %.0f %0.f %.0f",
|
||||||
|
entity->GetX(),
|
||||||
|
entity->GetY(),
|
||||||
|
entity->GetZ());
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
0,
|
||||||
|
"| %s | Entity ID %5d | Door ID %i | %s | x %.0f | y %0.f | z %.0f",
|
||||||
|
EQEmu::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Goto").c_str(),
|
||||||
|
entity->GetID(),
|
||||||
|
entity->GetDoorID(),
|
||||||
|
entity->GetDoorName(),
|
||||||
|
entity->GetX(),
|
||||||
|
entity->GetY(),
|
||||||
|
entity->GetZ()
|
||||||
|
);
|
||||||
|
|
||||||
|
found_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Objects
|
||||||
|
*/
|
||||||
|
if (search_type.find("objects") != std::string::npos) {
|
||||||
|
auto &entity_list_search = entity_list.GetObjectList();
|
||||||
|
|
||||||
|
for (auto &itr : entity_list_search) {
|
||||||
|
Object * entity = itr.second;
|
||||||
|
|
||||||
|
entity_count++;
|
||||||
|
|
||||||
|
std::string entity_name = entity->GetModelName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter by name
|
||||||
|
*/
|
||||||
|
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string saylink = StringFormat(
|
||||||
|
"#goto %.0f %0.f %.0f",
|
||||||
|
entity->GetX(),
|
||||||
|
entity->GetY(),
|
||||||
|
entity->GetZ());
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
0,
|
||||||
|
"| %s | Entity ID %5d | Object DBID %i | %s | x %.0f | y %0.f | z %.0f",
|
||||||
|
EQEmu::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Goto").c_str(),
|
||||||
|
entity->GetID(),
|
||||||
|
entity->GetDBID(),
|
||||||
|
entity->GetModelName(),
|
||||||
|
entity->GetX(),
|
||||||
|
entity->GetY(),
|
||||||
|
entity->GetZ()
|
||||||
|
);
|
||||||
|
|
||||||
|
found_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found_count) {
|
||||||
|
c->Message(
|
||||||
|
0, "Found (%i) of type (%s) in zone (%i) total",
|
||||||
|
found_count,
|
||||||
|
search_type.c_str(),
|
||||||
|
entity_count
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
c->Message(0, "Usage of #listnpcs:");
|
c->Message(0, "Usage of #list");
|
||||||
c->Message(0, "#listnpcs [#] [#] (Each number would search by ID, ex. #listnpcs 1 30, searches 1-30)");
|
c->Message(0, "- #list [npcs|players|corpses|doors|objects] [search]");
|
||||||
c->Message(0, "#listnpcs [name] (Would search for a npc with [name])");
|
c->Message(0, "- Example: #list npc (Blank for all)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1534,24 +1788,24 @@ void command_npcstats(Client *c, const Seperator *sep)
|
|||||||
c->Message(0, "ERROR: Target is not a NPC!");
|
c->Message(0, "ERROR: Target is not a NPC!");
|
||||||
else {
|
else {
|
||||||
auto target_npc = c->GetTarget()->CastToNPC();
|
auto target_npc = c->GetTarget()->CastToNPC();
|
||||||
c->Message(0, "NPC Stats:");
|
c->Message(0, "# NPC Stats");
|
||||||
c->Message(0, "Name: %s NpcID: %u", target_npc->GetName(), target_npc->GetNPCTypeID());
|
c->Message(0, "- Name: %s NpcID: %u", target_npc->GetName(), target_npc->GetNPCTypeID());
|
||||||
c->Message(0, "Race: %i Level: %i Class: %i Material: %i", target_npc->GetRace(), target_npc->GetLevel(), target_npc->GetClass(), target_npc->GetTexture());
|
c->Message(0, "- Race: %i Level: %i Class: %i Material: %i", target_npc->GetRace(), target_npc->GetLevel(), target_npc->GetClass(), target_npc->GetTexture());
|
||||||
c->Message(0, "Current HP: %i Max HP: %i", target_npc->GetHP(), target_npc->GetMaxHP());
|
c->Message(0, "- Current HP: %i Max HP: %i", target_npc->GetHP(), target_npc->GetMaxHP());
|
||||||
//c->Message(0, "Weapon Item Number: %s", target_npc->GetWeapNo());
|
//c->Message(0, "Weapon Item Number: %s", target_npc->GetWeapNo());
|
||||||
c->Message(0, "Gender: %i Size: %f Bodytype: %d", target_npc->GetGender(), target_npc->GetSize(), target_npc->GetBodyType());
|
c->Message(0, "- Gender: %i Size: %f Bodytype: %d", target_npc->GetGender(), target_npc->GetSize(), target_npc->GetBodyType());
|
||||||
c->Message(0, "Runspeed: %.3f Walkspeed: %.3f", static_cast<float>(0.025f * target_npc->GetRunspeed()), static_cast<float>(0.025f * target_npc->GetWalkspeed()));
|
c->Message(0, "- Runspeed: %.3f Walkspeed: %.3f", static_cast<float>(0.025f * target_npc->GetRunspeed()), static_cast<float>(0.025f * target_npc->GetWalkspeed()));
|
||||||
c->Message(0, "Spawn Group: %i Grid: %i", target_npc->GetSp2(), target_npc->GetGrid());
|
c->Message(0, "- Spawn Group: %i Grid: %i", target_npc->GetSp2(), target_npc->GetGrid());
|
||||||
if (target_npc->proximity) {
|
if (target_npc->proximity) {
|
||||||
c->Message(0, "Proximity: Enabled");
|
c->Message(0, "- Proximity: Enabled");
|
||||||
c->Message(0, "Cur_X: %1.3f, Cur_Y: %1.3f, Cur_Z: %1.3f", target_npc->GetX(), target_npc->GetY(), target_npc->GetZ());
|
c->Message(0, "-- Cur_X: %1.3f, Cur_Y: %1.3f, Cur_Z: %1.3f", target_npc->GetX(), target_npc->GetY(), target_npc->GetZ());
|
||||||
c->Message(0, "Min_X: %1.3f(%1.3f), Max_X: %1.3f(%1.3f), X_Range: %1.3f", target_npc->proximity->min_x, (target_npc->proximity->min_x - target_npc->GetX()), target_npc->proximity->max_x, (target_npc->proximity->max_x - target_npc->GetX()), (target_npc->proximity->max_x - target_npc->proximity->min_x));
|
c->Message(0, "-- Min_X: %1.3f(%1.3f), Max_X: %1.3f(%1.3f), X_Range: %1.3f", target_npc->proximity->min_x, (target_npc->proximity->min_x - target_npc->GetX()), target_npc->proximity->max_x, (target_npc->proximity->max_x - target_npc->GetX()), (target_npc->proximity->max_x - target_npc->proximity->min_x));
|
||||||
c->Message(0, "Min_Y: %1.3f(%1.3f), Max_Y: %1.3f(%1.3f), Y_Range: %1.3f", target_npc->proximity->min_y, (target_npc->proximity->min_y - target_npc->GetY()), target_npc->proximity->max_y, (target_npc->proximity->max_y - target_npc->GetY()), (target_npc->proximity->max_y - target_npc->proximity->min_y));
|
c->Message(0, "-- Min_Y: %1.3f(%1.3f), Max_Y: %1.3f(%1.3f), Y_Range: %1.3f", target_npc->proximity->min_y, (target_npc->proximity->min_y - target_npc->GetY()), target_npc->proximity->max_y, (target_npc->proximity->max_y - target_npc->GetY()), (target_npc->proximity->max_y - target_npc->proximity->min_y));
|
||||||
c->Message(0, "Min_Z: %1.3f(%1.3f), Max_Z: %1.3f(%1.3f), Z_Range: %1.3f", target_npc->proximity->min_z, (target_npc->proximity->min_z - target_npc->GetZ()), target_npc->proximity->max_z, (target_npc->proximity->max_z - target_npc->GetZ()), (target_npc->proximity->max_z - target_npc->proximity->min_z));
|
c->Message(0, "-- Min_Z: %1.3f(%1.3f), Max_Z: %1.3f(%1.3f), Z_Range: %1.3f", target_npc->proximity->min_z, (target_npc->proximity->min_z - target_npc->GetZ()), target_npc->proximity->max_z, (target_npc->proximity->max_z - target_npc->GetZ()), (target_npc->proximity->max_z - target_npc->proximity->min_z));
|
||||||
c->Message(0, "Say: %s", (target_npc->proximity->say ? "Enabled" : "Disabled"));
|
c->Message(0, "-- Say: %s", (target_npc->proximity->say ? "Enabled" : "Disabled"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
c->Message(0, "Proximity: Disabled");
|
c->Message(0, "-Proximity: Disabled");
|
||||||
}
|
}
|
||||||
c->Message(0, "");
|
c->Message(0, "");
|
||||||
c->Message(0, "EmoteID: %i", target_npc->GetEmoteID());
|
c->Message(0, "EmoteID: %i", target_npc->GetEmoteID());
|
||||||
@ -1762,7 +2016,7 @@ void command_zheader(Client *c, const Seperator *sep)
|
|||||||
c->Message(0, "Invalid Zone Name: %s", sep->argplus[1]);
|
c->Message(0, "Invalid Zone Name: %s", sep->argplus[1]);
|
||||||
else {
|
else {
|
||||||
|
|
||||||
if (zone->LoadZoneCFG(sep->argplus[1], true))
|
if (zone->LoadZoneCFG(sep->argplus[1], 0))
|
||||||
c->Message(0, "Successfully loaded zone header for %s from database.", sep->argplus[1]);
|
c->Message(0, "Successfully loaded zone header for %s from database.", sep->argplus[1]);
|
||||||
else
|
else
|
||||||
c->Message(0, "Failed to load zone header %s from database", sep->argplus[1]);
|
c->Message(0, "Failed to load zone header %s from database", sep->argplus[1]);
|
||||||
@ -2123,9 +2377,10 @@ void command_grid(Client *c, const Seperator *sep)
|
|||||||
auto &mob_list = entity_list.GetMobList();
|
auto &mob_list = entity_list.GetMobList();
|
||||||
for (auto itr = mob_list.begin(); itr != mob_list.end(); ++itr) {
|
for (auto itr = mob_list.begin(); itr != mob_list.end(); ++itr) {
|
||||||
Mob *mob = itr->second;
|
Mob *mob = itr->second;
|
||||||
if (mob->IsNPC() && mob->GetRace() == 2254)
|
if (mob->IsNPC() && mob->GetRace() == 2254) {
|
||||||
mob->Depop();
|
mob->Depop();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spawn grid nodes
|
* Spawn grid nodes
|
||||||
@ -2144,11 +2399,12 @@ void command_grid(Client *c, const Seperator *sep)
|
|||||||
npc->GMMove(node_position.x, node_position.y, node_position.z, node_position.w);
|
npc->GMMove(node_position.x, node_position.y, node_position.z, node_position.w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcasecmp("delete", sep->arg[1]) == 0)
|
else if (strcasecmp("delete", sep->arg[1]) == 0) {
|
||||||
database.ModifyGrid(c, true,atoi(sep->arg[2]),0,0,zone->GetZoneID());
|
database.ModifyGrid(c, true, atoi(sep->arg[2]), 0, 0, zone->GetZoneID());
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
c->Message(0,"Usage: #grid add/delete grid_num wandertype pausetype");
|
c->Message(0, "Usage: #grid add/delete grid_num wandertype pausetype");
|
||||||
c->Message(0,"Usage: #grid max - displays the highest grid ID used in this zone (for add)");
|
c->Message(0, "Usage: #grid max - displays the highest grid ID used in this zone (for add)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4436,6 +4692,49 @@ void command_depopzone(Client *c, const Seperator *sep)
|
|||||||
c->Message(0, "Zone depoped.");
|
c->Message(0, "Zone depoped.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void command_devtools(Client *c, const Seperator *sep)
|
||||||
|
{
|
||||||
|
std::string menu_commands_search;
|
||||||
|
std::string window_toggle_command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search entity commands
|
||||||
|
*/
|
||||||
|
menu_commands_search += "[" + EQEmu::SayLinkEngine::GenerateQuestSaylink("#list npcs", false, "NPC") + "] ";
|
||||||
|
menu_commands_search += "[" + EQEmu::SayLinkEngine::GenerateQuestSaylink("#list players", false, "Players") + "] ";
|
||||||
|
menu_commands_search += "[" + EQEmu::SayLinkEngine::GenerateQuestSaylink("#list corpses", false, "Corpses") + "] ";
|
||||||
|
menu_commands_search += "[" + EQEmu::SayLinkEngine::GenerateQuestSaylink("#list doors", false, "Doors") + "] ";
|
||||||
|
menu_commands_search += "[" + EQEmu::SayLinkEngine::GenerateQuestSaylink("#list objects", false, "Objects") + "] ";
|
||||||
|
|
||||||
|
std::string dev_tools_window_key = StringFormat("%i-dev-tools-window-disabled", c->AccountID());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle window toggle
|
||||||
|
*/
|
||||||
|
if (strcasecmp(sep->arg[1], "disable_window") == 0) {
|
||||||
|
DataBucket::SetData(dev_tools_window_key, "true");
|
||||||
|
c->SetDevToolsWindowEnabled(false);
|
||||||
|
}
|
||||||
|
if (strcasecmp(sep->arg[1], "enable_window") == 0) {
|
||||||
|
DataBucket::DeleteData(dev_tools_window_key);
|
||||||
|
c->SetDevToolsWindowEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show window status
|
||||||
|
*/
|
||||||
|
window_toggle_command = "Disabled [" + EQEmu::SayLinkEngine::GenerateQuestSaylink("#devtools enable_window", false, "Enable") + "] ";
|
||||||
|
if (c->IsDevToolsWindowEnabled()) {
|
||||||
|
window_toggle_command = "Enabled [" + EQEmu::SayLinkEngine::GenerateQuestSaylink("#devtools disable_window", false, "Disable") + "] ";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print menu
|
||||||
|
*/
|
||||||
|
c->Message(0, "| [Devtools] Window %s", window_toggle_command.c_str());
|
||||||
|
c->Message(0, "| [Devtools] Search %s", menu_commands_search.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
void command_repop(Client *c, const Seperator *sep)
|
void command_repop(Client *c, const Seperator *sep)
|
||||||
{
|
{
|
||||||
int timearg = 1;
|
int timearg = 1;
|
||||||
@ -11234,6 +11533,133 @@ void command_reloadtraps(Client *c, const Seperator *sep)
|
|||||||
c->Message(CC_Default, "Traps reloaded for %s.", zone->GetShortName());
|
c->Message(CC_Default, "Traps reloaded for %s.", zone->GetShortName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void command_scale(Client *c, const Seperator *sep)
|
||||||
|
{
|
||||||
|
if (sep->argnum == 0) {
|
||||||
|
c->Message(15, "# Usage # ");
|
||||||
|
c->Message(15, "#scale [static/dynamic] (With targeted NPC)");
|
||||||
|
c->Message(15, "#scale [npc_name_search] [static/dynamic] (To make zone-wide changes)");
|
||||||
|
c->Message(15, "#scale all [static/dynamic]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Targeted changes
|
||||||
|
*/
|
||||||
|
if (c->GetTarget() && c->GetTarget()->IsNPC() && sep->argnum < 2) {
|
||||||
|
NPC * npc = c->GetTarget()->CastToNPC();
|
||||||
|
|
||||||
|
bool apply_status = false;
|
||||||
|
if (strcasecmp(sep->arg[1], "dynamic") == 0) {
|
||||||
|
c->Message(15, "Applying global base scaling to npc dynamically (All stats set to zeroes)...");
|
||||||
|
apply_status = npc_scale_manager->ApplyGlobalBaseScalingToNPCDynamically(npc);
|
||||||
|
}
|
||||||
|
else if (strcasecmp(sep->arg[1], "static") == 0) {
|
||||||
|
c->Message(15, "Applying global base scaling to npc statically (Copying base stats onto NPC)...");
|
||||||
|
apply_status = npc_scale_manager->ApplyGlobalBaseScalingToNPCStatically(npc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (apply_status) {
|
||||||
|
c->Message(15, "Applied to NPC '%s' successfully!", npc->GetName());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c->Message(15, "Failed to load scaling data from the database "
|
||||||
|
"for this npc / type, see 'NPCScaling' log for more info");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c->GetTarget() && sep->argnum < 2) {
|
||||||
|
c->Message(15, "Target must be an npc!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zonewide
|
||||||
|
*/
|
||||||
|
if (sep->argnum > 1) {
|
||||||
|
|
||||||
|
std::string scale_type;
|
||||||
|
if (strcasecmp(sep->arg[2], "dynamic") == 0) {
|
||||||
|
scale_type = "dynamic";
|
||||||
|
}
|
||||||
|
else if (strcasecmp(sep->arg[2], "static") == 0) {
|
||||||
|
scale_type = "static";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scale_type.length() <= 0) {
|
||||||
|
c->Message(15, "You must first set if you intend on using static versus dynamic for these changes");
|
||||||
|
c->Message(15, "#scale [npc_name_search] [static/dynamic]");
|
||||||
|
c->Message(15, "#scale all [static/dynamic]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string search_string = sep->arg[1];
|
||||||
|
|
||||||
|
auto &entity_list_search = entity_list.GetNPCList();
|
||||||
|
|
||||||
|
int found_count = 0;
|
||||||
|
for (auto &itr : entity_list_search) {
|
||||||
|
NPC *entity = itr.second;
|
||||||
|
|
||||||
|
std::string entity_name = entity->GetName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter by name
|
||||||
|
*/
|
||||||
|
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos && strcasecmp(sep->arg[1], "all") != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string status = "(Searching)";
|
||||||
|
|
||||||
|
if (strcasecmp(sep->arg[3], "apply") == 0) {
|
||||||
|
status = "(Applying)";
|
||||||
|
|
||||||
|
if (strcasecmp(sep->arg[2], "dynamic") == 0) {
|
||||||
|
npc_scale_manager->ApplyGlobalBaseScalingToNPCDynamically(entity);
|
||||||
|
}
|
||||||
|
if (strcasecmp(sep->arg[2], "static") == 0) {
|
||||||
|
npc_scale_manager->ApplyGlobalBaseScalingToNPCStatically(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
15,
|
||||||
|
"| ID %5d | %s | x %.0f | y %0.f | z %.0f | DBID %u %s",
|
||||||
|
entity->GetID(),
|
||||||
|
entity->GetName(),
|
||||||
|
entity->GetX(),
|
||||||
|
entity->GetY(),
|
||||||
|
entity->GetZ(),
|
||||||
|
entity->GetNPCTypeID(),
|
||||||
|
status.c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
found_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(sep->arg[3], "apply") == 0) {
|
||||||
|
c->Message(15, "%s scaling applied against (%i) NPC's", sep->arg[2], found_count);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
std::string saylink = StringFormat(
|
||||||
|
"#scale %s %s apply",
|
||||||
|
sep->arg[1],
|
||||||
|
sep->arg[2]
|
||||||
|
);
|
||||||
|
|
||||||
|
c->Message(15, "Found (%i) NPC's that match this search...", found_count);
|
||||||
|
c->Message(
|
||||||
|
15, "To apply these changes, click <%s> or type %s",
|
||||||
|
EQEmu::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Apply").c_str(),
|
||||||
|
saylink.c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// All new code added to command.cpp should be BEFORE this comment line. Do no append code to this file below the BOTS code block.
|
// All new code added to command.cpp should be BEFORE this comment line. Do no append code to this file below the BOTS code block.
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
#include "bot_command.h"
|
#include "bot_command.h"
|
||||||
|
|||||||
@ -84,6 +84,7 @@ void command_deletegraveyard(Client *c, const Seperator *sep);
|
|||||||
void command_delpetition(Client *c, const Seperator *sep);
|
void command_delpetition(Client *c, const Seperator *sep);
|
||||||
void command_depop(Client *c, const Seperator *sep);
|
void command_depop(Client *c, const Seperator *sep);
|
||||||
void command_depopzone(Client *c, const Seperator *sep);
|
void command_depopzone(Client *c, const Seperator *sep);
|
||||||
|
void command_devtools(Client *c, const Seperator *sep);
|
||||||
void command_details(Client *c, const Seperator *sep);
|
void command_details(Client *c, const Seperator *sep);
|
||||||
void command_disablerecipe(Client *c, const Seperator *sep);
|
void command_disablerecipe(Client *c, const Seperator *sep);
|
||||||
void command_disarmtrap(Client *c, const Seperator *sep);
|
void command_disarmtrap(Client *c, const Seperator *sep);
|
||||||
@ -152,6 +153,7 @@ void command_kill(Client *c, const Seperator *sep);
|
|||||||
void command_lastname(Client *c, const Seperator *sep);
|
void command_lastname(Client *c, const Seperator *sep);
|
||||||
void command_level(Client *c, const Seperator *sep);
|
void command_level(Client *c, const Seperator *sep);
|
||||||
void command_listnpcs(Client *c, const Seperator *sep);
|
void command_listnpcs(Client *c, const Seperator *sep);
|
||||||
|
void command_list(Client *c, const Seperator *sep);
|
||||||
void command_listpetition(Client *c, const Seperator *sep);
|
void command_listpetition(Client *c, const Seperator *sep);
|
||||||
void command_load_shared_memory(Client *c, const Seperator *sep);
|
void command_load_shared_memory(Client *c, const Seperator *sep);
|
||||||
void command_loc(Client *c, const Seperator *sep);
|
void command_loc(Client *c, const Seperator *sep);
|
||||||
@ -242,6 +244,7 @@ void command_resetaa_timer(Client *c, const Seperator *sep);
|
|||||||
void command_revoke(Client *c, const Seperator *sep);
|
void command_revoke(Client *c, const Seperator *sep);
|
||||||
void command_rules(Client *c, const Seperator *sep);
|
void command_rules(Client *c, const Seperator *sep);
|
||||||
void command_save(Client *c, const Seperator *sep);
|
void command_save(Client *c, const Seperator *sep);
|
||||||
|
void command_scale(Client *c, const Seperator *sep);
|
||||||
void command_scribespell(Client *c, const Seperator *sep);
|
void command_scribespell(Client *c, const Seperator *sep);
|
||||||
void command_scribespells(Client *c, const Seperator *sep);
|
void command_scribespells(Client *c, const Seperator *sep);
|
||||||
void command_sendop(Client *c, const Seperator *sep);
|
void command_sendop(Client *c, const Seperator *sep);
|
||||||
|
|||||||
@ -820,7 +820,7 @@ void Doors::SetDisableTimer(bool flag) {
|
|||||||
|
|
||||||
void Doors::CreateDatabaseEntry()
|
void Doors::CreateDatabaseEntry()
|
||||||
{
|
{
|
||||||
if(database.GetDoorsDBCountPlusOne(zone->GetShortName(), zone->GetInstanceVersion()) - 1 >= 255) {
|
if (database.GetDoorsDBCountPlusOne(zone->GetShortName(), zone->GetInstanceVersion()) - 1 >= 255) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -843,3 +843,17 @@ void Doors::CreateDatabaseEntry()
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Doors::GetX()
|
||||||
|
{
|
||||||
|
return m_Position.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Doors::GetY()
|
||||||
|
{
|
||||||
|
return m_Position.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Doors::GetZ()
|
||||||
|
{
|
||||||
|
return m_Position.z;
|
||||||
|
}
|
||||||
|
|||||||
@ -64,6 +64,10 @@ public:
|
|||||||
void SetSize(uint16 size);
|
void SetSize(uint16 size);
|
||||||
void ToggleState(Mob *sender);
|
void ToggleState(Mob *sender);
|
||||||
|
|
||||||
|
float GetX();
|
||||||
|
float GetY();
|
||||||
|
float GetZ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint32 database_id;
|
uint32 database_id;
|
||||||
|
|||||||
@ -2870,6 +2870,20 @@ XS(XS__GetInstanceID) {
|
|||||||
XSRETURN_UV(id);
|
XSRETURN_UV(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XS(XS__GetInstanceIDByCharID);
|
||||||
|
XS(XS__GetInstanceIDByCharID) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 3)
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::GetInstanceIDByCharID(string zone_name, uint16 version, uint32 char_id)");
|
||||||
|
|
||||||
|
char *zone = (char *) SvPV_nolen(ST(0));
|
||||||
|
uint16 version = (int) SvUV(ST(1));
|
||||||
|
uint32 char_id = (int) SvUV(ST(2));
|
||||||
|
uint16 id = quest_manager.GetInstanceIDByCharID(zone, version, char_id);
|
||||||
|
|
||||||
|
XSRETURN_UV(id);
|
||||||
|
}
|
||||||
|
|
||||||
XS(XS__GetCharactersInInstance);
|
XS(XS__GetCharactersInInstance);
|
||||||
XS(XS__GetCharactersInInstance) {
|
XS(XS__GetCharactersInInstance) {
|
||||||
dXSARGS;
|
dXSARGS;
|
||||||
@ -2921,6 +2935,19 @@ XS(XS__AssignToInstance) {
|
|||||||
XSRETURN_EMPTY;
|
XSRETURN_EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XS(XS__AssignToInstanceByCharID);
|
||||||
|
XS(XS__AssignToInstanceByCharID) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 2)
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::AssignToInstanceByCharID(uint16 instance_id, uint32 char_id)");
|
||||||
|
|
||||||
|
uint16 instance_id = (int) SvUV(ST(0));
|
||||||
|
uint32 char_id = (int) SvUV(ST(1));
|
||||||
|
quest_manager.AssignToInstanceByCharID(instance_id, char_id);
|
||||||
|
|
||||||
|
XSRETURN_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
XS(XS__AssignGroupToInstance);
|
XS(XS__AssignGroupToInstance);
|
||||||
XS(XS__AssignGroupToInstance) {
|
XS(XS__AssignGroupToInstance) {
|
||||||
dXSARGS;
|
dXSARGS;
|
||||||
@ -2957,6 +2984,19 @@ XS(XS__RemoveFromInstance) {
|
|||||||
XSRETURN_EMPTY;
|
XSRETURN_EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XS(XS__RemoveFromInstanceByCharID);
|
||||||
|
XS(XS__RemoveFromInstanceByCharID) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 2)
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::RemoveFromInstanceByCharID(uint16 instance_id, uint32 char_id)");
|
||||||
|
|
||||||
|
uint16 instance_id = (int) SvUV(ST(0));
|
||||||
|
uint32 char_id = (int) SvUV(ST(1));
|
||||||
|
quest_manager.RemoveFromInstanceByCharID(instance_id, char_id);
|
||||||
|
|
||||||
|
XSRETURN_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
XS(XS__RemoveAllFromInstance);
|
XS(XS__RemoveAllFromInstance);
|
||||||
XS(XS__RemoveAllFromInstance) {
|
XS(XS__RemoveAllFromInstance) {
|
||||||
dXSARGS;
|
dXSARGS;
|
||||||
@ -3025,7 +3065,7 @@ XS(XS__saylink) {
|
|||||||
Perl_croak(aTHX_ "Usage: quest::saylink(string message, [bool silent = false], [link_name = message])");
|
Perl_croak(aTHX_ "Usage: quest::saylink(string message, [bool silent = false], [link_name = message])");
|
||||||
dXSTARG;
|
dXSTARG;
|
||||||
|
|
||||||
Const_char *RETVAL;
|
std::string RETVAL;
|
||||||
char message[250];
|
char message[250];
|
||||||
char link_name[250];
|
char link_name[250];
|
||||||
bool silent = false;
|
bool silent = false;
|
||||||
@ -3039,7 +3079,8 @@ XS(XS__saylink) {
|
|||||||
strcpy(link_name, message);
|
strcpy(link_name, message);
|
||||||
|
|
||||||
RETVAL = quest_manager.saylink(message, silent, link_name);
|
RETVAL = quest_manager.saylink(message, silent, link_name);
|
||||||
sv_setpv(TARG, RETVAL);
|
|
||||||
|
sv_setpv(TARG, RETVAL.c_str());
|
||||||
XSprePUSH;
|
XSprePUSH;
|
||||||
PUSHTARG;
|
PUSHTARG;
|
||||||
XSRETURN(1);
|
XSRETURN(1);
|
||||||
@ -3675,6 +3716,7 @@ EXTERN_C XS(boot_quest) {
|
|||||||
newXS(strcpy(buf, "AssignGroupToInstance"), XS__AssignGroupToInstance, file);
|
newXS(strcpy(buf, "AssignGroupToInstance"), XS__AssignGroupToInstance, file);
|
||||||
newXS(strcpy(buf, "AssignRaidToInstance"), XS__AssignRaidToInstance, file);
|
newXS(strcpy(buf, "AssignRaidToInstance"), XS__AssignRaidToInstance, file);
|
||||||
newXS(strcpy(buf, "AssignToInstance"), XS__AssignToInstance, file);
|
newXS(strcpy(buf, "AssignToInstance"), XS__AssignToInstance, file);
|
||||||
|
newXS(strcpy(buf, "AssignToInstanceByCharID"), XS__AssignToInstanceByCharID, file);
|
||||||
newXS(strcpy(buf, "ChooseRandom"), XS__ChooseRandom, file);
|
newXS(strcpy(buf, "ChooseRandom"), XS__ChooseRandom, file);
|
||||||
newXS(strcpy(buf, "CreateInstance"), XS__CreateInstance, file);
|
newXS(strcpy(buf, "CreateInstance"), XS__CreateInstance, file);
|
||||||
newXS(strcpy(buf, "DestroyInstance"), XS__DestroyInstance, file);
|
newXS(strcpy(buf, "DestroyInstance"), XS__DestroyInstance, file);
|
||||||
@ -3686,6 +3728,7 @@ EXTERN_C XS(boot_quest) {
|
|||||||
newXS(strcpy(buf, "FlyMode"), XS__FlyMode, file);
|
newXS(strcpy(buf, "FlyMode"), XS__FlyMode, file);
|
||||||
newXS(strcpy(buf, "GetCharactersInInstance"), XS__GetCharactersInInstance, file);
|
newXS(strcpy(buf, "GetCharactersInInstance"), XS__GetCharactersInInstance, file);
|
||||||
newXS(strcpy(buf, "GetInstanceID"), XS__GetInstanceID, file);
|
newXS(strcpy(buf, "GetInstanceID"), XS__GetInstanceID, file);
|
||||||
|
newXS(strcpy(buf, "GetInstanceIDByCharID"), XS__GetInstanceIDByCharID, file);
|
||||||
newXS(strcpy(buf, "GetSpellResistType"), XS__GetSpellResistType, file);
|
newXS(strcpy(buf, "GetSpellResistType"), XS__GetSpellResistType, file);
|
||||||
newXS(strcpy(buf, "GetSpellTargetType"), XS__GetSpellTargetType, file);
|
newXS(strcpy(buf, "GetSpellTargetType"), XS__GetSpellTargetType, file);
|
||||||
newXS(strcpy(buf, "GetTimeSeconds"), XS__GetTimeSeconds, file);
|
newXS(strcpy(buf, "GetTimeSeconds"), XS__GetTimeSeconds, file);
|
||||||
@ -3704,6 +3747,7 @@ EXTERN_C XS(boot_quest) {
|
|||||||
newXS(strcpy(buf, "MovePCInstance"), XS__MovePCInstance, file);
|
newXS(strcpy(buf, "MovePCInstance"), XS__MovePCInstance, file);
|
||||||
newXS(strcpy(buf, "RemoveAllFromInstance"), XS__RemoveAllFromInstance, file);
|
newXS(strcpy(buf, "RemoveAllFromInstance"), XS__RemoveAllFromInstance, file);
|
||||||
newXS(strcpy(buf, "RemoveFromInstance"), XS__RemoveFromInstance, file);
|
newXS(strcpy(buf, "RemoveFromInstance"), XS__RemoveFromInstance, file);
|
||||||
|
newXS(strcpy(buf, "RemoveFromInstanceByCharID"), XS__RemoveFromInstanceByCharID, file);
|
||||||
newXS(strcpy(buf, "SendMail"), XS__SendMail, file);
|
newXS(strcpy(buf, "SendMail"), XS__SendMail, file);
|
||||||
newXS(strcpy(buf, "SetRunning"), XS__SetRunning, file);
|
newXS(strcpy(buf, "SetRunning"), XS__SetRunning, file);
|
||||||
newXS(strcpy(buf, "activespeakactivity"), XS__activespeakactivity, file);
|
newXS(strcpy(buf, "activespeakactivity"), XS__activespeakactivity, file);
|
||||||
|
|||||||
@ -40,6 +40,8 @@
|
|||||||
#include "string_ids.h"
|
#include "string_ids.h"
|
||||||
#include "worldserver.h"
|
#include "worldserver.h"
|
||||||
#include "water_map.h"
|
#include "water_map.h"
|
||||||
|
#include "npc_scale_manager.h"
|
||||||
|
#include "../common/say_link.h"
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
@ -2703,58 +2705,6 @@ char *EntityList::RemoveNumbers(char *name)
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityList::ListNPCs(Client* client, const char *arg1, const char *arg2, uint8 searchtype)
|
|
||||||
{
|
|
||||||
if (arg1 == 0)
|
|
||||||
searchtype = 0;
|
|
||||||
else if (arg2 == 0 && searchtype >= 2)
|
|
||||||
searchtype = 0;
|
|
||||||
uint32 x = 0;
|
|
||||||
uint32 z = 0;
|
|
||||||
char sName[36];
|
|
||||||
|
|
||||||
auto it = npc_list.begin();
|
|
||||||
client->Message(0, "NPCs in the zone:");
|
|
||||||
if (searchtype == 0) {
|
|
||||||
while (it != npc_list.end()) {
|
|
||||||
NPC *n = it->second;
|
|
||||||
|
|
||||||
client->Message(0, " %5d: %s (%.0f, %0.f, %.0f)", n->GetID(), n->GetName(), n->GetX(), n->GetY(), n->GetZ());
|
|
||||||
x++;
|
|
||||||
z++;
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
} else if (searchtype == 1) {
|
|
||||||
client->Message(0, "Searching by name method. (%s)",arg1);
|
|
||||||
auto tmp = new char[strlen(arg1) + 1];
|
|
||||||
strcpy(tmp, arg1);
|
|
||||||
strupr(tmp);
|
|
||||||
while (it != npc_list.end()) {
|
|
||||||
z++;
|
|
||||||
strcpy(sName, it->second->GetName());
|
|
||||||
strupr(sName);
|
|
||||||
if (strstr(sName, tmp)) {
|
|
||||||
NPC *n = it->second;
|
|
||||||
client->Message(0, " %5d: %s (%.0f, %.0f, %.0f)", n->GetID(), n->GetName(), n->GetX(), n->GetY(), n->GetZ());
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
safe_delete_array(tmp);
|
|
||||||
} else if (searchtype == 2) {
|
|
||||||
client->Message(0, "Searching by number method. (%s %s)",arg1,arg2);
|
|
||||||
while (it != npc_list.end()) {
|
|
||||||
z++;
|
|
||||||
if ((it->second->GetID() >= atoi(arg1)) && (it->second->GetID() <= atoi(arg2)) && (atoi(arg1) <= atoi(arg2))) {
|
|
||||||
client->Message(0, " %5d: %s", it->second->GetID(), it->second->GetName());
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client->Message(0, "%d npcs listed. There is a total of %d npcs in this zone.", x, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EntityList::ListNPCCorpses(Client *client)
|
void EntityList::ListNPCCorpses(Client *client)
|
||||||
{
|
{
|
||||||
uint32 x = 0;
|
uint32 x = 0;
|
||||||
|
|||||||
@ -381,7 +381,6 @@ public:
|
|||||||
void SendPetitionToAdmins();
|
void SendPetitionToAdmins();
|
||||||
void AddLootToNPCS(uint32 item_id, uint32 count);
|
void AddLootToNPCS(uint32 item_id, uint32 count);
|
||||||
|
|
||||||
void ListNPCs(Client* client, const char* arg1 = 0, const char* arg2 = 0, uint8 searchtype = 0);
|
|
||||||
void ListNPCCorpses(Client* client);
|
void ListNPCCorpses(Client* client);
|
||||||
void ListPlayerCorpses(Client* client);
|
void ListPlayerCorpses(Client* client);
|
||||||
int32 DeleteNPCCorpses();
|
int32 DeleteNPCCorpses();
|
||||||
|
|||||||
28
zone/exp.cpp
28
zone/exp.cpp
@ -684,17 +684,15 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(RuleB(Character, PerCharacterQglobalMaxLevel)){
|
if (GetClientMaxLevel() > 0) {
|
||||||
uint32 MaxLevel = GetCharMaxLevelFromQGlobal();
|
int client_max_level = GetClientMaxLevel();
|
||||||
if(MaxLevel){
|
if (GetLevel() >= client_max_level) {
|
||||||
if(GetLevel() >= MaxLevel){
|
uint32 expneeded = GetEXPForLevel(client_max_level);
|
||||||
uint32 expneeded = GetEXPForLevel(MaxLevel);
|
|
||||||
if(set_exp > expneeded) {
|
if(set_exp > expneeded) {
|
||||||
set_exp = expneeded;
|
set_exp = expneeded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ((GetLevel() != check_level) && !(check_level >= maxlevel)) {
|
if ((GetLevel() != check_level) && !(check_level >= maxlevel)) {
|
||||||
char val1[20]={0};
|
char val1[20]={0};
|
||||||
@ -1130,7 +1128,23 @@ uint32 Client::GetCharMaxLevelFromQGlobal() {
|
|||||||
++gcount;
|
++gcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 Client::GetCharMaxLevelFromBucket() {
|
||||||
|
uint32 char_id = this->CharacterID();
|
||||||
|
std::string query = StringFormat("SELECT value FROM data_buckets WHERE key = '%i-CharMaxLevel'", char_id);
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
Log(Logs::General, Logs::Error, "Data bucket for CharMaxLevel for char ID %i failed.", char_id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results.RowCount() > 0) {
|
||||||
|
auto row = results.begin();
|
||||||
|
return atoi(row[0]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Client::GetRequiredAAExperience() {
|
uint32 Client::GetRequiredAAExperience() {
|
||||||
|
|||||||
@ -789,33 +789,29 @@ int lua_merchant_count_item(uint32 npc_id, uint32 item_id) {
|
|||||||
|
|
||||||
std::string lua_item_link(int item_id) {
|
std::string lua_item_link(int item_id) {
|
||||||
char text[250] = { 0 };
|
char text[250] = { 0 };
|
||||||
quest_manager.varlink(text, item_id);
|
|
||||||
|
|
||||||
return std::string(text);
|
return quest_manager.varlink(text, item_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string lua_say_link(const char *phrase, bool silent, const char *link_name) {
|
std::string lua_say_link(const char *phrase, bool silent, const char *link_name) {
|
||||||
char text[256] = { 0 };
|
char text[256] = { 0 };
|
||||||
strncpy(text, phrase, 255);
|
strncpy(text, phrase, 255);
|
||||||
quest_manager.saylink(text, silent, link_name);
|
|
||||||
|
|
||||||
return std::string(text);
|
return quest_manager.saylink(text, silent, link_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string lua_say_link(const char *phrase, bool silent) {
|
std::string lua_say_link(const char *phrase, bool silent) {
|
||||||
char text[256] = { 0 };
|
char text[256] = { 0 };
|
||||||
strncpy(text, phrase, 255);
|
strncpy(text, phrase, 255);
|
||||||
quest_manager.saylink(text, silent, text);
|
|
||||||
|
|
||||||
return std::string(text);
|
return quest_manager.saylink(text, silent, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string lua_say_link(const char *phrase) {
|
std::string lua_say_link(const char *phrase) {
|
||||||
char text[256] = { 0 };
|
char text[256] = { 0 };
|
||||||
strncpy(text, phrase, 255);
|
strncpy(text, phrase, 255);
|
||||||
quest_manager.saylink(text, false, text);
|
|
||||||
|
|
||||||
return std::string(text);
|
return quest_manager.saylink(text, false, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string lua_get_data(std::string bucket_key) {
|
std::string lua_get_data(std::string bucket_key) {
|
||||||
@ -866,10 +862,18 @@ int lua_get_instance_id(const char *zone, uint32 version) {
|
|||||||
return quest_manager.GetInstanceID(zone, version);
|
return quest_manager.GetInstanceID(zone, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int lua_get_instance_id_by_char_id(const char *zone, uint32 version, uint32 char_id) {
|
||||||
|
return quest_manager.GetInstanceIDByCharID(zone, version, char_id);
|
||||||
|
}
|
||||||
|
|
||||||
void lua_assign_to_instance(uint32 instance_id) {
|
void lua_assign_to_instance(uint32 instance_id) {
|
||||||
quest_manager.AssignToInstance(instance_id);
|
quest_manager.AssignToInstance(instance_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lua_assign_to_instance_by_char_id(uint32 instance_id, uint32 char_id) {
|
||||||
|
quest_manager.AssignToInstanceByCharID(instance_id, char_id);
|
||||||
|
}
|
||||||
|
|
||||||
void lua_assign_group_to_instance(uint32 instance_id) {
|
void lua_assign_group_to_instance(uint32 instance_id) {
|
||||||
quest_manager.AssignGroupToInstance(instance_id);
|
quest_manager.AssignGroupToInstance(instance_id);
|
||||||
}
|
}
|
||||||
@ -882,6 +886,10 @@ void lua_remove_from_instance(uint32 instance_id) {
|
|||||||
quest_manager.RemoveFromInstance(instance_id);
|
quest_manager.RemoveFromInstance(instance_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lua_remove_from_instance_by_char_id(uint32 instance_id, uint32 char_id) {
|
||||||
|
quest_manager.RemoveFromInstanceByCharID(instance_id, char_id);
|
||||||
|
}
|
||||||
|
|
||||||
void lua_remove_all_from_instance(uint32 instance_id) {
|
void lua_remove_all_from_instance(uint32 instance_id) {
|
||||||
quest_manager.RemoveAllFromInstance(instance_id);
|
quest_manager.RemoveAllFromInstance(instance_id);
|
||||||
}
|
}
|
||||||
@ -1430,19 +1438,19 @@ void lua_create_npc(luabind::adl::object table, float x, float y, float z, float
|
|||||||
LuaCreateNPCParse(AC, uint32, 0);
|
LuaCreateNPCParse(AC, uint32, 0);
|
||||||
LuaCreateNPCParse(Mana, uint32, 0);
|
LuaCreateNPCParse(Mana, uint32, 0);
|
||||||
LuaCreateNPCParse(ATK, uint32, 0);
|
LuaCreateNPCParse(ATK, uint32, 0);
|
||||||
LuaCreateNPCParse(STR, uint32, 75);
|
LuaCreateNPCParse(STR, uint32, 0);
|
||||||
LuaCreateNPCParse(STA, uint32, 75);
|
LuaCreateNPCParse(STA, uint32, 0);
|
||||||
LuaCreateNPCParse(DEX, uint32, 75);
|
LuaCreateNPCParse(DEX, uint32, 0);
|
||||||
LuaCreateNPCParse(AGI, uint32, 75);
|
LuaCreateNPCParse(AGI, uint32, 0);
|
||||||
LuaCreateNPCParse(INT, uint32, 75);
|
LuaCreateNPCParse(INT, uint32, 0);
|
||||||
LuaCreateNPCParse(WIS, uint32, 75);
|
LuaCreateNPCParse(WIS, uint32, 0);
|
||||||
LuaCreateNPCParse(CHA, uint32, 75);
|
LuaCreateNPCParse(CHA, uint32, 0);
|
||||||
LuaCreateNPCParse(MR, int32, 25);
|
LuaCreateNPCParse(MR, int32, 0);
|
||||||
LuaCreateNPCParse(FR, int32, 25);
|
LuaCreateNPCParse(FR, int32, 0);
|
||||||
LuaCreateNPCParse(CR, int32, 25);
|
LuaCreateNPCParse(CR, int32, 0);
|
||||||
LuaCreateNPCParse(PR, int32, 25);
|
LuaCreateNPCParse(PR, int32, 0);
|
||||||
LuaCreateNPCParse(DR, int32, 25);
|
LuaCreateNPCParse(DR, int32, 0);
|
||||||
LuaCreateNPCParse(Corrup, int32, 25);
|
LuaCreateNPCParse(Corrup, int32, 0);
|
||||||
LuaCreateNPCParse(PhR, int32, 0);
|
LuaCreateNPCParse(PhR, int32, 0);
|
||||||
LuaCreateNPCParse(haircolor, uint8, 0);
|
LuaCreateNPCParse(haircolor, uint8, 0);
|
||||||
LuaCreateNPCParse(beardcolor, uint8, 0);
|
LuaCreateNPCParse(beardcolor, uint8, 0);
|
||||||
@ -1689,13 +1697,16 @@ luabind::scope lua_register_general() {
|
|||||||
luabind::def("destroy_instance", &lua_destroy_instance),
|
luabind::def("destroy_instance", &lua_destroy_instance),
|
||||||
luabind::def("update_instance_timer", &lua_update_instance_timer),
|
luabind::def("update_instance_timer", &lua_update_instance_timer),
|
||||||
luabind::def("get_instance_id", &lua_get_instance_id),
|
luabind::def("get_instance_id", &lua_get_instance_id),
|
||||||
|
luabind::def("get_instance_id_by_char_id", &lua_get_instance_id_by_char_id),
|
||||||
luabind::def("get_instance_timer", &lua_get_instance_timer),
|
luabind::def("get_instance_timer", &lua_get_instance_timer),
|
||||||
luabind::def("get_instance_timer_by_id", &lua_get_instance_timer_by_id),
|
luabind::def("get_instance_timer_by_id", &lua_get_instance_timer_by_id),
|
||||||
luabind::def("get_characters_in_instance", &lua_get_characters_in_instance),
|
luabind::def("get_characters_in_instance", &lua_get_characters_in_instance),
|
||||||
luabind::def("assign_to_instance", &lua_assign_to_instance),
|
luabind::def("assign_to_instance", &lua_assign_to_instance),
|
||||||
|
luabind::def("assign_to_instance_by_char_id", &lua_assign_to_instance_by_char_id),
|
||||||
luabind::def("assign_group_to_instance", &lua_assign_group_to_instance),
|
luabind::def("assign_group_to_instance", &lua_assign_group_to_instance),
|
||||||
luabind::def("assign_raid_to_instance", &lua_assign_raid_to_instance),
|
luabind::def("assign_raid_to_instance", &lua_assign_raid_to_instance),
|
||||||
luabind::def("remove_from_instance", &lua_remove_from_instance),
|
luabind::def("remove_from_instance", &lua_remove_from_instance),
|
||||||
|
luabind::def("remove_from_instance_by_char_id", &lua_remove_from_instance_by_char_id),
|
||||||
luabind::def("remove_all_from_instance", &lua_remove_all_from_instance),
|
luabind::def("remove_all_from_instance", &lua_remove_all_from_instance),
|
||||||
luabind::def("flag_instance_by_group_leader", &lua_flag_instance_by_group_leader),
|
luabind::def("flag_instance_by_group_leader", &lua_flag_instance_by_group_leader),
|
||||||
luabind::def("flag_instance_by_raid_leader", &lua_flag_instance_by_raid_leader),
|
luabind::def("flag_instance_by_raid_leader", &lua_flag_instance_by_raid_leader),
|
||||||
|
|||||||
106
zone/mob.cpp
106
zone/mob.cpp
@ -122,6 +122,8 @@ Mob::Mob(const char* in_name,
|
|||||||
targeted = 0;
|
targeted = 0;
|
||||||
currently_fleeing = false;
|
currently_fleeing = false;
|
||||||
|
|
||||||
|
currently_fleeing = false;
|
||||||
|
|
||||||
AI_Init();
|
AI_Init();
|
||||||
SetMoving(false);
|
SetMoving(false);
|
||||||
moved = false;
|
moved = false;
|
||||||
@ -129,14 +131,16 @@ Mob::Mob(const char* in_name,
|
|||||||
|
|
||||||
name[0] = 0;
|
name[0] = 0;
|
||||||
orig_name[0] = 0;
|
orig_name[0] = 0;
|
||||||
|
|
||||||
clean_name[0] = 0;
|
clean_name[0] = 0;
|
||||||
lastname[0] = 0;
|
lastname[0] = 0;
|
||||||
if (in_name) {
|
if (in_name) {
|
||||||
strn0cpy(name, in_name, 64);
|
strn0cpy(name, in_name, 64);
|
||||||
strn0cpy(orig_name, in_name, 64);
|
strn0cpy(orig_name, in_name, 64);
|
||||||
}
|
}
|
||||||
if (in_lastname)
|
if (in_lastname) {
|
||||||
strn0cpy(lastname, in_lastname, 64);
|
strn0cpy(lastname, in_lastname, 64);
|
||||||
|
}
|
||||||
cur_hp = in_cur_hp;
|
cur_hp = in_cur_hp;
|
||||||
max_hp = in_max_hp;
|
max_hp = in_max_hp;
|
||||||
base_hp = in_max_hp;
|
base_hp = in_max_hp;
|
||||||
@ -155,10 +159,11 @@ Mob::Mob(const char* in_name,
|
|||||||
base_size = size;
|
base_size = size;
|
||||||
runspeed = in_runspeed;
|
runspeed = in_runspeed;
|
||||||
// neotokyo: sanity check
|
// neotokyo: sanity check
|
||||||
if (runspeed < 0 || runspeed > 20)
|
if (runspeed < 0 || runspeed > 20) {
|
||||||
runspeed = 1.25f;
|
runspeed = 1.25f;
|
||||||
base_runspeed = (int)((float)runspeed * 40.0f);
|
|
||||||
// clients -- todo movement this doesn't take into account gm speed we need to fix that.
|
// clients -- todo movement this doesn't take into account gm speed we need to fix that.
|
||||||
|
|
||||||
if (runspeed == 0.7f) {
|
if (runspeed == 0.7f) {
|
||||||
base_runspeed = 28;
|
base_runspeed = 28;
|
||||||
walkspeed = 0.3f;
|
walkspeed = 0.3f;
|
||||||
@ -169,9 +174,9 @@ Mob::Mob(const char* in_name,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
base_walkspeed = base_runspeed * 100 / 265;
|
base_walkspeed = base_runspeed * 100 / 265;
|
||||||
walkspeed = ((float)base_walkspeed) * 0.025f;
|
walkspeed = ((float) base_walkspeed) * 0.025f;
|
||||||
base_fearspeed = base_runspeed * 100 / 127;
|
base_fearspeed = base_runspeed * 100 / 127;
|
||||||
fearspeed = ((float)base_fearspeed) * 0.025f;
|
fearspeed = ((float) base_fearspeed) * 0.025f;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_hp_percent = 0;
|
last_hp_percent = 0;
|
||||||
@ -183,8 +188,9 @@ Mob::Mob(const char* in_name,
|
|||||||
|
|
||||||
|
|
||||||
// sanity check
|
// sanity check
|
||||||
if (runspeed < 0 || runspeed > 20)
|
if (runspeed < 0 || runspeed > 20) {
|
||||||
runspeed = 1.25f;
|
runspeed = 1.25f;
|
||||||
|
}
|
||||||
|
|
||||||
m_Light.Type[EQEmu::lightsource::LightInnate] = in_light;
|
m_Light.Type[EQEmu::lightsource::LightInnate] = in_light;
|
||||||
m_Light.Level[EQEmu::lightsource::LightInnate] = EQEmu::lightsource::TypeToLevel(m_Light.Type[EQEmu::lightsource::LightInnate]);
|
m_Light.Level[EQEmu::lightsource::LightInnate] = EQEmu::lightsource::TypeToLevel(m_Light.Type[EQEmu::lightsource::LightInnate]);
|
||||||
@ -225,10 +231,13 @@ Mob::Mob(const char* in_name,
|
|||||||
SpellPowerDistanceMod = 0;
|
SpellPowerDistanceMod = 0;
|
||||||
last_los_check = false;
|
last_los_check = false;
|
||||||
|
|
||||||
if (in_aa_title > 0)
|
if (in_aa_title > 0) {
|
||||||
aa_title = in_aa_title;
|
aa_title = in_aa_title;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
aa_title = 0xFF;
|
aa_title = 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
AC = in_ac;
|
AC = in_ac;
|
||||||
ATK = in_atk;
|
ATK = in_atk;
|
||||||
STR = in_str;
|
STR = in_str;
|
||||||
@ -239,10 +248,8 @@ Mob::Mob(const char* in_name,
|
|||||||
WIS = in_wis;
|
WIS = in_wis;
|
||||||
CHA = in_cha;
|
CHA = in_cha;
|
||||||
MR = CR = FR = DR = PR = Corrup = 0;
|
MR = CR = FR = DR = PR = Corrup = 0;
|
||||||
|
|
||||||
ExtraHaste = 0;
|
ExtraHaste = 0;
|
||||||
bEnraged = false;
|
bEnraged = false;
|
||||||
|
|
||||||
shield_target = nullptr;
|
shield_target = nullptr;
|
||||||
current_mana = 0;
|
current_mana = 0;
|
||||||
max_mana = 0;
|
max_mana = 0;
|
||||||
@ -251,7 +258,7 @@ Mob::Mob(const char* in_name,
|
|||||||
ooc_regen = RuleI(NPC, OOCRegen); //default Out of Combat Regen
|
ooc_regen = RuleI(NPC, OOCRegen); //default Out of Combat Regen
|
||||||
maxlevel = in_maxlevel;
|
maxlevel = in_maxlevel;
|
||||||
scalerate = in_scalerate;
|
scalerate = in_scalerate;
|
||||||
invisible = false;
|
invisible = 0;
|
||||||
invisible_undead = false;
|
invisible_undead = false;
|
||||||
invisible_animals = false;
|
invisible_animals = false;
|
||||||
sneaking = false;
|
sneaking = false;
|
||||||
@ -266,10 +273,7 @@ Mob::Mob(const char* in_name,
|
|||||||
InitializeBuffSlots();
|
InitializeBuffSlots();
|
||||||
|
|
||||||
// clear the proc arrays
|
// clear the proc arrays
|
||||||
int i;
|
for (int j = 0; j < MAX_PROCS; j++) {
|
||||||
int j;
|
|
||||||
for (j = 0; j < MAX_PROCS; j++)
|
|
||||||
{
|
|
||||||
PermaProcs[j].spellID = SPELL_UNKNOWN;
|
PermaProcs[j].spellID = SPELL_UNKNOWN;
|
||||||
PermaProcs[j].chance = 0;
|
PermaProcs[j].chance = 0;
|
||||||
PermaProcs[j].base_spellID = SPELL_UNKNOWN;
|
PermaProcs[j].base_spellID = SPELL_UNKNOWN;
|
||||||
@ -288,8 +292,7 @@ Mob::Mob(const char* in_name,
|
|||||||
RangedProcs[j].level_override = -1;
|
RangedProcs[j].level_override = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = EQEmu::textures::textureBegin; i < EQEmu::textures::materialCount; i++)
|
for (int i = EQEmu::textures::textureBegin; i < EQEmu::textures::materialCount; i++) {
|
||||||
{
|
|
||||||
armor_tint.Slot[i].Color = in_armor_tint.Slot[i].Color;
|
armor_tint.Slot[i].Color = in_armor_tint.Slot[i].Color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,7 +301,6 @@ Mob::Mob(const char* in_name,
|
|||||||
m_Delta = glm::vec4();
|
m_Delta = glm::vec4();
|
||||||
animation = 0;
|
animation = 0;
|
||||||
|
|
||||||
logging_enabled = false;
|
|
||||||
isgrouped = false;
|
isgrouped = false;
|
||||||
israidgrouped = false;
|
israidgrouped = false;
|
||||||
|
|
||||||
@ -320,8 +322,7 @@ Mob::Mob(const char* in_name,
|
|||||||
target = 0;
|
target = 0;
|
||||||
|
|
||||||
ActiveProjectileATK = false;
|
ActiveProjectileATK = false;
|
||||||
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++)
|
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) {
|
||||||
{
|
|
||||||
ProjectileAtk[i].increment = 0;
|
ProjectileAtk[i].increment = 0;
|
||||||
ProjectileAtk[i].hit_increment = 0;
|
ProjectileAtk[i].hit_increment = 0;
|
||||||
ProjectileAtk[i].target_id = 0;
|
ProjectileAtk[i].target_id = 0;
|
||||||
@ -364,8 +365,7 @@ Mob::Mob(const char* in_name,
|
|||||||
amnesiad = false;
|
amnesiad = false;
|
||||||
inWater = false;
|
inWater = false;
|
||||||
int m;
|
int m;
|
||||||
for (m = 0; m < MAX_SHIELDERS; m++)
|
for (m = 0; m < MAX_SHIELDERS; m++) {
|
||||||
{
|
|
||||||
shielder[m].shielder_id = 0;
|
shielder[m].shielder_id = 0;
|
||||||
shielder[m].shielder_bonus = 0;
|
shielder[m].shielder_bonus = 0;
|
||||||
}
|
}
|
||||||
@ -396,6 +396,7 @@ Mob::Mob(const char* in_name,
|
|||||||
for (i = 0; i < MAX_SPELL_TRIGGER * 2; i++) {
|
for (i = 0; i < MAX_SPELL_TRIGGER * 2; i++) {
|
||||||
viral_spells[i] = 0;
|
viral_spells[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pStandingPetOrder = SPO_Follow;
|
pStandingPetOrder = SPO_Follow;
|
||||||
pseudo_rooted = false;
|
pseudo_rooted = false;
|
||||||
|
|
||||||
@ -428,13 +429,20 @@ Mob::Mob(const char* in_name,
|
|||||||
m_TargetRing = glm::vec3();
|
m_TargetRing = glm::vec3();
|
||||||
|
|
||||||
flymode = GravityBehavior::Water;
|
flymode = GravityBehavior::Water;
|
||||||
|
|
||||||
DistractedFromGrid = false;
|
DistractedFromGrid = false;
|
||||||
hate_list.SetHateOwner(this);
|
hate_list.SetHateOwner(this);
|
||||||
|
|
||||||
m_AllowBeneficial = false;
|
m_AllowBeneficial = false;
|
||||||
m_DisableMelee = false;
|
m_DisableMelee = false;
|
||||||
for (int i = 0; i < EQEmu::skills::HIGHEST_SKILL + 2; i++) { SkillDmgTaken_Mod[i] = 0; }
|
|
||||||
for (int i = 0; i < HIGHEST_RESIST + 2; i++) { Vulnerability_Mod[i] = 0; }
|
for (int i = 0; i < EQEmu::skills::HIGHEST_SKILL + 2; i++) {
|
||||||
|
SkillDmgTaken_Mod[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < HIGHEST_RESIST + 2; i++) {
|
||||||
|
Vulnerability_Mod[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
emoteid = 0;
|
emoteid = 0;
|
||||||
endur_upkeep = false;
|
endur_upkeep = false;
|
||||||
@ -823,6 +831,7 @@ int32 Mob::CalcMaxMana() {
|
|||||||
int32 Mob::CalcMaxHP() {
|
int32 Mob::CalcMaxHP() {
|
||||||
max_hp = (base_hp + itembonuses.HP + spellbonuses.HP);
|
max_hp = (base_hp + itembonuses.HP + spellbonuses.HP);
|
||||||
max_hp += max_hp * ((aabonuses.MaxHPChange + spellbonuses.MaxHPChange + itembonuses.MaxHPChange) / 10000.0f);
|
max_hp += max_hp * ((aabonuses.MaxHPChange + spellbonuses.MaxHPChange + itembonuses.MaxHPChange) / 10000.0f);
|
||||||
|
|
||||||
return max_hp;
|
return max_hp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3183,8 +3192,7 @@ void Mob::QuestJournalledSay(Client *QuestInitiator, const char *str)
|
|||||||
|
|
||||||
const char *Mob::GetCleanName()
|
const char *Mob::GetCleanName()
|
||||||
{
|
{
|
||||||
if(!strlen(clean_name))
|
if (!strlen(clean_name)) {
|
||||||
{
|
|
||||||
CleanMobName(GetName(), clean_name);
|
CleanMobName(GetName(), clean_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3396,24 +3404,33 @@ int Mob::GetHaste()
|
|||||||
return 100 + h;
|
return 100 + h;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::SetTarget(Mob* mob) {
|
void Mob::SetTarget(Mob *mob)
|
||||||
|
{
|
||||||
if (target == mob)
|
if (target == mob) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
target = mob;
|
target = mob;
|
||||||
entity_list.UpdateHoTT(this);
|
entity_list.UpdateHoTT(this);
|
||||||
|
|
||||||
if(IsNPC())
|
if (IsNPC()) {
|
||||||
parse->EventNPC(EVENT_TARGET_CHANGE, CastToNPC(), mob, "", 0);
|
parse->EventNPC(EVENT_TARGET_CHANGE, CastToNPC(), mob, "", 0);
|
||||||
else if (IsClient())
|
}
|
||||||
|
else if (IsClient()) {
|
||||||
parse->EventPlayer(EVENT_TARGET_CHANGE, CastToClient(), "", 0);
|
parse->EventPlayer(EVENT_TARGET_CHANGE, CastToClient(), "", 0);
|
||||||
|
|
||||||
if(IsPet() && GetOwner() && GetOwner()->IsClient())
|
if (this->CastToClient()->admin > 200) {
|
||||||
GetOwner()->CastToClient()->UpdateXTargetType(MyPetTarget, mob);
|
this->DisplayInfo(mob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this->IsClient() && this->GetTarget() && this->CastToClient()->hp_other_update_throttle_timer.Check())
|
if (IsPet() && GetOwner() && GetOwner()->IsClient()) {
|
||||||
|
GetOwner()->CastToClient()->UpdateXTargetType(MyPetTarget, mob);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->IsClient() && this->GetTarget() && this->CastToClient()->hp_other_update_throttle_timer.Check()) {
|
||||||
this->GetTarget()->SendHPUpdate(false, true);
|
this->GetTarget()->SendHPUpdate(false, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For when we want a Ground Z at a location we are not at yet
|
// For when we want a Ground Z at a location we are not at yet
|
||||||
@ -3563,11 +3580,10 @@ void Mob::SetEntityVariable(const char *id, const char *m_var)
|
|||||||
m_EntityVariables[id] = n_m_var;
|
m_EntityVariables[id] = n_m_var;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* Mob::GetEntityVariable(const char *id)
|
const char *Mob::GetEntityVariable(const char *id)
|
||||||
{
|
{
|
||||||
auto iter = m_EntityVariables.find(id);
|
auto iter = m_EntityVariables.find(id);
|
||||||
if(iter != m_EntityVariables.end())
|
if (iter != m_EntityVariables.end()) {
|
||||||
{
|
|
||||||
return iter->second.c_str();
|
return iter->second.c_str();
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -5483,14 +5499,26 @@ bool Mob::HasSpellEffect(int effectid)
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Mob::GetSpecialAbility(int ability) {
|
int Mob::GetSpecialAbility(int ability)
|
||||||
if(ability >= MAX_SPECIAL_ATTACK || ability < 0) {
|
{
|
||||||
|
if (ability >= MAX_SPECIAL_ATTACK || ability < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SpecialAbilities[ability].level;
|
return SpecialAbilities[ability].level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Mob::HasSpecialAbilities()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MAX_SPECIAL_ATTACK; ++i) {
|
||||||
|
if (GetSpecialAbility(i)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int Mob::GetSpecialAbilityParam(int ability, int param) {
|
int Mob::GetSpecialAbilityParam(int ability, int param) {
|
||||||
if(param >= MAX_SPECIAL_ATTACK_PARAMS || param < 0 || ability >= MAX_SPECIAL_ATTACK || ability < 0) {
|
if(param >= MAX_SPECIAL_ATTACK_PARAMS || param < 0 || ability >= MAX_SPECIAL_ATTACK || ability < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
21
zone/mob.h
21
zone/mob.h
@ -165,6 +165,8 @@ public:
|
|||||||
inline virtual bool IsMob() const { return true; }
|
inline virtual bool IsMob() const { return true; }
|
||||||
inline virtual bool InZone() const { return true; }
|
inline virtual bool InZone() const { return true; }
|
||||||
|
|
||||||
|
void DisplayInfo(Mob *mob);
|
||||||
|
|
||||||
//Somewhat sorted: needs documenting!
|
//Somewhat sorted: needs documenting!
|
||||||
|
|
||||||
//Attack
|
//Attack
|
||||||
@ -481,6 +483,11 @@ public:
|
|||||||
inline virtual int32 GetINT() const { return INT + itembonuses.INT + spellbonuses.INT; }
|
inline virtual int32 GetINT() const { return INT + itembonuses.INT + spellbonuses.INT; }
|
||||||
inline virtual int32 GetWIS() const { return WIS + itembonuses.WIS + spellbonuses.WIS; }
|
inline virtual int32 GetWIS() const { return WIS + itembonuses.WIS + spellbonuses.WIS; }
|
||||||
inline virtual int32 GetCHA() const { return CHA + itembonuses.CHA + spellbonuses.CHA; }
|
inline virtual int32 GetCHA() const { return CHA + itembonuses.CHA + spellbonuses.CHA; }
|
||||||
|
inline virtual int32 GetHeroicMR() const { return 0; }
|
||||||
|
inline virtual int32 GetHeroicFR() const { return 0; }
|
||||||
|
inline virtual int32 GetHeroicDR() const { return 0; }
|
||||||
|
inline virtual int32 GetHeroicPR() const { return 0; }
|
||||||
|
inline virtual int32 GetHeroicCR() const { return 0; }
|
||||||
inline virtual int32 GetMR() const { return MR + itembonuses.MR + spellbonuses.MR; }
|
inline virtual int32 GetMR() const { return MR + itembonuses.MR + spellbonuses.MR; }
|
||||||
inline virtual int32 GetFR() const { return FR + itembonuses.FR + spellbonuses.FR; }
|
inline virtual int32 GetFR() const { return FR + itembonuses.FR + spellbonuses.FR; }
|
||||||
inline virtual int32 GetDR() const { return DR + itembonuses.DR + spellbonuses.DR; }
|
inline virtual int32 GetDR() const { return DR + itembonuses.DR + spellbonuses.DR; }
|
||||||
@ -494,6 +501,13 @@ public:
|
|||||||
inline StatBonuses* GetItemBonusesPtr() { return &itembonuses; }
|
inline StatBonuses* GetItemBonusesPtr() { return &itembonuses; }
|
||||||
inline StatBonuses* GetSpellBonusesPtr() { return &spellbonuses; }
|
inline StatBonuses* GetSpellBonusesPtr() { return &spellbonuses; }
|
||||||
inline StatBonuses* GetAABonusesPtr() { return &aabonuses; }
|
inline StatBonuses* GetAABonusesPtr() { return &aabonuses; }
|
||||||
|
inline virtual int32 GetHeroicSTR() const { return 0; }
|
||||||
|
inline virtual int32 GetHeroicSTA() const { return 0; }
|
||||||
|
inline virtual int32 GetHeroicDEX() const { return 0; }
|
||||||
|
inline virtual int32 GetHeroicAGI() const { return 0; }
|
||||||
|
inline virtual int32 GetHeroicINT() const { return 0; }
|
||||||
|
inline virtual int32 GetHeroicWIS() const { return 0; }
|
||||||
|
inline virtual int32 GetHeroicCHA() const { return 0; }
|
||||||
inline virtual int32 GetMaxSTR() const { return GetSTR(); }
|
inline virtual int32 GetMaxSTR() const { return GetSTR(); }
|
||||||
inline virtual int32 GetMaxSTA() const { return GetSTA(); }
|
inline virtual int32 GetMaxSTA() const { return GetSTA(); }
|
||||||
inline virtual int32 GetMaxDEX() const { return GetDEX(); }
|
inline virtual int32 GetMaxDEX() const { return GetDEX(); }
|
||||||
@ -513,6 +527,7 @@ public:
|
|||||||
inline int32 GetMaxMana() const { return max_mana; }
|
inline int32 GetMaxMana() const { return max_mana; }
|
||||||
inline int32 GetMana() const { return current_mana; }
|
inline int32 GetMana() const { return current_mana; }
|
||||||
virtual int32 GetEndurance() const { return 0; }
|
virtual int32 GetEndurance() const { return 0; }
|
||||||
|
virtual int32 GetMaxEndurance() const { return 0; }
|
||||||
virtual void SetEndurance(int32 newEnd) { return; }
|
virtual void SetEndurance(int32 newEnd) { return; }
|
||||||
int32 GetItemHPBonuses();
|
int32 GetItemHPBonuses();
|
||||||
int32 GetSpellHPBonuses();
|
int32 GetSpellHPBonuses();
|
||||||
@ -1042,6 +1057,7 @@ public:
|
|||||||
inline bool Sanctuary() const { return spellbonuses.Sanctuary; }
|
inline bool Sanctuary() const { return spellbonuses.Sanctuary; }
|
||||||
|
|
||||||
bool HasNPCSpecialAtk(const char* parse);
|
bool HasNPCSpecialAtk(const char* parse);
|
||||||
|
bool HasSpecialAbilities();
|
||||||
int GetSpecialAbility(int ability);
|
int GetSpecialAbility(int ability);
|
||||||
int GetSpecialAbilityParam(int ability, int param);
|
int GetSpecialAbilityParam(int ability, int param);
|
||||||
void SetSpecialAbility(int ability, int level);
|
void SetSpecialAbility(int ability, int level);
|
||||||
@ -1140,6 +1156,10 @@ public:
|
|||||||
int GetWeaponDamage(Mob *against, const EQEmu::ItemData *weapon_item);
|
int GetWeaponDamage(Mob *against, const EQEmu::ItemData *weapon_item);
|
||||||
int GetWeaponDamage(Mob *against, const EQEmu::ItemInstance *weapon_item, uint32 *hate = nullptr);
|
int GetWeaponDamage(Mob *against, const EQEmu::ItemInstance *weapon_item, uint32 *hate = nullptr);
|
||||||
|
|
||||||
|
int32 GetHPRegen() const;
|
||||||
|
int32 GetManaRegen() const;
|
||||||
|
|
||||||
|
|
||||||
// Bots HealRotation methods
|
// Bots HealRotation methods
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
bool IsHealRotationTarget() { return (m_target_of_heal_rotation.use_count() && m_target_of_heal_rotation.get()); }
|
bool IsHealRotationTarget() { return (m_target_of_heal_rotation.use_count() && m_target_of_heal_rotation.get()); }
|
||||||
@ -1461,7 +1481,6 @@ protected:
|
|||||||
|
|
||||||
bool pAIControlled;
|
bool pAIControlled;
|
||||||
bool roamer;
|
bool roamer;
|
||||||
bool logging_enabled;
|
|
||||||
|
|
||||||
int wandertype;
|
int wandertype;
|
||||||
int pausetype;
|
int pausetype;
|
||||||
|
|||||||
831
zone/mob_info.cpp
Normal file
831
zone/mob_info.cpp
Normal file
@ -0,0 +1,831 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2018 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "client.h"
|
||||||
|
#include "mob.h"
|
||||||
|
#include "../common/races.h"
|
||||||
|
#include "../common/say_link.h"
|
||||||
|
#include "npc_scale_manager.h"
|
||||||
|
|
||||||
|
std::string commify(const std::string &number)
|
||||||
|
{
|
||||||
|
std::string temp_string;
|
||||||
|
|
||||||
|
auto string_length = static_cast<int>(number.length());
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (i = string_length - 3; i >= 0; i -= 3) {
|
||||||
|
if (i > 0) {
|
||||||
|
temp_string = "," + number.substr(static_cast<unsigned long>(i), 3) + temp_string;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
temp_string = number.substr(static_cast<unsigned long>(i), 3) + temp_string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < 0) {
|
||||||
|
temp_string = number.substr(0, static_cast<unsigned long>(3 + i)) + temp_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
return temp_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string GetMobAttributeByString(Mob *mob, const std::string &attribute)
|
||||||
|
{
|
||||||
|
std::string entity_variable = "modify_stat_" + attribute;
|
||||||
|
std::string scaling_modified;
|
||||||
|
if (mob->GetEntityVariable(entity_variable.c_str())) {
|
||||||
|
scaling_modified = " *";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "ac") {
|
||||||
|
if (mob->GetEntityVariable(std::string("modify_stat_max_hp").c_str())) {
|
||||||
|
scaling_modified = " *";
|
||||||
|
}
|
||||||
|
|
||||||
|
return commify(std::to_string(mob->GetAC())) + scaling_modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "atk") {
|
||||||
|
return std::to_string(mob->GetATK()) + scaling_modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "end") {
|
||||||
|
int endurance = 0;
|
||||||
|
if (mob->IsClient()) {
|
||||||
|
endurance = mob->CastToClient()->GetEndurance();
|
||||||
|
}
|
||||||
|
|
||||||
|
return commify(std::to_string(endurance));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "hp") {
|
||||||
|
return commify(std::to_string(mob->GetHP()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "hp_min_max") {
|
||||||
|
if (mob->GetEntityVariable(std::string("modify_stat_max_hp").c_str())) {
|
||||||
|
scaling_modified = " *";
|
||||||
|
}
|
||||||
|
|
||||||
|
return commify(std::to_string(mob->GetHP())) + scaling_modified + " / " +
|
||||||
|
commify(std::to_string(mob->GetMaxHP())) + " (" +
|
||||||
|
std::to_string((int) mob->GetHPRatio()) + "%)";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "mana") {
|
||||||
|
return commify(std::to_string(mob->GetMana()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "mp_min_max") {
|
||||||
|
return commify(std::to_string(mob->GetMana())) + " / " + commify(std::to_string(mob->GetMaxMana())) + " (" +
|
||||||
|
std::to_string((int) mob->GetManaPercent()) + "%)";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "end_min_max") {
|
||||||
|
return commify(std::to_string(mob->GetEndurance())) + " / " + commify(std::to_string(mob->GetMaxEndurance())) + " (" +
|
||||||
|
std::to_string((int)mob->GetEndurancePercent()) + "%)";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "str") {
|
||||||
|
return commify(std::to_string(mob->GetSTR())) + scaling_modified + " / " +
|
||||||
|
commify(std::to_string(mob->GetMaxSTR())) + " +" +
|
||||||
|
commify(std::to_string(mob->GetHeroicSTR()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "sta") {
|
||||||
|
return commify(std::to_string(mob->GetSTA())) + scaling_modified + " / " +
|
||||||
|
commify(std::to_string(mob->GetMaxSTA())) + " +" +
|
||||||
|
commify(std::to_string(mob->GetHeroicSTA()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "dex") {
|
||||||
|
return commify(std::to_string(mob->GetDEX())) + scaling_modified + " / " +
|
||||||
|
commify(std::to_string(mob->GetMaxDEX())) + " +" +
|
||||||
|
commify(std::to_string(mob->GetHeroicDEX()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "agi") {
|
||||||
|
return commify(std::to_string(mob->GetAGI())) + scaling_modified + " / " +
|
||||||
|
commify(std::to_string(mob->GetMaxAGI())) + " +" +
|
||||||
|
commify(std::to_string(mob->GetHeroicAGI()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "int") {
|
||||||
|
return commify(std::to_string(mob->GetINT())) + scaling_modified + " / " +
|
||||||
|
commify(std::to_string(mob->GetMaxINT())) + " +" +
|
||||||
|
commify(std::to_string(mob->GetHeroicINT()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "wis") {
|
||||||
|
return commify(std::to_string(mob->GetWIS())) + scaling_modified + " / " +
|
||||||
|
commify(std::to_string(mob->GetMaxWIS())) + " +" +
|
||||||
|
commify(std::to_string(mob->GetHeroicWIS()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "cha") {
|
||||||
|
return commify(std::to_string(mob->GetCHA())) + scaling_modified + " / " +
|
||||||
|
commify(std::to_string(mob->GetMaxCHA())) + " +" +
|
||||||
|
commify(std::to_string(mob->GetHeroicCHA()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "mr") {
|
||||||
|
return commify(std::to_string(mob->GetMR())) + scaling_modified + " / " +
|
||||||
|
commify(std::to_string(mob->GetMaxMR())) + " +" +
|
||||||
|
commify(std::to_string(mob->GetHeroicMR()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "cr") {
|
||||||
|
return commify(std::to_string(mob->GetCR())) + scaling_modified + " / " +
|
||||||
|
commify(std::to_string(mob->GetMaxCR())) + " +" +
|
||||||
|
commify(std::to_string(mob->GetHeroicCR()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "fr") {
|
||||||
|
return commify(std::to_string(mob->GetFR())) + scaling_modified + " / " +
|
||||||
|
commify(std::to_string(mob->GetMaxFR())) + " +" +
|
||||||
|
commify(std::to_string(mob->GetHeroicFR()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "pr") {
|
||||||
|
return commify(std::to_string(mob->GetPR())) + scaling_modified + " / " +
|
||||||
|
commify(std::to_string(mob->GetMaxPR())) + " +" +
|
||||||
|
commify(std::to_string(mob->GetHeroicPR()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "dr") {
|
||||||
|
return commify(std::to_string(mob->GetDR())) + scaling_modified + " / " +
|
||||||
|
commify(std::to_string(mob->GetMaxDR())) + " +" +
|
||||||
|
commify(std::to_string(mob->GetHeroicDR()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "cr") {
|
||||||
|
return commify(std::to_string(mob->GetCR())) + scaling_modified + " / " +
|
||||||
|
commify(std::to_string(mob->GetMaxCR())) + " +" +
|
||||||
|
commify(std::to_string(mob->GetHeroicCR()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "pr") {
|
||||||
|
return commify(std::to_string(mob->GetPR())) + scaling_modified + " / " +
|
||||||
|
commify(std::to_string(mob->GetMaxPR())) + " +" +
|
||||||
|
commify(std::to_string(mob->GetHeroicPR()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "cor") {
|
||||||
|
return std::to_string(mob->GetCorrup());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "phy") {
|
||||||
|
return std::to_string(mob->GetPhR());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "name") {
|
||||||
|
return mob->GetCleanName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "surname") {
|
||||||
|
std::string last_name = mob->GetLastName();
|
||||||
|
return (last_name.length() > 0 ? mob->GetLastName() : " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "race") {
|
||||||
|
return GetRaceIDName(mob->GetRace());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "class") {
|
||||||
|
return GetClassIDName(mob->GetClass(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "level") {
|
||||||
|
return std::to_string(mob->GetLevel());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "flymode") {
|
||||||
|
return std::to_string(mob->GetFlyMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "maxbuffslots") {
|
||||||
|
return std::to_string(mob->GetMaxBuffSlots());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "curbuffslots") {
|
||||||
|
return std::to_string(mob->GetCurrentBuffSlots());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "tohit") {
|
||||||
|
return std::to_string(mob->compute_tohit(EQEmu::skills::SkillHandtoHand));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "total_to_hit") {
|
||||||
|
return std::to_string(mob->GetTotalToHit(EQEmu::skills::SkillHandtoHand, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "defense") {
|
||||||
|
return std::to_string(mob->compute_defense());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "total_defense") {
|
||||||
|
return std::to_string(mob->GetTotalDefense());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "offense") {
|
||||||
|
return std::to_string(mob->offense(EQEmu::skills::SkillHandtoHand));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "mitigation_ac") {
|
||||||
|
return std::to_string(mob->GetMitigationAC());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mob->IsNPC()) {
|
||||||
|
NPC *npc = mob->CastToNPC();
|
||||||
|
|
||||||
|
if (attribute == "npcid") {
|
||||||
|
return std::to_string(npc->GetNPCTypeID());
|
||||||
|
}
|
||||||
|
if (attribute == "texture") {
|
||||||
|
return std::to_string(npc->GetTexture());
|
||||||
|
}
|
||||||
|
if (attribute == "bodytype") {
|
||||||
|
return std::to_string(npc->GetBodyType());
|
||||||
|
}
|
||||||
|
if (attribute == "gender") {
|
||||||
|
return std::to_string(npc->GetGender());
|
||||||
|
}
|
||||||
|
if (attribute == "size") {
|
||||||
|
return std::to_string((int)npc->GetSize());
|
||||||
|
}
|
||||||
|
if (attribute == "runspeed") {
|
||||||
|
return std::to_string((int)npc->GetRunspeed());
|
||||||
|
}
|
||||||
|
if (attribute == "walkspeed") {
|
||||||
|
return std::to_string((int)npc->GetWalkspeed());
|
||||||
|
}
|
||||||
|
if (attribute == "spawngroup") {
|
||||||
|
return std::to_string(npc->GetSp2());
|
||||||
|
}
|
||||||
|
if (attribute == "grid") {
|
||||||
|
return std::to_string(npc->GetGrid());
|
||||||
|
}
|
||||||
|
if (attribute == "emote") {
|
||||||
|
return std::to_string(npc->GetEmoteID());
|
||||||
|
}
|
||||||
|
if (attribute == "see_invis") {
|
||||||
|
return std::to_string(npc->SeeInvisible());
|
||||||
|
}
|
||||||
|
if (attribute == "see_invis_undead") {
|
||||||
|
return std::to_string(npc->SeeInvisibleUndead());
|
||||||
|
}
|
||||||
|
if (attribute == "faction") {
|
||||||
|
return std::to_string(npc->GetNPCFactionID());
|
||||||
|
}
|
||||||
|
if (attribute == "loottable") {
|
||||||
|
return std::to_string(npc->GetLoottableID());
|
||||||
|
}
|
||||||
|
if (attribute == "prim_skill") {
|
||||||
|
return std::to_string(npc->GetPrimSkill());
|
||||||
|
}
|
||||||
|
if (attribute == "sec_skill") {
|
||||||
|
return std::to_string(npc->GetSecSkill());
|
||||||
|
}
|
||||||
|
if (attribute == "melee_texture_1") {
|
||||||
|
return std::to_string(npc->GetMeleeTexture1());
|
||||||
|
}
|
||||||
|
if (attribute == "melee_texture_2") {
|
||||||
|
return std::to_string(npc->GetMeleeTexture2());
|
||||||
|
}
|
||||||
|
if (attribute == "aggrorange") {
|
||||||
|
return std::to_string((int)npc->GetAggroRange());
|
||||||
|
}
|
||||||
|
if (attribute == "assistrange") {
|
||||||
|
return std::to_string((int)npc->GetAssistRange());
|
||||||
|
}
|
||||||
|
if (attribute == "findable") {
|
||||||
|
return std::to_string(npc->IsFindable());
|
||||||
|
}
|
||||||
|
if (attribute == "trackable") {
|
||||||
|
return std::to_string(npc->IsTrackable());
|
||||||
|
}
|
||||||
|
if (attribute == "spells_id") {
|
||||||
|
return std::to_string(npc->GetNPCSpellsID());
|
||||||
|
}
|
||||||
|
if (attribute == "roambox_min_x") {
|
||||||
|
return std::to_string((int)npc->GetRoamboxMinX());
|
||||||
|
}
|
||||||
|
if (attribute == "roambox_max_x") {
|
||||||
|
return std::to_string((int)npc->GetRoamboxMaxX());
|
||||||
|
}
|
||||||
|
if (attribute == "roambox_min_y") {
|
||||||
|
return std::to_string((int)npc->GetRoamboxMinY());
|
||||||
|
}
|
||||||
|
if (attribute == "roambox_max_y") {
|
||||||
|
return std::to_string((int)npc->GetRoamboxMaxY());
|
||||||
|
}
|
||||||
|
if (attribute == "roambox_min_delay") {
|
||||||
|
return std::to_string((int)npc->GetRoamboxMinDelay());
|
||||||
|
}
|
||||||
|
if (attribute == "roambox_delay") {
|
||||||
|
return std::to_string((int)npc->GetRoamboxDelay());
|
||||||
|
}
|
||||||
|
if (attribute == "roambox_distance") {
|
||||||
|
return std::to_string((int)npc->GetRoamboxDistance());
|
||||||
|
}
|
||||||
|
if (attribute == "proximity_min_x") {
|
||||||
|
return std::to_string((int)npc->GetProximityMinX());
|
||||||
|
}
|
||||||
|
if (attribute == "proximity_max_x") {
|
||||||
|
return std::to_string((int)npc->GetProximityMaxX());
|
||||||
|
}
|
||||||
|
if (attribute == "proximity_min_y") {
|
||||||
|
return std::to_string((int)npc->GetProximityMinY());
|
||||||
|
}
|
||||||
|
if (attribute == "proximity_max_y") {
|
||||||
|
return std::to_string((int)npc->GetProximityMaxY());
|
||||||
|
}
|
||||||
|
if (attribute == "proximity_min_z") {
|
||||||
|
return std::to_string((int)npc->GetProximityMinZ());
|
||||||
|
}
|
||||||
|
if (attribute == "proximity_max_z") {
|
||||||
|
return std::to_string((int)npc->GetProximityMaxZ());
|
||||||
|
}
|
||||||
|
if (attribute == "accuracy") {
|
||||||
|
return std::to_string((int)npc->GetAccuracyRating()) + scaling_modified;
|
||||||
|
}
|
||||||
|
if (attribute == "slow_mitigation") {
|
||||||
|
if (mob->GetEntityVariable(std::string("modify_stat_slow_mitigation").c_str())) {
|
||||||
|
scaling_modified = " *";
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::to_string((int)npc->GetSlowMitigation()) + scaling_modified;
|
||||||
|
}
|
||||||
|
if (attribute == "min_hit") {
|
||||||
|
if (mob->GetEntityVariable(std::string("modify_stat_min_hit").c_str())) {
|
||||||
|
scaling_modified = " *";
|
||||||
|
}
|
||||||
|
|
||||||
|
return commify(std::to_string((int)npc->GetMinDMG())) + scaling_modified;
|
||||||
|
}
|
||||||
|
if (attribute == "max_hit") {
|
||||||
|
if (mob->GetEntityVariable(std::string("modify_stat_max_hit").c_str())) {
|
||||||
|
scaling_modified = " *";
|
||||||
|
}
|
||||||
|
|
||||||
|
return commify(std::to_string((int)npc->GetMaxDMG())) + scaling_modified;
|
||||||
|
}
|
||||||
|
if (attribute == "hp_regen") {
|
||||||
|
if (mob->GetEntityVariable(std::string("modify_stat_hp_regen").c_str())) {
|
||||||
|
scaling_modified = " *";
|
||||||
|
}
|
||||||
|
|
||||||
|
return commify(std::to_string((int)npc->GetHPRegen())) + scaling_modified;
|
||||||
|
}
|
||||||
|
if (attribute == "attack_delay") {
|
||||||
|
if (mob->GetEntityVariable(std::string("modify_stat_attack_delay").c_str())) {
|
||||||
|
scaling_modified = " *";
|
||||||
|
}
|
||||||
|
|
||||||
|
return commify(std::to_string(npc->GetAttackDelay())) + scaling_modified;
|
||||||
|
}
|
||||||
|
if (attribute == "spell_scale") {
|
||||||
|
if (mob->GetEntityVariable(std::string("modify_stat_spell_scale").c_str())) {
|
||||||
|
scaling_modified = " *";
|
||||||
|
}
|
||||||
|
|
||||||
|
return commify(std::to_string((int)npc->GetSpellScale())) + scaling_modified;
|
||||||
|
}
|
||||||
|
if (attribute == "heal_scale") {
|
||||||
|
if (mob->GetEntityVariable(std::string("modify_stat_heal_scale").c_str())) {
|
||||||
|
scaling_modified = " *";
|
||||||
|
}
|
||||||
|
|
||||||
|
return commify(std::to_string((int)npc->GetHealScale())) + scaling_modified;
|
||||||
|
}
|
||||||
|
if (attribute == "avoidance") {
|
||||||
|
return commify(std::to_string((int)npc->GetAvoidanceRating())) + scaling_modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
npc->GetNPCEmote(npc->GetEmoteID(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mob->IsClient()) {
|
||||||
|
Client *client = mob->CastToClient();
|
||||||
|
|
||||||
|
if (attribute == "shielding") {
|
||||||
|
return commify(std::to_string((int)client->GetShielding())) + " / " +
|
||||||
|
commify(std::to_string((int) RuleI(Character, ItemShieldingCap)));
|
||||||
|
}
|
||||||
|
if (attribute == "spell_shielding") {
|
||||||
|
return commify(std::to_string((int)client->GetSpellShield())) + " / " +
|
||||||
|
commify(std::to_string((int) RuleI(Character, ItemSpellShieldingCap)));
|
||||||
|
}
|
||||||
|
if (attribute == "dot_shielding") {
|
||||||
|
return commify(std::to_string((int)client->GetDoTShield())) + " / " +
|
||||||
|
commify(std::to_string((int) RuleI(Character, ItemDoTShieldingCap)));
|
||||||
|
}
|
||||||
|
if (attribute == "stun_resist") {
|
||||||
|
return commify(std::to_string((int)client->GetStunResist())) + " / " +
|
||||||
|
commify(std::to_string((int) RuleI(Character, ItemStunResistCap)));
|
||||||
|
}
|
||||||
|
if (attribute == "damage_shield") {
|
||||||
|
return commify(std::to_string((int)client->GetDS())) + " / " +
|
||||||
|
commify(std::to_string((int) RuleI(Character, ItemDamageShieldCap)));
|
||||||
|
}
|
||||||
|
if (attribute == "avoidance") {
|
||||||
|
return commify(std::to_string((int) client->GetAvoidance())) + " / " +
|
||||||
|
commify(std::to_string((int) RuleI(Character, ItemAvoidanceCap)));
|
||||||
|
}
|
||||||
|
if (attribute == "strikethrough") {
|
||||||
|
return commify(std::to_string((int) client->GetStrikeThrough())) + " / " +
|
||||||
|
commify(std::to_string((int) RuleI(Character, ItemStrikethroughCap)));
|
||||||
|
}
|
||||||
|
if (attribute == "accuracy") {
|
||||||
|
return commify(std::to_string((int) client->GetAccuracy())) + " / " +
|
||||||
|
commify(std::to_string((int) RuleI(Character, ItemAccuracyCap)));
|
||||||
|
}
|
||||||
|
if (attribute == "combat_effects") {
|
||||||
|
return commify(std::to_string((int) client->GetCombatEffects())) + " / " +
|
||||||
|
commify(std::to_string((int) RuleI(Character, ItemCombatEffectsCap)));
|
||||||
|
}
|
||||||
|
if (attribute == "heal_amount") {
|
||||||
|
return commify(std::to_string((int) client->GetHealAmt())) + " / " +
|
||||||
|
commify(std::to_string((int) RuleI(Character, ItemHealAmtCap)));
|
||||||
|
}
|
||||||
|
if (attribute == "spell_dmg") {
|
||||||
|
return commify(std::to_string((int) client->GetSpellDmg())) + " / " +
|
||||||
|
commify(std::to_string((int) RuleI(Character, ItemSpellDmgCap)));
|
||||||
|
}
|
||||||
|
if (attribute == "clairvoyance") {
|
||||||
|
return commify(std::to_string((int) client->GetClair())) + " / " +
|
||||||
|
commify(std::to_string((int) RuleI(Character, ItemClairvoyanceCap)));
|
||||||
|
}
|
||||||
|
if (attribute == "ds_mitigation") {
|
||||||
|
return commify(std::to_string((int) client->GetDSMit())) + " / " +
|
||||||
|
commify(std::to_string((int) RuleI(Character, ItemDSMitigationCap)));
|
||||||
|
}
|
||||||
|
if (attribute == "hp_regen") {
|
||||||
|
return commify(std::to_string((int) client->GetHPRegen())) + " / " +
|
||||||
|
commify(std::to_string((int) RuleI(Character, ItemHealthRegenCap)));
|
||||||
|
}
|
||||||
|
if (attribute == "mana_regen") {
|
||||||
|
return commify(std::to_string((int) client->GetManaRegen())) + " / " +
|
||||||
|
commify(std::to_string((int) RuleI(Character, ItemManaRegenCap)));
|
||||||
|
}
|
||||||
|
if (attribute == "end_regen") {
|
||||||
|
return commify(std::to_string((int) client->CalcEnduranceRegen())) + " / " +
|
||||||
|
commify(std::to_string((int) client->CalcEnduranceRegenCap()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == "type") {
|
||||||
|
std::string entity_type = "Mob";
|
||||||
|
|
||||||
|
if (mob->IsCorpse()) {
|
||||||
|
entity_type = "Corpse";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mob->IsNPC()) {
|
||||||
|
entity_type = "NPC";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mob->IsClient()) {
|
||||||
|
entity_type = "Client";
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string WriteDisplayInfoSection(
|
||||||
|
Mob *mob,
|
||||||
|
const std::string §ion_name,
|
||||||
|
std::vector<std::string> attributes_list,
|
||||||
|
int column_count = 3,
|
||||||
|
bool display_section_name = false
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::string text;
|
||||||
|
|
||||||
|
if (display_section_name) {
|
||||||
|
text += "<c \"#FFFF66\">" + section_name + "</c><br>";
|
||||||
|
}
|
||||||
|
|
||||||
|
text += "<table><tbody>";
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
bool first_row = true;
|
||||||
|
|
||||||
|
for (const auto &attribute : attributes_list) {
|
||||||
|
if (index == 0) {
|
||||||
|
if (first_row) {
|
||||||
|
text += "<tr>\n";
|
||||||
|
first_row = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
text += "</tr><tr>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string attribute_name = attribute;
|
||||||
|
|
||||||
|
find_replace(attribute_name, "_min_max", std::string(""));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate attribute names with underscores
|
||||||
|
* "total_to_hit" = "Total To Hit"
|
||||||
|
*/
|
||||||
|
if (attribute_name.find('_') != std::string::npos) {
|
||||||
|
std::vector<std::string> split_string = split(attribute_name, '_');
|
||||||
|
std::string new_attribute_name;
|
||||||
|
for (std::string &string_value : split_string) {
|
||||||
|
new_attribute_name += ucfirst(string_value) + " ";
|
||||||
|
}
|
||||||
|
attribute_name = new_attribute_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute names less than 4 characters get capitalized
|
||||||
|
* "hp" = "HP"
|
||||||
|
*/
|
||||||
|
if (attribute_name.length() <= 3) {
|
||||||
|
attribute_name = str_toupper(attribute_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute names larger than 3 characters get capitalized first letter
|
||||||
|
* "avoidance" = "Avoidance"
|
||||||
|
*/
|
||||||
|
if (attribute_name.length() > 3) {
|
||||||
|
attribute_name = ucfirst(attribute_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
find_replace(attribute_name, "Proximity", std::string(""));
|
||||||
|
find_replace(attribute_name, "Roambox", std::string(""));
|
||||||
|
|
||||||
|
std::string attribute_value = GetMobAttributeByString(mob, attribute);
|
||||||
|
|
||||||
|
if (attribute_value.length() <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
text += "<td>" + attribute_name + "</td><td>" + GetMobAttributeByString(mob, attribute) + "</td>";
|
||||||
|
|
||||||
|
if (index == column_count) {
|
||||||
|
index = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
text += "</tr></tbody></table>";
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void NPCCommandsMenu(Client* client, NPC* npc)
|
||||||
|
{
|
||||||
|
std::string menu_commands;
|
||||||
|
|
||||||
|
if (npc->GetGrid() > 0) {
|
||||||
|
menu_commands += "[" + EQEmu::SayLinkEngine::GenerateQuestSaylink("#grid show", false, "Grid Points") + "] ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (npc->GetEmoteID() > 0) {
|
||||||
|
std::string saylink = StringFormat("#emotesearch %u", npc->GetEmoteID());
|
||||||
|
menu_commands += "[" + EQEmu::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Emotes") + "] ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (npc->GetLoottableID() > 0) {
|
||||||
|
menu_commands += "[" + EQEmu::SayLinkEngine::GenerateQuestSaylink("#npcloot show", false, "Loot") + "] ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (menu_commands.length() > 0) {
|
||||||
|
std::string dev_menu = "[" + EQEmu::SayLinkEngine::GenerateQuestSaylink("#devtools", false, "DevTools") + "] ";;
|
||||||
|
client->Message(0, "| %s [Show Commands] %s", dev_menu.c_str(), menu_commands.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mob::DisplayInfo(Mob *mob)
|
||||||
|
{
|
||||||
|
if (!mob) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->IsClient()) {
|
||||||
|
|
||||||
|
std::string window_text = "<c \"#FFFF66\">*Drag window open vertically to see all</c><br>";
|
||||||
|
|
||||||
|
Client *client = this->CastToClient();
|
||||||
|
|
||||||
|
if (!client->IsDevToolsWindowEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> info_attributes = {
|
||||||
|
"name",
|
||||||
|
"race",
|
||||||
|
"surname",
|
||||||
|
"class",
|
||||||
|
};
|
||||||
|
window_text += WriteDisplayInfoSection(mob, "Info", info_attributes, 1, false);
|
||||||
|
|
||||||
|
std::vector<std::string> basic_attributes = {
|
||||||
|
"type",
|
||||||
|
"level",
|
||||||
|
"hp_min_max",
|
||||||
|
"ac",
|
||||||
|
"mp_min_max",
|
||||||
|
"atk",
|
||||||
|
"end_min_max",
|
||||||
|
};
|
||||||
|
window_text += WriteDisplayInfoSection(mob, "Main", basic_attributes, 1, false);
|
||||||
|
|
||||||
|
std::vector<std::string> stat_attributes = {
|
||||||
|
"str",
|
||||||
|
"sta",
|
||||||
|
"agi",
|
||||||
|
"dex",
|
||||||
|
"wis",
|
||||||
|
"int",
|
||||||
|
"cha",
|
||||||
|
};
|
||||||
|
window_text += WriteDisplayInfoSection(mob, "Statistics", stat_attributes, 1, false);
|
||||||
|
|
||||||
|
std::vector<std::string> resist_attributes = {
|
||||||
|
"pr",
|
||||||
|
"mr",
|
||||||
|
"dr",
|
||||||
|
"fr",
|
||||||
|
"cr",
|
||||||
|
"cor",
|
||||||
|
"phy",
|
||||||
|
};
|
||||||
|
window_text += WriteDisplayInfoSection(mob, "Resists", resist_attributes, 1, false);
|
||||||
|
|
||||||
|
std::vector<std::string> calculations = {
|
||||||
|
"tohit",
|
||||||
|
"total_to_hit",
|
||||||
|
"defense",
|
||||||
|
"total_defense",
|
||||||
|
"offense",
|
||||||
|
"mitigation_ac",
|
||||||
|
};
|
||||||
|
window_text += WriteDisplayInfoSection(mob, "Calculations", calculations, 1, true);
|
||||||
|
|
||||||
|
if (mob->IsClient()) {
|
||||||
|
std::vector<std::string> mods = {
|
||||||
|
"hp_regen",
|
||||||
|
"mana_regen",
|
||||||
|
"end_regen",
|
||||||
|
"heal_amount",
|
||||||
|
"spell_dmg",
|
||||||
|
"clairvoyance",
|
||||||
|
};
|
||||||
|
window_text += WriteDisplayInfoSection(mob, "Mods", mods, 1, true);
|
||||||
|
|
||||||
|
std::vector<std::string> mod_defensive = {
|
||||||
|
"shielding",
|
||||||
|
"spell_shielding",
|
||||||
|
"dot_shielding",
|
||||||
|
"stun_resist",
|
||||||
|
"damage_shield",
|
||||||
|
"ds_mitigation",
|
||||||
|
"avoidance",
|
||||||
|
};
|
||||||
|
|
||||||
|
window_text += WriteDisplayInfoSection(mob, "Mod Defensive", mod_defensive, 1, true);
|
||||||
|
|
||||||
|
std::vector<std::string> mod_offensive = {
|
||||||
|
"strikethrough",
|
||||||
|
"accuracy",
|
||||||
|
"combat_effects",
|
||||||
|
};
|
||||||
|
window_text += WriteDisplayInfoSection(mob, "Mod Offensive", mod_offensive, 1, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mob->IsNPC()) {
|
||||||
|
NPC *npc = mob->CastToNPC();
|
||||||
|
|
||||||
|
std::vector<std::string> npc_stats = {
|
||||||
|
"accuracy",
|
||||||
|
"slow_mitigation",
|
||||||
|
"min_hit",
|
||||||
|
"max_hit",
|
||||||
|
"hp_regen",
|
||||||
|
"attack_delay",
|
||||||
|
"spell_scale",
|
||||||
|
"heal_scale",
|
||||||
|
"avoidance",
|
||||||
|
};
|
||||||
|
|
||||||
|
window_text += WriteDisplayInfoSection(mob, "NPC Stats", npc_stats, 1, true);
|
||||||
|
|
||||||
|
std::vector<std::string> npc_attributes = {
|
||||||
|
"npcid",
|
||||||
|
"texture",
|
||||||
|
"bodytype",
|
||||||
|
"gender",
|
||||||
|
"size",
|
||||||
|
"runspeed",
|
||||||
|
"walkspeed",
|
||||||
|
"spawngroup",
|
||||||
|
"grid",
|
||||||
|
"emote",
|
||||||
|
"see_invis",
|
||||||
|
"see_invis_undead",
|
||||||
|
"faction",
|
||||||
|
"loottable",
|
||||||
|
"prim_skill",
|
||||||
|
"sec_skill",
|
||||||
|
"melee_texture_1",
|
||||||
|
"melee_texture_2",
|
||||||
|
"aggrorange",
|
||||||
|
"assistrange",
|
||||||
|
"findable",
|
||||||
|
"trackable",
|
||||||
|
"flymode",
|
||||||
|
"spells_id",
|
||||||
|
"curbuffslots",
|
||||||
|
"maxbuffslots",
|
||||||
|
};
|
||||||
|
|
||||||
|
window_text += WriteDisplayInfoSection(mob, "NPC Attributes", npc_attributes, 1, true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print Roambox
|
||||||
|
*/
|
||||||
|
if (npc->GetRoamboxMaxX() != 0 && npc->GetRoamboxMinX() != 0) {
|
||||||
|
std::vector<std::string> npc_roambox = {
|
||||||
|
"roambox_min_x",
|
||||||
|
"roambox_max_x",
|
||||||
|
"roambox_min_y",
|
||||||
|
"roambox_max_y",
|
||||||
|
"roambox_min_delay",
|
||||||
|
"roambox_delay",
|
||||||
|
"roambox_distance",
|
||||||
|
};
|
||||||
|
|
||||||
|
window_text += WriteDisplayInfoSection(mob, "Roambox", npc_roambox, 1, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (npc->proximity != nullptr) {
|
||||||
|
std::vector<std::string> npc_proximity = {
|
||||||
|
"proximity_min_x",
|
||||||
|
"proximity_max_x",
|
||||||
|
"proximity_min_y",
|
||||||
|
"proximity_max_y",
|
||||||
|
"proximity_min_z",
|
||||||
|
"proximity_max_z",
|
||||||
|
};
|
||||||
|
|
||||||
|
window_text += WriteDisplayInfoSection(mob, "Proximity", npc_proximity, 1, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
int8 npc_type = npc_scale_manager->GetNPCScalingType(npc);
|
||||||
|
std::string npc_type_string = npc_scale_manager->GetNPCScalingTypeName(npc);
|
||||||
|
|
||||||
|
client->Message(
|
||||||
|
0,
|
||||||
|
"| # Target: %s Type: %i (%s)",
|
||||||
|
npc->GetCleanName(),
|
||||||
|
npc_type,
|
||||||
|
npc_type_string.c_str());
|
||||||
|
|
||||||
|
NPCCommandsMenu(client, npc);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Window Length: " << window_text.length() << std::endl;
|
||||||
|
|
||||||
|
if (client->GetDisplayMobInfoWindow()) {
|
||||||
|
client->SendFullPopup(
|
||||||
|
"GM: Entity Info",
|
||||||
|
window_text.c_str(),
|
||||||
|
EQEmu::popupresponse::MOB_INFO_DISMISS,
|
||||||
|
0,
|
||||||
|
100,
|
||||||
|
0,
|
||||||
|
"Snooze",
|
||||||
|
"OK"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
zone/net.cpp
10
zone/net.cpp
@ -42,7 +42,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "../common/spdat.h"
|
#include "../common/spdat.h"
|
||||||
#include "../common/eqemu_logsys.h"
|
#include "../common/eqemu_logsys.h"
|
||||||
|
|
||||||
|
|
||||||
#include "zone_config.h"
|
#include "zone_config.h"
|
||||||
#include "masterentity.h"
|
#include "masterentity.h"
|
||||||
#include "worldserver.h"
|
#include "worldserver.h"
|
||||||
@ -62,6 +61,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "embparser.h"
|
#include "embparser.h"
|
||||||
#include "lua_parser.h"
|
#include "lua_parser.h"
|
||||||
#include "questmgr.h"
|
#include "questmgr.h"
|
||||||
|
#include "npc_scale_manager.h"
|
||||||
|
|
||||||
#include "../common/event/event_loop.h"
|
#include "../common/event/event_loop.h"
|
||||||
#include "../common/event/timer.h"
|
#include "../common/event/timer.h"
|
||||||
@ -104,6 +104,7 @@ npcDecayTimes_Struct npcCorpseDecayTimes[100];
|
|||||||
TitleManager title_manager;
|
TitleManager title_manager;
|
||||||
QueryServ *QServ = 0;
|
QueryServ *QServ = 0;
|
||||||
TaskManager *taskmanager = 0;
|
TaskManager *taskmanager = 0;
|
||||||
|
NpcScaleManager *npc_scale_manager;
|
||||||
QuestParserCollection *parse = 0;
|
QuestParserCollection *parse = 0;
|
||||||
EQEmuLogSys LogSys;
|
EQEmuLogSys LogSys;
|
||||||
const SPDat_Spell_Struct* spells;
|
const SPDat_Spell_Struct* spells;
|
||||||
@ -222,7 +223,6 @@ int main(int argc, char** argv) {
|
|||||||
worldserver.SetLauncherName("NONE");
|
worldserver.SetLauncherName("NONE");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Log(Logs::General, Logs::Zone_Server, "Connecting to MySQL...");
|
Log(Logs::General, Logs::Zone_Server, "Connecting to MySQL...");
|
||||||
if (!database.Connect(
|
if (!database.Connect(
|
||||||
Config->DatabaseHost.c_str(),
|
Config->DatabaseHost.c_str(),
|
||||||
@ -255,6 +255,12 @@ int main(int argc, char** argv) {
|
|||||||
guild_mgr.SetDatabase(&database);
|
guild_mgr.SetDatabase(&database);
|
||||||
GuildBanks = nullptr;
|
GuildBanks = nullptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NPC Scale Manager
|
||||||
|
*/
|
||||||
|
npc_scale_manager = new NpcScaleManager;
|
||||||
|
npc_scale_manager->LoadScaleData();
|
||||||
|
|
||||||
#ifdef _EQDEBUG
|
#ifdef _EQDEBUG
|
||||||
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
|
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
992
zone/npc.cpp
992
zone/npc.cpp
File diff suppressed because it is too large
Load Diff
52
zone/npc.h
52
zone/npc.h
@ -106,7 +106,7 @@ public:
|
|||||||
static bool SpawnZoneController();
|
static bool SpawnZoneController();
|
||||||
static int8 GetAILevel(bool iForceReRead = false);
|
static int8 GetAILevel(bool iForceReRead = false);
|
||||||
|
|
||||||
NPC(const NPCType* data, Spawn2* respawn, const glm::vec4& position, GravityBehavior iflymode, bool IsCorpse = false);
|
NPC(const NPCType* npc_type_data, Spawn2* respawn, const glm::vec4& position, GravityBehavior iflymode, bool IsCorpse = false);
|
||||||
|
|
||||||
virtual ~NPC();
|
virtual ~NPC();
|
||||||
|
|
||||||
@ -142,9 +142,6 @@ public:
|
|||||||
virtual void AI_Event_SpellCastFinished(bool iCastSucceeded, uint16 slot);
|
virtual void AI_Event_SpellCastFinished(bool iCastSucceeded, uint16 slot);
|
||||||
|
|
||||||
void LevelScale();
|
void LevelScale();
|
||||||
void CalcNPCResists();
|
|
||||||
void CalcNPCRegen();
|
|
||||||
void CalcNPCDamage();
|
|
||||||
|
|
||||||
virtual void SetTarget(Mob* mob);
|
virtual void SetTarget(Mob* mob);
|
||||||
virtual uint16 GetSkill(EQEmu::skills::SkillType skill_num) const { if (skill_num <= EQEmu::skills::HIGHEST_SKILL) { return skills[skill_num]; } return 0; }
|
virtual uint16 GetSkill(EQEmu::skills::SkillType skill_num) const { if (skill_num <= EQEmu::skills::HIGHEST_SKILL) { return skills[skill_num]; } return 0; }
|
||||||
@ -252,12 +249,23 @@ public:
|
|||||||
|
|
||||||
void SignalNPC(int _signal_id);
|
void SignalNPC(int _signal_id);
|
||||||
|
|
||||||
inline int32 GetNPCFactionID() const { return npc_faction_id; }
|
inline int32 GetNPCFactionID() const
|
||||||
inline int32 GetPrimaryFaction() const { return primary_faction; }
|
{ return npc_faction_id; }
|
||||||
int32 GetNPCHate(Mob* in_ent) {return hate_list.GetEntHateAmount(in_ent);}
|
|
||||||
bool IsOnHatelist(Mob*p) { return hate_list.IsEntOnHateList(p);}
|
|
||||||
|
|
||||||
void SetNPCFactionID(int32 in) { npc_faction_id = in; database.GetFactionIdsForNPC(npc_faction_id, &faction_list, &primary_faction); }
|
inline int32 GetPrimaryFaction() const
|
||||||
|
{ return primary_faction; }
|
||||||
|
|
||||||
|
int32 GetNPCHate(Mob *in_ent)
|
||||||
|
{ return hate_list.GetEntHateAmount(in_ent); }
|
||||||
|
|
||||||
|
bool IsOnHatelist(Mob *p)
|
||||||
|
{ return hate_list.IsEntOnHateList(p); }
|
||||||
|
|
||||||
|
void SetNPCFactionID(int32 in)
|
||||||
|
{
|
||||||
|
npc_faction_id = in;
|
||||||
|
database.GetFactionIdsForNPC(npc_faction_id, &faction_list, &primary_faction);
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec4 m_SpawnPoint;
|
glm::vec4 m_SpawnPoint;
|
||||||
|
|
||||||
@ -309,6 +317,9 @@ public:
|
|||||||
inline bool IsGuarding() const { return(m_GuardPoint.w != 0); }
|
inline bool IsGuarding() const { return(m_GuardPoint.w != 0); }
|
||||||
void SaveGuardSpotCharm();
|
void SaveGuardSpotCharm();
|
||||||
|
|
||||||
|
uint16 GetMeleeTexture1() const;
|
||||||
|
uint16 GetMeleeTexture2() const;
|
||||||
|
|
||||||
void RestoreGuardSpotCharm();
|
void RestoreGuardSpotCharm();
|
||||||
|
|
||||||
void AI_SetRoambox(
|
void AI_SetRoambox(
|
||||||
@ -338,6 +349,13 @@ public:
|
|||||||
inline const uint32 GetNPCSpellsID() const { return npc_spells_id; }
|
inline const uint32 GetNPCSpellsID() const { return npc_spells_id; }
|
||||||
inline const uint32 GetNPCSpellsEffectsID() const { return npc_spells_effects_id; }
|
inline const uint32 GetNPCSpellsEffectsID() const { return npc_spells_effects_id; }
|
||||||
|
|
||||||
|
float GetProximityMinX();
|
||||||
|
float GetProximityMaxX();
|
||||||
|
float GetProximityMinY();
|
||||||
|
float GetProximityMaxY();
|
||||||
|
float GetProximityMinZ();
|
||||||
|
float GetProximityMaxZ();
|
||||||
|
|
||||||
ItemList itemlist; //kathgar - why is this public? Doing other things or I would check the code
|
ItemList itemlist; //kathgar - why is this public? Doing other things or I would check the code
|
||||||
|
|
||||||
NPCProximity* proximity;
|
NPCProximity* proximity;
|
||||||
@ -354,7 +372,7 @@ public:
|
|||||||
void SetAvoidanceRating(int32 d) { avoidance_rating = d;}
|
void SetAvoidanceRating(int32 d) { avoidance_rating = d;}
|
||||||
int32 GetRawAC() const { return AC; }
|
int32 GetRawAC() const { return AC; }
|
||||||
|
|
||||||
void ModifyNPCStat(const char *identifier, const char *newValue);
|
void ModifyNPCStat(const char *identifier, const char *new_value);
|
||||||
virtual void SetLevel(uint8 in_level, bool command = false);
|
virtual void SetLevel(uint8 in_level, bool command = false);
|
||||||
|
|
||||||
bool IsLDoNTrapped() const { return (ldon_trapped); }
|
bool IsLDoNTrapped() const { return (ldon_trapped); }
|
||||||
@ -432,6 +450,17 @@ public:
|
|||||||
|
|
||||||
bool IgnoreDespawn() { return ignore_despawn; }
|
bool IgnoreDespawn() { return ignore_despawn; }
|
||||||
|
|
||||||
|
float GetRoamboxMaxX() const;
|
||||||
|
float GetRoamboxMaxY() const;
|
||||||
|
float GetRoamboxMinX() const;
|
||||||
|
float GetRoamboxMinY() const;
|
||||||
|
float GetRoamboxDistance() const;
|
||||||
|
float GetRoamboxDestinationX() const;
|
||||||
|
float GetRoamboxDestinationY() const;
|
||||||
|
float GetRoamboxDestinationZ() const;
|
||||||
|
uint32 GetRoamboxDelay() const;
|
||||||
|
uint32 GetRoamboxMinDelay() const;
|
||||||
|
|
||||||
std::unique_ptr<Timer> AIautocastspell_timer;
|
std::unique_ptr<Timer> AIautocastspell_timer;
|
||||||
|
|
||||||
virtual int GetStuckBehavior() const { return NPCTypedata_ours ? NPCTypedata_ours->stuck_behavior : NPCTypedata->stuck_behavior; }
|
virtual int GetStuckBehavior() const { return NPCTypedata_ours ? NPCTypedata_ours->stuck_behavior : NPCTypedata->stuck_behavior; }
|
||||||
@ -548,7 +577,8 @@ protected:
|
|||||||
uint32 equipment[EQEmu::invslot::EQUIPMENT_COUNT]; //this is an array of item IDs
|
uint32 equipment[EQEmu::invslot::EQUIPMENT_COUNT]; //this is an array of item IDs
|
||||||
|
|
||||||
uint32 herosforgemodel; //this is the Hero Forge Armor Model (i.e 63 or 84 or 203)
|
uint32 herosforgemodel; //this is the Hero Forge Armor Model (i.e 63 or 84 or 203)
|
||||||
uint16 d_melee_texture1; //this is an item Material value
|
uint16 d_melee_texture1;
|
||||||
|
//this is an item Material value
|
||||||
uint16 d_melee_texture2; //this is an item Material value (offhand)
|
uint16 d_melee_texture2; //this is an item Material value (offhand)
|
||||||
const char* ammo_idfile; //this determines projectile graphic "IT###" (see item field 'idfile')
|
const char* ammo_idfile; //this determines projectile graphic "IT###" (see item field 'idfile')
|
||||||
uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation
|
uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation
|
||||||
|
|||||||
624
zone/npc_scale_manager.cpp
Normal file
624
zone/npc_scale_manager.cpp
Normal file
@ -0,0 +1,624 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2018 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "npc_scale_manager.h"
|
||||||
|
#include "../common/string_util.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param npc
|
||||||
|
*/
|
||||||
|
void NpcScaleManager::ScaleNPC(NPC * npc)
|
||||||
|
{
|
||||||
|
int8 npc_type = GetNPCScalingType(npc);
|
||||||
|
int npc_level = npc->GetLevel();
|
||||||
|
bool is_auto_scaled = IsAutoScaled(npc);
|
||||||
|
|
||||||
|
global_npc_scale scale_data = GetGlobalScaleDataForTypeLevel(npc_type, npc_level);
|
||||||
|
|
||||||
|
if (!scale_data.level) {
|
||||||
|
Log(Logs::General, Logs::NPCScaling, "NPC: %s - scaling data not found for type: %i level: %i",
|
||||||
|
npc->GetCleanName(),
|
||||||
|
npc_type,
|
||||||
|
npc_level
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (npc->GetAC() == 0) {
|
||||||
|
npc->ModifyNPCStat("ac", std::to_string(scale_data.ac).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetMaxHP() == 0) {
|
||||||
|
npc->ModifyNPCStat("max_hp", std::to_string(scale_data.hp).c_str());
|
||||||
|
npc->Heal();
|
||||||
|
}
|
||||||
|
if (npc->GetAccuracyRating() == 0) {
|
||||||
|
npc->ModifyNPCStat("accuracy", std::to_string(scale_data.accuracy).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetSlowMitigation() == 0) {
|
||||||
|
npc->ModifyNPCStat("slow_mitigation", std::to_string(scale_data.slow_mitigation).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetATK() == 0) {
|
||||||
|
npc->ModifyNPCStat("atk", std::to_string(scale_data.attack).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetSTR() == 0) {
|
||||||
|
npc->ModifyNPCStat("str", std::to_string(scale_data.strength).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetSTA() == 0) {
|
||||||
|
npc->ModifyNPCStat("sta", std::to_string(scale_data.stamina).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetDEX() == 0) {
|
||||||
|
npc->ModifyNPCStat("dex", std::to_string(scale_data.dexterity).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetAGI() == 0) {
|
||||||
|
npc->ModifyNPCStat("agi", std::to_string(scale_data.agility).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetINT() == 0) {
|
||||||
|
npc->ModifyNPCStat("int", std::to_string(scale_data.intelligence).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetWIS() == 0) {
|
||||||
|
npc->ModifyNPCStat("wis", std::to_string(scale_data.wisdom).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetCHA() == 0) {
|
||||||
|
npc->ModifyNPCStat("cha", std::to_string(scale_data.charisma).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetMR() == 0) {
|
||||||
|
npc->ModifyNPCStat("mr", std::to_string(scale_data.magic_resist).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetCR() == 0) {
|
||||||
|
npc->ModifyNPCStat("cr", std::to_string(scale_data.cold_resist).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetFR() == 0) {
|
||||||
|
npc->ModifyNPCStat("fr", std::to_string(scale_data.fire_resist).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetPR() == 0) {
|
||||||
|
npc->ModifyNPCStat("pr", std::to_string(scale_data.poison_resist).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetDR() == 0) {
|
||||||
|
npc->ModifyNPCStat("dr", std::to_string(scale_data.disease_resist).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetCorrup() == 0) {
|
||||||
|
npc->ModifyNPCStat("cr", std::to_string(scale_data.corruption_resist).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetPhR() == 0) {
|
||||||
|
npc->ModifyNPCStat("pr", std::to_string(scale_data.physical_resist).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetMinDMG() == 0) {
|
||||||
|
int min_dmg = scale_data.min_dmg;
|
||||||
|
if (RuleB(Combat, UseNPCDamageClassLevelMods)) {
|
||||||
|
int32 class_level_damage_mod = GetClassLevelDamageMod(npc->GetLevel(), npc->GetClass());
|
||||||
|
min_dmg = (min_dmg * class_level_damage_mod) / 220;
|
||||||
|
|
||||||
|
Log(Logs::Moderate,
|
||||||
|
Logs::NPCScaling,
|
||||||
|
"ClassLevelDamageMod::min_dmg base: %i calc: %i",
|
||||||
|
scale_data.min_dmg,
|
||||||
|
min_dmg);
|
||||||
|
}
|
||||||
|
|
||||||
|
npc->ModifyNPCStat("min_hit", std::to_string(min_dmg).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetMaxDMG() == 0) {
|
||||||
|
int max_dmg = scale_data.max_dmg;
|
||||||
|
if (RuleB(Combat, UseNPCDamageClassLevelMods)) {
|
||||||
|
int32 class_level_damage_mod = GetClassLevelDamageMod(npc->GetLevel(), npc->GetClass());
|
||||||
|
max_dmg = (scale_data.max_dmg * class_level_damage_mod) / 220;
|
||||||
|
|
||||||
|
Log(Logs::Moderate,
|
||||||
|
Logs::NPCScaling,
|
||||||
|
"ClassLevelDamageMod::max_dmg base: %i calc: %i",
|
||||||
|
scale_data.max_dmg,
|
||||||
|
max_dmg
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
npc->ModifyNPCStat("max_hit", std::to_string(max_dmg).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetHPRegen() == 0) {
|
||||||
|
npc->ModifyNPCStat("hp_regen", std::to_string(scale_data.hp_regen_rate).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetAttackDelay() == 0) {
|
||||||
|
npc->ModifyNPCStat("attack_delay", std::to_string(scale_data.attack_delay).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetSpellScale() == 0) {
|
||||||
|
npc->ModifyNPCStat("spell_scale", std::to_string(scale_data.spell_scale).c_str());
|
||||||
|
}
|
||||||
|
if (npc->GetHealScale() == 0) {
|
||||||
|
npc->ModifyNPCStat("heal_scale", std::to_string(scale_data.heal_scale).c_str());
|
||||||
|
}
|
||||||
|
if (!npc->HasSpecialAbilities() && is_auto_scaled) {
|
||||||
|
npc->ModifyNPCStat("special_abilities", scale_data.special_abilities.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LogSys.log_settings[Logs::NPCScaling].is_category_enabled == 1) {
|
||||||
|
std::string scale_log;
|
||||||
|
|
||||||
|
for (const auto &stat : scaling_stats) {
|
||||||
|
std::string variable = StringFormat("modify_stat_%s", stat.c_str());
|
||||||
|
if (npc->EntityVariableExists(variable.c_str())) {
|
||||||
|
scale_log += stat + ": " + npc->GetEntityVariable(variable.c_str()) + " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(Logs::General,
|
||||||
|
Logs::NPCScaling,
|
||||||
|
"(%s) level: %i type: %i Auto: %s Setting: %s",
|
||||||
|
npc->GetCleanName(),
|
||||||
|
npc_level,
|
||||||
|
npc_type,
|
||||||
|
(is_auto_scaled ? "true" : "false"),
|
||||||
|
scale_log.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NpcScaleManager::LoadScaleData()
|
||||||
|
{
|
||||||
|
auto results = database.QueryDatabase(
|
||||||
|
"SELECT "
|
||||||
|
"type,"
|
||||||
|
"level,"
|
||||||
|
"ac,"
|
||||||
|
"hp,"
|
||||||
|
"accuracy,"
|
||||||
|
"slow_mitigation,"
|
||||||
|
"attack,"
|
||||||
|
"strength,"
|
||||||
|
"stamina,"
|
||||||
|
"dexterity,"
|
||||||
|
"agility,"
|
||||||
|
"intelligence,"
|
||||||
|
"wisdom,"
|
||||||
|
"charisma,"
|
||||||
|
"magic_resist,"
|
||||||
|
"cold_resist,"
|
||||||
|
"fire_resist,"
|
||||||
|
"poison_resist,"
|
||||||
|
"disease_resist,"
|
||||||
|
"corruption_resist,"
|
||||||
|
"physical_resist,"
|
||||||
|
"min_dmg,"
|
||||||
|
"max_dmg,"
|
||||||
|
"hp_regen_rate,"
|
||||||
|
"attack_delay,"
|
||||||
|
"spell_scale,"
|
||||||
|
"heal_scale,"
|
||||||
|
"special_abilities"
|
||||||
|
" FROM `npc_scale_global_base`"
|
||||||
|
);
|
||||||
|
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
global_npc_scale scale_data;
|
||||||
|
|
||||||
|
scale_data.type = atoi(row[0]);
|
||||||
|
scale_data.level = atoi(row[1]);
|
||||||
|
scale_data.ac = atoi(row[2]);
|
||||||
|
scale_data.hp = atoi(row[3]);
|
||||||
|
scale_data.accuracy = atoi(row[4]);
|
||||||
|
scale_data.slow_mitigation = atoi(row[5]);
|
||||||
|
scale_data.attack = atoi(row[6]);
|
||||||
|
scale_data.strength = atoi(row[7]);
|
||||||
|
scale_data.stamina = atoi(row[8]);
|
||||||
|
scale_data.dexterity = atoi(row[9]);
|
||||||
|
scale_data.agility = atoi(row[10]);
|
||||||
|
scale_data.intelligence = atoi(row[11]);
|
||||||
|
scale_data.wisdom = atoi(row[12]);
|
||||||
|
scale_data.charisma = atoi(row[13]);
|
||||||
|
scale_data.magic_resist = atoi(row[14]);
|
||||||
|
scale_data.cold_resist = atoi(row[15]);
|
||||||
|
scale_data.fire_resist = atoi(row[16]);
|
||||||
|
scale_data.poison_resist = atoi(row[17]);
|
||||||
|
scale_data.disease_resist = atoi(row[18]);
|
||||||
|
scale_data.corruption_resist = atoi(row[19]);
|
||||||
|
scale_data.physical_resist = atoi(row[20]);
|
||||||
|
scale_data.min_dmg = atoi(row[21]);
|
||||||
|
scale_data.max_dmg = atoi(row[22]);
|
||||||
|
scale_data.hp_regen_rate = atoi(row[23]);
|
||||||
|
scale_data.attack_delay = atoi(row[24]);
|
||||||
|
scale_data.spell_scale = atoi(row[25]);
|
||||||
|
scale_data.heal_scale = atoi(row[26]);
|
||||||
|
|
||||||
|
if (row[25]) {
|
||||||
|
scale_data.special_abilities = row[27];
|
||||||
|
}
|
||||||
|
|
||||||
|
npc_global_base_scaling_data.insert(
|
||||||
|
std::make_pair(
|
||||||
|
std::make_pair(scale_data.type, scale_data.level),
|
||||||
|
scale_data
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(Logs::General, Logs::NPCScaling, "Global Base Scaling Data Loaded...");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param npc_type
|
||||||
|
* @param npc_level
|
||||||
|
* @return NpcScaleManager::global_npc_scale
|
||||||
|
*/
|
||||||
|
NpcScaleManager::global_npc_scale NpcScaleManager::GetGlobalScaleDataForTypeLevel(int8 npc_type, int npc_level)
|
||||||
|
{
|
||||||
|
auto iter = npc_global_base_scaling_data.find(std::make_pair(npc_type, npc_level));
|
||||||
|
if (iter != npc_global_base_scaling_data.end()) {
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param level
|
||||||
|
* @param npc_class
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
uint32 NpcScaleManager::GetClassLevelDamageMod(uint32 level, uint32 npc_class)
|
||||||
|
{
|
||||||
|
uint32 multiplier = 0;
|
||||||
|
|
||||||
|
switch (npc_class) {
|
||||||
|
case WARRIOR: {
|
||||||
|
if (level < 20) {
|
||||||
|
multiplier = 220;
|
||||||
|
}
|
||||||
|
else if (level < 30) {
|
||||||
|
multiplier = 230;
|
||||||
|
}
|
||||||
|
else if (level < 40) {
|
||||||
|
multiplier = 250;
|
||||||
|
}
|
||||||
|
else if (level < 53) {
|
||||||
|
multiplier = 270;
|
||||||
|
}
|
||||||
|
else if (level < 57) {
|
||||||
|
multiplier = 280;
|
||||||
|
}
|
||||||
|
else if (level < 60) {
|
||||||
|
multiplier = 290;
|
||||||
|
}
|
||||||
|
else if (level < 70) {
|
||||||
|
multiplier = 300;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
multiplier = 311;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DRUID:
|
||||||
|
case CLERIC:
|
||||||
|
case SHAMAN: {
|
||||||
|
if (level < 70) {
|
||||||
|
multiplier = 150;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
multiplier = 157;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BERSERKER:
|
||||||
|
case PALADIN:
|
||||||
|
case SHADOWKNIGHT: {
|
||||||
|
if (level < 35) {
|
||||||
|
multiplier = 210;
|
||||||
|
}
|
||||||
|
else if (level < 45) {
|
||||||
|
multiplier = 220;
|
||||||
|
}
|
||||||
|
else if (level < 51) {
|
||||||
|
multiplier = 230;
|
||||||
|
}
|
||||||
|
else if (level < 56) {
|
||||||
|
multiplier = 240;
|
||||||
|
}
|
||||||
|
else if (level < 60) {
|
||||||
|
multiplier = 250;
|
||||||
|
}
|
||||||
|
else if (level < 68) {
|
||||||
|
multiplier = 260;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
multiplier = 270;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MONK:
|
||||||
|
case BARD:
|
||||||
|
case ROGUE:
|
||||||
|
case BEASTLORD: {
|
||||||
|
if (level < 51) {
|
||||||
|
multiplier = 180;
|
||||||
|
}
|
||||||
|
else if (level < 58) {
|
||||||
|
multiplier = 190;
|
||||||
|
}
|
||||||
|
else if (level < 70) {
|
||||||
|
multiplier = 200;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
multiplier = 210;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RANGER: {
|
||||||
|
if (level < 58) {
|
||||||
|
multiplier = 200;
|
||||||
|
}
|
||||||
|
else if (level < 70) {
|
||||||
|
multiplier = 210;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
multiplier = 220;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MAGICIAN:
|
||||||
|
case WIZARD:
|
||||||
|
case NECROMANCER:
|
||||||
|
case ENCHANTER: {
|
||||||
|
if (level < 70) {
|
||||||
|
multiplier = 120;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
multiplier = 127;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
if (level < 35) {
|
||||||
|
multiplier = 210;
|
||||||
|
}
|
||||||
|
else if (level < 45) {
|
||||||
|
multiplier = 220;
|
||||||
|
}
|
||||||
|
else if (level < 51) {
|
||||||
|
multiplier = 230;
|
||||||
|
}
|
||||||
|
else if (level < 56) {
|
||||||
|
multiplier = 240;
|
||||||
|
}
|
||||||
|
else if (level < 60) {
|
||||||
|
multiplier = 250;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
multiplier = 260;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param npc
|
||||||
|
* @return int8
|
||||||
|
*/
|
||||||
|
int8 NpcScaleManager::GetNPCScalingType(NPC *&npc)
|
||||||
|
{
|
||||||
|
std::string npc_name = npc->GetName();
|
||||||
|
|
||||||
|
if (npc->IsRareSpawn() || npc_name.find('#') != std::string::npos || isupper(npc_name[0])) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (npc->IsRaidTarget()) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param npc
|
||||||
|
* @return std::string
|
||||||
|
*/
|
||||||
|
std::string NpcScaleManager::GetNPCScalingTypeName(NPC *&npc)
|
||||||
|
{
|
||||||
|
int8 scaling_type = GetNPCScalingType(npc);
|
||||||
|
|
||||||
|
if (scaling_type == 1) {
|
||||||
|
return "Named";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (npc->IsRaidTarget()) {
|
||||||
|
return "Raid";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Trash";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines based on minimum criteria if NPC is auto scaled for certain things to be scaled like
|
||||||
|
* special abilities. We use this so we don't blindly assume we want things to be applied
|
||||||
|
*
|
||||||
|
* @param npc
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool NpcScaleManager::IsAutoScaled(NPC *npc)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(npc->GetHP() == 0 &&
|
||||||
|
npc->GetMaxDMG() == 0 &&
|
||||||
|
npc->GetMinDMG() == 0 &&
|
||||||
|
npc->GetSTR() == 0 &&
|
||||||
|
npc->GetSTA() == 0 &&
|
||||||
|
npc->GetDEX() == 0 &&
|
||||||
|
npc->GetAGI() == 0 &&
|
||||||
|
npc->GetINT() == 0 &&
|
||||||
|
npc->GetWIS() == 0 &&
|
||||||
|
npc->GetCHA() == 0 &&
|
||||||
|
npc->GetMR() == 0 &&
|
||||||
|
npc->GetFR() == 0 &&
|
||||||
|
npc->GetCR() == 0 &&
|
||||||
|
npc->GetPR() == 0 &&
|
||||||
|
npc->GetDR() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns false if scaling data not found
|
||||||
|
* @param npc
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool NpcScaleManager::ApplyGlobalBaseScalingToNPCStatically(NPC *&npc)
|
||||||
|
{
|
||||||
|
int8 npc_type = GetNPCScalingType(npc);
|
||||||
|
int npc_level = npc->GetLevel();
|
||||||
|
|
||||||
|
global_npc_scale scale_data = GetGlobalScaleDataForTypeLevel(npc_type, npc_level);
|
||||||
|
|
||||||
|
if (!scale_data.level) {
|
||||||
|
Log(
|
||||||
|
Logs::General,
|
||||||
|
Logs::NPCScaling,
|
||||||
|
"NpcScaleManager::ApplyGlobalBaseScalingToNPCStatically NPC: %s - scaling data not found for type: %i level: %i",
|
||||||
|
npc->GetCleanName(),
|
||||||
|
npc_type,
|
||||||
|
npc_level
|
||||||
|
);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string query = StringFormat(
|
||||||
|
"UPDATE `npc_types` SET "
|
||||||
|
"AC = %i, "
|
||||||
|
"hp = %i, "
|
||||||
|
"Accuracy = %i, "
|
||||||
|
"slow_mitigation = %i, "
|
||||||
|
"ATK = %i, "
|
||||||
|
"STR = %i, "
|
||||||
|
"STA = %i, "
|
||||||
|
"DEX = %i, "
|
||||||
|
"AGI = %i, "
|
||||||
|
"_INT = %i, "
|
||||||
|
"WIS = %i, "
|
||||||
|
"CHA = %i, "
|
||||||
|
"MR = %i, "
|
||||||
|
"CR = %i, "
|
||||||
|
"FR = %i, "
|
||||||
|
"PR = %i, "
|
||||||
|
"DR = %i, "
|
||||||
|
"Corrup = %i, "
|
||||||
|
"PhR = %i, "
|
||||||
|
"mindmg = %i, "
|
||||||
|
"maxdmg = %i, "
|
||||||
|
"hp_regen_rate = %i, "
|
||||||
|
"attack_delay = %i, "
|
||||||
|
"spellscale = %i, "
|
||||||
|
"healscale = %i, "
|
||||||
|
"special_abilities = '%s' "
|
||||||
|
"WHERE `id` = %i",
|
||||||
|
scale_data.ac,
|
||||||
|
scale_data.hp,
|
||||||
|
scale_data.accuracy,
|
||||||
|
scale_data.slow_mitigation,
|
||||||
|
scale_data.attack,
|
||||||
|
scale_data.strength,
|
||||||
|
scale_data.stamina,
|
||||||
|
scale_data.dexterity,
|
||||||
|
scale_data.agility,
|
||||||
|
scale_data.intelligence,
|
||||||
|
scale_data.wisdom,
|
||||||
|
scale_data.charisma,
|
||||||
|
scale_data.magic_resist,
|
||||||
|
scale_data.cold_resist,
|
||||||
|
scale_data.fire_resist,
|
||||||
|
scale_data.poison_resist,
|
||||||
|
scale_data.disease_resist,
|
||||||
|
scale_data.corruption_resist,
|
||||||
|
scale_data.physical_resist,
|
||||||
|
scale_data.min_dmg,
|
||||||
|
scale_data.max_dmg,
|
||||||
|
scale_data.hp_regen_rate,
|
||||||
|
scale_data.attack_delay,
|
||||||
|
scale_data.spell_scale,
|
||||||
|
scale_data.heal_scale,
|
||||||
|
EscapeString(scale_data.special_abilities).c_str(),
|
||||||
|
npc->GetNPCTypeID()
|
||||||
|
);
|
||||||
|
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
|
||||||
|
return results.Success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns false if scaling data not found
|
||||||
|
* @param npc
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool NpcScaleManager::ApplyGlobalBaseScalingToNPCDynamically(NPC *&npc)
|
||||||
|
{
|
||||||
|
int8 npc_type = GetNPCScalingType(npc);
|
||||||
|
int npc_level = npc->GetLevel();
|
||||||
|
|
||||||
|
global_npc_scale scale_data = GetGlobalScaleDataForTypeLevel(npc_type, npc_level);
|
||||||
|
|
||||||
|
if (!scale_data.level) {
|
||||||
|
Log(
|
||||||
|
Logs::General,
|
||||||
|
Logs::NPCScaling,
|
||||||
|
"NpcScaleManager::ApplyGlobalBaseScalingToNPCDynamically NPC: %s - scaling data not found for type: %i level: %i",
|
||||||
|
npc->GetCleanName(),
|
||||||
|
npc_type,
|
||||||
|
npc_level
|
||||||
|
);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string query = StringFormat(
|
||||||
|
"UPDATE `npc_types` SET "
|
||||||
|
"AC = 0, "
|
||||||
|
"hp = 0, "
|
||||||
|
"Accuracy = 0, "
|
||||||
|
"slow_mitigation = 0, "
|
||||||
|
"ATK = 0, "
|
||||||
|
"STR = 0, "
|
||||||
|
"STA = 0, "
|
||||||
|
"DEX = 0, "
|
||||||
|
"AGI = 0, "
|
||||||
|
"_INT = 0, "
|
||||||
|
"WIS = 0, "
|
||||||
|
"CHA = 0, "
|
||||||
|
"MR = 0, "
|
||||||
|
"CR = 0, "
|
||||||
|
"FR = 0, "
|
||||||
|
"PR = 0, "
|
||||||
|
"DR = 0, "
|
||||||
|
"Corrup = 0, "
|
||||||
|
"PhR = 0, "
|
||||||
|
"mindmg = 0, "
|
||||||
|
"maxdmg = 0, "
|
||||||
|
"hp_regen_rate = 0, "
|
||||||
|
"attack_delay = 0, "
|
||||||
|
"spellscale = 0, "
|
||||||
|
"healscale = 0, "
|
||||||
|
"special_abilities = '' "
|
||||||
|
"WHERE `id` = %i",
|
||||||
|
npc->GetNPCTypeID()
|
||||||
|
);
|
||||||
|
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
|
||||||
|
return results.Success();
|
||||||
|
}
|
||||||
107
zone/npc_scale_manager.h
Normal file
107
zone/npc_scale_manager.h
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2018 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* 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 EQEMU_NPC_SCALE_MANAGER_H
|
||||||
|
#define EQEMU_NPC_SCALE_MANAGER_H
|
||||||
|
|
||||||
|
#include "npc.h"
|
||||||
|
|
||||||
|
class NpcScaleManager {
|
||||||
|
public:
|
||||||
|
struct global_npc_scale {
|
||||||
|
int type;
|
||||||
|
int level;
|
||||||
|
int ac;
|
||||||
|
int hp;
|
||||||
|
int accuracy;
|
||||||
|
int slow_mitigation;
|
||||||
|
int attack;
|
||||||
|
int strength;
|
||||||
|
int stamina;
|
||||||
|
int dexterity;
|
||||||
|
int agility;
|
||||||
|
int intelligence;
|
||||||
|
int wisdom;
|
||||||
|
int charisma;
|
||||||
|
int magic_resist;
|
||||||
|
int cold_resist;
|
||||||
|
int fire_resist;
|
||||||
|
int poison_resist;
|
||||||
|
int disease_resist;
|
||||||
|
int corruption_resist;
|
||||||
|
int physical_resist;
|
||||||
|
int min_dmg;
|
||||||
|
int max_dmg;
|
||||||
|
int hp_regen_rate;
|
||||||
|
int attack_delay;
|
||||||
|
int spell_scale;
|
||||||
|
int heal_scale;
|
||||||
|
|
||||||
|
std::string special_abilities;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<std::string> scaling_stats = {
|
||||||
|
"ac",
|
||||||
|
"max_hp",
|
||||||
|
"accuracy",
|
||||||
|
"slow_mitigation",
|
||||||
|
"atk",
|
||||||
|
"str",
|
||||||
|
"sta",
|
||||||
|
"dex",
|
||||||
|
"agi",
|
||||||
|
"int",
|
||||||
|
"wis",
|
||||||
|
"cha",
|
||||||
|
"mr",
|
||||||
|
"cr",
|
||||||
|
"fr",
|
||||||
|
"pr",
|
||||||
|
"dr",
|
||||||
|
"cr",
|
||||||
|
"pr",
|
||||||
|
"min_hit",
|
||||||
|
"max_hit",
|
||||||
|
"hp_regen",
|
||||||
|
"attack_delay",
|
||||||
|
"spell_scale",
|
||||||
|
"heal_scale",
|
||||||
|
"special_abilities"
|
||||||
|
};
|
||||||
|
|
||||||
|
void ScaleNPC(NPC * npc);
|
||||||
|
bool IsAutoScaled(NPC * npc);
|
||||||
|
bool LoadScaleData();
|
||||||
|
|
||||||
|
global_npc_scale GetGlobalScaleDataForTypeLevel(int8 npc_type, int npc_level);
|
||||||
|
|
||||||
|
std::map<std::pair<int, int>, global_npc_scale> npc_global_base_scaling_data;
|
||||||
|
|
||||||
|
int8 GetNPCScalingType(NPC * &npc);
|
||||||
|
std::string GetNPCScalingTypeName(NPC * &npc);
|
||||||
|
bool ApplyGlobalBaseScalingToNPCStatically(NPC * &npc);
|
||||||
|
bool ApplyGlobalBaseScalingToNPCDynamically(NPC * &npc);
|
||||||
|
|
||||||
|
uint32 GetClassLevelDamageMod(uint32 level, uint32 npc_class);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern NpcScaleManager *npc_scale_manager;
|
||||||
|
|
||||||
|
#endif //EQEMU_NPC_SCALE_MANAGER_H
|
||||||
@ -180,7 +180,7 @@ protected:
|
|||||||
void RandomSpawn(bool send_packet = false); //spawn this ground spawn at a random place
|
void RandomSpawn(bool send_packet = false); //spawn this ground spawn at a random place
|
||||||
|
|
||||||
Object_Struct m_data; // Packet data
|
Object_Struct m_data; // Packet data
|
||||||
EQEmu::ItemInstance* m_inst; // Item representing object
|
EQEmu::ItemInstance *m_inst; // Item representing object
|
||||||
bool m_inuse; // Currently in use by a client?
|
bool m_inuse; // Currently in use by a client?
|
||||||
uint32 m_id; // Database key, different than drop_id
|
uint32 m_id; // Database key, different than drop_id
|
||||||
uint32 m_type; // Object Type, ie, forge, oven, dropped item, etc (ref: ContainerUseTypes)
|
uint32 m_type; // Object Type, ie, forge, oven, dropped item, etc (ref: ContainerUseTypes)
|
||||||
|
|||||||
@ -976,37 +976,44 @@ void QuestManager::permagender(int gender_id) {
|
|||||||
uint16 QuestManager::scribespells(uint8 max_level, uint8 min_level) {
|
uint16 QuestManager::scribespells(uint8 max_level, uint8 min_level) {
|
||||||
QuestManagerCurrentQuestVars();
|
QuestManagerCurrentQuestVars();
|
||||||
uint16 book_slot, count;
|
uint16 book_slot, count;
|
||||||
uint16 curspell;
|
uint16 spell_id;
|
||||||
|
|
||||||
uint32 Char_ID = initiator->CharacterID();
|
uint32 char_id = initiator->CharacterID();
|
||||||
bool SpellGlobalRule = RuleB(Spells, EnableSpellGlobals);
|
bool SpellGlobalRule = RuleB(Spells, EnableSpellGlobals);
|
||||||
|
bool SpellBucketRule = RuleB(Spells, EnableSpellBuckets);
|
||||||
bool SpellGlobalCheckResult = 0;
|
bool SpellGlobalCheckResult = 0;
|
||||||
|
bool SpellBucketCheckResult = 0;
|
||||||
|
|
||||||
|
|
||||||
for(curspell = 0, book_slot = initiator->GetNextAvailableSpellBookSlot(), count = 0; curspell < SPDAT_RECORDS && book_slot < MAX_PP_SPELLBOOK; curspell++, book_slot = initiator->GetNextAvailableSpellBookSlot(book_slot))
|
for(spell_id = 0, book_slot = initiator->GetNextAvailableSpellBookSlot(), count = 0; spell_id < SPDAT_RECORDS && book_slot < MAX_PP_SPELLBOOK; spell_id++, book_slot = initiator->GetNextAvailableSpellBookSlot(book_slot))
|
||||||
{
|
{
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
spells[curspell].classes[WARRIOR] != 0 && //check if spell exists
|
spells[spell_id].classes[WARRIOR] != 0 && //check if spell exists
|
||||||
spells[curspell].classes[initiator->GetPP().class_-1] <= max_level && //maximum level
|
spells[spell_id].classes[initiator->GetPP().class_-1] <= max_level && //maximum level
|
||||||
spells[curspell].classes[initiator->GetPP().class_-1] >= min_level && //minimum level
|
spells[spell_id].classes[initiator->GetPP().class_-1] >= min_level && //minimum level
|
||||||
spells[curspell].skill != 52 &&
|
spells[spell_id].skill != 52 &&
|
||||||
spells[curspell].effectid[EFFECT_COUNT - 1] != 10
|
spells[spell_id].effectid[EFFECT_COUNT - 1] != 10
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (book_slot == -1) //no more book slots
|
if (book_slot == -1) //no more book slots
|
||||||
break;
|
break;
|
||||||
if(!IsDiscipline(curspell) && !initiator->HasSpellScribed(curspell)) { //isn't a discipline & we don't already have it scribed
|
if(!IsDiscipline(spell_id) && !initiator->HasSpellScribed(spell_id)) { //isn't a discipline & we don't already have it scribed
|
||||||
if (SpellGlobalRule) {
|
if (SpellGlobalRule) {
|
||||||
// Bool to see if the character has the required QGlobal to scribe it if one exists in the Spell_Globals table
|
// Bool to see if the character has the required QGlobal to scribe it if one exists in the Spell_Globals table
|
||||||
SpellGlobalCheckResult = initiator->SpellGlobalCheck(curspell, Char_ID);
|
SpellGlobalCheckResult = initiator->SpellGlobalCheck(spell_id, char_id);
|
||||||
if (SpellGlobalCheckResult) {
|
if (SpellGlobalCheckResult) {
|
||||||
initiator->ScribeSpell(curspell, book_slot);
|
initiator->ScribeSpell(spell_id, book_slot);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
} else if (SpellBucketRule) {
|
||||||
|
SpellBucketCheckResult = initiator->SpellBucketCheck(spell_id, char_id);
|
||||||
|
if (SpellBucketCheckResult) {
|
||||||
|
initiator->ScribeSpell(spell_id, book_slot);
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
initiator->ScribeSpell(curspell, book_slot);
|
initiator->ScribeSpell(spell_id, book_slot);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1018,46 +1025,59 @@ uint16 QuestManager::scribespells(uint8 max_level, uint8 min_level) {
|
|||||||
uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) {
|
uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) {
|
||||||
QuestManagerCurrentQuestVars();
|
QuestManagerCurrentQuestVars();
|
||||||
uint16 count;
|
uint16 count;
|
||||||
uint16 curspell;
|
uint16 spell_id;
|
||||||
|
|
||||||
uint32 Char_ID = initiator->CharacterID();
|
uint32 char_id = initiator->CharacterID();
|
||||||
bool SpellGlobalRule = RuleB(Spells, EnableSpellGlobals);
|
bool SpellGlobalRule = RuleB(Spells, EnableSpellGlobals);
|
||||||
|
bool SpellBucketRule = RuleB(Spells, EnableSpellBuckets);
|
||||||
bool SpellGlobalCheckResult = 0;
|
bool SpellGlobalCheckResult = 0;
|
||||||
|
bool SpellBucketCheckResult = 0;
|
||||||
|
|
||||||
for(curspell = 0, count = 0; curspell < SPDAT_RECORDS; curspell++)
|
for(spell_id = 0, count = 0; spell_id < SPDAT_RECORDS; spell_id++)
|
||||||
{
|
{
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
spells[curspell].classes[WARRIOR] != 0 && //check if spell exists
|
spells[spell_id].classes[WARRIOR] != 0 && //check if spell exists
|
||||||
spells[curspell].classes[initiator->GetPP().class_-1] <= max_level && //maximum level
|
spells[spell_id].classes[initiator->GetPP().class_-1] <= max_level && //maximum level
|
||||||
spells[curspell].classes[initiator->GetPP().class_-1] >= min_level && //minimum level
|
spells[spell_id].classes[initiator->GetPP().class_-1] >= min_level && //minimum level
|
||||||
spells[curspell].skill != 52 &&
|
spells[spell_id].skill != 52 &&
|
||||||
( !RuleB(Spells, UseCHAScribeHack) || spells[curspell].effectid[EFFECT_COUNT - 1] != 10 )
|
( !RuleB(Spells, UseCHAScribeHack) || spells[spell_id].effectid[EFFECT_COUNT - 1] != 10 )
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if(IsDiscipline(curspell)){
|
if(IsDiscipline(spell_id)){
|
||||||
//we may want to come up with a function like Client::GetNextAvailableSpellBookSlot() to help speed this up a little
|
//we may want to come up with a function like Client::GetNextAvailableSpellBookSlot() to help speed this up a little
|
||||||
for(uint32 r = 0; r < MAX_PP_DISCIPLINES; r++) {
|
for(uint32 r = 0; r < MAX_PP_DISCIPLINES; r++) {
|
||||||
if(initiator->GetPP().disciplines.values[r] == curspell) {
|
if(initiator->GetPP().disciplines.values[r] == spell_id) {
|
||||||
initiator->Message(13, "You already know this discipline.");
|
initiator->Message(13, "You already know this discipline.");
|
||||||
break; //continue the 1st loop
|
break; //continue the 1st loop
|
||||||
}
|
}
|
||||||
else if(initiator->GetPP().disciplines.values[r] == 0) {
|
else if(initiator->GetPP().disciplines.values[r] == 0) {
|
||||||
if (SpellGlobalRule) {
|
if (SpellGlobalRule) {
|
||||||
// Bool to see if the character has the required QGlobal to train it if one exists in the Spell_Globals table
|
// Bool to see if the character has the required QGlobal to train it if one exists in the Spell_Globals table
|
||||||
SpellGlobalCheckResult = initiator->SpellGlobalCheck(curspell, Char_ID);
|
SpellGlobalCheckResult = initiator->SpellGlobalCheck(spell_id, char_id);
|
||||||
if (SpellGlobalCheckResult) {
|
if (SpellGlobalCheckResult) {
|
||||||
initiator->GetPP().disciplines.values[r] = curspell;
|
initiator->GetPP().disciplines.values[r] = spell_id;
|
||||||
database.SaveCharacterDisc(Char_ID, r, curspell);
|
database.SaveCharacterDisc(char_id, r, spell_id);
|
||||||
initiator->SendDisciplineUpdate();
|
initiator->SendDisciplineUpdate();
|
||||||
initiator->Message(0, "You have learned a new discipline!");
|
initiator->Message(0, "You have learned a new discipline!");
|
||||||
count++; //success counter
|
count++; //success counter
|
||||||
}
|
}
|
||||||
break; //continue the 1st loop
|
break; //continue the 1st loop
|
||||||
|
} else if (SpellBucketRule) {
|
||||||
|
// Bool to see if the character has the required bucket to train it if one exists in the spell_buckets table
|
||||||
|
SpellBucketCheckResult = initiator->SpellBucketCheck(spell_id, char_id);
|
||||||
|
if (SpellBucketCheckResult) {
|
||||||
|
initiator->GetPP().disciplines.values[r] = spell_id;
|
||||||
|
database.SaveCharacterDisc(char_id, r, spell_id);
|
||||||
|
initiator->SendDisciplineUpdate();
|
||||||
|
initiator->Message(0, "You have learned a new discipline!");
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
initiator->GetPP().disciplines.values[r] = curspell;
|
initiator->GetPP().disciplines.values[r] = spell_id;
|
||||||
database.SaveCharacterDisc(Char_ID, r, curspell);
|
database.SaveCharacterDisc(char_id, r, spell_id);
|
||||||
initiator->SendDisciplineUpdate();
|
initiator->SendDisciplineUpdate();
|
||||||
initiator->Message(0, "You have learned a new discipline!");
|
initiator->Message(0, "You have learned a new discipline!");
|
||||||
count++; //success counter
|
count++; //success counter
|
||||||
@ -2659,6 +2679,10 @@ uint16 QuestManager::GetInstanceID(const char *zone, int16 version)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16 QuestManager::GetInstanceIDByCharID(const char *zone, int16 version, uint32 char_id) {
|
||||||
|
return database.GetInstanceID(zone, char_id, version);
|
||||||
|
}
|
||||||
|
|
||||||
void QuestManager::AssignToInstance(uint16 instance_id)
|
void QuestManager::AssignToInstance(uint16 instance_id)
|
||||||
{
|
{
|
||||||
QuestManagerCurrentQuestVars();
|
QuestManagerCurrentQuestVars();
|
||||||
@ -2668,6 +2692,10 @@ void QuestManager::AssignToInstance(uint16 instance_id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QuestManager::AssignToInstanceByCharID(uint16 instance_id, uint32 char_id) {
|
||||||
|
database.AddClientToInstance(instance_id, char_id);
|
||||||
|
}
|
||||||
|
|
||||||
void QuestManager::AssignGroupToInstance(uint16 instance_id)
|
void QuestManager::AssignGroupToInstance(uint16 instance_id)
|
||||||
{
|
{
|
||||||
QuestManagerCurrentQuestVars();
|
QuestManagerCurrentQuestVars();
|
||||||
@ -2708,6 +2736,10 @@ void QuestManager::RemoveFromInstance(uint16 instance_id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QuestManager::RemoveFromInstanceByCharID(uint16 instance_id, uint32 char_id) {
|
||||||
|
database.RemoveClientFromInstance(instance_id, char_id);
|
||||||
|
}
|
||||||
|
|
||||||
void QuestManager::RemoveAllFromInstance(uint16 instance_id)
|
void QuestManager::RemoveAllFromInstance(uint16 instance_id)
|
||||||
{
|
{
|
||||||
QuestManagerCurrentQuestVars();
|
QuestManagerCurrentQuestVars();
|
||||||
@ -2759,47 +2791,11 @@ void QuestManager::FlagInstanceByRaidLeader(uint32 zone, int16 version)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkName) {
|
std::string QuestManager::saylink(char *saylink_text, bool silent, const char *link_name)
|
||||||
|
{
|
||||||
QuestManagerCurrentQuestVars();
|
QuestManagerCurrentQuestVars();
|
||||||
|
|
||||||
int sayid = 0;
|
return EQEmu::SayLinkEngine::GenerateQuestSaylink(saylink_text, silent, link_name);
|
||||||
|
|
||||||
int sz = strlen(Phrase);
|
|
||||||
auto escaped_string = new char[sz * 2];
|
|
||||||
database.DoEscapeString(escaped_string, Phrase, sz);
|
|
||||||
|
|
||||||
// Query for an existing phrase and id in the saylink table
|
|
||||||
std::string query = StringFormat("SELECT `id` FROM `saylink` WHERE `phrase` = '%s'", escaped_string);
|
|
||||||
auto results = database.QueryDatabase(query);
|
|
||||||
if (results.Success()) {
|
|
||||||
if (results.RowCount() >= 1) {
|
|
||||||
for (auto row = results.begin();row != results.end(); ++row)
|
|
||||||
sayid = atoi(row[0]);
|
|
||||||
} else {
|
|
||||||
std::string insert_query = StringFormat("INSERT INTO `saylink` (`phrase`) VALUES ('%s')", escaped_string);
|
|
||||||
results = database.QueryDatabase(insert_query);
|
|
||||||
if (!results.Success()) {
|
|
||||||
Log(Logs::General, Logs::Error, "Error in saylink phrase queries", results.ErrorMessage().c_str());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sayid = results.LastInsertedID();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
safe_delete_array(escaped_string);
|
|
||||||
|
|
||||||
//Create the say link as an item link hash
|
|
||||||
EQEmu::SayLinkEngine linker;
|
|
||||||
linker.SetProxyItemID(SAYLINK_ITEM_ID);
|
|
||||||
if (silent)
|
|
||||||
linker.SetProxyAugment2ID(sayid);
|
|
||||||
else
|
|
||||||
linker.SetProxyAugment1ID(sayid);
|
|
||||||
linker.SetProxyText(LinkName);
|
|
||||||
|
|
||||||
strcpy(Phrase, linker.GenerateLink().c_str());
|
|
||||||
|
|
||||||
return Phrase;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* QuestManager::getguildnamebyid(int guild_id) {
|
const char* QuestManager::getguildnamebyid(int guild_id) {
|
||||||
|
|||||||
@ -234,10 +234,13 @@ public:
|
|||||||
uint32 GetInstanceTimerByID(uint16 instance_id = 0);
|
uint32 GetInstanceTimerByID(uint16 instance_id = 0);
|
||||||
void DestroyInstance(uint16 instance_id);
|
void DestroyInstance(uint16 instance_id);
|
||||||
uint16 GetInstanceID(const char *zone, int16 version);
|
uint16 GetInstanceID(const char *zone, int16 version);
|
||||||
|
uint16 GetInstanceIDByCharID(const char *zone, int16 version, uint32 char_id);
|
||||||
void AssignToInstance(uint16 instance_id);
|
void AssignToInstance(uint16 instance_id);
|
||||||
|
void AssignToInstanceByCharID(uint16 instance_id, uint32 char_id);
|
||||||
void AssignGroupToInstance(uint16 instance_id);
|
void AssignGroupToInstance(uint16 instance_id);
|
||||||
void AssignRaidToInstance(uint16 instance_id);
|
void AssignRaidToInstance(uint16 instance_id);
|
||||||
void RemoveFromInstance(uint16 instance_id);
|
void RemoveFromInstance(uint16 instance_id);
|
||||||
|
void RemoveFromInstanceByCharID(uint16 instance_id, uint32 char_id);
|
||||||
//void RemoveGroupFromInstance(uint16 instance_id); //potentially useful but not implmented at this time.
|
//void RemoveGroupFromInstance(uint16 instance_id); //potentially useful but not implmented at this time.
|
||||||
//void RemoveRaidFromInstance(uint16 instance_id); //potentially useful but not implmented at this time.
|
//void RemoveRaidFromInstance(uint16 instance_id); //potentially useful but not implmented at this time.
|
||||||
void RemoveAllFromInstance(uint16 instance_id);
|
void RemoveAllFromInstance(uint16 instance_id);
|
||||||
@ -245,7 +248,7 @@ public:
|
|||||||
void FlagInstanceByGroupLeader(uint32 zone, int16 version);
|
void FlagInstanceByGroupLeader(uint32 zone, int16 version);
|
||||||
void FlagInstanceByRaidLeader(uint32 zone, int16 version);
|
void FlagInstanceByRaidLeader(uint32 zone, int16 version);
|
||||||
const char* varlink(char* perltext, int item_id);
|
const char* varlink(char* perltext, int item_id);
|
||||||
const char* saylink(char* Phrase, bool silent, const char* LinkName);
|
std::string saylink(char *saylink_text, bool silent, const char *link_name);
|
||||||
const char* getguildnamebyid(int guild_id);
|
const char* getguildnamebyid(int guild_id);
|
||||||
void SetRunning(bool val);
|
void SetRunning(bool val);
|
||||||
bool IsRunning();
|
bool IsRunning();
|
||||||
|
|||||||
@ -3005,6 +3005,10 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2,
|
|||||||
if(effect1 != effect2)
|
if(effect1 != effect2)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (IsBardOnlyStackEffect(effect1) && GetSpellLevel(spellid1, BARD) != 255 &&
|
||||||
|
GetSpellLevel(spellid2, BARD) != 255)
|
||||||
|
continue;
|
||||||
|
|
||||||
// big ol' list according to the client, wasn't that nice!
|
// big ol' list according to the client, wasn't that nice!
|
||||||
if (IsEffectIgnoredInStacking(effect1))
|
if (IsEffectIgnoredInStacking(effect1))
|
||||||
continue;
|
continue;
|
||||||
@ -5115,14 +5119,11 @@ int Client::FindSpellBookSlotBySpellID(uint16 spellid) {
|
|||||||
return -1; //default
|
return -1; //default
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Client::SpellGlobalCheck(uint16 spell_ID, uint32 char_ID) {
|
bool Client::SpellGlobalCheck(uint16 spell_id, uint32 char_id) {
|
||||||
|
std::string spell_global_name;
|
||||||
std::string spell_Global_Name;
|
int spell_global_value;
|
||||||
int spell_Global_Value;
|
int global_value;
|
||||||
int global_Value;
|
std::string query = StringFormat("SELECT qglobal, value FROM spell_globals WHERE spellid = %i", spell_id);
|
||||||
|
|
||||||
std::string query = StringFormat("SELECT qglobal, value FROM spell_globals "
|
|
||||||
"WHERE spellid = %i", spell_ID);
|
|
||||||
auto results = database.QueryDatabase(query);
|
auto results = database.QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
return false; // Query failed, so prevent spell from scribing just in case
|
return false; // Query failed, so prevent spell from scribing just in case
|
||||||
@ -5132,37 +5133,79 @@ bool Client::SpellGlobalCheck(uint16 spell_ID, uint32 char_ID) {
|
|||||||
return true; // Spell ID isn't listed in the spells_global table, so it is not restricted from scribing
|
return true; // Spell ID isn't listed in the spells_global table, so it is not restricted from scribing
|
||||||
|
|
||||||
auto row = results.begin();
|
auto row = results.begin();
|
||||||
spell_Global_Name = row[0];
|
spell_global_name = row[0];
|
||||||
spell_Global_Value = atoi(row[1]);
|
spell_global_value = atoi(row[1]);
|
||||||
|
|
||||||
if (spell_Global_Name.empty())
|
if (spell_global_name.empty())
|
||||||
return true; // If the entry in the spell_globals table has nothing set for the qglobal name
|
return true; // If the entry in the spell_globals table has nothing set for the qglobal name
|
||||||
|
|
||||||
query = StringFormat("SELECT value FROM quest_globals "
|
query = StringFormat("SELECT value FROM quest_globals "
|
||||||
"WHERE charid = %i AND name = '%s'",
|
"WHERE charid = %i AND name = '%s'",
|
||||||
char_ID, spell_Global_Name.c_str());
|
char_id, spell_global_name.c_str());
|
||||||
results = database.QueryDatabase(query);
|
results = database.QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
Log(Logs::General, Logs::Error, "Spell ID %i query of spell_globals with Name: '%s' Value: '%i' failed", spell_ID, spell_Global_Name.c_str(), spell_Global_Value);
|
Log(Logs::General, Logs::Error, "Spell ID %i query of spell_globals with Name: '%s' Value: '%i' failed", spell_id, spell_global_name.c_str(), spell_global_value);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results.RowCount() != 1) {
|
if (results.RowCount() != 1) {
|
||||||
Log(Logs::General, Logs::Error, "Char ID: %i does not have the Qglobal Name: '%s' for Spell ID %i", char_ID, spell_Global_Name.c_str(), spell_ID);
|
Log(Logs::General, Logs::Error, "Char ID: %i does not have the Qglobal Name: '%s' for Spell ID %i", char_id, spell_global_name.c_str(), spell_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
row = results.begin();
|
||||||
|
global_value = atoi(row[0]);
|
||||||
|
if (global_value == spell_global_value)
|
||||||
|
return true; // If the values match from both tables, allow the spell to be scribed
|
||||||
|
else if (global_value > spell_global_value)
|
||||||
|
return true; // Check if the qglobal value is greater than the require spellglobal value
|
||||||
|
|
||||||
|
// If no matching result found in qglobals, don't scribe this spell
|
||||||
|
Log(Logs::General, Logs::Error, "Char ID: %i Spell_globals Name: '%s' Value: '%i' did not match QGlobal Value: '%i' for Spell ID %i", char_id, spell_global_name.c_str(), spell_global_value, global_value, spell_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Client::SpellBucketCheck(uint16 spell_id, uint32 char_id) {
|
||||||
|
std::string spell_bucket_name;
|
||||||
|
int spell_bucket_value;
|
||||||
|
int bucket_value;
|
||||||
|
std::string query = StringFormat("SELECT key, value FROM spell_buckets WHERE spellid = %i", spell_id);
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (!results.Success())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (results.RowCount() != 1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
spell_bucket_name = row[0];
|
||||||
|
spell_bucket_value = atoi(row[1]);
|
||||||
|
if (spell_bucket_name.empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
query = StringFormat("SELECT value FROM data_buckets WHERE key = '%i-%s'", char_id, spell_bucket_name.c_str());
|
||||||
|
results = database.QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
Log(Logs::General, Logs::Error, "Spell bucket %s for spell ID %i for char ID %i failed.", spell_bucket_name.c_str(), spell_id, char_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results.RowCount() != 1) {
|
||||||
|
Log(Logs::General, Logs::Error, "Spell bucket %s does not exist for spell ID %i for char ID %i.", spell_bucket_name.c_str(), spell_id, char_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
row = results.begin();
|
row = results.begin();
|
||||||
|
|
||||||
global_Value = atoi(row[0]);
|
bucket_value = atoi(row[0]);
|
||||||
|
|
||||||
if (global_Value == spell_Global_Value)
|
if (bucket_value == spell_bucket_value)
|
||||||
return true; // If the values match from both tables, allow the spell to be scribed
|
return true; // If the values match from both tables, allow the spell to be scribed
|
||||||
else if (global_Value > spell_Global_Value)
|
else if (bucket_value > spell_bucket_value)
|
||||||
return true; // Check if the qglobal value is greater than the require spellglobal value
|
return true; // Check if the data bucket value is greater than the required spell bucket value
|
||||||
|
|
||||||
// If no matching result found in qglobals, don't scribe this spell
|
// If no matching result found in spell buckets, don't scribe this spell
|
||||||
Log(Logs::General, Logs::Error, "Char ID: %i Spell_globals Name: '%s' Value: '%i' did not match QGlobal Value: '%i' for Spell ID %i", char_ID, spell_Global_Name.c_str(), spell_Global_Value, global_Value, spell_ID);
|
Log(Logs::General, Logs::Error, "Spell bucket %s for spell ID %i for char ID %i did not match value %i.", spell_bucket_name.c_str(), spell_id, char_id, spell_bucket_value);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5605,8 +5648,7 @@ void NPC::InitializeBuffSlots()
|
|||||||
{
|
{
|
||||||
int max_slots = GetMaxTotalSlots();
|
int max_slots = GetMaxTotalSlots();
|
||||||
buffs = new Buffs_Struct[max_slots];
|
buffs = new Buffs_Struct[max_slots];
|
||||||
for(int x = 0; x < max_slots; ++x)
|
for (int x = 0; x < max_slots; ++x) {
|
||||||
{
|
|
||||||
buffs[x].spellid = SPELL_UNKNOWN;
|
buffs[x].spellid = SPELL_UNKNOWN;
|
||||||
buffs[x].UpdateClient = false;
|
buffs[x].UpdateClient = false;
|
||||||
}
|
}
|
||||||
|
|||||||
31
zone/zone.cpp
Normal file → Executable file
31
zone/zone.cpp
Normal file → Executable file
@ -896,7 +896,7 @@ bool Zone::Init(bool iStaticZone) {
|
|||||||
SetStaticZone(iStaticZone);
|
SetStaticZone(iStaticZone);
|
||||||
|
|
||||||
//load the zone config file.
|
//load the zone config file.
|
||||||
if (!LoadZoneCFG(zone->GetShortName(), zone->GetInstanceVersion(), true)) // try loading the zone name...
|
if (!LoadZoneCFG(zone->GetShortName(), zone->GetInstanceVersion())) // try loading the zone name...
|
||||||
LoadZoneCFG(zone->GetFileName(), zone->GetInstanceVersion()); // if that fails, try the file name, then load defaults
|
LoadZoneCFG(zone->GetFileName(), zone->GetInstanceVersion()); // if that fails, try the file name, then load defaults
|
||||||
|
|
||||||
if(RuleManager::Instance()->GetActiveRulesetID() != default_ruleset)
|
if(RuleManager::Instance()->GetActiveRulesetID() != default_ruleset)
|
||||||
@ -1057,35 +1057,27 @@ void Zone::ReloadStaticData() {
|
|||||||
zone->LoadNPCEmotes(&NPCEmoteList);
|
zone->LoadNPCEmotes(&NPCEmoteList);
|
||||||
|
|
||||||
//load the zone config file.
|
//load the zone config file.
|
||||||
if (!LoadZoneCFG(zone->GetShortName(), zone->GetInstanceVersion(), true)) // try loading the zone name...
|
if (!LoadZoneCFG(zone->GetShortName(), zone->GetInstanceVersion())) // try loading the zone name...
|
||||||
LoadZoneCFG(zone->GetFileName(), zone->GetInstanceVersion()); // if that fails, try the file name, then load defaults
|
LoadZoneCFG(zone->GetFileName(), zone->GetInstanceVersion()); // if that fails, try the file name, then load defaults
|
||||||
|
|
||||||
Log(Logs::General, Logs::Status, "Zone Static Data Reloaded.");
|
Log(Logs::General, Logs::Status, "Zone Static Data Reloaded.");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Zone::LoadZoneCFG(const char* filename, uint16 instance_id, bool DontLoadDefault)
|
bool Zone::LoadZoneCFG(const char* filename, uint16 instance_id)
|
||||||
{
|
{
|
||||||
|
|
||||||
memset(&newzone_data, 0, sizeof(NewZone_Struct));
|
memset(&newzone_data, 0, sizeof(NewZone_Struct));
|
||||||
if(instance_id == 0)
|
|
||||||
{
|
|
||||||
map_name = nullptr;
|
|
||||||
if(!database.GetZoneCFG(database.GetZoneID(filename), 0, &newzone_data, can_bind,
|
|
||||||
can_combat, can_levitate, can_castoutdoor, is_city, is_hotzone, allow_mercs, zone_type, default_ruleset, &map_name))
|
|
||||||
{
|
|
||||||
Log(Logs::General, Logs::Error, "Error loading the Zone Config.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Fall back to base zone if we don't find the instance version.
|
|
||||||
map_name = nullptr;
|
map_name = nullptr;
|
||||||
|
|
||||||
if(!database.GetZoneCFG(database.GetZoneID(filename), instance_id, &newzone_data, can_bind,
|
if(!database.GetZoneCFG(database.GetZoneID(filename), instance_id, &newzone_data, can_bind,
|
||||||
can_combat, can_levitate, can_castoutdoor, is_city, is_hotzone, allow_mercs, zone_type, default_ruleset, &map_name))
|
can_combat, can_levitate, can_castoutdoor, is_city, is_hotzone, allow_mercs, zone_type, default_ruleset, &map_name))
|
||||||
|
{
|
||||||
|
// If loading a non-zero instance failed, try loading the default
|
||||||
|
if (instance_id != 0)
|
||||||
{
|
{
|
||||||
safe_delete_array(map_name);
|
safe_delete_array(map_name);
|
||||||
if(!database.GetZoneCFG(database.GetZoneID(filename), 0, &newzone_data, can_bind,
|
if(!database.GetZoneCFG(database.GetZoneID(filename), 0, &newzone_data, can_bind, can_combat, can_levitate,
|
||||||
can_combat, can_levitate, can_castoutdoor, is_city, is_hotzone, allow_mercs, zone_type, default_ruleset, &map_name))
|
can_castoutdoor, is_city, is_hotzone, allow_mercs, zone_type, default_ruleset, &map_name))
|
||||||
{
|
{
|
||||||
Log(Logs::General, Logs::Error, "Error loading the Zone Config.");
|
Log(Logs::General, Logs::Error, "Error loading the Zone Config.");
|
||||||
return false;
|
return false;
|
||||||
@ -1277,7 +1269,8 @@ bool Zone::Process() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Weather_Timer->Check()){
|
if(Weather_Timer->Check())
|
||||||
|
{
|
||||||
Weather_Timer->Disable();
|
Weather_Timer->Disable();
|
||||||
this->ChangeWeather();
|
this->ChangeWeather();
|
||||||
}
|
}
|
||||||
|
|||||||
2
zone/zone.h
Normal file → Executable file
2
zone/zone.h
Normal file → Executable file
@ -94,7 +94,7 @@ public:
|
|||||||
bool is_zone_time_localized;
|
bool is_zone_time_localized;
|
||||||
|
|
||||||
bool Init(bool iStaticZone);
|
bool Init(bool iStaticZone);
|
||||||
bool LoadZoneCFG(const char* filename, uint16 instance_id, bool DontLoadDefault = false);
|
bool LoadZoneCFG(const char* filename, uint16 instance_id);
|
||||||
bool SaveZoneCFG();
|
bool SaveZoneCFG();
|
||||||
bool IsLoaded();
|
bool IsLoaded();
|
||||||
bool IsPVPZone() { return pvpzone; }
|
bool IsPVPZone() { return pvpzone; }
|
||||||
|
|||||||
@ -2638,7 +2638,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load
|
|||||||
temp_npctype_data->spellscale = atoi(row[86]);
|
temp_npctype_data->spellscale = atoi(row[86]);
|
||||||
temp_npctype_data->healscale = atoi(row[87]);
|
temp_npctype_data->healscale = atoi(row[87]);
|
||||||
temp_npctype_data->no_target_hotkey = atoi(row[88]) == 1 ? true: false;
|
temp_npctype_data->no_target_hotkey = atoi(row[88]) == 1 ? true: false;
|
||||||
temp_npctype_data->raid_target = atoi(row[89]) == 0 ? false: true;
|
temp_npctype_data->raid_target = atoi(row[89]) == 0 ? false : true;
|
||||||
temp_npctype_data->attack_delay = atoi(row[90]) * 100; // TODO: fix DB
|
temp_npctype_data->attack_delay = atoi(row[90]) * 100; // TODO: fix DB
|
||||||
temp_npctype_data->light = (atoi(row[91]) & 0x0F);
|
temp_npctype_data->light = (atoi(row[91]) & 0x0F);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user