/// <summary>
        /// Changes action record at specified position.
        /// </summary>
        /// <param name="blockName">Name of block file.</param>
        /// <param name="position">Start position of action record.</param>
        /// <param name="axis">Rotation axis.</param>
        /// <param name="duration">Duration of action.</param>
        /// <param name="magnitude">Magnitude of action.</param>
        public void ModActionRecord(string blockName, long position, byte axis, UInt16 duration, UInt16 magnitude)
        {
            // Load resources
            string  path    = Path.Combine(arena2Path, "BLOCKS.BSA");
            BsaFile bsaFile = new BsaFile(
                path,
                FileUsage.UseDisk,
                false);

            // Get binary record
            int index = bsaFile.GetRecordIndex(blockName);

            byte[] buffer = bsaFile.GetRecordBytes(index);

            // Create stream to binary record
            MemoryStream ms = new MemoryStream(buffer);

            ms.Position = position;

            // Write new data
            BinaryWriter writer = new BinaryWriter(ms, Encoding.UTF8);

            writer.Write(axis);
            writer.Write(duration);
            writer.Write(magnitude);
            writer.Close();

            // Save back binary record
            bsaFile.RewriteRecord(index, buffer);
        }
        /// <summary>
        /// ARCH3D.BSA: Modify base texture assigned to plane.
        /// </summary>
        /// <param name="MeshID">ID of mesh.</param>
        /// <param name="planeIndex">Plane index.</param>
        /// <param name="textureArchive">New texture archive index to set.</param>
        /// <param name="textureRecord">New texture record inex to set.</param>
        public void ModPlaneTexture(uint MeshID, int planeIndex, int textureArchive, int textureRecord)
        {
            // Load resources
            string     path       = Path.Combine(arena2Path, "ARCH3D.BSA");
            Arch3dFile arch3dFile = new Arch3dFile(
                path,
                FileUsage.UseMemory,
                true);
            BsaFile bsaFile = new BsaFile(
                path,
                FileUsage.UseDisk,
                false);

            // Get mesh record
            int index = arch3dFile.GetRecordIndex(MeshID);

            arch3dFile.LoadRecord(index);
            Arch3dFile.MeshRecord record = arch3dFile.MeshRecords[index];

            // Get binary record
            byte[] buffer = bsaFile.GetRecordBytes(index);

            // Compose new texture bitfield
            UInt16 textureBitfield = (UInt16)((textureArchive << 7) + textureRecord);

            // Get start position of plane header
            long position = record.PureMesh.Planes[planeIndex].Header.Position;

            // Offset to texture bitfield
            position += 2;

            // Create stream to binary record
            MemoryStream ms = new MemoryStream(buffer);

            ms.Position = position;

            // Write new bitfield
            BinaryWriter writer = new BinaryWriter(ms, Encoding.UTF8);

            writer.Write(textureBitfield);
            writer.Close();

            // Save back binary record
            bsaFile.RewriteRecord(index, buffer);
        }
        static void Main(string[] args)
        {
            // Specify Arena2 path of local Daggerfall installation
            string MyArena2Path = "C:\\dosgames\\DAGGER\\ARENA2";

            // Path to BSA file
            string FilePath = Path.Combine(MyArena2Path, "BLOCKS.BSA");

            // Open BSA file
            BsaFile bsaFile = new BsaFile(
                FilePath,
                FileUsage.UseDisk,
                true);

            // Output some information about the file
            Console.WriteLine("BSA file {0} has {1} records",
                              Path.GetFileName(FilePath),
                              bsaFile.Count);

            // Output some information about a record
            int    record = 0;
            int    length = bsaFile.GetRecordLength(record);
            string name   = bsaFile.GetRecordName(record);

            Console.WriteLine("Record {0} is {1} bytes long and named {2}",
                              record,
                              length,
                              name);

            // Get the record data
            byte[] data = bsaFile.GetRecordBytes(record);

            // This byte array now contains the binary data for this record
            // You can query it using streams to read in whatever data you like
            // (i.e. work with the file formats directly)
            // Here the array is just ignored and will pass out of scope
            // before being garbage collected.
        }
