diff options
20 files changed, 159 insertions, 110 deletions
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index bd9a0fdf5d5..1124edcfc81 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -282,7 +282,7 @@ void PetAI::UpdateAllies() for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* Target = itr->GetSource(); - if (!Target || !group->SameSubGroup(owner->ToPlayer(), Target)) + if (!Target || !Target->IsInMap(owner) || !group->SameSubGroup(owner->ToPlayer(), Target)) continue; if (Target->GetGUID() == owner->GetGUID()) diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp index 0128a8d55a1..1dda5017208 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp @@ -126,7 +126,8 @@ void npc_escortAI::JustDied(Unit* /*killer*/) { for (GroupReference* groupRef = group->GetFirstMember(); groupRef != NULL; groupRef = groupRef->next()) if (Player* member = groupRef->GetSource()) - member->FailQuest(m_pQuestForEscort->GetQuestId()); + if (member->IsInMap(player)) + member->FailQuest(m_pQuestForEscort->GetQuestId()); } else player->FailQuest(m_pQuestForEscort->GetQuestId()); diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp index 07294655449..8d2803b10b7 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp @@ -152,7 +152,8 @@ void FollowerAI::JustDied(Unit* /*killer*/) { for (GroupReference* groupRef = group->GetFirstMember(); groupRef != NULL; groupRef = groupRef->next()) if (Player* member = groupRef->GetSource()) - member->FailQuest(m_pQuestForFollow->GetQuestId()); + if (member->IsInMap(player)) + member->FailQuest(m_pQuestForFollow->GetQuestId()); } else player->FailQuest(m_pQuestForFollow->GetQuestId()); @@ -230,7 +231,6 @@ void FollowerAI::UpdateAI(uint32 uiDiff) for (GroupReference* groupRef = group->GetFirstMember(); groupRef != NULL; groupRef = groupRef->next()) { Player* member = groupRef->GetSource(); - if (member && me->IsWithinDistInMap(member, MAX_PLAYER_DISTANCE)) { bIsMaxRangeExceeded = false; @@ -338,8 +338,7 @@ Player* FollowerAI::GetLeaderForFollower() for (GroupReference* groupRef = group->GetFirstMember(); groupRef != NULL; groupRef = groupRef->next()) { Player* member = groupRef->GetSource(); - - if (member && member->IsAlive() && me->IsWithinDistInMap(member, MAX_PLAYER_DISTANCE)) + if (member && me->IsWithinDistInMap(member, MAX_PLAYER_DISTANCE) && member->IsAlive()) { TC_LOG_DEBUG("scripts", "FollowerAI GetLeader changed and returned new leader."); m_uiLeaderGUID = member->GetGUID(); diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index acd2f794bca..96ed78b08de 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -243,6 +243,8 @@ void SmartAI::EndPath(bool fail) for (GroupReference* groupRef = group->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next()) { Player* groupGuy = groupRef->GetSource(); + if (!groupGuy->IsInMap(player)) + continue; if (!fail && groupGuy->IsAtGroupRewardDistance(me) && !groupGuy->HasCorpse()) groupGuy->AreaExploredOrEventHappens(mEscortQuestID); @@ -411,8 +413,7 @@ bool SmartAI::IsEscortInvokerInRange() for (GroupReference* groupRef = group->GetFirstMember(); groupRef != nullptr; 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/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index f5026728012..be37c0e671e 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -2831,7 +2831,8 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* { for (GroupReference* groupRef = group->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next()) if (Player* member = groupRef->GetSource()) - l->push_back(member); + if (member->IsInMap(player)) + l->push_back(member); } // We still add the player to the list if there is no group. If we do // this even if there is a group (thus the else-check), it will add the @@ -3048,7 +3049,8 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* { for (GroupReference* it = lootGroup->GetFirstMember(); it != nullptr; it = it->next()) if (Player* recipient = it->GetSource()) - l->push_back(recipient); + if (recipient->IsInMap(me)) + l->push_back(recipient); } else { diff --git a/src/server/game/Combat/ThreatManager.h b/src/server/game/Combat/ThreatManager.h index a0678613fe0..61e9fcb60fb 100644 --- a/src/server/game/Combat/ThreatManager.h +++ b/src/server/game/Combat/ThreatManager.h @@ -221,6 +221,7 @@ class TC_GAME_API ThreatManager float getThreat(Unit* victim, bool alsoSearchOfflineList = false); bool isThreatListEmpty() const { return iThreatContainer.empty(); } + bool areThreatListsEmpty() const { return iThreatContainer.empty() && iThreatOfflineContainer.empty(); } void processThreatEvent(ThreatRefStatusChangeEvent* threatRefStatusChangeEvent); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index e8a5eafe527..5a97aec51ea 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -554,7 +554,7 @@ void Creature::Update(uint32 diff) if (m_groupLootTimer <= diff) { if (Group* group = sGroupMgr->GetGroupByGUID(lootingGroupLowGUID)) - group->EndRoll(&loot); + group->EndRoll(&loot, GetMap()); m_groupLootTimer = 0; lootingGroupLowGUID.Clear(); diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index a2e58bccdd2..1fb30cb49a2 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -714,7 +714,7 @@ void GameObject::Update(uint32 diff) if (m_groupLootTimer <= diff) { if (Group* group = sGroupMgr->GetGroupByGUID(lootingGroupLowGUID)) - group->EndRoll(&loot); + group->EndRoll(&loot, GetMap()); m_groupLootTimer = 0; lootingGroupLowGUID.Clear(); @@ -1441,7 +1441,7 @@ void GameObject::Use(Unit* user) if (!itr->second.IsEmpty()) { - if (Player* ChairUser = ObjectAccessor::FindPlayer(itr->second)) + if (Player* ChairUser = ObjectAccessor::GetPlayer(*this, itr->second)) { if (ChairUser->IsSitState() && ChairUser->GetStandState() != UNIT_STAND_STATE_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/src/server/game/Entities/Player/KillRewarder.cpp b/src/server/game/Entities/Player/KillRewarder.cpp index 2c0ddc20fba..5250dc6bfa5 100644 --- a/src/server/game/Entities/Player/KillRewarder.cpp +++ b/src/server/game/Entities/Player/KillRewarder.cpp @@ -94,7 +94,7 @@ inline void KillRewarder::_InitGroupData() // 2. In case when player is in group, initialize variables necessary for group calculations: for (GroupReference* itr = _group->GetFirstMember(); itr != nullptr; itr = itr->next()) if (Player* member = itr->GetSource()) - if (member->IsAlive() && member->IsAtGroupRewardDistance(_victim)) + if (_killer == member || (member->IsAtGroupRewardDistance(_victim) && member->IsAlive())) { const uint8 lvl = member->getLevel(); // 2.1. _count - number of alive group members within reward distance; @@ -240,7 +240,8 @@ void KillRewarder::_RewardGroup() { if (Player* member = itr->GetSource()) { - if (member->IsAtGroupRewardDistance(_victim)) + // Killer may not be at reward distance, check directly + if (_killer == member || member->IsAtGroupRewardDistance(_victim)) { _RewardPlayer(member, isDungeon); member->UpdateCriteria(CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, 0, _victim); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 6df63e2c386..c668944d843 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1742,6 +1742,7 @@ void Player::RemoveFromWorld() StopCastingCharm(); StopCastingBindSight(); UnsummonPetTemporaryIfAny(); + ClearComboPoints(); sOutdoorPvPMgr->HandlePlayerLeaveZone(this, m_zoneUpdateId); sBattlefieldMgr->HandlePlayerLeaveZone(this, m_zoneUpdateId); } @@ -13684,6 +13685,17 @@ void Player::RemoveEnchantmentDurations(Item* item) } } +void Player::RemoveEnchantmentDurationsReferences(Item* item) +{ + for (EnchantDurationList::iterator itr = m_enchantDuration.begin(); itr != m_enchantDuration.end();) + { + if (itr->item == item) + itr = m_enchantDuration.erase(itr); + else + ++itr; + } +} + void Player::RemoveArenaEnchantments(EnchantmentSlot slot) { // remove enchantments from equipped items first to clean up the m_enchantDuration list @@ -20477,6 +20489,10 @@ void Player::_SaveInventory(SQLTransaction& trans) stmt->setUInt64(2, GetGUID().GetCounter()); trans->Append(stmt); + RemoveTradeableItem(item); + RemoveEnchantmentDurationsReferences(item); + RemoveItemDurations(item); + // also THIS item should be somewhere else, cheat attempt item->FSetState(ITEM_REMOVED); // we are IN updateQueue right now, can't use SetState which modifies the queue DeleteRefundReference(item->GetGUID()); @@ -24892,15 +24908,13 @@ void Player::RewardPlayerAndGroupAtEvent(uint32 creature_id, WorldObject* pRewar bool Player::IsAtGroupRewardDistance(WorldObject const* pRewardSource) const { - if (!pRewardSource) + if (!pRewardSource || !IsInMap(pRewardSource)) return false; + const 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; @@ -24909,15 +24923,13 @@ bool Player::IsAtGroupRewardDistance(WorldObject const* pRewardSource) const bool Player::IsAtRecruitAFriendDistance(WorldObject const* pOther) const { - if (!pOther) + if (!pOther || !IsInMap(pOther)) return false; + const WorldObject* player = GetCorpse(); if (!player || IsAlive()) player = this; - if (player->GetMapId() != pOther->GetMapId() || player->GetInstanceId() != pOther->GetInstanceId()) - return false; - return pOther->GetDistance(player) <= sWorld->getFloatConfig(CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE); } @@ -25150,7 +25162,7 @@ PartyResult Player::CanUninviteFromGroup(ObjectGuid guidMember) const /// @todo Should also be sent when anyone has recently left combat, with an aprox ~5 seconds timer. for (GroupReference const* itr = grp->GetFirstMember(); itr != nullptr; itr = itr->next()) - if (itr->GetSource() && itr->GetSource()->IsInCombat()) + if (itr->GetSource() && itr->GetSource()->IsInMap(this) && itr->GetSource()->IsInCombat()) return ERR_PARTY_LFG_BOOT_IN_COMBAT; /* Missing support for these types diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index a482ad4c5c1..b027fa928e5 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1263,6 +1263,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void UpdateItemDuration(uint32 time, bool realtimeonly = false); void AddEnchantmentDurations(Item* item); void RemoveEnchantmentDurations(Item* item); + void RemoveEnchantmentDurationsReferences(Item* item); void RemoveArenaEnchantments(EnchantmentSlot slot); void AddEnchantmentDuration(Item* item, EnchantmentSlot slot, uint32 duration); void ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool apply_dur = true, bool ignore_condition = false); diff --git a/src/server/game/Entities/Totem/Totem.cpp b/src/server/game/Entities/Totem/Totem.cpp index 2c17b7fbfb3..17be943b823 100644 --- a/src/server/game/Entities/Totem/Totem.cpp +++ b/src/server/game/Entities/Totem/Totem.cpp @@ -129,7 +129,7 @@ void Totem::UnSummon(uint32 msTime) for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* target = itr->GetSource(); - if (target && group->SameSubGroup(owner, target)) + if (target && target->IsInMap(owner) && group->SameSubGroup(owner, target)) target->RemoveAurasDueToSpell(GetSpell(), GetGUID()); } } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index e046dc17402..9dc36a84021 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -6304,12 +6304,12 @@ Unit* Unit::GetNextRandomRaidMemberOrPet(float radius) if (Player* Target = itr->GetSource()) { // 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.push_back(Target); // Push player's pet to vector if (Unit* pet = Target->GetGuardianPet()) - if (pet != this && pet->IsAlive() && IsWithinDistInMap(pet, radius) && !IsHostileTo(pet)) + if (pet != this && IsWithinDistInMap(pet, radius) && pet->IsAlive() && !IsHostileTo(pet)) nearMembers.push_back(pet); } @@ -9617,7 +9617,7 @@ void Unit::CleanupBeforeRemoveFromMap(bool finalCleanup) m_Events.KillAllEvents(false); // non-delatable (currently cast 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. } @@ -11859,23 +11859,23 @@ void Unit::GetPartyMembers(std::list<Unit*> &TagUnitMap) Player* Target = itr->GetSource(); // IsHostileTo check duel and controlled by enemy - if (Target && Target->GetSubGroup() == subgroup && !IsHostileTo(Target)) + if (Target && Target->IsInMap(owner) && Target->GetSubGroup() == subgroup && !IsHostileTo(Target)) { - if (Target->IsAlive() && IsInMap(Target)) + if (Target->IsAlive()) TagUnitMap.push_back(Target); if (Guardian* pet = Target->GetGuardianPet()) - if (pet->IsAlive() && IsInMap(Target)) + if (pet->IsAlive()) TagUnitMap.push_back(pet); } } } else { - if (owner->IsAlive() && (owner == this || IsInMap(owner))) + if ((owner == this || IsInMap(owner)) && owner->IsAlive()) TagUnitMap.push_back(owner); if (Guardian* pet = owner->GetGuardianPet()) - if (pet->IsAlive() && (pet == this || IsInMap(pet))) + if ((pet == this || IsInMap(pet)) && pet->IsAlive()) TagUnitMap.push_back(pet); } } diff --git a/src/server/game/Grids/ObjectGridLoader.cpp b/src/server/game/Grids/ObjectGridLoader.cpp index 01928bc5e01..6d1fb267d7f 100644 --- a/src/server/game/Grids/ObjectGridLoader.cpp +++ b/src/server/game/Grids/ObjectGridLoader.cpp @@ -221,7 +221,7 @@ void ObjectGridStoper::Visit(CreatureMapType &m) iter->GetSource()->RemoveAllDynObjects(); iter->GetSource()->RemoveAllAreaTriggers(); - if (iter->GetSource()->IsInCombat()) + if (iter->GetSource()->IsInCombat() || !iter->GetSource()->getThreatManager().areThreatListsEmpty()) { iter->GetSource()->CombatStop(); iter->GetSource()->DeleteThreatList(); diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 068502a6bbe..8fa7be7dda9 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -617,7 +617,7 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R if (roll->totalPass + roll->totalNeed + roll->totalGreed >= roll->totalPlayersRolling) { - CountTheRoll(it); + CountTheRoll(it, nullptr); it = RollId.begin(); } } @@ -1199,17 +1199,17 @@ void Group::CountRollVote(ObjectGuid playerGuid, ObjectGuid lootObjectGuid, uint } if (roll->totalPass + roll->totalNeed + roll->totalGreed >= roll->totalPlayersRolling) - CountTheRoll(rollI); + CountTheRoll(rollI, nullptr); } //called when roll timer expires -void Group::EndRoll(Loot* pLoot) +void Group::EndRoll(Loot* pLoot, Map* allowedMap) { for (Rolls::iterator itr = RollId.begin(); itr != RollId.end();) { if ((*itr)->getLoot() == pLoot) { - CountTheRoll(itr); //i don't have to edit player votes, who didn't vote ... he will pass + CountTheRoll(itr, allowedMap); //i don't have to edit player votes, who didn't vote ... he will pass itr = RollId.begin(); } else @@ -1217,7 +1217,7 @@ void Group::EndRoll(Loot* pLoot) } } -void Group::CountTheRoll(Rolls::iterator rollI) +void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap) { Roll* roll = *rollI; if (!roll->isValid()) // is loot already deleted ? @@ -1233,14 +1233,21 @@ void Group::CountTheRoll(Rolls::iterator rollI) if (!roll->playerVote.empty()) { uint8 maxresul = 0; - ObjectGuid maxguid = (*roll->playerVote.begin()).first; - Player* player; + ObjectGuid maxguid = ObjectGuid::Empty; + Player* player = nullptr; for (Roll::PlayerVote::const_iterator itr=roll->playerVote.begin(); itr != roll->playerVote.end(); ++itr) { if (itr->second != NEED) continue; + player = ObjectAccessor::FindPlayer(itr->first); + if (!player || (allowedMap != nullptr && player->FindMap() != allowedMap)) + { + --roll->totalNeed; + continue; + } + uint8 randomN = urand(1, 100); SendLootRoll(itr->first, randomN, ROLL_NEED, *roll); if (maxresul < randomN) @@ -1249,39 +1256,46 @@ void Group::CountTheRoll(Rolls::iterator rollI) maxresul = randomN; } } - SendLootRollWon(maxguid, maxresul, ROLL_NEED, *roll); - player = ObjectAccessor::FindConnectedPlayer(maxguid); - if (player && player->GetSession()) + if (!maxguid.IsEmpty()) { - player->UpdateCriteria(CRITERIA_TYPE_ROLL_NEED_ON_LOOT, roll->itemid, maxresul); + SendLootRollWon(maxguid, maxresul, ROLL_NEED, *roll); + player = ObjectAccessor::FindConnectedPlayer(maxguid); - ItemPosCountVec dest; - LootItem* item = &(roll->itemSlot >= roll->getLoot()->items.size() ? roll->getLoot()->quest_items[roll->itemSlot - roll->getLoot()->items.size()] : roll->getLoot()->items[roll->itemSlot]); - InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count); - if (msg == EQUIP_ERR_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, nullptr, nullptr, roll->itemid); + player->UpdateCriteria(CRITERIA_TYPE_ROLL_NEED_ON_LOOT, roll->itemid, maxresul); + + ItemPosCountVec dest; + LootItem* item = &(roll->itemSlot >= roll->getLoot()->items.size() ? roll->getLoot()->quest_items[roll->itemSlot - roll->getLoot()->items.size()] : roll->getLoot()->items[roll->itemSlot]); + InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count); + if (msg == EQUIP_ERR_OK) + { + 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, nullptr, nullptr, roll->itemid); + } } } + else + roll->totalNeed = 0; } } - else if (roll->totalGreed > 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()) { uint8 maxresul = 0; - ObjectGuid maxguid = (*roll->playerVote.begin()).first; - Player* player; + ObjectGuid maxguid = ObjectGuid::Empty; + Player* player = nullptr; RollVote rollvote = NOT_VALID; Roll::PlayerVote::iterator itr; @@ -1290,6 +1304,13 @@ void Group::CountTheRoll(Rolls::iterator rollI) if (itr->second != GREED && itr->second != DISENCHANT) continue; + player = ObjectAccessor::FindPlayer(itr->first); + if (!player || (allowedMap != NULL && player->FindMap() != allowedMap)) + { + --roll->totalGreed; + continue; + } + uint8 randomN = urand(1, 100); SendLootRoll(itr->first, randomN, itr->second, *roll); if (maxresul < randomN) @@ -1299,64 +1320,71 @@ void Group::CountTheRoll(Rolls::iterator rollI) rollvote = itr->second; } } - SendLootRollWon(maxguid, maxresul, rollvote, *roll); - player = ObjectAccessor::FindConnectedPlayer(maxguid); - if (player && player->GetSession()) + if (!maxguid.IsEmpty()) { - player->UpdateCriteria(CRITERIA_TYPE_ROLL_GREED_ON_LOOT, roll->itemid, maxresul); - - LootItem* item = &(roll->itemSlot >= roll->getLoot()->items.size() ? roll->getLoot()->quest_items[roll->itemSlot - roll->getLoot()->items.size()] : roll->getLoot()->items[roll->itemSlot]); + SendLootRollWon(maxguid, maxresul, rollvote, *roll); + player = ObjectAccessor::FindConnectedPlayer(maxguid); - if (rollvote == GREED) + if (player && player->GetSession()) { - ItemPosCountVec dest; - InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count); - if (msg == EQUIP_ERR_OK) + player->UpdateCriteria(CRITERIA_TYPE_ROLL_GREED_ON_LOOT, roll->itemid, maxresul); + + LootItem* item = &(roll->itemSlot >= roll->getLoot()->items.size() ? roll->getLoot()->quest_items[roll->itemSlot - roll->getLoot()->items.size()] : roll->getLoot()->items[roll->itemSlot]); + + if (rollvote == GREED) + { + ItemPosCountVec dest; + InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count); + if (msg == EQUIP_ERR_OK) + { + 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, nullptr, nullptr, roll->itemid); + } + } + else if (rollvote == DISENCHANT) { 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, nullptr, nullptr, roll->itemid); - } - } - else if (rollvote == DISENCHANT) - { - item->is_looted = true; - roll->getLoot()->NotifyItemRemoved(roll->itemSlot); - roll->getLoot()->unlootedCount--; - player->UpdateCriteria(CRITERIA_TYPE_CAST_SPELL, 13262); // Disenchant - - ItemDisenchantLootEntry const* disenchant = ASSERT_NOTNULL(roll->GetItemDisenchantLoot(player)); + player->UpdateCriteria(CRITERIA_TYPE_CAST_SPELL, 13262); // Disenchant - ItemPosCountVec dest; - InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count); - if (msg == EQUIP_ERR_OK) - player->AutoStoreLoot(disenchant->ID, LootTemplates_Disenchant, true); - else // If the player's inventory is full, send the disenchant result in a mail. - { - Loot loot; - loot.FillLoot(disenchant->ID, LootTemplates_Disenchant, player, true); + ItemDisenchantLootEntry const* disenchant = ASSERT_NOTNULL(roll->GetItemDisenchantLoot(player)); - uint32 max_slot = loot.GetMaxSlotInLootFor(player); - for (uint32 i = 0; i < max_slot; ++i) + ItemPosCountVec dest; + InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count); + if (msg == EQUIP_ERR_OK) + player->AutoStoreLoot(disenchant->ID, LootTemplates_Disenchant, true); + else // If the player's inventory is full, send the disenchant result in a mail. { - LootItem* lootItem = loot.LootItemInSlot(i, player); - player->SendEquipError(msg, nullptr, nullptr, lootItem->itemid); - player->SendItemRetrievalMail(lootItem->itemid, lootItem->count); + Loot loot; + loot.FillLoot(disenchant->ID, LootTemplates_Disenchant, player, true); + + uint32 max_slot = loot.GetMaxSlotInLootFor(player); + for (uint32 i = 0; i < max_slot; ++i) + { + LootItem* lootItem = loot.LootItemInSlot(i, player); + player->SendEquipError(msg, nullptr, nullptr, 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/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h index 520d1da80dd..dcec9759536 100644 --- a/src/server/game/Groups/Group.h +++ b/src/server/game/Groups/Group.h @@ -391,9 +391,9 @@ class TC_GAME_API Group void GroupLoot(Loot* loot, WorldObject* pLootedObject); void MasterLoot(Loot* loot, WorldObject* pLootedObject); Rolls::iterator GetRoll(ObjectGuid lootObjectGuid, uint8 lootListId); - void CountTheRoll(Rolls::iterator roll); + void CountTheRoll(Rolls::iterator roll, Map* allowedMap); void CountRollVote(ObjectGuid playerGuid, ObjectGuid lootObjectGuid, uint8 lootListId, uint8 choice); - void EndRoll(Loot* loot); + void EndRoll(Loot* loot, Map* allowedMap); // related to disenchant rolls void ResetMaxEnchantingLevel(); diff --git a/src/server/game/Loot/Loot.cpp b/src/server/game/Loot/Loot.cpp index ab32019a4cc..c16178da814 100644 --- a/src/server/game/Loot/Loot.cpp +++ b/src/server/game/Loot/Loot.cpp @@ -266,7 +266,8 @@ bool Loot::FillLoot(uint32 lootId, LootStore const& store, Player* lootOwner, bo for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) if (Player* player = itr->GetSource()) // 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 (uint8 i = 0; i < items.size(); ++i) { diff --git a/src/server/scripts/EasternKingdoms/Stratholme/stratholme.cpp b/src/server/scripts/EasternKingdoms/Stratholme/stratholme.cpp index a48587849b5..3fae22e8e50 100644 --- a/src/server/scripts/EasternKingdoms/Stratholme/stratholme.cpp +++ b/src/server/scripts/EasternKingdoms/Stratholme/stratholme.cpp @@ -65,7 +65,7 @@ public: for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* pGroupie = itr->GetSource(); - if (!pGroupie) + if (!pGroupie || !pGroupie->IsInMap(player)) continue; if (pGroupie->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE && diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp index ce0163d1f98..3e5755713db 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp @@ -371,7 +371,8 @@ class boss_lady_deathwhisper : public CreatureScript { for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) if (Player* member = itr->GetSource()) - member->KilledMonsterCredit(NPC_DARNAVAN_CREDIT); + if (member->IsInMap(owner)) + member->KilledMonsterCredit(NPC_DARNAVAN_CREDIT); } else owner->KilledMonsterCredit(NPC_DARNAVAN_CREDIT); @@ -885,7 +886,8 @@ class npc_darnavan : public CreatureScript { for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) if (Player* member = itr->GetSource()) - member->FailQuest(QUEST_DEPROGRAMMING); + if (member->IsInMap(owner)) + member->FailQuest(QUEST_DEPROGRAMMING); } else owner->FailQuest(QUEST_DEPROGRAMMING); diff --git a/src/server/scripts/Outland/zone_terokkar_forest.cpp b/src/server/scripts/Outland/zone_terokkar_forest.cpp index 6e24ad8d462..a266e88ee90 100644 --- a/src/server/scripts/Outland/zone_terokkar_forest.cpp +++ b/src/server/scripts/Outland/zone_terokkar_forest.cpp @@ -114,7 +114,7 @@ public: for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* groupie = itr->GetSource(); - if (groupie && + if (groupie && groupie->IsInMap(player) && groupie->GetQuestStatus(QUEST_DONTKILLTHEFATONE) == QUEST_STATUS_INCOMPLETE && groupie->GetReqKillOrCastCurrentCount(QUEST_DONTKILLTHEFATONE, NPC_BOULDERFIST_INVADER) == REQUIRED_KILL_COUNT) { |