Beispiel #1
0
        public override List<ZoneEntryStruct> GetSpawns()
        {
            List<ZoneEntryStruct> zoneSpawns = new List<ZoneEntryStruct>();

            List<byte[]> spawnPackets = GetPacketsOfType("OP_ZoneEntry", PacketDirection.ServerToClient);

            foreach (var spawnPacket in spawnPackets)
            {
                var newSpawn = new ZoneEntryStruct();

                var buffer = new ByteStream(spawnPacket);

                newSpawn.SpawnName = buffer.ReadString(true);
                newSpawn.SpawnName = Utils.MakeCleanName(newSpawn.SpawnName);
                newSpawn.SpawnID = buffer.ReadUInt32();
                newSpawn.Level = buffer.ReadByte();
                buffer.SkipBytes(4);
                newSpawn.IsNPC = buffer.ReadByte();
                var bitfield=buffer.ReadUInt32();
                newSpawn.Gender = (bitfield & 3);
                var otherData = buffer.ReadByte();
                buffer.SkipBytes(8);

                if ((otherData & 1) > 0)
                {
                    newSpawn.DestructableString1 = buffer.ReadString(false);
                    newSpawn.DestructableString2 = buffer.ReadString(false);
                    newSpawn.DestructableString3 = buffer.ReadString(false);
                    buffer.SkipBytes(53);
                }

                if ((otherData & 4) > 0)
                {
                    buffer.ReadString(false);
                    buffer.ReadString(false);
                    buffer.SkipBytes(54);
                }

                newSpawn.PropCount = buffer.ReadByte();

                if (newSpawn.PropCount > 0)
                    newSpawn.BodyType = buffer.ReadUInt32();
                else
                    newSpawn.BodyType = 0;

                for (var i = 1; i < newSpawn.PropCount; ++i)
                            buffer.SkipBytes(4);

                buffer.SkipBytes(1);   // Skip HP %
                newSpawn.Beard = buffer.ReadByte(); //Beardstyle
                newSpawn.HairColor = buffer.ReadByte();
                newSpawn.EyeColor1 = buffer.ReadByte();
                newSpawn.EyeColor2 = buffer.ReadByte();
                newSpawn.HairStyle = buffer.ReadByte();
                newSpawn.BeardColor = buffer.ReadByte();

                newSpawn.DrakkinHeritage = buffer.ReadUInt32();
                // vsab: an_unemployed_mercenary's and some newer npc's seem to have newSpawn.DrakkinHeritage set to 255, then have invalid numbers for the next ones
                if (newSpawn.DrakkinHeritage == 255)
                {
                    newSpawn.DrakkinHeritage = 0;
                    newSpawn.DrakkinTattoo = 0;
                    newSpawn.DrakkinDetails = 0;
                    buffer.SkipBytes(8);
                }
                else
                {
                    newSpawn.DrakkinTattoo = buffer.ReadUInt32();
                    newSpawn.DrakkinDetails = buffer.ReadUInt32();
                }

                newSpawn.EquipChest2 = buffer.ReadByte();
                var useWorn = (newSpawn.EquipChest2 == 255);
                buffer.SkipBytes(2);    // 2 Unknown bytes;
                newSpawn.Helm= buffer.ReadByte();
                newSpawn.Size = buffer.ReadSingle();
                newSpawn.Face = buffer.ReadByte();
                newSpawn.WalkSpeed = buffer.ReadSingle();
                newSpawn.RunSpeed = buffer.ReadSingle();
                newSpawn.Race = buffer.ReadUInt32();

                buffer.SkipBytes(1);   // Skip Holding

                newSpawn.Deity = buffer.ReadUInt32();
                buffer.SkipBytes(8);    // Skip GuildID and GuildRank
                newSpawn.Class = buffer.ReadUInt32();
                buffer.SkipBytes(1);     // Skip PVP, Standstate, Light, Flymode
                newSpawn.StandState = buffer.ReadByte(); //110 is sitting, 100 is standing, 120 is FD/corpse, mounts show as 102
                buffer.SkipBytes(2);
                newSpawn.LastName = buffer.ReadString(true);

                buffer.SkipBytes(6);

                newSpawn.PetOwnerID = buffer.ReadUInt32();

                newSpawn.MeleeTexture1 = 0;
                newSpawn.MeleeTexture2 = 0;
                buffer.SkipBytes(newSpawn.IsNPC == 1 ? 37 : 25);

                if (newSpawn.IsNPC == 0 || NPCType.IsPlayableRace(newSpawn.Race))
                {
                    var posn = buffer.GetPosition();
                    for (var colourSlot = 0; colourSlot < 9; ++colourSlot)
                        newSpawn.SlotColour[colourSlot] = buffer.ReadUInt32();
                    var diff = buffer.GetPosition() - posn;
                    Debug.Assert(diff == 36, "Colour slots wrong!");
                    for (var i = 0; i < 9; ++i)
                    {
                        newSpawn.Equipment[i] = buffer.ReadUInt32();

                        var equip3 = buffer.ReadUInt32();

                        var equip2 = buffer.ReadUInt32();

                        var equip1 = buffer.ReadUInt32();

                        var equip0 = buffer.ReadUInt32();
                    }

                    if (newSpawn.Equipment[Constants.MATERIAL_CHEST] > 0)
                    {
                        newSpawn.EquipChest2 = (byte)newSpawn.Equipment[Constants.MATERIAL_CHEST];

                    }
                    //vsab: unverified.....
                    newSpawn.ArmorTintRed = (byte)((newSpawn.SlotColour[Constants.MATERIAL_CHEST] >> 16) & 0xff);
                    newSpawn.ArmorTintGreen = (byte)((newSpawn.SlotColour[Constants.MATERIAL_CHEST] >> 8) & 0xff);
                    newSpawn.ArmorTintBlue = (byte)(newSpawn.SlotColour[Constants.MATERIAL_CHEST] & 0xff);

                    if (newSpawn.Equipment[Constants.MATERIAL_PRIMARY] > 0)
                        newSpawn.MeleeTexture1 = newSpawn.Equipment[Constants.MATERIAL_PRIMARY];

                    if (newSpawn.Equipment[Constants.MATERIAL_SECONDARY] > 0)
                        newSpawn.MeleeTexture2 = newSpawn.Equipment[Constants.MATERIAL_SECONDARY];

                    if (useWorn)
                        newSpawn.Helm = (byte)newSpawn.Equipment[Constants.MATERIAL_HEAD];
                    else
                        newSpawn.Helm = 0;
                }
                else
                {
                    buffer.SkipBytes(20);
                    newSpawn.MeleeTexture1 = buffer.ReadUInt32();
                    buffer.SkipBytes(16);
                    newSpawn.MeleeTexture2 = buffer.ReadUInt32();
                    buffer.SkipBytes(16);
                }
                if (newSpawn.EquipChest2 == 255)
                    newSpawn.EquipChest2 = 0;

                if (newSpawn.Helm == 255)
                    newSpawn.Helm = 0;

                var position1 = buffer.ReadUInt32();
                var position2 = buffer.ReadUInt32(); //not valid this patch
                var position3 = buffer.ReadUInt32();
                var position4 = buffer.ReadUInt32();
                var position5 = buffer.ReadUInt32();

                newSpawn.XPos = Utils.EQ19ToFloat((Int32)((position4 >> 13) & 0x7FFFF));
                newSpawn.YPos = Utils.EQ19ToFloat((Int32)(position1 >> 12) & 0x7FFFF);
                newSpawn.ZPos = Utils.EQ19ToFloat((Int32)(position3) & 0x7FFFF);
                newSpawn.Heading = Utils.EQ19ToFloat((Int32)(position5) & 0x7FF);

                if ((otherData & 16) > 1)
                {
                    newSpawn.Title = buffer.ReadString(false);
                }

                if ((otherData & 32) > 1)
                {
                    newSpawn.Suffix = buffer.ReadString(false);
                }

                // unknowns
                buffer.SkipBytes(8);

                newSpawn.IsMercenary = buffer.ReadByte();

                buffer.SkipBytes(54);
                var expectedLength = buffer.Length();
                var currentPoint = buffer.GetPosition();
                Debug.Assert(currentPoint == expectedLength, "Length mismatch while parsing zone spawns");
                zoneSpawns.Add(newSpawn);
            }
            return zoneSpawns;
        }
        public override List<ZoneEntryStruct> GetSpawns()
        {
            List<ZoneEntryStruct> ZoneSpawns = new List<ZoneEntryStruct>();

            List<byte[]> SpawnPackets = GetPacketsOfType("OP_ZoneEntry", PacketDirection.ServerToClient);

            foreach (byte[] SpawnPacket in SpawnPackets)
            {
                ZoneEntryStruct newSpawn = new ZoneEntryStruct();

                ByteStream buffer = new ByteStream(SpawnPacket);

                newSpawn.SpawnName = buffer.ReadString(true);

                newSpawn.SpawnName = Utils.MakeCleanName(newSpawn.SpawnName);

                newSpawn.SpawnID = buffer.ReadUInt32();

                newSpawn.Level = buffer.ReadByte();

                float UnkSize = buffer.ReadSingle();

                newSpawn.IsNPC = buffer.ReadByte();

                UInt32 Bitfield = buffer.ReadUInt32();

                newSpawn.Gender = (Bitfield & 3);

                Byte OtherData = buffer.ReadByte();

                buffer.SkipBytes(8);    // Skip 8 unknown bytes

                newSpawn.DestructableString1 = "";
                newSpawn.DestructableString2 = "";
                newSpawn.DestructableString3 = "";

                if ((newSpawn.IsNPC > 0) && ((OtherData & 1) > 0))
                {
                    // Destructable Objects
                    newSpawn.DestructableString1 = buffer.ReadString(false);
                    newSpawn.DestructableString2 = buffer.ReadString(false);
                    newSpawn.DestructableString3 = buffer.ReadString(false);
                    buffer.SkipBytes(53);
                }

                if ((OtherData & 4) > 0)
                {
                    // Auras
                    buffer.ReadString(false);
                    buffer.ReadString(false);
                    buffer.SkipBytes(54);
                }

                newSpawn.PropCount = buffer.ReadByte();

                if (newSpawn.PropCount > 0)
                    newSpawn.BodyType = buffer.ReadUInt32();
                else
                    newSpawn.BodyType = 0;

                for (int j = 1; j < newSpawn.PropCount; ++j)
                    buffer.SkipBytes(4);

                buffer.SkipBytes(1);   // Skip HP %
                newSpawn.HairColor = buffer.ReadByte();
                newSpawn.BeardColor = buffer.ReadByte();
                newSpawn.EyeColor1 = buffer.ReadByte();
                newSpawn.EyeColor2 = buffer.ReadByte();
                newSpawn.HairStyle = buffer.ReadByte();
                newSpawn.Beard = buffer.ReadByte();

                newSpawn.DrakkinHeritage = buffer.ReadUInt32();
                newSpawn.DrakkinTattoo = buffer.ReadUInt32();
                newSpawn.DrakkinDetails = buffer.ReadUInt32();

                newSpawn.EquipChest2 = buffer.ReadByte();

                bool UseWorn = (newSpawn.EquipChest2 == 255);

                buffer.SkipBytes(2);    // 2 Unknown bytes;

                newSpawn.Helm = buffer.ReadByte();

                newSpawn.Size = buffer.ReadSingle();

                newSpawn.Face = buffer.ReadByte();

                newSpawn.WalkSpeed = buffer.ReadSingle();

                newSpawn.RunSpeed = buffer.ReadSingle();

                newSpawn.Race = buffer.ReadUInt32();

                buffer.SkipBytes(1);   // Skip Holding

                newSpawn.Deity = buffer.ReadUInt32();

                buffer.SkipBytes(8);    // Skip GuildID and GuildRank

                newSpawn.Class = buffer.ReadByte();

                buffer.SkipBytes(4);     // Skip PVP, Standstate, Light, Flymode

                newSpawn.LastName = buffer.ReadString(true);

                buffer.SkipBytes(6);

                newSpawn.PetOwnerID = buffer.ReadUInt32();

                buffer.SkipBytes(25);

                newSpawn.MeleeTexture1 = 0;
                newSpawn.MeleeTexture2 = 0;

                if ((newSpawn.IsNPC == 0) || NPCType.IsPlayableRace(newSpawn.Race))
                {
                    for (int ColourSlot = 0; ColourSlot < 9; ++ColourSlot)
                        newSpawn.SlotColour[ColourSlot] = buffer.ReadUInt32();

                    for (int i = 0; i < 9; ++i)
                    {
                        newSpawn.Equipment[i] = buffer.ReadUInt32();

                        UInt32 Equip3 = buffer.ReadUInt32();

                        UInt32 Equip2 = buffer.ReadUInt32();

                        UInt32 Equip1 = buffer.ReadUInt32();

                        UInt32 Equip0 = buffer.ReadUInt32();
                    }

                    if (newSpawn.Equipment[Constants.MATERIAL_CHEST] > 0)
                    {
                        newSpawn.EquipChest2 = (byte)newSpawn.Equipment[Constants.MATERIAL_CHEST];

                    }

                    newSpawn.ArmorTintRed = (byte)((newSpawn.SlotColour[Constants.MATERIAL_CHEST] >> 16) & 0xff);

                    newSpawn.ArmorTintGreen = (byte)((newSpawn.SlotColour[Constants.MATERIAL_CHEST] >> 8) & 0xff);

                    newSpawn.ArmorTintBlue = (byte)(newSpawn.SlotColour[Constants.MATERIAL_CHEST] & 0xff);

                    if (newSpawn.Equipment[Constants.MATERIAL_PRIMARY] > 0)
                        newSpawn.MeleeTexture1 = newSpawn.Equipment[Constants.MATERIAL_PRIMARY];

                    if (newSpawn.Equipment[Constants.MATERIAL_SECONDARY] > 0)
                        newSpawn.MeleeTexture2 = newSpawn.Equipment[Constants.MATERIAL_SECONDARY];

                    if (UseWorn)
                        newSpawn.Helm = (byte)newSpawn.Equipment[Constants.MATERIAL_HEAD];
                    else
                        newSpawn.Helm = 0;

                }
                else
                {
                    // Non playable race

                    buffer.SkipBytes(20);

                    newSpawn.MeleeTexture1 = buffer.ReadUInt32();
                    buffer.SkipBytes(16);
                    newSpawn.MeleeTexture2 = buffer.ReadUInt32();
                    buffer.SkipBytes(16);
                }

                if (newSpawn.EquipChest2 == 255)
                    newSpawn.EquipChest2 = 0;

                if (newSpawn.Helm == 255)
                    newSpawn.Helm = 0;

                UInt32 Position1 = buffer.ReadUInt32();

                UInt32 Position2 = buffer.ReadUInt32();

                UInt32 Position3 = buffer.ReadUInt32();

                UInt32 Position4 = buffer.ReadUInt32();

                UInt32 Position5 = buffer.ReadUInt32();

                newSpawn.YPos = Utils.EQ19ToFloat((Int32)((Position1 >> 12) & 0x7FFFF));

                newSpawn.ZPos = Utils.EQ19ToFloat((Int32)(Position2) & 0x7FFFF);

                newSpawn.XPos = Utils.EQ19ToFloat((Int32)(Position4 >> 13) & 0x7FFFF);

                newSpawn.Heading = Utils.EQ19ToFloat((Int32)(Position3 >> 13) & 0xFFF);

                if ((OtherData & 16) > 0)
                {
                    newSpawn.Title = buffer.ReadString(false);
                }

                if ((OtherData & 32) > 0)
                {
                    newSpawn.Suffix = buffer.ReadString(false);
                }

                // unknowns
                buffer.SkipBytes(8);

                newSpawn.IsMercenary = buffer.ReadByte();

                buffer.SkipBytes(54);
                var expectedLength = buffer.Length();
                var currentPoint = buffer.GetPosition();
                Debug.Assert(currentPoint == expectedLength, "Length mismatch while parsing zone spawns");

                ZoneSpawns.Add(newSpawn);
            }
            return ZoneSpawns;
        }