Esempio n. 4
0
        /// <summary>
        /// Opens the save game index specified.
        /// </summary>
        /// <param name="save">Save index</param>
        /// <param name="loadingInGame">True if the save game is being loaded for regular play, false if loading for Save Explorer.</param>
        /// <returns>True if successful.</returns>
        public bool OpenSave(int save, bool loadingInGame = true)
        {
            if (!HasSave(save))
            {
                return(false);
            }

            if (!LoadSaveImage(save))
            {
                throw new Exception("Could not open SaveImage for index " + save);
            }

            if (!LoadSaveName(save))
            {
                throw new Exception("Could not open SaveName for index " + save);
            }

            saveTree = new SaveTree();
            if (!saveTree.Open(Path.Combine(saveGameDict[save], SaveTree.Filename)))
            {
                throw new Exception("Could not open SaveTree for index " + save);
            }

            saveVars = new SaveVars();
            if (!saveVars.Open(Path.Combine(saveGameDict[save], SaveVars.Filename)))
            {
                throw new Exception("Could not open SaveVars for index " + save);
            }

            mapSave = new BsaFile();
            if (!mapSave.Load(Path.Combine(saveGameDict[save], "MAPSAVE.SAV"), FileUsage.UseMemory, true))
            {
                throw new Exception("Could not open MapSave for index " + save);
            }

            if (loadingInGame) // Only check MAPSAVE if loading in-game, not if viewing in Save Explorer. There is a noticeable delay for
                               // Save Explorer as the classic saves are loaded, and a null exception if the Save Explorer is opened
                               // without the game running in the editor, due to PlayerGPS.dfUnity not being instantiated.
                               // Save Explorer currently has no use for MAPSAVE data. This code should be revisited (speed up MAPSAVE processing,
                               // fix null exception, remove this bool check) if MAPSAVE-related functionality is added to Save Explorer.
            {
                PlayerGPS gps = GameManager.Instance.PlayerGPS;
                gps.ClearDiscoveryData();
                for (int regionIndex = 0; regionIndex < 62; regionIndex++)
                {
                    // Generate name from region index
                    string name = string.Format("MAPSAVE.{0:000}", regionIndex);

                    // Get record index
                    int index = mapSave.GetRecordIndex(name);
                    if (index == -1)
                    {
                        return(false);
                    }

                    // Read MAPSAVE data
                    byte[] data = mapSave.GetRecordBytes(index);

                    // Parse MAPSAVE data for discovered locations
                    DFRegion regionData    = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetRegion(regionIndex);
                    int      locationCount = Math.Min(data.Length, (int)regionData.LocationCount);
                    for (int i = 0; i < locationCount; i++)
                    {
                        // If a location is marked as discovered in classic but not DF Unity, discover it for DF Unity
                        if ((data[i] & 0x40) != 0 && !regionData.MapTable[i].Discovered)
                        {
                            DFLocation location = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetLocation(regionIndex, i);
                            gps.DiscoverLocation(regionData.Name, location.Name);
                        }
                    }
                }
            }

            rumorFile = new RumorFile();
            if (!rumorFile.Load(Path.Combine(saveGameDict[save], "RUMOR.DAT"), FileUsage.UseMemory, true))
            {
                UnityEngine.Debug.Log("Could not open RUMOR.DAT for index " + save);
            }

            for (int i = 0; i < rumorFile.rumors.Count; i++)
            {
                GameManager.Instance.TalkManager.ImportClassicRumor(rumorFile.rumors[i]);
            }

            bioFile = new BioFile();
            if (!bioFile.Load(Path.Combine(saveGameDict[save], "BIO.DAT")))
            {
                UnityEngine.Debug.Log("Could not open BIO.DAT for index " + save);
            }

            return(true);
        }
Esempio n. 5
0
        /// <summary>
        /// Opens the save game index specified.
        /// </summary>
        /// <param name="save">Save index</param>
        /// <returns>True if successful.</returns>
        public bool OpenSave(int save)
        {
            if (!HasSave(save))
            {
                return(false);
            }

            if (!LoadSaveImage(save))
            {
                throw new Exception("Could not open SaveImage for index " + save);
            }

            if (!LoadSaveName(save))
            {
                throw new Exception("Could not open SaveName for index " + save);
            }

            saveTree = new SaveTree();
            if (!saveTree.Open(Path.Combine(saveGameDict[save], SaveTree.Filename)))
            {
                throw new Exception("Could not open SaveTree for index " + save);
            }

            saveVars = new SaveVars();
            if (!saveVars.Open(Path.Combine(saveGameDict[save], SaveVars.Filename)))
            {
                throw new Exception("Could not open SaveVars for index " + save);
            }

            mapSave = new BsaFile();
            if (!mapSave.Load(Path.Combine(saveGameDict[save], "MAPSAVE.SAV"), FileUsage.UseMemory, true))
            {
                throw new Exception("Could not open MapSave for index " + save);
            }

            PlayerGPS gps = GameManager.Instance.PlayerGPS;

            gps.ClearDiscoveryData();
            for (int regionIndex = 0; regionIndex < 62; regionIndex++)
            {
                // Generate name from region index
                string name = string.Format("MAPSAVE.{0:000}", regionIndex);

                // Get record index
                int index = mapSave.GetRecordIndex(name);
                if (index == -1)
                {
                    return(false);
                }

                // Read MAPSAVE data
                byte[] data = mapSave.GetRecordBytes(index);

                // Parse MAPSAVE data for discovered locations
                DFRegion regionData = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetRegion(regionIndex);
                for (int i = 0; i < regionData.LocationCount; i++)
                {
                    if ((data[i] & 0x40) != 0)
                    {
                        // Discover the location in DF Unity's data
                        if (regionData.MapTable[i].Discovered == false)
                        {
                            DFLocation location = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetLocation(regionIndex, i);
                            gps.DiscoverLocation(regionData.Name, location.Name);
                        }
                    }
                }
            }

            return(true);
        }