Fixes and cleanups in loot code.

* Move not-normal loot tables generation in single place (Loot::FillLoot function) for group and non group case.
* Simplify LootView code.
This commit is contained in:
VladimirMangos 2009-02-07 09:19:18 +03:00
parent fb432a0f36
commit 7d63f4ce02
6 changed files with 86 additions and 99 deletions

View file

@ -480,7 +480,7 @@ void GameObject::Delete()
AddObjectToRemoveList();
}
void GameObject::getFishLoot(Loot *fishloot)
void GameObject::getFishLoot(Loot *fishloot, Player* loot_owner)
{
fishloot->clear();
@ -488,10 +488,10 @@ void GameObject::getFishLoot(Loot *fishloot)
// if subzone loot exist use it
if(LootTemplates_Fishing.HaveLootFor(subzone))
fishloot->FillLoot(subzone, LootTemplates_Fishing, NULL);
fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner,true);
// else use zone loot
else
fishloot->FillLoot(GetZoneId(), LootTemplates_Fishing, NULL);
fishloot->FillLoot(GetZoneId(), LootTemplates_Fishing, loot_owner,true);
}
void GameObject::SaveToDB()

View file

@ -507,7 +507,7 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
void Delete();
void SetSpellId(uint32 id) { m_spellId = id;}
uint32 GetSpellId() const { return m_spellId;}
void getFishLoot(Loot *loot);
void getFishLoot(Loot *loot, Player* loot_owner);
GameobjectTypes GetGoType() const { return GameobjectTypes(GetByteValue(GAMEOBJECT_BYTES_1, 1)); }
void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); }
uint8 GetGoState() const { return GetByteValue(GAMEOBJECT_BYTES_1, 0); }

View file

