mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 07:37:01 +00:00
[9579] Use ObjectGuid in some loot code.
Also use ObjectGuidSet instead std::set<ObjectGuid>
This commit is contained in:
parent
acde81fc54
commit
8416702d7c
13 changed files with 447 additions and 428 deletions
|
|
@ -94,7 +94,7 @@ VisibleNotifier::Notify()
|
||||||
|
|
||||||
// generate outOfRange for not iterate objects
|
// generate outOfRange for not iterate objects
|
||||||
i_data.AddOutOfRangeGUID(i_clientGUIDs);
|
i_data.AddOutOfRangeGUID(i_clientGUIDs);
|
||||||
for(Player::ClientGUIDs::iterator itr = i_clientGUIDs.begin();itr!=i_clientGUIDs.end();++itr)
|
for(ObjectGuidSet::iterator itr = i_clientGUIDs.begin();itr!=i_clientGUIDs.end();++itr)
|
||||||
{
|
{
|
||||||
i_player.m_clientGUIDs.erase(*itr);
|
i_player.m_clientGUIDs.erase(*itr);
|
||||||
|
|
||||||
|
|
@ -123,8 +123,8 @@ VisibleNotifier::Notify()
|
||||||
i_player.GetSession()->SendPacket(&packet);
|
i_player.GetSession()->SendPacket(&packet);
|
||||||
|
|
||||||
// send out of range to other players if need
|
// send out of range to other players if need
|
||||||
std::set<ObjectGuid> const& oor = i_data.GetOutOfRangeGUIDs();
|
ObjectGuidSet const& oor = i_data.GetOutOfRangeGUIDs();
|
||||||
for(std::set<ObjectGuid>::const_iterator iter = oor.begin(); iter != oor.end(); ++iter)
|
for(ObjectGuidSet::const_iterator iter = oor.begin(); iter != oor.end(); ++iter)
|
||||||
{
|
{
|
||||||
if(!iter->IsPlayer())
|
if(!iter->IsPlayer())
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ namespace MaNGOS
|
||||||
Player &i_player;
|
Player &i_player;
|
||||||
UpdateData i_data;
|
UpdateData i_data;
|
||||||
UpdateDataMapType i_data_updates;
|
UpdateDataMapType i_data_updates;
|
||||||
Player::ClientGUIDs i_clientGUIDs;
|
ObjectGuidSet i_clientGUIDs;
|
||||||
std::set<WorldObject*> i_visibleNow;
|
std::set<WorldObject*> i_visibleNow;
|
||||||
|
|
||||||
explicit VisibleNotifier(Player &player) : i_player(player),i_clientGUIDs(player.m_clientGUIDs) {}
|
explicit VisibleNotifier(Player &player) : i_player(player),i_clientGUIDs(player.m_clientGUIDs) {}
|
||||||
|
|
|
||||||
|
|
@ -35,60 +35,72 @@ void WorldSession::HandleAutostoreLootItemOpcode( WorldPacket & recv_data )
|
||||||
{
|
{
|
||||||
sLog.outDebug("WORLD: CMSG_AUTOSTORE_LOOT_ITEM");
|
sLog.outDebug("WORLD: CMSG_AUTOSTORE_LOOT_ITEM");
|
||||||
Player *player = GetPlayer();
|
Player *player = GetPlayer();
|
||||||
uint64 lguid = player->GetLootGUID();
|
ObjectGuid lguid = player->GetLootGUID();
|
||||||
Loot *loot;
|
Loot *loot;
|
||||||
uint8 lootSlot;
|
uint8 lootSlot;
|
||||||
|
|
||||||
recv_data >> lootSlot;
|
recv_data >> lootSlot;
|
||||||
|
|
||||||
if (IS_GAMEOBJECT_GUID(lguid))
|
switch( lguid.GetHigh())
|
||||||
{
|
{
|
||||||
GameObject *go = player->GetMap()->GetGameObject(lguid);
|
case HIGHGUID_GAMEOBJECT:
|
||||||
|
|
||||||
// not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO
|
|
||||||
if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player,INTERACTION_DISTANCE)))
|
|
||||||
{
|
{
|
||||||
player->SendLootRelease(lguid);
|
GameObject *go = player->GetMap()->GetGameObject(lguid);
|
||||||
|
|
||||||
|
// not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO
|
||||||
|
if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player,INTERACTION_DISTANCE)))
|
||||||
|
{
|
||||||
|
player->SendLootRelease(lguid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loot = &go->loot;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HIGHGUID_ITEM:
|
||||||
|
{
|
||||||
|
Item *pItem = player->GetItemByGuid( lguid );
|
||||||
|
|
||||||
|
if (!pItem)
|
||||||
|
{
|
||||||
|
player->SendLootRelease(lguid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loot = &pItem->loot;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HIGHGUID_CORPSE:
|
||||||
|
{
|
||||||
|
Corpse *bones = player->GetMap()->GetCorpse(lguid);
|
||||||
|
if (!bones)
|
||||||
|
{
|
||||||
|
player->SendLootRelease(lguid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loot = &bones->loot;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HIGHGUID_UNIT:
|
||||||
|
{
|
||||||
|
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) )
|
||||||
|
{
|
||||||
|
player->SendLootRelease(lguid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loot = &pCreature->loot;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
sLog.outError("%s is unsupported for looting.",lguid.GetString().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
loot = &go->loot;
|
|
||||||
}
|
|
||||||
else if (IS_ITEM_GUID(lguid))
|
|
||||||
{
|
|
||||||
Item *pItem = player->GetItemByGuid( lguid );
|
|
||||||
|
|
||||||
if (!pItem)
|
|
||||||
{
|
|
||||||
player->SendLootRelease(lguid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
loot = &pItem->loot;
|
|
||||||
}
|
|
||||||
else if (IS_CORPSE_GUID(lguid))
|
|
||||||
{
|
|
||||||
Corpse *bones = player->GetMap()->GetCorpse(lguid);
|
|
||||||
if (!bones)
|
|
||||||
{
|
|
||||||
player->SendLootRelease(lguid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
loot = &bones->loot;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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) )
|
|
||||||
{
|
|
||||||
player->SendLootRelease(lguid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
loot = &pCreature->loot;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QuestItem *qitem = NULL;
|
QuestItem *qitem = NULL;
|
||||||
|
|
@ -162,13 +174,13 @@ void WorldSession::HandleLootMoneyOpcode( WorldPacket & /*recv_data*/ )
|
||||||
sLog.outDebug("WORLD: CMSG_LOOT_MONEY");
|
sLog.outDebug("WORLD: CMSG_LOOT_MONEY");
|
||||||
|
|
||||||
Player *player = GetPlayer();
|
Player *player = GetPlayer();
|
||||||
uint64 guid = player->GetLootGUID();
|
ObjectGuid guid = player->GetLootGUID();
|
||||||
if(!guid)
|
if (guid.IsEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Loot *pLoot = NULL;
|
Loot *pLoot = NULL;
|
||||||
|
|
||||||
switch(GUID_HIPART(guid))
|
switch(guid.GetHigh())
|
||||||
{
|
{
|
||||||
case HIGHGUID_GAMEOBJECT:
|
case HIGHGUID_GAMEOBJECT:
|
||||||
{
|
{
|
||||||
|
|
@ -210,9 +222,9 @@ void WorldSession::HandleLootMoneyOpcode( WorldPacket & /*recv_data*/ )
|
||||||
return; // unlootable type
|
return; // unlootable type
|
||||||
}
|
}
|
||||||
|
|
||||||
if( pLoot )
|
if (pLoot)
|
||||||
{
|
{
|
||||||
if (!IS_ITEM_GUID(guid) && player->GetGroup()) //item can be looted only single player
|
if (!guid.IsItem() && player->GetGroup()) //item can be looted only single player
|
||||||
{
|
{
|
||||||
Group *group = player->GetGroup();
|
Group *group = player->GetGroup();
|
||||||
|
|
||||||
|
|
@ -274,7 +286,7 @@ void WorldSession::HandleLootReleaseOpcode( WorldPacket & recv_data )
|
||||||
DoLootRelease(lguid);
|
DoLootRelease(lguid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::DoLootRelease( uint64 lguid )
|
void WorldSession::DoLootRelease(ObjectGuid lguid)
|
||||||
{
|
{
|
||||||
Player *player = GetPlayer();
|
Player *player = GetPlayer();
|
||||||
Loot *loot;
|
Loot *loot;
|
||||||
|
|
@ -287,152 +299,163 @@ void WorldSession::DoLootRelease( uint64 lguid )
|
||||||
if(!player->IsInWorld())
|
if(!player->IsInWorld())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (IS_GAMEOBJECT_GUID(lguid))
|
switch(lguid.GetHigh())
|
||||||
{
|
{
|
||||||
GameObject *go = GetPlayer()->GetMap()->GetGameObject(lguid);
|
case HIGHGUID_GAMEOBJECT:
|
||||||
|
|
||||||
// not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO
|
|
||||||
if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player,INTERACTION_DISTANCE)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
loot = &go->loot;
|
|
||||||
|
|
||||||
if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR)
|
|
||||||
{
|
{
|
||||||
// locked doors are opened with spelleffect openlock, prevent remove its as looted
|
GameObject *go = GetPlayer()->GetMap()->GetGameObject(lguid);
|
||||||
go->UseDoorOrButton();
|
|
||||||
}
|
// not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO
|
||||||
else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE)
|
if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player,INTERACTION_DISTANCE)))
|
||||||
{
|
return;
|
||||||
// GO is mineral vein? so it is not removed after its looted
|
|
||||||
if(go->GetGoType() == GAMEOBJECT_TYPE_CHEST)
|
loot = &go->loot;
|
||||||
|
|
||||||
|
if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR)
|
||||||
{
|
{
|
||||||
uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens;
|
// locked doors are opened with spelleffect openlock, prevent remove its as looted
|
||||||
uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens;
|
go->UseDoorOrButton();
|
||||||
|
}
|
||||||
// only vein pass this check
|
else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE)
|
||||||
if(go_min != 0 && go_max > go_min)
|
{
|
||||||
|
// GO is mineral vein? so it is not removed after its looted
|
||||||
|
if(go->GetGoType() == GAMEOBJECT_TYPE_CHEST)
|
||||||
{
|
{
|
||||||
float amount_rate = sWorld.getConfig(CONFIG_FLOAT_RATE_MINING_AMOUNT);
|
uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens;
|
||||||
float min_amount = go_min*amount_rate;
|
uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens;
|
||||||
float max_amount = go_max*amount_rate;
|
|
||||||
|
|
||||||
go->AddUse();
|
// only vein pass this check
|
||||||
float uses = float(go->GetUseCount());
|
if(go_min != 0 && go_max > go_min)
|
||||||
|
|
||||||
if(uses < max_amount)
|
|
||||||
{
|
{
|
||||||
if(uses >= min_amount)
|
float amount_rate = sWorld.getConfig(CONFIG_FLOAT_RATE_MINING_AMOUNT);
|
||||||
{
|
float min_amount = go_min*amount_rate;
|
||||||
float chance_rate = sWorld.getConfig(CONFIG_FLOAT_RATE_MINING_NEXT);
|
float max_amount = go_max*amount_rate;
|
||||||
|
|
||||||
int32 ReqValue = 175;
|
go->AddUse();
|
||||||
LockEntry const *lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId);
|
float uses = float(go->GetUseCount());
|
||||||
if(lockInfo)
|
|
||||||
ReqValue = lockInfo->Skill[0];
|
if(uses < max_amount)
|
||||||
float skill = float(player->GetSkillValue(SKILL_MINING))/(ReqValue+25);
|
{
|
||||||
double chance = pow(0.8*chance_rate,4*(1/double(max_amount))*double(uses));
|
if(uses >= min_amount)
|
||||||
if(roll_chance_f(float(100.0f*chance+skill)))
|
|
||||||
{
|
{
|
||||||
go->SetLootState(GO_READY);
|
float chance_rate = sWorld.getConfig(CONFIG_FLOAT_RATE_MINING_NEXT);
|
||||||
|
|
||||||
|
int32 ReqValue = 175;
|
||||||
|
LockEntry const *lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId);
|
||||||
|
if(lockInfo)
|
||||||
|
ReqValue = lockInfo->Skill[0];
|
||||||
|
float skill = float(player->GetSkillValue(SKILL_MINING))/(ReqValue+25);
|
||||||
|
double chance = pow(0.8*chance_rate,4*(1/double(max_amount))*double(uses));
|
||||||
|
if(roll_chance_f(float(100.0f*chance+skill)))
|
||||||
|
{
|
||||||
|
go->SetLootState(GO_READY);
|
||||||
|
}
|
||||||
|
else // not have more uses
|
||||||
|
go->SetLootState(GO_JUST_DEACTIVATED);
|
||||||
}
|
}
|
||||||
else // not have more uses
|
else // 100% chance until min uses
|
||||||
go->SetLootState(GO_JUST_DEACTIVATED);
|
go->SetLootState(GO_READY);
|
||||||
}
|
}
|
||||||
else // 100% chance until min uses
|
else // max uses already
|
||||||
go->SetLootState(GO_READY);
|
go->SetLootState(GO_JUST_DEACTIVATED);
|
||||||
}
|
}
|
||||||
else // max uses already
|
else // not vein
|
||||||
go->SetLootState(GO_JUST_DEACTIVATED);
|
go->SetLootState(GO_JUST_DEACTIVATED);
|
||||||
}
|
}
|
||||||
else // not vein
|
else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE)
|
||||||
go->SetLootState(GO_JUST_DEACTIVATED);
|
{ // The fishing hole used once more
|
||||||
}
|
go->AddUse(); // if the max usage is reached, will be despawned in next tick
|
||||||
else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE)
|
if (go->GetUseCount() >= urand(go->GetGOInfo()->fishinghole.minSuccessOpens,go->GetGOInfo()->fishinghole.maxSuccessOpens))
|
||||||
{ // The fishing hole used once more
|
{
|
||||||
go->AddUse(); // if the max usage is reached, will be despawned in next tick
|
go->SetLootState(GO_JUST_DEACTIVATED);
|
||||||
if (go->GetUseCount() >= urand(go->GetGOInfo()->fishinghole.minSuccessOpens,go->GetGOInfo()->fishinghole.maxSuccessOpens))
|
}
|
||||||
{
|
else
|
||||||
go->SetLootState(GO_JUST_DEACTIVATED);
|
go->SetLootState(GO_READY);
|
||||||
}
|
}
|
||||||
else
|
else // not chest (or vein/herb/etc)
|
||||||
go->SetLootState(GO_READY);
|
go->SetLootState(GO_JUST_DEACTIVATED);
|
||||||
|
|
||||||
|
loot->clear();
|
||||||
}
|
}
|
||||||
else // not chest (or vein/herb/etc)
|
else
|
||||||
go->SetLootState(GO_JUST_DEACTIVATED);
|
// not fully looted object
|
||||||
|
go->SetLootState(GO_ACTIVATED);
|
||||||
loot->clear();
|
break;
|
||||||
}
|
}
|
||||||
else
|
case HIGHGUID_CORPSE: // ONLY remove insignia at BG
|
||||||
// not fully looted object
|
|
||||||
go->SetLootState(GO_ACTIVATED);
|
|
||||||
}
|
|
||||||
else if (IS_CORPSE_GUID(lguid)) // ONLY remove insignia at BG
|
|
||||||
{
|
|
||||||
Corpse *corpse = _player->GetMap()->GetCorpse(lguid);
|
|
||||||
if (!corpse || !corpse->IsWithinDistInMap(_player,INTERACTION_DISTANCE) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
loot = &corpse->loot;
|
|
||||||
|
|
||||||
if (loot->isLooted())
|
|
||||||
{
|
{
|
||||||
loot->clear();
|
Corpse *corpse = _player->GetMap()->GetCorpse(lguid);
|
||||||
corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE);
|
if (!corpse || !corpse->IsWithinDistInMap(_player,INTERACTION_DISTANCE) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
loot = &corpse->loot;
|
||||||
|
|
||||||
|
if (loot->isLooted())
|
||||||
|
{
|
||||||
|
loot->clear();
|
||||||
|
corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
case HIGHGUID_ITEM:
|
||||||
else if (IS_ITEM_GUID(lguid))
|
|
||||||
{
|
|
||||||
Item *pItem = player->GetItemByGuid(lguid );
|
|
||||||
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)) &&
|
|
||||||
proto->Class == ITEM_CLASS_TRADE_GOODS)
|
|
||||||
{
|
{
|
||||||
pItem->m_lootGenerated = false;
|
Item *pItem = player->GetItemByGuid(lguid );
|
||||||
pItem->loot.clear();
|
if(!pItem)
|
||||||
|
return;
|
||||||
|
|
||||||
uint32 count = pItem->GetCount();
|
ItemPrototype const* proto = pItem->GetProto();
|
||||||
|
|
||||||
// >=5 checked in spell code, but will work for cheating cases also with removing from another stacks.
|
// destroy only 5 items from stack in case prospecting and milling
|
||||||
if(count > 5)
|
if( (proto->BagFamily & (BAG_FAMILY_MASK_MINING_SUPP|BAG_FAMILY_MASK_HERBS)) &&
|
||||||
count = 5;
|
proto->Class == ITEM_CLASS_TRADE_GOODS)
|
||||||
|
{
|
||||||
|
pItem->m_lootGenerated = false;
|
||||||
|
pItem->loot.clear();
|
||||||
|
|
||||||
player->DestroyItemCount(pItem, count, true);
|
uint32 count = pItem->GetCount();
|
||||||
|
|
||||||
|
// >=5 checked in spell code, but will work for cheating cases also with removing from another stacks.
|
||||||
|
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);
|
||||||
|
return; // item can be looted only single player
|
||||||
}
|
}
|
||||||
else
|
case HIGHGUID_UNIT:
|
||||||
// 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);
|
|
||||||
return; // item can be looted only single player
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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) )
|
|
||||||
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
|
Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid);
|
||||||
if(!pCreature->isAlive())
|
|
||||||
pCreature->AllLootRemovedFromCorpse();
|
|
||||||
|
|
||||||
pCreature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
|
bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass()==CLASS_ROGUE && pCreature->lootForPickPocketed);
|
||||||
loot->clear();
|
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())
|
||||||
|
pCreature->AllLootRemovedFromCorpse();
|
||||||
|
|
||||||
|
pCreature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
|
||||||
|
loot->clear();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
sLog.outError("%s is unsupported for looting.", lguid.GetString().c_str());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,9 +75,7 @@ enum HighGuid
|
||||||
#define IS_PLAYER_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_PLAYER && Guid!=0 )
|
#define IS_PLAYER_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_PLAYER && Guid!=0 )
|
||||||
#define IS_UNIT_GUID(Guid) ( IS_CREATURE_OR_PET_GUID(Guid) || IS_PLAYER_GUID(Guid) )
|
#define IS_UNIT_GUID(Guid) ( IS_CREATURE_OR_PET_GUID(Guid) || IS_PLAYER_GUID(Guid) )
|
||||||
// special case for empty guid need check
|
// special case for empty guid need check
|
||||||
#define IS_ITEM_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_ITEM )
|
|
||||||
#define IS_GAMEOBJECT_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_GAMEOBJECT )
|
#define IS_GAMEOBJECT_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_GAMEOBJECT )
|
||||||
#define IS_CORPSE_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_CORPSE )
|
|
||||||
#define IS_MO_TRANSPORT(Guid) ( GUID_HIPART(Guid) == HIGHGUID_MO_TRANSPORT )
|
#define IS_MO_TRANSPORT(Guid) ( GUID_HIPART(Guid) == HIGHGUID_MO_TRANSPORT )
|
||||||
|
|
||||||
// l - OBJECT_FIELD_GUID
|
// l - OBJECT_FIELD_GUID
|
||||||
|
|
@ -233,6 +231,8 @@ class ObjectGuid
|
||||||
uint64 m_guid;
|
uint64 m_guid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::set<ObjectGuid> ObjectGuidSet;
|
||||||
|
|
||||||
class PackedGuid
|
class PackedGuid
|
||||||
{
|
{
|
||||||
friend ByteBuffer& operator<< (ByteBuffer& buf, PackedGuid const& guid);
|
friend ByteBuffer& operator<< (ByteBuffer& buf, PackedGuid const& guid);
|
||||||
|
|
|
||||||
|
|
@ -7533,14 +7533,15 @@ void Player::RemovedInsignia(Player* looterPlr)
|
||||||
looterPlr->SendLoot(bones->GetGUID(), LOOT_INSIGNIA);
|
looterPlr->SendLoot(bones->GetGUID(), LOOT_INSIGNIA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::SendLootRelease( uint64 guid )
|
void Player::SendLootRelease(ObjectGuid guid)
|
||||||
{
|
{
|
||||||
WorldPacket data( SMSG_LOOT_RELEASE_RESPONSE, (8+1) );
|
WorldPacket data( SMSG_LOOT_RELEASE_RESPONSE, (8+1) );
|
||||||
data << uint64(guid) << uint8(1);
|
data << guid;
|
||||||
|
data << uint8(1);
|
||||||
SendDirectMessage( &data );
|
SendDirectMessage( &data );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::SendLoot(uint64 guid, LootType loot_type)
|
void Player::SendLoot(ObjectGuid guid, LootType loot_type)
|
||||||
{
|
{
|
||||||
if (uint64 lguid = GetLootGUID())
|
if (uint64 lguid = GetLootGUID())
|
||||||
m_session->DoLootRelease(lguid);
|
m_session->DoLootRelease(lguid);
|
||||||
|
|
@ -7549,224 +7550,236 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
|
||||||
PermissionTypes permission = ALL_PERMISSION;
|
PermissionTypes permission = ALL_PERMISSION;
|
||||||
|
|
||||||
sLog.outDebug("Player::SendLoot");
|
sLog.outDebug("Player::SendLoot");
|
||||||
if (IS_GAMEOBJECT_GUID(guid))
|
switch(guid.GetHigh())
|
||||||
{
|
{
|
||||||
sLog.outDebug(" IS_GAMEOBJECT_GUID(guid)");
|
case HIGHGUID_GAMEOBJECT:
|
||||||
GameObject *go = GetMap()->GetGameObject(guid);
|
|
||||||
|
|
||||||
// not check distance for GO in case owned GO (fishing bobber case, for example)
|
|
||||||
// And permit out of range GO with no owner in case fishing hole
|
|
||||||
if (!go || (loot_type != LOOT_FISHINGHOLE && (loot_type != LOOT_FISHING || go->GetOwnerGUID() != GetGUID()) && !go->IsWithinDistInMap(this,INTERACTION_DISTANCE)))
|
|
||||||
{
|
{
|
||||||
SendLootRelease(guid);
|
sLog.outDebug(" IS_GAMEOBJECT_GUID(guid)");
|
||||||
return;
|
GameObject *go = GetMap()->GetGameObject(guid);
|
||||||
}
|
|
||||||
|
|
||||||
loot = &go->loot;
|
// not check distance for GO in case owned GO (fishing bobber case, for example)
|
||||||
|
// And permit out of range GO with no owner in case fishing hole
|
||||||
if (go->getLootState() == GO_READY)
|
if (!go || (loot_type != LOOT_FISHINGHOLE && (loot_type != LOOT_FISHING || go->GetOwnerGUID() != GetGUID()) && !go->IsWithinDistInMap(this,INTERACTION_DISTANCE)))
|
||||||
{
|
|
||||||
uint32 lootid = go->GetGOInfo()->GetLootId();
|
|
||||||
if ((go->GetEntry() == BG_AV_OBJECTID_MINE_N || go->GetEntry() == BG_AV_OBJECTID_MINE_S))
|
|
||||||
if (BattleGround *bg = GetBattleGround())
|
|
||||||
if (bg->GetTypeID() == BATTLEGROUND_AV)
|
|
||||||
if (!(((BattleGroundAV*)bg)->PlayerCanDoMineQuest(go->GetEntry(), GetTeam())))
|
|
||||||
{
|
|
||||||
SendLootRelease(guid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lootid)
|
|
||||||
{
|
{
|
||||||
sLog.outDebug(" if(lootid)");
|
SendLootRelease(guid);
|
||||||
loot->clear();
|
return;
|
||||||
loot->FillLoot(lootid, LootTemplates_Gameobject, this, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loot_type == LOOT_FISHING)
|
loot = &go->loot;
|
||||||
go->getFishLoot(loot,this);
|
|
||||||
|
|
||||||
go->SetLootState(GO_ACTIVATED);
|
if (go->getLootState() == GO_READY)
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (IS_ITEM_GUID(guid))
|
|
||||||
{
|
|
||||||
Item *item = GetItemByGuid( guid );
|
|
||||||
|
|
||||||
if (!item)
|
|
||||||
{
|
|
||||||
SendLootRelease(guid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
loot = &item->loot;
|
|
||||||
|
|
||||||
if (!item->m_lootGenerated)
|
|
||||||
{
|
|
||||||
item->m_lootGenerated = true;
|
|
||||||
loot->clear();
|
|
||||||
|
|
||||||
switch(loot_type)
|
|
||||||
{
|
{
|
||||||
case LOOT_DISENCHANTING:
|
uint32 lootid = go->GetGOInfo()->GetLootId();
|
||||||
loot->FillLoot(item->GetProto()->DisenchantID, LootTemplates_Disenchant, this,true);
|
if ((go->GetEntry() == BG_AV_OBJECTID_MINE_N || go->GetEntry() == BG_AV_OBJECTID_MINE_S))
|
||||||
break;
|
if (BattleGround *bg = GetBattleGround())
|
||||||
case LOOT_PROSPECTING:
|
if (bg->GetTypeID() == BATTLEGROUND_AV)
|
||||||
loot->FillLoot(item->GetEntry(), LootTemplates_Prospecting, this,true);
|
if (!(((BattleGroundAV*)bg)->PlayerCanDoMineQuest(go->GetEntry(), GetTeam())))
|
||||||
break;
|
{
|
||||||
case LOOT_MILLING:
|
SendLootRelease(guid);
|
||||||
loot->FillLoot(item->GetEntry(), LootTemplates_Milling, this,true);
|
return;
|
||||||
break;
|
}
|
||||||
default:
|
|
||||||
loot->FillLoot(item->GetEntry(), LootTemplates_Item, this,true);
|
|
||||||
loot->generateMoneyLoot(item->GetProto()->MinMoneyLoot,item->GetProto()->MaxMoneyLoot);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (IS_CORPSE_GUID(guid)) // remove insignia
|
|
||||||
{
|
|
||||||
Corpse *bones = GetMap()->GetCorpse(guid);
|
|
||||||
|
|
||||||
if (!bones || !((loot_type == LOOT_CORPSE) || (loot_type == LOOT_INSIGNIA)) || (bones->GetType() != CORPSE_BONES) )
|
if (lootid)
|
||||||
{
|
|
||||||
SendLootRelease(guid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
loot = &bones->loot;
|
|
||||||
|
|
||||||
if (!bones->lootForBody)
|
|
||||||
{
|
|
||||||
bones->lootForBody = true;
|
|
||||||
uint32 pLevel = bones->loot.gold;
|
|
||||||
bones->loot.clear();
|
|
||||||
if (GetBattleGround()->GetTypeID() == BATTLEGROUND_AV)
|
|
||||||
loot->FillLoot(0, LootTemplates_Creature, this, false);
|
|
||||||
// It may need a better formula
|
|
||||||
// Now it works like this: lvl10: ~6copper, lvl70: ~9silver
|
|
||||||
bones->loot.gold = (uint32)( urand(50, 150) * 0.016f * pow( ((float)pLevel)/5.76f, 2.5f) * sWorld.getConfig(CONFIG_FLOAT_RATE_DROP_MONEY) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bones->lootRecipient != this)
|
|
||||||
permission = NONE_PERMISSION;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Creature *creature = GetMap()->GetCreature(guid);
|
|
||||||
|
|
||||||
// must be in range and creature must be alive for pickpocket and must be dead for another loot
|
|
||||||
if (!creature || creature->isAlive()!=(loot_type == LOOT_PICKPOCKETING) || !creature->IsWithinDistInMap(this,INTERACTION_DISTANCE))
|
|
||||||
{
|
|
||||||
SendLootRelease(guid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loot_type == LOOT_PICKPOCKETING && IsFriendlyTo(creature))
|
|
||||||
{
|
|
||||||
SendLootRelease(guid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
loot = &creature->loot;
|
|
||||||
|
|
||||||
if (loot_type == LOOT_PICKPOCKETING)
|
|
||||||
{
|
|
||||||
if (!creature->lootForPickPocketed)
|
|
||||||
{
|
|
||||||
creature->lootForPickPocketed = true;
|
|
||||||
loot->clear();
|
|
||||||
|
|
||||||
if (uint32 lootid = creature->GetCreatureInfo()->pickpocketLootId)
|
|
||||||
loot->FillLoot(lootid, LootTemplates_Pickpocketing, this, false);
|
|
||||||
|
|
||||||
// Generate extra money for pick pocket loot
|
|
||||||
const uint32 a = urand(0, creature->getLevel()/2);
|
|
||||||
const uint32 b = urand(0, getLevel()/2);
|
|
||||||
loot->gold = uint32(10 * (a + b) * sWorld.getConfig(CONFIG_FLOAT_RATE_DROP_MONEY));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// the player whose group may loot the corpse
|
|
||||||
Player *recipient = creature->GetLootRecipient();
|
|
||||||
if (!recipient)
|
|
||||||
{
|
|
||||||
creature->SetLootRecipient(this);
|
|
||||||
recipient = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (creature->lootForPickPocketed)
|
|
||||||
{
|
|
||||||
creature->lootForPickPocketed = false;
|
|
||||||
loot->clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!creature->lootForBody)
|
|
||||||
{
|
|
||||||
creature->lootForBody = true;
|
|
||||||
loot->clear();
|
|
||||||
|
|
||||||
if (uint32 lootid = creature->GetCreatureInfo()->lootid)
|
|
||||||
loot->FillLoot(lootid, LootTemplates_Creature, recipient, false);
|
|
||||||
|
|
||||||
loot->generateMoneyLoot(creature->GetCreatureInfo()->mingold,creature->GetCreatureInfo()->maxgold);
|
|
||||||
|
|
||||||
if (Group* group = recipient->GetGroup())
|
|
||||||
{
|
{
|
||||||
group->UpdateLooterGuid(creature,true);
|
sLog.outDebug(" if(lootid)");
|
||||||
|
loot->clear();
|
||||||
|
loot->FillLoot(lootid, LootTemplates_Gameobject, this, false);
|
||||||
|
}
|
||||||
|
|
||||||
switch (group->GetLootMethod())
|
if (loot_type == LOOT_FISHING)
|
||||||
{
|
go->getFishLoot(loot,this);
|
||||||
case GROUP_LOOT:
|
|
||||||
// GroupLoot delete items over threshold (threshold even not implemented), and roll them. Items with quality<threshold, round robin
|
go->SetLootState(GO_ACTIVATED);
|
||||||
group->GroupLoot(recipient->GetGUID(), loot, creature);
|
}
|
||||||
break;
|
break;
|
||||||
case NEED_BEFORE_GREED:
|
}
|
||||||
group->NeedBeforeGreed(recipient->GetGUID(), loot, creature);
|
case HIGHGUID_ITEM:
|
||||||
break;
|
{
|
||||||
case MASTER_LOOT:
|
Item *item = GetItemByGuid( guid );
|
||||||
group->MasterLoot(recipient->GetGUID(), loot, creature);
|
|
||||||
break;
|
if (!item)
|
||||||
default:
|
{
|
||||||
break;
|
SendLootRelease(guid);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loot = &item->loot;
|
||||||
|
|
||||||
|
if (!item->m_lootGenerated)
|
||||||
|
{
|
||||||
|
item->m_lootGenerated = true;
|
||||||
|
loot->clear();
|
||||||
|
|
||||||
|
switch(loot_type)
|
||||||
|
{
|
||||||
|
case LOOT_DISENCHANTING:
|
||||||
|
loot->FillLoot(item->GetProto()->DisenchantID, LootTemplates_Disenchant, this,true);
|
||||||
|
break;
|
||||||
|
case LOOT_PROSPECTING:
|
||||||
|
loot->FillLoot(item->GetEntry(), LootTemplates_Prospecting, this,true);
|
||||||
|
break;
|
||||||
|
case LOOT_MILLING:
|
||||||
|
loot->FillLoot(item->GetEntry(), LootTemplates_Milling, this,true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
loot->FillLoot(item->GetEntry(), LootTemplates_Item, this,true);
|
||||||
|
loot->generateMoneyLoot(item->GetProto()->MinMoneyLoot,item->GetProto()->MaxMoneyLoot);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HIGHGUID_CORPSE: // remove insignia
|
||||||
|
{
|
||||||
|
Corpse *bones = GetMap()->GetCorpse(guid);
|
||||||
|
|
||||||
// possible only if creature->lootForBody && loot->empty() at spell cast check
|
if (!bones || !((loot_type == LOOT_CORPSE) || (loot_type == LOOT_INSIGNIA)) || (bones->GetType() != CORPSE_BONES) )
|
||||||
if (loot_type == LOOT_SKINNING)
|
|
||||||
{
|
{
|
||||||
loot->clear();
|
SendLootRelease(guid);
|
||||||
loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, this, false);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loot = &bones->loot;
|
||||||
|
|
||||||
|
if (!bones->lootForBody)
|
||||||
|
{
|
||||||
|
bones->lootForBody = true;
|
||||||
|
uint32 pLevel = bones->loot.gold;
|
||||||
|
bones->loot.clear();
|
||||||
|
if (GetBattleGround()->GetTypeID() == BATTLEGROUND_AV)
|
||||||
|
loot->FillLoot(0, LootTemplates_Creature, this, false);
|
||||||
|
// It may need a better formula
|
||||||
|
// Now it works like this: lvl10: ~6copper, lvl70: ~9silver
|
||||||
|
bones->loot.gold = (uint32)( urand(50, 150) * 0.016f * pow( ((float)pLevel)/5.76f, 2.5f) * sWorld.getConfig(CONFIG_FLOAT_RATE_DROP_MONEY) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bones->lootRecipient != this)
|
||||||
|
permission = NONE_PERMISSION;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HIGHGUID_UNIT:
|
||||||
|
{
|
||||||
|
Creature *creature = GetMap()->GetCreature(guid);
|
||||||
|
|
||||||
|
// must be in range and creature must be alive for pickpocket and must be dead for another loot
|
||||||
|
if (!creature || creature->isAlive()!=(loot_type == LOOT_PICKPOCKETING) || !creature->IsWithinDistInMap(this,INTERACTION_DISTANCE))
|
||||||
|
{
|
||||||
|
SendLootRelease(guid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loot_type == LOOT_PICKPOCKETING && IsFriendlyTo(creature))
|
||||||
|
{
|
||||||
|
SendLootRelease(guid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loot = &creature->loot;
|
||||||
|
|
||||||
|
if (loot_type == LOOT_PICKPOCKETING)
|
||||||
|
{
|
||||||
|
if (!creature->lootForPickPocketed)
|
||||||
|
{
|
||||||
|
creature->lootForPickPocketed = true;
|
||||||
|
loot->clear();
|
||||||
|
|
||||||
|
if (uint32 lootid = creature->GetCreatureInfo()->pickpocketLootId)
|
||||||
|
loot->FillLoot(lootid, LootTemplates_Pickpocketing, this, false);
|
||||||
|
|
||||||
|
// Generate extra money for pick pocket loot
|
||||||
|
const uint32 a = urand(0, creature->getLevel()/2);
|
||||||
|
const uint32 b = urand(0, getLevel()/2);
|
||||||
|
loot->gold = uint32(10 * (a + b) * sWorld.getConfig(CONFIG_FLOAT_RATE_DROP_MONEY));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// set group rights only for loot_type != LOOT_SKINNING
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(Group* group = GetGroup())
|
// the player whose group may loot the corpse
|
||||||
|
Player *recipient = creature->GetLootRecipient();
|
||||||
|
if (!recipient)
|
||||||
{
|
{
|
||||||
if (group == recipient->GetGroup())
|
creature->SetLootRecipient(this);
|
||||||
|
recipient = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (creature->lootForPickPocketed)
|
||||||
|
{
|
||||||
|
creature->lootForPickPocketed = false;
|
||||||
|
loot->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!creature->lootForBody)
|
||||||
|
{
|
||||||
|
creature->lootForBody = true;
|
||||||
|
loot->clear();
|
||||||
|
|
||||||
|
if (uint32 lootid = creature->GetCreatureInfo()->lootid)
|
||||||
|
loot->FillLoot(lootid, LootTemplates_Creature, recipient, false);
|
||||||
|
|
||||||
|
loot->generateMoneyLoot(creature->GetCreatureInfo()->mingold,creature->GetCreatureInfo()->maxgold);
|
||||||
|
|
||||||
|
if (Group* group = recipient->GetGroup())
|
||||||
{
|
{
|
||||||
if (group->GetLootMethod() == FREE_FOR_ALL)
|
group->UpdateLooterGuid(creature,true);
|
||||||
permission = ALL_PERMISSION;
|
|
||||||
else if (group->GetLooterGuid() == GetGUID())
|
switch (group->GetLootMethod())
|
||||||
{
|
{
|
||||||
if (group->GetLootMethod() == MASTER_LOOT)
|
case GROUP_LOOT:
|
||||||
permission = MASTER_PERMISSION;
|
// GroupLoot delete items over threshold (threshold even not implemented), and roll them. Items with quality<threshold, round robin
|
||||||
else
|
group->GroupLoot(recipient->GetGUID(), loot, creature);
|
||||||
|
break;
|
||||||
|
case NEED_BEFORE_GREED:
|
||||||
|
group->NeedBeforeGreed(recipient->GetGUID(), loot, creature);
|
||||||
|
break;
|
||||||
|
case MASTER_LOOT:
|
||||||
|
group->MasterLoot(recipient->GetGUID(), loot, creature);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// possible only if creature->lootForBody && loot->empty() at spell cast check
|
||||||
|
if (loot_type == LOOT_SKINNING)
|
||||||
|
{
|
||||||
|
loot->clear();
|
||||||
|
loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, this, false);
|
||||||
|
}
|
||||||
|
// set group rights only for loot_type != LOOT_SKINNING
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(Group* group = GetGroup())
|
||||||
|
{
|
||||||
|
if (group == recipient->GetGroup())
|
||||||
|
{
|
||||||
|
if (group->GetLootMethod() == FREE_FOR_ALL)
|
||||||
permission = ALL_PERMISSION;
|
permission = ALL_PERMISSION;
|
||||||
|
else if (group->GetLooterGuid() == GetGUID())
|
||||||
|
{
|
||||||
|
if (group->GetLootMethod() == MASTER_LOOT)
|
||||||
|
permission = MASTER_PERMISSION;
|
||||||
|
else
|
||||||
|
permission = ALL_PERMISSION;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
permission = GROUP_PERMISSION;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
permission = GROUP_PERMISSION;
|
permission = NONE_PERMISSION;
|
||||||
}
|
}
|
||||||
|
else if (recipient == this)
|
||||||
|
permission = ALL_PERMISSION;
|
||||||
else
|
else
|
||||||
permission = NONE_PERMISSION;
|
permission = NONE_PERMISSION;
|
||||||
}
|
}
|
||||||
else if (recipient == this)
|
|
||||||
permission = ALL_PERMISSION;
|
|
||||||
else
|
|
||||||
permission = NONE_PERMISSION;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
sLog.outError("%s is unsupported for looting.", guid.GetString().c_str());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -7785,7 +7798,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
|
||||||
|
|
||||||
WorldPacket data(SMSG_LOOT_RESPONSE, (9+50)); // we guess size
|
WorldPacket data(SMSG_LOOT_RESPONSE, (9+50)); // we guess size
|
||||||
|
|
||||||
data << uint64(guid);
|
data << guid;
|
||||||
data << uint8(loot_type);
|
data << uint8(loot_type);
|
||||||
data << LootView(*loot, this, permission);
|
data << LootView(*loot, this, permission);
|
||||||
|
|
||||||
|
|
@ -7795,7 +7808,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
|
||||||
if (permission != NONE_PERMISSION)
|
if (permission != NONE_PERMISSION)
|
||||||
loot->AddLooter(GetGUID());
|
loot->AddLooter(GetGUID());
|
||||||
|
|
||||||
if (loot_type == LOOT_CORPSE && !IS_ITEM_GUID(guid))
|
if (loot_type == LOOT_CORPSE && !guid.IsItem())
|
||||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING);
|
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -8670,47 +8683,31 @@ Item* Player::GetItemByLimitedCategory(uint32 limitedCategory) const
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item* Player::GetItemByGuid( uint64 guid ) const
|
Item* Player::GetItemByGuid(ObjectGuid guid) const
|
||||||
{
|
{
|
||||||
for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i)
|
for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i)
|
||||||
{
|
if (Item *pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||||
Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i );
|
if (pItem->GetGUID() == guid.GetRawValue())
|
||||||
if( pItem && pItem->GetGUID() == guid )
|
return pItem;
|
||||||
return pItem;
|
|
||||||
}
|
|
||||||
for(int i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
|
for(int i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
|
||||||
{
|
if (Item *pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||||
Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i );
|
if (pItem->GetGUID() == guid.GetRawValue())
|
||||||
if( pItem && pItem->GetGUID() == guid )
|
return pItem;
|
||||||
return pItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
|
for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
|
||||||
{
|
if (Bag *pBag = (Bag*)GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||||
Bag *pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i );
|
|
||||||
if( pBag )
|
|
||||||
{
|
|
||||||
for(uint32 j = 0; j < pBag->GetBagSize(); ++j)
|
for(uint32 j = 0; j < pBag->GetBagSize(); ++j)
|
||||||
{
|
if (Item* pItem = pBag->GetItemByPos(j))
|
||||||
Item* pItem = pBag->GetItemByPos( j );
|
if (pItem->GetGUID() == guid.GetRawValue())
|
||||||
if( pItem && pItem->GetGUID() == guid )
|
return pItem;
|
||||||
return pItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(int i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i)
|
for(int i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i)
|
||||||
{
|
if (Bag *pBag = (Bag*)GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||||
Bag *pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i );
|
|
||||||
if( pBag )
|
|
||||||
{
|
|
||||||
for(uint32 j = 0; j < pBag->GetBagSize(); ++j)
|
for(uint32 j = 0; j < pBag->GetBagSize(); ++j)
|
||||||
{
|
if (Item* pItem = pBag->GetItemByPos(j))
|
||||||
Item* pItem = pBag->GetItemByPos( j );
|
if (pItem->GetGUID() == guid.GetRawValue())
|
||||||
if( pItem && pItem->GetGUID() == guid )
|
return pItem;
|
||||||
return pItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -18876,13 +18873,13 @@ void Player::UpdateVisibilityOf(WorldObject const* viewPoint, WorldObject* targe
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline void UpdateVisibilityOf_helper(std::set<ObjectGuid>& s64, T* target)
|
inline void UpdateVisibilityOf_helper(ObjectGuidSet& s64, T* target)
|
||||||
{
|
{
|
||||||
s64.insert(target->GetGUID());
|
s64.insert(target->GetGUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void UpdateVisibilityOf_helper(std::set<ObjectGuid>& s64, GameObject* target)
|
inline void UpdateVisibilityOf_helper(ObjectGuidSet& s64, GameObject* target)
|
||||||
{
|
{
|
||||||
if(!target->IsTransport())
|
if(!target->IsTransport())
|
||||||
s64.insert(target->GetGUID());
|
s64.insert(target->GetGUID());
|
||||||
|
|
@ -19529,7 +19526,7 @@ void Player::UpdateForQuestWorldObjects()
|
||||||
|
|
||||||
UpdateData udata;
|
UpdateData udata;
|
||||||
WorldPacket packet;
|
WorldPacket packet;
|
||||||
for(ClientGUIDs::const_iterator itr=m_clientGUIDs.begin(); itr!=m_clientGUIDs.end(); ++itr)
|
for(ObjectGuidSet::const_iterator itr=m_clientGUIDs.begin(); itr!=m_clientGUIDs.end(); ++itr)
|
||||||
{
|
{
|
||||||
if (itr->IsGameobject())
|
if (itr->IsGameobject())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1149,7 +1149,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
uint8 FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap ) const;
|
uint8 FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap ) const;
|
||||||
uint32 GetItemCount( uint32 item, bool inBankAlso = false, Item* skipItem = NULL ) const;
|
uint32 GetItemCount( uint32 item, bool inBankAlso = false, Item* skipItem = NULL ) const;
|
||||||
uint32 GetItemCountWithLimitCategory(uint32 limitCategory) const;
|
uint32 GetItemCountWithLimitCategory(uint32 limitCategory) const;
|
||||||
Item* GetItemByGuid( uint64 guid ) const;
|
Item* GetItemByGuid(ObjectGuid uint64) const;
|
||||||
Item* GetItemByEntry(uint32 item) const; // only for special cases
|
Item* GetItemByEntry(uint32 item) const; // only for special cases
|
||||||
Item* GetItemByLimitedCategory(uint32 limitedCategory) const;
|
Item* GetItemByLimitedCategory(uint32 limitedCategory) const;
|
||||||
Item* GetItemByPos( uint16 pos ) const;
|
Item* GetItemByPos( uint16 pos ) const;
|
||||||
|
|
@ -1789,8 +1789,8 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
void ApplyManaRegenBonus(int32 amount, bool apply);
|
void ApplyManaRegenBonus(int32 amount, bool apply);
|
||||||
void UpdateManaRegen();
|
void UpdateManaRegen();
|
||||||
|
|
||||||
const uint64& GetLootGUID() const { return m_lootGuid; }
|
const uint64& GetLootGUID() const { return m_lootGuid.GetRawValue(); }
|
||||||
void SetLootGUID(const uint64 &guid) { m_lootGuid = guid; }
|
void SetLootGUID(ObjectGuid const& guid) { m_lootGuid = guid; }
|
||||||
|
|
||||||
void RemovedInsignia(Player* looterPlr);
|
void RemovedInsignia(Player* looterPlr);
|
||||||
|
|
||||||
|
|
@ -1985,8 +1985,8 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
PlayerMenu* PlayerTalkClass;
|
PlayerMenu* PlayerTalkClass;
|
||||||
std::vector<ItemSetEffect *> ItemSetEff;
|
std::vector<ItemSetEffect *> ItemSetEff;
|
||||||
|
|
||||||
void SendLoot(uint64 guid, LootType loot_type);
|
void SendLoot(ObjectGuid guid, LootType loot_type);
|
||||||
void SendLootRelease( uint64 guid );
|
void SendLootRelease(ObjectGuid guid );
|
||||||
void SendNotifyLootItemRemoved(uint8 lootSlot);
|
void SendNotifyLootItemRemoved(uint8 lootSlot);
|
||||||
void SendNotifyLootMoneyRemoved();
|
void SendNotifyLootMoneyRemoved();
|
||||||
|
|
||||||
|
|
@ -2178,8 +2178,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
Object* GetObjectByTypeMask(ObjectGuid guid, TypeMask typemask);
|
Object* GetObjectByTypeMask(ObjectGuid guid, TypeMask typemask);
|
||||||
|
|
||||||
// currently visible objects at player client
|
// currently visible objects at player client
|
||||||
typedef std::set<ObjectGuid> ClientGUIDs;
|
ObjectGuidSet m_clientGUIDs;
|
||||||
ClientGUIDs m_clientGUIDs;
|
|
||||||
|
|
||||||
bool HaveAtClient(WorldObject const* u) { return u==this || m_clientGUIDs.find(u->GetGUID())!=m_clientGUIDs.end(); }
|
bool HaveAtClient(WorldObject const* u) { return u==this || m_clientGUIDs.find(u->GetGUID())!=m_clientGUIDs.end(); }
|
||||||
|
|
||||||
|
|
@ -2375,7 +2374,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
time_t m_lastHonorUpdateTime;
|
time_t m_lastHonorUpdateTime;
|
||||||
|
|
||||||
void outDebugValues() const;
|
void outDebugValues() const;
|
||||||
uint64 m_lootGuid;
|
ObjectGuid m_lootGuid;
|
||||||
|
|
||||||
uint32 m_team;
|
uint32 m_team;
|
||||||
uint32 m_nextSave;
|
uint32 m_nextSave;
|
||||||
|
|
|
||||||
|
|
@ -639,7 +639,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket
|
||||||
WorldPacket data(SMSG_QUESTGIVER_STATUS_MULTIPLE, 4);
|
WorldPacket data(SMSG_QUESTGIVER_STATUS_MULTIPLE, 4);
|
||||||
data << uint32(count); // placeholder
|
data << uint32(count); // placeholder
|
||||||
|
|
||||||
for(Player::ClientGUIDs::const_iterator itr = _player->m_clientGUIDs.begin(); itr != _player->m_clientGUIDs.end(); ++itr)
|
for(ObjectGuidSet::const_iterator itr = _player->m_clientGUIDs.begin(); itr != _player->m_clientGUIDs.end(); ++itr)
|
||||||
{
|
{
|
||||||
uint8 questStatus = DIALOG_STATUS_NONE;
|
uint8 questStatus = DIALOG_STATUS_NONE;
|
||||||
uint8 defstatus = DIALOG_STATUS_NONE;
|
uint8 defstatus = DIALOG_STATUS_NONE;
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ void SpellCastTargets::Update(Unit* caster)
|
||||||
if(caster->GetTypeId() == TYPEID_PLAYER)
|
if(caster->GetTypeId() == TYPEID_PLAYER)
|
||||||
{
|
{
|
||||||
if(m_targetMask & TARGET_FLAG_ITEM)
|
if(m_targetMask & TARGET_FLAG_ITEM)
|
||||||
m_itemTarget = ((Player*)caster)->GetItemByGuid(m_itemTargetGUID.GetRawValue());
|
m_itemTarget = ((Player*)caster)->GetItemByGuid(m_itemTargetGUID);
|
||||||
else if(m_targetMask & TARGET_FLAG_TRADE_ITEM)
|
else if(m_targetMask & TARGET_FLAG_TRADE_ITEM)
|
||||||
{
|
{
|
||||||
Player* pTrader = ((Player*)caster)->GetTrader();
|
Player* pTrader = ((Player*)caster)->GetTrader();
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ UpdateData::UpdateData() : m_blockCount(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateData::AddOutOfRangeGUID(std::set<ObjectGuid>& guids)
|
void UpdateData::AddOutOfRangeGUID(ObjectGuidSet& guids)
|
||||||
{
|
{
|
||||||
m_outOfRangeGUIDs.insert(guids.begin(),guids.end());
|
m_outOfRangeGUIDs.insert(guids.begin(),guids.end());
|
||||||
}
|
}
|
||||||
|
|
@ -115,7 +115,7 @@ bool UpdateData::BuildPacket(WorldPacket *packet)
|
||||||
buf << (uint8) UPDATETYPE_OUT_OF_RANGE_OBJECTS;
|
buf << (uint8) UPDATETYPE_OUT_OF_RANGE_OBJECTS;
|
||||||
buf << (uint32) m_outOfRangeGUIDs.size();
|
buf << (uint32) m_outOfRangeGUIDs.size();
|
||||||
|
|
||||||
for(std::set<ObjectGuid>::const_iterator i = m_outOfRangeGUIDs.begin(); i != m_outOfRangeGUIDs.end(); ++i)
|
for(ObjectGuidSet::const_iterator i = m_outOfRangeGUIDs.begin(); i != m_outOfRangeGUIDs.end(); ++i)
|
||||||
buf << i->WriteAsPacked();
|
buf << i->WriteAsPacked();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,9 @@
|
||||||
#define __UPDATEDATA_H
|
#define __UPDATEDATA_H
|
||||||
|
|
||||||
#include "ByteBuffer.h"
|
#include "ByteBuffer.h"
|
||||||
|
#include "ObjectGuid.h"
|
||||||
|
|
||||||
class WorldPacket;
|
class WorldPacket;
|
||||||
class ObjectGuid;
|
|
||||||
|
|
||||||
enum OBJECT_UPDATE_TYPE
|
enum OBJECT_UPDATE_TYPE
|
||||||
{
|
{
|
||||||
|
|
@ -54,18 +54,18 @@ class UpdateData
|
||||||
public:
|
public:
|
||||||
UpdateData();
|
UpdateData();
|
||||||
|
|
||||||
void AddOutOfRangeGUID(std::set<ObjectGuid>& guids);
|
void AddOutOfRangeGUID(ObjectGuidSet& guids);
|
||||||
void AddOutOfRangeGUID(ObjectGuid const &guid);
|
void AddOutOfRangeGUID(ObjectGuid const &guid);
|
||||||
void AddUpdateBlock(const ByteBuffer &block);
|
void AddUpdateBlock(const ByteBuffer &block);
|
||||||
bool BuildPacket(WorldPacket *packet);
|
bool BuildPacket(WorldPacket *packet);
|
||||||
bool HasData() { return m_blockCount > 0 || !m_outOfRangeGUIDs.empty(); }
|
bool HasData() { return m_blockCount > 0 || !m_outOfRangeGUIDs.empty(); }
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
std::set<ObjectGuid> const& GetOutOfRangeGUIDs() const { return m_outOfRangeGUIDs; }
|
ObjectGuidSet const& GetOutOfRangeGUIDs() const { return m_outOfRangeGUIDs; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint32 m_blockCount;
|
uint32 m_blockCount;
|
||||||
std::set<ObjectGuid> m_outOfRangeGUIDs;
|
ObjectGuidSet m_outOfRangeGUIDs;
|
||||||
ByteBuffer m_data;
|
ByteBuffer m_data;
|
||||||
|
|
||||||
void Compress(void* dst, uint32 *dst_size, void* src, int src_size);
|
void Compress(void* dst, uint32 *dst_size, void* src, int src_size);
|
||||||
|
|
|
||||||
|
|
@ -255,7 +255,7 @@ class MANGOS_DLL_SPEC WorldSession
|
||||||
|
|
||||||
void BuildPartyMemberStatsChangedPacket(Player *player, WorldPacket *data);
|
void BuildPartyMemberStatsChangedPacket(Player *player, WorldPacket *data);
|
||||||
|
|
||||||
void DoLootRelease( uint64 lguid );
|
void DoLootRelease(ObjectGuid lguid);
|
||||||
|
|
||||||
// Account mute time
|
// Account mute time
|
||||||
time_t m_muteTime;
|
time_t m_muteTime;
|
||||||
|
|
|
||||||
|
|
@ -692,7 +692,7 @@ bool ChatHandler::HandleDebugGetItemValueCommand(const char* args)
|
||||||
uint32 guid = (uint32)atoi(e);
|
uint32 guid = (uint32)atoi(e);
|
||||||
uint32 index = (uint32)atoi(f);
|
uint32 index = (uint32)atoi(f);
|
||||||
|
|
||||||
Item *i = m_session->GetPlayer()->GetItemByGuid(MAKE_NEW_GUID(guid, 0, HIGHGUID_ITEM));
|
Item *i = m_session->GetPlayer()->GetItemByGuid(ObjectGuid(HIGHGUID_ITEM, guid));
|
||||||
|
|
||||||
if (!i)
|
if (!i)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -723,7 +723,7 @@ bool ChatHandler::HandleDebugSetItemValueCommand(const char* args)
|
||||||
uint32 index = (uint32)atoi(f);
|
uint32 index = (uint32)atoi(f);
|
||||||
uint32 value = (uint32)atoi(g);
|
uint32 value = (uint32)atoi(g);
|
||||||
|
|
||||||
Item *i = m_session->GetPlayer()->GetItemByGuid(MAKE_NEW_GUID(guid, 0, HIGHGUID_ITEM));
|
Item *i = m_session->GetPlayer()->GetItemByGuid(ObjectGuid(HIGHGUID_ITEM, guid));
|
||||||
|
|
||||||
if (!i)
|
if (!i)
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "9578"
|
#define REVISION_NR "9579"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue