aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/base/characters_database.sql107
-rw-r--r--sql/updates/characters/2015_01_16_00_characters.sql67
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp182
-rw-r--r--src/server/game/Entities/Player/Player.cpp170
-rw-r--r--src/server/game/Entities/Player/Player.h3
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp4
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp30
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h36
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp23
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.h6
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,