Beispiel #1
0
        void ReadRecordRoot()
        {
            MemoryStream stream = new MemoryStream(streamData);
            BinaryReader reader = new BinaryReader(stream);

            // Must have RecordRootLength of bytes to read or something has gone wrong
            if (stream.Length < RecordRootLength)
            {
                stream.Close();
                return;
            }

            // Position
            reader.BaseStream.Position = 6;
            recordRoot.Position        = SaveTree.ReadPosition(reader);

            // RecordID
            reader.BaseStream.Position = 30;
            recordRoot.RecordID        = reader.ReadUInt32();

            // QuestID
            reader.BaseStream.Position = 37;
            recordRoot.QuestID         = reader.ReadByte();

            // ParentRecordID
            reader.BaseStream.Position = 38;
            recordRoot.ParentRecordID  = reader.ReadUInt32();

            // ParentRecordType
            reader.BaseStream.Position  = 66;
            recordRoot.ParentRecordType = (RecordTypes)reader.ReadInt32();

            reader.Close();
        }
        /// <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);
            }

            return(true);
        }
Beispiel #3
0
        void ReadRawData()
        {
            MemoryStream stream = new MemoryStream(RawData);
            BinaryReader reader = new BinaryReader(stream, Encoding.UTF8);

            // Read Version - must be 0x126
            Version = reader.ReadInt32();
            if (Version != VersionNumber)
            {
                throw new Exception("SaveTree file has an invalid version number, must be 0x126.");
            }

            // Read character position. A character position record later in the file (record type 0x04) is used for positioning the player, not this.
            // Currently not clear what classic uses this one for.
            CharacterPosition          = new HeaderCharacterPositionRecord();
            CharacterPosition.Position = SaveTree.ReadPosition(reader);

            // Read MapID
            MapID = reader.ReadUInt16();

            // Read Environment
            Environment = reader.ReadByte();

            reader.Close();
        }
Beispiel #4
0
        void ReadRawData()
        {
            MemoryStream stream = new MemoryStream(RawData);
            BinaryReader reader = new BinaryReader(stream, Encoding.UTF8);

            // Read Version - must be 0x26
            Version = reader.ReadByte();
            if (Version != VersionNumber)
            {
                throw new Exception("SaveTree file has an invalid version number, must be 0x26.");
            }

            // Read CharacterPosition.RecordType - must be 0x01
            CharacterPosition            = new CharacterPositionRecord();
            CharacterPosition.RecordType = reader.ReadByte();
            if (CharacterPosition.RecordType != (int)RecordTypes.CharacterPosition)
            {
                throw new Exception("Expected CharacterPosition in SaveTreeHeader has an invalid record type, must be 0x01.");
            }

            // Read CharacterPosition.Unknown
            CharacterPosition.Unknown = reader.ReadUInt16();

            // Read CharacterPosition.Position
            CharacterPosition.Position = SaveTree.ReadPosition(reader);

            // Read Unknown
            Unknown = reader.ReadUInt16();

            reader.Close();
        }
