rendered paste body{
this.action = (ItemActionType) data[1];
this.category = (ItemCategory) data[3];
this.uid = BitConverter.ToUInt32(data, 4);
int pOffset = data[0] == 0x9d ? 13 : 8;
this.flags = (ItemFlag) BitConverter.ToUInt32(data, pOffset);
//TODO: figure if there's more info in there
this.version = (GameVersion) data[pOffset += 4];
pOffset++;
if (this.action == ItemActionType.AddToGround
|| this.action == ItemActionType.DropToGround
|| this.action == ItemActionType.OnGround)
{
this.x = BitConverter.ToUInt16(data, pOffset);
this.y = BitConverter.ToUInt16(data, pOffset += 2);
//TODO: change to walk coords
// converting these coordinates:
// P: coordinate from packet; W: walking coordinate; c: constant
// 32*W + c == P
// I just took a look at it on the fly, will examine that later, but for
// now a good value for c seems to be -131028 (got that from the first calculation and
// it works fine... maximum difference I got between the calculated coordinates
// and the ones I took from Packet 0x03 was around 10 walking coordinate units)
// I guess the constant will be c = -131072 = -2^17... that would make more sense.
pOffset += 2;
//TODO: Unknown bit
pOffset = pOffset * 8 + 1;
this.container = (ItemContainer) ByteConverter.GetBits(data, ref pOffset, 4);
}
else
{
this.container = (ItemContainer) (data[pOffset+2] & 0x0F);
pOffset = pOffset * 8;
this.destination = (ItemDestination) ByteConverter.GetBits(data, ref pOffset, 5);
this.location = (EquipmentLocation) ByteConverter.GetBits(data, ref pOffset, 4);
this.x = (ushort) ByteConverter.GetBits(data, ref pOffset, 4);
this.y = (ushort) ByteConverter.GetBits(data, ref pOffset, 3);
//TODO: Unknown nibble
pOffset += 4;
}
if ((this.flags & ItemFlag.Ear) == ItemFlag.Ear)
{
this.baseItem = BaseItem.Get(BaseItems.Ear);
this.charClass = (CharacterClass) ByteConverter.GetBits(data, ref pOffset, 3);
this.level = (ushort) ByteConverter.GetBits(data, ref pOffset, 7);
System.Text.StringBuilder builder = new System.Text.StringBuilder();
int mChar;
while ((mChar = ByteConverter.GetBits(data, ref pOffset, 7)) != 0)
builder.Append((char) mChar);
this.name = builder.ToString();
return;
}
this.baseItem = BaseItem.GetByCode(this.category, String.Concat(
(char) ByteConverter.GetBits(data, ref pOffset, 8),
(char) ByteConverter.GetBits(data, ref pOffset, 8),
(char) ByteConverter.GetBits(data, ref pOffset, 8)
));
//TODO: Unknown nibble
pOffset += 4;
if (this.baseItem.Id == BaseItems.Gold)
{
// TODO: haven't tried yet to figure out what this is
//ByteConverter.GetBits(data, pOffset, 4);
pOffset += 4;
// 1 indicates that we have a big pile of gold
// This might not be the 100% correct number of bits but it works correctly as long as
// it just is "ordinary" gold (perhaps there are mods out there with "uber gold" or s.th. like that^^)
if (ByteConverter.GetBits(data, ref pOffset, 1) == 1)
this.quantity = ByteConverter.GetBits(data, ref pOffset, 20);
else
this.quantity = ByteConverter.GetBits(data, ref pOffset, 18);
this.offset = pOffset;
return;
}
// Buffer to container mapping (sanitize NPC tabs IDs and coords, changed belt location to X, Y, etc.)
if ((this.flags & ItemFlag.InStore) == ItemFlag.InStore // Flag is not always set for shop items !?!
|| this.action == ItemActionType.AddToShop || this.action == ItemActionType.RemoveFromShop)
{
int buff = (int)this.container | 0x80;
if (this.y < 2 && (buff == 0x83 || buff == 0x85 || buff == 0x89))
{
buff -= 1;
this.y += 8;
}
this.container = (ItemContainer) buff;
}
else if (this.container == ItemContainer.Equipment)
{
if (this.location == EquipmentLocation.NotApplicable)
{
if ((this.Flags & ItemFlag.InSocket) == ItemFlag.InSocket)
this.container = ItemContainer.Item;
else
{
this.container = ItemContainer.Belt;
this.y = this.x / 4;
this.x = this.x % 4;
}
}
else
{ // Hides them in dump... not needed anyway
this.y = -1;
this.x = -1;
}
}
// TODO: I don't know what this is (always 2 ??)
this.unknown1 = (byte) ByteConverter.GetBits(data, ref pOffset, 4);
// Used Sockets : 3
if ((this.flags & ItemFlag.Socketed) == ItemFlag.Socketed)
this.usedSockets = (byte) ByteConverter.GetBits(data, pOffset, 3);
pOffset += 3;
// Ends here if Simple or Gamble Item
if ((this.flags & ItemFlag.SimpleItem) == ItemFlag.SimpleItem
|| (this.flags & ItemFlag.Gamble) == ItemFlag.Gamble)
{
this.offset = pOffset;
return;
}
// ILevel : 7
this.level = (byte) ByteConverter.GetBits(data, ref pOffset, 7);
// Quality : 4
this.quality = (ItemQuality) ByteConverter.GetBits(data, ref pOffset, 4);
// Graphic : 1 : 3
if (ByteConverter.GetBits(data, ref pOffset, 1) == 1)
this.graphic = ByteConverter.GetBits(data, ref pOffset, 3);
//TODO: ClassInfo : 1 : 11
if (ByteConverter.GetBits(data, ref pOffset, 1) == 1)
this.classInfo = ByteConverter.GetBits(data, ref pOffset, 11);
// Quality information
if ((this.flags & ItemFlag.Identified) == ItemFlag.Identified)
{
switch(this.quality)
{
case ItemQuality.Inferior:
this.prefix = new ItemAffix(ItemAffixType.InferiorPrefix,
ByteConverter.GetBits(data, ref pOffset, 3));
break;
case ItemQuality.Superior:
this.prefix = new ItemAffix(ItemAffixType.SuperiorPrefix, 0);
//TODO: quality type ? whether to show prefix (e.g. off for runewords) ?
pOffset += 3;
break;
case ItemQuality.Magic:
this.prefix = new ItemAffix(ItemAffixType.MagicPrefix,
ByteConverter.GetBits(data, ref pOffset, 11));
this.suffix = new ItemAffix(ItemAffixType.MagicSuffix,
ByteConverter.GetBits(data, ref pOffset, 11));
break;
case ItemQuality.Rare:
case ItemQuality.Crafted:
this.prefix = new ItemAffix(ItemAffixType.RarePrefix,
ByteConverter.GetBits(data, ref pOffset, 8));
this.suffix = new ItemAffix(ItemAffixType.RareSuffix,
ByteConverter.GetBits(data, ref pOffset, 8));
for (int i=0; i < 3; i++)
{
if (ByteConverter.GetBits(data, ref pOffset, 1) == 1)
this.magicPrefixes[i] = new ItemAffix(ItemAffixType.MagicPrefix,
ByteConverter.GetBits(data, ref pOffset, 11));
if (ByteConverter.GetBits(data, ref pOffset, 1) == 1 )
this.magicSuffixes[i] = new ItemAffix(ItemAffixType.MagicSuffix,
ByteConverter.GetBits(data, ref pOffset, 11));
}
break;
case ItemQuality.Set:
case ItemQuality.Unique:
//TODO: unique set id
ByteConverter.GetBits(data, ref pOffset, 12);
break;
}
}
// Personalized Name : 7 * (NULLSTRING Length)
if ((this.Flags & ItemFlag.Personalized) == ItemFlag.Personalized)
{
System.Text.StringBuilder builder = new System.Text.StringBuilder();
int mChar;
while ((mChar = ByteConverter.GetBits(data, ref pOffset, 7)) != 0)
builder.Append((char) mChar);
this.name = builder.ToString();
}
// Runeword Info : 16
if ((this.Flags & ItemFlag.Runeword) == ItemFlag.Runeword)
{
//TODO: runeword id
ByteConverter.GetBits(data, ref pOffset, 12);
//UNKNOWN: this might also be the number of stat's the current set hold? (read this somewhere)
//this.extraMods = (int)
ByteConverter.GetBits(data, ref pOffset, 4);
}
// Defense : 11
if (this.baseItem is BaseArmor)
this.defense = ByteConverter.GetBits(data, ref pOffset, 11) - 10;
//if (this.baseItem.NoDurability != 1)
if (this.baseItem is BaseArmor || this.baseItem is BaseWeapon)
{
this.maxDurability = ByteConverter.GetBits(data, ref pOffset, 8);
//todo, if this is 0 it is indestructible by default (PB)? Stat=zod for zoded?
//what about Stormshield, etc..? UNTESTED -> (indestructible)
if (this.MaxDurability > 0)
{
this.currentDurability = ByteConverter.GetBits(data, ref pOffset, 8);
//TODO: unknown. Indestructible bit ??
ByteConverter.GetBits(data, ref pOffset, 1);
}
}
// Total Sockets : 4
if ((this.Flags & ItemFlag.Socketed) == ItemFlag.Socketed)
this.sockets = ByteConverter.GetBits(data, ref pOffset, 4);
// Useable : 5; Quantity : 9
if (this.baseItem.Stackable == 1)
{
if (this.baseItem.Useable == 1)
{
//TODO: figure what this is for (tp tome = 0, id tome = 1...)
this.use = ByteConverter.GetBits(data, ref pOffset, 5);
}
this.quantity = (ushort) ByteConverter.GetBits(data, ref pOffset, 9);
}
// Extra Set Mods (Item's Set Bonuses)
if (this.Quality == ItemQuality.Set)
this.extraMods = ByteConverter.GetBits(data, ref pOffset, 5);
if ((this.Flags & ItemFlag.Identified) != ItemFlag.Identified)
{
this.offset = pOffset;
return;
}
int maxOffset = data.Length * 8 - 9;
bool skipFirstEnd = (this.flags & ItemFlag.Runeword) == ItemFlag.Runeword;
while (pOffset < maxOffset)
{
int statID = ByteConverter.GetBits(data, ref pOffset, 9);
if (statID == 0x1FF)
{
if (skipFirstEnd)
{
skipFirstEnd = false;
continue;
}
break;
}
if (statID < 0 || (int) StatType.Invalid <= statID)
{
//TODO: something about it... or remove...
pOffset -= 9;
break;
}
ItemStat stat = ReadStat(ref data, ref pOffset, BaseStat.Get(statID));
if (stat != null)
this.stats.Add(stat);
else
break;
}
if (extraMods > 0)
{
this.setBonuses = new System.Collections.ArrayList();
while (extraMods-- > 0)
{
int statID = ByteConverter.GetBits(data, ref pOffset, 9);
if (statID == 0x1FF)
break;
if (statID < 0 || (int) StatType.Invalid <= statID)
{
//TODO: something about it... or remove...
pOffset -= 9;
break;
}
ItemStat stat = ReadStat(ref data, ref pOffset, BaseStat.Get(statID));
if (stat != null)
this.setBonuses.Add(stat);
else
break;
}
}
this.offset = pOffset;
}