mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 18:51:29 +00:00
Added new data bucket and quest functionality.
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.
This commit is contained in:
parent
f4dee67d7c
commit
8ae9c99f3d
@ -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
|
||||||
@ -342,7 +343,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 ...
|
||||||
|
|||||||
@ -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 9131
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9021
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9021
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -384,6 +384,7 @@
|
|||||||
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 COLUMNS FROM `name_filter` LIKE 'id'|empty|
|
9130|2018_11_25_name_filter_update.sql|SHOW COLUMNS FROM `name_filter` LIKE 'id'|empty|
|
||||||
|
9131|2018_12_13_spell_buckets.sql|SHOW TABLES LIKE 'spell_buckets'|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.');
|
||||||
@ -85,6 +85,7 @@ reports
|
|||||||
respawn_times
|
respawn_times
|
||||||
sharedbank
|
sharedbank
|
||||||
spell_globals
|
spell_globals
|
||||||
|
spell_buckets
|
||||||
timers
|
timers
|
||||||
trader
|
trader
|
||||||
trader_audit
|
trader_audit
|
||||||
|
|||||||
@ -773,8 +773,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; }
|
||||||
|
|||||||
28
zone/exp.cpp
28
zone/exp.cpp
@ -695,6 +695,18 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(RuleB(Character, PerCharacterBucketMaxLevel)){
|
||||||
|
uint32 MaxLevel = GetCharMaxLevelFromBucket();
|
||||||
|
if(MaxLevel){
|
||||||
|
if(GetLevel() >= MaxLevel){
|
||||||
|
uint32 expneeded = GetEXPForLevel(MaxLevel);
|
||||||
|
if(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};
|
||||||
@ -1133,6 +1145,22 @@ uint32 Client::GetCharMaxLevelFromQGlobal() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results.RowCount() > 0) {
|
||||||
|
auto row = results.begin();
|
||||||
|
return atoi(row[0]);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
uint32 Client::GetRequiredAAExperience() {
|
uint32 Client::GetRequiredAAExperience() {
|
||||||
#ifdef LUA_EQEMU
|
#ifdef LUA_EQEMU
|
||||||
uint32 lua_ret = 0;
|
uint32 lua_ret = 0;
|
||||||
|
|||||||
@ -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) {
|
||||||
else {
|
SpellBucketCheckResult = initiator->SpellBucketCheck(spell_id, char_id);
|
||||||
initiator->ScribeSpell(curspell, book_slot);
|
if (SpellBucketCheckResult) {
|
||||||
|
initiator->ScribeSpell(spell_id, book_slot);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
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
|
||||||
@ -2661,6 +2681,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();
|
||||||
@ -2670,6 +2694,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();
|
||||||
@ -2710,6 +2738,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();
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -5154,14 +5154,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
|
||||||
@ -5171,37 +5168,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user