Beispiel #5
0
        void ReadRecordRoot()
        {
            MemoryStream stream = new MemoryStream(streamData);
            BinaryReader reader = new BinaryReader(stream);

            // Must have RecordRootLength of bytes to read or something has gone wrong
            if (stream.Length < RecordRootLength)
            {
                stream.Close();
                return;
            }

            // Direction
            reader.BaseStream.Position = 1;
            recordRoot.Pitch           = reader.ReadInt16();
            recordRoot.Yaw             = reader.ReadInt16();

            // Position
            reader.BaseStream.Position = 7;
            recordRoot.Position        = SaveTree.ReadPosition(reader);

            // 3d View Picture
            reader.BaseStream.Position = 27;
            recordRoot.Picture1        = reader.ReadUInt16();

            // Inventory Picture
            recordRoot.Picture2 = reader.ReadUInt16();

            // RecordID
            recordRoot.RecordID = reader.ReadUInt32();

            // QuestID
            reader.BaseStream.Position = 38;
            recordRoot.QuestID         = reader.ReadByte();

            // ParentRecordID
            recordRoot.ParentRecordID = reader.ReadUInt32();

            // ItemObject
            reader.BaseStream.Position = 47;
            recordRoot.ItemObject      = reader.ReadUInt32();

            // QuestObjectID
            recordRoot.QuestObjectID = reader.ReadUInt32();

            // NextObject
            recordRoot.NextObject = reader.ReadUInt32();

            // ChildObject
            recordRoot.ChildObject = reader.ReadUInt32();

            // SublistHead
            recordRoot.SublistHead = reader.ReadUInt32();

            // ParentRecordType
            recordRoot.ParentRecordType = (RecordTypes)reader.ReadInt32();

            reader.Close();
        }
        void WriteRawData()
        {
            MemoryStream stream = new MemoryStream(RawData, true);
            BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8);

            // Write Version
            writer.Write(Version);

            // Write CharacterPosition.Position
            SaveTree.WritePosition(writer, CharacterPosition.Position);

            // Write MapID
            writer.Write(MapID);

            // Write Environment
            writer.Write(Environment);

            writer.Close();
        }
Beispiel #7
0
        void WriteRawData()
        {
            MemoryStream stream = new MemoryStream(RawData, true);
            BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8);

            // Write Version
            writer.Write(Version);

            // Write CharacterPosition.RecordType
            writer.Write(CharacterPosition.RecordType);

            // Write CharacterPosition.Unknown
            writer.Write(CharacterPosition.Unknown);

            // Write CharacterPosition.Position
            SaveTree.WritePosition(writer, CharacterPosition.Position);

            // Write Unknown
            writer.Write(Unknown);

            writer.Close();
        }
Beispiel #8
0
        /// <summary>
        /// Reads record data from stream.
        /// </summary>
        /// <param name="reader">Reader positioned at start of record data.</param>
        /// <param name="length">Length of record data to read.</param>
        public virtual void Open(BinaryReader reader, int length)
        {
            streamPosition = reader.BaseStream.Position;
            streamLength   = length;

            // Cannot read zero-length records
            if (length <= 0)
            {
                return;
            }

            // Peek record type and adjust for dungeon size
            recordType = SaveTree.PeekRecordType(reader);
            if (recordType == RecordTypes.DungeonInformation)
            {
                streamLength *= DungeonDataLengthMultiplier;
            }

            // Read raw record data
            streamData = reader.ReadBytes(streamLength);

            // Read RecordRoot data from start of memory buffer
            ReadRecordRoot();
        }
        void ReadRawData()
        {
            MemoryStream stream = new MemoryStream(RawData);
            BinaryReader reader = new BinaryReader(stream, Encoding.UTF8);

            // Read Version - must be 0x126
            Version = reader.ReadInt32();
            if (Version != VersionNumber)
            {
                throw new Exception("SaveTree file has an invalid version number, must be 0x126.");
            }

            // Read CharacterPosition.Position
            CharacterPosition          = new HeaderCharacterPositionRecord();
            CharacterPosition.Position = SaveTree.ReadPosition(reader);

            // Read MapID
            MapID = reader.ReadUInt16();

            // Read Environment
            Environment = reader.ReadByte();

            reader.Close();
        }