@ -366,8 +366,12 @@ void Loot::AddItem(LootStoreItem const & item)
}
// Calls processor of corresponding LootTemplate (which handles everything including references)
void Loot::FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner)
void Loot::FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner, bool personal)
{
// Must be provided
if(!loot_owner)
return;
LootTemplate const* tab = store.GetLootFor(loot_id);
if (!tab)
@ -381,35 +385,34 @@ void Loot::FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner)
tab->Process(*this, store,store.IsRatesAllowed ()); // Processing is done there, callback via Loot::AddItem()
// Setting access rights fow group-looting case
if(!loot_owner)
return;
// Setting access rights for group loot case
Group * pGroup=loot_owner->GetGroup();
if(!pGroup)
return;
for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
if(!personal && pGroup)
{
//fill the quest item map for every player in the recipient's group
Player* pl = itr->getSource();
if(!pl)
continue;
uint32 plguid = pl->GetGUIDLow();
QuestItemMap::iterator qmapitr = PlayerQuestItems.find(plguid);
if (qmapitr == PlayerQuestItems.end())
{
FillQuestLoot(pl);
}
qmapitr = PlayerFFAItems.find(plguid);
if (qmapitr == PlayerFFAItems.end())
{
FillFFALoot(pl);
}
qmapitr = PlayerNonQuestNonFFAConditionalItems.find(plguid);
if (qmapitr == PlayerNonQuestNonFFAConditionalItems.end())
{
FillNonQuestNonFFAConditionalLoot(pl);
}
for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
if(Player* pl = itr->getSource())
FillNotNormalLootFor(pl);
}
// ... for personal loot
else
FillNotNormalLootFor(loot_owner);
}
void Loot::FillNotNormalLootFor(Player* pl)
{
uint32 plguid = pl->GetGUIDLow();
QuestItemMap::iterator qmapitr = PlayerQuestItems.find(plguid);
if (qmapitr == PlayerQuestItems.end())
FillQuestLoot(pl);
qmapitr = PlayerFFAItems.find(plguid);
if (qmapitr == PlayerFFAItems.end())
FillFFALoot(pl);
qmapitr = PlayerNonQuestNonFFAConditionalItems.find(plguid);
if (qmapitr == PlayerNonQuestNonFFAConditionalItems.end())
FillNonQuestNonFFAConditionalLoot(pl);
}
QuestItemList* Loot::FillFFALoot(Player* player)
@ -653,12 +656,19 @@ ByteBuffer& operator<<(ByteBuffer& b, LootItem const& li)
ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
{
if (lv.permission == NONE_PERMISSION)
{
b << uint32(0); //gold
b << uint8(0); // item count
return b; // nothing output more
}
Loot &l = lv.loot;
uint8 itemsShown = 0;
//gold
b << uint32(lv.permission!=NONE_PERMISSION ? l.gold : 0);
b << uint32(l.gold);
size_t count_pos = b.wpos(); // pos of item count byte
b << uint8(0); // item count placeholder
@ -697,19 +707,21 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
}
break;
}
case NONE_PERMISSION:
default:
return b; // nothing output more
}
if (lv.qlist)
QuestItemMap const& lootPlayerQuestItems = l.GetPlayerQuestItems();
QuestItemMap::const_iterator q_itr = lootPlayerQuestItems.find(lv.viewer->GetGUIDLow());
if (q_itr != lootPlayerQuestItems.end())
{
for (QuestItemList::iterator qi = lv.qlist->begin() ; qi != lv.qlist->end(); ++qi)
QuestItemList *q_list = q_itr->second;
for (QuestItemList::iterator qi = q_list->begin() ; qi != q_list->end(); ++qi)
{
LootItem &item = l.quest_items[qi->index];
if (!qi->is_looted && !item.is_looted)
{
b << uint8(l.items.size() + (qi - lv.qlist->begin()));
b << uint8(l.items.size() + (qi - q_list->begin()));
b << item;
b << uint8(0); // allow loot
++itemsShown;
@ -717,9 +729,12 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
}
}
if (lv.ffalist)
QuestItemMap const& lootPlayerFFAItems = l.GetPlayerFFAItems();
QuestItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(lv.viewer->GetGUIDLow());
if (ffa_itr != lootPlayerFFAItems.end())
{
for (QuestItemList::iterator fi = lv.ffalist->begin() ; fi != lv.ffalist->end(); ++fi)
QuestItemList *ffa_list = ffa_itr->second;
for (QuestItemList::iterator fi = ffa_list->begin() ; fi != ffa_list->end(); ++fi)
{
LootItem &item = l.items[fi->index];
if (!fi->is_looted && !item.is_looted)
@ -731,9 +746,12 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
}
}
if (lv.conditionallist)
QuestItemMap const& lootPlayerNonQuestNonFFAConditionalItems = l.GetPlayerNonQuestNonFFAConditionalItems();
QuestItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(lv.viewer->GetGUIDLow());
if (nn_itr != lootPlayerNonQuestNonFFAConditionalItems.end())
{
for (QuestItemList::iterator ci = lv.conditionallist->begin() ; ci != lv.conditionallist->end(); ++ci)
QuestItemList *conditional_list = nn_itr->second;
for (QuestItemList::iterator ci = conditional_list->begin() ; ci != conditional_list->end(); ++ci)
{
LootItem &item = l.items[ci->index];
if (!ci->is_looted && !item.is_looted)

View file

@ -208,17 +208,19 @@ class LootValidatorRefManager : public RefManager<Loot, LootValidatorRef>
};
//=====================================================
struct LootView;
ByteBuffer& operator<<(ByteBuffer& b, LootItem const& li);
ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv);
struct Loot
{
friend ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv);
QuestItemMap const& GetPlayerQuestItems() const { return PlayerQuestItems; }
QuestItemMap const& GetPlayerFFAItems() const { return PlayerFFAItems; }
QuestItemMap const& GetPlayerNonQuestNonFFAConditionalItems() const { return PlayerNonQuestNonFFAConditionalItems; }
QuestItemList* FillFFALoot(Player* player);
QuestItemList* FillQuestLoot(Player* player);
QuestItemList* FillNonQuestNonFFAConditionalLoot(Player* player);
std::vector<LootItem> items;
std::vector<LootItem> quest_items;
uint32 gold;
@ -265,13 +267,19 @@ struct Loot
void RemoveLooter(uint64 GUID) { PlayersLooting.erase(GUID); }
void generateMoneyLoot(uint32 minAmount, uint32 maxAmount);
void FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner);
void FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner, bool personal);
// Inserts the item into the loot (called by LootTemplate processors)
void AddItem(LootStoreItem const & item);
LootItem* LootItemInSlot(uint32 lootslot, Player* player, QuestItem** qitem = NULL, QuestItem** ffaitem = NULL, QuestItem** conditem = NULL);
private:
void FillNotNormalLootFor(Player* player);
QuestItemList* FillFFALoot(Player* player);
QuestItemList* FillQuestLoot(Player* player);
QuestItemList* FillNonQuestNonFFAConditionalLoot(Player* player);
std::set<uint64> PlayersLooting;
QuestItemMap PlayerQuestItems;
QuestItemMap PlayerFFAItems;
@ -279,19 +287,15 @@ struct Loot
// All rolls are registered here. They need to know, when the loot is not valid anymore
LootValidatorRefManager i_LootValidatorRefManager;
};
struct LootView
{
Loot &loot;
QuestItemList *qlist;
QuestItemList *ffalist;
QuestItemList *conditionallist;
Player *viewer;
PermissionTypes permission;
LootView(Loot &_loot, QuestItemList *_qlist, QuestItemList *_ffalist, QuestItemList *_conditionallist, Player *_viewer,PermissionTypes _permission = ALL_PERMISSION)
: loot(_loot), qlist(_qlist), ffalist(_ffalist), conditionallist(_conditionallist), viewer(_viewer), permission(_permission) {}
LootView(Loot &_loot, Player *_viewer,PermissionTypes _permission = ALL_PERMISSION)
: loot(_loot), viewer(_viewer), permission(_permission) {}
};
extern LootStore LootTemplates_Creature;
@ -337,6 +341,4 @@ inline void LoadLootTables()
LoadLootTemplates_Reference();
}
ByteBuffer& operator<<(ByteBuffer& b, LootItem const& li);
ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv);
#endif

