Core/Loot: Move loot rolls from Group to Loot
Port From (https://github.com/TrinityCore/TrinityCore/commit/3ef5079feeedfdafc9d3c1d9f865e96dbc77ecc8)
This commit is contained in:
@@ -92,6 +92,13 @@ namespace Game.Entities
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Update(uint diff)
|
||||
{
|
||||
base.Update(diff);
|
||||
|
||||
loot?.Update();
|
||||
}
|
||||
|
||||
public void SaveToDB()
|
||||
{
|
||||
// prevent DB data inconsistence problems and duplicates
|
||||
|
||||
@@ -91,8 +91,6 @@ namespace Game.Entities
|
||||
List<VendorItemCount> m_vendorItemCounts = new();
|
||||
|
||||
public Loot loot;
|
||||
public uint m_groupLootTimer; // (msecs)timer used for group loot
|
||||
public ObjectGuid lootingGroupLowGUID; // used to find group which is looting corpse
|
||||
ObjectGuid m_lootRecipient;
|
||||
ObjectGuid m_lootRecipientGroup;
|
||||
}
|
||||
|
||||
@@ -507,20 +507,9 @@ namespace Game.Entities
|
||||
if (IsEngaged())
|
||||
AIUpdateTick(diff);
|
||||
|
||||
if (loot != null && m_groupLootTimer != 0 && !lootingGroupLowGUID.IsEmpty())
|
||||
{
|
||||
if (m_groupLootTimer <= diff)
|
||||
{
|
||||
Group group = Global.GroupMgr.GetGroupByGUID(lootingGroupLowGUID);
|
||||
if (group)
|
||||
group.EndRoll(loot, GetMap());
|
||||
loot?.Update();
|
||||
|
||||
m_groupLootTimer = 0;
|
||||
lootingGroupLowGUID.Clear();
|
||||
}
|
||||
else m_groupLootTimer -= diff;
|
||||
}
|
||||
else if (m_corpseRemoveTime <= GameTime.GetGameTime())
|
||||
if (m_corpseRemoveTime <= GameTime.GetGameTime())
|
||||
{
|
||||
RemoveCorpse(false);
|
||||
Log.outDebug(LogFilter.Unit, "Removing corpse... {0} ", GetEntry());
|
||||
|
||||
@@ -697,20 +697,7 @@ namespace Game.Entities
|
||||
}
|
||||
break;
|
||||
case GameObjectTypes.Chest:
|
||||
if (loot != null && m_groupLootTimer != 0)
|
||||
{
|
||||
if (m_groupLootTimer <= diff)
|
||||
{
|
||||
Group group = Global.GroupMgr.GetGroupByGUID(lootingGroupLowGUID);
|
||||
if (group)
|
||||
group.EndRoll(loot, GetMap());
|
||||
|
||||
m_groupLootTimer = 0;
|
||||
lootingGroupLowGUID.Clear();
|
||||
}
|
||||
else
|
||||
m_groupLootTimer -= diff;
|
||||
}
|
||||
loot?.Update();
|
||||
|
||||
// Non-consumable chest was partially looted and restock time passed, restock all loot now
|
||||
if (GetGoInfo().Chest.consumable == 0 && GameTime.GetGameTime() >= m_restockTime)
|
||||
@@ -3423,8 +3410,6 @@ namespace Game.Entities
|
||||
ObjectGuid m_lootRecipientGroup;
|
||||
LootModes m_LootMode; // bitmask, default LOOT_MODE_DEFAULT, determines what loot will be lootable
|
||||
uint m_lootGenerationTime;
|
||||
public uint m_groupLootTimer; // (msecs)timer used for group loot
|
||||
public ObjectGuid lootingGroupLowGUID; // used to find group which is looting
|
||||
long m_packedRotation;
|
||||
Quaternion m_localRotation;
|
||||
public Position StationaryPosition { get; set; }
|
||||
|
||||
@@ -240,6 +240,7 @@ namespace Game.Entities
|
||||
SceneMgr m_sceneMgr;
|
||||
|
||||
Dictionary<ObjectGuid, Loot> m_AELootView = new();
|
||||
List<LootRoll> m_lootRolls = new(); // loot rolls waiting for answer
|
||||
|
||||
CUFProfile[] _CUFProfiles = new CUFProfile[PlayerConst.MaxCUFProfiles];
|
||||
float[] m_powerFraction = new float[(int)PowerType.MaxPerClass];
|
||||
|
||||
@@ -71,7 +71,8 @@ namespace Game.Entities
|
||||
if (state == LfgState.FinishedDungeon)
|
||||
return PartyResult.PartyLfgBootDungeonComplete;
|
||||
|
||||
if (grp.IsRollLootActive())
|
||||
Player player = Global.ObjAccessor.FindConnectedPlayer(guidMember);
|
||||
if (!player.m_lootRolls.Empty())
|
||||
return PartyResult.PartyLfgBootLootRolls;
|
||||
|
||||
// @todo Should also be sent when anyone has recently left combat, with an aprox ~5 seconds timer.
|
||||
|
||||
@@ -2949,13 +2949,12 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public InventoryResult CanRollForItemInLFG(ItemTemplate proto, WorldObject lootedObject)
|
||||
public InventoryResult CanRollForItemInLFG(ItemTemplate proto, Map map)
|
||||
{
|
||||
if (!GetGroup() || !GetGroup().IsLFGGroup())
|
||||
return InventoryResult.Ok; // not in LFG group
|
||||
|
||||
// check if looted object is inside the lfg dungeon
|
||||
Map map = lootedObject.GetMap();
|
||||
if (!Global.LFGMgr.InLfgDungeonMap(GetGroup().GetGUID(), map.GetId(), map.GetDifficultyID()))
|
||||
return InventoryResult.Ok;
|
||||
|
||||
@@ -3946,7 +3945,7 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyItemLootedSpell(Item item, bool apply)
|
||||
public void ApplyItemLootedSpell(Item item, bool apply)
|
||||
{
|
||||
if (item.GetTemplate().HasFlag(ItemFlags.Legacy))
|
||||
return;
|
||||
@@ -4104,6 +4103,18 @@ namespace Game.Entities
|
||||
return null;
|
||||
}
|
||||
|
||||
public LootRoll GetLootRoll(ObjectGuid lootObjectGuid, byte lootListId)
|
||||
{
|
||||
return m_lootRolls.Find(roll => roll.IsLootItem(lootObjectGuid, lootListId));
|
||||
}
|
||||
|
||||
public void AddLootRoll(LootRoll roll) { m_lootRolls.Add(roll); }
|
||||
|
||||
public void RemoveLootRoll(LootRoll roll)
|
||||
{
|
||||
m_lootRolls.Remove(roll);
|
||||
}
|
||||
|
||||
//Inventory
|
||||
public bool IsInventoryPos(ushort pos)
|
||||
{
|
||||
@@ -5881,33 +5892,13 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
public void AutoStoreLoot(uint loot_id, LootStore store, ItemContext context = 0, bool broadcast = false, bool createdByPlayer = false) { AutoStoreLoot(ItemConst.NullBag, ItemConst.NullSlot, loot_id, store, context, broadcast); }
|
||||
|
||||
void AutoStoreLoot(byte bag, byte slot, uint loot_id, LootStore store, ItemContext context = 0, bool broadcast = false, bool createdByPlayer = false)
|
||||
{
|
||||
Loot loot = new(null, ObjectGuid.Empty, LootType.None, LootMethod.FreeForAll);
|
||||
Loot loot = new(null, ObjectGuid.Empty, LootType.None, null);
|
||||
loot.FillLoot(loot_id, store, this, true, false, LootModes.Default, context);
|
||||
|
||||
uint max_slot = loot.GetMaxSlotInLootFor(this);
|
||||
for (uint i = 0; i < max_slot; ++i)
|
||||
{
|
||||
LootItem lootItem = loot.LootItemInSlot(i, this);
|
||||
|
||||
List<ItemPosCount> dest = new();
|
||||
InventoryResult msg = CanStoreNewItem(bag, slot, dest, lootItem.itemid, lootItem.count);
|
||||
if (msg != InventoryResult.Ok && slot != ItemConst.NullSlot)
|
||||
msg = CanStoreNewItem(bag, ItemConst.NullSlot, dest, lootItem.itemid, lootItem.count);
|
||||
if (msg != InventoryResult.Ok && bag != ItemConst.NullBag)
|
||||
msg = CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, lootItem.itemid, lootItem.count);
|
||||
if (msg != InventoryResult.Ok)
|
||||
{
|
||||
SendEquipError(msg, null, null, lootItem.itemid);
|
||||
continue;
|
||||
}
|
||||
|
||||
Item pItem = StoreNewItem(dest, lootItem.itemid, true, lootItem.randomBonusListId, null, lootItem.context, lootItem.BonusListIDs);
|
||||
SendNewItem(pItem, lootItem.count, false, createdByPlayer, broadcast);
|
||||
ApplyItemLootedSpell(pItem, true);
|
||||
}
|
||||
|
||||
loot.AutoStore(this, bag, slot, broadcast, createdByPlayer);
|
||||
Unit.ProcSkillsAndAuras(this, null, new ProcFlagsInit(ProcFlags.Looted), new ProcFlagsInit(ProcFlags.None), ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
|
||||
}
|
||||
|
||||
@@ -6052,7 +6043,7 @@ namespace Game.Entities
|
||||
|
||||
// LootItem is being removed (looted) from the container, delete it from the DB.
|
||||
if (loot.loot_type == LootType.Item)
|
||||
Global.LootItemStorage.RemoveStoredLootItemForContainer(lootWorldObjectGuid.GetCounter(), item.itemid, item.count, item.itemIndex);
|
||||
Global.LootItemStorage.RemoveStoredLootItemForContainer(lootWorldObjectGuid.GetCounter(), item.itemid, item.count, item.LootListId);
|
||||
|
||||
ApplyItemLootedSpell(newitem, true);
|
||||
}
|
||||
@@ -6092,7 +6083,7 @@ namespace Game.Entities
|
||||
// Now we must make bones lootable, and send player loot
|
||||
bones.SetCorpseDynamicFlag(CorpseDynFlags.Lootable);
|
||||
|
||||
bones.loot = new Loot(GetMap(), bones.GetGUID(), LootType.Insignia, looterPlr.GetGroup() != null ? looterPlr.GetGroup().GetLootMethod() : LootMethod.FreeForAll);
|
||||
bones.loot = new Loot(GetMap(), bones.GetGUID(), LootType.Insignia, looterPlr.GetGroup());
|
||||
|
||||
// For AV Achievement
|
||||
Battleground bg = GetBattleground();
|
||||
@@ -6192,7 +6183,7 @@ namespace Game.Entities
|
||||
Group group = GetGroup();
|
||||
bool groupRules = (group != null && go.GetGoInfo().type == GameObjectTypes.Chest && go.GetGoInfo().Chest.usegrouplootrules != 0);
|
||||
|
||||
loot = new Loot(GetMap(), guid, loot_type, groupRules ? group.GetLootMethod() : LootMethod.FreeForAll);
|
||||
loot = new Loot(GetMap(), guid, loot_type, groupRules ? group : null);
|
||||
if (go.GetMap().Is25ManRaid())
|
||||
loot.maxDuplicates = 3;
|
||||
|
||||
@@ -6224,22 +6215,6 @@ namespace Game.Entities
|
||||
else if (loot_type == LootType.FishingJunk)
|
||||
go.GetFishLootJunk(loot, this);
|
||||
|
||||
if (go.GetGoInfo().type == GameObjectTypes.Chest && go.GetGoInfo().Chest.usegrouplootrules != 0)
|
||||
{
|
||||
switch (group.GetLootMethod())
|
||||
{
|
||||
case LootMethod.GroupLoot:
|
||||
// GroupLoot: rolls items over threshold. Items with quality < threshold, round robin
|
||||
group.GroupLoot(loot, go);
|
||||
break;
|
||||
case LootMethod.MasterLoot:
|
||||
group.MasterLoot(loot, go);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
go.SetLootState(LootState.Activated, this);
|
||||
}
|
||||
|
||||
@@ -6253,6 +6228,9 @@ namespace Game.Entities
|
||||
case LootMethod.MasterLoot:
|
||||
permission = group.GetMasterLooterGuid() == GetGUID() ? PermissionTypes.Master : PermissionTypes.Restricted;
|
||||
break;
|
||||
case LootMethod.RoundRobin:
|
||||
permission = PermissionTypes.RoundRobin;
|
||||
break;
|
||||
case LootMethod.FreeForAll:
|
||||
permission = PermissionTypes.All;
|
||||
break;
|
||||
@@ -6284,7 +6262,7 @@ namespace Game.Entities
|
||||
if (!item.m_lootGenerated && !Global.LootItemStorage.LoadStoredLoot(item, this))
|
||||
{
|
||||
item.m_lootGenerated = true;
|
||||
loot = new Loot(GetMap(), guid, loot_type, LootMethod.FreeForAll);
|
||||
loot = new Loot(GetMap(), guid, loot_type, null);
|
||||
item.loot = loot;
|
||||
|
||||
switch (loot_type)
|
||||
@@ -6355,7 +6333,7 @@ namespace Game.Entities
|
||||
{
|
||||
creature.StartPickPocketRefillTimer();
|
||||
|
||||
loot = new Loot(GetMap(), creature.GetGUID(), LootType.Pickpocketing, LootMethod.FreeForAll);
|
||||
loot = new Loot(GetMap(), creature.GetGUID(), LootType.Pickpocketing, null);
|
||||
creature.loot = loot;
|
||||
uint lootid = creature.GetCreatureTemplate().PickPocketId;
|
||||
if (lootid != 0)
|
||||
@@ -6392,27 +6370,6 @@ namespace Game.Entities
|
||||
return;
|
||||
}
|
||||
|
||||
if (loot.loot_type == LootType.None)
|
||||
{
|
||||
// for creature, loot is filled when creature is killed.
|
||||
Group group = creature.GetLootRecipientGroup();
|
||||
if (group)
|
||||
{
|
||||
switch (loot.GetLootMethod())
|
||||
{
|
||||
case LootMethod.GroupLoot:
|
||||
// GroupLoot: rolls items over threshold. Items with quality < threshold, round robin
|
||||
group.GroupLoot(loot, creature);
|
||||
break;
|
||||
case LootMethod.MasterLoot:
|
||||
group.MasterLoot(loot, creature);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (loot.loot_type == LootType.Skinning)
|
||||
{
|
||||
loot_type = LootType.Skinning;
|
||||
@@ -6443,6 +6400,9 @@ namespace Game.Entities
|
||||
case LootMethod.FreeForAll:
|
||||
permission = PermissionTypes.All;
|
||||
break;
|
||||
case LootMethod.RoundRobin:
|
||||
permission = PermissionTypes.RoundRobin;
|
||||
break;
|
||||
default:
|
||||
permission = PermissionTypes.Group;
|
||||
break;
|
||||
@@ -6475,7 +6435,7 @@ namespace Game.Entities
|
||||
SendPacket(packet);
|
||||
|
||||
// add 'this' player as one of the players that are looting 'loot'
|
||||
loot.AddLooter(GetGUID());
|
||||
loot.OnLootOpened(GetMap(), GetGUID());
|
||||
m_AELootView[loot.GetGUID()] = loot;
|
||||
|
||||
if (loot_type == LootType.Corpse && !guid.IsItem())
|
||||
|
||||
@@ -757,6 +757,7 @@ namespace Game.Entities
|
||||
UnsummonPetTemporaryIfAny();
|
||||
ClearComboPoints();
|
||||
GetSession().DoLootReleaseAll();
|
||||
m_lootRolls.Clear();
|
||||
Global.OutdoorPvPMgr.HandlePlayerLeaveZone(this, m_zoneUpdateId);
|
||||
Global.BattleFieldMgr.HandlePlayerLeaveZone(this, m_zoneUpdateId);
|
||||
}
|
||||
@@ -3140,7 +3141,15 @@ namespace Game.Entities
|
||||
case LootMethod.MasterLoot:
|
||||
case LootMethod.FreeForAll:
|
||||
return true;
|
||||
case LootMethod.RoundRobin:
|
||||
// may only loot if the player is the loot roundrobin player
|
||||
// or if there are free/quest/conditional item for the player
|
||||
if (loot.roundRobinPlayer.IsEmpty() || loot.roundRobinPlayer == GetGUID())
|
||||
return true;
|
||||
|
||||
return loot.HasItemFor(this);
|
||||
case LootMethod.GroupLoot:
|
||||
case LootMethod.NeedBeforeGreed:
|
||||
// may only loot if the player is the loot roundrobin player
|
||||
// or item over threshold (so roll(s) can be launched)
|
||||
// or if there are free/quest/conditional item for the player
|
||||
|
||||
@@ -752,7 +752,6 @@ namespace Game.Entities
|
||||
|
||||
Player looter = player;
|
||||
var group = player.GetGroup();
|
||||
bool hasLooterGuid = false;
|
||||
if (group)
|
||||
{
|
||||
group.BroadcastPacket(partyKillLog, group.GetMemberGroup(player.GetGUID()) != 0);
|
||||
@@ -764,10 +763,7 @@ namespace Game.Entities
|
||||
{
|
||||
looter = Global.ObjAccessor.FindPlayer(group.GetLooterGuid());
|
||||
if (looter)
|
||||
{
|
||||
hasLooterGuid = true;
|
||||
creature.SetLootRecipient(looter); // update creature loot recipient to the allowed looter.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -777,7 +773,7 @@ namespace Game.Entities
|
||||
// Generate loot before updating looter
|
||||
if (creature)
|
||||
{
|
||||
creature.loot = new Loot(creature.GetMap(), creature.GetGUID(), LootType.Corpse, group != null ? group.GetLootMethod() : LootMethod.FreeForAll);
|
||||
creature.loot = new Loot(creature.GetMap(), creature.GetGUID(), LootType.Corpse, group);
|
||||
Loot loot = creature.loot;
|
||||
if (creature.GetMap().Is25ManRaid())
|
||||
loot.maxDuplicates = 3;
|
||||
@@ -789,24 +785,11 @@ namespace Game.Entities
|
||||
if (creature.GetLootMode() > 0)
|
||||
loot.GenerateMoneyLoot(creature.GetCreatureTemplate().MinGold, creature.GetCreatureTemplate().MaxGold);
|
||||
|
||||
if (group)
|
||||
{
|
||||
if (hasLooterGuid)
|
||||
group.SendLooter(creature, looter);
|
||||
else
|
||||
group.SendLooter(creature, null);
|
||||
loot.NotifyLootList(creature.GetMap());
|
||||
|
||||
// Update round robin looter only if the creature had loot
|
||||
if (!loot.Empty())
|
||||
group.UpdateLooterGuid(creature);
|
||||
}
|
||||
else
|
||||
{
|
||||
LootList lootList = new();
|
||||
lootList.Owner = creature.GetGUID();
|
||||
lootList.LootObj = creature.loot.GetGUID();
|
||||
player.SendMessageToSet(lootList, true);
|
||||
}
|
||||
// Update round robin looter only if the creature had loot
|
||||
if (group != null && !loot.Empty())
|
||||
group.UpdateLooterGuid(creature);
|
||||
}
|
||||
|
||||
player.RewardPlayerAndGroupAtKill(victim, false);
|
||||
|
||||
Reference in New Issue
Block a user