Core/PacketIO: Updated equipment set packets and implemented saving transmog outfits (even if transmog itself isnt updated)
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
DROP TABLE IF EXISTS `character_transmog_outfits`;
|
||||
CREATE TABLE `character_transmog_outfits` (
|
||||
`guid` bigint(20) NOT NULL DEFAULT '0',
|
||||
`setguid` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`setindex` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`name` varchar(128) NOT NULL,
|
||||
`iconname` varchar(256) NOT NULL,
|
||||
`ignore_mask` int(11) NOT NULL DEFAULT '0',
|
||||
`appearance0` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance1` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance2` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance3` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance4` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance5` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance6` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance7` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance8` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance9` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance10` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance11` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance12` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance13` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance14` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance15` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance16` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance17` int(10) NOT NULL DEFAULT '0',
|
||||
`appearance18` int(10) NOT NULL DEFAULT '0',
|
||||
`mainHandEnchant` int(10) NOT NULL DEFAULT '0',
|
||||
`offHandEnchant` int(10) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`setguid`),
|
||||
UNIQUE KEY `idx_set` (`guid`,`setguid`,`setindex`),
|
||||
KEY `Idx_setindex` (`setindex`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
@@ -126,6 +126,9 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_CRITERIAPROGRESS, "SELECT criteria, counter, date FROM character_achievement_progress WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_EQUIPMENTSETS, "SELECT setguid, setindex, name, iconname, ignore_mask, item0, item1, item2, item3, item4, item5, item6, item7, item8, "
|
||||
"item9, item10, item11, item12, item13, item14, item15, item16, item17, item18 FROM character_equipmentsets WHERE guid = ? ORDER BY setindex", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_TRANSMOG_OUTFITS, "SELECT setguid, setindex, name, iconname, ignore_mask, appearance0, appearance1, appearance2, appearance3, appearance4, "
|
||||
"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 FROM character_battleground_data WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_TALENTS, "SELECT spell, talentGroup FROM character_talent WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_SKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = ?", CONNECTION_ASYNC);
|
||||
@@ -263,6 +266,14 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
"item4, item5, item6, item7, item8, item9, item10, item11, item12, item13, item14, item15, item16, item17, item18) "
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_EQUIP_SET, "DELETE FROM character_equipmentsets WHERE setguid=?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_TRANSMOG_OUTFIT, "UPDATE character_transmog_outfits SET name=?, iconname=?, ignore_mask=?, appearance0=?, appearance1=?, appearance2=?, appearance3=?, "
|
||||
"appearance4=?, appearance5=?, appearance6=?, appearance7=?, appearance8=?, appearance9=?, appearance10=?, appearance11=?, appearance12=?, appearance13=?, appearance14=?, "
|
||||
"appearance15=?, appearance16=?, appearance17=?, appearance18=?, mainHandEnchant=?, offHandEnchant=? WHERE guid=? AND setguid=? AND setindex=?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_TRANSMOG_OUTFIT, "INSERT INTO character_transmog_outfits (guid, setguid, setindex, name, iconname, ignore_mask, appearance0, appearance1, appearance2, "
|
||||
"appearance3, appearance4, appearance5, appearance6, appearance7, appearance8, appearance9, appearance10, appearance11, appearance12, appearance13, appearance14, appearance15, "
|
||||
"appearance16, appearance17, appearance18, mainHandEnchant, offHandEnchant) "
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_TRANSMOG_OUTFIT, "DELETE FROM character_transmog_outfits WHERE setguid=?", CONNECTION_ASYNC);
|
||||
|
||||
// Auras
|
||||
PrepareStatement(CHAR_INS_AURA, "INSERT INTO character_aura (guid, casterGuid, itemGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges, castItemLevel) "
|
||||
@@ -550,6 +561,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(CHAR_DEL_MAIL_ITEMS, "DELETE FROM mail_items WHERE receiver = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_ACHIEVEMENTS, "DELETE FROM character_achievement WHERE guid = ? AND achievement NOT IN (456,457,458,459,460,461,462,463,464,465,466,467,1400,1402,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,1420,1421,1422,1423,1424,1425,1426,1427,1463,3117,3259,4078,4576,4998,4999,5000,5001,5002,5003,5004,5005,5006,5007,5008,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,5395,5396,6433,6523,6524,6743,6744,6745,6746,6747,6748,6749,6750,6751,6752,6829,6859,6860,6861,6862,6863,6864,6865,6866,6867,6868,6869,6870,6871,6872,6873)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_EQUIPMENTSETS, "DELETE FROM character_equipmentsets WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_TRANSMOG_OUTFITS, "DELETE FROM character_transmog_outfits WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GUILD_EVENTLOG_BY_PLAYER, "DELETE FROM guild_eventlog WHERE PlayerGuid1 = ? OR PlayerGuid2 = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GUILD_BANK_EVENTLOG_BY_PLAYER, "DELETE FROM guild_bank_eventlog WHERE PlayerGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_TALENT, "DELETE FROM character_talent WHERE guid = ?", CONNECTION_ASYNC);
|
||||
|
||||
@@ -109,6 +109,7 @@ enum CharacterDatabaseStatements
|
||||
CHAR_SEL_CHARACTER_ACHIEVEMENTS,
|
||||
CHAR_SEL_CHARACTER_CRITERIAPROGRESS,
|
||||
CHAR_SEL_CHARACTER_EQUIPMENTSETS,
|
||||
CHAR_SEL_CHARACTER_TRANSMOG_OUTFITS,
|
||||
CHAR_SEL_CHARACTER_BGDATA,
|
||||
CHAR_SEL_CHARACTER_TALENTS,
|
||||
CHAR_SEL_CHARACTER_SKILLS,
|
||||
@@ -219,6 +220,10 @@ enum CharacterDatabaseStatements
|
||||
CHAR_INS_EQUIP_SET,
|
||||
CHAR_DEL_EQUIP_SET,
|
||||
|
||||
CHAR_UPD_TRANSMOG_OUTFIT,
|
||||
CHAR_INS_TRANSMOG_OUTFIT,
|
||||
CHAR_DEL_TRANSMOG_OUTFIT,
|
||||
|
||||
CHAR_INS_AURA,
|
||||
CHAR_INS_AURA_EFFECT,
|
||||
|
||||
@@ -466,6 +471,7 @@ enum CharacterDatabaseStatements
|
||||
CHAR_DEL_MAIL_ITEMS,
|
||||
CHAR_DEL_CHAR_ACHIEVEMENTS,
|
||||
CHAR_DEL_CHAR_EQUIPMENTSETS,
|
||||
CHAR_DEL_CHAR_TRANSMOG_OUTFITS,
|
||||
CHAR_DEL_GUILD_EVENTLOG_BY_PLAYER,
|
||||
CHAR_DEL_GUILD_BANK_EVENTLOG_BY_PLAYER,
|
||||
CHAR_DEL_CHAR_TALENT,
|
||||
|
||||
@@ -102,6 +102,7 @@ TC_GAME_API extern DB2Storage<ItemEffectEntry> sItemEffectS
|
||||
TC_GAME_API extern DB2Storage<ItemEntry> sItemStore;
|
||||
TC_GAME_API extern DB2Storage<ItemExtendedCostEntry> sItemExtendedCostStore;
|
||||
TC_GAME_API extern DB2Storage<ItemLimitCategoryEntry> sItemLimitCategoryStore;
|
||||
TC_GAME_API extern DB2Storage<ItemModifiedAppearanceEntry> sItemModifiedAppearanceStore;
|
||||
TC_GAME_API extern DB2Storage<ItemPriceBaseEntry> sItemPriceBaseStore;
|
||||
TC_GAME_API extern DB2Storage<ItemRandomPropertiesEntry> sItemRandomPropertiesStore;
|
||||
TC_GAME_API extern DB2Storage<ItemRandomSuffixEntry> sItemRandomSuffixStore;
|
||||
|
||||
@@ -4003,6 +4003,10 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
|
||||
stmt->setUInt64(0, guid);
|
||||
trans->Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_TRANSMOG_OUTFITS);
|
||||
stmt->setUInt64(0, guid);
|
||||
trans->Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_EVENTLOG_BY_PLAYER);
|
||||
stmt->setUInt64(0, guid);
|
||||
stmt->setUInt64(1, guid);
|
||||
@@ -16131,7 +16135,7 @@ void Player::_LoadArenaTeamInfo(PreparedQueryResult result)
|
||||
|
||||
void Player::_LoadEquipmentSets(PreparedQueryResult result)
|
||||
{
|
||||
// SetPQuery(PLAYER_LOGIN_QUERY_LOADEQUIPMENTSETS, "SELECT setguid, setindex, name, iconname, item0, item1, item2, item3, item4, item5, item6, item7, item8, item9, item10, item11, item12, item13, item14, item15, item16, item17, item18 FROM character_equipmentsets WHERE guid = '%u' ORDER BY setindex", GUID_LOPART(m_guid));
|
||||
// SetPQuery(PLAYER_LOGIN_QUERY_LOADEQUIPMENTSETS, "SELECT setguid, setindex, name, iconname, ignore_mask, item0, item1, item2, item3, item4, item5, item6, item7, item8, item9, item10, item11, item12, item13, item14, item15, item16, item17, item18 FROM character_equipmentsets WHERE guid = '%u' ORDER BY setindex", GUID_LOPART(m_guid));
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
@@ -16141,6 +16145,7 @@ void Player::_LoadEquipmentSets(PreparedQueryResult result)
|
||||
EquipmentSetInfo eqSet;
|
||||
|
||||
eqSet.Data.Guid = fields[0].GetUInt64();
|
||||
eqSet.Data.Type = EquipmentSetInfo::EQUIPMENT;
|
||||
eqSet.Data.SetID = fields[1].GetUInt8();
|
||||
eqSet.Data.SetName = fields[2].GetString();
|
||||
eqSet.Data.SetIcon = fields[3].GetString();
|
||||
@@ -16151,14 +16156,55 @@ void Player::_LoadEquipmentSets(PreparedQueryResult result)
|
||||
if (ObjectGuid::LowType guid = fields[5 + i].GetUInt64())
|
||||
eqSet.Data.Pieces[i] = ObjectGuid::Create<HighGuid::Item>(guid);
|
||||
|
||||
eqSet.Data.Appearances.fill(0);
|
||||
eqSet.Data.Enchants.fill(0);
|
||||
|
||||
if (eqSet.Data.SetID >= MAX_EQUIPMENT_SET_INDEX) // client limit
|
||||
continue;
|
||||
|
||||
_equipmentSets[eqSet.Data.SetID] = eqSet;
|
||||
_equipmentSets[eqSet.Data.Guid] = eqSet;
|
||||
}
|
||||
while (result->NextRow());
|
||||
}
|
||||
|
||||
void Player::_LoadTransmogOutfits(PreparedQueryResult result)
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7 8 9
|
||||
//SELECT setguid, setindex, name, iconname, ignore_mask, appearance0, appearance1, appearance2, appearance3, appearance4,
|
||||
// 10 11 12 13 14 15 16 17 18 19 20 21
|
||||
// appearance5, appearance6, appearance7, appearance8, appearance9, appearance10, appearance11, appearance12, appearance13, appearance14, appearance15, appearance16,
|
||||
// 22 23 24 25
|
||||
// appearance17, appearance18, mainHandEnchant, offHandEnchant FROM character_transmog_outfits WHERE guid = ? ORDER BY setindex
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
EquipmentSetInfo eqSet;
|
||||
|
||||
eqSet.Data.Guid = fields[0].GetUInt64();
|
||||
eqSet.Data.Type = EquipmentSetInfo::TRANSMOG;
|
||||
eqSet.Data.SetID = fields[1].GetUInt8();
|
||||
eqSet.Data.SetName = fields[2].GetString();
|
||||
eqSet.Data.SetIcon = fields[3].GetString();
|
||||
eqSet.Data.IgnoreMask = fields[4].GetUInt32();
|
||||
eqSet.State = EQUIPMENT_SET_UNCHANGED;
|
||||
eqSet.Data.Pieces.fill(ObjectGuid::Empty);
|
||||
|
||||
for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i)
|
||||
eqSet.Data.Appearances[i] = fields[5 + i].GetInt32();
|
||||
|
||||
for (std::size_t i = 0; i < eqSet.Data.Enchants.size(); ++i)
|
||||
eqSet.Data.Enchants[i] = fields[24 + i].GetInt32();
|
||||
|
||||
if (eqSet.Data.SetID >= MAX_EQUIPMENT_SET_INDEX) // client limit
|
||||
continue;
|
||||
|
||||
_equipmentSets[eqSet.Data.Guid] = eqSet;
|
||||
} while (result->NextRow());
|
||||
}
|
||||
|
||||
void Player::_LoadBGData(PreparedQueryResult result)
|
||||
{
|
||||
if (!result)
|
||||
@@ -16972,6 +17018,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
|
||||
_LoadDeclinedNames(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_DECLINED_NAMES));
|
||||
|
||||
_LoadEquipmentSets(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_EQUIPMENT_SETS));
|
||||
_LoadTransmogOutfits(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_TRANSMOG_OUTFITS));
|
||||
|
||||
_LoadCUFProfiles(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES));
|
||||
|
||||
@@ -24799,12 +24846,12 @@ void Player::SendEquipmentSetList()
|
||||
SendDirectMessage(data.Write());
|
||||
}
|
||||
|
||||
void Player::SetEquipmentSet(EquipmentSetInfo::EquipmentSetData&& newEqSet)
|
||||
void Player::SetEquipmentSet(EquipmentSetInfo::EquipmentSetData const& newEqSet)
|
||||
{
|
||||
if (newEqSet.Guid != 0)
|
||||
{
|
||||
// something wrong...
|
||||
EquipmentSetContainer::const_iterator itr = _equipmentSets.find(newEqSet.SetID);
|
||||
EquipmentSetContainer::const_iterator itr = _equipmentSets.find(newEqSet.Guid);
|
||||
if (itr == _equipmentSets.end() || itr->second.Data.Guid != newEqSet.Guid)
|
||||
{
|
||||
TC_LOG_ERROR("entities.player", "Player::SetEquipmentSet: Player '%s' (%s) tried to save nonexistent equipment set " UI64FMTD " (index: %u)",
|
||||
@@ -24813,7 +24860,7 @@ void Player::SetEquipmentSet(EquipmentSetInfo::EquipmentSetData&& newEqSet)
|
||||
}
|
||||
}
|
||||
|
||||
EquipmentSetInfo& eqSlot = _equipmentSets[newEqSet.SetID];
|
||||
EquipmentSetInfo& eqSlot = _equipmentSets[newEqSet.Guid];
|
||||
|
||||
EquipmentSetUpdateState oldState = eqSlot.State;
|
||||
|
||||
@@ -24825,6 +24872,7 @@ void Player::SetEquipmentSet(EquipmentSetInfo::EquipmentSetData&& newEqSet)
|
||||
|
||||
WorldPackets::EquipmentSet::EquipmentSetID data;
|
||||
data.GUID = eqSlot.Data.Guid;
|
||||
data.Type = eqSlot.Data.Type;
|
||||
data.SetID = eqSlot.Data.SetID;
|
||||
SendDirectMessage(data.Write());
|
||||
}
|
||||
@@ -24845,39 +24893,76 @@ void Player::_SaveEquipmentSets(SQLTransaction& trans)
|
||||
++itr;
|
||||
break; // nothing do
|
||||
case EQUIPMENT_SET_CHANGED:
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_EQUIP_SET);
|
||||
stmt->setString(j++, eqSet.Data.SetName);
|
||||
stmt->setString(j++, eqSet.Data.SetIcon);
|
||||
stmt->setUInt32(j++, eqSet.Data.IgnoreMask);
|
||||
|
||||
for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i)
|
||||
stmt->setUInt64(j++, eqSet.Data.Pieces[i].GetCounter());
|
||||
|
||||
stmt->setUInt64(j++, GetGUID().GetCounter());
|
||||
stmt->setUInt64(j++, eqSet.Data.Guid);
|
||||
stmt->setUInt32(j, eqSet.Data.SetID);
|
||||
{
|
||||
if (eqSet.Data.Type == EquipmentSetInfo::EQUIPMENT)
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_EQUIP_SET);
|
||||
stmt->setString(j++, eqSet.Data.SetName);
|
||||
stmt->setString(j++, eqSet.Data.SetIcon);
|
||||
stmt->setUInt32(j++, eqSet.Data.IgnoreMask);
|
||||
for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i)
|
||||
stmt->setUInt64(j++, eqSet.Data.Pieces[i].GetCounter());
|
||||
stmt->setUInt64(j++, GetGUID().GetCounter());
|
||||
stmt->setUInt64(j++, eqSet.Data.Guid);
|
||||
stmt->setUInt32(j, eqSet.Data.SetID);
|
||||
}
|
||||
else
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_TRANSMOG_OUTFIT);
|
||||
stmt->setString(j++, eqSet.Data.SetName);
|
||||
stmt->setString(j++, eqSet.Data.SetIcon);
|
||||
stmt->setUInt32(j++, eqSet.Data.IgnoreMask);
|
||||
for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i)
|
||||
stmt->setInt32(j++, eqSet.Data.Appearances[i]);
|
||||
for (std::size_t i = 0; i < eqSet.Data.Enchants.size(); ++i)
|
||||
stmt->setInt32(j++, eqSet.Data.Enchants[i]);
|
||||
stmt->setUInt64(j++, GetGUID().GetCounter());
|
||||
stmt->setUInt64(j++, eqSet.Data.Guid);
|
||||
stmt->setUInt32(j, eqSet.Data.SetID);
|
||||
}
|
||||
trans->Append(stmt);
|
||||
eqSet.State = EQUIPMENT_SET_UNCHANGED;
|
||||
++itr;
|
||||
break;
|
||||
}
|
||||
case EQUIPMENT_SET_NEW:
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_EQUIP_SET);
|
||||
stmt->setUInt64(j++, GetGUID().GetCounter());
|
||||
stmt->setUInt64(j++, eqSet.Data.Guid);
|
||||
stmt->setUInt32(j++, eqSet.Data.SetID);
|
||||
stmt->setString(j++, eqSet.Data.SetName);
|
||||
stmt->setString(j++, eqSet.Data.SetIcon);
|
||||
stmt->setUInt32(j++, eqSet.Data.IgnoreMask);
|
||||
|
||||
for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i)
|
||||
stmt->setUInt64(j++, eqSet.Data.Pieces[i].GetCounter());
|
||||
|
||||
{
|
||||
if (eqSet.Data.Type == EquipmentSetInfo::EQUIPMENT)
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_EQUIP_SET);
|
||||
stmt->setUInt64(j++, GetGUID().GetCounter());
|
||||
stmt->setUInt64(j++, eqSet.Data.Guid);
|
||||
stmt->setUInt32(j++, eqSet.Data.SetID);
|
||||
stmt->setString(j++, eqSet.Data.SetName);
|
||||
stmt->setString(j++, eqSet.Data.SetIcon);
|
||||
stmt->setUInt32(j++, eqSet.Data.IgnoreMask);
|
||||
for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i)
|
||||
stmt->setUInt64(j++, eqSet.Data.Pieces[i].GetCounter());
|
||||
}
|
||||
else
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_TRANSMOG_OUTFIT);
|
||||
stmt->setUInt64(j++, GetGUID().GetCounter());
|
||||
stmt->setUInt64(j++, eqSet.Data.Guid);
|
||||
stmt->setUInt32(j++, eqSet.Data.SetID);
|
||||
stmt->setString(j++, eqSet.Data.SetName);
|
||||
stmt->setString(j++, eqSet.Data.SetIcon);
|
||||
stmt->setUInt32(j++, eqSet.Data.IgnoreMask);
|
||||
for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i)
|
||||
stmt->setInt32(j++, eqSet.Data.Appearances[i]);
|
||||
for (std::size_t i = 0; i < eqSet.Data.Enchants.size(); ++i)
|
||||
stmt->setInt32(j++, eqSet.Data.Enchants[i]);
|
||||
}
|
||||
trans->Append(stmt);
|
||||
eqSet.State = EQUIPMENT_SET_UNCHANGED;
|
||||
++itr;
|
||||
break;
|
||||
}
|
||||
case EQUIPMENT_SET_DELETED:
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_EQUIP_SET);
|
||||
if (eqSet.Data.Type == EquipmentSetInfo::EQUIPMENT)
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_EQUIP_SET);
|
||||
else
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_TRANSMOG_OUTFIT);
|
||||
stmt->setUInt64(0, eqSet.Data.Guid);
|
||||
trans->Append(stmt);
|
||||
itr = _equipmentSets.erase(itr);
|
||||
|
||||
@@ -808,24 +808,33 @@ enum EquipmentSetUpdateState
|
||||
|
||||
struct EquipmentSetInfo
|
||||
{
|
||||
enum EquipmentSetType : int32
|
||||
{
|
||||
EQUIPMENT = 0,
|
||||
TRANSMOG = 1
|
||||
};
|
||||
|
||||
/// Data sent in EquipmentSet related packets
|
||||
struct EquipmentSetData
|
||||
{
|
||||
EquipmentSetType Type = EQUIPMENT;
|
||||
uint64 Guid = 0; ///< Set Identifier
|
||||
uint32 SetID = 0; ///< Index
|
||||
uint32 IgnoreMask = 0; ///< Mask of EquipmentSlot
|
||||
std::string SetName;
|
||||
std::string SetIcon;
|
||||
ObjectGuid Pieces[EQUIPMENT_SLOT_END];
|
||||
std::array<ObjectGuid, EQUIPMENT_SLOT_END> Pieces;
|
||||
std::array<int32, EQUIPMENT_SLOT_END> Appearances; ///< ItemModifiedAppearanceID
|
||||
std::array<int32, 2> Enchants; ///< SpellItemEnchantmentID
|
||||
} Data;
|
||||
|
||||
/// Server-side data
|
||||
EquipmentSetUpdateState State = EQUIPMENT_SET_NEW;
|
||||
};
|
||||
|
||||
#define MAX_EQUIPMENT_SET_INDEX 10 // client limit
|
||||
#define MAX_EQUIPMENT_SET_INDEX 20 // client limit
|
||||
|
||||
typedef std::map<uint32, EquipmentSetInfo> EquipmentSetContainer;
|
||||
typedef std::map<uint64, EquipmentSetInfo> EquipmentSetContainer;
|
||||
|
||||
struct ItemPosCount
|
||||
{
|
||||
@@ -955,6 +964,7 @@ enum PlayerLoginQueryIndex
|
||||
PLAYER_LOGIN_QUERY_LOAD_ACHIEVEMENTS,
|
||||
PLAYER_LOGIN_QUERY_LOAD_CRITERIA_PROGRESS,
|
||||
PLAYER_LOGIN_QUERY_LOAD_EQUIPMENT_SETS,
|
||||
PLAYER_LOGIN_QUERY_LOAD_TRANSMOG_OUTFITS,
|
||||
PLAYER_LOGIN_QUERY_LOAD_BG_DATA,
|
||||
PLAYER_LOGIN_QUERY_LOAD_TALENTS,
|
||||
PLAYER_LOGIN_QUERY_LOAD_ACCOUNT_DATA,
|
||||
@@ -2139,7 +2149,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
|
||||
void CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx, Item* item, ItemTemplate const* proto);
|
||||
|
||||
void SendEquipmentSetList();
|
||||
void SetEquipmentSet(EquipmentSetInfo::EquipmentSetData&& newEqSet);
|
||||
void SetEquipmentSet(EquipmentSetInfo::EquipmentSetData const& newEqSet);
|
||||
void DeleteEquipmentSet(uint64 id);
|
||||
|
||||
void SendInitWorldStates(uint32 zone, uint32 area);
|
||||
@@ -2519,6 +2529,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
|
||||
void _LoadDeclinedNames(PreparedQueryResult result);
|
||||
void _LoadArenaTeamInfo(PreparedQueryResult result);
|
||||
void _LoadEquipmentSets(PreparedQueryResult result);
|
||||
void _LoadTransmogOutfits(PreparedQueryResult result);
|
||||
void _LoadBGData(PreparedQueryResult result);
|
||||
void _LoadTalents(PreparedQueryResult result);
|
||||
void _LoadInstanceTimeRestrictions(PreparedQueryResult result);
|
||||
|
||||
@@ -192,6 +192,10 @@ bool LoginQueryHolder::Initialize()
|
||||
stmt->setUInt64(0, lowGuid);
|
||||
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_EQUIPMENT_SETS, stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_TRANSMOG_OUTFITS);
|
||||
stmt->setUInt64(0, lowGuid);
|
||||
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_TRANSMOG_OUTFITS, stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CUF_PROFILES);
|
||||
stmt->setUInt64(0, lowGuid);
|
||||
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES, stmt);
|
||||
@@ -1623,29 +1627,53 @@ void WorldSession::HandleEquipmentSetSave(WorldPackets::EquipmentSet::SaveEquipm
|
||||
if (saveEquipmentSet.Set.SetID >= MAX_EQUIPMENT_SET_INDEX) // client set slots amount
|
||||
return;
|
||||
|
||||
if (saveEquipmentSet.Set.Type > EquipmentSetInfo::TRANSMOG)
|
||||
return;
|
||||
|
||||
for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i)
|
||||
{
|
||||
if (!(saveEquipmentSet.Set.IgnoreMask & (1 << i)))
|
||||
{
|
||||
ObjectGuid const& itemGuid = saveEquipmentSet.Set.Pieces[i];
|
||||
if (saveEquipmentSet.Set.Type == EquipmentSetInfo::EQUIPMENT)
|
||||
{
|
||||
saveEquipmentSet.Set.Appearances[i] = 0;
|
||||
|
||||
Item* item = _player->GetItemByPos(INVENTORY_SLOT_BAG_0, i);
|
||||
ObjectGuid const& itemGuid = saveEquipmentSet.Set.Pieces[i];
|
||||
|
||||
/// cheating check 1 (item equipped but sent empty guid)
|
||||
if (!item && !itemGuid.IsEmpty())
|
||||
return;
|
||||
Item* item = _player->GetItemByPos(INVENTORY_SLOT_BAG_0, i);
|
||||
|
||||
/// cheating check 2 (sent guid does not match equipped item)
|
||||
if (item && item->GetGUID() != itemGuid)
|
||||
return;
|
||||
/// cheating check 1 (item equipped but sent empty guid)
|
||||
if (!item && !itemGuid.IsEmpty())
|
||||
return;
|
||||
|
||||
/// cheating check 2 (sent guid does not match equipped item)
|
||||
if (item && item->GetGUID() != itemGuid)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
saveEquipmentSet.Set.Pieces[i].Clear();
|
||||
if (saveEquipmentSet.Set.Appearances[i] && !sItemModifiedAppearanceStore.LookupEntry(saveEquipmentSet.Set.Appearances[i]))
|
||||
return;
|
||||
|
||||
// TODO: validata whether appearance is known
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
saveEquipmentSet.Set.Pieces[i].Clear();
|
||||
saveEquipmentSet.Set.Appearances[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
saveEquipmentSet.Set.IgnoreMask &= 0x7FFFF; /// clear invalid bits (i > EQUIPMENT_SLOT_END)
|
||||
if (saveEquipmentSet.Set.Type == EquipmentSetInfo::EQUIPMENT)
|
||||
{
|
||||
saveEquipmentSet.Set.Enchants[0] = 0;
|
||||
saveEquipmentSet.Set.Enchants[1] = 0;
|
||||
}
|
||||
|
||||
_player->SetEquipmentSet(std::move(saveEquipmentSet.Set));
|
||||
_player->SetEquipmentSet(saveEquipmentSet.Set);
|
||||
}
|
||||
|
||||
void WorldSession::HandleDeleteEquipmentSet(WorldPackets::EquipmentSet::DeleteEquipmentSet& deleteEquipmentSet)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
WorldPacket const* WorldPackets::EquipmentSet::EquipmentSetID::Write()
|
||||
{
|
||||
_worldPacket << uint64(GUID);
|
||||
_worldPacket << int32(Type);
|
||||
_worldPacket << uint32(SetID);
|
||||
|
||||
return &_worldPacket;
|
||||
@@ -31,12 +32,18 @@ WorldPacket const* WorldPackets::EquipmentSet::LoadEquipmentSet::Write()
|
||||
|
||||
for (EquipmentSetInfo::EquipmentSetData const* equipSet : SetData)
|
||||
{
|
||||
_worldPacket << int32(equipSet->Type);
|
||||
_worldPacket << uint64(equipSet->Guid);
|
||||
_worldPacket << uint32(equipSet->SetID);
|
||||
_worldPacket << uint32(equipSet->IgnoreMask);
|
||||
|
||||
for (ObjectGuid const& guid : equipSet->Pieces)
|
||||
_worldPacket << guid;
|
||||
for (std::size_t i = 0; i < EQUIPMENT_SLOT_END; ++i)
|
||||
{
|
||||
_worldPacket << equipSet->Pieces[i];
|
||||
_worldPacket << int32(equipSet->Appearances[i]);
|
||||
}
|
||||
|
||||
_worldPacket.append(equipSet->Enchants.data(), equipSet->Enchants.size());
|
||||
|
||||
_worldPacket.WriteBits(equipSet->SetName.length(), 8);
|
||||
_worldPacket.WriteBits(equipSet->SetIcon.length(), 9);
|
||||
@@ -51,12 +58,19 @@ WorldPacket const* WorldPackets::EquipmentSet::LoadEquipmentSet::Write()
|
||||
|
||||
void WorldPackets::EquipmentSet::SaveEquipmentSet::Read()
|
||||
{
|
||||
Set.Type = EquipmentSetInfo::EquipmentSetType(_worldPacket.read<int32>());
|
||||
_worldPacket >> Set.Guid;
|
||||
_worldPacket >> Set.SetID;
|
||||
_worldPacket >> Set.IgnoreMask;
|
||||
|
||||
for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i)
|
||||
{
|
||||
_worldPacket >> Set.Pieces[i];
|
||||
_worldPacket >> Set.Appearances[i];
|
||||
}
|
||||
|
||||
_worldPacket >> Set.Enchants[0];
|
||||
_worldPacket >> Set.Enchants[1];
|
||||
|
||||
uint32 setNameLength = _worldPacket.ReadBits(8);
|
||||
uint32 setIconLength = _worldPacket.ReadBits(9);
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace WorldPackets
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
uint64 GUID = 0; ///< Set Identifier
|
||||
int32 Type = 0;
|
||||
uint32 SetID = 0; ///< Index
|
||||
};
|
||||
|
||||
|
||||
@@ -676,7 +676,7 @@ void OpcodeTable::Initialize()
|
||||
DEFINE_HANDLER(CMSG_REVERT_MONUMENT_APPEARANCE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
|
||||
DEFINE_HANDLER(CMSG_RIDE_VEHICLE_INTERACT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Vehicle::RideVehicleInteract, &WorldSession::HandleRideVehicleInteract);
|
||||
DEFINE_HANDLER(CMSG_SAVE_CUF_PROFILES, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Misc::SaveCUFProfiles, &WorldSession::HandleSaveCUFProfiles);
|
||||
DEFINE_HANDLER(CMSG_SAVE_EQUIPMENT_SET, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::EquipmentSet::SaveEquipmentSet, &WorldSession::HandleEquipmentSetSave);
|
||||
DEFINE_HANDLER(CMSG_SAVE_EQUIPMENT_SET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::EquipmentSet::SaveEquipmentSet, &WorldSession::HandleEquipmentSetSave);
|
||||
DEFINE_HANDLER(CMSG_SAVE_GUILD_EMBLEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Guild::SaveGuildEmblem, &WorldSession::HandleSaveGuildEmblem);
|
||||
DEFINE_HANDLER(CMSG_SCENE_PLAYBACK_CANCELED, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Scenes::ScenePlaybackCanceled, &WorldSession::HandleScenePlaybackCanceled);
|
||||
DEFINE_HANDLER(CMSG_SCENE_PLAYBACK_COMPLETE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Scenes::ScenePlaybackComplete, &WorldSession::HandleScenePlaybackComplete);
|
||||
@@ -1077,7 +1077,7 @@ void OpcodeTable::Initialize()
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ENCOUNTER_START, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ENUM_CHARACTERS_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ENVIRONMENTAL_DAMAGE_LOG, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_EQUIPMENT_SET_ID, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_EQUIPMENT_SET_ID, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_EXPECTED_SPAM_RECORDS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_EXPLORATION_EXPERIENCE, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_FACTION_BONUS_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
|
||||
@@ -1297,7 +1297,7 @@ void OpcodeTable::Initialize()
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LIVE_REGION_CHARACTER_COPY_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LIVE_REGION_GET_ACCOUNT_CHARACTER_LIST_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOAD_CUF_PROFILES, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOAD_EQUIPMENT_SET, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOAD_EQUIPMENT_SET, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOAD_SELECTED_TROPHY_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOGIN_SET_TIME_SPEED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOGIN_VERIFY_WORLD, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
||||
|
||||
Reference in New Issue
Block a user