Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skinning breaks when bags are full #5318

Closed
Loginisalreadytaken opened this issue Feb 19, 2012 · 3 comments
Closed

Skinning breaks when bags are full #5318

Loginisalreadytaken opened this issue Feb 19, 2012 · 3 comments

Comments

@Loginisalreadytaken
Copy link

  1. Successfully skin a beast with a full inventory.
  2. Cancel/close the loot window.
  3. The corpse remains and is not skinable anymore.

Core revision: Trinity Core a3e739e+
Database revision: TDB 335.11.46

@Warpten
Copy link
Member

Warpten commented Feb 28, 2012

Issue lies in EffectSkinning spell handler.

    m_caster->ToPlayer()->SendLoot(creature->GetGUID(), LOOT_SKINNING);
    creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);

Should definitely not remove the flag, the flag should be removed only when the last item has been looted by the player.

needs some rewrite, will deal with it when i'll get msvc++ back working ...

@ghost ghost assigned Star-lion Nov 24, 2012
@Subv
Copy link
Contributor

Subv commented Jun 24, 2014

I need someone to test this for me:

diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index c81ba40..f9279d8 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -142,7 +142,7 @@ bool ForcedDespawnDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
 }

 Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapObject(),
-lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLowGUID(0),
+lootForPickPocketed(false), lootForBody(false), lootForSkinned(false), m_groupLootTimer(0), lootingGroupLowGUID(0),
 m_PlayerDamageReq(0), m_lootRecipient(0), m_lootRecipientGroup(0), m_corpseRemoveTime(0), m_respawnTime(0),
 m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_reactState(REACT_AGGRESSIVE),
 m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false),
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 9cc08e3..7c180b1 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;
         bool lootForPickPocketed;
         bool lootForBody;
+        bool lootForSkinned;
         Player* GetLootRecipient() const;
         Group* GetLootRecipientGroup() const;
         bool hasLootRecipient() const { return m_lootRecipient || m_lootRecipientGroup; }
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 9733c0f..d1e8d7f 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -9021,8 +9021,12 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
             // possible only if creature->lootForBody && loot->empty() at spell cast check
             if (loot_type == LOOT_SKINNING)
             {
-                loot->clear();
-                loot->FillLoot(creature->GetCreatureTemplate()->SkinLootId, LootTemplates_Skinning, this, true);
+                if (!creature->lootForSkinned)
+                {
+                    creature->lootForSkinned = true;
+                    loot->clear();
+                    loot->FillLoot(creature->GetCreatureTemplate()->SkinLootId, LootTemplates_Skinning, this, true);
+                }
                 permission = OWNER_PERMISSION;
             }
             // set group rights only for loot_type != LOOT_SKINNING
diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp
index 61f0b9a..2464a53 100644
--- a/src/server/game/Handlers/LootHandler.cpp
+++ b/src/server/game/Handlers/LootHandler.cpp
@@ -355,11 +355,15 @@ void WorldSession::DoLootRelease(uint64 lguid)
         loot = &creature->loot;
         if (loot->isLooted())
         {
+            creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
+            
+            if (loot->loot_type == LOOT_SKINNING)
+                creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
+
             // skip pickpocketing loot for speed, skinning timer reduction is no-op in fact
             if (!creature->IsAlive())
                 creature->AllLootRemovedFromCorpse();

-            creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
             loot->clear();
         }
         else
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 48c2a76..0a39433 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -5058,7 +5058,7 @@ SpellCastResult Spell::CheckCast(bool strict)
                     return SPELL_FAILED_TARGET_UNSKINNABLE;

                 Creature* creature = m_targets.GetUnitTarget()->ToCreature();
-                if (creature->GetCreatureType() != CREATURE_TYPE_CRITTER && !creature->loot.isLooted())
+                if (creature->GetCreatureType() != CREATURE_TYPE_CRITTER && creature->loot.loot_type != LOOT_SKINNING && !creature->loot.isLooted())
                     return SPELL_FAILED_TARGET_NOT_LOOTED;

                 uint32 skill = creature->GetCreatureTemplate()->GetRequiredLootSkill();
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 9cf0e1a..178f3e5 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -4702,15 +4702,26 @@ void Spell::EffectSkinning(SpellEffIndex /*effIndex*/)

     uint32 skill = creature->GetCreatureTemplate()->GetRequiredLootSkill();

+    bool awardPoints = true;
+
+    // Check if a skinning loot table was already generated for this creature
+    if (creature->loot.loot_type == LOOT_SKINNING)
+    {
+        if (!creature->loot.hasItemFor(m_caster->ToPlayer())) // Return if this player can't loot the creature
+            return;
+
+        awardPoints = false; // Do not grant skill points for this loot, they were already granted the first time.
+    }
+
     m_caster->ToPlayer()->SendLoot(creature->GetGUID(), LOOT_SKINNING);
-    creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);

     int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;

     int32 skillValue = m_caster->ToPlayer()->GetPureSkillValue(skill);

     // Double chances for elites
-    m_caster->ToPlayer()->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1);
+    if (awardPoints)
+        m_caster->ToPlayer()->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1);
 }

 void Spell::EffectCharge(SpellEffIndex /*effIndex*/)

@Subv
Copy link
Contributor

Subv commented Jun 24, 2014

Updated the patch

@Subv Subv closed this as completed in a0fedd1 Jun 25, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants