mirror of
https://github.com/mangosfour/server.git
synced 2025-12-15 19:37:02 +00:00
Fixed talents display and inspect
This commit is contained in:
parent
8c489f80dc
commit
9e1e845e54
5 changed files with 131 additions and 133 deletions
|
|
@ -1184,76 +1184,20 @@ void WorldSession::HandleInspectOpcode(WorldPacket& recv_data)
|
|||
if(!plr) // wrong player
|
||||
return;
|
||||
|
||||
uint32 talent_points = 0x3D;
|
||||
uint32 guid_size = plr->GetPackGUID().size();
|
||||
WorldPacket data(SMSG_INSPECT_TALENT, 4+talent_points);
|
||||
WorldPacket data(SMSG_INSPECT_TALENT, 50);
|
||||
data.append(plr->GetPackGUID());
|
||||
data << uint32(talent_points);
|
||||
|
||||
// fill by 0 talents array
|
||||
for(uint32 i = 0; i < talent_points; ++i)
|
||||
data << uint8(0);
|
||||
|
||||
if(sWorld.getConfig(CONFIG_TALENTS_INSPECTING) || _player->isGameMaster())
|
||||
{
|
||||
// find class talent tabs (all players have 3 talent tabs)
|
||||
uint32 const* talentTabIds = GetTalentTabPages(plr->getClass());
|
||||
|
||||
uint32 talentTabPos = 0; // pos of first talent rank in tab including all prev tabs
|
||||
for(uint32 i = 0; i < 3; ++i)
|
||||
{
|
||||
uint32 talentTabId = talentTabIds[i];
|
||||
|
||||
// fill by real data
|
||||
for(uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId)
|
||||
{
|
||||
TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId);
|
||||
if(!talentInfo)
|
||||
continue;
|
||||
|
||||
// skip another tab talents
|
||||
if(talentInfo->TalentTab != talentTabId)
|
||||
continue;
|
||||
|
||||
// find talent rank
|
||||
uint32 curtalent_maxrank = 0;
|
||||
for(uint32 k = 5; k > 0; --k)
|
||||
{
|
||||
if(talentInfo->RankID[k-1] && plr->HasSpell(talentInfo->RankID[k-1]))
|
||||
{
|
||||
curtalent_maxrank = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// not learned talent
|
||||
if(!curtalent_maxrank)
|
||||
continue;
|
||||
|
||||
// 1 rank talent bit index
|
||||
uint32 curtalent_index = talentTabPos + GetTalentInspectBitPosInTab(talentId);
|
||||
|
||||
uint32 curtalent_rank_index = curtalent_index+curtalent_maxrank-1;
|
||||
|
||||
// slot/offset in 7-bit bytes
|
||||
uint32 curtalent_rank_slot7 = curtalent_rank_index / 7;
|
||||
uint32 curtalent_rank_offset7 = curtalent_rank_index % 7;
|
||||
|
||||
// rank pos with skipped 8 bit
|
||||
uint32 curtalent_rank_index2 = curtalent_rank_slot7 * 8 + curtalent_rank_offset7;
|
||||
|
||||
// slot/offset in 8-bit bytes with skipped high bit
|
||||
uint32 curtalent_rank_slot = curtalent_rank_index2 / 8;
|
||||
uint32 curtalent_rank_offset = curtalent_rank_index2 % 8;
|
||||
|
||||
// apply mask
|
||||
uint32 val = data.read<uint8>(guid_size + 4 + curtalent_rank_slot);
|
||||
val |= (1 << curtalent_rank_offset);
|
||||
data.put<uint8>(guid_size + 4 + curtalent_rank_slot, val & 0xFF);
|
||||
}
|
||||
|
||||
talentTabPos += GetTalentTabInspectBitSize(talentTabId);
|
||||
}
|
||||
plr->BuildPlayerTalentsInfoData(&data);
|
||||
plr->BuildEnchantmentsInfoData(&data);
|
||||
}
|
||||
else
|
||||
{
|
||||
data << uint32(0); // unspentTalentPoints
|
||||
data << uint8(0); // talentGroupCount
|
||||
data << uint8(0); // talentGroupIndex
|
||||
data << uint32(0); // slotUsedMask
|
||||
}
|
||||
|
||||
SendPacket(&data);
|
||||
|
|
|
|||
|
|
@ -18089,6 +18089,7 @@ void Player::SendInitialPacketsBeforeAddToMap()
|
|||
data << uint32( GetTutorialInt(i) );
|
||||
GetSession()->SendPacket(&data);
|
||||
|
||||
SendTalentInfoData(false);
|
||||
SendInitialSpells();
|
||||
|
||||
data.Initialize(SMSG_SEND_UNLEARN_SPELLS, 4);
|
||||
|
|
@ -19611,3 +19612,119 @@ uint8 Player::CanEquipUniqueItem( ItemPrototype const* itemProto, uint8 except_s
|
|||
|
||||
return EQUIP_ERR_OK;
|
||||
}
|
||||
|
||||
void Player::BuildPlayerTalentsInfoData(WorldPacket *data)
|
||||
{
|
||||
*data << uint32(GetFreeTalentPoints()); // unspentTalentPoints
|
||||
uint8 talentGroupCount = 1;
|
||||
*data << uint8(talentGroupCount); // talent group count (1 or 2)
|
||||
*data << uint8(0); // talent group index (0 or 1)
|
||||
|
||||
if(talentGroupCount)
|
||||
{
|
||||
uint8 talentIdCount = 0;
|
||||
size_t pos = data->wpos();
|
||||
*data << uint8(talentIdCount); // [PH], talentIdCount
|
||||
|
||||
// find class talent tabs (all players have 3 talent tabs)
|
||||
uint32 const* talentTabIds = GetTalentTabPages(getClass());
|
||||
|
||||
for(uint32 i = 0; i < 3; ++i)
|
||||
{
|
||||
uint32 talentTabId = talentTabIds[i];
|
||||
|
||||
for(uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId)
|
||||
{
|
||||
TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId);
|
||||
if(!talentInfo)
|
||||
continue;
|
||||
|
||||
// skip another tab talents
|
||||
if(talentInfo->TalentTab != talentTabId)
|
||||
continue;
|
||||
|
||||
// find max talent rank
|
||||
int32 curtalent_maxrank = -1;
|
||||
for(int32 k = 4; k > -1; --k)
|
||||
{
|
||||
if(talentInfo->RankID[k] && HasSpell(talentInfo->RankID[k]))
|
||||
{
|
||||
curtalent_maxrank = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// not learned talent
|
||||
if(curtalent_maxrank < 0)
|
||||
continue;
|
||||
|
||||
*data << uint32(talentInfo->TalentID); // Talent.dbc
|
||||
*data << uint8(curtalent_maxrank); // talentMaxRank (0-4)
|
||||
|
||||
++talentIdCount;
|
||||
}
|
||||
}
|
||||
|
||||
data->put<uint8>(pos, talentIdCount); // put real count
|
||||
|
||||
uint8 glyphsCount = 6;
|
||||
*data << uint8(glyphsCount); // glyphs count
|
||||
|
||||
for(uint8 i = 0; i < glyphsCount; ++i)
|
||||
*data << uint16(GetGlyph(i)); // GlyphProperties.dbc
|
||||
}
|
||||
}
|
||||
|
||||
void Player::BuildPetTalentsInfoData(WorldPacket *data)
|
||||
{
|
||||
*data << uint32(0); // unspentTalentPoints
|
||||
*data << uint8(0); // talentCount
|
||||
/*for(talentCount)
|
||||
{
|
||||
*data << uint32(0); // Talent.dbc
|
||||
*data << uint8(0); // maxRank
|
||||
}*/
|
||||
}
|
||||
|
||||
void Player::SendTalentInfoData(bool pet)
|
||||
{
|
||||
WorldPacket data(SMSG_UNKNOWN_1216, 50);
|
||||
data << uint8(pet);
|
||||
if(pet)
|
||||
BuildPetTalentsInfoData(&data);
|
||||
else
|
||||
BuildPlayerTalentsInfoData(&data);
|
||||
GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
void Player::BuildEnchantmentsInfoData(WorldPacket *data)
|
||||
{
|
||||
uint32 slotUsedMask = 0;
|
||||
*data << uint32(slotUsedMask); // > 0x80000
|
||||
|
||||
for(uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i)
|
||||
{
|
||||
if(slotUsedMask & 1)
|
||||
{
|
||||
*data << uint32(0); // item entry
|
||||
uint16 enchantmentMask = 0;
|
||||
*data << uint16(enchantmentMask); // > 0x1000
|
||||
|
||||
for(uint32 j = 0; j < MAX_ENCHANTMENT_SLOT; ++j)
|
||||
{
|
||||
if(enchantmentMask & 1)
|
||||
{
|
||||
*data << uint16(0); // enchantmentId?
|
||||
}
|
||||
|
||||
enchantmentMask >>= 1;
|
||||
}
|
||||
|
||||
*data << uint16(0);
|
||||
*data << uint8(0); // PGUID!
|
||||
*data << uint32(0);
|
||||
}
|
||||
|
||||
slotUsedMask >>= 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1187,6 +1187,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
void ApplyEnchantment(Item *item,EnchantmentSlot slot,bool apply, bool apply_dur = true, bool ignore_condition = false);
|
||||
void ApplyEnchantment(Item *item,bool apply);
|
||||
void SendEnchantmentDurations();
|
||||
void BuildEnchantmentsInfoData(WorldPacket *data);
|
||||
void AddItemDurations(Item *item);
|
||||
void RemoveItemDurations(Item *item);
|
||||
void SendItemDurations();
|
||||
|
|
@ -1459,6 +1460,9 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
bool resetTalents(bool no_cost = false);
|
||||
uint32 resetTalentsCost() const;
|
||||
void InitTalentForLevel();
|
||||
void BuildPlayerTalentsInfoData(WorldPacket *data);
|
||||
void BuildPetTalentsInfoData(WorldPacket *data);
|
||||
void SendTalentInfoData(bool pet);
|
||||
|
||||
uint32 CalculateTalentsPoints() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -120,9 +120,6 @@ TalentSpellPosMap sTalentSpellPosMap;
|
|||
DBCStorage <TalentTabEntry> sTalentTabStore(TalentTabEntryfmt);
|
||||
|
||||
// store absolute bit position for first rank for talent inspect
|
||||
typedef std::map<uint32,uint32> TalentInspectMap;
|
||||
static TalentInspectMap sTalentPosInInspect;
|
||||
static TalentInspectMap sTalentTabSizeInInspect;
|
||||
static uint32 sTalentTabPages[12/*MAX_CLASSES*/][3];
|
||||
|
||||
DBCStorage <TaxiNodesEntry> sTaxiNodesStore(TaxiNodesEntryfmt);
|
||||
|
|
@ -350,34 +347,6 @@ void LoadDBCStores(const std::string& dataPath)
|
|||
|
||||
// prepare fast data access to bit pos of talent ranks for use at inspecting
|
||||
{
|
||||
// fill table by amount of talent ranks and fill sTalentTabBitSizeInInspect
|
||||
// store in with (row,col,talent)->size key for correct sorting by (row,col)
|
||||
typedef std::map<uint32,uint32> TalentBitSize;
|
||||
TalentBitSize sTalentBitSize;
|
||||
for(uint32 i = 1; i < sTalentStore.GetNumRows(); ++i)
|
||||
{
|
||||
TalentEntry const *talentInfo = sTalentStore.LookupEntry(i);
|
||||
if (!talentInfo) continue;
|
||||
|
||||
TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab );
|
||||
if(!talentTabInfo)
|
||||
continue;
|
||||
|
||||
// find talent rank
|
||||
uint32 curtalent_maxrank = 0;
|
||||
for(uint32 k = 5; k > 0; --k)
|
||||
{
|
||||
if(talentInfo->RankID[k-1])
|
||||
{
|
||||
curtalent_maxrank = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sTalentBitSize[(talentInfo->Row<<24) + (talentInfo->Col<<16)+talentInfo->TalentID] = curtalent_maxrank;
|
||||
sTalentTabSizeInInspect[talentInfo->TalentTab] += curtalent_maxrank;
|
||||
}
|
||||
|
||||
// now have all max ranks (and then bit amount used for store talent ranks in inspect)
|
||||
for(uint32 talentTabId = 1; talentTabId < sTalentTabStore.GetNumRows(); ++talentTabId)
|
||||
{
|
||||
|
|
@ -390,22 +359,6 @@ void LoadDBCStores(const std::string& dataPath)
|
|||
for(uint32 m=1;!(m & talentTabInfo->ClassMask) && cls < 12 /*MAX_CLASSES*/;m <<=1, ++cls) {}
|
||||
|
||||
sTalentTabPages[cls][talentTabInfo->tabpage]=talentTabId;
|
||||
|
||||
// add total amount bits for first rank starting from talent tab first talent rank pos.
|
||||
uint32 pos = 0;
|
||||
for(TalentBitSize::iterator itr = sTalentBitSize.begin(); itr != sTalentBitSize.end(); ++itr)
|
||||
{
|
||||
uint32 talentId = itr->first & 0xFFFF;
|
||||
TalentEntry const *talentInfo = sTalentStore.LookupEntry( talentId );
|
||||
if(!talentInfo)
|
||||
continue;
|
||||
|
||||
if(talentInfo->TalentTab != talentTabId)
|
||||
continue;
|
||||
|
||||
sTalentPosInInspect[talentId] = pos;
|
||||
pos+= itr->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -679,24 +632,6 @@ void Map2ZoneCoordinates(float& x,float& y,uint32 zone)
|
|||
std::swap(x,y); // client have map coords swapped
|
||||
}
|
||||
|
||||
uint32 GetTalentInspectBitPosInTab(uint32 talentId)
|
||||
{
|
||||
TalentInspectMap::const_iterator itr = sTalentPosInInspect.find(talentId);
|
||||
if(itr == sTalentPosInInspect.end())
|
||||
return 0;
|
||||
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
uint32 GetTalentTabInspectBitSize(uint32 talentTabId)
|
||||
{
|
||||
TalentInspectMap::const_iterator itr = sTalentTabSizeInInspect.find(talentTabId);
|
||||
if(itr == sTalentTabSizeInInspect.end())
|
||||
return 0;
|
||||
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
uint32 const* GetTalentTabPages(uint32 cls)
|
||||
{
|
||||
return sTalentTabPages[cls];
|
||||
|
|
|
|||
|
|
@ -55,8 +55,6 @@ bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredT
|
|||
void Zone2MapCoordinates(float& x,float& y,uint32 zone);
|
||||
void Map2ZoneCoordinates(float& x,float& y,uint32 zone);
|
||||
|
||||
uint32 GetTalentInspectBitPosInTab(uint32 talentId);
|
||||
uint32 GetTalentTabInspectBitSize(uint32 talentTabId);
|
||||
uint32 const* /*[3]*/ GetTalentTabPages(uint32 cls);
|
||||
|
||||
template<class T>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue