diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 11 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/Creature.h | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 59 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Handlers/LootHandler.cpp | 29 | ||||
-rw-r--r-- | src/server/game/Loot/LootMgr.h | 17 |
7 files changed, 81 insertions, 39 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 52f3a87e7bb..c9a2015dbb8 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -547,15 +547,6 @@ void Creature::Update(uint32 diff) if (!IsAlive()) break; - time_t now = time(NULL); - - // Check if we should refill the pickpocketing loot - if (loot.loot_type == LOOT_PICKPOCKETING && _pickpocketLootRestore && _pickpocketLootRestore <= now) - { - loot.clear(); - _pickpocketLootRestore = 0; - } - if (m_regenTimer > 0) { if (diff >= m_regenTimer) @@ -1531,7 +1522,7 @@ void Creature::Respawn(bool force) TC_LOG_DEBUG("entities.unit", "Respawning creature %s (GuidLow: %u, Full GUID: " UI64FMTD " Entry: %u)", GetName().c_str(), GetGUIDLow(), GetGUID(), GetEntry()); m_respawnTime = 0; - _pickpocketLootRestore = 0; + ResetPickPocketRefillTimer(); loot.clear(); if (m_originalEntry != GetEntry()) UpdateEntry(m_originalEntry); diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 8ba5fdcb6fb..1154bc17d1f 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -553,6 +553,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject Loot loot; void StartPickPocketRefillTimer(); void ResetPickPocketRefillTimer() { _pickpocketLootRestore = 0; } + bool CanGeneratePickPocketLoot() const { return _pickpocketLootRestore <= time(NULL); } void SetSkinner(uint64 guid) { _skinner = guid; } uint64 GetSkinner() const { return _skinner; } // Returns the player who skinned this creature Player* GetLootRecipient() const; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index ba8e8eafe79..b11d2d03a13 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -8935,18 +8935,27 @@ void Player::SendLoot(uint64 guid, LootType loot_type) { if (loot->loot_type != LOOT_PICKPOCKETING) { - creature->StartPickPocketRefillTimer(); - loot->clear(); + if (creature->CanGeneratePickPocketLoot()) + { + creature->StartPickPocketRefillTimer(); + loot->clear(); - if (uint32 lootid = creature->GetCreatureTemplate()->pickpocketLootId) - loot->FillLoot(lootid, LootTemplates_Pickpocketing, this, true); + if (uint32 lootid = creature->GetCreatureTemplate()->pickpocketLootId) + loot->FillLoot(lootid, LootTemplates_Pickpocketing, this, true); - // Generate extra money for pick pocket loot - const uint32 a = urand(0, creature->getLevel()/2); - const uint32 b = urand(0, getLevel()/2); - loot->gold = uint32(10 * (a + b) * sWorld->getRate(RATE_DROP_MONEY)); - permission = OWNER_PERMISSION; - } + // Generate extra money for pick pocket loot + const uint32 a = urand(0, creature->getLevel() / 2); + const uint32 b = urand(0, getLevel() / 2); + loot->gold = uint32(10 * (a + b) * sWorld->getRate(RATE_DROP_MONEY)); + permission = OWNER_PERMISSION; + } + else + { + permission = NONE_PERMISSION; + SendLootError(guid, LOOT_ERROR_ALREADY_PICKPOCKETED); + return; + } + } // else - still has pickpocket loot generated & not fully taken } else { @@ -9025,8 +9034,6 @@ void Player::SendLoot(uint64 guid, LootType loot_type) } } - SetLootGUID(guid); - // LOOT_INSIGNIA and LOOT_FISHINGHOLE unsupported by client switch (loot_type) { @@ -9039,21 +9046,35 @@ void Player::SendLoot(uint64 guid, LootType loot_type) // need know merged fishing/corpse loot type for achievements loot->loot_type = loot_type; - WorldPacket data(SMSG_LOOT_RESPONSE, (9+50)); // we guess size - data << uint64(guid); - data << uint8(loot_type); - data << LootView(*loot, this, permission); + if (permission != NONE_PERMISSION) + { + SetLootGUID(guid); - SendDirectMessage(&data); + WorldPacket data(SMSG_LOOT_RESPONSE, (9 + 50)); // we guess size + data << uint64(guid); + data << uint8(loot_type); + data << LootView(*loot, this, permission); + SendDirectMessage(&data); - // add 'this' player as one of the players that are looting 'loot' - if (permission != NONE_PERMISSION) + // add 'this' player as one of the players that are looting 'loot' loot->AddLooter(GetGUID()); + } + else + SendLootError(GetLootGUID(), LOOT_ERROR_DIDNT_KILL); if (loot_type == LOOT_CORPSE && !IS_ITEM_GUID(guid)) SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); } +void Player::SendLootError(uint64 guid, LootError error) +{ + WorldPacket data(SMSG_LOOT_RESPONSE, 10); + data << uint64(guid); + data << uint8(LOOT_NONE); + data << uint8(error); + SendDirectMessage(&data); +} + void Player::SendNotifyLootMoneyRemoved() { WorldPacket data(SMSG_LOOT_CLEAR_MONEY, 0); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 851afecdbaf..6510d7f2f26 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2018,6 +2018,7 @@ class Player : public Unit, public GridObject<Player> std::vector<ItemSetEffect*> ItemSetEff; void SendLoot(uint64 guid, LootType loot_type); + void SendLootError(uint64 guid, LootError error); void SendLootRelease(uint64 guid); void SendNotifyLootItemRemoved(uint8 lootSlot); void SendNotifyLootMoneyRemoved(); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index f5b72b845a5..9c7779407f1 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -15251,8 +15251,6 @@ void Unit::Kill(Unit* victim, bool durabilityLoss) if (creature) { Loot* loot = &creature->loot; - if (creature->loot.loot_type == LOOT_PICKPOCKETING) - creature->ResetPickPocketRefillTimer(); loot->clear(); if (uint32 lootid = creature->GetCreatureTemplate()->lootid) diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp index b9c6f349ac3..8bc9c5dc659 100644 --- a/src/server/game/Handlers/LootHandler.cpp +++ b/src/server/game/Handlers/LootHandler.cpp @@ -82,10 +82,9 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket& recvData) Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid); bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING); - if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) { - player->SendLootRelease(lguid); + player->SendLootError(lguid, lootAllowed ? LOOT_ERROR_TOO_FAR : LOOT_ERROR_DIDNT_KILL); return; } @@ -155,6 +154,8 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/) if (creature->IsAlive()) shareMoney = false; } + else + player->SendLootError(guid, lootAllowed ? LOOT_ERROR_TOO_FAR : LOOT_ERROR_DIDNT_KILL); break; } default: @@ -394,21 +395,28 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPacket& recvData) if (!_player->GetGroup() || _player->GetGroup()->GetMasterLooterGuid() != _player->GetGUID() || _player->GetGroup()->GetLootMethod() != MASTER_LOOT) { - _player->SendLootRelease(GetPlayer()->GetLootGUID()); + _player->SendLootError(lootguid, LOOT_ERROR_DIDNT_KILL); return; } Player* target = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(target_playerguid, 0, HIGHGUID_PLAYER)); if (!target) + { + _player->SendLootError(lootguid, LOOT_ERROR_PLAYER_NOT_FOUND); return; + } TC_LOG_DEBUG("network", "WorldSession::HandleLootMasterGiveOpcode (CMSG_LOOT_MASTER_GIVE, 0x02A3) Target = [%s].", target->GetName().c_str()); if (_player->GetLootGUID() != lootguid) + { + _player->SendLootError(lootguid, LOOT_ERROR_DIDNT_KILL); return; + } if (!_player->IsInRaidWith(target) || !_player->IsInMap(target)) { + _player->SendLootError(lootguid, LOOT_ERROR_MASTER_OTHER); TC_LOG_INFO("loot", "MasterLootItem: Player %s tried to give an item to ineligible player %s !", GetPlayer()->GetName().c_str(), target->GetName().c_str()); return; } @@ -450,16 +458,21 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPacket& recvData) msg = EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM; if (msg != EQUIP_ERR_OK) { + if (msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS) + _player->SendLootError(lootguid, LOOT_ERROR_MASTER_UNIQUE_ITEM); + else if (msg == EQUIP_ERR_INVENTORY_FULL) + _player->SendLootError(lootguid, LOOT_ERROR_MASTER_INV_FULL); + else + _player->SendLootError(lootguid, LOOT_ERROR_MASTER_OTHER); + target->SendEquipError(msg, NULL, NULL, item.itemid); - // send duplicate of error massage to master looter - _player->SendEquipError(msg, NULL, NULL, item.itemid); return; } // list of players allowed to receive this item in trade AllowedLooterSet looters = item.GetAllowedLooters(); - // not move item from loot to target inventory + // now move item from loot to target inventory Item* newitem = target->StoreNewItem(dest, item.itemid, true, item.randomPropertyId, looters); target->SendNewItem(newitem, uint32(item.count), false, false, true); target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item.itemid, item.count); @@ -467,8 +480,8 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPacket& recvData) target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM, item.itemid, item.count); // mark as looted - item.count=0; - item.is_looted=true; + item.count = 0; + item.is_looted = true; loot->NotifyItemRemoved(slotid); --loot->unlootedCount; diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h index cb3b9082c20..7dc89935a69 100644 --- a/src/server/game/Loot/LootMgr.h +++ b/src/server/game/Loot/LootMgr.h @@ -92,6 +92,23 @@ enum LootType LOOT_FISHING_JUNK = 22 // unsupported by client, sending LOOT_FISHING instead }; +enum LootError +{ + LOOT_ERROR_DIDNT_KILL = 0, // You don't have permission to loot that corpse. + LOOT_ERROR_TOO_FAR = 4, // You are too far away to loot that corpse. + LOOT_ERROR_BAD_FACING = 5, // You must be facing the corpse to loot it. + LOOT_ERROR_LOCKED = 6, // Someone is already looting that corpse. + LOOT_ERROR_NOTSTANDING = 8, // You need to be standing up to loot something! + LOOT_ERROR_STUNNED = 9, // You can't loot anything while stunned! + LOOT_ERROR_PLAYER_NOT_FOUND = 10, // Player not found + LOOT_ERROR_PLAY_TIME_EXCEEDED = 11, // Maximum play time exceeded + LOOT_ERROR_MASTER_INV_FULL = 12, // That player's inventory is full + LOOT_ERROR_MASTER_UNIQUE_ITEM = 13, // Player has too many of that item already + LOOT_ERROR_MASTER_OTHER = 14, // Can't assign item to that player + LOOT_ERROR_ALREADY_PICKPOCKETED = 15, // Your target has already had its pockets picked + LOOT_ERROR_NOT_WHILE_SHAPESHIFTED = 16 // You can't do that while shapeshifted. +}; + // type of Loot Item in Loot View enum LootSlotType { |