aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2014-07-31 21:41:41 +0200
committerShauren <shauren.trinity@gmail.com>2014-07-31 21:41:41 +0200
commit45e9ef3d938acc833025cfa7e94d6c21c7623c89 (patch)
treedfe702bfd3ab482b9f0aa128769903be3725714d /src
parentdaecbd67e84c03b337d361b3446c09e634c69737 (diff)
Core/Loot: Fixed pickpocket refill timer and use send proper loot error packets to master looter
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp11
-rw-r--r--src/server/game/Entities/Creature/Creature.h1
-rw-r--r--src/server/game/Entities/Player/Player.cpp59
-rw-r--r--src/server/game/Entities/Player/Player.h1
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp2
-rw-r--r--src/server/game/Handlers/LootHandler.cpp29
-rw-r--r--src/server/game/Loot/LootMgr.h17
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
{