Updated to 8.2.0.31429 (scripts disabled atm, they still need updated)
Code Port from TrinityCore https://github.com/TrinityCore/TrinityCore Casc from WoW-Tools https://github.com/WoW-Tools/CASCExplorer
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Game.Network;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
@@ -27,8 +28,7 @@ namespace Game.Entities
|
||||
objectTypeMask |= TypeMask.Container;
|
||||
objectTypeId = TypeId.Container;
|
||||
|
||||
valuesCount = (int)ContainerFields.End;
|
||||
_dynamicValuesCount = (int)ItemDynamicFields.End;
|
||||
m_containerData = new ContainerData();
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
@@ -86,20 +86,20 @@ namespace Game.Entities
|
||||
|
||||
if (owner)
|
||||
{
|
||||
SetGuidValue(ItemFields.Owner, owner.GetGUID());
|
||||
SetGuidValue(ItemFields.Contained, owner.GetGUID());
|
||||
SetOwnerGUID(owner.GetGUID());
|
||||
SetContainedIn(owner.GetGUID());
|
||||
}
|
||||
|
||||
SetUInt32Value(ItemFields.MaxDurability, itemProto.MaxDurability);
|
||||
SetUInt32Value(ItemFields.Durability, itemProto.MaxDurability);
|
||||
SetUInt32Value(ItemFields.StackCount, 1);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.MaxDurability), itemProto.MaxDurability);
|
||||
SetDurability(itemProto.MaxDurability);
|
||||
SetCount(1);
|
||||
|
||||
// Setting the number of Slots the Container has
|
||||
SetUInt32Value(ContainerFields.NumSlots, itemProto.GetContainerSlots());
|
||||
SetBagSize(itemProto.GetContainerSlots());
|
||||
|
||||
// Cleaning 20 slots
|
||||
for (byte i = 0; i < ItemConst.MaxBagSize; ++i)
|
||||
SetGuidValue(ContainerFields.Slot1 + (i * 4), ObjectGuid.Empty);
|
||||
SetSlot(i, ObjectGuid.Empty);
|
||||
|
||||
m_bagslot = new Item[ItemConst.MaxBagSize];
|
||||
return true;
|
||||
@@ -111,11 +111,11 @@ namespace Game.Entities
|
||||
return false;
|
||||
|
||||
ItemTemplate itemProto = GetTemplate(); // checked in Item.LoadFromDB
|
||||
SetUInt32Value(ContainerFields.NumSlots, itemProto.GetContainerSlots());
|
||||
SetBagSize(itemProto.GetContainerSlots());
|
||||
// cleanup bag content related item value fields (its will be filled correctly from `character_inventory`)
|
||||
for (byte i = 0; i < ItemConst.MaxBagSize; ++i)
|
||||
{
|
||||
SetGuidValue(ContainerFields.Slot1 + (i * 4), ObjectGuid.Empty);
|
||||
SetSlot(i, ObjectGuid.Empty);
|
||||
m_bagslot[i] = null;
|
||||
}
|
||||
return true;
|
||||
@@ -144,9 +144,9 @@ namespace Game.Entities
|
||||
{
|
||||
if (m_bagslot[slot] != null)
|
||||
m_bagslot[slot].SetContainer(null);
|
||||
|
||||
|
||||
m_bagslot[slot] = null;
|
||||
SetGuidValue(ContainerFields.Slot1 + (slot * 4), ObjectGuid.Empty);
|
||||
SetSlot(slot, ObjectGuid.Empty);
|
||||
}
|
||||
|
||||
public void StoreItem(byte slot, Item pItem, bool update)
|
||||
@@ -154,9 +154,9 @@ namespace Game.Entities
|
||||
if (pItem != null && pItem.GetGUID() != GetGUID())
|
||||
{
|
||||
m_bagslot[slot] = pItem;
|
||||
SetGuidValue(ContainerFields.Slot1 + (slot * 4), pItem.GetGUID());
|
||||
pItem.SetGuidValue(ItemFields.Contained, GetGUID());
|
||||
pItem.SetGuidValue(ItemFields.Owner, GetOwnerGUID());
|
||||
SetSlot(slot, pItem.GetGUID());
|
||||
pItem.SetContainedIn(GetGUID());
|
||||
pItem.SetOwnerGUID(GetOwnerGUID());
|
||||
pItem.SetContainer(this);
|
||||
pItem.SetSlot(slot);
|
||||
}
|
||||
@@ -171,6 +171,45 @@ namespace Game.Entities
|
||||
m_bagslot[i].BuildCreateUpdateBlockForPlayer(data, target);
|
||||
}
|
||||
|
||||
public override void BuildValuesCreate(WorldPacket data, Player target)
|
||||
{
|
||||
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
|
||||
WorldPacket buffer = new WorldPacket();
|
||||
|
||||
buffer.WriteUInt8((byte)flags);
|
||||
m_objectData.WriteCreate(buffer, flags, this, target);
|
||||
m_itemData.WriteCreate(buffer, flags, this, target);
|
||||
m_containerData.WriteCreate(buffer, flags, this, target);
|
||||
|
||||
data.WriteUInt32(buffer.GetSize());
|
||||
data.WriteBytes(buffer);
|
||||
}
|
||||
|
||||
public override void BuildValuesUpdate(WorldPacket data, Player target)
|
||||
{
|
||||
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
|
||||
WorldPacket buffer = new WorldPacket();
|
||||
|
||||
buffer.WriteUInt32(m_values.GetChangedObjectTypeMask());
|
||||
if (m_values.HasChanged(TypeId.Object))
|
||||
m_objectData.WriteUpdate(buffer, flags, this, target);
|
||||
|
||||
if (m_values.HasChanged(TypeId.Item))
|
||||
m_itemData.WriteUpdate(buffer, flags, this, target);
|
||||
|
||||
if (m_values.HasChanged(TypeId.Container))
|
||||
m_containerData.WriteUpdate(buffer, flags, this, target);
|
||||
|
||||
data.WriteUInt32(buffer.GetSize());
|
||||
data.WriteBytes(buffer);
|
||||
}
|
||||
|
||||
public override void ClearUpdateMask(bool remove)
|
||||
{
|
||||
m_values.ClearChangesMask(m_containerData);
|
||||
base.ClearUpdateMask(remove);
|
||||
}
|
||||
|
||||
public bool IsEmpty()
|
||||
{
|
||||
for (var i = 0; i < GetBagSize(); ++i)
|
||||
@@ -243,13 +282,17 @@ namespace Game.Entities
|
||||
return null;
|
||||
}
|
||||
|
||||
public uint GetBagSize() { return GetUInt32Value(ContainerFields.NumSlots); }
|
||||
public uint GetBagSize() { return m_containerData.NumSlots; }
|
||||
void SetBagSize(uint numSlots) { SetUpdateFieldValue(m_values.ModifyValue(m_containerData).ModifyValue(m_containerData.NumSlots), numSlots); }
|
||||
|
||||
void SetSlot(int slot, ObjectGuid guid) { SetUpdateFieldValue(ref m_values.ModifyValue(m_containerData).ModifyValue(m_containerData.Slots, slot), guid); }
|
||||
|
||||
public static Item NewItemOrBag(ItemTemplate proto)
|
||||
{
|
||||
return (proto.GetInventoryType() == InventoryType.Bag) ? new Bag() : new Item();
|
||||
}
|
||||
|
||||
ContainerData m_containerData;
|
||||
Item[] m_bagslot = new Item[36];
|
||||
}
|
||||
}
|
||||
|
||||
+381
-356
File diff suppressed because it is too large
Load Diff
@@ -22,148 +22,79 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
public class ItemEnchantment
|
||||
public class ItemEnchantmentManager
|
||||
{
|
||||
static ItemEnchantment()
|
||||
public static void LoadItemRandomBonusListTemplates()
|
||||
{
|
||||
RandomItemEnch = new EnchantmentStore();
|
||||
}
|
||||
uint oldMSTime = Time.GetMSTime();
|
||||
|
||||
public static void LoadRandomEnchantmentsTable()
|
||||
{
|
||||
// for reload case
|
||||
RandomItemEnch[ItemRandomEnchantmentType.Property].Clear();
|
||||
RandomItemEnch[ItemRandomEnchantmentType.Suffix].Clear();
|
||||
_storage.Clear();
|
||||
|
||||
// 0 1 2 3
|
||||
SQLResult result = DB.World.Query("SELECT entry, type, ench, chance FROM item_enchantment_template");
|
||||
// 0 1 2
|
||||
SQLResult result = DB.World.Query("SELECT Id, BonusListID, Chance FROM item_random_bonus_list_template");
|
||||
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
Log.outError(LogFilter.Player, "Loaded 0 Item Enchantment definitions. DB table `item_enchantment_template` is empty.");
|
||||
return;
|
||||
}
|
||||
uint count = 0;
|
||||
|
||||
do
|
||||
{
|
||||
uint entry = result.Read<uint>(0);
|
||||
ItemRandomEnchantmentType type = (ItemRandomEnchantmentType)result.Read<byte>(1);
|
||||
uint ench = result.Read<uint>(2);
|
||||
float chance = result.Read<float>(3);
|
||||
uint id = result.Read<uint>(0);
|
||||
uint bonusListId = result.Read<uint>(1);
|
||||
float chance = result.Read<float>(2);
|
||||
|
||||
switch (type)
|
||||
if (Global.DB2Mgr.GetItemBonusList(bonusListId) == null)
|
||||
{
|
||||
case ItemRandomEnchantmentType.Property:
|
||||
if (!CliDB.ItemRandomPropertiesStorage.ContainsKey(ench))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Property {0} used in `item_enchantment_template` by entry {1} doesn't have exist in ItemRandomProperties.db2", ench, entry);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case ItemRandomEnchantmentType.Suffix:
|
||||
if (!CliDB.ItemRandomSuffixStorage.ContainsKey(ench))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Suffix {0} used in `item_enchantment_template` by entry {1} doesn't have exist in ItemRandomSuffix.db2", ench, entry);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case ItemRandomEnchantmentType.BonusList:
|
||||
if (Global.DB2Mgr.GetItemBonusList(ench) == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Bonus list {0} used in `item_enchantment_template` by entry {1} doesn't have exist in ItemBonus.db2", ench, entry);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.outError(LogFilter.Sql, "Invalid random enchantment type specified in `item_enchantment_template` table for `entry` {0} `ench` {1}", entry, ench);
|
||||
break;
|
||||
Log.outError(LogFilter.Sql, $"Bonus list {bonusListId} used in `item_random_bonus_list_template` by id {id} doesn't have exist in ItemBonus.db2");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (chance < 0.000001f || chance > 100.0f)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Random item enchantment for entry {0} type {1} ench {2} has invalid chance {3}", entry, type, ench, chance);
|
||||
Log.outError(LogFilter.Sql, $"Bonus list {bonusListId} used in `item_random_bonus_list_template` by id {id} has invalid chance {chance}");
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ItemRandomEnchantmentType.Property:
|
||||
RandomItemEnch[ItemRandomEnchantmentType.Property].Add(entry, new EnchStoreItem(type, ench, chance));
|
||||
break;
|
||||
case ItemRandomEnchantmentType.Suffix:
|
||||
case ItemRandomEnchantmentType.BonusList: // random bonus lists use RandomSuffix field in Item-sparse.db2
|
||||
RandomItemEnch[ItemRandomEnchantmentType.Suffix].Add(entry, new EnchStoreItem(type, ench, chance));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!_storage.ContainsKey(id))
|
||||
_storage[id] = new RandomBonusListIds();
|
||||
|
||||
RandomBonusListIds ids = _storage[id];
|
||||
ids.BonusListIDs.Add(bonusListId);
|
||||
ids.Chances.Add(chance);
|
||||
|
||||
++count;
|
||||
} while (result.NextRow());
|
||||
|
||||
Log.outInfo(LogFilter.Player, "Loaded {0} Item Enchantment definitions", count);
|
||||
Log.outInfo(LogFilter.Player, $"Loaded {count} Random item bonus list definitions in {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
|
||||
}
|
||||
|
||||
public static ItemRandomEnchantmentId GetItemEnchantMod(int entry, ItemRandomEnchantmentType type)
|
||||
{
|
||||
if (entry == 0)
|
||||
return ItemRandomEnchantmentId.Empty;
|
||||
|
||||
if (entry == -1)
|
||||
return ItemRandomEnchantmentId.Empty;
|
||||
|
||||
var tab = RandomItemEnch[type].LookupByKey(entry);
|
||||
if (tab == null)
|
||||
{
|
||||
Log.outError(LogFilter.Player, "Item RandomProperty / RandomSuffix id #{0} used in `item_template` but it does not have records in `item_enchantment_template` table.", entry);
|
||||
return ItemRandomEnchantmentId.Empty;
|
||||
}
|
||||
|
||||
var selectedItem = tab.SelectRandomElementByWeight(enchant => enchant.chance);
|
||||
|
||||
return new ItemRandomEnchantmentId(selectedItem.type, selectedItem.ench);
|
||||
}
|
||||
|
||||
public static ItemRandomEnchantmentId GenerateItemRandomPropertyId(uint item_id)
|
||||
public static uint GenerateItemRandomBonusListId(uint item_id)
|
||||
{
|
||||
ItemTemplate itemProto = Global.ObjectMgr.GetItemTemplate(item_id);
|
||||
if (itemProto == null)
|
||||
return ItemRandomEnchantmentId.Empty;
|
||||
return 0;
|
||||
|
||||
// item must have one from this field values not null if it can have random enchantments
|
||||
if (itemProto.GetRandomProperty() == 0 && itemProto.GetRandomSuffix() == 0)
|
||||
return ItemRandomEnchantmentId.Empty;
|
||||
if (itemProto.RandomBonusListTemplateId == 0)
|
||||
return 0;
|
||||
|
||||
// item can have not null only one from field values
|
||||
if (itemProto.GetRandomProperty() != 0 && itemProto.GetRandomSuffix() != 0)
|
||||
var tab = _storage.LookupByKey(itemProto.RandomBonusListTemplateId);
|
||||
if (tab == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Item template {0} have RandomProperty == {1} and RandomSuffix == {2}, but must have one from field =0", itemProto.GetId(), itemProto.GetRandomProperty(), itemProto.GetRandomSuffix());
|
||||
return ItemRandomEnchantmentId.Empty;
|
||||
Log.outError(LogFilter.Sql, $"Item RandomBonusListTemplateId id {itemProto.RandomBonusListTemplateId} used in `item_template_addon` but it does not have records in `item_random_bonus_list_template` table.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// RandomProperty case
|
||||
if (itemProto.GetRandomProperty() != 0)
|
||||
return GetItemEnchantMod((int)itemProto.GetRandomProperty(), ItemRandomEnchantmentType.Property);
|
||||
// RandomSuffix case
|
||||
else
|
||||
return GetItemEnchantMod((int)itemProto.GetRandomSuffix(), ItemRandomEnchantmentType.Suffix);
|
||||
}
|
||||
|
||||
public static uint GenerateEnchSuffixFactor(uint item_id)
|
||||
{
|
||||
ItemTemplate itemProto = Global.ObjectMgr.GetItemTemplate(item_id);
|
||||
|
||||
if (itemProto == null)
|
||||
return 0;
|
||||
if (itemProto.GetRandomSuffix() == 0)
|
||||
return 0;
|
||||
|
||||
return GetRandomPropertyPoints(itemProto.GetBaseItemLevel(), itemProto.GetQuality(), itemProto.GetInventoryType(), itemProto.GetSubClass());
|
||||
//todo fix me this is ulgy
|
||||
return tab.BonusListIDs.SelectRandomElementByWeight(x => (float)tab.Chances[tab.BonusListIDs.IndexOf(x)]);
|
||||
}
|
||||
|
||||
public static uint GetRandomPropertyPoints(uint itemLevel, ItemQuality quality, InventoryType inventoryType, uint subClass)
|
||||
{
|
||||
{
|
||||
uint propIndex;
|
||||
|
||||
switch (inventoryType)
|
||||
{
|
||||
case InventoryType.Head:
|
||||
@@ -208,11 +139,11 @@ namespace Game.Entities
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
RandPropPointsRecord randPropPointsEntry = CliDB.RandPropPointsStorage.LookupByKey(itemLevel);
|
||||
if (randPropPointsEntry == null)
|
||||
return 0;
|
||||
|
||||
// Select rare/epic modifier
|
||||
switch (quality)
|
||||
{
|
||||
case ItemQuality.Uncommon:
|
||||
@@ -225,69 +156,16 @@ namespace Game.Entities
|
||||
case ItemQuality.Artifact:
|
||||
return randPropPointsEntry.Epic[propIndex];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static EnchantmentStore RandomItemEnch;
|
||||
|
||||
public class EnchStoreItem
|
||||
{
|
||||
public EnchStoreItem()
|
||||
{
|
||||
ench = 0;
|
||||
chance = 0;
|
||||
}
|
||||
public EnchStoreItem(ItemRandomEnchantmentType _type, uint _ench, float _chance)
|
||||
{
|
||||
type = _type;
|
||||
ench = _ench;
|
||||
chance = _chance;
|
||||
}
|
||||
|
||||
public ItemRandomEnchantmentType type;
|
||||
public uint ench;
|
||||
public float chance;
|
||||
}
|
||||
|
||||
class EnchantmentStore
|
||||
{
|
||||
public EnchantmentStore()
|
||||
{
|
||||
_data[(byte)ItemRandomEnchantmentType.Property] = new MultiMap<uint, EnchStoreItem>();
|
||||
_data[(byte)ItemRandomEnchantmentType.Suffix] = new MultiMap<uint, EnchStoreItem>();
|
||||
}
|
||||
|
||||
public MultiMap<uint, EnchStoreItem> this[ItemRandomEnchantmentType type]
|
||||
{
|
||||
get
|
||||
{
|
||||
//(type != ItemRandomEnchantmentType.BonusList, "Random bonus lists do not have their own storage, use Suffix for them");
|
||||
return _data[(byte)type];
|
||||
}
|
||||
}
|
||||
|
||||
MultiMap<uint, EnchStoreItem>[] _data = new MultiMap<uint, EnchStoreItem>[2];
|
||||
}
|
||||
static Dictionary<uint, RandomBonusListIds> _storage = new Dictionary<uint, RandomBonusListIds>();
|
||||
}
|
||||
|
||||
public struct ItemRandomEnchantmentId
|
||||
public class RandomBonusListIds
|
||||
{
|
||||
public static ItemRandomEnchantmentId Empty = default(ItemRandomEnchantmentId);
|
||||
|
||||
public ItemRandomEnchantmentId(ItemRandomEnchantmentType type, uint id)
|
||||
{
|
||||
Type = type;
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public ItemRandomEnchantmentType Type;
|
||||
public uint Id;
|
||||
}
|
||||
|
||||
public enum ItemRandomEnchantmentType
|
||||
{
|
||||
Property = 0,
|
||||
Suffix = 1,
|
||||
BonusList = 2
|
||||
public List<uint> BonusListIDs = new List<uint>();
|
||||
public List<double> Chances = new List<double>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,9 +223,9 @@ namespace Game.Entities
|
||||
if (GetFlags().HasAnyFlag(ItemFlags.IsBoundToAccount) && alwaysAllowBoundToAccount)
|
||||
return true;
|
||||
|
||||
uint spec = player.GetUInt32Value(ActivePlayerFields.LootSpecId);
|
||||
uint spec = player.GetLootSpecId();
|
||||
if (spec == 0)
|
||||
spec = player.GetUInt32Value(PlayerFields.CurrentSpecId);
|
||||
spec = player.GetPrimarySpecialization();
|
||||
if (spec == 0)
|
||||
spec = player.GetDefaultSpecId();
|
||||
|
||||
@@ -295,8 +295,6 @@ namespace Game.Entities
|
||||
public uint GetPageText() { return ExtendedData.PageID; }
|
||||
public uint GetStartQuest() { return ExtendedData.StartQuestID; }
|
||||
public uint GetLockID() { return ExtendedData.LockID; }
|
||||
public uint GetRandomProperty() { return ExtendedData.RandomSelect; }
|
||||
public uint GetRandomSuffix() { return ExtendedData.ItemRandomSuffixGroupID; }
|
||||
public uint GetItemSet() { return ExtendedData.ItemSet; }
|
||||
public uint GetArea() { return ExtendedData.ZoneBound; }
|
||||
public uint GetMap() { return ExtendedData.InstanceBound; }
|
||||
@@ -345,6 +343,7 @@ namespace Game.Entities
|
||||
public uint MaxMoneyLoot;
|
||||
public ItemFlagsCustom FlagsCu;
|
||||
public float SpellPPMRate;
|
||||
public uint RandomBonusListTemplateId;
|
||||
public BitArray[] Specializations = new BitArray[3];
|
||||
public uint ItemSpecClassMask;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user