Beispiel #3
0
        public override List<ZoneEntryStruct> GetSpawns()
        {
            List<ZoneEntryStruct> ZoneSpawns = new List<ZoneEntryStruct>();
                        List<byte[]> SpawnPackets = GetPacketsOfType("OP_ZoneEntry", PacketDirection.ServerToClient);

            foreach (byte[] SpawnPacket in SpawnPackets)
            {
                ZoneEntryStruct NewSpawn = new ZoneEntryStruct();

                ByteStream Buffer = new ByteStream(SpawnPacket);

                NewSpawn.SpawnName = Buffer.ReadString(true);

                NewSpawn.SpawnName = Utils.MakeCleanName(NewSpawn.SpawnName);

                NewSpawn.SpawnID = Buffer.ReadUInt32();

                NewSpawn.Level = Buffer.ReadByte();

                float UnkSize = Buffer.ReadSingle();

                NewSpawn.IsNPC = Buffer.ReadByte();

                UInt32 Bitfield = Buffer.ReadUInt32();

                NewSpawn.Showname = (Bitfield >> 28) & 1;
                NewSpawn.TargetableWithHotkey = (Bitfield >> 27) & 1;
                NewSpawn.Targetable = (Bitfield >> 26) & 1;

                NewSpawn.ShowHelm = (Bitfield >> 24) & 1;
                NewSpawn.Gender = (Bitfield >> 20) & 3;

                NewSpawn.Padding5 = (Bitfield >> 4) & 1;
                NewSpawn.Padding7 = (Bitfield >> 6) & 2047;
                NewSpawn.Padding26 = (Bitfield >> 25) & 1;

                Byte OtherData = Buffer.ReadByte();

                Buffer.SkipBytes(8);    // Skip 8 unknown bytes

                NewSpawn.DestructableString1 = "";
                NewSpawn.DestructableString2 = "";
                NewSpawn.DestructableString3 = "";

                if ((NewSpawn.IsNPC == 1) && ((OtherData & 3) > 0))
                {
                    // Destructable Objects. Not handled yet
                    //
                    //SQLOut(String.Format("-- OBJECT FOUND SpawnID {0}", SpawnID.ToString("x")));

                    NewSpawn.DestructableString1 = Buffer.ReadString(false);

                    NewSpawn.DestructableString2 = Buffer.ReadString(false);

                    NewSpawn.DestructableString3 = Buffer.ReadString(false);

                    NewSpawn.DestructableUnk1 = Buffer.ReadUInt32();

                    NewSpawn.DestructableUnk2 = Buffer.ReadUInt32();

                    NewSpawn.DestructableID1 = Buffer.ReadUInt32();

                    NewSpawn.DestructableID2 = Buffer.ReadUInt32();

                    NewSpawn.DestructableID3 = Buffer.ReadUInt32();

                    NewSpawn.DestructableID4 = Buffer.ReadUInt32();

                    NewSpawn.DestructableUnk3 = Buffer.ReadUInt32();

                    NewSpawn.DestructableUnk4 = Buffer.ReadUInt32();

                    NewSpawn.DestructableUnk5 = Buffer.ReadUInt32();

                    NewSpawn.DestructableUnk6 = Buffer.ReadUInt32();

                    NewSpawn.DestructableUnk7 = Buffer.ReadUInt32();

                    NewSpawn.DestructableUnk8 = Buffer.ReadUInt32();

                    NewSpawn.DestructableUnk9 = Buffer.ReadUInt32();

                    NewSpawn.DestructableByte = Buffer.ReadByte();

                    //SQLOut(String.Format("-- DES: {0,8:x} {1,8:x} {2,8:d} {3,8:d} {4,8:d} {5,8:d} {6,8:x} {7,8:x} {8,8:x} {9,8:x} {10,8:x} {11,8:x} {12,8:x} {13,2:x} {14} {15} {16}",
                    //          DestructableUnk1, DestructableUnk2, DestructableID1, DestructableID2, DestructableID3, DestructableID4,
                    //          DestructableUnk3, DestructableUnk4, DestructableUnk5, DestructableUnk6, DestructableUnk7, DestructableUnk8,
                    //          DestructableUnk9, DestructableByte, DestructableString1, DestructableString2, DestructableString3));
                }

                NewSpawn.Size = Buffer.ReadSingle();

                NewSpawn.Face = Buffer.ReadByte();

                NewSpawn.WalkSpeed = Buffer.ReadSingle();

                NewSpawn.RunSpeed = Buffer.ReadSingle();

                NewSpawn.Race = Buffer.ReadUInt32();

                NewSpawn.PropCount = Buffer.ReadByte();

                NewSpawn.BodyType = 0;

                if (NewSpawn.PropCount >= 1)
                {
                    NewSpawn.BodyType = Buffer.ReadUInt32();

                    for (int j = 1; j < NewSpawn.PropCount; ++j)
                        Buffer.SkipBytes(4);
                }

                Buffer.SkipBytes(1);   // Skip HP %

                NewSpawn.HairColor = Buffer.ReadByte();
                NewSpawn.BeardColor = Buffer.ReadByte();
                NewSpawn.EyeColor1 = Buffer.ReadByte();
                NewSpawn.EyeColor2 = Buffer.ReadByte();
                NewSpawn.HairStyle = Buffer.ReadByte();
                NewSpawn.Beard = Buffer.ReadByte();

                NewSpawn.DrakkinHeritage = Buffer.ReadUInt32();

                NewSpawn.DrakkinTattoo = Buffer.ReadUInt32();

                NewSpawn.DrakkinDetails = Buffer.ReadUInt32();

                Buffer.SkipBytes(1);   // Skip Holding

                NewSpawn.Deity = Buffer.ReadUInt32();

                Buffer.SkipBytes(8);    // Skip GuildID and GuildRank

                NewSpawn.Class = Buffer.ReadByte();

                Buffer.SkipBytes(4);     // Skip PVP, Standstate, Light, Flymode

                NewSpawn.EquipChest2 = Buffer.ReadByte();

                bool UseWorn = (NewSpawn.EquipChest2 == 255);

                Buffer.SkipBytes(2);    // 2 Unknown bytes;

                NewSpawn.Helm = Buffer.ReadByte();

                NewSpawn.LastName = Buffer.ReadString(false);

                Buffer.SkipBytes(5);    // AATitle + unknown byte

                NewSpawn.PetOwnerID = Buffer.ReadUInt32();

                Buffer.SkipBytes(25);   // Unknown byte + 6 unknown uint32

                UInt32 Position1 = Buffer.ReadUInt32();

                UInt32 Position2 = Buffer.ReadUInt32();

                UInt32 Position3 = Buffer.ReadUInt32();

                UInt32 Position4 = Buffer.ReadUInt32();

                UInt32 Position5 = Buffer.ReadUInt32();

                NewSpawn.YPos = Utils.EQ19ToFloat((Int32)(Position3 & 0x7FFFF));

                NewSpawn.Heading = Utils.EQ19ToFloat((Int32)(Position4 & 0xFFF));

                NewSpawn.XPos = Utils.EQ19ToFloat((Int32)(Position4 >> 12) & 0x7FFFF);

                NewSpawn.ZPos = Utils.EQ19ToFloat((Int32)(Position5 & 0x7FFFF));

                for (int ColourSlot = 0; ColourSlot < 9; ++ColourSlot)
                    NewSpawn.SlotColour[ColourSlot] = Buffer.ReadUInt32();

                NewSpawn.MeleeTexture1 = 0;
                NewSpawn.MeleeTexture2 = 0;

                if (NPCType.IsPlayableRace(NewSpawn.Race))
                {
                    for (int i = 0; i < 9; ++i)
                    {
                        NewSpawn.Equipment[i] = Buffer.ReadUInt32();

                        UInt32 Equip1 = Buffer.ReadUInt32();

                        UInt32 Equip0 = Buffer.ReadUInt32();
                    }

                    if (NewSpawn.Equipment[Constants.MATERIAL_CHEST] > 0)
                    {
                        NewSpawn.EquipChest2 = (byte)NewSpawn.Equipment[Constants.MATERIAL_CHEST];

                    }

                    NewSpawn.ArmorTintRed = (byte)((NewSpawn.SlotColour[Constants.MATERIAL_CHEST] >> 16) & 0xff);

                    NewSpawn.ArmorTintGreen = (byte)((NewSpawn.SlotColour[Constants.MATERIAL_CHEST] >> 8) & 0xff);

                    NewSpawn.ArmorTintBlue = (byte)(NewSpawn.SlotColour[Constants.MATERIAL_CHEST] & 0xff);

                    if (NewSpawn.Equipment[Constants.MATERIAL_PRIMARY] > 0)
                        NewSpawn.MeleeTexture1 = NewSpawn.Equipment[Constants.MATERIAL_PRIMARY];

                    if (NewSpawn.Equipment[Constants.MATERIAL_SECONDARY] > 0)
                        NewSpawn.MeleeTexture2 = NewSpawn.Equipment[Constants.MATERIAL_SECONDARY];

                    if (UseWorn)
                        NewSpawn.Helm = (byte)NewSpawn.Equipment[Constants.MATERIAL_HEAD];
                    else
                        NewSpawn.Helm = 0;

                }
                else
                {
                    // Non playable race
                    NewSpawn.MeleeTexture1 = NewSpawn.SlotColour[3];
                    NewSpawn.MeleeTexture2 = NewSpawn.SlotColour[6];
                }

                if (NewSpawn.EquipChest2 == 255)
                    NewSpawn.EquipChest2 = 0;

                if (NewSpawn.Helm == 255)
                    NewSpawn.Helm = 0;

                if ((OtherData & 4) > 0)
                {
                    NewSpawn.Title = Buffer.ReadString(false);
                }

                if ((OtherData & 8) > 0)
                {
                    NewSpawn.Suffix = Buffer.ReadString(false);
                }

                // unknowns
                Buffer.SkipBytes(8);

                NewSpawn.IsMercenary = Buffer.ReadByte();

                ZoneSpawns.Add(NewSpawn);
            }

            return ZoneSpawns;
        }