Core/Misc: Fix various crashes, also related to multithreading

Port From (https://github.com/TrinityCore/TrinityCore/commit/ad008c43b75080ec59aa973f1e2e4424332c34a4)
This commit is contained in:
hondacrx
2019-08-16 22:03:02 -04:00
parent 653a9bb035
commit d3bce6a75c
19 changed files with 174 additions and 117 deletions
+4 -4
View File
@@ -271,14 +271,14 @@ namespace Game.AI
{ {
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.next()) for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.next())
{ {
Player Target = refe.GetSource(); Player target = refe.GetSource();
if (!Target || !group.SameSubGroup(owner.ToPlayer(), Target)) if (!target || !target.IsInMap(owner) || !group.SameSubGroup(owner.ToPlayer(), target))
continue; continue;
if (Target.GetGUID() == owner.GetGUID()) if (target.GetGUID() == owner.GetGUID())
continue; continue;
m_AllySet.Add(Target.GetGUID()); m_AllySet.Add(target.GetGUID());
} }
} }
else //remove group else //remove group
@@ -115,7 +115,8 @@ namespace Game.AI
{ {
Player member = groupRef.GetSource(); Player member = groupRef.GetSource();
if (member) if (member)
member.FailQuest(m_pQuestForEscort.Id); if (member.IsInMap(player))
member.FailQuest(m_pQuestForEscort.Id);
} }
} }
else else
@@ -153,7 +153,8 @@ namespace Game.AI
{ {
Player member = groupRef.GetSource(); Player member = groupRef.GetSource();
if (member) if (member)
member.FailQuest(m_pQuestForFollow.Id); if (member.IsInMap(player))
member.FailQuest(m_pQuestForFollow.Id);
} }
} }
else else
@@ -343,8 +344,7 @@ namespace Game.AI
for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.next()) for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.next())
{ {
Player member = groupRef.GetSource(); Player member = groupRef.GetSource();
if (member && me.IsWithinDistInMap(member, 100.0f) && member.IsAlive())
if (member && member.IsAlive() && me.IsWithinDistInMap(member, 100.0f))
{ {
Log.outDebug(LogFilter.Scripts, "FollowerAI GetLeader changed and returned new leader."); Log.outDebug(LogFilter.Scripts, "FollowerAI GetLeader changed and returned new leader.");
m_uiLeaderGUID = member.GetGUID(); m_uiLeaderGUID = member.GetGUID();
+3 -2
View File
@@ -249,6 +249,8 @@ namespace Game.AI
for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.next()) for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.next())
{ {
Player groupGuy = groupRef.GetSource(); Player groupGuy = groupRef.GetSource();
if (!groupGuy.IsInMap(player))
continue;
if (!fail && groupGuy.IsAtGroupRewardDistance(me) && !groupGuy.GetCorpse()) if (!fail && groupGuy.IsAtGroupRewardDistance(me) && !groupGuy.GetCorpse())
groupGuy.AreaExploredOrEventHappens(mEscortQuestID); groupGuy.AreaExploredOrEventHappens(mEscortQuestID);
@@ -402,8 +404,7 @@ namespace Game.AI
for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.next()) for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.next())
{ {
Player groupGuy = groupRef.GetSource(); Player groupGuy = groupRef.GetSource();
if (groupGuy.IsInMap(player) && me.GetDistance(groupGuy) <= SMART_ESCORT_MAX_PLAYER_DIST)
if (me.GetDistance(groupGuy) <= SMART_ESCORT_MAX_PLAYER_DIST)
return true; return true;
} }
} }
+4 -2
View File
@@ -2614,7 +2614,8 @@ namespace Game.AI
{ {
Player member = groupRef.GetSource(); Player member = groupRef.GetSource();
if (member) if (member)
l.Add(member); if (member.IsInMap(player))
l.Add(member);
} }
} }
// We still add the player to the list if there is no group. If we do // We still add the player to the list if there is no group. If we do
@@ -2838,7 +2839,8 @@ namespace Game.AI
{ {
Player recipient = refe.GetSource(); Player recipient = refe.GetSource();
if (recipient) if (recipient)
l.Add(recipient); if (recipient.IsInMap(me))
l.Add(recipient);
} }
} }
else else
+4
View File
@@ -239,6 +239,10 @@ namespace Game.Combat
{ {
return threatContainer.empty(); return threatContainer.empty();
} }
public bool areThreatListsEmpty()
{
return threatContainer.empty() && threatOfflineContainer.empty();
}
public HostileReference getCurrentVictim() public HostileReference getCurrentVictim()
{ {
+2 -1
View File
@@ -400,7 +400,8 @@ namespace Game.Entities
{ {
Group group = Global.GroupMgr.GetGroupByGUID(lootingGroupLowGUID); Group group = Global.GroupMgr.GetGroupByGUID(lootingGroupLowGUID);
if (group) if (group)
group.EndRoll(loot); group.EndRoll(loot, GetMap());
m_groupLootTimer = 0; m_groupLootTimer = 0;
lootingGroupLowGUID.Clear(); lootingGroupLowGUID.Clear();
} }
@@ -668,7 +668,7 @@ namespace Game.Entities
{ {
Group group = Global.GroupMgr.GetGroupByGUID(lootingGroupLowGUID); Group group = Global.GroupMgr.GetGroupByGUID(lootingGroupLowGUID);
if (group) if (group)
group.EndRoll(loot); group.EndRoll(loot, GetMap());
m_groupLootTimer = 0; m_groupLootTimer = 0;
lootingGroupLowGUID.Clear(); lootingGroupLowGUID.Clear();
@@ -1396,7 +1396,7 @@ namespace Game.Entities
if (!slot.Value.IsEmpty()) if (!slot.Value.IsEmpty())
{ {
Player ChairUser = Global.ObjAccessor.FindPlayer(slot.Value); Player ChairUser = Global.ObjAccessor.GetPlayer(this, slot.Value);
if (ChairUser != null) if (ChairUser != null)
if (ChairUser.IsSitState() && ChairUser.GetStandState() != UnitStandStateType.Sit && ChairUser.GetExactDist2d(x_i, y_i) < 0.1f) if (ChairUser.IsSitState() && ChairUser.GetStandState() != UnitStandStateType.Sit && ChairUser.GetExactDist2d(x_i, y_i) < 0.1f)
continue; // This seat is already occupied by ChairUser. NOTE: Not sure if the ChairUser.getStandState() != UNIT_STAND_STATE_SIT check is required. continue; // This seat is already occupied by ChairUser. NOTE: Not sure if the ChairUser.getStandState() != UNIT_STAND_STATE_SIT check is required.
+3 -2
View File
@@ -104,7 +104,7 @@ namespace Game.Entities
Player member = refe.GetSource(); Player member = refe.GetSource();
if (member) if (member)
{ {
if (member.IsAlive() && member.IsAtGroupRewardDistance(_victim)) if (_killer == member || (member.IsAtGroupRewardDistance(_victim) && member.IsAlive()))
{ {
uint lvl = member.getLevel(); uint lvl = member.getLevel();
// 2.1. _count - number of alive group members within reward distance; // 2.1. _count - number of alive group members within reward distance;
@@ -254,7 +254,8 @@ namespace Game.Entities
Player member = refe.GetSource(); Player member = refe.GetSource();
if (member) if (member)
{ {
if (member.IsAtGroupRewardDistance(_victim)) // Killer may not be at reward distance, check directly
if (_killer == member || member.IsAtGroupRewardDistance(_victim))
{ {
_RewardPlayer(member, isDungeon); _RewardPlayer(member, isDungeon);
member.UpdateCriteria(CriteriaTypes.SpecialPvpKill, 1, 0, 0, _victim); member.UpdateCriteria(CriteriaTypes.SpecialPvpKill, 1, 0, 0, _victim);
+4
View File
@@ -1525,6 +1525,10 @@ namespace Game.Entities
stmt.AddValue(2, GetGUID().GetCounter()); stmt.AddValue(2, GetGUID().GetCounter());
trans.Append(stmt); trans.Append(stmt);
RemoveTradeableItem(item);
RemoveEnchantmentDurationsReferences(item);
RemoveItemDurations(item);
// also THIS item should be somewhere else, cheat attempt // also THIS item should be somewhere else, cheat attempt
item.FSetState(ItemUpdateState.Removed); // we are IN updateQueue right now, can't use SetState which modifies the queue item.FSetState(ItemUpdateState.Removed); // we are IN updateQueue right now, can't use SetState which modifies the queue
DeleteRefundReference(item.GetGUID()); DeleteRefundReference(item.GetGUID());
+3 -5
View File
@@ -76,7 +76,7 @@ namespace Game.Entities
// @todo Should also be sent when anyone has recently left combat, with an aprox ~5 seconds timer. // @todo Should also be sent when anyone has recently left combat, with an aprox ~5 seconds timer.
for (GroupReference refe = grp.GetFirstMember(); refe != null; refe = refe.next()) for (GroupReference refe = grp.GetFirstMember(); refe != null; refe = refe.next())
if (refe.GetSource() && refe.GetSource().IsInCombat()) if (refe.GetSource() && refe.GetSource().IsInMap(this) && refe.GetSource().IsInCombat())
return PartyResult.PartyLfgBootInCombat; return PartyResult.PartyLfgBootInCombat;
/* Missing support for these types /* Missing support for these types
@@ -192,15 +192,13 @@ namespace Game.Entities
public bool IsAtGroupRewardDistance(WorldObject pRewardSource) public bool IsAtGroupRewardDistance(WorldObject pRewardSource)
{ {
if (!pRewardSource) if (!pRewardSource || !IsInMap(pRewardSource))
return false; return false;
WorldObject player = GetCorpse(); WorldObject player = GetCorpse();
if (!player || IsAlive()) if (!player || IsAlive())
player = this; player = this;
if (player.GetMapId() != pRewardSource.GetMapId() || player.GetInstanceId() != pRewardSource.GetInstanceId())
return false;
if (player.GetMap().IsDungeon()) if (player.GetMap().IsDungeon())
return true; return true;
+16 -1
View File
@@ -967,6 +967,16 @@ namespace Game.Entities
} }
} }
} }
void RemoveEnchantmentDurationsReferences(Item item)
{
foreach (var enchantDuration in m_enchantDuration)
{
if (enchantDuration.item == item)
m_enchantDuration.Remove(enchantDuration);
}
}
public void RemoveArenaEnchantments(EnchantmentSlot slot) public void RemoveArenaEnchantments(EnchantmentSlot slot)
{ {
// remove enchantments from equipped items first to clean up the m_enchantDuration list // remove enchantments from equipped items first to clean up the m_enchantDuration list
@@ -1043,7 +1053,12 @@ namespace Game.Entities
} }
// from spell cases (m_lastPotionId set in Spell.SendSpellCooldown) // from spell cases (m_lastPotionId set in Spell.SendSpellCooldown)
else else
GetSpellHistory().SendCooldownEvent(spell.m_spellInfo, m_lastPotionId, spell); {
if (spell.IsIgnoringCooldowns())
return;
else
GetSpellHistory().SendCooldownEvent(spell.m_spellInfo, m_lastPotionId, spell);
}
m_lastPotionId = 0; m_lastPotionId = 0;
} }
+3 -4
View File
@@ -862,6 +862,7 @@ namespace Game.Entities
StopCastingCharm(); StopCastingCharm();
StopCastingBindSight(); StopCastingBindSight();
UnsummonPetTemporaryIfAny(); UnsummonPetTemporaryIfAny();
ClearComboPoints();
Global.OutdoorPvPMgr.HandlePlayerLeaveZone(this, m_zoneUpdateId); Global.OutdoorPvPMgr.HandlePlayerLeaveZone(this, m_zoneUpdateId);
Global.BattleFieldMgr.HandlePlayerLeaveZone(this, m_zoneUpdateId); Global.BattleFieldMgr.HandlePlayerLeaveZone(this, m_zoneUpdateId);
} }
@@ -7031,15 +7032,13 @@ namespace Game.Entities
bool IsAtRecruitAFriendDistance(WorldObject pOther) bool IsAtRecruitAFriendDistance(WorldObject pOther)
{ {
if (!pOther) if (!pOther || !IsInMap(pOther))
return false; return false;
WorldObject player = GetCorpse(); WorldObject player = GetCorpse();
if (!player || IsAlive()) if (!player || IsAlive())
player = this; player = this;
if (player.GetMapId() != pOther.GetMapId() || player.GetInstanceId() != pOther.GetInstanceId())
return false;
return pOther.GetDistance(player) <= WorldConfig.GetFloatValue(WorldCfg.MaxRecruitAFriendDistance); return pOther.GetDistance(player) <= WorldConfig.GetFloatValue(WorldCfg.MaxRecruitAFriendDistance);
} }
+1 -1
View File
@@ -135,7 +135,7 @@ namespace Game.Entities
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.next()) for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.next())
{ {
Player target = refe.GetSource(); Player target = refe.GetSource();
if (target && group.SameSubGroup(owner, target)) if (target && target.IsInMap(owner) && group.SameSubGroup(owner, target))
target.RemoveAurasDueToSpell(GetSpell(), GetGUID()); target.RemoveAurasDueToSpell(GetSpell(), GetGUID());
} }
} }
+6 -6
View File
@@ -1741,17 +1741,17 @@ namespace Game.Entities
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.next()) for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.next())
{ {
Player Target = refe.GetSource(); Player target = refe.GetSource();
if (Target) if (target)
{ {
// IsHostileTo check duel and controlled by enemy // IsHostileTo check duel and controlled by enemy
if (Target != this && Target.IsAlive() && IsWithinDistInMap(Target, radius) && !IsHostileTo(Target)) if (target != this && IsWithinDistInMap(target, radius) && target.IsAlive() && !IsHostileTo(target))
nearMembers.Add(Target); nearMembers.Add(target);
// Push player's pet to vector // Push player's pet to vector
Unit pet = Target.GetGuardianPet(); Unit pet = target.GetGuardianPet();
if (pet) if (pet)
if (pet != this && pet.IsAlive() && IsWithinDistInMap(pet, radius) && !IsHostileTo(pet)) if (pet != this && IsWithinDistInMap(pet, radius) && pet.IsAlive() && !IsHostileTo(pet))
nearMembers.Add(pet); nearMembers.Add(pet);
} }
} }
+1 -1
View File
@@ -485,7 +485,7 @@ namespace Game.Entities
m_Events.KillAllEvents(false); // non-delatable (currently casted spells) will not deleted now but it will deleted at call in Map.RemoveAllObjectsInRemoveList m_Events.KillAllEvents(false); // non-delatable (currently casted spells) will not deleted now but it will deleted at call in Map.RemoveAllObjectsInRemoveList
CombatStop(); CombatStop();
DeleteThreatList(); DeleteThreatList();
getHostileRefManager().setOnlineOfflineState(false); getHostileRefManager().deleteReferences();
GetMotionMaster().Clear(false); // remove different non-standard movement generators. GetMotionMaster().Clear(false); // remove different non-standard movement generators.
} }
public override void CleanupsBeforeDelete(bool finalCleanup = true) public override void CleanupsBeforeDelete(bool finalCleanup = true)
+110 -80
View File
@@ -560,7 +560,7 @@ namespace Game.Groups
roll.playerVote.Remove(guid); roll.playerVote.Remove(guid);
if (roll.totalPass + roll.totalNeed + roll.totalGreed >= roll.totalPlayersRolling) if (roll.totalPass + roll.totalNeed + roll.totalGreed >= roll.totalPlayersRolling)
CountTheRoll(roll); CountTheRoll(roll, null);
} }
// Update subgroups // Update subgroups
@@ -1110,21 +1110,21 @@ namespace Game.Groups
} }
if (roll.totalPass + roll.totalNeed + roll.totalGreed >= roll.totalPlayersRolling) if (roll.totalPass + roll.totalNeed + roll.totalGreed >= roll.totalPlayersRolling)
CountTheRoll(roll); CountTheRoll(roll, null);
} }
public void EndRoll(Loot pLoot) public void EndRoll(Loot pLoot, Map allowedMap)
{ {
foreach (var roll in RollId) foreach (var roll in RollId)
{ {
if (roll.getLoot() == pLoot) if (roll.getLoot() == pLoot)
{ {
CountTheRoll(roll); //i don't have to edit player votes, who didn't vote ... he will pass CountTheRoll(roll, allowedMap); //i don't have to edit player votes, who didn't vote ... he will pass
} }
} }
} }
void CountTheRoll(Roll roll) void CountTheRoll(Roll roll, Map allowedMap)
{ {
if (!roll.isValid()) // is loot already deleted ? if (!roll.isValid()) // is loot already deleted ?
{ {
@@ -1138,13 +1138,21 @@ namespace Game.Groups
if (!roll.playerVote.Empty()) if (!roll.playerVote.Empty())
{ {
byte maxresul = 0; byte maxresul = 0;
ObjectGuid maxguid = roll.playerVote.First().Key; ObjectGuid maxguid = ObjectGuid.Empty;
Player player = null;
foreach (var pair in roll.playerVote) foreach (var pair in roll.playerVote)
{ {
if (pair.Value != RollType.Need) if (pair.Value != RollType.Need)
continue; continue;
player = Global.ObjAccessor.FindPlayer(pair.Key);
if (!player || (allowedMap != null && player.GetMap() != allowedMap))
{
--roll.totalNeed;
continue;
}
byte randomN = (byte)RandomHelper.IRand(1, 100); byte randomN = (byte)RandomHelper.IRand(1, 100);
SendLootRoll(pair.Key, randomN, RollType.Need, roll); SendLootRoll(pair.Key, randomN, RollType.Need, roll);
if (maxresul < randomN) if (maxresul < randomN)
@@ -1153,66 +1161,18 @@ namespace Game.Groups
maxresul = randomN; maxresul = randomN;
} }
} }
SendLootRollWon(maxguid, maxresul, RollType.Need, roll);
Player player = Global.ObjAccessor.FindPlayer(maxguid);
if (player && player.GetSession() != null) if (!maxguid.IsEmpty())
{ {
player.UpdateCriteria(CriteriaTypes.RollNeedOnLoot, roll.itemid, maxresul); SendLootRollWon(maxguid, maxresul, RollType.Need, roll);
player = Global.ObjAccessor.FindConnectedPlayer(maxguid);
List<ItemPosCount> dest = new List<ItemPosCount>(); if (player && player.GetSession())
LootItem item = (roll.itemSlot >= roll.getLoot().items.Count ? roll.getLoot().quest_items[roll.itemSlot - roll.getLoot().items.Count] : roll.getLoot().items[roll.itemSlot]);
InventoryResult msg = player.CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, roll.itemid, item.count);
if (msg == InventoryResult.Ok)
{ {
item.is_looted = true; player.UpdateCriteria(CriteriaTypes.RollNeedOnLoot, roll.itemid, maxresul);
roll.getLoot().NotifyItemRemoved(roll.itemSlot);
roll.getLoot().unlootedCount--;
player.StoreNewItem(dest, roll.itemid, true, item.randomBonusListId, item.GetAllowedLooters(), item.context, item.BonusListIDs);
}
else
{
item.is_blocked = false;
item.rollWinnerGUID = player.GetGUID();
player.SendEquipError(msg, null, null, roll.itemid);
}
}
}
}
else if (roll.totalGreed > 0)
{
if (!roll.playerVote.Empty())
{
byte maxresul = 0;
ObjectGuid maxguid = roll.playerVote.First().Key;
RollType rollVote = RollType.NotValid;
foreach (var pair in roll.playerVote)
{
if (pair.Value != RollType.Greed && pair.Value != RollType.Disenchant)
continue;
byte randomN = (byte)RandomHelper.IRand(1, 100);
SendLootRoll(pair.Key, randomN, pair.Value, roll);
if (maxresul < randomN)
{
maxguid = pair.Key;
maxresul = randomN;
rollVote = pair.Value;
}
}
SendLootRollWon(maxguid, maxresul, rollVote, roll);
Player player = Global.ObjAccessor.FindPlayer(maxguid);
if (player && player.GetSession() != null)
{
player.UpdateCriteria(CriteriaTypes.RollGreedOnLoot, roll.itemid, maxresul);
LootItem item = roll.itemSlot >= roll.getLoot().items.Count ? roll.getLoot().quest_items[roll.itemSlot - roll.getLoot().items.Count] : roll.getLoot().items[roll.itemSlot];
if (rollVote == RollType.Greed)
{
List<ItemPosCount> dest = new List<ItemPosCount>(); List<ItemPosCount> dest = new List<ItemPosCount>();
LootItem item = (roll.itemSlot >= roll.getLoot().items.Count ? roll.getLoot().quest_items[roll.itemSlot - roll.getLoot().items.Count] : roll.getLoot().items[roll.itemSlot]);
InventoryResult msg = player.CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, roll.itemid, item.count); InventoryResult msg = player.CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, roll.itemid, item.count);
if (msg == InventoryResult.Ok) if (msg == InventoryResult.Ok)
{ {
@@ -1228,37 +1188,107 @@ namespace Game.Groups
player.SendEquipError(msg, null, null, roll.itemid); player.SendEquipError(msg, null, null, roll.itemid);
} }
} }
else if (rollVote == RollType.Disenchant) }
else
roll.totalNeed = 0;
}
}
if (roll.totalNeed == 0 && roll.totalGreed > 0) // if (roll->totalNeed == 0 && ...), not else if, because numbers can be modified above if player is on a different map
{
if (!roll.playerVote.Empty())
{
byte maxresul = 0;
ObjectGuid maxguid = ObjectGuid.Empty;
Player player = null;
RollType rollVote = RollType.NotValid;
foreach (var pair in roll.playerVote)
{
if (pair.Value != RollType.Greed && pair.Value != RollType.Disenchant)
continue;
player = Global.ObjAccessor.FindPlayer(pair.Key);
if (!player || (allowedMap != null && player.GetMap() != allowedMap))
{ {
item.is_looted = true; --roll.totalGreed;
roll.getLoot().NotifyItemRemoved(roll.itemSlot); continue;
roll.getLoot().unlootedCount--; }
player.UpdateCriteria(CriteriaTypes.CastSpell, 13262); // Disenchant
ItemDisenchantLootRecord disenchant = roll.GetItemDisenchantLoot(player); byte randomN = (byte)RandomHelper.IRand(1, 100);
SendLootRoll(pair.Key, randomN, pair.Value, roll);
if (maxresul < randomN)
{
maxguid = pair.Key;
maxresul = randomN;
rollVote = pair.Value;
}
}
List<ItemPosCount> dest = new List<ItemPosCount>(); if (!maxguid.IsEmpty())
InventoryResult msg = player.CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, roll.itemid, item.count); {
if (msg == InventoryResult.Ok) SendLootRollWon(maxguid, maxresul, rollVote, roll);
player.AutoStoreLoot(disenchant.Id, LootStorage.Disenchant, true); player = Global.ObjAccessor.FindConnectedPlayer(maxguid);
else // If the player's inventory is full, send the disenchant result in a mail.
if (player && player.GetSession() != null)
{
player.UpdateCriteria(CriteriaTypes.RollGreedOnLoot, roll.itemid, maxresul);
LootItem item = roll.itemSlot >= roll.getLoot().items.Count ? roll.getLoot().quest_items[roll.itemSlot - roll.getLoot().items.Count] : roll.getLoot().items[roll.itemSlot];
if (rollVote == RollType.Greed)
{ {
Loot loot = new Loot(); List<ItemPosCount> dest = new List<ItemPosCount>();
loot.FillLoot(disenchant.Id, LootStorage.Disenchant, player, true); InventoryResult msg = player.CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, roll.itemid, item.count);
if (msg == InventoryResult.Ok)
uint max_slot = loot.GetMaxSlotInLootFor(player);
for (uint i = 0; i < max_slot; ++i)
{ {
LootItem lootItem = loot.LootItemInSlot(i, player); item.is_looted = true;
player.SendEquipError(msg, null, null, lootItem.itemid); roll.getLoot().NotifyItemRemoved(roll.itemSlot);
player.SendItemRetrievalMail(lootItem.itemid, lootItem.count); roll.getLoot().unlootedCount--;
player.StoreNewItem(dest, roll.itemid, true, item.randomBonusListId, item.GetAllowedLooters(), item.context, item.BonusListIDs);
}
else
{
item.is_blocked = false;
item.rollWinnerGUID = player.GetGUID();
player.SendEquipError(msg, null, null, roll.itemid);
}
}
else if (rollVote == RollType.Disenchant)
{
item.is_looted = true;
roll.getLoot().NotifyItemRemoved(roll.itemSlot);
roll.getLoot().unlootedCount--;
player.UpdateCriteria(CriteriaTypes.CastSpell, 13262); // Disenchant
ItemDisenchantLootRecord disenchant = roll.GetItemDisenchantLoot(player);
List<ItemPosCount> dest = new List<ItemPosCount>();
InventoryResult msg = player.CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, roll.itemid, item.count);
if (msg == InventoryResult.Ok)
player.AutoStoreLoot(disenchant.Id, LootStorage.Disenchant, true);
else // If the player's inventory is full, send the disenchant result in a mail.
{
Loot loot = new Loot();
loot.FillLoot(disenchant.Id, LootStorage.Disenchant, player, true);
uint max_slot = loot.GetMaxSlotInLootFor(player);
for (uint i = 0; i < max_slot; ++i)
{
LootItem lootItem = loot.LootItemInSlot(i, player);
player.SendEquipError(msg, null, null, lootItem.itemid);
player.SendItemRetrievalMail(lootItem.itemid, lootItem.count);
}
} }
} }
} }
} }
else
roll.totalGreed = 0;
} }
} }
else
if (roll.totalNeed == 0 && roll.totalGreed == 0) // if, not else, because numbers can be modified above if player is on a different map
{ {
SendLootAllPassed(roll); SendLootAllPassed(roll);
+2 -1
View File
@@ -228,7 +228,8 @@ namespace Game.Loots
{ {
Player player = refe.GetSource(); Player player = refe.GetSource();
if (player) // should actually be looted object instead of lootOwner but looter has to be really close so doesnt really matter if (player) // should actually be looted object instead of lootOwner but looter has to be really close so doesnt really matter
FillNotNormalLootFor(player, player.IsAtGroupRewardDistance(lootOwner)); if (player.IsInMap(lootOwner))
FillNotNormalLootFor(player, player.IsAtGroupRewardDistance(lootOwner));
} }
for (byte i = 0; i < items.Count; ++i) for (byte i = 0; i < items.Count; ++i)
+1 -1
View File
@@ -167,7 +167,7 @@ namespace Game.Maps
creature.RemoveAllDynObjects(); creature.RemoveAllDynObjects();
creature.RemoveAllAreaTriggers(); creature.RemoveAllAreaTriggers();
if (creature.IsInCombat()) if (creature.IsInCombat() || !creature.GetThreatManager().areThreatListsEmpty())
{ {
creature.CombatStop(); creature.CombatStop();
creature.DeleteThreatList(); creature.DeleteThreatList();