/*Loot type MUST be 1-corpse, go 2-skinning/herbalism/minning 3-Fishing */ void Player::SendLoot(uint64 guid,uint8 loot_type, uint32 mapid) { Group * m_Group = m_playerInfo->m_Group; if( !IsInWorld() ) return; Loot * pLoot = NULL; uint32 guidtype = GET_TYPE_FROM_GUID(guid); int8 loot_method; if( m_Group != NULL ) loot_method = m_Group->GetMethod(); else loot_method = PARTY_LOOT_FFA; if(guidtype == HIGHGUID_TYPE_UNIT) { Creature* pCreature = GetMapMgr()->GetCreature(GET_LOWGUID_PART(guid)); if(!pCreature)return; pLoot=&pCreature->loot; m_currentLoot = pCreature->GetGUID(); }else if(guidtype == HIGHGUID_TYPE_GAMEOBJECT) { GameObject* pGO = GetMapMgr()->GetGameObject(GET_LOWGUID_PART(guid)); if(!pGO)return; pGO->SetByte(GAMEOBJECT_BYTES_1, 0,0); pLoot=&pGO->loot; m_currentLoot = pGO->GetGUID(); } else if((guidtype == HIGHGUID_TYPE_PLAYER) ) { Player *p=GetMapMgr()->GetPlayer((uint32)guid); if(!p)return; pLoot=&p->loot; m_currentLoot = p->GetGUID(); } else if( (guidtype == HIGHGUID_TYPE_CORPSE)) { Corpse *pCorpse = objmgr.GetCorpse((uint32)guid); if(!pCorpse)return; pLoot=&pCorpse->loot; m_currentLoot = pCorpse->GetGUID(); } else if( (guidtype == HIGHGUID_TYPE_ITEM) ) { Item *pItem = GetItemInterface()->GetItemByGUID(guid); if(!pItem) return; pLoot = pItem->loot; m_currentLoot = pItem->GetGUID(); } if(!pLoot) { // something whack happened.. damn cheaters.. return; } // add to looter set pLoot->looters.insert( GetLowGUID() ); WorldPacket data, data2(32); data.SetOpcode( SMSG_LOOT_RESPONSE ); m_lootGuid = guid; data << uint64( guid ); data << uint8( loot_type );//loot_type; data << uint32( pLoot->gold ); data << uint8( 0 ); //loot size reserve std::vector<__LootItem>::iterator iter=pLoot->items.begin(); uint32 count= 0; uint8 slottype = 0; for(uint32 x= 0;iter!=pLoot->items.end();iter++,x++) { if (iter->iItemsCount == 0) continue; LooterSet::iterator itr = iter->has_looted.find(GetLowGUID()); if (iter->has_looted.end() != itr) continue; ItemPrototype* itemProto =iter->item.itemproto; if (!itemProto) continue; // check if it's on ML if so only quest items and ffa loot should be shown based on mob if ( loot_method == PARTY_LOOT_MASTER && m_Group && m_Group->GetLooter() != m_playerInfo ) // pass on all ffa_loot and the grey / white items if ( !iter->ffa_loot && !(itemProto->Quality < m_Group->GetThreshold()) ) continue; //quest items check. type 4/5 //quest items that don't start quests. if((itemProto->Bonding == ITEM_BIND_QUEST) && !(itemProto->QuestId) && !HasQuestForItem(itemProto->ItemId)) continue; if((itemProto->Bonding == ITEM_BIND_QUEST2) && !(itemProto->QuestId) && !HasQuestForItem(itemProto->ItemId)) continue; //quest items that start quests need special check to avoid drops all the time. if((itemProto->Bonding == ITEM_BIND_QUEST) && (itemProto->QuestId) && GetQuestLogForEntry(itemProto->QuestId)) continue; if((itemProto->Bonding == ITEM_BIND_QUEST2) && (itemProto->QuestId) && GetQuestLogForEntry(itemProto->QuestId)) continue; if((itemProto->Bonding == ITEM_BIND_QUEST) && (itemProto->QuestId) && HasFinishedQuest(itemProto->QuestId)) continue; if((itemProto->Bonding == ITEM_BIND_QUEST2) && (itemProto->QuestId) && HasFinishedQuest(itemProto->QuestId)) continue; //check for starting item quests that need questlines. if((itemProto->QuestId && itemProto->Bonding != ITEM_BIND_QUEST && itemProto->Bonding != ITEM_BIND_QUEST2)) { bool HasRequiredQuests = true; Quest * pQuest = QuestStorage.LookupEntry(itemProto->QuestId); if(pQuest) { uint32 finishedCount = 0; //check if its a questline. for(uint32 i = 0; i < pQuest->count_requiredquests; i++) { if(pQuest->required_quests[i]) { if(!HasFinishedQuest(pQuest->required_quests[i]) || GetQuestLogForEntry(pQuest->required_quests[i])) { if (!(pQuest->quest_flags & QUEST_FLAG_ONLY_ONE_REQUIRED)) { HasRequiredQuests = false; break; } } else { finishedCount++; } } } if (pQuest->quest_flags & QUEST_FLAG_ONLY_ONE_REQUIRED) { if (finishedCount == 0) continue; } else { if(!HasRequiredQuests) continue; } } } slottype = 0; if(m_Group != NULL && loot_type < 2) { switch(loot_method) { case PARTY_LOOT_MASTER: slottype = 2; break; case PARTY_LOOT_GROUP: case PARTY_LOOT_RR: case PARTY_LOOT_NBG: slottype = 1; break; default: slottype = 0; break; } // only quality items are distributed if(itemProto->Quality < m_Group->GetThreshold()) { slottype = 0; } // if all people passed anyone can loot it? :P if(iter->passed) slottype = 0; // All players passed on the loot //if it is ffa loot and not an masterlooter if(iter->ffa_loot) slottype = 0; } data << uint8( x ); data << uint32( itemProto->ItemId ); data << uint32( iter->iItemsCount );//nr of items of this type data << uint32( iter->item.displayid ); if(iter->iRandomSuffix) { data << uint32( Item::GenerateRandomSuffixFactor( itemProto ) ); data << uint32( -int32( iter->iRandomSuffix->id ) ); } else if(iter->iRandomProperty) { data << uint32( 0 ); data << uint32( iter->iRandomProperty->ID ); } else { data << uint32( 0 ); data << uint32( 0 ); } data << slottype; // "still being rolled for" flag if(slottype == 1) { if(iter->roll == NULL && !iter->passed) { int32 ipid = 0; uint32 factor= 0; if(iter->iRandomProperty) ipid=iter->iRandomProperty->ID; else if(iter->iRandomSuffix) { ipid = -int32(iter->iRandomSuffix->id); factor=Item::GenerateRandomSuffixFactor(iter->item.itemproto); } if(iter->item.itemproto) { iter->roll = new LootRoll(60000, (m_Group != NULL ? m_Group->MemberCount() : 1), guid, x, itemProto->ItemId, factor, uint32(ipid), GetMapMgr()); data2.Initialize(SMSG_LOOT_START_ROLL); data2 << guid; data2 << uint32( mapid ); data2 << uint32( x ); data2 << uint32( itemProto->ItemId ); data2 << uint32( factor ); if(iter->iRandomProperty) data2 << uint32(iter->iRandomProperty->ID); else if(iter->iRandomSuffix) data2 << uint32( ipid ); else data2 << uint32( 0 ); data2 << uint32( iter->iItemsCount ); data2 << uint32( 60000 ); // countdown data2 << uint8( 7 ); // some sort of flags that require research } Group * pGroup = m_playerInfo->m_Group; if(pGroup) { pGroup->Lock(); for(uint32 i = 0; i < pGroup->GetSubGroupCount(); ++i) { for(GroupMembersSet::iterator itr2 = pGroup->GetSubGroup(i)->GetGroupMembersBegin(); itr2 != pGroup->GetSubGroup(i)->GetGroupMembersEnd(); ++itr2) { PlayerInfo *pinfo = *itr2; if( pinfo->m_loggedInPlayer && pinfo->m_loggedInPlayer->GetItemInterface()->CanReceiveItem( itemProto, iter->iItemsCount ) == 0 ) { if( pinfo->m_loggedInPlayer->m_passOnLoot ) iter->roll->PlayerRolled( pinfo->m_loggedInPlayer, 3 ); // passed else pinfo->m_loggedInPlayer->SendPacket( &data2 ); } } } pGroup->Unlock(); } else { m_session->SendPacket(&data2); } } } count++; } data.wpos(13); data << uint8( count ); m_session->SendPacket(&data); SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING ); }
Corpse * ObjectAccessor::GetCorpse(uint32 mapid, float x, float y, uint64 guid) { Corpse * corpse = HashMapHolder<Corpse>::Find(guid); if (corpse && corpse->GetMapId() == mapid) { CellPair p = Looking4group::ComputeCellPair(x,y); if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) { sLog.outLog(LOG_DEFAULT, "ERROR: ObjectAccessor::GetCorpse: invalid coordinates supplied X:%f Y:%f grid cell [%u:%u]", x, y, p.x_coord, p.y_coord); return NULL; } CellPair q = Looking4group::ComputeCellPair(corpse->GetPositionX(), corpse->GetPositionY()); if (q.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || q.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) { sLog.outLog(LOG_DEFAULT, "ERROR: ObjectAccessor::GetCorpse: object " UI64FMTD " has invalid coordinates X:%f Y:%f grid cell [%u:%u]", corpse->GetGUID(), corpse->GetPositionX(), corpse->GetPositionY(), q.x_coord, q.y_coord); return NULL; } int32 dx = int32(p.x_coord) - int32(q.x_coord); int32 dy = int32(p.y_coord) - int32(q.y_coord); if (dx > -2 && dx < 2 && dy > -2 && dy < 2) return corpse; } return NULL; }