Beispiel #10
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);
        }
        void OnGUI()
        {
            if (!IsReady())
            {
                EditorGUILayout.HelpBox("DaggerfallUnity instance not ready. Have you set your Arena2 path?", MessageType.Info);
                return;
            }

            if (selectedSave != lastSelectedSave || currentSaveTree == null)
            {
                currentSaveTree = saveTrees[selectedSave];
                currentSaveVars = saveVars[selectedSave];
                if (currentSaveTree == null || currentSaveVars == null)
                    return;

                currentItems = currentSaveTree.FindRecords(RecordTypes.Item).ToArray();

                // Merge savetree faction data
                factionDict = factionFile.Merge(currentSaveVars);

                lastSelectedSave = selectedSave;
            }

            if (saveTrees != null && saveTrees.Length > 0)
            {
                DisplaySaveSelectGUI();
                DisplaySaveImageGUI();
                DisplaySaveStatsGUI();
                DisplaySaveCharacterGUI();

                scrollPos = GUILayoutHelper.ScrollView(scrollPos, () =>
                {
                    EditorGUILayout.Space();
                    showFactionsFoldout = GUILayoutHelper.Foldout(showFactionsFoldout, new GUIContent("Factions"), () =>
                    {
                        GUILayoutHelper.Indent(() =>
                        {
                            DisplayFactionsFoldout();
                        });
                    });

                    EditorGUILayout.Space();
                    showItemsFoldout = GUILayoutHelper.Foldout(showItemsFoldout, new GUIContent("Items"), () =>
                    {
                        GUILayoutHelper.Indent(() =>
                        {
                            DisplayItemsFoldout();
                        });
                    });

                    EditorGUILayout.Space();
                    showSaveTreeFoldout = GUILayoutHelper.Foldout(showSaveTreeFoldout, new GUIContent("SaveTree"), () =>
                    {
                        EditorGUILayout.HelpBox("Temporarily Filtering out records of type UnknownTownLink and UnknownItemRecord to keep list manageable.", MessageType.Info);

                        DisplaySaveTree(currentSaveTree.RootRecord);
                    });
                });
            }
        }
        void OnGUI()
        {
            if (!IsReady())
            {
                EditorGUILayout.HelpBox("DaggerfallUnity instance not ready. Have you set your Arena2 path?", MessageType.Info);
                return;
            }

            currentSaveTree = saveTrees[selectedSave];
            if (currentSaveTree == null)
                return;

            if (saveTrees != null && saveTrees.Length > 0)
            {
                DisplaySaveSelectGUI();
                DisplaySaveImageGUI();
                DisplaySaveStatsGUI();
                DisplaySaveCharacterGUI();

                EditorGUILayout.Space();
                EditorGUILayout.HelpBox("Temporarily Filtering out records of type UnknownTownLink and UnknownItemRecord to keep list manageable.", MessageType.Info);
                scrollPos = GUILayoutHelper.ScrollView(scrollPos, () =>
                {
                    DisplaySaveTree(currentSaveTree.RootRecord);
                });
            }
        }
        /// <summary>
        /// Assigns character items from classic save tree.
        /// </summary>
        public void AssignItems(SaveTree saveTree)
        {
            // Find character record, should always be a singleton
            CharacterRecord characterRecord = (CharacterRecord)saveTree.FindRecord(RecordTypes.Character);
            if (characterRecord == null)
                return;

            // Find all character-owned items
            List<SaveTreeBaseRecord> itemRecords = saveTree.FindRecords(RecordTypes.Item, characterRecord);

            // Filter for container-based inventory items
            List<SaveTreeBaseRecord> filteredRecords = saveTree.FilterRecordsByParentType(itemRecords, RecordTypes.Container);

            // Add interim Daggerfall Unity items
            foreach (var record in filteredRecords)
            {
                // Get container parent
                ContainerRecord containerRecord = (ContainerRecord)record.Parent;

                // Add to local inventory or wagon
                DaggerfallUnityItem newItem = new DaggerfallUnityItem((ItemRecord)record);
                if (containerRecord.IsWagon)
                    wagonItems.AddItem(newItem);
                else
                    items.AddItem(newItem);

                // Equip to player if equipped in save
                for (int i = 0; i < characterRecord.ParsedData.equippedItems.Length; i++)
                {
                    if (characterRecord.ParsedData.equippedItems[i] == (record.RecordRoot.RecordID >> 8))
                        equipTable.EquipItem(newItem);
                }
            }
        }
Beispiel #14
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);
        }
        /// <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);

            return true;
        }