fix(Core/Loot): Set skinnable flag only after all loot was taken. Source: TrinityCore. (#9573)

Fixes #9318
This commit is contained in:
UltraNix
2021-12-12 14:31:00 +01:00
committed by GitHub
parent 4e93671b3c
commit b1303e0e96
3 changed files with 35 additions and 21 deletions

View File

@@ -1793,11 +1793,6 @@ void Creature::setDeathState(DeathState s, bool despawn)
setActive(false);
if (!IsPet() && GetCreatureTemplate()->SkinLootId)
if (LootTemplates_Skinning.HaveLootFor(GetCreatureTemplate()->SkinLootId))
if (hasLootRecipient())
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
if (HasSearchedAssistance())
{
SetNoSearchAssistance(false);
@@ -1869,6 +1864,7 @@ void Creature::Respawn(bool force)
LOG_DEBUG("entities.unit", "Respawning creature %s (SpawnId: %u, %s)", GetName().c_str(), GetSpawnId(), GetGUID().ToString().c_str());
m_respawnTime = 0;
ResetPickPocketLootTime();
loot.clear();
if (m_originalEntry != GetEntry())
UpdateEntry(m_originalEntry);
@@ -2710,25 +2706,33 @@ void Creature::GetRespawnPosition(float& x, float& y, float& z, float* ori, floa
void Creature::AllLootRemovedFromCorpse()
{
if (!HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE))
if (loot.loot_type != LOOT_SKINNING && !IsPet() && GetCreatureTemplate()->SkinLootId && hasLootRecipient())
{
time_t now = time(nullptr);
if (m_corpseRemoveTime <= now)
return;
if (LootTemplates_Skinning.HaveLootFor(GetCreatureTemplate()->SkinLootId))
{
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
}
}
float decayRate;
CreatureTemplate const* cinfo = GetCreatureTemplate();
time_t now = time(nullptr);
if (m_corpseRemoveTime <= now)
{
return;
}
decayRate = sWorld->getRate(RATE_CORPSE_DECAY_LOOTED);
uint32 diff = uint32((m_corpseRemoveTime - now) * decayRate);
float decayRate = sWorld->getRate(RATE_CORPSE_DECAY_LOOTED);
uint32 diff = uint32((m_corpseRemoveTime - now) * decayRate);
m_respawnTime -= diff;
m_respawnTime -= diff;
// corpse skinnable, but without skinning flag, and then skinned, corpse will despawn next update
if (cinfo && cinfo->SkinLootId)
m_corpseRemoveTime = time(nullptr);
else
m_corpseRemoveTime -= diff;
// corpse skinnable, but without skinning flag, and then skinned, corpse will despawn next update
if (loot.loot_type == LOOT_SKINNING)
{
m_corpseRemoveTime = time(nullptr);
}
else
{
m_corpseRemoveTime -= diff;
}
}

View File

@@ -5667,6 +5667,9 @@ bool Player::isAllowedToLoot(const Creature* creature)
if (!loot->hasItemForAll() && !loot->hasItemFor(this)) // no loot in creature for this player
return false;
if (loot->loot_type == LOOT_SKINNING)
return creature->GetLootRecipientGUID() == GetGUID();
Group* thisGroup = GetGroup();
if (!thisGroup)
return this == creature->GetLootRecipient();

View File

@@ -17116,9 +17116,16 @@ void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackTyp
if (!creature->IsPet() && creature->GetLootMode() > 0)
{
creature->DeleteThreatList();
CreatureTemplate const* cInfo = creature->GetCreatureTemplate();
if (cInfo && (cInfo->lootid || cInfo->maxgold > 0))
// must be after setDeathState which resets dynamic flags
if (!creature->loot.empty())
{
creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
}
else
{
creature->AllLootRemovedFromCorpse();
}
}
// Call KilledUnit for creatures, this needs to be called after the lootable flag is set