Exemple #1
0
        /// <summary>
        /// Creates a character record from a raw record that begins at offset 0
        /// </summary>
        /// <param name="rawRecord"></param>
        public PlayerCharacterRecord(byte[] rawRecord)
        {
            Debug.Assert(rawRecord.Length == (int)CHARACTER_RECORD_BYTE_ARRAY_SIZE);
            List <byte> rawRecordByteList = new List <byte>(rawRecord);

            Name                   = DataChunk.CreateDataChunk(DataChunk.DataFormatType.SimpleString, "Character Name", rawRecordByteList, (int)CharacterRecordOffsets.Name, 9).GetChunkAsString();
            Gender                 = (CharacterGender)rawRecordByteList[(int)CharacterRecordOffsets.Gender];
            Class                  = (CharacterClass)rawRecordByteList[(int)CharacterRecordOffsets.Class];
            Status                 = (CharacterStatus)rawRecordByteList[(int)CharacterRecordOffsets.Status];
            Stats.Strength         = rawRecordByteList[(int)CharacterRecordOffsets.Strength];
            Stats.Dexterity        = rawRecordByteList[(int)CharacterRecordOffsets.Dexterity];
            Stats.Intelligence     = rawRecordByteList[(int)CharacterRecordOffsets.Intelligence];
            Stats.CurrentMp        = rawRecordByteList[(int)CharacterRecordOffsets.CurrentMP];
            Stats.CurrentHp        = DataChunk.CreateDataChunk(DataChunk.DataFormatType.UINT16List, "Current hit points", rawRecordByteList, (int)CharacterRecordOffsets.CurrentHP, sizeof(UInt16)).GetChunkAsUint16List()[0];
            Stats.MaximumHp        = DataChunk.CreateDataChunk(DataChunk.DataFormatType.UINT16List, "Maximum hit points", rawRecordByteList, (int)CharacterRecordOffsets.MaximimumHP, sizeof(UInt16)).GetChunkAsUint16List()[0];
            Stats.ExperiencePoints = DataChunk.CreateDataChunk(DataChunk.DataFormatType.UINT16List, "Maximum hit points", rawRecordByteList, (int)CharacterRecordOffsets.ExperiencePoints, sizeof(UInt16)).GetChunkAsUint16List()[0];
            Stats.Level            = rawRecordByteList[(int)CharacterRecordOffsets.Level];

            // this approach is necessary because I have found circumstances where shields and weapons were swapped in the save file
            // I couldn't guarantee that other items wouldn't do the same so instead we allow each of the equipment save
            // slots can be "whatever" in "whatever" order. When I save them back to disk, I will save them in the correct order
            // Also confirmed that Ultima 5 can handle these equipment saves out of order as well
            List <DataOvlReference.Equipment> allEquipment = new List <DataOvlReference.Equipment>(6);

            allEquipment.Add((DataOvlReference.Equipment)rawRecordByteList[(int)CharacterRecordOffsets.Helmet]);
            allEquipment.Add((DataOvlReference.Equipment)rawRecordByteList[(int)CharacterRecordOffsets.Armor]);
            allEquipment.Add((DataOvlReference.Equipment)rawRecordByteList[(int)CharacterRecordOffsets.Weapon]);
            allEquipment.Add((DataOvlReference.Equipment)rawRecordByteList[(int)CharacterRecordOffsets.Shield]);
            allEquipment.Add((DataOvlReference.Equipment)rawRecordByteList[(int)CharacterRecordOffsets.Ring]);
            allEquipment.Add((DataOvlReference.Equipment)rawRecordByteList[(int)CharacterRecordOffsets.Amulet]);

            Equipped.Helmet    = (DataOvlReference.Equipment)rawRecordByteList[(int)CharacterRecordOffsets.Helmet];
            Equipped.Armor     = (DataOvlReference.Equipment)rawRecordByteList[(int)CharacterRecordOffsets.Armor];
            Equipped.LeftHand  = (DataOvlReference.Equipment)rawRecordByteList[(int)CharacterRecordOffsets.Weapon];
            Equipped.RightHand = (DataOvlReference.Equipment)rawRecordByteList[(int)CharacterRecordOffsets.Shield];
            Equipped.Ring      = (DataOvlReference.Equipment)rawRecordByteList[(int)CharacterRecordOffsets.Ring];
            Equipped.Amulet    = (DataOvlReference.Equipment)rawRecordByteList[(int)CharacterRecordOffsets.Amulet];

            // sometimes U5 swaps the shield and weapon, so we are going to be careful and just swap them back
            if ((int)Equipped.LeftHand <= (int)DataOvlReference.Equipment.JewelShield && (int)Equipped.LeftHand >= (int)DataOvlReference.Equipment.Dagger)
            {
                DataOvlReference.Equipment shieldEquip = Equipped.RightHand;
                Equipped.RightHand = Equipped.LeftHand;
                Equipped.LeftHand  = shieldEquip;
            }


            InnOrParty = rawRecordByteList[(int)CharacterRecordOffsets.InnParty];

            Unknown1 = rawRecordByteList[(int)CharacterRecordOffsets.Unknown1];
            Unknown2 = rawRecordByteList[(int)CharacterRecordOffsets.Unknown2];
        }
