// find login descriptions followed by deaths of the logged in character
        private List <Tuple <int, int, uint> > FindDeaths()
        {
            uint characterID      = uint.MaxValue;
            uint loginCharacterID = 0x0;
            List <Tuple <int, int, uint> > deathRecords = new List <Tuple <int, int, uint> >();
            int startRecord = -1;

            for (int i = 0; i < records.Count; i++)
            {
                using (BinaryReader messageDataReader = new BinaryReader(new MemoryStream(records[i].data)))
                {
                    PacketOpcode opcode = Util.readOrderedOpcode(messageDataReader, ref characterID);
                    switch (opcode)
                    {
                    case PacketOpcode.CHARACTER_ENTER_GAME_EVENT:
                    {
                        Proto_UI.EnterWorld message = Proto_UI.EnterWorld.read(messageDataReader);
                        startRecord = i;
                        break;
                    }

                    case PacketOpcode.PLAYER_DESCRIPTION_EVENT:
                    {
                        CM_Login.PlayerDescription message = CM_Login.PlayerDescription.read(messageDataReader);
                        if ((uint)message.CACQualities._weenie_type == 43480 || (uint)message.CACQualities._weenie_type == 43481)
                        {
                            // exclude Olthoi play
                            continue;
                        }
                        loginCharacterID = characterID;
                        break;
                    }

                    case PacketOpcode.VICTIM_NOTIFICATION_EVENT:
                    {
                        // we have a player descrption event for this death
                        if (characterID == loginCharacterID)
                        {
                            deathRecords.Add(new Tuple <int, int, uint>(startRecord, i, loginCharacterID));
                        }
                        break;
                    }
                    }
                }
            }

            return(deathRecords);
        }
        private void PlayerDescription(BinaryReader messageDataReader)
        {
            CM_Login.PlayerDescription message = CM_Login.PlayerDescription.read(messageDataReader);
            // level
            character.Name  = message.CACQualities.CBaseQualities._strStatsTable.hashTable[STypeString.NAME_STRING].ToString();
            character.Level = message.CACQualities.CBaseQualities._intStatsTable.hashTable[STypeInt.LEVEL_INT];
            if (message.CACQualities.CBaseQualities._intStatsTable.hashTable.ContainsKey(STypeInt.AUGMENTATION_LESS_DEATH_ITEM_LOSS_INT))
            {
                character.DeathAugmentations = message.CACQualities.CBaseQualities._intStatsTable.hashTable[STypeInt.AUGMENTATION_LESS_DEATH_ITEM_LOSS_INT];
            }
            if (message.CACQualities.CBaseQualities._intStatsTable.hashTable.ContainsKey(STypeInt.PLAYER_KILLER_STATUS_INT))
            {
                character.PKStatus = (PKStatusEnum)message.CACQualities.CBaseQualities._intStatsTable.hashTable[STypeInt.PLAYER_KILLER_STATUS_INT];
            }

            // pack items
            foreach (CM_Inventory.ContentProfile item in message.clist.list)
            {
                character.AddItem(item);

                Item addedItem;
                uint id = item.m_iid;
                if (otherObjects.TryGetValue(id, out addedItem))
                {
                    // moving item in world into inventory
                    character.UpdateItem(addedItem, item.m_uContainerProperties == (uint)ContainerProperties.Container);
                    otherObjects.Remove(id);
                }
                if (item.m_uContainerProperties == (uint)ContainerProperties.Container) // it's a container
                {
                    // pack might need moving
                    if (character.FindItem(id, out addedItem))
                    {
                        character.UpdateItem(addedItem, item.m_uContainerProperties == (uint)ContainerProperties.Container);
                    }
                    // look for items in the world in this container to add
                    foreach (Item otherItem in new List <Item>(otherObjects.Values))
                    {
                        if (otherItem.ContainerID == id)
                        {
                            character.AddItem(otherItem);
                            otherObjects.Remove(otherItem.ID);
                        }
                    }
                }
            }
            // wielded items
            foreach (CM_Login.InventoryPlacement item in message.ilist.list)
            {
                character.AddWieldedItem(item);

                Item addedItem;
                uint id = item.iid_;
                // moving item in world into inventory
                if (otherObjects.TryGetValue(id, out addedItem))
                {
                    // moving item in world into inventory
                    character.UpdateItem(addedItem);
                    otherObjects.Remove(id);
                }
            }
        }