feat(Core/Scripting): Implement OnAllowedForPlayerLootCheck() hook (#12316)
* feat(Core/Scripting): Implement OnAllowedForPlayerLootCheck() hook * reverse logic
This commit is contained in:
@@ -284,6 +284,8 @@ void Creature::AddToWorld()
|
|||||||
GetZoneScript()->OnCreatureCreate(this);
|
GetZoneScript()->OnCreatureCreate(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loot.sourceWorldObjectGUID = GetGUID();
|
||||||
|
|
||||||
sScriptMgr->OnCreatureAddWorld(this);
|
sScriptMgr->OnCreatureAddWorld(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,6 +159,8 @@ void GameObject::AddToWorld()
|
|||||||
|
|
||||||
WorldObject::AddToWorld();
|
WorldObject::AddToWorld();
|
||||||
|
|
||||||
|
loot.sourceWorldObjectGUID = GetGUID();
|
||||||
|
|
||||||
sScriptMgr->OnGameObjectAddWorld(this);
|
sScriptMgr->OnGameObjectAddWorld(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13180,7 +13180,7 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!item->AllowedForPlayer(this))
|
if (!item->AllowedForPlayer(this, loot->sourceWorldObjectGUID))
|
||||||
{
|
{
|
||||||
SendLootRelease(GetLootGUID());
|
SendLootRelease(GetLootGUID());
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1015,7 +1015,7 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject)
|
|||||||
continue;
|
continue;
|
||||||
if (member->IsAtLootRewardDistance(pLootedObject))
|
if (member->IsAtLootRewardDistance(pLootedObject))
|
||||||
{
|
{
|
||||||
if (i->AllowedForPlayer(member))
|
if (i->AllowedForPlayer(member, loot->sourceWorldObjectGUID))
|
||||||
{
|
{
|
||||||
r->totalPlayersRolling++;
|
r->totalPlayersRolling++;
|
||||||
|
|
||||||
@@ -1099,7 +1099,7 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject)
|
|||||||
|
|
||||||
if (member->IsAtLootRewardDistance(pLootedObject))
|
if (member->IsAtLootRewardDistance(pLootedObject))
|
||||||
{
|
{
|
||||||
if (i->AllowedForPlayer(member))
|
if (i->AllowedForPlayer(member, loot->sourceWorldObjectGUID))
|
||||||
{
|
{
|
||||||
r->totalPlayersRolling++;
|
r->totalPlayersRolling++;
|
||||||
r->playerVote[member->GetGUID()] = NOT_EMITED_YET;
|
r->playerVote[member->GetGUID()] = NOT_EMITED_YET;
|
||||||
@@ -1157,7 +1157,7 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject)
|
|||||||
if (!playerToRoll)
|
if (!playerToRoll)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (i->AllowedForPlayer(playerToRoll) && playerToRoll->IsAtLootRewardDistance(lootedObject))
|
if (i->AllowedForPlayer(playerToRoll, loot->sourceWorldObjectGUID) && playerToRoll->IsAtLootRewardDistance(lootedObject))
|
||||||
{
|
{
|
||||||
r->totalPlayersRolling++;
|
r->totalPlayersRolling++;
|
||||||
if (playerToRoll->GetPassOnGroupLoot())
|
if (playerToRoll->GetPassOnGroupLoot())
|
||||||
@@ -1231,7 +1231,7 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject)
|
|||||||
if (!playerToRoll)
|
if (!playerToRoll)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (i->AllowedForPlayer(playerToRoll) && playerToRoll->IsAtLootRewardDistance(lootedObject))
|
if (i->AllowedForPlayer(playerToRoll, loot->sourceWorldObjectGUID) && playerToRoll->IsAtLootRewardDistance(lootedObject))
|
||||||
{
|
{
|
||||||
r->totalPlayersRolling++;
|
r->totalPlayersRolling++;
|
||||||
r->playerVote[playerToRoll->GetGUID()] = NOT_EMITED_YET;
|
r->playerVote[playerToRoll->GetGUID()] = NOT_EMITED_YET;
|
||||||
|
|||||||
@@ -469,7 +469,7 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPacket& recvData)
|
|||||||
|
|
||||||
ItemPosCountVec dest;
|
ItemPosCountVec dest;
|
||||||
InventoryResult msg = target->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item.itemid, item.count);
|
InventoryResult msg = target->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item.itemid, item.count);
|
||||||
if (!item.AllowedForPlayer(target, true))
|
if (!item.AllowedForPlayer(target, loot->sourceWorldObjectGUID))
|
||||||
msg = EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
|
msg = EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
|
||||||
if (msg != EQUIP_ERR_OK)
|
if (msg != EQUIP_ERR_OK)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -404,7 +404,7 @@ LootItem::LootItem(LootStoreItem const& li)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Basic checks for player/item compatibility - if false no chance to see the item in the loot
|
// Basic checks for player/item compatibility - if false no chance to see the item in the loot
|
||||||
bool LootItem::AllowedForPlayer(Player const* player, bool isGivenByMasterLooter /*= false*/, bool allowQuestLoot /*= true*/) const
|
bool LootItem::AllowedForPlayer(Player const* player, bool isGivenByMasterLooter /*= false*/, bool allowQuestLoot /*= true*/, ObjectGuid source) const
|
||||||
{
|
{
|
||||||
ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(itemid);
|
ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(itemid);
|
||||||
if (!pProto)
|
if (!pProto)
|
||||||
@@ -472,6 +472,11 @@ bool LootItem::AllowedForPlayer(Player const* player, bool isGivenByMasterLooter
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!sScriptMgr->OnAllowedForPlayerLootCheck(player, source))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,7 +520,7 @@ void Loot::AddItem(LootStoreItem const& item)
|
|||||||
{
|
{
|
||||||
if (auto member = itr->GetSource())
|
if (auto member = itr->GetSource())
|
||||||
{
|
{
|
||||||
if (generatedLoot.AllowedForPlayer(member))
|
if (generatedLoot.AllowedForPlayer(member, sourceWorldObjectGUID))
|
||||||
{
|
{
|
||||||
canSeeItemInLootWindow = true;
|
canSeeItemInLootWindow = true;
|
||||||
break;
|
break;
|
||||||
@@ -523,7 +528,7 @@ void Loot::AddItem(LootStoreItem const& item)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (generatedLoot.AllowedForPlayer(player))
|
else if (generatedLoot.AllowedForPlayer(player, sourceWorldObjectGUID))
|
||||||
{
|
{
|
||||||
canSeeItemInLootWindow = true;
|
canSeeItemInLootWindow = true;
|
||||||
}
|
}
|
||||||
@@ -626,7 +631,7 @@ void Loot::FillNotNormalLootFor(Player* player)
|
|||||||
else
|
else
|
||||||
item = &quest_items[i - itemsSize];
|
item = &quest_items[i - itemsSize];
|
||||||
|
|
||||||
if (!item->is_looted && item->freeforall && item->AllowedForPlayer(player))
|
if (!item->is_looted && item->freeforall && item->AllowedForPlayer(player, sourceWorldObjectGUID))
|
||||||
if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item->itemid))
|
if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item->itemid))
|
||||||
if (proto->IsCurrencyToken())
|
if (proto->IsCurrencyToken())
|
||||||
player->StoreLootItem(i, this);
|
player->StoreLootItem(i, this);
|
||||||
@@ -640,7 +645,7 @@ QuestItemList* Loot::FillFFALoot(Player* player)
|
|||||||
for (uint8 i = 0; i < items.size(); ++i)
|
for (uint8 i = 0; i < items.size(); ++i)
|
||||||
{
|
{
|
||||||
LootItem& item = items[i];
|
LootItem& item = items[i];
|
||||||
if (!item.is_looted && item.freeforall && item.AllowedForPlayer(player))
|
if (!item.is_looted && item.freeforall && item.AllowedForPlayer(player, containerGUID))
|
||||||
{
|
{
|
||||||
ql->push_back(QuestItem(i));
|
ql->push_back(QuestItem(i));
|
||||||
++unlootedCount;
|
++unlootedCount;
|
||||||
@@ -701,7 +706,7 @@ QuestItemList* Loot::FillNonQuestNonFFAConditionalLoot(Player* player)
|
|||||||
for (uint8 i = 0; i < items.size(); ++i)
|
for (uint8 i = 0; i < items.size(); ++i)
|
||||||
{
|
{
|
||||||
LootItem& item = items[i];
|
LootItem& item = items[i];
|
||||||
if (!item.is_looted && !item.freeforall && (item.AllowedForPlayer(player) || (item.follow_loot_rules && player->GetGroup() && ((player->GetGroup()->GetLootMethod() == MASTER_LOOT && player->GetGroup()->GetMasterLooterGuid() == player->GetGUID()) || player->GetGroup()->GetLootMethod() != MASTER_LOOT ))))
|
if (!item.is_looted && !item.freeforall && (item.AllowedForPlayer(player, sourceWorldObjectGUID) || (item.follow_loot_rules && player->GetGroup() && ((player->GetGroup()->GetLootMethod() == MASTER_LOOT && player->GetGroup()->GetMasterLooterGuid() == player->GetGUID()) || player->GetGroup()->GetLootMethod() != MASTER_LOOT ))))
|
||||||
{
|
{
|
||||||
item.AddAllowedLooter(player);
|
item.AddAllowedLooter(player);
|
||||||
|
|
||||||
@@ -820,7 +825,7 @@ LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, QuestItem * *qit
|
|||||||
if (qitem)
|
if (qitem)
|
||||||
*qitem = qitem2;
|
*qitem = qitem2;
|
||||||
item = &quest_items[qitem2->index];
|
item = &quest_items[qitem2->index];
|
||||||
if (item->follow_loot_rules && !item->AllowedForPlayer(player)) // pussywizard: such items (follow_loot_rules) are added to every player, but not everyone is allowed, check it here
|
if (item->follow_loot_rules && !item->AllowedForPlayer(player, sourceWorldObjectGUID)) // pussywizard: such items (follow_loot_rules) are added to every player, but not everyone is allowed, check it here
|
||||||
return nullptr;
|
return nullptr;
|
||||||
is_looted = qitem2->is_looted;
|
is_looted = qitem2->is_looted;
|
||||||
}
|
}
|
||||||
@@ -989,7 +994,7 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
|
|||||||
// blocked rolled items and quest items, and !ffa items
|
// blocked rolled items and quest items, and !ffa items
|
||||||
for (uint8 i = 0; i < l.items.size(); ++i)
|
for (uint8 i = 0; i < l.items.size(); ++i)
|
||||||
{
|
{
|
||||||
if (!l.items[i].is_looted && !l.items[i].freeforall && (l.items[i].conditions.empty() || isMasterLooter) && l.items[i].AllowedForPlayer(lv.viewer))
|
if (!l.items[i].is_looted && !l.items[i].freeforall && (l.items[i].conditions.empty() || isMasterLooter) && l.items[i].AllowedForPlayer(lv.viewer, l.sourceWorldObjectGUID))
|
||||||
{
|
{
|
||||||
uint8 slot_type = 0;
|
uint8 slot_type = 0;
|
||||||
|
|
||||||
@@ -1047,7 +1052,7 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
|
|||||||
{
|
{
|
||||||
for (uint8 i = 0; i < l.items.size(); ++i)
|
for (uint8 i = 0; i < l.items.size(); ++i)
|
||||||
{
|
{
|
||||||
if (!l.items[i].is_looted && !l.items[i].freeforall && l.items[i].conditions.empty() && l.items[i].AllowedForPlayer(lv.viewer))
|
if (!l.items[i].is_looted && !l.items[i].freeforall && l.items[i].conditions.empty() && l.items[i].AllowedForPlayer(lv.viewer, l.sourceWorldObjectGUID))
|
||||||
{
|
{
|
||||||
if (l.roundRobinPlayer && lv.viewer->GetGUID() != l.roundRobinPlayer)
|
if (l.roundRobinPlayer && lv.viewer->GetGUID() != l.roundRobinPlayer)
|
||||||
// item shall not be displayed.
|
// item shall not be displayed.
|
||||||
@@ -1066,7 +1071,7 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
|
|||||||
uint8 slot_type = lv.permission == OWNER_PERMISSION ? LOOT_SLOT_TYPE_OWNER : LOOT_SLOT_TYPE_ALLOW_LOOT;
|
uint8 slot_type = lv.permission == OWNER_PERMISSION ? LOOT_SLOT_TYPE_OWNER : LOOT_SLOT_TYPE_ALLOW_LOOT;
|
||||||
for (uint8 i = 0; i < l.items.size(); ++i)
|
for (uint8 i = 0; i < l.items.size(); ++i)
|
||||||
{
|
{
|
||||||
if (!l.items[i].is_looted && !l.items[i].freeforall && l.items[i].conditions.empty() && l.items[i].AllowedForPlayer(lv.viewer))
|
if (!l.items[i].is_looted && !l.items[i].freeforall && l.items[i].conditions.empty() && l.items[i].AllowedForPlayer(lv.viewer, l.sourceWorldObjectGUID))
|
||||||
{
|
{
|
||||||
b << uint8(i) << l.items[i];
|
b << uint8(i) << l.items[i];
|
||||||
b << uint8(slot_type);
|
b << uint8(slot_type);
|
||||||
|
|||||||
@@ -176,8 +176,8 @@ struct LootItem
|
|||||||
LootItem() = default;
|
LootItem() = default;
|
||||||
|
|
||||||
// Basic checks for player/item compatibility - if false no chance to see the item in the loot
|
// Basic checks for player/item compatibility - if false no chance to see the item in the loot
|
||||||
bool AllowedForPlayer(Player const* player, bool isGivenByMasterLooter = false, bool allowQuestLoot = true) const;
|
bool AllowedForPlayer(Player const* player, bool isGivenByMasterLooter = false, bool allowQuestLoot = true, ObjectGuid source = ObjectGuid::Empty) const;
|
||||||
|
bool AllowedForPlayer(Player const* player, ObjectGuid source) { return AllowedForPlayer(player, false, true, source); };
|
||||||
void AddAllowedLooter(Player const* player);
|
void AddAllowedLooter(Player const* player);
|
||||||
[[nodiscard]] const AllowedLooterSet& GetAllowedLooters() const { return allowedGUIDs; }
|
[[nodiscard]] const AllowedLooterSet& GetAllowedLooters() const { return allowedGUIDs; }
|
||||||
};
|
};
|
||||||
@@ -327,6 +327,7 @@ struct Loot
|
|||||||
|
|
||||||
// GUID of container that holds this loot (item_instance.entry), set for items that can be looted
|
// GUID of container that holds this loot (item_instance.entry), set for items that can be looted
|
||||||
ObjectGuid containerGUID;
|
ObjectGuid containerGUID;
|
||||||
|
ObjectGuid sourceWorldObjectGUID;
|
||||||
GameObject* sourceGameObject{nullptr};
|
GameObject* sourceGameObject{nullptr};
|
||||||
|
|
||||||
Loot(uint32 _gold = 0) : gold(_gold) { }
|
Loot(uint32 _gold = 0) : gold(_gold) { }
|
||||||
|
|||||||
@@ -161,3 +161,18 @@ void ScriptMgr::OnLoadSpellCustomAttr(SpellInfo* spell)
|
|||||||
script->OnLoadSpellCustomAttr(spell);
|
script->OnLoadSpellCustomAttr(spell);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ScriptMgr::OnAllowedForPlayerLootCheck(Player const* player, ObjectGuid source)
|
||||||
|
{
|
||||||
|
auto ret = IsValidBoolScript<GlobalScript>([&](GlobalScript* script)
|
||||||
|
{
|
||||||
|
return script->OnAllowedForPlayerLootCheck(player, source);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ret && *ret)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1549,6 +1549,9 @@ public:
|
|||||||
|
|
||||||
// Called after loading spell dbc corrections
|
// Called after loading spell dbc corrections
|
||||||
virtual void OnLoadSpellCustomAttr(SpellInfo* /*spell*/) { }
|
virtual void OnLoadSpellCustomAttr(SpellInfo* /*spell*/) { }
|
||||||
|
|
||||||
|
// Called when checking if a player can see the creature loot
|
||||||
|
virtual bool OnAllowedForPlayerLootCheck(Player const* /*player*/, ObjectGuid /*source*/) { return false; };
|
||||||
};
|
};
|
||||||
|
|
||||||
class BGScript : public ScriptObject
|
class BGScript : public ScriptObject
|
||||||
@@ -2371,6 +2374,7 @@ public: /* GlobalScript */
|
|||||||
bool OnIsAffectedBySpellModCheck(SpellInfo const* affectSpell, SpellInfo const* checkSpell, SpellModifier const* mod);
|
bool OnIsAffectedBySpellModCheck(SpellInfo const* affectSpell, SpellInfo const* checkSpell, SpellModifier const* mod);
|
||||||
bool OnSpellHealingBonusTakenNegativeModifiers(Unit const* target, Unit const* caster, SpellInfo const* spellInfo, float& val);
|
bool OnSpellHealingBonusTakenNegativeModifiers(Unit const* target, Unit const* caster, SpellInfo const* spellInfo, float& val);
|
||||||
void OnLoadSpellCustomAttr(SpellInfo* spell);
|
void OnLoadSpellCustomAttr(SpellInfo* spell);
|
||||||
|
bool OnAllowedForPlayerLootCheck(Player const* player, ObjectGuid source);
|
||||||
|
|
||||||
public: /* Scheduled scripts */
|
public: /* Scheduled scripts */
|
||||||
uint32 IncreaseScheduledScriptsCount() { return ++_scheduledScripts; }
|
uint32 IncreaseScheduledScriptsCount() { return ++_scheduledScripts; }
|
||||||
|
|||||||
Reference in New Issue
Block a user