diff options
Diffstat (limited to 'src/game/Player.cpp')
-rw-r--r-- | src/game/Player.cpp | 610 |
1 files changed, 435 insertions, 175 deletions
diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 5f97ab82e68..188a41f5b94 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -349,10 +349,6 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa PlayerTalkClass = new PlayerMenu( GetSession() ); m_currentBuybackSlot = BUYBACK_SLOT_START; - for ( int aX = 0 ; aX < 8 ; aX++ ) - m_Tutorials[ aX ] = 0x00; - m_TutorialsChanged = false; - m_DailyQuestChanged = false; m_lastDailyQuestTime = 0; @@ -429,7 +425,10 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa m_lastPotionId = 0; - for (int i = 0; i < BASEMOD_END; i++) + m_activeSpec = 0; + m_specsCount = 0; + + for (int i = 0; i < BASEMOD_END; ++i) { m_auraBaseMod[i][FLAT_MOD] = 0.0f; m_auraBaseMod[i][PCT_MOD] = 1.0f; @@ -454,7 +453,7 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa m_summon_z = 0.0f; //Default movement to run mode - m_unit_movement_flags = 0; + //m_unit_movement_flags = 0; m_mover = this; m_seer = this; @@ -598,6 +597,7 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 SetUInt64Value( PLAYER__FIELD_KNOWN_TITLES, 0 ); // 0=disabled SetUInt64Value( PLAYER__FIELD_KNOWN_TITLES1, 0 ); // 0=disabled + SetUInt64Value( PLAYER__FIELD_KNOWN_TITLES2, 0 ); // 0=disabled SetUInt32Value( PLAYER_CHOSEN_TITLE, 0 ); SetUInt32Value( PLAYER_FIELD_KILLS, 0 ); SetUInt32Value( PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 0 ); @@ -1535,14 +1535,14 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; slot++) { - uint32 visualbase = PLAYER_VISIBLE_ITEM_1_0 + (slot * MAX_VISIBLE_ITEM_OFFSET); + uint32 visualbase = PLAYER_VISIBLE_ITEM_1_ENTRYID + (slot * 2); uint32 item_id = GetUInt32Value(visualbase); const ItemPrototype * proto = objmgr.GetItemPrototype(item_id); SpellItemEnchantmentEntry const *enchant = NULL; for(uint8 enchantSlot = PERM_ENCHANTMENT_SLOT; enchantSlot <= TEMP_ENCHANTMENT_SLOT; ++enchantSlot) { - uint32 enchantId = GetUInt32Value(visualbase+1+enchantSlot); + uint32 enchantId = GetUInt16Value(visualbase + 1, enchantSlot); if(enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId)) break; } @@ -1645,6 +1645,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati // reset movement flags at teleport, because player will continue move with these flags after teleport SetUnitMovementFlags(0); + m_movementInfo.flags = 0; if (m_transport) { @@ -2423,6 +2424,8 @@ void Player::InitTalentForLevel() else SetFreeTalentPoints(talentPointsForLevel-m_usedTalentCount); } + + SendTalentsInfoData(false); // update at client } void Player::InitStatsForLevel(bool reapplyMods) @@ -2603,7 +2606,7 @@ void Player::SendInitialSpells() if(!itr->second->active || itr->second->disabled) continue; - data << uint16(itr->first); + data << uint32(itr->first); data << uint16(0); // it's not slot id spellCount +=1; @@ -2623,7 +2626,7 @@ void Player::SendInitialSpells() if(itr->second.end > infTime) continue; - data << uint16(itr->first); + data << uint32(itr->first); time_t cooldown = 0; if(itr->second.end > curTime) @@ -2816,15 +2819,15 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen if(next_active_spell_id) { // update spell ranks in spellbook and action bar - WorldPacket data(SMSG_SUPERCEDED_SPELL, (4)); - data << uint16(spell_id); - data << uint16(next_active_spell_id); + WorldPacket data(SMSG_SUPERCEDED_SPELL, 4 + 4); + data << uint32(spell_id); + data << uint32(next_active_spell_id); GetSession()->SendPacket( &data ); } else { WorldPacket data(SMSG_REMOVED_SPELL, 4); - data << uint16(spell_id); + data << uint32(spell_id); GetSession()->SendPacket(&data); } } @@ -2915,9 +2918,9 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen { if(IsInWorld()) // not send spell (re-/over-)learn packets at loading { - WorldPacket data(SMSG_SUPERCEDED_SPELL, (4)); - data << uint16(itr2->first); - data << uint16(spell_id); + WorldPacket data(SMSG_SUPERCEDED_SPELL, 4 + 4); + data << uint32(itr2->first); + data << uint32(spell_id); GetSession()->SendPacket( &data ); } @@ -2931,9 +2934,9 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen { if(IsInWorld()) // not send spell (re-/over-)learn packets at loading { - WorldPacket data(SMSG_SUPERCEDED_SPELL, (4)); - data << uint16(spell_id); - data << uint16(itr2->first); + WorldPacket data(SMSG_SUPERCEDED_SPELL, 4 + 4); + data << uint32(spell_id); + data << uint32(itr2->first); GetSession()->SendPacket( &data ); } @@ -3325,9 +3328,9 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool update_action_bar_ if(update_action_bar_for_low_rank) { // downgrade spell ranks in spellbook and action bar - WorldPacket data(SMSG_SUPERCEDED_SPELL, (4)); - data << uint16(spell_id); - data << uint16(prev_id); + WorldPacket data(SMSG_SUPERCEDED_SPELL, 4 + 4); + data << uint32(spell_id); + data << uint32(prev_id); GetSession()->SendPacket( &data ); prev_activate = true; } @@ -3341,7 +3344,7 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool update_action_bar_ if(!prev_activate) { WorldPacket data(SMSG_REMOVED_SPELL, 4); - data << uint16(spell_id); + data << uint32(spell_id); GetSession()->SendPacket(&data); } } @@ -3727,23 +3730,12 @@ void Player::InitVisibleBits() // Players visible items are not inventory stuff for(uint16 i = 0; i < EQUIPMENT_SLOT_END; ++i) { - uint32 offset = i * MAX_VISIBLE_ITEM_OFFSET; - - // item creator - updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_CREATOR + 0 + offset); - updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_CREATOR + 1 + offset); + uint32 offset = i * 2; // item entry - updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_0 + 0 + offset); - - // item enchantments - for(uint8 j = 0; j < MAX_ENCHANTMENT_SLOT; ++j) - updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_0 + 1 + j + offset); - - // random properties - updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_PROPERTIES + offset); - updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_SEED + offset); - updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_PAD + offset); + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_ENTRYID + offset); + // enchant + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + offset); } updateVisualBits.SetBit(PLAYER_CHOSEN_TITLE); @@ -3768,7 +3760,7 @@ void Player::BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target ) m_items[i]->BuildCreateUpdateBlockForPlayer( data, target ); } - for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i) { if(m_items[i] == NULL) continue; @@ -3801,7 +3793,7 @@ void Player::DestroyForPlayer( Player *target ) const m_items[i]->DestroyForPlayer( target ); } - for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i) { if(m_items[i] == NULL) continue; @@ -4022,6 +4014,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC CharacterDatabase.PExecute("DELETE FROM character_pet_declinedname WHERE owner = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_achievement WHERE guid = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_achievement_progress WHERE guid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_equipmentsets WHERE guid = '%u'",guid); CharacterDatabase.CommitTransaction(); //LoginDatabase.PExecute("UPDATE realmcharacters SET numchars = numchars - 1 WHERE acctid = %d AND realmid = %d", accountId, realmID); @@ -5540,7 +5533,8 @@ void Player::SendInitialActionButtons() const { sLog.outDetail( "Initializing Action Buttons for '%u'", GetGUIDLow() ); - WorldPacket data(SMSG_ACTION_BUTTONS, (MAX_ACTION_BUTTONS*4)); + WorldPacket data(SMSG_ACTION_BUTTONS, 1+(MAX_ACTION_BUTTONS*4)); + data << uint8(0); // can be 0, 1, 2 for(int button = 0; button < MAX_ACTION_BUTTONS; ++button) { ActionButtonList::const_iterator itr = m_actionButtons.find(button); @@ -8462,7 +8456,7 @@ uint8 Player::CanUnequipItems( uint32 item, uint32 count ) const return EQUIP_ERR_OK; } } - for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i) { pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && pItem->GetEntry() == item ) @@ -8504,7 +8498,7 @@ uint32 Player::GetItemCount( uint32 item, bool inBankAlso, Item* skipItem ) cons if( pItem && pItem != skipItem && pItem->GetEntry() == item ) count += pItem->GetCount(); } - for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i) { Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && pItem != skipItem && pItem->GetEntry() == item ) @@ -8564,7 +8558,7 @@ Item* Player::GetItemByGuid( uint64 guid ) const if( pItem && pItem->GetGUID() == guid ) return pItem; } - for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i) { Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && pItem->GetGUID() == guid ) @@ -8610,7 +8604,7 @@ Item* Player::GetItemByPos( uint16 pos ) const Item* Player::GetItemByPos( uint8 bag, uint8 slot ) const { - if( bag == INVENTORY_SLOT_BAG_0 && ( slot < BANK_SLOT_BAG_END || slot >= KEYRING_SLOT_START && slot < QUESTBAG_SLOT_END ) ) + if( bag == INVENTORY_SLOT_BAG_0 && ( slot < BANK_SLOT_BAG_END || slot >= KEYRING_SLOT_START && slot < CURRENCYTOKEN_SLOT_END ) ) return m_items[slot]; else if(bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END || bag >= BANK_SLOT_BAG_START && bag < BANK_SLOT_BAG_END ) @@ -8680,7 +8674,7 @@ bool Player::IsInventoryPos( uint8 bag, uint8 slot ) return true; if( bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END ) return true; - if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= KEYRING_SLOT_START && slot < QUESTBAG_SLOT_END ) ) + if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= KEYRING_SLOT_START && slot < CURRENCYTOKEN_SLOT_END ) ) return true; return false; } @@ -8801,7 +8795,7 @@ bool Player::HasItemCount( uint32 item, uint32 count, bool inBankAlso ) const return true; } } - for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i) { Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && pItem->GetEntry() == item ) @@ -8968,7 +8962,7 @@ bool Player::HasItemTotemCategory( uint32 TotemCategory ) const if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) return true; } - for(uint8 i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; ++i) + for(uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i) { pItem = GetUseableItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) @@ -9008,18 +9002,10 @@ uint8 Player::_CanStoreItem_InSpecificSlot( uint8 bag, uint8 slot, ItemPosCountV if(slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_START+GetMaxKeyringSize() && !(pProto->BagFamily & BAG_FAMILY_MASK_KEYS)) return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; - // vanitypet case (not use, vanity pets stored as spells) - if(slot >= VANITYPET_SLOT_START && slot < VANITYPET_SLOT_END) - return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; - // currencytoken case if(slot >= CURRENCYTOKEN_SLOT_START && slot < CURRENCYTOKEN_SLOT_END && !(pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS)) return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; - // guestbag case (not use) - if(slot >= QUESTBAG_SLOT_START && slot < QUESTBAG_SLOT_END) - return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; - // prevent cheating if(slot >= BUYBACK_SLOT_START && slot < BUYBACK_SLOT_END || slot >= PLAYER_SLOT_END) return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; @@ -9265,7 +9251,7 @@ uint8 Player::_CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, uint3 { if( bag == INVENTORY_SLOT_BAG_0 ) // inventory { - res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,QUESTBAG_SLOT_END,dest,pProto,count,true,pItem,bag,slot); + res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,CURRENCYTOKEN_SLOT_END,dest,pProto,count,true,pItem,bag,slot); if(res!=EQUIP_ERR_OK) { if(no_space_count) @@ -9439,7 +9425,7 @@ uint8 Player::_CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, uint3 // search stack for merge to if( pProto->Stackable != 1 ) { - res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,QUESTBAG_SLOT_END,dest,pProto,count,true,pItem,bag,slot); + res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,CURRENCYTOKEN_SLOT_END,dest,pProto,count,true,pItem,bag,slot); if(res!=EQUIP_ERR_OK) { if(no_space_count) @@ -10660,30 +10646,14 @@ void Player::SetVisibleItemSlot(uint8 slot, Item *pItem) { if(pItem) { - SetUInt64Value(PLAYER_VISIBLE_ITEM_1_CREATOR + (slot * MAX_VISIBLE_ITEM_OFFSET), pItem->GetUInt64Value(ITEM_FIELD_CREATOR)); - - int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (slot * MAX_VISIBLE_ITEM_OFFSET); - SetUInt32Value(VisibleBase + 0, pItem->GetEntry()); - - for(int i = 0; i < MAX_INSPECTED_ENCHANTMENT_SLOT; ++i) - SetUInt32Value(VisibleBase + 1 + i, pItem->GetEnchantmentId(EnchantmentSlot(i))); - - // Use SetInt16Value to prevent set high part to FFFF for negative value - SetInt16Value( PLAYER_VISIBLE_ITEM_1_PROPERTIES + (slot * MAX_VISIBLE_ITEM_OFFSET), 0, pItem->GetItemRandomPropertyId()); - SetUInt32Value(PLAYER_VISIBLE_ITEM_1_PROPERTIES + 1 + (slot * MAX_VISIBLE_ITEM_OFFSET), pItem->GetItemSuffixFactor()); + SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (slot * 2), pItem->GetEntry()); + SetUInt16Value(PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + (slot * 2), 0, pItem->GetEnchantmentId(PERM_ENCHANTMENT_SLOT)); + SetUInt16Value(PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + (slot * 2), 1, pItem->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT)); } else { - SetUInt64Value(PLAYER_VISIBLE_ITEM_1_CREATOR + (slot * MAX_VISIBLE_ITEM_OFFSET), 0); - - int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (slot * MAX_VISIBLE_ITEM_OFFSET); - SetUInt32Value(VisibleBase + 0, 0); - - for(int i = 0; i < MAX_INSPECTED_ENCHANTMENT_SLOT; ++i) - SetUInt32Value(VisibleBase + 1 + i, 0); - - SetUInt32Value(PLAYER_VISIBLE_ITEM_1_PROPERTIES + 0 + (slot * MAX_VISIBLE_ITEM_OFFSET), 0); - SetUInt32Value(PLAYER_VISIBLE_ITEM_1_PROPERTIES + 1 + (slot * MAX_VISIBLE_ITEM_OFFSET), 0); + SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (slot * 2), 0); + SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + (slot * 2), 0); } } @@ -10933,7 +10903,7 @@ void Player::DestroyItemCount( uint32 item, uint32 count, bool update, bool uneq } } - for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i) { if (Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i )) { @@ -11038,7 +11008,7 @@ void Player::DestroyZoneLimitedItem( bool update, uint32 new_zone ) if (pItem->IsLimitedToAnotherMapOrZone(GetMapId(), new_zone)) DestroyItem( INVENTORY_SLOT_BAG_0, i, update); - for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i) if (Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i )) if (pItem->IsLimitedToAnotherMapOrZone(GetMapId(), new_zone)) DestroyItem( INVENTORY_SLOT_BAG_0, i, update); @@ -12171,11 +12141,12 @@ void Player::ApplyEnchantment(Item *item, EnchantmentSlot slot, bool apply, bool } // visualize enchantment at player and equipped items - if(slot < MAX_INSPECTED_ENCHANTMENT_SLOT) - { - int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (item->GetSlot() * MAX_VISIBLE_ITEM_OFFSET); - SetUInt32Value(VisibleBase + 1 + slot, apply? item->GetEnchantmentId(slot) : 0); - } + if(slot == PERM_ENCHANTMENT_SLOT) + SetUInt16Value(PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + (item->GetSlot() * 2), 0, apply ? item->GetEnchantmentId(slot) : 0); + + if(slot == TEMP_ENCHANTMENT_SLOT) + SetUInt16Value(PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + (item->GetSlot() * 2), 1, apply ? item->GetEnchantmentId(slot) : 0); + if(apply_dur) { @@ -12275,9 +12246,9 @@ void Player::PrepareQuestMenu( uint64 guid ) uint32 quest_id = i->second; QuestStatus status = GetQuestStatus( quest_id ); if ( status == QUEST_STATUS_COMPLETE && !GetQuestRewardStatus( quest_id ) ) - qm.AddMenuItem(quest_id, DIALOG_STATUS_REWARD_REP); + qm.AddMenuItem(quest_id, DIALOG_STATUS_UNK2); else if ( status == QUEST_STATUS_INCOMPLETE ) - qm.AddMenuItem(quest_id, DIALOG_STATUS_INCOMPLETE); + qm.AddMenuItem(quest_id, DIALOG_STATUS_UNK2); else if (status == QUEST_STATUS_AVAILABLE ) qm.AddMenuItem(quest_id, DIALOG_STATUS_CHAT); } @@ -12291,9 +12262,9 @@ void Player::PrepareQuestMenu( uint64 guid ) QuestStatus status = GetQuestStatus( quest_id ); if (pQuest->IsAutoComplete() && CanTakeQuest(pQuest, false)) - qm.AddMenuItem(quest_id, DIALOG_STATUS_REWARD_REP); + qm.AddMenuItem(quest_id, DIALOG_STATUS_UNK2); else if ( status == QUEST_STATUS_NONE && CanTakeQuest( pQuest, false ) ) - qm.AddMenuItem(quest_id, DIALOG_STATUS_AVAILABLE); + qm.AddMenuItem(quest_id, DIALOG_STATUS_CHAT); } } @@ -12316,10 +12287,10 @@ void Player::SendPreparedQuest( uint64 guid ) if ( pQuest ) { - if( status == DIALOG_STATUS_REWARD_REP && !GetQuestRewardStatus( quest_id ) ) + if( status == DIALOG_STATUS_UNK2 && !GetQuestRewardStatus( quest_id ) ) + PlayerTalkClass->SendQuestGiverRequestItems( pQuest, guid, CanRewardQuest(pQuest, false), true ); + else if( status == DIALOG_STATUS_UNK2 ) PlayerTalkClass->SendQuestGiverRequestItems( pQuest, guid, CanRewardQuest(pQuest, false), true ); - else if( status == DIALOG_STATUS_INCOMPLETE ) - PlayerTalkClass->SendQuestGiverRequestItems( pQuest, guid, false, true ); // Send completable on repeatable quest if player don't have quest else if( pQuest->IsRepeatable() && !pQuest->IsDaily() ) PlayerTalkClass->SendQuestGiverRequestItems( pQuest, guid, CanCompleteRepeatableQuest(pQuest), true ); @@ -14119,6 +14090,38 @@ void Player::_LoadArenaTeamInfo(QueryResult *result) delete result; } +void Player::_LoadEquipmentSets(QueryResult *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)); + if (!result) + return; + + uint32 count = 0; + do + { + Field *fields = result->Fetch(); + + EquipmentSet eqSet; + + eqSet.Guid = fields[0].GetUInt64(); + uint32 index = fields[1].GetUInt32(); + eqSet.Name = fields[2].GetCppString(); + eqSet.IconName = fields[3].GetCppString(); + eqSet.state = EQUIPMENT_SET_UNCHANGED; + + for(uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) + eqSet.Items[i] = fields[4+i].GetUInt32(); + + m_EquipmentSets[index] = eqSet; + + ++count; + + if(count >= MAX_EQUIPMENT_SET_INDEX) // client limit + break; + } while (result->NextRow()); + delete result; +} + bool Player::LoadPositionFromDB(uint32& mapid, float& x,float& y,float& z,float& o, bool& in_flight, uint64 guid) { QueryResult *result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,taxi_path FROM characters WHERE guid = '%u'",GUID_LOPART(guid)); @@ -14662,8 +14665,6 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) InitTalentForLevel(); learnDefaultSpells(); - _LoadTutorials(holder->GetResult(PLAYER_LOGIN_QUERY_LOADTUTORIALS)); - // must be before inventory (some items required reputation check) m_reputationMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADREPUTATION)); @@ -14808,6 +14809,9 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) m_achievementMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS), holder->GetResult(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS)); m_achievementMgr.CheckAllAchievementCriteria(); + + _LoadEquipmentSets(holder->GetResult(PLAYER_LOGIN_QUERY_LOADEQUIPMENTSETS)); + return true; } @@ -15426,27 +15430,6 @@ void Player::_LoadSpells(QueryResult *result) } } -void Player::_LoadTutorials(QueryResult *result) -{ - //QueryResult *result = CharacterDatabase.PQuery("SELECT tut0,tut1,tut2,tut3,tut4,tut5,tut6,tut7 FROM character_tutorial WHERE account = '%u' AND realmid = '%u'", GetAccountId(), realmid); - - if(result) - { - do - { - Field *fields = result->Fetch(); - - for (int iI=0; iI<8; iI++) - m_Tutorials[iI] = fields[iI].GetUInt32(); - } - while( result->NextRow() ); - - delete result; - } - - m_TutorialsChanged = false; -} - void Player::_LoadGroup(QueryResult *result) { //QueryResult *result = CharacterDatabase.PQuery("SELECT leaderGuid FROM group_member WHERE memberGuid='%u'", GetGUIDLow()); @@ -15961,13 +15944,14 @@ void Player::SaveToDB() _SaveInventory(); _SaveQuestStatus(); _SaveDailyQuestStatus(); - _SaveTutorials(); _SaveSpells(); _SaveSpellCooldowns(); _SaveActions(); _SaveAuras(); m_achievementMgr.SaveToDB(); m_reputationMgr.SaveToDB(); + _SaveEquipmentSets(); + GetSession()->SaveTutorialsData(); // changed only while character in game CharacterDatabase.CommitTransaction(); @@ -16248,33 +16232,6 @@ void Player::_SaveSpells() } } -void Player::_SaveTutorials() -{ - if(!m_TutorialsChanged) - return; - - uint32 Rows=0; - // it's better than rebuilding indexes multiple times - QueryResult *result = CharacterDatabase.PQuery("SELECT count(*) AS r FROM character_tutorial WHERE account = '%u' AND realmid = '%u'", GetSession()->GetAccountId(), realmID ); - if(result) - { - Rows = result->Fetch()[0].GetUInt32(); - delete result; - } - - if (Rows) - { - CharacterDatabase.PExecute("UPDATE character_tutorial SET tut0='%u', tut1='%u', tut2='%u', tut3='%u', tut4='%u', tut5='%u', tut6='%u', tut7='%u' WHERE account = '%u' AND realmid = '%u'", - m_Tutorials[0], m_Tutorials[1], m_Tutorials[2], m_Tutorials[3], m_Tutorials[4], m_Tutorials[5], m_Tutorials[6], m_Tutorials[7], GetSession()->GetAccountId(), realmID ); - } - else - { - CharacterDatabase.PExecute("INSERT INTO character_tutorial (account,realmid,tut0,tut1,tut2,tut3,tut4,tut5,tut6,tut7) VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", GetSession()->GetAccountId(), realmID, m_Tutorials[0], m_Tutorials[1], m_Tutorials[2], m_Tutorials[3], m_Tutorials[4], m_Tutorials[5], m_Tutorials[6], m_Tutorials[7]); - }; - - m_TutorialsChanged = false; -} - void Player::outDebugValues() const { if(!sLog.IsOutDebug()) // optimize disabled debug output @@ -16711,9 +16668,8 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent) if(pet->isControlled()) { - WorldPacket data(SMSG_PET_SPELLS, 8+4); + WorldPacket data(SMSG_PET_SPELLS, 8); data << uint64(0); - data << uint32(0); GetSession()->SendPacket(&data); if(GetGroup()) @@ -16843,9 +16799,9 @@ void Player::PetSpellInitialize() CharmInfo *charmInfo = pet->GetCharmInfo(); - WorldPacket data(SMSG_PET_SPELLS, 8+4+4+4+4*MAX_UNIT_ACTION_BAR_INDEX+1+1); + WorldPacket data(SMSG_PET_SPELLS, 8+2+4+4+4*MAX_UNIT_ACTION_BAR_INDEX+1+1); data << uint64(pet->GetGUID()); - data << uint32(pet->GetCreatureInfo()->family); // creature family (required for pet talents) + data << uint16(pet->GetCreatureInfo()->family); // creature family (required for pet talents) data << uint32(0); data << uint8(pet->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0); @@ -16883,7 +16839,7 @@ void Player::PetSpellInitialize() { time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILISECONDS : 0; - data << uint16(itr->first); // spellid + data << uint32(itr->first); // spellid data << uint16(0); // spell category? data << uint32(cooldown); // cooldown data << uint32(0); // category cooldown @@ -16893,7 +16849,7 @@ void Player::PetSpellInitialize() { time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILISECONDS : 0; - data << uint16(itr->first); // spellid + data << uint32(itr->first); // spellid data << uint16(0); // spell category? data << uint32(0); // cooldown data << uint32(cooldown); // category cooldown @@ -16918,9 +16874,9 @@ void Player::PossessSpellInitialize() return; } - WorldPacket data(SMSG_PET_SPELLS, 8+4+4+4+4*MAX_UNIT_ACTION_BAR_INDEX+1+1); + WorldPacket data(SMSG_PET_SPELLS, 8+2+4+4+4*MAX_UNIT_ACTION_BAR_INDEX+1+1); data << uint64(charm->GetGUID()); - data << uint32(0); + data << uint16(0); data << uint32(0); data << uint32(0); @@ -16938,10 +16894,10 @@ void Player::VehicleSpellInitialize() if(!charm) return; - WorldPacket data(SMSG_PET_SPELLS, 8+4+4+4+4*10+1+1); + WorldPacket data(SMSG_PET_SPELLS, 8+2+4+4+4*10+1+1); data << uint64(charm->GetGUID()); - data << uint32(0x00000000); - data << uint32(0x00000000); + data << uint16(0); + data << uint32(0); data << uint32(0x00000101); for(uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i) @@ -16998,9 +16954,9 @@ void Player::CharmSpellInitialize() } } - WorldPacket data(SMSG_PET_SPELLS, 8+4+4+4+4*MAX_UNIT_ACTION_BAR_INDEX+1+4*addlist+1); + WorldPacket data(SMSG_PET_SPELLS, 8+2+4+4+4*MAX_UNIT_ACTION_BAR_INDEX+1+4*addlist+1); data << uint64(charm->GetGUID()); - data << uint32(0); + data << uint16(0); data << uint32(0); if(charm->GetTypeId() != TYPEID_PLAYER) @@ -17032,9 +16988,8 @@ void Player::CharmSpellInitialize() void Player::SendRemoveControlBar() { - WorldPacket data(SMSG_PET_SPELLS, 8+4); + WorldPacket data(SMSG_PET_SPELLS, 8); data << uint64(0); - data << uint32(0); GetSession()->SendPacket(&data); } @@ -17892,8 +17847,8 @@ void Player::UpdateHomebindTime(uint32 time) { if (time >= m_HomebindTimer) { - // teleport to homebind location - TeleportTo(m_homebindMapId, m_homebindX, m_homebindY, m_homebindZ, GetOrientation()); + // teleport to nearest graveyard + RepopAtGraveyard(); } else m_HomebindTimer -= time; @@ -18680,6 +18635,8 @@ void Player::SendInitialPacketsBeforeAddToMap() data << uint32(0); // unknown, may be rest state time or experience GetSession()->SendPacket(&data); + GetSocial()->SendSocialList(); + // Homebind data.Initialize(SMSG_BINDPOINTUPDATE, 5*4); data << m_homebindX << m_homebindY << m_homebindZ; @@ -18690,12 +18647,7 @@ void Player::SendInitialPacketsBeforeAddToMap() // SMSG_SET_PROFICIENCY // SMSG_UPDATE_AURA_DURATION - // tutorial stuff - data.Initialize(SMSG_TUTORIAL_FLAGS, 8*4); - for (int i = 0; i < 8; ++i) - data << uint32( GetTutorialInt(i) ); - GetSession()->SendPacket(&data); - + SendTalentsInfoData(false); SendInitialSpells(); data.Initialize(SMSG_SEND_UNLEARN_SPELLS, 4); @@ -18711,16 +18663,13 @@ void Player::SendInitialPacketsBeforeAddToMap() GetZoneAndAreaId(newzone,newarea); UpdateZone(newzone,newarea); // also call SendInitWorldStates(); - // SMSG_SET_AURA_SINGLE + SendEquipmentSetList(); - data.Initialize(SMSG_LOGIN_SETTIMESPEED, 8); + data.Initialize(SMSG_LOGIN_SETTIMESPEED, 4 + 4 + 4); data << uint32(secsToTimeBitFields(sWorld.GetGameTime())); data << (float)0.01666667f; // game speed + data << uint32(0); // added in 3.1.2 GetSession()->SendPacket( &data ); - - // set fly flag if in fly form or taxi flight to prevent visually drop at ground in showup moment - //if(HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || isInFlight()) - // AddUnitMovementFlag(MOVEMENTFLAG_FLYING2); } void Player::SendInitialPacketsAfterAddToMap() @@ -20076,7 +20025,7 @@ bool Player::isTotalImmune() bool Player::HasTitle(uint32 bitIndex) { - if (bitIndex > 128) + if (bitIndex > 192) return false; uint32 fieldIndexOffset = bitIndex / 32; @@ -20773,3 +20722,314 @@ bool Player::canSeeSpellClickOn(Creature const *c) const } return false; } + +void Player::BuildPlayerTalentsInfoData(WorldPacket *data) +{ + *data << uint32(GetFreeTalentPoints()); // unspentTalentPoints + uint8 talentGroupCount = 1; + *data << uint8(talentGroupCount); // talent group count (0, 1 or 2) + *data << uint8(0); // talent group index (0 or 1) + + if(talentGroupCount) + { + // loop through all specs (only 1 for now) + for(uint32 groups = 0; groups < talentGroupCount; ++groups) + { + 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 + + *data << uint8(MAX_GLYPH_SLOT_INDEX); // glyphs count + + for(uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i) + *data << uint16(GetGlyph(i)); // GlyphProperties.dbc + } + } +} + +void Player::BuildPetTalentsInfoData(WorldPacket *data) +{ + uint32 unspentTalentPoints = 0; + size_t pointsPos = data->wpos(); + *data << uint32(unspentTalentPoints); // [PH], unspentTalentPoints + + uint8 talentIdCount = 0; + size_t countPos = data->wpos(); + *data << uint8(talentIdCount); // [PH], talentIdCount + + Pet *pet = GetPet(); + if(!pet) + return; + + unspentTalentPoints = pet->GetFreeTalentPoints(); + + data->put<uint32>(pointsPos, unspentTalentPoints); // put real points + + CreatureInfo const *ci = pet->GetCreatureInfo(); + if(!ci) + return; + + CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family); + if(!pet_family || pet_family->petTalentType < 0) + return; + + for(uint32 talentTabId = 1; talentTabId < sTalentTabStore.GetNumRows(); ++talentTabId) + { + TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentTabId ); + if(!talentTabInfo) + continue; + + if(!((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask)) + continue; + + 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] && pet->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>(countPos, talentIdCount); // put real count + + break; + } +} + +void Player::SendTalentsInfoData(bool pet) +{ + WorldPacket data(SMSG_TALENTS_INFO, 50); + data << uint8(pet ? 1 : 0); + if(pet) + BuildPetTalentsInfoData(&data); + else + BuildPlayerTalentsInfoData(&data); + GetSession()->SendPacket(&data); +} + +void Player::BuildEnchantmentsInfoData(WorldPacket *data) +{ + uint32 slotUsedMask = 0; + size_t slotUsedMaskPos = data->wpos(); + *data << uint32(slotUsedMask); // slotUsedMask < 0x80000 + + for(uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) + { + Item *item = GetItemByPos(INVENTORY_SLOT_BAG_0, i); + + if(!item) + continue; + + slotUsedMask |= (1 << i); + + *data << uint32(item->GetEntry()); // item entry + + uint16 enchantmentMask = 0; + size_t enchantmentMaskPos = data->wpos(); + *data << uint16(enchantmentMask); // enchantmentMask < 0x1000 + + for(uint32 j = 0; j < MAX_ENCHANTMENT_SLOT; ++j) + { + uint32 enchId = item->GetEnchantmentId(EnchantmentSlot(j)); + + if(!enchId) + continue; + + enchantmentMask |= (1 << j); + + *data << uint16(enchId); // enchantmentId? + } + + data->put<uint16>(enchantmentMaskPos, enchantmentMask); + + *data << uint16(0); // ? + *data << uint8(0); // PGUID! + *data << uint32(0); // seed? + } + + data->put<uint32>(slotUsedMaskPos, slotUsedMask); +} + +void Player::SendEquipmentSetList() +{ + uint32 count = 0; + WorldPacket data(SMSG_EQUIPMENT_SET_LIST, 4); + size_t count_pos = data.wpos(); + data << uint32(count); // count placeholder + for(EquipmentSets::iterator itr = m_EquipmentSets.begin(); itr != m_EquipmentSets.end(); ++itr) + { + if(itr->second.state==EQUIPMENT_SET_DELETED) + continue; + data.appendPackGUID(itr->second.Guid); + data << uint32(itr->first); + data << itr->second.Name; + data << itr->second.IconName; + for(uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) + data.appendPackGUID(MAKE_NEW_GUID(itr->second.Items[i], 0, HIGHGUID_ITEM)); + + ++count; // client have limit but it checked at loading and set + } + data.put<uint32>(count_pos, count); + GetSession()->SendPacket(&data); +} + +void Player::SetEquipmentSet(uint32 index, EquipmentSet eqset) +{ + if(eqset.Guid != 0) + { + bool found = false; + + for(EquipmentSets::iterator itr = m_EquipmentSets.begin(); itr != m_EquipmentSets.end(); ++itr) + { + if((itr->second.Guid == eqset.Guid) && (itr->first == index)) + { + found = true; + break; + } + } + + if(!found) // something wrong... + { + sLog.outError("Player %s tried to save equipment set "UI64FMTD" (index %u), but that equipment set not found!", GetName(), eqset.Guid, index); + return; + } + } + + EquipmentSet& eqslot = m_EquipmentSets[index]; + + EquipmentSetUpdateState old_state = eqslot.state; + + eqslot = eqset; + + if(eqset.Guid == 0) + { + eqslot.Guid = objmgr.GenerateEquipmentSetGuid(); + + WorldPacket data(SMSG_EQUIPMENT_SET_SAVED, 4 + 1); + data << uint32(index); + data.appendPackGUID(eqslot.Guid); + GetSession()->SendPacket(&data); + } + + eqslot.state = old_state == EQUIPMENT_SET_NEW ? EQUIPMENT_SET_NEW : EQUIPMENT_SET_CHANGED; +} + +void Player::_SaveEquipmentSets() +{ + for(EquipmentSets::iterator itr = m_EquipmentSets.begin(); itr != m_EquipmentSets.end();) + { + uint32 index = itr->first; + EquipmentSet& eqset = itr->second; + switch(eqset.state) + { + case EQUIPMENT_SET_UNCHANGED: + ++itr; + break; // nothing do + case EQUIPMENT_SET_CHANGED: + CharacterDatabase.PExecute("UPDATE character_equipmentsets SET name='%s', iconname='%s', item0='%u', item1='%u', item2='%u', item3='%u', item4='%u', item5='%u', item6='%u', item7='%u', item8='%u', item9='%u', item10='%u', item11='%u', item12='%u', item13='%u', item14='%u', item15='%u', item16='%u', item17='%u', item18='%u' WHERE guid='%u' AND setguid='"UI64FMTD"' AND setindex='%u'", + eqset.Name.c_str(), eqset.IconName.c_str(), eqset.Items[0], eqset.Items[1], eqset.Items[2], eqset.Items[3], eqset.Items[4], eqset.Items[5], eqset.Items[6], eqset.Items[7], + eqset.Items[8], eqset.Items[9], eqset.Items[10], eqset.Items[11], eqset.Items[12], eqset.Items[13], eqset.Items[14], eqset.Items[15], eqset.Items[16], eqset.Items[17], eqset.Items[18], GetGUIDLow(), eqset.Guid, index); + eqset.state = EQUIPMENT_SET_UNCHANGED; + ++itr; + break; + case EQUIPMENT_SET_NEW: + CharacterDatabase.PExecute("INSERT INTO character_equipmentsets VALUES ('%u', '"UI64FMTD"', '%u', '%s', '%s', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", + GetGUIDLow(), eqset.Guid, index, eqset.Name.c_str(), eqset.IconName.c_str(), eqset.Items[0], eqset.Items[1], eqset.Items[2], eqset.Items[3], eqset.Items[4], eqset.Items[5], eqset.Items[6], eqset.Items[7], + eqset.Items[8], eqset.Items[9], eqset.Items[10], eqset.Items[11], eqset.Items[12], eqset.Items[13], eqset.Items[14], eqset.Items[15], eqset.Items[16], eqset.Items[17], eqset.Items[18]); + eqset.state = EQUIPMENT_SET_UNCHANGED; + ++itr; + break; + case EQUIPMENT_SET_DELETED: + CharacterDatabase.PExecute("DELETE FROM character_equipmentsets WHERE setguid="UI64FMTD, eqset.Guid); + m_EquipmentSets.erase(itr++); + break; + } + } +} + +void Player::DeleteEquipmentSet(uint64 setGuid) +{ + for(EquipmentSets::iterator itr = m_EquipmentSets.begin(); itr != m_EquipmentSets.end(); ++itr) + { + if(itr->second.Guid == setGuid) + { + if(itr->second.state == EQUIPMENT_SET_NEW) + m_EquipmentSets.erase(itr); + else + itr->second.state = EQUIPMENT_SET_DELETED; + break; + } + } +} + +void Player::ActivateSpec(uint32 specNum) +{ + if(GetActiveSpec() == specNum) + return; + + resetTalents(true); +}
\ No newline at end of file |