Core/Loot: Prevent looting bosses by players that have already completed that encounter

Port From (https://github.com/TrinityCore/TrinityCore/commit/9ce47e6809eecc891904e272b368596fdc55e6a4)
This commit is contained in:
hondacrx
2022-10-06 20:50:10 -04:00
parent 2bba8aeb99
commit 39e9e73277
6 changed files with 57 additions and 14 deletions
+1 -1
View File
@@ -5973,7 +5973,7 @@ namespace Game.Entities
return;
}
if (!item.AllowedForPlayer(this))
if (!item.HasAllowedLooter(GetGUID()))
{
SendLootReleaseAll();
return;
+13
View File
@@ -558,6 +558,19 @@ namespace Game.Entities
SendPacket(transferAborted);
}
public bool IsLockedToDungeonEncounter(uint dungeonEncounterId)
{
DungeonEncounterRecord dungeonEncounter = CliDB.DungeonEncounterStorage.LookupByKey(dungeonEncounterId);
if (dungeonEncounter == null)
return false;
InstanceLock instanceLock = Global.InstanceLockMgr.FindActiveInstanceLock(GetGUID(), new MapDb2Entries(GetMap().GetEntry(), GetMap().GetMapDifficulty()));
if (instanceLock == null)
return false;
return (instanceLock.GetData().CompletedEncountersMask & (1u << dungeonEncounter.Bit)) != 0;
}
public override void ProcessTerrainStatusUpdate(ZLiquidStatus oldLiquidStatus, LiquidData newLiquidData)
{
// process liquid auras using generic unit code
+2 -1
View File
@@ -3130,7 +3130,8 @@ namespace Game.Entities
Loot loot = creature.GetLootForPlayer(this);
if (loot == null || loot.IsLooted()) // nothing to loot or everything looted.
return false;
if (!loot.HasItemForAll() && !loot.HasItemFor(this)) // no loot in creature for this player
if (!loot.HasAllowedLooter(GetGUID()) || (!loot.HasItemForAll() && !loot.HasItemFor(this))) // no loot in creature for this player
return false;
if (loot.loot_type == LootType.Skinning)
+15 -6
View File
@@ -119,6 +119,9 @@ namespace Game
if (!member)
continue;
if (!loot.HasAllowedLooter(member.GetGUID()))
continue;
if (player.IsAtGroupRewardDistance(member))
playersNear.Add(member);
}
@@ -406,15 +409,21 @@ namespace Game
{
Loot loot = _player.GetAELootView().LookupByKey(req.Object);
if (loot == null || loot.GetLootMethod() != LootMethod.MasterLoot)
return;
if (!_player.IsInRaidWith(target) || !_player.IsInMap(target))
{
_player.SendLootError(req.Object, ObjectGuid.Empty, LootError.MasterOther);
_player.SendLootError(req.Object, loot.GetOwnerGUID(), LootError.MasterOther);
Log.outInfo(LogFilter.Cheat, $"MasterLootItem: Player {GetPlayer().GetName()} tried to give an item to ineligible player {target.GetName()} !");
return;
}
if (loot == null || loot.GetLootMethod() != LootMethod.MasterLoot)
if (!loot.HasAllowedLooter(masterLootItem.Target))
{
_player.SendLootError(req.Object, loot.GetOwnerGUID(), LootError.MasterOther);
return;
}
if (req.LootListID >= loot.items.Count)
{
@@ -426,16 +435,16 @@ namespace Game
List<ItemPosCount> dest = new();
InventoryResult msg = target.CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, item.itemid, item.count);
if (!item.AllowedForPlayer(target, true))
if (!item.HasAllowedLooter(target.GetGUID()))
msg = InventoryResult.CantEquipEver;
if (msg != InventoryResult.Ok)
{
if (msg == InventoryResult.ItemMaxCount)
_player.SendLootError(req.Object, ObjectGuid.Empty, LootError.MasterUniqueItem);
_player.SendLootError(req.Object, loot.GetOwnerGUID(), LootError.MasterUniqueItem);
else if (msg == InventoryResult.InvFull)
_player.SendLootError(req.Object, ObjectGuid.Empty, LootError.MasterInvFull);
_player.SendLootError(req.Object, loot.GetOwnerGUID(), LootError.MasterInvFull);
else
_player.SendLootError(req.Object, ObjectGuid.Empty, LootError.MasterOther);
_player.SendLootError(req.Object, loot.GetOwnerGUID(), LootError.MasterOther);
return;
}
+25 -5
View File
@@ -45,7 +45,13 @@ namespace Game.Loots
randomBonusListId = ItemEnchantmentManager.GenerateItemRandomBonusListId(itemid);
}
public bool AllowedForPlayer(Player player, bool isGivenByMasterLooter = false)
/// <summary>
/// Basic checks for player/item compatibility - if false no chance to see the item in the loot - used only for loot generation
/// </summary>
/// <param name="player"></param>
/// <param name="loot"></param>
/// <returns></returns>
public bool AllowedForPlayer(Player player, Loot loot)
{
// DB conditions check
if (!Global.ConditionMgr.IsObjectMeetToConditions(player, conditions))
@@ -63,7 +69,7 @@ namespace Game.Loots
return false;
// Master looter can see all items even if the character can't loot them
if (!isGivenByMasterLooter && player.GetGroup() && player.GetGroup().GetMasterLooterGuid() == player.GetGUID())
if (loot.GetLootMethod() == LootMethod.MasterLoot && follow_loot_rules && player.GetGroup() != null && player.GetGroup().GetMasterLooterGuid() == player.GetGUID())
return true;
// Don't allow loot for players without profession or those who already know the recipe
@@ -108,6 +114,11 @@ namespace Game.Loots
allowedGUIDs.Add(player.GetGUID());
}
public bool HasAllowedLooter(ObjectGuid looter)
{
return allowedGUIDs.Contains(looter);
}
public LootSlotType? GetUiTypeForPlayer(Player player, Loot loot)
{
if (is_looted)
@@ -439,7 +450,7 @@ namespace Game.Loots
foreach (ObjectGuid allowedLooter in m_lootItem.GetAllowedLooters())
{
Player plr = Global.ObjAccessor.GetPlayer(m_map, allowedLooter);
if (!plr || !m_lootItem.AllowedForPlayer(plr)) // check if player meet the condition to be able to roll this item
if (!plr || !m_lootItem.HasAllowedLooter(plr.GetGUID())) // check if player meet the condition to be able to roll this item
{
m_rollVoteMap[allowedLooter].Vote = RollVote.NotValid;
continue;
@@ -692,7 +703,7 @@ namespace Game.Loots
if (lootItem == null || lootItem.is_looted)
continue;
if (!lootItem.AllowedForPlayer(player))
if (!lootItem.HasAllowedLooter(GetGUID()))
continue;
if (lootItem.is_blocked)
@@ -817,6 +828,10 @@ namespace Game.Loots
void FillNotNormalLootFor(Player player)
{
if (_dungeonEncounterId != 0)
if (player.IsLockedToDungeonEncounter(_dungeonEncounterId))
return;
ObjectGuid plguid = player.GetGUID();
_allowedLooters.Add(plguid);
@@ -824,7 +839,7 @@ namespace Game.Loots
foreach (LootItem item in items)
{
if (!item.AllowedForPlayer(player))
if (!item.AllowedForPlayer(player, this))
continue;
if (item.freeforall)
@@ -921,6 +936,11 @@ namespace Game.Loots
}
}
public bool HasAllowedLooter(ObjectGuid looter)
{
return _allowedLooters.Contains(looter);
}
public void GenerateMoneyLoot(uint minAmount, uint maxAmount)
{
if (maxAmount > 0)
+1 -1
View File
@@ -208,7 +208,7 @@ namespace Game.Loots
// saved to the DB that the player never should have gotten. This check prevents that, so that only
// items that the player should get in loot are in the DB.
// IE: Horde items are not saved to the DB for Ally players.
if (!li.AllowedForPlayer(player))
if (!li.AllowedForPlayer(player, loot))
continue;
// Don't save currency tokens