Implement group loot for chest having GroupLootRules (go type=3, data15=1).

Implement round robin loot.
Implement round robin for underthreshold items (group loot and need befor greed).
Fix "all players pass" bug on creature.
Add SMSG_LOOT_LIST message to indicate looter (round robin or master).
And some other minor loot bugs.

Fixes issue #167.
Fixes issue #247.

--HG--
branch : trunk
This commit is contained in:
Trazom62
2010-03-11 22:55:02 +01:00
parent d9f257a18c
commit ed8c5ef6ff
10 changed files with 578 additions and 257 deletions

View File

@@ -274,7 +274,7 @@ void WorldSession::HandleLootReleaseOpcode( WorldPacket & recv_data )
DoLootRelease(lguid);
}
void WorldSession::DoLootRelease( uint64 lguid )
void WorldSession::DoLootRelease(uint64 lguid)
{
Player *player = GetPlayer();
Loot *loot;
@@ -284,7 +284,7 @@ void WorldSession::DoLootRelease( uint64 lguid )
player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING);
if(!player->IsInWorld())
if (!player->IsInWorld())
return;
if (IS_GAMEOBJECT_GUID(lguid))
@@ -364,13 +364,29 @@ void WorldSession::DoLootRelease( uint64 lguid )
loot->clear();
}
else
{
// not fully looted object
go->SetLootState(GO_ACTIVATED);
// if the round robin player release, reset it.
if (player->GetGUID() == loot->roundRobinPlayer)
{
if (Group* pGroup = player->GetGroup())
{
if (pGroup->GetLootMethod() != MASTER_LOOT)
{
loot->roundRobinPlayer = 0;
}
}
else
loot->roundRobinPlayer = 0;
}
}
}
else if (IS_CORPSE_GUID(lguid)) // ONLY remove insignia at BG
{
Corpse *corpse = ObjectAccessor::GetCorpse(*player, lguid);
if (!corpse || !corpse->IsWithinDistInMap(_player,INTERACTION_DISTANCE) )
if (!corpse || !corpse->IsWithinDistInMap(_player,INTERACTION_DISTANCE))
return;
loot = &corpse->loot;
@@ -384,13 +400,13 @@ void WorldSession::DoLootRelease( uint64 lguid )
else if (IS_ITEM_GUID(lguid))
{
Item *pItem = player->GetItemByGuid(lguid );
if(!pItem)
if (!pItem)
return;
ItemPrototype const* proto = pItem->GetProto();
// destroy only 5 items from stack in case prospecting and milling
if( (proto->BagFamily & (BAG_FAMILY_MASK_MINING_SUPP|BAG_FAMILY_MASK_HERBS)) &&
if ((proto->BagFamily & (BAG_FAMILY_MASK_MINING_SUPP|BAG_FAMILY_MASK_HERBS)) &&
proto->Class == ITEM_CLASS_TRADE_GOODS)
{
pItem->m_lootGenerated = false;
@@ -399,14 +415,14 @@ void WorldSession::DoLootRelease( uint64 lguid )
uint32 count = pItem->GetCount();
// >=5 checked in spell code, but will work for cheating cases also with removing from another stacks.
if(count > 5)
if (count > 5)
count = 5;
player->DestroyItemCount(pItem, count, true);
}
else
// FIXME: item don't must be deleted in case not fully looted state. But this pre-request implement loot saving in DB at item save. Or checting possible.
player->DestroyItem( pItem->GetBagSlot(),pItem->GetSlot(), true);
// FIXME: item must not be deleted in case not fully looted state. But this pre-request implement loot saving in DB at item save. Or cheating possible.
player->DestroyItem(pItem->GetBagSlot(),pItem->GetSlot(), true);
return; // item can be looted only single player
}
else
@@ -414,26 +430,40 @@ void WorldSession::DoLootRelease( uint64 lguid )
Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid);
bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass()==CLASS_ROGUE && pCreature->lootForPickPocketed);
if ( !ok_loot || !pCreature->IsWithinDistInMap(_player,INTERACTION_DISTANCE) )
if (!ok_loot || !pCreature->IsWithinDistInMap(_player,INTERACTION_DISTANCE))
return;
loot = &pCreature->loot;
// update next looter
if(Player *recipient = pCreature->GetLootRecipient())
if(Group* group = recipient->GetGroup())
if (group->GetLooterGuid() == player->GetGUID())
group->UpdateLooterGuid(pCreature);
if (loot->isLooted())
{
// skip pickpocketing loot for speed, skinning timer redunction is no-op in fact
if(!pCreature->isAlive())
if (!pCreature->isAlive())
pCreature->AllLootRemovedFromCorpse();
pCreature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
pCreature->SetLootRecipient(NULL);
loot->clear();
}
else
{
// if the round robin player release, reset it.
if (player->GetGUID() == loot->roundRobinPlayer)
{
if (Group* pGroup = player->GetGroup())
{
if (pGroup->GetLootMethod() != MASTER_LOOT)
{
loot->roundRobinPlayer = 0;
pGroup->SendLooter(pCreature, NULL);
// force update of dynamic flags, otherwise other group's players still not able to loot.
pCreature->ForceValuesUpdateAtIndex(UNIT_DYNAMIC_FLAGS);
}
}
else
loot->roundRobinPlayer = 0;
}
}
}
//Player is not looking at loot list, he doesn't need to see updates on the loot list