diff options
author | Shauren <shauren.trinity@gmail.com> | 2015-01-16 23:32:41 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2015-01-16 23:32:41 +0100 |
commit | 469b836114cd1530d93aa946f6f6e1f995e091ab (patch) | |
tree | 6e3d6cc62063599931056a12a0128a14c428a166 | |
parent | 44b2e520218f3d0d1969efb7fa22c869e5c7833f (diff) |
Core/Auras: Fixed saving all aura effect values to database
-rw-r--r-- | sql/base/characters_database.sql | 107 | ||||
-rw-r--r-- | sql/updates/characters/2015_01_16_00_characters.sql | 67 | ||||
-rw-r--r-- | src/server/game/Entities/Pet/Pet.cpp | 182 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 170 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 3 | ||||
-rw-r--r-- | src/server/game/Handlers/CharacterHandler.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.cpp | 30 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.h | 36 | ||||
-rw-r--r-- | src/server/shared/Database/Implementation/CharacterDatabase.cpp | 23 | ||||
-rw-r--r-- | src/server/shared/Database/Implementation/CharacterDatabase.h | 6 |
10 files changed, 428 insertions, 200 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql index 88327122f26..aa5ec6f9c5a 100644 --- a/sql/base/characters_database.sql +++ b/sql/base/characters_database.sql @@ -483,22 +483,16 @@ DROP TABLE IF EXISTS `character_aura`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `character_aura` ( `guid` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier', - `caster_guid` binary(16) NOT NULL COMMENT 'Full Global Unique Identifier', - `item_guid` binary(16) NOT NULL DEFAULT '0', - `spell` mediumint(8) unsigned NOT NULL DEFAULT '0', - `effect_mask` tinyint(3) unsigned NOT NULL DEFAULT '0', - `recalculate_mask` tinyint(3) unsigned NOT NULL DEFAULT '0', - `stackcount` tinyint(3) unsigned NOT NULL DEFAULT '1', - `amount0` int(11) NOT NULL DEFAULT '0', - `amount1` int(11) NOT NULL DEFAULT '0', - `amount2` int(11) NOT NULL DEFAULT '0', - `base_amount0` int(11) NOT NULL DEFAULT '0', - `base_amount1` int(11) NOT NULL DEFAULT '0', - `base_amount2` int(11) NOT NULL DEFAULT '0', - `maxduration` int(11) NOT NULL DEFAULT '0', - `remaintime` int(11) NOT NULL DEFAULT '0', - `remaincharges` tinyint(3) unsigned NOT NULL DEFAULT '0', - PRIMARY KEY (`guid`,`caster_guid`,`item_guid`,`spell`,`effect_mask`) + `casterGuid` binary(16) NOT NULL COMMENT 'Full Global Unique Identifier', + `itemGuid` binary(16) NOT NULL, + `spell` int(10) unsigned NOT NULL, + `effectMask` int(10) unsigned NOT NULL, + `recalculateMask` int(10) unsigned NOT NULL DEFAULT '0', + `stackCount` tinyint(3) unsigned NOT NULL DEFAULT '1', + `maxDuration` int(11) NOT NULL DEFAULT '0', + `remainTime` int(11) NOT NULL DEFAULT '0', + `remainCharges` tinyint(3) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`guid`,`casterGuid`,`itemGuid`,`spell`,`effectMask`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System'; /*!40101 SET character_set_client = @saved_cs_client */; @@ -512,6 +506,34 @@ LOCK TABLES `character_aura` WRITE; UNLOCK TABLES; -- +-- Table structure for table `character_aura_effect` +-- + +DROP TABLE IF EXISTS `character_aura_effect`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `character_aura_effect` ( + `guid` bigint(20) unsigned NOT NULL, + `casterGuid` binary(16) NOT NULL COMMENT 'Full Global Unique Identifier' , + `itemGuid` binary(16) NOT NULL, + `spell` int(10) unsigned NOT NULL , + `effectMask` int(10) unsigned NOT NULL, + `effectIndex` tinyint(3) unsigned NOT NULL, + `amount` int(11) NOT NULL DEFAULT 0, + `baseAmount` int(11) NOT NULL DEFAULT 0, +PRIMARY KEY (`guid`,`casterGuid`,`itemGuid`,`spell`,`effectMask`,`effectIndex`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System'; + +-- +-- Dumping data for table `character_aura_effect` +-- + +LOCK TABLES `character_aura_effect` WRITE; +/*!40000 ALTER TABLE `character_aura_effect` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_aura_effect` ENABLE KEYS */; +UNLOCK TABLES; + +-- -- Table structure for table `character_banned` -- @@ -2476,22 +2498,16 @@ DROP TABLE IF EXISTS `pet_aura`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `pet_aura` ( - `guid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier', - `caster_guid` binary(16) NOT NULL DEFAULT '0' COMMENT 'Full Global Unique Identifier', - `spell` mediumint(8) unsigned NOT NULL DEFAULT '0', - `effect_mask` tinyint(3) unsigned NOT NULL DEFAULT '0', - `recalculate_mask` tinyint(3) unsigned NOT NULL DEFAULT '0', - `stackcount` tinyint(3) unsigned NOT NULL DEFAULT '1', - `amount0` mediumint(8) NOT NULL, - `amount1` mediumint(8) NOT NULL, - `amount2` mediumint(8) NOT NULL, - `base_amount0` mediumint(8) NOT NULL, - `base_amount1` mediumint(8) NOT NULL, - `base_amount2` mediumint(8) NOT NULL, - `maxduration` int(11) NOT NULL DEFAULT '0', - `remaintime` int(11) NOT NULL DEFAULT '0', - `remaincharges` tinyint(3) unsigned NOT NULL DEFAULT '0', - PRIMARY KEY (`guid`,`spell`,`effect_mask`) + `guid` int(10) unsigned NOT NULL COMMENT 'Global Unique Identifier', + `casterGuid` binary(16) NOT NULL COMMENT 'Full Global Unique Identifier', + `spell` int(10) unsigned NOT NULL, + `effectMask` int(10) unsigned NOT NULL, + `recalculateMask` int(10) unsigned NOT NULL DEFAULT 0, + `stackCount` tinyint(3) unsigned NOT NULL DEFAULT 1, + `maxDuration` int(11) NOT NULL DEFAULT 0, + `remainTime` int(11) NOT NULL DEFAULT 0, + `remainCharges` tinyint(3) unsigned NOT NULL DEFAULT 0, + PRIMARY KEY (`guid`,`spell`,`effectMask`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Pet System'; /*!40101 SET character_set_client = @saved_cs_client */; @@ -2505,6 +2521,33 @@ LOCK TABLES `pet_aura` WRITE; UNLOCK TABLES; -- +-- Table structure for table `pet_aura_effect` +-- + +DROP TABLE IF EXISTS `pet_aura_effect`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `pet_aura_effect` ( + `guid` int(10) unsigned NOT NULL COMMENT 'Global Unique Identifier', + `casterGuid` binary(16) NOT NULL COMMENT 'Full Global Unique Identifier' , + `spell` int(10) unsigned NOT NULL, + `effectMask` int(10) unsigned NOT NULL, + `effectIndex` tinyint(3) unsigned NOT NULL, + `amount` int(11) NOT NULL DEFAULT 0, + `baseAmount` int(11) NOT NULL DEFAULT 0, +PRIMARY KEY (`guid`,`casterGuid`,`spell`,`effectMask`,`effectIndex`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Pet System'; + +-- +-- Dumping data for table `pet_aura_effect` +-- + +LOCK TABLES `pet_aura_effect` WRITE; +/*!40000 ALTER TABLE `pet_aura_effect` DISABLE KEYS */; +/*!40000 ALTER TABLE `pet_aura_effect` ENABLE KEYS */; +UNLOCK TABLES; + +-- -- Table structure for table `pet_spell` -- diff --git a/sql/updates/characters/2015_01_16_00_characters.sql b/sql/updates/characters/2015_01_16_00_characters.sql new file mode 100644 index 00000000000..b3557fa1694 --- /dev/null +++ b/sql/updates/characters/2015_01_16_00_characters.sql @@ -0,0 +1,67 @@ +-- +-- Table structure for table `character_aura_effect` +-- + +DROP TABLE IF EXISTS `character_aura_effect`; +CREATE TABLE `character_aura_effect` ( + `guid` bigint(20) unsigned NOT NULL COMMENT 'Global Unique Identifier', + `casterGuid` binary(16) NOT NULL COMMENT 'Full Global Unique Identifier' , + `itemGuid` binary(16) NOT NULL, + `spell` int(10) unsigned NOT NULL , + `effectMask` int(10) unsigned NOT NULL, + `effectIndex` tinyint(3) unsigned NOT NULL, + `amount` int(11) NOT NULL DEFAULT 0, + `baseAmount` int(11) NOT NULL DEFAULT 0, +PRIMARY KEY (`guid`,`casterGuid`,`itemGuid`,`spell`,`effectMask`,`effectIndex`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System'; + +-- +-- Table structure for table `pet_aura_effect` +-- + +DROP TABLE IF EXISTS `pet_aura_effect`; +CREATE TABLE `pet_aura_effect` ( + `guid` int(10) unsigned NOT NULL COMMENT 'Global Unique Identifier', + `casterGuid` binary(16) NOT NULL COMMENT 'Full Global Unique Identifier' , + `spell` int(10) unsigned NOT NULL, + `effectMask` int(10) unsigned NOT NULL, + `effectIndex` tinyint(3) unsigned NOT NULL, + `amount` int(11) NOT NULL DEFAULT 0, + `baseAmount` int(11) NOT NULL DEFAULT 0, +PRIMARY KEY (`guid`,`casterGuid`,`spell`,`effectMask`,`effectIndex`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Pet System'; + +TRUNCATE `character_aura`; +ALTER TABLE `character_aura` + CHANGE `caster_guid` `casterGuid` binary(16) NOT NULL COMMENT 'Full Global Unique Identifier', + CHANGE `item_guid` `itemGuid` binary(16) NOT NULL, + CHANGE `spell` `spell` int(10) unsigned NOT NULL, + CHANGE `effect_mask` `effectMask` int(10) unsigned NOT NULL, + CHANGE `recalculate_mask` `recalculateMask` int(10) unsigned NOT NULL DEFAULT 0, + CHANGE `stackcount` `stackCount` tinyint(3) unsigned NOT NULL DEFAULT 1, + DROP `amount0`, + DROP `amount1`, + DROP `amount2`, + DROP `base_amount0`, + DROP `base_amount1`, + DROP `base_amount2`, + CHANGE `maxDuration` `maxDuration` int(11) NOT NULL DEFAULT 0, + CHANGE `remainTime` `remainTime` int(11) NOT NULL DEFAULT 0, + CHANGE `remainCharges` `remainCharges` tinyint(3) unsigned NOT NULL DEFAULT 0; + +TRUNCATE `pet_aura`; +ALTER TABLE `pet_aura` + CHANGE `caster_guid` `casterGuid` binary(16) NOT NULL COMMENT 'Full Global Unique Identifier', + CHANGE `spell` `spell` int(10) unsigned NOT NULL, + CHANGE `effect_mask` `effectMask` int(10) unsigned NOT NULL, + CHANGE `recalculate_mask` `recalculateMask` int(10) unsigned NOT NULL DEFAULT 0, + CHANGE `stackcount` `stackCount` tinyint(3) unsigned NOT NULL DEFAULT 1, + DROP `amount0`, + DROP `amount1`, + DROP `amount2`, + DROP `base_amount0`, + DROP `base_amount1`, + DROP `base_amount2`, + CHANGE `maxDuration` `maxDuration` int(11) NOT NULL DEFAULT 0, + CHANGE `remainTime` `remainTime` int(11) NOT NULL DEFAULT 0, + CHANGE `remainCharges` `remainCharges` tinyint(3) unsigned NOT NULL DEFAULT 0; diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index a030953c0a0..2c416cf4da7 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -495,6 +495,10 @@ void Pet::DeleteFromDB(uint32 guidlow) stmt->setUInt32(0, guidlow); trans->Append(stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PET_AURA_EFFECTS); + stmt->setUInt32(0, guidlow); + trans->Append(stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PET_AURAS); stmt->setUInt32(0, guidlow); trans->Append(stmt); @@ -1212,83 +1216,116 @@ void Pet::_LoadAuras(uint32 timediff) { TC_LOG_DEBUG("entities.pet", "Loading auras for %s", GetGUID().ToString().c_str()); - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_AURA); + /* + 0 1 2 3 4 5 + SELECT casterGuid, spell, effectMask, effectIndex, amount, baseAmount FROM pet_aura_effect WHERE guid = ? + */ + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_AURA_EFFECT); stmt->setUInt32(0, m_charmInfo->GetPetNumber()); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - if (result) + ObjectGuid casterGuid, itemGuid; + std::map<AuraKey, AuraLoadEffectInfo> effectInfo; + if (PreparedQueryResult effectResult = CharacterDatabase.Query(stmt)) { - ObjectGuid caster_guid; do { - int32 damage[3]; - int32 baseDamage[3]; - Field* fields = result->Fetch(); - caster_guid.SetRawValue(fields[0].GetBinary()); + Field* fields = effectResult->Fetch(); + uint32 effectIndex = fields[3].GetUInt8(); + if (effectIndex < MAX_SPELL_EFFECTS) + { + casterGuid.SetRawValue(fields[0].GetBinary()); + if (casterGuid.IsEmpty()) + casterGuid = GetGUID(); + + AuraKey key{ casterGuid, itemGuid, fields[1].GetUInt32(), fields[2].GetUInt32() }; + AuraLoadEffectInfo& info = effectInfo[key]; + info.Amounts[effectIndex] = fields[4].GetInt32(); + info.BaseAmounts[effectIndex] = fields[5].GetInt32(); + } + } while (effectResult->NextRow()); + } + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_AURA); + stmt->setUInt32(0, m_charmInfo->GetPetNumber()); + + /* + 0 1 2 3 4 5 6 7 + SELECT casterGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges FROM pet_aura WHERE guid = ? + */ + if (PreparedQueryResult auraResult = CharacterDatabase.Query(stmt)) + { + do + { + Field* fields = auraResult->Fetch(); // NULL guid stored - pet is the caster of the spell - see Pet::_SaveAuras - if (!caster_guid) - caster_guid = GetGUID(); - uint32 spellid = fields[1].GetUInt32(); - uint8 effmask = fields[2].GetUInt8(); - uint8 recalculatemask = fields[3].GetUInt8(); - uint8 stackcount = fields[4].GetUInt8(); - damage[0] = fields[5].GetInt32(); - damage[1] = fields[6].GetInt32(); - damage[2] = fields[7].GetInt32(); - baseDamage[0] = fields[8].GetInt32(); - baseDamage[1] = fields[9].GetInt32(); - baseDamage[2] = fields[10].GetInt32(); - int32 maxduration = fields[11].GetInt32(); - int32 remaintime = fields[12].GetInt32(); - uint8 remaincharges = fields[13].GetUInt8(); - - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid); + casterGuid.SetRawValue(fields[0].GetBinary()); + if (casterGuid.IsEmpty()) + casterGuid = GetGUID(); + + AuraKey key{ casterGuid, itemGuid, fields[1].GetUInt32(), fields[2].GetUInt32() }; + uint32 recalculateMask = fields[3].GetUInt32(); + uint8 stackCount = fields[4].GetUInt8(); + int32 maxDuration = fields[5].GetInt32(); + int32 remainTime = fields[6].GetInt32(); + uint8 remainCharges = fields[7].GetUInt8(); + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(key.SpellId); if (!spellInfo) { - TC_LOG_ERROR("entities.pet", "Unknown aura (spellid %u), ignore.", spellid); + TC_LOG_ERROR("entities.pet", "Unknown aura (spellid %u), ignore.", key.SpellId); continue; } // negative effects should continue counting down after logout - if (remaintime != -1 && !spellInfo->IsPositive()) + if (remainTime != -1 && !spellInfo->IsPositive()) { - if (remaintime/IN_MILLISECONDS <= int32(timediff)) + if (remainTime/IN_MILLISECONDS <= int32(timediff)) continue; - remaintime -= timediff*IN_MILLISECONDS; + remainTime -= timediff*IN_MILLISECONDS; } - // prevent wrong values of remaincharges + // prevent wrong values of remainCharges if (spellInfo->ProcCharges) { - if (remaincharges <= 0 || remaincharges > spellInfo->ProcCharges) - remaincharges = spellInfo->ProcCharges; + // we have no control over the order of applying auras and modifiers allow auras + // to have more charges than value in SpellInfo + if (remainCharges <= 0/* || remainCharges > spellproto->procCharges*/) + remainCharges = spellInfo->ProcCharges; } else - remaincharges = 0; + remainCharges = 0; - if (Aura* aura = Aura::TryCreate(spellInfo, effmask, this, NULL, &baseDamage[0], NULL, caster_guid)) + AuraLoadEffectInfo& info = effectInfo[key]; + if (Aura* aura = Aura::TryCreate(spellInfo, key.EffectMask, this, NULL, info.BaseAmounts.data(), NULL, casterGuid)) { if (!aura->CanBeSaved()) { aura->Remove(); continue; } - aura->SetLoadedState(maxduration, remaintime, remaincharges, stackcount, recalculatemask, &damage[0]); + + aura->SetLoadedState(maxDuration, remainTime, remainCharges, stackCount, recalculateMask, info.Amounts.data()); aura->ApplyForTargets(); - TC_LOG_INFO("entities.pet", "Added aura spellid %u, effectmask %u", spellInfo->Id, effmask); + TC_LOG_INFO("entities.pet", "Added aura spellid %u, effectmask %u", spellInfo->Id, key.EffectMask); } } - while (result->NextRow()); + while (auraResult->NextRow()); } } void Pet::_SaveAuras(SQLTransaction& trans) { - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PET_AURAS); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PET_AURA_EFFECTS); stmt->setUInt32(0, m_charmInfo->GetPetNumber()); trans->Append(stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PET_AURAS); + stmt->setUInt32(0, m_charmInfo->GetPetNumber()); + trans->Append(stmt); + + uint8 index; for (AuraMap::const_iterator itr = m_ownedAuras.begin(); itr != m_ownedAuras.end(); ++itr) { // check if the aura has to be saved @@ -1296,51 +1333,42 @@ void Pet::_SaveAuras(SQLTransaction& trans) continue; Aura* aura = itr->second; - - int32 damage[MAX_SPELL_EFFECTS]; - int32 baseDamage[MAX_SPELL_EFFECTS]; - uint8 effMask = 0; - uint8 recalculateMask = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if (aura->GetEffect(i)) - { - baseDamage[i] = aura->GetEffect(i)->GetBaseAmount(); - damage[i] = aura->GetEffect(i)->GetAmount(); - effMask |= (1<<i); - if (aura->GetEffect(i)->CanBeRecalculated()) - recalculateMask |= (1<<i); - } - else - { - baseDamage[i] = 0; - damage[i] = 0; - } - } + uint32 recalculateMask = 0; + AuraKey key = aura->GenerateKey(recalculateMask); // don't save guid of caster in case we are caster of the spell - guid for pet is generated every pet load, so it won't match saved guid anyways - ObjectGuid casterGUID = (itr->second->GetCasterGUID() == GetGUID()) ? ObjectGuid::Empty : itr->second->GetCasterGUID(); - - uint8 index = 0; + if (key.Caster == GetGUID()) + key.Caster.Clear(); + index = 0; stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PET_AURA); stmt->setUInt32(index++, m_charmInfo->GetPetNumber()); - stmt->setBinary(index++, casterGUID.GetRawValue()); - stmt->setUInt32(index++, itr->second->GetId()); - stmt->setUInt8(index++, effMask); - stmt->setUInt8(index++, recalculateMask); - stmt->setUInt8(index++, itr->second->GetStackAmount()); - stmt->setInt32(index++, damage[0]); - stmt->setInt32(index++, damage[1]); - stmt->setInt32(index++, damage[2]); - stmt->setInt32(index++, baseDamage[0]); - stmt->setInt32(index++, baseDamage[1]); - stmt->setInt32(index++, baseDamage[2]); - stmt->setInt32(index++, itr->second->GetMaxDuration()); - stmt->setInt32(index++, itr->second->GetDuration()); - stmt->setUInt8(index++, itr->second->GetCharges()); - + stmt->setBinary(index++, key.Caster.GetRawValue()); + stmt->setUInt32(index++, key.SpellId); + stmt->setUInt32(index++, key.EffectMask); + stmt->setUInt32(index++, recalculateMask); + stmt->setUInt8(index++, aura->GetStackAmount()); + stmt->setInt32(index++, aura->GetMaxDuration()); + stmt->setInt32(index++, aura->GetDuration()); + stmt->setUInt8(index++, aura->GetCharges()); trans->Append(stmt); + + for (AuraEffect const* effect : aura->GetAuraEffects()) + { + if (effect) + { + index = 0; + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PET_AURA_EFFECT); + stmt->setUInt32(index++, m_charmInfo->GetPetNumber()); + stmt->setBinary(index++, key.Caster.GetRawValue()); + stmt->setUInt32(index++, key.SpellId); + stmt->setUInt32(index++, key.EffectMask); + stmt->setUInt8(index++, effect->GetEffIndex()); + stmt->setInt32(index++, effect->GetAmount()); + stmt->setInt32(index++, effect->GetBaseAmount()); + trans->Append(stmt); + } + } } } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 733df1048b3..5f1042bb93a 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -4594,6 +4594,10 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe stmt->setUInt64(0, guid); trans->Append(stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_AURA_EFFECT); + stmt->setUInt64(0, guid); + trans->Append(stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_AURA); stmt->setUInt64(0, guid); trans->Append(stmt); @@ -17209,7 +17213,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) _LoadSpells(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_SPELLS)); _LoadGlyphs(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GLYPHS)); - _LoadAuras(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_AURAS), time_diff); + _LoadAuras(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_AURAS), holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_AURA_EFFECTS), time_diff); _LoadGlyphAuras(); // add ghost flag (must be after aura load: PLAYER_FLAGS_GHOST set in aura) if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) @@ -17474,67 +17478,83 @@ void Player::_LoadActions(PreparedQueryResult result) } } -void Player::_LoadAuras(PreparedQueryResult result, uint32 timediff) +void Player::_LoadAuras(PreparedQueryResult auraResult, PreparedQueryResult effectResult, uint32 timediff) { TC_LOG_DEBUG("entities.player.loading", "Loading auras for %s", GetGUID().ToString().c_str()); - /* 0 1 2 3 4 5 6 7 8 9 10 - QueryResult* result = CharacterDatabase.PQuery("SELECT caster_guid, spell, effect_mask, recalculate_mask, stackcount, amount0, amount1, amount2, base_amount0, base_amount1, base_amount2, - 11 12 13 - maxduration, remaintime, remaincharges FROM character_aura WHERE guid = '%u'", GetGUIDLow()); + /* + 0 1 2 3 4 5 6 + SELECT casterGuid, itemGuid, spell, effectMask, effectIndex, amount, baseAmount FROM character_aura_effect WHERE guid = ? */ - if (result) + ObjectGuid casterGuid, itemGuid; + std::map<AuraKey, AuraLoadEffectInfo> effectInfo; + if (effectResult) { - ObjectGuid caster_guid; do { - Field* fields = result->Fetch(); - int32 damage[3]; - int32 baseDamage[3]; - caster_guid.SetRawValue(fields[0].GetBinary()); - uint32 spellid = fields[1].GetUInt32(); - uint8 effmask = fields[2].GetUInt8(); - uint8 recalculatemask = fields[3].GetUInt8(); - uint8 stackcount = fields[4].GetUInt8(); - damage[0] = fields[5].GetInt32(); - damage[1] = fields[6].GetInt32(); - damage[2] = fields[7].GetInt32(); - baseDamage[0] = fields[8].GetInt32(); - baseDamage[1] = fields[9].GetInt32(); - baseDamage[2] = fields[10].GetInt32(); - int32 maxduration = fields[11].GetInt32(); - int32 remaintime = fields[12].GetInt32(); - uint8 remaincharges = fields[13].GetUInt8(); - - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid); + Field* fields = effectResult->Fetch(); + uint32 effectIndex = fields[4].GetUInt8(); + if (effectIndex < MAX_SPELL_EFFECTS) + { + casterGuid.SetRawValue(fields[0].GetBinary()); + itemGuid.SetRawValue(fields[1].GetBinary()); + AuraKey key{ casterGuid, itemGuid, fields[2].GetUInt32(), fields[3].GetUInt32() }; + AuraLoadEffectInfo& info = effectInfo[key]; + info.Amounts[effectIndex] = fields[5].GetInt32(); + info.BaseAmounts[effectIndex] = fields[6].GetInt32(); + } + } + while (effectResult->NextRow()); + } + + /* + 0 1 2 3 4 5 6 7 8 + SELECT casterGuid, itemGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges FROM character_aura WHERE guid = ? + */ + if (auraResult) + { + do + { + Field* fields = auraResult->Fetch(); + casterGuid.SetRawValue(fields[0].GetBinary()); + itemGuid.SetRawValue(fields[1].GetBinary()); + AuraKey key{ casterGuid, itemGuid, fields[2].GetUInt32(), fields[3].GetUInt32() }; + uint32 recalculateMask = fields[4].GetUInt32(); + uint8 stackCount = fields[5].GetUInt8(); + int32 maxDuration = fields[6].GetInt32(); + int32 remainTime = fields[7].GetInt32(); + uint8 remainCharges = fields[8].GetUInt8(); + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(key.SpellId); if (!spellInfo) { - TC_LOG_ERROR("entities.player", "Unknown aura (spellid %u), ignore.", spellid); + TC_LOG_ERROR("entities.player", "Unknown aura (spellid %u), ignore.", key.SpellId); continue; } // negative effects should continue counting down after logout - if (remaintime != -1 && !spellInfo->IsPositive()) + if (remainTime != -1 && !spellInfo->IsPositive()) { - if (remaintime/IN_MILLISECONDS <= int32(timediff)) + if (remainTime/IN_MILLISECONDS <= int32(timediff)) continue; - remaintime -= timediff*IN_MILLISECONDS; + remainTime -= timediff*IN_MILLISECONDS; } - // prevent wrong values of remaincharges + // prevent wrong values of remainCharges if (spellInfo->ProcCharges) { // we have no control over the order of applying auras and modifiers allow auras // to have more charges than value in SpellInfo - if (remaincharges <= 0/* || remaincharges > spellproto->procCharges*/) - remaincharges = spellInfo->ProcCharges; + if (remainCharges <= 0/* || remainCharges > spellproto->procCharges*/) + remainCharges = spellInfo->ProcCharges; } else - remaincharges = 0; + remainCharges = 0; - if (Aura* aura = Aura::TryCreate(spellInfo, effmask, this, NULL, &baseDamage[0], NULL, caster_guid)) + AuraLoadEffectInfo& info = effectInfo[key]; + if (Aura* aura = Aura::TryCreate(spellInfo, key.EffectMask, this, NULL, info.BaseAmounts.data(), NULL, casterGuid)) { if (!aura->CanBeSaved()) { @@ -17542,12 +17562,12 @@ void Player::_LoadAuras(PreparedQueryResult result, uint32 timediff) continue; } - aura->SetLoadedState(maxduration, remaintime, remaincharges, stackcount, recalculatemask, &damage[0]); + aura->SetLoadedState(maxDuration, remainTime, remainCharges, stackCount, recalculateMask, info.Amounts.data()); aura->ApplyForTargets(); - TC_LOG_INFO("entities.player", "Added aura spellid %u, effectmask %u", spellInfo->Id, effmask); + TC_LOG_INFO("entities.player", "Added aura spellid %u, effectmask %u", spellInfo->Id, key.EffectMask); } } - while (result->NextRow()); + while (auraResult->NextRow()); } } @@ -19229,57 +19249,55 @@ void Player::_SaveActions(SQLTransaction& trans) void Player::_SaveAuras(SQLTransaction& trans) { - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_AURA); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_AURA_EFFECT); stmt->setUInt64(0, GetGUID().GetCounter()); trans->Append(stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_AURA); + stmt->setUInt64(0, GetGUID().GetCounter()); + trans->Append(stmt); + + uint8 index; for (AuraMap::const_iterator itr = m_ownedAuras.begin(); itr != m_ownedAuras.end(); ++itr) { if (!itr->second->CanBeSaved()) continue; Aura* aura = itr->second; + uint32 recalculateMask = 0; + AuraKey key = aura->GenerateKey(recalculateMask); - int32 damage[MAX_SPELL_EFFECTS]; - int32 baseDamage[MAX_SPELL_EFFECTS]; - uint8 effMask = 0; - uint8 recalculateMask = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if (AuraEffect const* effect = aura->GetEffect(i)) - { - baseDamage[i] = effect->GetBaseAmount(); - damage[i] = effect->GetAmount(); - effMask |= 1 << i; - if (effect->CanBeRecalculated()) - recalculateMask |= 1 << i; - } - else - { - baseDamage[i] = 0; - damage[i] = 0; - } - } - - uint8 index = 0; + index = 0; stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_AURA); stmt->setUInt64(index++, GetGUID().GetCounter()); - stmt->setBinary(index++, itr->second->GetCasterGUID().GetRawValue()); - stmt->setBinary(index++, itr->second->GetCastItemGUID().GetRawValue()); - stmt->setUInt32(index++, itr->second->GetId()); - stmt->setUInt8(index++, effMask); + stmt->setBinary(index++, key.Caster.GetRawValue()); + stmt->setBinary(index++, key.Item.GetRawValue()); + stmt->setUInt32(index++, key.SpellId); + stmt->setUInt32(index++, key.EffectMask); stmt->setUInt8(index++, recalculateMask); - stmt->setUInt8(index++, itr->second->GetStackAmount()); - stmt->setInt32(index++, damage[0]); - stmt->setInt32(index++, damage[1]); - stmt->setInt32(index++, damage[2]); - stmt->setInt32(index++, baseDamage[0]); - stmt->setInt32(index++, baseDamage[1]); - stmt->setInt32(index++, baseDamage[2]); - stmt->setInt32(index++, itr->second->GetMaxDuration()); - stmt->setInt32(index++, itr->second->GetDuration()); - stmt->setUInt8(index, itr->second->GetCharges()); + stmt->setUInt8(index++, aura->GetStackAmount()); + stmt->setInt32(index++, aura->GetMaxDuration()); + stmt->setInt32(index++, aura->GetDuration()); + stmt->setUInt8(index, aura->GetCharges()); trans->Append(stmt); + + for (AuraEffect const* effect : aura->GetAuraEffects()) + { + if (effect) + { + index = 0; + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_AURA_EFFECT); + stmt->setUInt64(index++, GetGUID().GetCounter()); + stmt->setBinary(index++, key.Caster.GetRawValue()); + stmt->setBinary(index++, key.Item.GetRawValue()); + stmt->setUInt32(index++, key.SpellId); + stmt->setUInt32(index++, key.EffectMask); + stmt->setUInt8(index++, effect->GetEffIndex()); + stmt->setInt32(index++, effect->GetAmount()); + stmt->setInt32(index++, effect->GetBaseAmount()); + trans->Append(stmt); + } + } } } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 9423b912548..8c36ba55010 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -908,6 +908,7 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOAD_GROUP, PLAYER_LOGIN_QUERY_LOAD_BOUND_INSTANCES, PLAYER_LOGIN_QUERY_LOAD_AURAS, + PLAYER_LOGIN_QUERY_LOAD_AURA_EFFECTS, PLAYER_LOGIN_QUERY_LOAD_SPELLS, PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS, PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES, @@ -2659,7 +2660,7 @@ class Player : public Unit, public GridObject<Player> /*********************************************************/ void _LoadActions(PreparedQueryResult result); - void _LoadAuras(PreparedQueryResult result, uint32 timediff); + void _LoadAuras(PreparedQueryResult auraResult, PreparedQueryResult effectResult, uint32 timediff); void _LoadGlyphAuras(); void _LoadBoundInstances(PreparedQueryResult result); void _LoadInventory(PreparedQueryResult result, uint32 timeDiff); diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 84e6ed34bb8..aca64f99f3b 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -93,6 +93,10 @@ bool LoginQueryHolder::Initialize() stmt->setUInt64(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_AURAS, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_AURA_EFFECTS); + stmt->setUInt64(0, lowGuid); + res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_AURA_EFFECTS, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_SPELL); stmt->setUInt64(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_SPELLS, stmt); diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 28c2927bd8b..1f2d599121e 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -398,7 +398,7 @@ void Aura::_InitEffects(uint32 effMask, Unit* caster, int32 *baseAmount) for (SpellEffectInfo const* effect : GetSpellEffectInfos()) { - if (effect && effMask & (uint8(1) << effect->EffectIndex)) + if (effect && effMask & (1 << effect->EffectIndex)) _effects[effect->EffectIndex] = new AuraEffect(this, effect->EffectIndex, baseAmount ? baseAmount + effect->EffectIndex : NULL, caster); } } @@ -1113,18 +1113,40 @@ int32 Aura::CalcDispelChance(Unit* auraTarget, bool offensive) const return 100 - resistChance; } -void Aura::SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, int32 *amount) +AuraKey Aura::GenerateKey(uint32& recalculateMask) const { - m_maxDuration = maxduration; + AuraKey key; + key.Caster = GetCasterGUID(); + key.Item = GetCastItemGUID(); + key.SpellId = GetId(); + key.EffectMask = 0; + recalculateMask = 0; + for (uint32 i = 0; i < _effects.size(); ++i) + { + if (AuraEffect const* effect = _effects[i]) + { + key.EffectMask |= 1 << i; + if (effect->CanBeRecalculated()) + recalculateMask |= 1 << i; + } + } + + return key; +} + +void Aura::SetLoadedState(int32 maxDuration, int32 duration, int32 charges, uint8 stackAmount, uint32 recalculateMask, int32* amount) +{ + m_maxDuration = maxDuration; m_duration = duration; m_procCharges = charges; m_isUsingCharges = m_procCharges != 0; - m_stackAmount = stackamount; + m_stackAmount = stackAmount; Unit* caster = GetCaster(); for (AuraEffect* effect : GetAuraEffects()) { if (!effect) continue; + effect->SetAmount(amount[effect->GetEffIndex()]); effect->SetCanBeRecalculated((recalculateMask & (1 << effect->GetEffIndex())) != 0); effect->CalculatePeriodic(caster, false, true); diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index 8841d887e86..3a05da9cd1e 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -91,6 +91,28 @@ class AuraApplication void ClientUpdate(bool remove = false); }; +#pragma pack(push, 1) +// Structure representing database aura primary key fields +struct AuraKey +{ + ObjectGuid Caster; + ObjectGuid Item; + uint32 SpellId; + uint32 EffectMask; + + bool operator<(AuraKey const& right) const + { + return memcmp(this, &right, sizeof(*this)) < 0; + } +}; + +struct AuraLoadEffectInfo +{ + std::array<int32, MAX_SPELL_EFFECTS> Amounts; + std::array<int32, MAX_SPELL_EFFECTS> BaseAmounts; +}; +#pragma pack(pop) + class Aura { friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); @@ -184,12 +206,21 @@ class Aura void UnregisterSingleTarget(); int32 CalcDispelChance(Unit* auraTarget, bool offensive) const; - void SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, int32 *baseAmount); + /** + * @fn AuraKey Aura::GenerateKey(uint32& recalculateMask) const + * + * @brief Fills a helper structure containing aura primary key for `character_aura`, `character_aura_effect`, `pet_aura`, `pet_aura_effect` tables. + * + * @param [out] recalculateMask Mask of effects that can be recalculated to store in database - not part of aura key. + * + * @return Aura key. + */ + AuraKey GenerateKey(uint32& recalculateMask) const; + void SetLoadedState(int32 maxDuration, int32 duration, int32 charges, uint8 stackAmount, uint32 recalculateMask, int32* amount); // helpers for aura effects bool HasEffect(uint8 effIndex) const { return GetEffect(effIndex) != NULL; } bool HasEffectType(AuraType type) const; - //AuraEffect* GetEffect(uint8 effIndex) const { ASSERT (effIndex < MAX_SPELL_EFFECTS); return Effects[effIndex]; } AuraEffect* GetEffect(uint32 index) const; uint32 GetEffectMask() const; void RecalculateAmountOfEffects(); @@ -335,4 +366,5 @@ class ChargeDropEvent : public BasicEvent Aura* _base; AuraRemoveMode _mode; }; + #endif diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index 5e914391bd9..9d7a09702eb 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -79,8 +79,8 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_GROUP_MEMBER, "SELECT guid FROM group_member WHERE memberGuid = ?", CONNECTION_BOTH); PrepareStatement(CHAR_SEL_CHARACTER_INSTANCE, "SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = ?", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_CHARACTER_AURAS, "SELECT caster_guid, spell, effect_mask, recalculate_mask, stackcount, amount0, amount1, amount2, " - "base_amount0, base_amount1, base_amount2, maxduration, remaintime, remaincharges FROM character_aura WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_CHARACTER_AURAS, "SELECT casterGuid, itemGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges FROM character_aura WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_CHARACTER_AURA_EFFECTS, "SELECT casterGuid, itemGuid, spell, effectMask, effectIndex, amount, baseAmount FROM character_aura_effect WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_SPELL, "SELECT spell, active, disabled FROM character_spell WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS, "SELECT quest, status, timer FROM character_queststatus WHERE guid = ? AND status <> 0", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES, "SELECT quest, objective, data FROM character_queststatus_objectives WHERE guid = ?", CONNECTION_ASYNC); @@ -260,8 +260,10 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_EQUIP_SET, "DELETE FROM character_equipmentsets WHERE setguid=?", CONNECTION_ASYNC); // Auras - PrepareStatement(CHAR_INS_AURA, "INSERT INTO character_aura (guid, caster_guid, item_guid, spell, effect_mask, recalculate_mask, stackcount, amount0, amount1, amount2, base_amount0, base_amount1, base_amount2, maxduration, remaintime, remaincharges) " - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_INS_AURA, "INSERT INTO character_aura (guid, casterGuid, itemGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_INS_AURA_EFFECT, "INSERT INTO character_aura_effect (guid, casterGuid, itemGuid, spell, effectMask, effectIndex, amount, baseAmount) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); // Currency PrepareStatement(CHAR_SEL_PLAYER_CURRENCY, "SELECT Currency, Quantity, WeeklyQuantity, TrackedQuantity, Flags FROM character_currency WHERE CharacterGuid = ?", CONNECTION_ASYNC); @@ -434,7 +436,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_CHARACTER_SOCIAL, "DELETE FROM character_social WHERE guid = ? AND friend = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_CHARACTER_SOCIAL_NOTE, "UPDATE character_social SET note = ? WHERE guid = ? AND friend = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_CHARACTER_POSITION, "UPDATE characters SET position_x = ?, position_y = ?, position_z = ?, orientation = ?, map = ?, zone = ?, trans_x = 0, trans_y = 0, trans_z = 0, transguid = 0, taxi_path = '' WHERE guid = ?", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_CHARACTER_AURA_FROZEN, "SELECT characters.name, character_aura.remaintime FROM characters LEFT JOIN character_aura ON (characters.guid = character_aura.guid) WHERE character_aura.spell = 9454", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_CHARACTER_AURA_FROZEN, "SELECT characters.name, character_aura.remainTime FROM characters LEFT JOIN character_aura ON (characters.guid = character_aura.guid) WHERE character_aura.spell = 9454", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHARACTER_ONLINE, "SELECT name, account, map, zone FROM characters WHERE online > 0", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_DEL_INFO_BY_GUID, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL AND guid = ?", CONNECTION_BOTH); PrepareStatement(CHAR_SEL_CHAR_DEL_INFO_BY_NAME, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL AND deleteInfos_Name LIKE CONCAT('%%', ?, '%%')", CONNECTION_SYNCH); @@ -517,6 +519,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_CHARACTER, "DELETE FROM characters WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_CHAR_ACTION, "DELETE FROM character_action WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_CHAR_AURA, "DELETE FROM character_aura WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_DEL_CHAR_AURA_EFFECT, "DELETE FROM character_aura_effect WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_CHAR_GIFT, "DELETE FROM character_gifts WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_CHAR_INSTANCE, "DELETE FROM character_instance WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_CHAR_INVENTORY, "DELETE FROM character_inventory WHERE guid = ?", CONNECTION_ASYNC); @@ -608,18 +611,22 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_CHAR_PET_DECLINEDNAME_BY_OWNER, "DELETE FROM character_pet_declinedname WHERE owner = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_CHAR_PET_DECLINEDNAME, "DELETE FROM character_pet_declinedname WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_CHAR_PET_DECLINEDNAME, "INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_PET_AURA, "SELECT caster_guid, spell, effect_mask, recalculate_mask, stackcount, amount0, amount1, amount2, base_amount0, base_amount1, base_amount2, maxduration, remaintime, remaincharges FROM pet_aura WHERE guid = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_PET_AURA, "SELECT casterGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges FROM pet_aura WHERE guid = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_PET_AURA_EFFECT, "SELECT casterGuid, spell, effectMask, effectIndex, amount, baseAmount FROM pet_aura_effect WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_PET_SPELL, "SELECT spell, active FROM pet_spell WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_PET_SPELL_COOLDOWN, "SELECT spell, time FROM pet_spell_cooldown WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_PET_DECLINED_NAME, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_pet_declinedname WHERE owner = ? AND id = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_DEL_PET_AURAS, "DELETE FROM pet_aura WHERE guid = ?", CONNECTION_BOTH); + PrepareStatement(CHAR_DEL_PET_AURA_EFFECTS, "DELETE FROM pet_aura_effect WHERE guid = ?", CONNECTION_BOTH); PrepareStatement(CHAR_DEL_PET_SPELLS, "DELETE FROM pet_spell WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_PET_SPELL_COOLDOWNS, "DELETE FROM pet_spell_cooldown WHERE guid = ?", CONNECTION_BOTH); PrepareStatement(CHAR_INS_PET_SPELL_COOLDOWN, "INSERT INTO pet_spell_cooldown (guid, spell, time) VALUES (?, ?, ?)", CONNECTION_BOTH); PrepareStatement(CHAR_DEL_PET_SPELL_BY_SPELL, "DELETE FROM pet_spell WHERE guid = ? and spell = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_PET_SPELL, "INSERT INTO pet_spell (guid, spell, active) VALUES (?, ?, ?)", CONNECTION_BOTH); - PrepareStatement(CHAR_INS_PET_AURA, "INSERT INTO pet_aura (guid, caster_guid, spell, effect_mask, recalculate_mask, stackcount, amount0, amount1, amount2, " - "base_amount0, base_amount1, base_amount2, maxduration, remaintime, remaincharges) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_BOTH); + PrepareStatement(CHAR_INS_PET_AURA, "INSERT INTO pet_aura (guid, casterGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_BOTH); + PrepareStatement(CHAR_INS_PET_AURA_EFFECT, "INSERT INTO pet_aura_effect (guid, casterGuid, spell, effectMask, effectIndex, amount, baseAmount) " + "VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_BOTH); PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND id = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY_AND_SLOT_2, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND entry = ? AND (slot = ? OR slot > ?)", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_PET_BY_SLOT, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND (slot = ? OR slot > ?) ", CONNECTION_SYNCH); diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index 81665743c8a..3dee607da48 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -79,6 +79,7 @@ enum CharacterDatabaseStatements CHAR_SEL_GROUP_MEMBER, CHAR_SEL_CHARACTER_INSTANCE, CHAR_SEL_CHARACTER_AURAS, + CHAR_SEL_CHARACTER_AURA_EFFECTS, CHAR_SEL_CHARACTER_SPELL, CHAR_SEL_CHARACTER_QUESTSTATUS, @@ -228,6 +229,7 @@ enum CharacterDatabaseStatements CHAR_DEL_EQUIP_SET, CHAR_INS_AURA, + CHAR_INS_AURA_EFFECT, CHAR_SEL_PLAYER_CURRENCY, CHAR_UPD_PLAYER_CURRENCY, @@ -448,6 +450,7 @@ enum CharacterDatabaseStatements CHAR_DEL_CHARACTER, CHAR_DEL_CHAR_ACTION, CHAR_DEL_CHAR_AURA, + CHAR_DEL_CHAR_AURA_EFFECT, CHAR_DEL_CHAR_GIFT, CHAR_DEL_CHAR_INSTANCE, CHAR_DEL_CHAR_INVENTORY, @@ -514,15 +517,18 @@ enum CharacterDatabaseStatements CHAR_DEL_CALENDAR_INVITE, CHAR_SEL_PET_AURA, + CHAR_SEL_PET_AURA_EFFECT, CHAR_SEL_PET_SPELL, CHAR_SEL_PET_SPELL_COOLDOWN, CHAR_SEL_PET_DECLINED_NAME, CHAR_DEL_PET_AURAS, + CHAR_DEL_PET_AURA_EFFECTS, CHAR_DEL_PET_SPELL_COOLDOWNS, CHAR_INS_PET_SPELL_COOLDOWN, CHAR_DEL_PET_SPELL_BY_SPELL, CHAR_INS_PET_SPELL, CHAR_INS_PET_AURA, + CHAR_INS_PET_AURA_EFFECT, CHAR_DEL_PET_SPELLS, CHAR_DEL_CHAR_PET_BY_OWNER, |