Core/Players: updated glyph handling for Cataclysm

This commit is contained in:
Ovahlord
2024-07-28 01:32:42 +02:00
parent 5657225f73
commit d8a9f7bd25
8 changed files with 100 additions and 120 deletions

View File

@@ -923,8 +923,9 @@ DROP TABLE IF EXISTS `character_glyphs`;
CREATE TABLE `character_glyphs` (
`guid` bigint unsigned NOT NULL,
`talentGroup` tinyint unsigned NOT NULL DEFAULT '0',
`glyphSlot` tinyint unsigned NOT NULL DEFAULT '0',
`glyphId` smallint unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`guid`,`talentGroup`,`glyphId`)
PRIMARY KEY (`guid`,`talentGroup`,`glyphSlot`,`glyphId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
@@ -3432,7 +3433,8 @@ INSERT INTO `updates` VALUES
('2024_06_02_00_characters.sql','18D12ED7A1D30675AAB807BAEB886FCCC76CED21','ARCHIVED','2024-06-02 23:04:45',0),
('2024_06_05_00_characters.sql','3BE1839524918827D4C0C8F9FBE9890CDF759FB4','RELEASED','2024-06-05 21:44:36',0),
('2024_06_25_00_characters.sql','046AC59E8B828B0C81A1A3C79860E464D96228B8','RELEASED','2024-06-25 17:56:15',0),
('2024_07_27_00_characters.sql','912ADCAC4948C75386387251D6FAEFB841574606','RELEASED','2024-07-27 01:03:05',0);
('2024_07_27_00_characters.sql','912ADCAC4948C75386387251D6FAEFB841574606','RELEASED','2024-07-27 01:03:05',0),
('2024_07_28_00_characters.sql','22C94D231C155686691780B65C12FCC2B4C3A6AA','RELEASED','2024-07-28 00:59:04',0);
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
UNLOCK TABLES;

View File

@@ -0,0 +1,4 @@
ALTER TABLE `character_glyphs`
ADD COLUMN `glyphSlot` tinyint UNSIGNED NOT NULL DEFAULT 0 AFTER `talentGroup`,
DROP PRIMARY KEY,
ADD PRIMARY KEY (`guid`, `talentGroup`, `glyphSlot`, `glyphId`);

View File

@@ -149,7 +149,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
"appearance5, appearance6, appearance7, appearance8, appearance9, appearance10, appearance11, appearance12, appearance13, appearance14, appearance15, appearance16, "
"appearance17, appearance18, mainHandEnchant, offHandEnchant FROM character_transmog_outfits WHERE guid = ? ORDER BY setindex", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_BGDATA, "SELECT instanceId, team, joinX, joinY, joinZ, joinO, joinMapId, taxiStart, taxiEnd, mountSpell, queueId FROM character_battleground_data WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_GLYPHS, "SELECT talentGroup, glyphId FROM character_glyphs WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_GLYPHS, "SELECT talentGroup, glyphSlot, glyphId FROM character_glyphs WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_TALENTS, "SELECT talentGroup, talentId, `rank` FROM character_talent WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_TALENT_GROUPS, "SELECT id, talentTabId FROM character_talent_group WHERE guid = ? ORDER BY id ASC", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_SKILLS, "SELECT skill, value, max, professionSlot FROM character_skills WHERE guid = ?", CONNECTION_ASYNC);
@@ -616,7 +616,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
"attackPower, rangedAttackPower, spellPower, resilience, mastery, versatility) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_PETITION_BY_OWNER, "DELETE FROM petition WHERE ownerguid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_PETITION_SIGNATURE_BY_OWNER, "DELETE FROM petition_sign WHERE ownerguid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_GLYPHS, "INSERT INTO character_glyphs VALUES(?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_GLYPHS, "INSERT INTO character_glyphs (guid, talentGroup, glyphSlot, glyphId) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_TALENT, "INSERT INTO character_talent (guid, talentGroup, talentId, `rank`) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_TALENT_GROUP, "INSERT INTO character_talent_group (guid, id, talentTabId) VALUES (?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_LIST_SLOT, "UPDATE characters SET slot = ? WHERE guid = ? AND account = ?", CONNECTION_ASYNC);

View File

@@ -17365,8 +17365,8 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
RegisterPowerTypes();
UpdateDisplayPower();
_LoadTalents(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_TALENT_GROUPS), holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_TALENTS));
_LoadGlyphs(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GLYPHS));
SetActiveTalentGroup(HasTalentGroupUnlocked(fields.activeTalentGroup) ? fields.activeTalentGroup : 0, false);
_LoadSpells(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_SPELLS), holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_SPELL_FAVORITES));
@@ -17376,9 +17376,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
GetSession()->GetCollectionMgr()->LoadItemAppearances();
GetSession()->GetCollectionMgr()->LoadTransmogIllusions();
_LoadGlyphs(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GLYPHS));
_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 (HasPlayerFlag(PLAYER_FLAGS_GHOST))
m_deathState = DEAD;
@@ -17796,12 +17794,6 @@ void Player::_LoadAuras(PreparedQueryResult auraResult, PreparedQueryResult effe
}
}
void Player::_LoadGlyphAuras()
{
for (uint32 glyphId : GetGlyphs(GetActiveTalentGroup()))
CastSpell(this, sGlyphPropertiesStore.AssertEntry(glyphId)->SpellID, true);
}
void Player::LoadCorpse(PreparedQueryResult result)
{
if (IsAlive() || HasAtLoginFlag(AT_LOGIN_RESURRECT))
@@ -23307,17 +23299,6 @@ void Player::SendInitialPacketsBeforeAddToMap()
GetSpellHistory()->WritePacket(&sendSpellCharges);
SendDirectMessage(sendSpellCharges.Write());
WorldPackets::Talent::ActiveGlyphs activeGlyphs;
activeGlyphs.Glyphs.reserve(GetGlyphs(GetActiveTalentGroup()).size());
for (uint32 glyphId : GetGlyphs(GetActiveTalentGroup()))
if (std::vector<uint32> const* bindableSpells = sDB2Manager.GetGlyphBindableSpells(glyphId))
for (uint32 bindableSpell : *bindableSpells)
if (HasSpell(bindableSpell) && m_overrideSpells.find(bindableSpell) == m_overrideSpells.end())
activeGlyphs.Glyphs.emplace_back(uint32(bindableSpell), uint16(glyphId));
activeGlyphs.IsFullUpdate = true;
SendDirectMessage(activeGlyphs.Write());
/// SMSG_ACTION_BUTTONS
SendInitialActionButtons();
@@ -25944,8 +25925,6 @@ void Player::InitGlyphsForLevel()
break;
SetGlyphSlot(slotIndex, glyphSlot->ID);
SetGlyph(slotIndex, 0);
++slotIndex;
}
@@ -25962,6 +25941,36 @@ void Player::InitGlyphsForLevel()
SetGlyphsEnabled(slotMask);
}
void Player::ApplyGlyph(uint8 index, uint32 glyphRecId)
{
if (index >= m_activePlayerData->Glyphs.size())
return;
GlyphPropertiesEntry const* glyphEntry = sGlyphPropertiesStore.LookupEntry(glyphRecId);
if (!glyphEntry)
return;
_talentGroups[_activeTalentGroup].Glyphs[index] = glyphRecId;
SetGlyph(index, glyphRecId);
CastSpell(this, glyphEntry->SpellID, true);
SendTalentsInfoData();
}
void Player::RemoveGlyph(uint8 index)
{
if (index >= m_activePlayerData->Glyphs.size())
return;
if (GlyphPropertiesEntry const* glyphEntry = sGlyphPropertiesStore.LookupEntry(m_activePlayerData->Glyphs[index]))
RemoveAurasDueToSpell(glyphEntry->SpellID);
_talentGroups[_activeTalentGroup].Glyphs[index] = 0;
SetGlyph(index, 0);
SendTalentsInfoData();
}
void Player::UpdateFallInformationIfNeed(MovementInfo const& minfo, uint16 opcode)
{
if (m_lastFallTime >= minfo.jump.fallTime || m_lastFallZ <= minfo.pos.GetPositionZ() || opcode == CMSG_MOVE_FALL_LAND)
@@ -26371,7 +26380,7 @@ void Player::SetMap(Map* map)
void Player::_LoadGlyphs(PreparedQueryResult result)
{
// SELECT talentGroup, glyphId from character_glyphs WHERE guid = ?
// SELECT talentGroup, glyphSlot, glyphId from character_glyphs WHERE guid = ?
if (!result)
return;
@@ -26379,16 +26388,21 @@ void Player::_LoadGlyphs(PreparedQueryResult result)
{
Field* fields = result->Fetch();
uint8 spec = fields[0].GetUInt8();
if (spec >= MAX_SPECIALIZATIONS || !sDB2Manager.GetChrSpecializationByIndex(GetClass(), spec))
uint8 talentGroupIndex = fields[0].GetUInt8();
if (_talentGroups.size() < uint8(talentGroupIndex + 1))
continue;
uint16 glyphId = fields[1].GetUInt16();
if (!sGlyphPropertiesStore.LookupEntry(glyphId))
TalentGroupInfo& talentGroup = _talentGroups[talentGroupIndex];
uint8 glyphSlot = fields[1].GetUInt8();
if (glyphSlot >= talentGroup.Glyphs.size())
continue;
GetGlyphs(spec).push_back(glyphId);
uint16 glyphId = fields[2].GetUInt16();
if (!sGlyphPropertiesStore.HasRecord(glyphId))
continue;
talentGroup.Glyphs[glyphSlot] = glyphId;
} while (result->NextRow());
}
@@ -26398,19 +26412,27 @@ void Player::_SaveGlyphs(CharacterDatabaseTransaction trans) const
stmt->setUInt64(0, GetGUID().GetCounter());
trans->Append(stmt);
for (uint8 spec = 0; spec < MAX_SPECIALIZATIONS; ++spec)
uint8 talentGroupIndex = 0;
for (TalentGroupInfo const& talentGroup : _talentGroups)
{
for (uint32 glyphId : GetGlyphs(spec))
uint8 glyphSlot = 0;
for (uint16 glyphId : talentGroup.Glyphs)
{
uint8 index = 0;
if (glyphId)
{
uint8 index = 0;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_GLYPHS);
stmt->setUInt64(index++, GetGUID().GetCounter());
stmt->setUInt8(index++, talentGroupIndex);
stmt->setUInt8(index++, glyphSlot);
stmt->setUInt16(index++, glyphId);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_GLYPHS);
stmt->setUInt64(index++, GetGUID().GetCounter());
stmt->setUInt8(index++, spec);
stmt->setUInt16(index++, uint16(glyphId));
trans->Append(stmt);
trans->Append(stmt);
}
++glyphSlot;
}
++talentGroupIndex;
}
}
@@ -28377,6 +28399,10 @@ void Player::SetActiveTalentGroup(uint8 group, bool withUpdate /*= true*/)
if (oldTalentTabId != newTalentTabId)
UnlearnTalentTreePrimarySpells();
for (uint16 glyphId : _talentGroups[_activeTalentGroup].Glyphs)
if (glyphId)
RemoveAurasDueToSpell(sGlyphPropertiesStore.AssertEntry(glyphId)->SpellID);
if (IsNonMeleeSpellCast(false))
InterruptNonMeleeSpells(false);
@@ -28433,17 +28459,24 @@ void Player::SetActiveTalentGroup(uint8 group, bool withUpdate /*= true*/)
RemoveSpell(spellId, false, false);
}
}
for (uint32 glyphId : GetGlyphs(GetActiveTalentGroup()))
RemoveAurasDueToSpell(sGlyphPropertiesStore.AssertEntry(glyphId)->SpellID);
}
_activeTalentGroup = group;
SetPrimaryTalentTree(newTalentTabId);
{
// Perform post switch actions - resetting powers, loading action bars, updating shapeshifting auras
SetPrimaryTalentTree(newTalentTabId);
uint8 glyphSlot = 0;
for (uint16 glyphId : _talentGroups[_activeTalentGroup].Glyphs)
{
if (glyphId)
CastSpell(this, sGlyphPropertiesStore.AssertEntry(glyphId)->SpellID, true);
SetGlyph(glyphSlot, glyphId);
++glyphSlot;
}
StartLoadingActionButtons();
UpdateDisplayPower();
@@ -28458,9 +28491,6 @@ void Player::SetActiveTalentGroup(uint8 group, bool withUpdate /*= true*/)
if (Item* equippedItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
SetVisibleItemSlot(i, equippedItem);
for (uint32 glyphId : GetGlyphs(GetActiveTalentGroup()))
CastSpell(this, sGlyphPropertiesStore.AssertEntry(glyphId)->SpellID, true);
Unit::AuraEffectList const& shapeshiftAuras = GetAuraEffectsByType(SPELL_AURA_MOD_SHAPESHIFT);
for (AuraEffect* aurEff : shapeshiftAuras)
{

View File

@@ -1869,6 +1869,8 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
void SendTalentsInfoData();
void InitGlyphsForLevel();
void ApplyGlyph(uint8 index, uint32 glyphRecId);
void RemoveGlyph(uint8 index);
void SetGlyph(uint8 index, uint32 glyphRecId) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::Glyphs, index), glyphRecId); }
void SetGlyphSlot(uint8 index, uint32 glyphSlotRecId) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::GlyphSlots, index), glyphSlotRecId); }
void SetGlyphsEnabled(uint32 slotMask) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::GlyphsEnabled), slotMask); }
@@ -2909,7 +2911,6 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
void _LoadActions(PreparedQueryResult result);
void _LoadAuras(PreparedQueryResult auraResult, PreparedQueryResult effectResult, uint32 timediff);
void _LoadGlyphAuras();
void _LoadInventory(PreparedQueryResult result, uint32 timeDiff);
void _LoadVoidStorage(PreparedQueryResult result);
void _LoadMail(PreparedQueryResult mailsResult, PreparedQueryResult mailItemsResult);

View File

@@ -6178,8 +6178,6 @@ SpellCastResult Spell::CheckCast(bool strict, int32* param1 /*= nullptr*/, int32
return SPELL_FAILED_GLYPH_NO_SPEC;
Player* caster = m_caster->ToPlayer();
if (!caster->HasSpell(m_misc.SpellId))
return SPELL_FAILED_NOT_KNOWN;
if (uint32 glyphId = spellEffectInfo.MiscValue)
{
@@ -6187,45 +6185,16 @@ SpellCastResult Spell::CheckCast(bool strict, int32* param1 /*= nullptr*/, int32
if (!glyphProperties)
return SPELL_FAILED_INVALID_GLYPH;
std::vector<uint32> const* glyphBindableSpells = sDB2Manager.GetGlyphBindableSpells(glyphId);
if (!glyphBindableSpells)
return SPELL_FAILED_INVALID_GLYPH;
if (std::find(glyphBindableSpells->begin(), glyphBindableSpells->end(), m_misc.SpellId) == glyphBindableSpells->end())
return SPELL_FAILED_INVALID_GLYPH;
if (std::vector<ChrSpecialization> const* glyphRequiredSpecs = sDB2Manager.GetGlyphRequiredSpecs(glyphId))
uint8 glyphSlot = 0;
for (uint32 activeGlyphId : caster->m_activePlayerData->Glyphs)
{
if (caster->GetPrimarySpecialization() == ChrSpecialization::None)
return SPELL_FAILED_GLYPH_NO_SPEC;
if (std::find(glyphRequiredSpecs->begin(), glyphRequiredSpecs->end(), caster->GetPrimarySpecialization()) == glyphRequiredSpecs->end())
return SPELL_FAILED_GLYPH_INVALID_SPEC;
}
uint32 replacedGlyph = 0;
for (uint32 activeGlyphId : caster->GetGlyphs(caster->GetActiveTalentGroup()))
{
if (std::vector<uint32> const* activeGlyphBindableSpells = sDB2Manager.GetGlyphBindableSpells(activeGlyphId))
{
if (std::find(activeGlyphBindableSpells->begin(), activeGlyphBindableSpells->end(), m_misc.SpellId) != activeGlyphBindableSpells->end())
{
replacedGlyph = activeGlyphId;
break;
}
}
}
for (uint32 activeGlyphId : caster->GetGlyphs(caster->GetActiveTalentGroup()))
{
if (activeGlyphId == replacedGlyph)
continue;
if (activeGlyphId == glyphId)
return SPELL_FAILED_UNIQUE_GLYPH;
if (sGlyphPropertiesStore.AssertEntry(activeGlyphId)->GlyphExclusiveCategoryID == glyphProperties->GlyphExclusiveCategoryID)
return SPELL_FAILED_GLYPH_EXCLUSIVE_CATEGORY;
if (m_misc.GlyphSlot == glyphSlot && activeGlyphId != 0)
return SPELL_FAILED_NO_ACTIVE_GLYPHS;
++glyphSlot;
}
}
break;

View File

@@ -572,7 +572,7 @@ class TC_GAME_API Spell
uint32 TalentId;
// SPELL_EFFECT_APPLY_GLYPH
uint32 SpellId;
uint32 GlyphSlot;
// SPELL_EFFECT_TALENT_SPEC_SELECT
uint32 SpecializationId;

View File

@@ -3331,41 +3331,15 @@ void Spell::EffectApplyGlyph()
if (!player)
return;
std::vector<uint32>& glyphs = player->GetGlyphs(player->GetActiveTalentGroup());
std::size_t replacedGlyph = glyphs.size();
for (std::size_t i = 0; i < glyphs.size(); ++i)
{
if (std::vector<uint32> const* activeGlyphBindableSpells = sDB2Manager.GetGlyphBindableSpells(glyphs[i]))
{
if (std::find(activeGlyphBindableSpells->begin(), activeGlyphBindableSpells->end(), m_misc.SpellId) != activeGlyphBindableSpells->end())
{
replacedGlyph = i;
player->RemoveAurasDueToSpell(sGlyphPropertiesStore.AssertEntry(glyphs[i])->SpellID);
break;
}
}
}
if (m_misc.GlyphSlot >= player->m_activePlayerData->Glyphs.size())
return;
uint32 glyphId = effectInfo->MiscValue;
if (replacedGlyph < glyphs.size())
{
if (glyphId)
glyphs[replacedGlyph] = glyphId;
else
glyphs.erase(glyphs.begin() + replacedGlyph);
}
else if (glyphId)
glyphs.push_back(glyphId);
player->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags2::ChangeGlyph);
if (GlyphPropertiesEntry const* glyphProperties = sGlyphPropertiesStore.LookupEntry(glyphId))
player->CastSpell(player, glyphProperties->SpellID, this);
WorldPackets::Talent::ActiveGlyphs activeGlyphs;
activeGlyphs.Glyphs.emplace_back(m_misc.SpellId, uint16(glyphId));
activeGlyphs.IsFullUpdate = false;
player->SendDirectMessage(activeGlyphs.Write());
if (glyphId)
player->ApplyGlyph(m_misc.GlyphSlot, glyphId);
else
player->RemoveGlyph(m_misc.GlyphSlot);
}
void Spell::EffectEnchantHeldItem()