diff --git a/Source/Game/AI/CoreAI/PetAI.cs b/Source/Game/AI/CoreAI/PetAI.cs index c12ae9bff..42f88cf9f 100644 --- a/Source/Game/AI/CoreAI/PetAI.cs +++ b/Source/Game/AI/CoreAI/PetAI.cs @@ -271,14 +271,14 @@ namespace Game.AI { for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.next()) { - Player Target = refe.GetSource(); - if (!Target || !group.SameSubGroup(owner.ToPlayer(), Target)) + Player target = refe.GetSource(); + if (!target || !target.IsInMap(owner) || !group.SameSubGroup(owner.ToPlayer(), target)) continue; - if (Target.GetGUID() == owner.GetGUID()) + if (target.GetGUID() == owner.GetGUID()) continue; - m_AllySet.Add(Target.GetGUID()); + m_AllySet.Add(target.GetGUID()); } } else //remove group diff --git a/Source/Game/AI/ScriptedAI/ScriptedEscortAI.cs b/Source/Game/AI/ScriptedAI/ScriptedEscortAI.cs index 868c625b2..745375e8e 100644 --- a/Source/Game/AI/ScriptedAI/ScriptedEscortAI.cs +++ b/Source/Game/AI/ScriptedAI/ScriptedEscortAI.cs @@ -115,7 +115,8 @@ namespace Game.AI { Player member = groupRef.GetSource(); if (member) - member.FailQuest(m_pQuestForEscort.Id); + if (member.IsInMap(player)) + member.FailQuest(m_pQuestForEscort.Id); } } else diff --git a/Source/Game/AI/ScriptedAI/ScriptedFollowerAI.cs b/Source/Game/AI/ScriptedAI/ScriptedFollowerAI.cs index 6b4c9f6db..42a051e4b 100644 --- a/Source/Game/AI/ScriptedAI/ScriptedFollowerAI.cs +++ b/Source/Game/AI/ScriptedAI/ScriptedFollowerAI.cs @@ -153,7 +153,8 @@ namespace Game.AI { Player member = groupRef.GetSource(); if (member) - member.FailQuest(m_pQuestForFollow.Id); + if (member.IsInMap(player)) + member.FailQuest(m_pQuestForFollow.Id); } } else @@ -343,8 +344,7 @@ namespace Game.AI for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.next()) { Player member = groupRef.GetSource(); - - if (member && member.IsAlive() && me.IsWithinDistInMap(member, 100.0f)) + if (member && me.IsWithinDistInMap(member, 100.0f) && member.IsAlive()) { Log.outDebug(LogFilter.Scripts, "FollowerAI GetLeader changed and returned new leader."); m_uiLeaderGUID = member.GetGUID(); diff --git a/Source/Game/AI/SmartScripts/SmartAI.cs b/Source/Game/AI/SmartScripts/SmartAI.cs index ef61503da..51b491f24 100644 --- a/Source/Game/AI/SmartScripts/SmartAI.cs +++ b/Source/Game/AI/SmartScripts/SmartAI.cs @@ -249,6 +249,8 @@ namespace Game.AI for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.next()) { Player groupGuy = groupRef.GetSource(); + if (!groupGuy.IsInMap(player)) + continue; if (!fail && groupGuy.IsAtGroupRewardDistance(me) && !groupGuy.GetCorpse()) groupGuy.AreaExploredOrEventHappens(mEscortQuestID); @@ -402,8 +404,7 @@ namespace Game.AI for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.next()) { Player groupGuy = groupRef.GetSource(); - - if (me.GetDistance(groupGuy) <= SMART_ESCORT_MAX_PLAYER_DIST) + if (groupGuy.IsInMap(player) && me.GetDistance(groupGuy) <= SMART_ESCORT_MAX_PLAYER_DIST) return true; } } diff --git a/Source/Game/AI/SmartScripts/SmartScript.cs b/Source/Game/AI/SmartScripts/SmartScript.cs index e0ec1af9d..bf9b5dc43 100644 --- a/Source/Game/AI/SmartScripts/SmartScript.cs +++ b/Source/Game/AI/SmartScripts/SmartScript.cs @@ -2614,7 +2614,8 @@ namespace Game.AI { Player member = groupRef.GetSource(); 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 @@ -2838,7 +2839,8 @@ namespace Game.AI { Player recipient = refe.GetSource(); if (recipient) - l.Add(recipient); + if (recipient.IsInMap(me)) + l.Add(recipient); } } else diff --git a/Source/Game/Combat/ThreatManager.cs b/Source/Game/Combat/ThreatManager.cs index 594b3f4ac..307263ac3 100644 --- a/Source/Game/Combat/ThreatManager.cs +++ b/Source/Game/Combat/ThreatManager.cs @@ -239,6 +239,10 @@ namespace Game.Combat { return threatContainer.empty(); } + public bool areThreatListsEmpty() + { + return threatContainer.empty() && threatOfflineContainer.empty(); + } public HostileReference getCurrentVictim() { diff --git a/Source/Game/Entities/Creature/Creature.cs b/Source/Game/Entities/Creature/Creature.cs index 95cdef750..e9709c096 100644 --- a/Source/Game/Entities/Creature/Creature.cs +++ b/Source/Game/Entities/Creature/Creature.cs @@ -400,7 +400,8 @@ namespace Game.Entities { Group group = Global.GroupMgr.GetGroupByGUID(lootingGroupLowGUID); if (group) - group.EndRoll(loot); + group.EndRoll(loot, GetMap()); + m_groupLootTimer = 0; lootingGroupLowGUID.Clear(); } diff --git a/Source/Game/Entities/GameObject/GameObject.cs b/Source/Game/Entities/GameObject/GameObject.cs index 59cb6dfcb..b68cc5b7c 100644 --- a/Source/Game/Entities/GameObject/GameObject.cs +++ b/Source/Game/Entities/GameObject/GameObject.cs @@ -668,7 +668,7 @@ namespace Game.Entities { Group group = Global.GroupMgr.GetGroupByGUID(lootingGroupLowGUID); if (group) - group.EndRoll(loot); + group.EndRoll(loot, GetMap()); m_groupLootTimer = 0; lootingGroupLowGUID.Clear(); @@ -1396,7 +1396,7 @@ namespace Game.Entities if (!slot.Value.IsEmpty()) { - Player ChairUser = Global.ObjAccessor.FindPlayer(slot.Value); + Player ChairUser = Global.ObjAccessor.GetPlayer(this, slot.Value); if (ChairUser != null) 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. diff --git a/Source/Game/Entities/Player/KillRewarder.cs b/Source/Game/Entities/Player/KillRewarder.cs index 8799cf210..877ff1561 100644 --- a/Source/Game/Entities/Player/KillRewarder.cs +++ b/Source/Game/Entities/Player/KillRewarder.cs @@ -104,7 +104,7 @@ namespace Game.Entities Player member = refe.GetSource(); if (member) { - if (member.IsAlive() && member.IsAtGroupRewardDistance(_victim)) + if (_killer == member || (member.IsAtGroupRewardDistance(_victim) && member.IsAlive())) { uint lvl = member.getLevel(); // 2.1. _count - number of alive group members within reward distance; @@ -254,7 +254,8 @@ namespace Game.Entities Player member = refe.GetSource(); if (member) { - if (member.IsAtGroupRewardDistance(_victim)) + // Killer may not be at reward distance, check directly + if (_killer == member || member.IsAtGroupRewardDistance(_victim)) { _RewardPlayer(member, isDungeon); member.UpdateCriteria(CriteriaTypes.SpecialPvpKill, 1, 0, 0, _victim); diff --git a/Source/Game/Entities/Player/Player.DB.cs b/Source/Game/Entities/Player/Player.DB.cs index dafb8a91e..560dfb2b5 100644 --- a/Source/Game/Entities/Player/Player.DB.cs +++ b/Source/Game/Entities/Player/Player.DB.cs @@ -1525,6 +1525,10 @@ namespace Game.Entities stmt.AddValue(2, GetGUID().GetCounter()); trans.Append(stmt); + RemoveTradeableItem(item); + RemoveEnchantmentDurationsReferences(item); + RemoveItemDurations(item); + // 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 DeleteRefundReference(item.GetGUID()); diff --git a/Source/Game/Entities/Player/Player.Groups.cs b/Source/Game/Entities/Player/Player.Groups.cs index e6bd42253..1be8a52f2 100644 --- a/Source/Game/Entities/Player/Player.Groups.cs +++ b/Source/Game/Entities/Player/Player.Groups.cs @@ -76,7 +76,7 @@ namespace Game.Entities // @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()) - if (refe.GetSource() && refe.GetSource().IsInCombat()) + if (refe.GetSource() && refe.GetSource().IsInMap(this) && refe.GetSource().IsInCombat()) return PartyResult.PartyLfgBootInCombat; /* Missing support for these types @@ -192,15 +192,13 @@ namespace Game.Entities public bool IsAtGroupRewardDistance(WorldObject pRewardSource) { - if (!pRewardSource) + if (!pRewardSource || !IsInMap(pRewardSource)) return false; + WorldObject player = GetCorpse(); if (!player || IsAlive()) player = this; - if (player.GetMapId() != pRewardSource.GetMapId() || player.GetInstanceId() != pRewardSource.GetInstanceId()) - return false; - if (player.GetMap().IsDungeon()) return true; diff --git a/Source/Game/Entities/Player/Player.Spells.cs b/Source/Game/Entities/Player/Player.Spells.cs index 507ee5c16..8a17791d9 100644 --- a/Source/Game/Entities/Player/Player.Spells.cs +++ b/Source/Game/Entities/Player/Player.Spells.cs @@ -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) { // 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) 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; } diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index 67dfe0655..f91394224 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -862,6 +862,7 @@ namespace Game.Entities StopCastingCharm(); StopCastingBindSight(); UnsummonPetTemporaryIfAny(); + ClearComboPoints(); Global.OutdoorPvPMgr.HandlePlayerLeaveZone(this, m_zoneUpdateId); Global.BattleFieldMgr.HandlePlayerLeaveZone(this, m_zoneUpdateId); } @@ -7031,15 +7032,13 @@ namespace Game.Entities bool IsAtRecruitAFriendDistance(WorldObject pOther) { - if (!pOther) + if (!pOther || !IsInMap(pOther)) return false; + WorldObject player = GetCorpse(); if (!player || IsAlive()) player = this; - if (player.GetMapId() != pOther.GetMapId() || player.GetInstanceId() != pOther.GetInstanceId()) - return false; - return pOther.GetDistance(player) <= WorldConfig.GetFloatValue(WorldCfg.MaxRecruitAFriendDistance); } diff --git a/Source/Game/Entities/Totem.cs b/Source/Game/Entities/Totem.cs index 1b5f59758..40fcf0b02 100644 --- a/Source/Game/Entities/Totem.cs +++ b/Source/Game/Entities/Totem.cs @@ -135,7 +135,7 @@ namespace Game.Entities for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.next()) { Player target = refe.GetSource(); - if (target && group.SameSubGroup(owner, target)) + if (target && target.IsInMap(owner) && group.SameSubGroup(owner, target)) target.RemoveAurasDueToSpell(GetSpell(), GetGUID()); } } diff --git a/Source/Game/Entities/Unit/Unit.Combat.cs b/Source/Game/Entities/Unit/Unit.Combat.cs index 90aa6f8d1..2b8faf493 100644 --- a/Source/Game/Entities/Unit/Unit.Combat.cs +++ b/Source/Game/Entities/Unit/Unit.Combat.cs @@ -1741,17 +1741,17 @@ namespace Game.Entities for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.next()) { - Player Target = refe.GetSource(); - if (Target) + Player target = refe.GetSource(); + if (target) { // IsHostileTo check duel and controlled by enemy - if (Target != this && Target.IsAlive() && IsWithinDistInMap(Target, radius) && !IsHostileTo(Target)) - nearMembers.Add(Target); + if (target != this && IsWithinDistInMap(target, radius) && target.IsAlive() && !IsHostileTo(target)) + nearMembers.Add(target); // Push player's pet to vector - Unit pet = Target.GetGuardianPet(); + Unit pet = target.GetGuardianPet(); 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); } } diff --git a/Source/Game/Entities/Unit/Unit.cs b/Source/Game/Entities/Unit/Unit.cs index 8f7127ccf..ab251ef08 100644 --- a/Source/Game/Entities/Unit/Unit.cs +++ b/Source/Game/Entities/Unit/Unit.cs @@ -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 CombatStop(); DeleteThreatList(); - getHostileRefManager().setOnlineOfflineState(false); + getHostileRefManager().deleteReferences(); GetMotionMaster().Clear(false); // remove different non-standard movement generators. } public override void CleanupsBeforeDelete(bool finalCleanup = true) diff --git a/Source/Game/Groups/Group.cs b/Source/Game/Groups/Group.cs index 43dbf2c88..7cb28d695 100644 --- a/Source/Game/Groups/Group.cs +++ b/Source/Game/Groups/Group.cs @@ -560,7 +560,7 @@ namespace Game.Groups roll.playerVote.Remove(guid); if (roll.totalPass + roll.totalNeed + roll.totalGreed >= roll.totalPlayersRolling) - CountTheRoll(roll); + CountTheRoll(roll, null); } // Update subgroups @@ -1110,21 +1110,21 @@ namespace Game.Groups } 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) { 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 ? { @@ -1138,13 +1138,21 @@ namespace Game.Groups if (!roll.playerVote.Empty()) { byte maxresul = 0; - ObjectGuid maxguid = roll.playerVote.First().Key; + ObjectGuid maxguid = ObjectGuid.Empty; + Player player = null; foreach (var pair in roll.playerVote) { if (pair.Value != RollType.Need) continue; + player = Global.ObjAccessor.FindPlayer(pair.Key); + if (!player || (allowedMap != null && player.GetMap() != allowedMap)) + { + --roll.totalNeed; + continue; + } + byte randomN = (byte)RandomHelper.IRand(1, 100); SendLootRoll(pair.Key, randomN, RollType.Need, roll); if (maxresul < randomN) @@ -1153,66 +1161,18 @@ namespace Game.Groups 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 dest = new List(); - 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) + if (player && player.GetSession()) { - item.is_looted = true; - 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; + player.UpdateCriteria(CriteriaTypes.RollNeedOnLoot, roll.itemid, maxresul); - 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 dest = new List(); + 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) { @@ -1228,37 +1188,107 @@ namespace Game.Groups 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.getLoot().NotifyItemRemoved(roll.itemSlot); - roll.getLoot().unlootedCount--; - player.UpdateCriteria(CriteriaTypes.CastSpell, 13262); // Disenchant + --roll.totalGreed; + continue; + } - 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 dest = new List(); - 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. + if (!maxguid.IsEmpty()) + { + SendLootRollWon(maxguid, maxresul, rollVote, roll); + player = Global.ObjAccessor.FindConnectedPlayer(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) { - 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) + List dest = new List(); + InventoryResult msg = player.CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, roll.itemid, item.count); + if (msg == InventoryResult.Ok) { - LootItem lootItem = loot.LootItemInSlot(i, player); - player.SendEquipError(msg, null, null, lootItem.itemid); - player.SendItemRetrievalMail(lootItem.itemid, lootItem.count); + item.is_looted = true; + 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 (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 dest = new List(); + 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); diff --git a/Source/Game/Loot/Loot.cs b/Source/Game/Loot/Loot.cs index acc0390c0..b4a370a0e 100644 --- a/Source/Game/Loot/Loot.cs +++ b/Source/Game/Loot/Loot.cs @@ -228,7 +228,8 @@ namespace Game.Loots { 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 - FillNotNormalLootFor(player, player.IsAtGroupRewardDistance(lootOwner)); + if (player.IsInMap(lootOwner)) + FillNotNormalLootFor(player, player.IsAtGroupRewardDistance(lootOwner)); } for (byte i = 0; i < items.Count; ++i) diff --git a/Source/Game/Maps/ObjectGridLoader.cs b/Source/Game/Maps/ObjectGridLoader.cs index c5eb30ec3..3bdc637b1 100644 --- a/Source/Game/Maps/ObjectGridLoader.cs +++ b/Source/Game/Maps/ObjectGridLoader.cs @@ -167,7 +167,7 @@ namespace Game.Maps creature.RemoveAllDynObjects(); creature.RemoveAllAreaTriggers(); - if (creature.IsInCombat()) + if (creature.IsInCombat() || !creature.GetThreatManager().areThreatListsEmpty()) { creature.CombatStop(); creature.DeleteThreatList();