Core/Loot: Allocate Loot separately from objects
Port From (https://github.com/TrinityCore/TrinityCore/commit/7957e2d380e08fa831765f610c0e29d2f3e11a04)
This commit is contained in:
@@ -325,7 +325,7 @@ namespace Game.Chat
|
||||
}
|
||||
|
||||
Loot loot = creatureTarget.loot;
|
||||
if (!creatureTarget.IsDead() || loot.Empty())
|
||||
if (!creatureTarget.IsDead() || loot == null || loot.Empty())
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.CommandNotDeadOrNoLoot, creatureTarget.GetName());
|
||||
return false;
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Game.Entities
|
||||
|
||||
m_updateFlag.Stationary = true;
|
||||
|
||||
m_corpseData = new CorpseData();
|
||||
m_corpseData = new();
|
||||
|
||||
m_time = GameTime.GetGameTime();
|
||||
}
|
||||
@@ -323,9 +323,11 @@ namespace Game.Entities
|
||||
public CellCoord GetCellCoord() { return _cellCoord; }
|
||||
public void SetCellCoord(CellCoord cellCoord) { _cellCoord = cellCoord; }
|
||||
|
||||
public override Loot GetLootForPlayer(Player player) { return loot; }
|
||||
|
||||
public CorpseData m_corpseData;
|
||||
|
||||
public Loot loot = new();
|
||||
public Loot loot;
|
||||
public Player lootRecipient;
|
||||
|
||||
CorpseType m_type;
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace Game.Entities
|
||||
// vendor items
|
||||
List<VendorItemCount> m_vendorItemCounts = new();
|
||||
|
||||
public Loot loot = new();
|
||||
public Loot loot;
|
||||
public uint m_groupLootTimer; // (msecs)timer used for group loot
|
||||
public ObjectGuid lootingGroupLowGUID; // used to find group which is looting corpse
|
||||
ObjectGuid m_lootRecipient;
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace Game.Entities
|
||||
SetDeathState(DeathState.Dead);
|
||||
RemoveAllAuras();
|
||||
//DestroyForNearbyPlayers(); // old UpdateObjectVisibility()
|
||||
loot.Clear();
|
||||
loot = null;
|
||||
uint respawnDelay = m_respawnDelay;
|
||||
CreatureAI ai = GetAI();
|
||||
if (ai != null)
|
||||
@@ -256,10 +256,6 @@ namespace Game.Entities
|
||||
if (cInfo == null)
|
||||
cInfo = normalInfo;
|
||||
|
||||
// Initialize loot duplicate count depending on raid difficulty
|
||||
if (GetMap().Is25ManRaid())
|
||||
loot.maxDuplicates = 3;
|
||||
|
||||
SetEntry(entry); // normal entry always
|
||||
m_creatureInfo = cInfo; // map mode related always
|
||||
|
||||
@@ -511,7 +507,7 @@ namespace Game.Entities
|
||||
if (IsEngaged())
|
||||
AIUpdateTick(diff);
|
||||
|
||||
if (m_groupLootTimer != 0 && !lootingGroupLowGUID.IsEmpty())
|
||||
if (loot != null && m_groupLootTimer != 0 && !lootingGroupLowGUID.IsEmpty())
|
||||
{
|
||||
if (m_groupLootTimer <= diff)
|
||||
{
|
||||
@@ -1941,7 +1937,7 @@ namespace Game.Entities
|
||||
Log.outDebug(LogFilter.Unit, "Respawning creature {0} ({1})", GetName(), GetGUID().ToString());
|
||||
m_respawnTime = 0;
|
||||
ResetPickPocketRefillTimer();
|
||||
loot.Clear();
|
||||
loot = null;
|
||||
|
||||
if (m_originalEntry != GetEntry())
|
||||
UpdateEntry(m_originalEntry);
|
||||
@@ -2578,7 +2574,7 @@ namespace Game.Entities
|
||||
|
||||
public void AllLootRemovedFromCorpse()
|
||||
{
|
||||
if (loot.loot_type != LootType.Skinning && !IsPet() && GetCreatureTemplate().SkinLootId != 0 && HasLootRecipient())
|
||||
if ((loot == null || loot.loot_type != LootType.Skinning) && !IsPet() && GetCreatureTemplate().SkinLootId != 0 && HasLootRecipient())
|
||||
if (LootStorage.Skinning.HaveLootFor(GetCreatureTemplate().SkinLootId))
|
||||
SetUnitFlag(UnitFlags.Skinnable);
|
||||
|
||||
@@ -2591,7 +2587,7 @@ namespace Game.Entities
|
||||
float decayRate = m_ignoreCorpseDecayRatio ? 1.0f : WorldConfig.GetFloatValue(WorldCfg.RateCorpseDecayLooted);
|
||||
|
||||
// corpse skinnable, but without skinning flag, and then skinned, corpse will despawn next update
|
||||
if (loot.loot_type == LootType.Skinning)
|
||||
if (loot != null && loot.loot_type == LootType.Skinning)
|
||||
m_corpseRemoveTime = now;
|
||||
else
|
||||
m_corpseRemoveTime = now + (uint)(m_corpseDelay * decayRate);
|
||||
@@ -3280,8 +3276,6 @@ namespace Game.Entities
|
||||
// checked at creature_template loading
|
||||
DefaultMovementType = (MovementGeneratorType)data.movementType;
|
||||
|
||||
loot.SetGUID(ObjectGuid.Create(HighGuid.LootObject, GetMapId(), data.Id, GetMap().GenerateLowGuid(HighGuid.LootObject)));
|
||||
|
||||
if (addToMap && !GetMap().AddToMap(this))
|
||||
return false;
|
||||
return true;
|
||||
|
||||
@@ -373,10 +373,6 @@ namespace Game.Entities
|
||||
LastUsedScriptID = GetGoInfo().ScriptId;
|
||||
AIM_Initialize();
|
||||
|
||||
// Initialize loot duplicate count depending on raid difficulty
|
||||
if (map.Is25ManRaid())
|
||||
loot.maxDuplicates = 3;
|
||||
|
||||
if (spawnid != 0)
|
||||
m_spawnId = spawnid;
|
||||
|
||||
@@ -701,7 +697,7 @@ namespace Game.Entities
|
||||
}
|
||||
break;
|
||||
case GameObjectTypes.Chest:
|
||||
if (m_groupLootTimer != 0)
|
||||
if (loot != null && m_groupLootTimer != 0)
|
||||
{
|
||||
if (m_groupLootTimer <= diff)
|
||||
{
|
||||
@@ -805,7 +801,7 @@ namespace Game.Entities
|
||||
return;
|
||||
}
|
||||
|
||||
loot.Clear();
|
||||
loot = null;
|
||||
|
||||
// Do not delete chests or goobers that are not consumed on loot, while still allowing them to despawn when they expire if summoned
|
||||
bool isSummonedAndExpired = (GetOwner() != null || GetSpellId() != 0) && m_respawnTime == 0;
|
||||
@@ -3315,6 +3311,8 @@ namespace Game.Entities
|
||||
|
||||
bool HasLootRecipient() { return !m_lootRecipient.IsEmpty() || !m_lootRecipientGroup.IsEmpty(); }
|
||||
|
||||
public override Loot GetLootForPlayer(Player player) { return loot; }
|
||||
|
||||
public override uint GetLevelForTarget(WorldObject target)
|
||||
{
|
||||
Unit owner = GetOwner();
|
||||
@@ -3441,7 +3439,7 @@ namespace Game.Entities
|
||||
Dictionary<uint, ObjectGuid> ChairListSlots = new();
|
||||
List<ObjectGuid> m_SkillupList = new();
|
||||
|
||||
public Loot loot = new();
|
||||
public Loot loot;
|
||||
|
||||
public GameObjectModel m_model;
|
||||
|
||||
|
||||
@@ -43,8 +43,6 @@ namespace Game.Entities
|
||||
uState = ItemUpdateState.New;
|
||||
uQueuePos = -1;
|
||||
m_lastPlayedTimeUpdate = GameTime.GetGameTime();
|
||||
|
||||
loot = new Loot();
|
||||
}
|
||||
|
||||
public virtual bool Create(ulong guidlow, uint itemId, ItemContext context, Player owner)
|
||||
@@ -386,7 +384,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
// Delete the items if this is a container
|
||||
if (!loot.IsLooted())
|
||||
if (loot != null && !loot.IsLooted())
|
||||
Global.LootItemStorage.RemoveStoredLootForContainer(GetGUID().GetCounter());
|
||||
|
||||
Dispose();
|
||||
@@ -689,7 +687,7 @@ namespace Game.Entities
|
||||
DeleteFromDB(trans, GetGUID().GetCounter());
|
||||
|
||||
// Delete the items if this is a container
|
||||
if (!loot.IsLooted())
|
||||
if (loot != null && !loot.IsLooted())
|
||||
Global.LootItemStorage.RemoveStoredLootForContainer(GetGUID().GetCounter());
|
||||
}
|
||||
|
||||
@@ -2668,6 +2666,8 @@ namespace Game.Entities
|
||||
|
||||
public ItemEffectRecord[] GetEffects() { return _bonusData.Effects[0.._bonusData.EffectCount]; }
|
||||
|
||||
public override Loot GetLootForPlayer(Player player) { return loot; }
|
||||
|
||||
//Static
|
||||
public static bool ItemCanGoIntoBag(ItemTemplate pProto, ItemTemplate pBagProto)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@ using Framework.Dynamic;
|
||||
using Game.AI;
|
||||
using Game.BattleFields;
|
||||
using Game.DataStorage;
|
||||
using Game.Loots;
|
||||
using Game.Maps;
|
||||
using Game.Movement;
|
||||
using Game.Networking;
|
||||
@@ -28,7 +29,6 @@ using Game.Scenarios;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Entities
|
||||
@@ -779,6 +779,8 @@ namespace Game.Entities
|
||||
return $"{base.GetDebugInfo()}\n{GetGUID()} Entry: {GetEntry()}\nName: { GetName()}";
|
||||
}
|
||||
|
||||
public virtual Loot GetLootForPlayer(Player player) { return null; }
|
||||
|
||||
public abstract void BuildValuesCreate(WorldPacket data, Player target);
|
||||
public abstract void BuildValuesUpdate(WorldPacket data, Player target);
|
||||
|
||||
|
||||
@@ -6105,9 +6105,23 @@ namespace Game.Entities
|
||||
// Now we must make bones lootable, and send player loot
|
||||
bones.SetCorpseDynamicFlag(CorpseDynFlags.Lootable);
|
||||
|
||||
// We store the level of our player in the gold field
|
||||
// We retrieve this information at Player.SendLoot()
|
||||
bones.loot.gold = GetLevel();
|
||||
bones.loot = new Loot();
|
||||
bones.loot.SetGUID(ObjectGuid.Create(HighGuid.LootObject, GetMapId(), 0, GetMap().GenerateLowGuid(HighGuid.LootObject)));
|
||||
|
||||
// For AV Achievement
|
||||
Battleground bg = GetBattleground();
|
||||
if (bg != null)
|
||||
{
|
||||
if (bg.GetTypeID(true) == BattlegroundTypeId.AV)
|
||||
bones.loot.FillLoot(1, LootStorage.Creature, this, true);
|
||||
}
|
||||
// For wintergrasp Quests
|
||||
else if (GetZoneId() == (uint)AreaId.Wintergrasp)
|
||||
bones.loot.FillLoot(1, LootStorage.Creature, this, true);
|
||||
|
||||
// It may need a better formula
|
||||
// Now it works like this: lvl10: ~6copper, lvl70: ~9silver
|
||||
bones.loot.gold = (uint)(RandomHelper.URand(50, 150) * 0.016f * Math.Pow((float)GetLevel() / 5.76f, 2.5f) * WorldConfig.GetFloatValue(WorldCfg.RateDropMoney));
|
||||
bones.lootRecipient = looterPlr;
|
||||
looterPlr.SendLoot(bones.GetGUID(), LootType.Insignia);
|
||||
}
|
||||
@@ -6168,12 +6182,12 @@ namespace Game.Entities
|
||||
return;
|
||||
}
|
||||
|
||||
loot = go.loot;
|
||||
loot = go.GetLootForPlayer(this);
|
||||
|
||||
// loot was generated and respawntime has passed since then, allow to recreate loot
|
||||
// to avoid bugs, this rule covers spawned gameobjects only
|
||||
// Don't allow to regenerate chest loot inside instances and raids, to avoid exploits with duplicate boss loot being given for some encounters
|
||||
if (go.IsSpawnedByDefault() && go.GetLootState() == LootState.Activated && !go.loot.IsLooted() && !go.GetMap().Instanceable() && go.GetLootGenerationTime() + go.GetRespawnDelay() < GameTime.GetGameTime())
|
||||
if (go.IsSpawnedByDefault() && go.GetLootState() == LootState.Activated && (loot == null || loot.IsLooted()) && !go.GetMap().Instanceable() && go.GetLootGenerationTime() + go.GetRespawnDelay() < GameTime.GetGameTime())
|
||||
go.SetLootState(LootState.Ready);
|
||||
|
||||
if (go.GetLootState() == LootState.Ready)
|
||||
@@ -6189,6 +6203,13 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
loot = new Loot();
|
||||
loot.SetGUID(ObjectGuid.Create(HighGuid.LootObject, go.GetMapId(), 0, go.GetMap().GenerateLowGuid(HighGuid.LootObject)));
|
||||
if (go.GetMap().Is25ManRaid())
|
||||
loot.maxDuplicates = 3;
|
||||
|
||||
go.loot = loot;
|
||||
|
||||
if (lootid != 0)
|
||||
{
|
||||
loot.Clear();
|
||||
@@ -6204,7 +6225,7 @@ namespace Game.Entities
|
||||
go.SetLootGenerationTime();
|
||||
|
||||
// get next RR player (for next loot)
|
||||
if (groupRules)
|
||||
if (groupRules && !loot.Empty())
|
||||
group.UpdateLooterGuid(go);
|
||||
}
|
||||
|
||||
@@ -6277,14 +6298,16 @@ namespace Game.Entities
|
||||
|
||||
permission = PermissionTypes.Owner;
|
||||
|
||||
loot = item.loot;
|
||||
loot = item.GetLootForPlayer(this);
|
||||
|
||||
// If item doesn't already have loot, attempt to load it. If that
|
||||
// fails then this is first time opening, generate loot
|
||||
if (!item.m_lootGenerated && !Global.LootItemStorage.LoadStoredLoot(item, this))
|
||||
{
|
||||
item.m_lootGenerated = true;
|
||||
loot.Clear();
|
||||
loot = new Loot();
|
||||
loot.SetGUID(ObjectGuid.Create(HighGuid.LootObject, GetMapId(), 0, GetMap().GenerateLowGuid(HighGuid.LootObject)));
|
||||
item.loot = loot;
|
||||
|
||||
switch (loot_type)
|
||||
{
|
||||
@@ -6320,29 +6343,9 @@ namespace Game.Entities
|
||||
return;
|
||||
}
|
||||
|
||||
loot = bones.loot;
|
||||
loot = bones.GetLootForPlayer(this);
|
||||
|
||||
if (loot.loot_type == LootType.None)
|
||||
{
|
||||
uint pLevel = bones.loot.gold;
|
||||
bones.loot.Clear();
|
||||
|
||||
// For AV Achievement
|
||||
Battleground bg = GetBattleground();
|
||||
if (bg)
|
||||
{
|
||||
if (bg.GetTypeID(true) == BattlegroundTypeId.AV)
|
||||
loot.FillLoot(SharedConst.PlayerCorpseLootEntry, LootStorage.Creature, this, true);
|
||||
}
|
||||
else if (GetZoneId() == (uint)AreaId.Wintergrasp)
|
||||
loot.FillLoot(SharedConst.PlayerCorpseLootEntry, LootStorage.Creature, this, true);
|
||||
|
||||
// It may need a better formula
|
||||
// Now it works like this: lvl10: ~6copper, lvl70: ~9silver
|
||||
bones.loot.gold = (uint)(RandomHelper.URand(50, 150) * 0.016f * Math.Pow(pLevel / 5.76f, 2.5f) * WorldConfig.GetFloatValue(WorldCfg.RateDropMoney));
|
||||
}
|
||||
|
||||
if (bones.lootRecipient != this)
|
||||
if (bones.lootRecipient != null && bones.lootRecipient != this)
|
||||
permission = PermissionTypes.None;
|
||||
else
|
||||
permission = PermissionTypes.Owner;
|
||||
@@ -6364,7 +6367,7 @@ namespace Game.Entities
|
||||
return;
|
||||
}
|
||||
|
||||
loot = creature.loot;
|
||||
loot = creature.GetLootForPlayer(this);
|
||||
|
||||
if (loot_type == LootType.Pickpocketing)
|
||||
{
|
||||
@@ -6491,6 +6494,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
// need know merged fishing/corpse loot type for achievements
|
||||
if (loot != null)
|
||||
loot.loot_type = loot_type;
|
||||
|
||||
if (permission != PermissionTypes.None)
|
||||
@@ -6532,7 +6536,7 @@ namespace Game.Entities
|
||||
SetUnitFlag(UnitFlags.Looting);
|
||||
}
|
||||
else
|
||||
SendLootError(loot.GetGUID(), guid, LootError.DidntKill);
|
||||
SendLootError(loot != null ? loot.GetGUID() : ObjectGuid.Empty, guid, LootError.DidntKill);
|
||||
}
|
||||
|
||||
public void SendLootError(ObjectGuid lootObj, ObjectGuid owner, LootError error)
|
||||
|
||||
@@ -3085,8 +3085,8 @@ namespace Game.Entities
|
||||
if (HasPendingBind())
|
||||
return false;
|
||||
|
||||
Loot loot = creature.loot;
|
||||
if (loot.IsLooted()) // nothing to loot or everything looted.
|
||||
Loot loot = creature.GetLootForPlayer(this);
|
||||
if (loot == null || loot.IsLooted()) // nothing to loot or everything looted.
|
||||
return false;
|
||||
if (!loot.HasItemForAll() && !loot.HasItemFor(this)) // no loot in creature for this player
|
||||
return false;
|
||||
|
||||
@@ -772,23 +772,16 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
player.SendPacket(partyKillLog);
|
||||
|
||||
if (creature != null)
|
||||
{
|
||||
LootList lootList = new();
|
||||
lootList.Owner = creature.GetGUID();
|
||||
lootList.LootObj = creature.loot.GetGUID();
|
||||
player.SendMessageToSet(lootList, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (creature)
|
||||
{
|
||||
creature.loot = new Loot();
|
||||
Loot loot = creature.loot;
|
||||
loot.SetGUID(ObjectGuid.Create(HighGuid.LootObject, creature.GetMapId(), 0, creature.GetMap().GenerateLowGuid(HighGuid.LootObject)));
|
||||
if (creature.GetMap().Is25ManRaid())
|
||||
loot.maxDuplicates = 3;
|
||||
|
||||
loot.Clear();
|
||||
uint lootid = creature.GetCreatureTemplate().LootId;
|
||||
if (lootid != 0)
|
||||
loot.FillLoot(lootid, LootStorage.Creature, looter, false, false, creature.GetLootMode(), creature.GetMap().GetDifficultyLootItemContext());
|
||||
@@ -807,6 +800,13 @@ namespace Game.Entities
|
||||
if (!loot.Empty())
|
||||
group.UpdateLooterGuid(creature);
|
||||
}
|
||||
else
|
||||
{
|
||||
LootList lootList = new();
|
||||
lootList.Owner = creature.GetGUID();
|
||||
lootList.LootObj = creature.loot.GetGUID();
|
||||
player.SendMessageToSet(lootList, true);
|
||||
}
|
||||
}
|
||||
|
||||
player.RewardPlayerAndGroupAtKill(victim, false);
|
||||
@@ -907,7 +907,7 @@ namespace Game.Entities
|
||||
if (!creature.IsPet())
|
||||
{
|
||||
// must be after setDeathState which resets dynamic flags
|
||||
if (!creature.loot.IsLooted())
|
||||
if (creature.loot != null && !creature.loot.IsLooted())
|
||||
creature.SetDynamicFlag(UnitDynFlags.Lootable);
|
||||
else
|
||||
creature.AllLootRemovedFromCorpse();
|
||||
|
||||
@@ -2778,7 +2778,7 @@ namespace Game.Groups
|
||||
RaidMarker[] m_markers = new RaidMarker[MapConst.RaidMarkersCount];
|
||||
uint m_activeMarkers;
|
||||
|
||||
public static implicit operator bool (Group group)
|
||||
public static implicit operator bool(Group group)
|
||||
{
|
||||
return group != null;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace Game
|
||||
continue;
|
||||
}
|
||||
|
||||
loot = go.loot;
|
||||
loot = go.GetLootForPlayer(player);
|
||||
}
|
||||
else if (lguid.IsItem())
|
||||
{
|
||||
@@ -65,7 +65,7 @@ namespace Game
|
||||
continue;
|
||||
}
|
||||
|
||||
loot = pItem.loot;
|
||||
loot = pItem.GetLootForPlayer(player);
|
||||
}
|
||||
else if (lguid.IsCorpse())
|
||||
{
|
||||
@@ -76,20 +76,35 @@ namespace Game
|
||||
continue;
|
||||
}
|
||||
|
||||
loot = bones.loot;
|
||||
loot = bones.GetLootForPlayer(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
Creature creature = player.GetMap().GetCreature(lguid);
|
||||
|
||||
bool lootAllowed = creature && creature.IsAlive() == (player.GetClass() == Class.Rogue && creature.loot.loot_type == LootType.Pickpocketing);
|
||||
if (!lootAllowed || !creature.IsWithinDistInMap(player, AELootCreatureCheck.LootDistance))
|
||||
if (creature == null)
|
||||
{
|
||||
player.SendLootError(req.Object, lguid, lootAllowed ? LootError.TooFar : LootError.DidntKill);
|
||||
player.SendLootError(req.Object, lguid, LootError.NoLoot);
|
||||
continue;
|
||||
}
|
||||
|
||||
loot = creature.loot;
|
||||
if (!creature.IsWithinDistInMap(player, AELootCreatureCheck.LootDistance))
|
||||
{
|
||||
player.SendLootError(req.Object, lguid, LootError.TooFar);
|
||||
continue;
|
||||
}
|
||||
|
||||
loot = creature.GetLootForPlayer(player);
|
||||
if (creature.IsAlive() != (loot != null && loot.loot_type == LootType.Pickpocketing))
|
||||
{
|
||||
player.SendLootError(req.Object, lguid, LootError.DidntKill);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (loot == null)
|
||||
{
|
||||
player.SendLootRelease(lguid);
|
||||
continue;
|
||||
}
|
||||
|
||||
player.StoreLootItem(lguid, (byte)(req.LootListID - 1), loot, aeResult);
|
||||
@@ -132,7 +147,7 @@ namespace Game
|
||||
|
||||
// do not check distance for GO if player is the owner of it (ex. fishing bobber)
|
||||
if (go && (go.GetOwnerGUID() == player.GetGUID() || go.IsWithinDistInMap(player)))
|
||||
loot = go.loot;
|
||||
loot = go.GetLootForPlayer(player);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -142,7 +157,7 @@ namespace Game
|
||||
|
||||
if (bones && bones.IsWithinDistInMap(player, SharedConst.InteractionDistance))
|
||||
{
|
||||
loot = bones.loot;
|
||||
loot = bones.GetLootForPlayer(player);
|
||||
shareMoney = false;
|
||||
}
|
||||
|
||||
@@ -153,7 +168,7 @@ namespace Game
|
||||
Item item = player.GetItemByGuid(guid);
|
||||
if (item)
|
||||
{
|
||||
loot = item.loot;
|
||||
loot = item.GetLootForPlayer(player);
|
||||
shareMoney = false;
|
||||
}
|
||||
break;
|
||||
@@ -162,15 +177,27 @@ namespace Game
|
||||
case HighGuid.Vehicle:
|
||||
{
|
||||
Creature creature = player.GetMap().GetCreature(guid);
|
||||
bool lootAllowed = creature && creature.IsAlive() == (player.GetClass() == Class.Rogue && creature.loot.loot_type == LootType.Pickpocketing);
|
||||
if (lootAllowed && creature.IsWithinDistInMap(player, AELootCreatureCheck.LootDistance))
|
||||
if (creature == null)
|
||||
{
|
||||
loot = creature.loot;
|
||||
if (creature.IsAlive())
|
||||
shareMoney = false;
|
||||
player.SendLootError(lootView.Key, guid, LootError.NoLoot);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
player.SendLootError(lootView.Key, guid, lootAllowed ? LootError.TooFar : LootError.DidntKill);
|
||||
|
||||
if (!creature.IsWithinDistInMap(player, AELootCreatureCheck.LootDistance))
|
||||
{
|
||||
player.SendLootError(lootView.Key, guid, LootError.TooFar);
|
||||
continue;
|
||||
}
|
||||
|
||||
loot = creature.GetLootForPlayer(player);
|
||||
if (creature.IsAlive() != (loot != null && loot.loot_type == LootType.Pickpocketing))
|
||||
{
|
||||
player.SendLootError(lootView.Key, guid, LootError.DidntKill);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (loot != null && loot.loot_type != LootType.Corpse)
|
||||
shareMoney = false;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -336,7 +363,7 @@ namespace Game
|
||||
if (!go || ((go.GetOwnerGUID() != player.GetGUID() && go.GetGoType() != GameObjectTypes.FishingHole) && !go.IsWithinDistInMap(player)))
|
||||
return;
|
||||
|
||||
loot = go.loot;
|
||||
loot = go.GetLootForPlayer(player);
|
||||
|
||||
if (go.GetGoType() == GameObjectTypes.Door)
|
||||
{
|
||||
@@ -374,9 +401,9 @@ namespace Game
|
||||
if (!corpse || !corpse.IsWithinDistInMap(player, SharedConst.InteractionDistance))
|
||||
return;
|
||||
|
||||
loot = corpse.loot;
|
||||
loot = corpse.GetLootForPlayer(player);
|
||||
|
||||
if (loot.IsLooted())
|
||||
if (loot != null && loot.IsLooted())
|
||||
{
|
||||
loot.Clear();
|
||||
corpse.RemoveCorpseDynamicFlag(CorpseDynFlags.Lootable);
|
||||
@@ -390,11 +417,13 @@ namespace Game
|
||||
|
||||
ItemTemplate proto = pItem.GetTemplate();
|
||||
|
||||
loot = pItem.GetLootForPlayer(player);
|
||||
|
||||
// destroy only 5 items from stack in case prospecting and milling
|
||||
if (pItem.loot.loot_type == LootType.Prospecting || pItem.loot.loot_type == LootType.Milling)
|
||||
if (loot != null && (loot.loot_type == LootType.Prospecting || loot.loot_type == LootType.Milling))
|
||||
{
|
||||
pItem.m_lootGenerated = false;
|
||||
pItem.loot.Clear();
|
||||
pItem.loot = null;
|
||||
|
||||
uint count = pItem.GetCount();
|
||||
|
||||
@@ -406,7 +435,8 @@ namespace Game
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pItem.loot.IsLooted() || !proto.HasFlag(ItemFlags.HasLoot)) // Only delete item if no loot or money (unlooted loot is saved to db)
|
||||
// Only delete item if no loot or money (unlooted loot is saved to db) or if it isn't an openable item
|
||||
if ((loot != null && loot.IsLooted()) || !proto.HasFlag(ItemFlags.HasLoot))
|
||||
player.DestroyItem(pItem.GetBagSlot(), pItem.GetSlot(), true);
|
||||
}
|
||||
return; // item can be looted only single player
|
||||
@@ -414,21 +444,23 @@ namespace Game
|
||||
else
|
||||
{
|
||||
Creature creature = player.GetMap().GetCreature(lguid);
|
||||
|
||||
bool lootAllowed = creature && creature.IsAlive() == (player.GetClass() == Class.Rogue && creature.loot.loot_type == LootType.Pickpocketing);
|
||||
if (!lootAllowed || !creature.IsWithinDistInMap(player, AELootCreatureCheck.LootDistance))
|
||||
if (creature == null)
|
||||
return;
|
||||
|
||||
loot = creature.loot;
|
||||
if (loot.IsLooted())
|
||||
if (!creature.IsWithinDistInMap(player, AELootCreatureCheck.LootDistance))
|
||||
return;
|
||||
|
||||
loot = creature.GetLootForPlayer(player);
|
||||
if (creature.IsAlive() != (loot != null && loot.loot_type == LootType.Pickpocketing))
|
||||
return;
|
||||
|
||||
if (loot == null || loot.IsLooted())
|
||||
{
|
||||
creature.RemoveDynamicFlag(UnitDynFlags.Lootable);
|
||||
|
||||
// skip pickpocketing loot for speed, skinning timer reduction is no-op in fact
|
||||
if (!creature.IsAlive())
|
||||
creature.AllLootRemovedFromCorpse();
|
||||
|
||||
loot.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -451,6 +483,7 @@ namespace Game
|
||||
}
|
||||
|
||||
//Player is not looking at loot list, he doesn't need to see updates on the loot list
|
||||
if (loot != null)
|
||||
loot.RemoveLooter(player.GetGUID());
|
||||
}
|
||||
|
||||
@@ -498,15 +531,15 @@ namespace Game
|
||||
if (!creature)
|
||||
return;
|
||||
|
||||
loot = creature.loot;
|
||||
loot = creature.GetLootForPlayer(_player);
|
||||
}
|
||||
else if (GetPlayer().GetLootGUID().IsGameObject())
|
||||
{
|
||||
GameObject pGO = GetPlayer().GetMap().GetGameObject(lootguid);
|
||||
if (!pGO)
|
||||
GameObject go = GetPlayer().GetMap().GetGameObject(lootguid);
|
||||
if (!go)
|
||||
return;
|
||||
|
||||
loot = pGO.loot;
|
||||
loot = go.GetLootForPlayer(_player);
|
||||
}
|
||||
|
||||
if (loot == null)
|
||||
|
||||
@@ -165,9 +165,9 @@ namespace Game.Loots
|
||||
|
||||
public class Loot
|
||||
{
|
||||
public Loot(uint _gold = 0)
|
||||
public Loot()
|
||||
{
|
||||
gold = _gold;
|
||||
gold = 0;
|
||||
unlootedCount = 0;
|
||||
loot_type = LootType.None;
|
||||
maxDuplicates = 1;
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace Game.Loots
|
||||
|
||||
public bool LoadStoredLoot(Item item, Player player)
|
||||
{
|
||||
Loot loot = item.loot;
|
||||
Loot loot = item.GetLootForPlayer(player);
|
||||
if (!_lootItemStorage.ContainsKey(item.GetGUID().GetCounter()))
|
||||
return false;
|
||||
|
||||
|
||||
@@ -5187,7 +5187,8 @@ namespace Game.Spells
|
||||
return SpellCastResult.TargetUnskinnable;
|
||||
|
||||
Creature creature = m_targets.GetUnitTarget().ToCreature();
|
||||
if (!creature.IsCritter() && !creature.loot.IsLooted())
|
||||
Loot loot = creature.GetLootForPlayer(m_caster.ToPlayer());
|
||||
if (loot != null && !loot.IsLooted())
|
||||
return SpellCastResult.TargetNotLooted;
|
||||
|
||||
SkillType skill = creature.GetCreatureTemplate().GetRequiredLootSkill();
|
||||
|
||||
Reference in New Issue
Block a user