Exemple #2
0
        /// <summary>
        /// Loads the "Look" descriptions
        /// </summary>
        /// <param name="u5directory">directory of data files</param>
        public Signs(string u5directory)
        {
            _signsByteArray = Utils.GetFileAsByteList(Path.Combine(u5directory, FileConstants.SIGNS_DAT));

            int nIndex = TOTAL_SIGNS * 2;

            // we are ignoring the "offsets" which are likely used to help optimize the lookup
            // on older hardware, instead we will just be lazy and search for them by cycling
            // through the whole list
            // TODO: optimize storage to improve lookup speed
            do
            {
                string rawSignTxt        = Utils.BytesToStringNullTerm(_signsByteArray, nIndex + 4, 0xFF);
                int    nRawSignTxtLength = rawSignTxt.Length;

                // there are often two "warning signs" in the main virtue townes. Only one of the signs text is actually
                // populated - so if we see a "\n" as the only string, then we look ahead to the next signs text and use
                // it instead
                if (rawSignTxt.Trim() == String.Empty)
                {
                    int nNextSignAdjust = rawSignTxt.Length + 1 + 4;
                    rawSignTxt = Utils.BytesToStringNullTerm(_signsByteArray, nIndex + 4 + nNextSignAdjust, 0xFF);
                }

                _signList.Add(new Sign((SmallMapReferences.SingleMapReference.Location)_signsByteArray[nIndex],
                                       _signsByteArray[nIndex + 1],
                                       _signsByteArray[nIndex + 2],
                                       _signsByteArray[nIndex + 3],
                                       rawSignTxt, nIndex));
                nIndex += nRawSignTxtLength + 1 + 4; // we hop over the string plus it's null byte plus the four bytes for definition
                // while we don't encounter four zero bytes in a row, which is essentially the end of the file
            } while (!(_signsByteArray[nIndex] == 0 && _signsByteArray[nIndex + 1] == 0 && _signsByteArray[nIndex + 2] == 0 && _signsByteArray[nIndex + 3] == 0));

            // there are some signs that are not included in the signs.dat file, so we manually pont to them and add them to our sign list
            List <byte> dataovlSignsByteArray = Utils.GetFileAsByteList(Path.Combine(u5directory, FileConstants.DATA_OVL));
            List <byte> shSign = DataChunk.CreateDataChunk(DataChunk.DataFormatType.ByteList, "SH Sign of Eight Laws", dataovlSignsByteArray, 0x743a, 0x66).GetAsByteList();

            _signList.Add(new Sign(SmallMapReferences.SingleMapReference.Location.Serpents_Hold, 0, 15, 19, shSign.ToArray(), 0x743a));
        }
Exemple #3
0
 public bool GetInventoryBool(InventoryThings thing)
 {
     return(DataChunk.CreateDataChunk(DataChunk.DataFormatType.Byte, "", _gameStateByteArray, (int)thing, sizeof(byte)).GetChunkAsByte() > 0);
 }