diff options
Diffstat (limited to 'src')
20 files changed, 161 insertions, 112 deletions
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 6662c4d87e9..1e059190a04 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -280,7 +280,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 369c92d4153..93f31a0f57a 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp @@ -150,7 +150,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 a2677b3bdf2..cf6c693fb7a 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp @@ -148,7 +148,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()); @@ -226,7 +227,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; @@ -333,8 +333,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 20efde08f1a..ed034cd3336 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -229,6 +229,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); @@ -384,8 +386,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 4d23ba14a5b..95a04a29cda 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -2601,7 +2601,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 @@ -2818,7 +2819,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 4b739d192c1..e17a6926ffd 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 0d18b915144..3c6fae376fc 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) { Group* group = sGroupMgr->GetGroupByGUID(lootingGroupLowGUID); if (group) - group->EndRoll(&loot); + group->EndRoll(&loot, GetMap()); m_groupLootTimer = 0; lootingGroupLowGUID = 0; } diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 8b80d027c9f..b7f4433b63e 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -582,7 +582,7 @@ void GameObject::Update(uint32 diff) { Group* group = sGroupMgr->GetGroupByGUID(lootingGroupLowGUID); if (group) - group->EndRoll(&loot); + group->EndRoll(&loot, GetMap()); m_groupLootTimer = 0; lootingGroupLowGUID = 0; } @@ -1290,7 +1290,7 @@ void GameObject::Use(Unit* user) if (itr->second) { - 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 0235866dbca..61a6277e6cd 100644 --- a/src/server/game/Entities/Player/KillRewarder.cpp +++ b/src/server/game/Entities/Player/KillRewarder.cpp @@ -90,7 +90,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; @@ -235,7 +235,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->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, _victim); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 2edff5f9527..73a20ff0310 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2145,6 +2145,8 @@ void Player::RemoveFromWorld() StopCastingCharm(); StopCastingBindSight(); UnsummonPetTemporaryIfAny(); + ClearComboPoints(); + ClearComboPointHolders(); sOutdoorPvPMgr->HandlePlayerLeaveZone(this, m_zoneUpdateId); sBattlefieldMgr->HandlePlayerLeaveZone(this, m_zoneUpdateId); } @@ -13467,6 +13469,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 @@ -19605,6 +19618,10 @@ void Player::_SaveInventory(SQLTransaction& trans) stmt->setUInt32(2, lowGuid); 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()); @@ -23631,15 +23648,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; @@ -23648,15 +23663,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); } @@ -23909,7 +23922,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 @@ -25753,7 +25766,6 @@ void Player::ActivateSpec(uint8 spec) if (Pet* pet = GetPet()) RemovePet(pet, PET_SAVE_NOT_IN_SLOT); - ClearComboPointHolders(); ClearAllReactives(); UnsummonAllTotems(); ExitVehicle(); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 9e671a305b0..9fbac96b4e6 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1291,6 +1291,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 65d31fc45dd..74acba5c0a9 100644 --- a/src/server/game/Entities/Totem/Totem.cpp +++ b/src/server/game/Entities/Totem/Totem.cpp @@ -136,7 +136,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 3407c63aa38..61cfa0322fd 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -6491,12 +6491,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); } @@ -10371,7 +10371,7 @@ void Unit::CleanupBeforeRemoveFromMap(bool finalCleanup) CombatStop(); ClearComboPointHolders(); DeleteThreatList(); - getHostileRefManager().setOnlineOfflineState(false); + getHostileRefManager().deleteReferences(); GetMotionMaster()->Clear(false); // remove different non-standard movement generators. } @@ -12555,23 +12555,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 48d4ef634fd..1cdedf34ec5 100644 --- a/src/server/game/Grids/ObjectGridLoader.cpp +++ b/src/server/game/Grids/ObjectGridLoader.cpp @@ -216,7 +216,7 @@ void ObjectGridStoper::Visit(CreatureMapType &m) for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) { iter->GetSource()->RemoveAllDynObjects(); - 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 11d29ba8b62..30ecfb83f59 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -1343,16 +1343,16 @@ void Group::CountRollVote(ObjectGuid playerGUID, ObjectGuid Guid, uint8 Choice) } 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 @@ -1360,7 +1360,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 ? @@ -1376,14 +1376,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(ObjectGuid::Empty, itr->first, randomN, ROLL_NEED, *roll); if (maxresul < randomN) @@ -1392,39 +1399,46 @@ void Group::CountTheRoll(Rolls::iterator rollI) maxresul = randomN; } } - SendLootRollWon(ObjectGuid::Empty, maxguid, maxresul, ROLL_NEED, *roll); - player = ObjectAccessor::FindConnectedPlayer(maxguid); - if (player && player->GetSession()) + if (!maxguid.IsEmpty()) { - player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT, roll->itemid, maxresul); + SendLootRollWon(ObjectGuid::Empty, 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->randomPropertyId, item->GetAllowedLooters()); - } - else - { - item->is_blocked = false; - item->rollWinnerGUID = player->GetGUID(); - player->SendEquipError(msg, nullptr, nullptr, roll->itemid); + player->UpdateAchievementCriteria(ACHIEVEMENT_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->randomPropertyId, item->GetAllowedLooters()); + } + else + { + item->is_blocked = false; + item->rollWinnerGUID = player->GetGUID(); + player->SendEquipError(msg, NULL, NULL, 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; @@ -1433,6 +1447,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(ObjectGuid::Empty, itr->first, randomN, itr->second, *roll); if (maxresul < randomN) @@ -1442,63 +1463,70 @@ void Group::CountTheRoll(Rolls::iterator rollI) rollvote = itr->second; } } - SendLootRollWon(ObjectGuid::Empty, maxguid, maxresul, rollvote, *roll); - player = ObjectAccessor::FindConnectedPlayer(maxguid); - if (player && player->GetSession()) + if (!maxguid.IsEmpty()) { - player->UpdateAchievementCriteria(ACHIEVEMENT_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(ObjectGuid::Empty, 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->UpdateAchievementCriteria(ACHIEVEMENT_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->randomPropertyId, item->GetAllowedLooters()); + } + else + { + item->is_blocked = false; + item->rollWinnerGUID = player->GetGUID(); + player->SendEquipError(msg, NULL, NULL, 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->randomPropertyId, item->GetAllowedLooters()); - } - 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--; - ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(roll->itemid); - player->UpdateAchievementCriteria(ACHIEVEMENT_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(pProto->DisenchantID, LootTemplates_Disenchant, true); - else // If the player's inventory is full, send the disenchant result in a mail. - { - Loot loot; - loot.FillLoot(pProto->DisenchantID, LootTemplates_Disenchant, player, true); - - uint32 max_slot = loot.GetMaxSlotInLootFor(player); - for (uint32 i = 0; i < max_slot; ++i) + ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(roll->itemid); + player->UpdateAchievementCriteria(ACHIEVEMENT_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(pProto->DisenchantID, 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(pProto->DisenchantID, 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, 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); @@ -1988,7 +2016,7 @@ bool Group::InCombatToInstance(uint32 instanceId) for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next()) { Player* player = itr->GetSource(); - if (player && !player->getAttackers().empty() && player->GetInstanceId() == instanceId && (player->GetMap()->IsRaidOrHeroicDungeon())) + if (player && player->GetInstanceId() == instanceId && !player->getAttackers().empty() && (player->GetMap()->IsRaidOrHeroicDungeon())) for (std::set<Unit*>::const_iterator i = player->getAttackers().begin(); i != player->getAttackers().end(); ++i) if ((*i) && (*i)->GetTypeId() == TYPEID_UNIT && (*i)->ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND) return true; diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h index d2c4ec692ba..cd8c50a8efd 100644 --- a/src/server/game/Groups/Group.h +++ b/src/server/game/Groups/Group.h @@ -303,9 +303,9 @@ class TC_GAME_API Group void NeedBeforeGreed(Loot* loot, WorldObject* pLootedObject); void MasterLoot(Loot* loot, WorldObject* pLootedObject); Rolls::iterator GetRoll(ObjectGuid Guid); - void CountTheRoll(Rolls::iterator roll); + void CountTheRoll(Rolls::iterator roll, Map* allowedMap); void CountRollVote(ObjectGuid playerGUID, ObjectGuid Guid, uint8 Choise); - void EndRoll(Loot* loot); + void EndRoll(Loot* loot, Map* allowedMap); // related to disenchant rolls void ResetMaxEnchantingLevel(); diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index d25eca4b036..9d56d8decb3 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -464,7 +464,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 03dd3986a4a..3ccf0e3dd19 100644 --- a/src/server/scripts/EasternKingdoms/Stratholme/stratholme.cpp +++ b/src/server/scripts/EasternKingdoms/Stratholme/stratholme.cpp @@ -61,7 +61,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 3567acb001b..a751e9e172c 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp @@ -367,7 +367,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); @@ -881,7 +882,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 1927dae9d57..d2a7a29e01a 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) { |