View file

@ -7401,11 +7401,11 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
{
sLog.outDebug(" if(lootid)");
loot->clear();
loot->FillLoot(lootid, LootTemplates_Gameobject, this);
loot->FillLoot(lootid, LootTemplates_Gameobject, this, false);
}
if(loot_type == LOOT_FISHING)
go->getFishLoot(loot);
go->getFishLoot(loot,this);
go->SetLootState(GO_ACTIVATED);
}
@ -7428,7 +7428,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
{
item->m_lootGenerated = true;
loot->clear();
loot->FillLoot(item->GetProto()->DisenchantID, LootTemplates_Disenchant, this);
loot->FillLoot(item->GetProto()->DisenchantID, LootTemplates_Disenchant, this,true);
}
}
else if(loot_type == LOOT_PROSPECTING)
@ -7439,7 +7439,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
{
item->m_lootGenerated = true;
loot->clear();
loot->FillLoot(item->GetEntry(), LootTemplates_Prospecting, this);
loot->FillLoot(item->GetEntry(), LootTemplates_Prospecting, this,true);
}
}
else if(loot_type == LOOT_MILLING)
@ -7450,7 +7450,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
{
item->m_lootGenerated = true;
loot->clear();
loot->FillLoot(item->GetEntry(), LootTemplates_Milling, this);
loot->FillLoot(item->GetEntry(), LootTemplates_Milling, this,true);
}
}
else
@ -7461,7 +7461,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
{
item->m_lootGenerated = true;
loot->clear();
loot->FillLoot(item->GetEntry(), LootTemplates_Item, this);
loot->FillLoot(item->GetEntry(), LootTemplates_Item, this,true);
loot->generateMoneyLoot(item->GetProto()->MinMoneyLoot,item->GetProto()->MaxMoneyLoot);
}
@ -7519,7 +7519,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
loot->clear();
if (uint32 lootid = creature->GetCreatureInfo()->pickpocketLootId)
loot->FillLoot(lootid, LootTemplates_Pickpocketing, this);
loot->FillLoot(lootid, LootTemplates_Pickpocketing, this, false);
// Generate extra money for pick pocket loot
const uint32 a = urand(0, creature->getLevel()/2);
@ -7549,7 +7549,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
loot->clear();
if (uint32 lootid = creature->GetCreatureInfo()->lootid)
loot->FillLoot(lootid, LootTemplates_Creature, recipient);
loot->FillLoot(lootid, LootTemplates_Creature, recipient, false);
loot->generateMoneyLoot(creature->GetCreatureInfo()->mingold,creature->GetCreatureInfo()->maxgold);
@ -7579,7 +7579,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
if (loot_type == LOOT_SKINNING)
{
loot->clear();
loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, this);
loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, this, false);
}
// set group rights only for loot_type != LOOT_SKINNING
else
@ -7613,39 +7613,6 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
SetLootGUID(guid);
QuestItemList *q_list = 0;
if (permission != NONE_PERMISSION)
{
QuestItemMap const& lootPlayerQuestItems = loot->GetPlayerQuestItems();
QuestItemMap::const_iterator itr = lootPlayerQuestItems.find(GetGUIDLow());
if (itr == lootPlayerQuestItems.end())
q_list = loot->FillQuestLoot(this);
else
q_list = itr->second;
}
QuestItemList *ffa_list = 0;
if (permission != NONE_PERMISSION)
{
QuestItemMap const& lootPlayerFFAItems = loot->GetPlayerFFAItems();
QuestItemMap::const_iterator itr = lootPlayerFFAItems.find(GetGUIDLow());
if (itr == lootPlayerFFAItems.end())
ffa_list = loot->FillFFALoot(this);
else
ffa_list = itr->second;
}
QuestItemList *conditional_list = 0;
if (permission != NONE_PERMISSION)
{
QuestItemMap const& lootPlayerNonQuestNonFFAConditionalItems = loot->GetPlayerNonQuestNonFFAConditionalItems();
QuestItemMap::const_iterator itr = lootPlayerNonQuestNonFFAConditionalItems.find(GetGUIDLow());
if (itr == lootPlayerNonQuestNonFFAConditionalItems.end())
conditional_list = loot->FillNonQuestNonFFAConditionalLoot(this);
else
conditional_list = itr->second;
}
// LOOT_PICKPOCKETING, LOOT_PROSPECTING, LOOT_DISENCHANTING, LOOT_INSIGNIA and LOOT_MILLING unsupported by client, sending LOOT_SKINNING instead
if(loot_type == LOOT_PICKPOCKETING || loot_type == LOOT_DISENCHANTING || loot_type == LOOT_PROSPECTING || loot_type == LOOT_INSIGNIA || loot_type == LOOT_MILLING)
loot_type = LOOT_SKINNING;
@ -7657,7 +7624,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
data << uint64(guid);
data << uint8(loot_type);
data << LootView(*loot, q_list, ffa_list, conditional_list, this, permission);
data << LootView(*loot, this, permission);
SendDirectMessage(&data);
@ -12799,7 +12766,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
Loot questMailLoot;
questMailLoot.FillLoot(pQuest->GetQuestId(), LootTemplates_QuestMail, this);
questMailLoot.FillLoot(pQuest->GetQuestId(), LootTemplates_QuestMail, this,true);
// fill mail
MailItemsInfo mi; // item list preparing
@ -19412,7 +19379,7 @@ void Player::InitRunes()
void Player::AutoStoreLootItem(uint8 bag, uint8 slot, uint32 loot_id, LootStore const& store)
{
Loot loot;
loot.FillLoot (loot_id,store,this);
loot.FillLoot (loot_id,store,this,true);
if(loot.items.empty ())
return;
LootItem const* lootItem = &loot.items[0];

View file

@ -1523,7 +1523,7 @@ void Aura::TriggerSpell()
}
Loot *loot = &creature->loot;
loot->clear();
loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, NULL);
loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, player, true);
for(uint8 i=0;i<loot->items.size();i++)
{
LootItem *item = loot->LootItemInSlot(i,player);