Example #1
0
        public static void ReadNativeBankData(SaveTreeBaseRecord records)
        {
            SetupAccounts();

            if (records == null || records.RecordType != RecordTypes.BankAccount)
            {
                return;
            }

            MemoryStream stream = new MemoryStream(records.RecordData);
            BinaryReader reader = new BinaryReader(stream);

            int count = 0;

            while (reader.BaseStream.Position + 13 < records.RecordLength)
            {
                BankRecordData_v1 record = new BankRecordData_v1();
                record.accountGold  = reader.ReadInt32();
                record.loanTotal    = reader.ReadInt32();
                record.loanDueDate  = reader.ReadUInt32();
                record.hasDefaulted = reader.ReadBoolean();
                record.regionIndex  = count;

                if (record.regionIndex >= BankAccounts.Length)
                {
                    Debug.LogError("error reading bank data from classic save");
                    break;
                }

                BankAccounts[record.regionIndex] = record;
                count++;
            }
            reader.Close();
        }
        void DisplaySaveTree(SaveTreeBaseRecord parent)
        {
            for (int i = 0; i < parent.Children.Count; i++)
            {
                RecordTypes recordType = parent.Children[i].RecordType;
                if (recordType == RecordTypes.Door || recordType == RecordTypes.Goods)
                {
                    continue;
                }

                string textLabel = recordType.ToString();
                if (recordType == RecordTypes.Item || recordType == RecordTypes.Spell)
                {
                    textLabel += string.Format(" [{0}]", GetItemOrSpellName(parent.Children[i]));
                }

                // Check if item equipped
                if (recordType == RecordTypes.Item)
                {
                    //ItemRecord itemRecord = (ItemRecord)parent.Children[i];
                    //textLabel += string.Format(" [id={0}]", itemRecord.RecordRoot.RecordID);

                    int equippedIndex = GetEquippedIndex(parent.Children[i] as ItemRecord);
                    if (equippedIndex != -1)
                    {
                        //textLabel = string.Format("(*={0:00}) {1}", equippedIndex, textLabel);
                    }
                }

                // Tag container types
                if (recordType == RecordTypes.Container && parent.RecordType == RecordTypes.Character)
                {
                    string[] tags = { " [Weapons & Armor]", " [Magic Items]", " [Clothing & Misc]", " [Ingredients]", " [Wagon]",
                                      " [House]",           " [Ship]",        " [Tavern Rooms]",    " [Item Repairers]" };

                    ContainerRecord containerRecord = (ContainerRecord)parent.Children[i];

                    textLabel += tags[containerRecord.RecordRoot.SpriteIndex];
                }

                EditorGUILayout.LabelField(textLabel);
                GUILayoutHelper.Indent(() =>
                {
                    DisplaySaveTree(parent.Children[i]);
                });
            }
        }
        void DisplaySaveTree(SaveTreeBaseRecord parent)
        {
            for (int i = 0; i < parent.Children.Count; i++)
            {
                RecordTypes recordType = parent.Children[i].RecordType;
                if (recordType == RecordTypes.Door || recordType == RecordTypes.UnknownItemRecord)
                {
                    continue;
                }

                string textLabel = recordType.ToString();
                if (recordType == RecordTypes.Item || recordType == RecordTypes.Spell)
                {
                    textLabel += string.Format(" [{0}]", GetItemOrSpellName(parent.Children[i]));
                }

                // Check if item equipped
                if (recordType == RecordTypes.Item)
                {
                    //ItemRecord itemRecord = (ItemRecord)parent.Children[i];
                    //textLabel += string.Format(" [id={0}]", itemRecord.RecordRoot.RecordID);

                    int equippedIndex = GetEquippedIndex(parent.Children[i] as ItemRecord);
                    if (equippedIndex != -1)
                    {
                        //textLabel = string.Format("(*={0:00}) {1}", equippedIndex, textLabel);
                    }
                }

                // Tag wagon container
                if (recordType == RecordTypes.Container && parent.RecordType == RecordTypes.Character)
                {
                    ContainerRecord containerRecord = (ContainerRecord)parent.Children[i];
                    if (containerRecord.IsWagon)
                    {
                        textLabel += " [Wagon]";
                    }
                }

                EditorGUILayout.LabelField(textLabel);
                GUILayoutHelper.Indent(() =>
                {
                    DisplaySaveTree(parent.Children[i]);
                });
            }
        }
        void RestoreOldClassSpecials(SaveTree saveTree, Races classicTransformedRace)
        {
            try
            {
                // Get old class record
                SaveTreeBaseRecord oldClassRecord = saveTree.FindRecord(RecordTypes.OldClass);
                if (oldClassRecord == null)
                {
                    return;
                }

                // Read old class data
                System.IO.MemoryStream stream = new System.IO.MemoryStream(oldClassRecord.RecordData);
                System.IO.BinaryReader reader = new System.IO.BinaryReader(stream);
                ClassFile classFile           = new ClassFile();
                classFile.Load(reader);
                reader.Close();

                // Restore any specials set by transformed race
                if (classicTransformedRace == Races.Vampire)
                {
                    // Restore pre-vampire specials
                    characterDocument.career.DamageFromSunlight   = classFile.Career.DamageFromSunlight;
                    characterDocument.career.DamageFromHolyPlaces = classFile.Career.DamageFromHolyPlaces;
                    characterDocument.career.Paralysis            = classFile.Career.Paralysis;
                    characterDocument.career.Disease = classFile.Career.Disease;
                }
                else if (classicTransformedRace == Races.Werewolf)
                {
                    // TODO: Restore pre-werewolf specials
                }
                else if (classicTransformedRace == Races.Wereboar)
                {
                    // TODO: Restore pre-wereboar specials
                }
            }
            catch (Exception ex)
            {
                Debug.LogErrorFormat("Could not restore old class specials for vamp/were import. Error: '{0}'", ex.Message);
            }
        }
        string GetItemOrSpellName(SaveTreeBaseRecord record)
        {
            string result = string.Empty;

            byte[]       recordData = record.RecordData;
            MemoryStream stream     = new MemoryStream(recordData);
            BinaryReader reader     = new BinaryReader(stream);

            if (record.RecordType == RecordTypes.Item)
            {
                result = FileProxy.ReadCString(reader);         // Name starts at offset 0
            }
            else if (record.RecordType == RecordTypes.Spell)
            {
                reader.BaseStream.Position += 47;               // Name starts at offset 47
                result = FileProxy.ReadCString(reader);
            }

            reader.Close();

            return(result);
        }
        void DisplaySaveTree(SaveTreeBaseRecord parent)
        {
            for (int i = 0; i < parent.Children.Count; i++)
            {
                RecordTypes recordType = parent.Children[i].RecordType;
                if (recordType == RecordTypes.UnknownTownLink || recordType == RecordTypes.UnknownItemRecord)
                {
                    continue;
                }

                string textLabel = recordType.ToString();
                if (recordType == RecordTypes.Item || recordType == RecordTypes.Spell)
                {
                    textLabel += string.Format(" [{0}]", GetItemOrSpellName(parent.Children[i]));
                }

                EditorGUILayout.LabelField(textLabel);
                GUILayoutHelper.Indent(() =>
                {
                    DisplaySaveTree(parent.Children[i]);
                });
            }
        }
        void StartFromClassicSave()
        {
            DaggerfallUnity.ResetUID();
            QuestMachine.Instance.ClearState();
            RaiseOnNewGameEvent();
            ResetWeaponManager();

            // Save index must be in range
            if (classicSaveIndex < 0 || classicSaveIndex >= 6)
            {
                throw new IndexOutOfRangeException("classicSaveIndex out of range.");
            }

            // Open saves in parent path of Arena2 folder
            string    path      = SaveLoadManager.Instance.DaggerfallSavePath;
            SaveGames saveGames = new SaveGames(path);

            if (!saveGames.IsPathOpen)
            {
                throw new Exception(string.Format("Could not open Daggerfall saves path {0}", path));
            }

            // Open save index
            if (!saveGames.TryOpenSave(classicSaveIndex))
            {
                string error = string.Format("Could not open classic save index {0}.", classicSaveIndex);
                DaggerfallUI.MessageBox(error);
                DaggerfallUnity.LogMessage(string.Format(error), true);
                return;
            }

            // Get required save data
            SaveTree saveTree = saveGames.SaveTree;
            SaveVars saveVars = saveGames.SaveVars;

            SaveTreeBaseRecord positionRecord = saveTree.FindRecord(RecordTypes.CharacterPositionRecord);

            if (NoWorld)
            {
                playerEnterExit.DisableAllParents();
            }
            else
            {
                // Set player to world position
                playerEnterExit.EnableExteriorParent();
                StreamingWorld streamingWorld = FindStreamingWorld();
                int            worldX         = positionRecord.RecordRoot.Position.WorldX;
                int            worldZ         = positionRecord.RecordRoot.Position.WorldZ;
                streamingWorld.TeleportToWorldCoordinates(worldX, worldZ);
                streamingWorld.suppressWorld = false;
            }

            GameObject      cameraObject = GameObject.FindGameObjectWithTag("MainCamera");
            PlayerMouseLook mouseLook    = cameraObject.GetComponent <PlayerMouseLook>();

            if (mouseLook)
            {
                // Classic save value ranges from -256 (looking up) to 256 (looking down).
                // The maximum up and down range of view in classic is similar to 45 degrees up and down in DF Unity.
                float pitch = positionRecord.RecordRoot.Pitch;
                if (pitch != 0)
                {
                    pitch = (pitch * 45 / 256);
                }
                mouseLook.Pitch = pitch;

                float yaw = positionRecord.RecordRoot.Yaw;
                // In classic saves 2048 units of yaw is 360 degrees.
                if (yaw != 0)
                {
                    yaw = (yaw * 360 / 2048);
                }
                mouseLook.Yaw = yaw;
            }

            // Set whether the player's weapon is drawn
            WeaponManager weaponManager = GameManager.Instance.WeaponManager;

            weaponManager.Sheathed = (!saveVars.WeaponDrawn);

            // Set game time
            DaggerfallUnity.Instance.WorldTime.Now.FromClassicDaggerfallTime(saveVars.GameTime);

            // Get character record
            List <SaveTreeBaseRecord> records = saveTree.FindRecords(RecordTypes.Character);

            if (records.Count != 1)
            {
                throw new Exception("SaveTree CharacterRecord not found.");
            }

            // Get prototypical character document data
            CharacterRecord characterRecord = (CharacterRecord)records[0];

            characterDocument = characterRecord.ToCharacterDocument();

            // Assign data to player entity
            PlayerEntity playerEntity = FindPlayerEntity();

            playerEntity.AssignCharacter(characterDocument, characterRecord.ParsedData.level, characterRecord.ParsedData.maxHealth, false);

            // Assign biography modifiers
            playerEntity.BiographyResistDiseaseMod = saveVars.BiographyResistDiseaseMod;
            playerEntity.BiographyResistMagicMod   = saveVars.BiographyResistMagicMod;
            playerEntity.BiographyAvoidHitMod      = saveVars.BiographyAvoidHitMod;
            playerEntity.BiographyResistPoisonMod  = saveVars.BiographyResistPoisonMod;
            playerEntity.BiographyFatigueMod       = saveVars.BiographyFatigueMod;

            // Assign faction data
            playerEntity.FactionData.ImportClassicReputation(saveVars);

            // Assign global variables
            playerEntity.GlobalVars.ImportClassicGlobalVars(saveVars);

            // Set time of last check for raising skills
            playerEntity.TimeOfLastSkillIncreaseCheck = saveVars.LastSkillCheckTime;

            // Assign items to player entity
            playerEntity.AssignItems(saveTree);

            // Assign guild memberships
            playerEntity.AssignGuildMemberships(saveTree);

            // Assign diseases and poisons to player entity
            playerEntity.AssignDiseasesAndPoisons(saveTree);

            // Assign gold pieces
            playerEntity.GoldPieces = (int)characterRecord.ParsedData.physicalGold;

            // Assign weapon hand being used
            weaponManager.UsingRightHand = !saveVars.UsingLeftHandWeapon;

            // GodMode setting
            playerEntity.GodMode = saveVars.GodMode;

            // Setup bank accounts
            var bankRecords = saveTree.FindRecord(RecordTypes.BankAccount);

            Banking.DaggerfallBankManager.ReadNativeBankData(bankRecords);

            // Get regional data.
            playerEntity.RegionData = saveVars.RegionData;

            // Set time tracked by playerEntity for game minute-based updates
            playerEntity.LastGameMinutes = saveVars.GameTime;

            // Get breath remaining if player was submerged (0 if they were not in the water)
            playerEntity.CurrentBreath = saveVars.BreathRemaining;

            // TODO: Import classic spellbook
            playerEntity.DeserializeSpellbook(null);

            // Get last type of crime committed
            playerEntity.CrimeCommitted = (PlayerEntity.Crimes)saveVars.CrimeCommitted;

            // Get weather
            byte[] climateWeathers = saveVars.ClimateWeathers;

            // Enums for thunder and snow are reversed in classic and Unity, so they are converted here.
            for (int i = 0; i < climateWeathers.Length; i++)
            {
                // TODO: 0x80 flag can be set for snow or rain, to add fog to these weathers. This isn't in DF Unity yet, so
                // temporarily removing the flag.
                climateWeathers[i] &= 0x7f;
                if (climateWeathers[i] == 5)
                {
                    climateWeathers[i] = 6;
                }
                else if (climateWeathers[i] == 6)
                {
                    climateWeathers[i] = 5;
                }
            }
            GameManager.Instance.WeatherManager.PlayerWeather.ClimateWeathers = climateWeathers;

            // Load character biography text
            playerEntity.BackStory = saveGames.BioFile.Lines;

            // Validate spellbook item
            DaggerfallUnity.Instance.ItemHelper.ValidateSpellbookItem(playerEntity);

            // Start game
            DaggerfallUI.Instance.PopToHUD();
            GameManager.Instance.PauseGame(false);
            DaggerfallUI.Instance.FadeBehaviour.FadeHUDFromBlack();
            DaggerfallUI.PostMessage(PostStartMessage);

            lastStartMethod = StartMethods.LoadClassicSave;
            SaveIndex       = -1;

            if (OnStartGame != null)
            {
                OnStartGame(this, null);
            }
        }
        void DisplaySaveStatsGUI()
        {
            if (currentSaveTree == null)
            {
                return;
            }

            SaveTreeBaseRecord positionRecord = currentSaveTree.FindRecord(RecordTypes.CharacterPositionRecord);

            EditorGUILayout.Space();
            GUILayoutHelper.Horizontal(() =>
            {
                EditorGUILayout.LabelField(new GUIContent("Version"), GUILayout.Width(EditorGUIUtility.labelWidth - 4));
                EditorGUILayout.SelectableLabel(currentSaveTree.Header.Version.ToString(), EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
            });
            GUILayoutHelper.Horizontal(() =>
            {
                string positionText = string.Format("X={0}, Y={1}, Z={2}",
                                                    positionRecord.RecordRoot.Position.WorldX,
                                                    positionRecord.RecordRoot.Position.WorldY,
                                                    positionRecord.RecordRoot.Position.WorldZ);

                EditorGUILayout.LabelField(new GUIContent("Player Position", "Position of player in the world."), GUILayout.Width(EditorGUIUtility.labelWidth - 4));
                EditorGUILayout.SelectableLabel(positionText, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
            });
            GUILayoutHelper.Horizontal(() =>
            {
                DFPosition mapPixel = MapsFile.WorldCoordToMapPixel(positionRecord.RecordRoot.Position.WorldX, positionRecord.RecordRoot.Position.WorldZ);
                string mapPixelText = string.Format("X={0}, Y={1}", mapPixel.X, mapPixel.Y);

                EditorGUILayout.LabelField(new GUIContent("Player Map Pixel", "Position of player on small map."), GUILayout.Width(EditorGUIUtility.labelWidth - 4));
                EditorGUILayout.SelectableLabel(mapPixelText, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
            });
            GUILayoutHelper.Horizontal(() =>
            {
                DaggerfallDateTime time = new DaggerfallDateTime();
                time.FromClassicDaggerfallTime(currentSaveVars.GameTime);

                EditorGUILayout.LabelField(new GUIContent("Player Time", "World time of this save."), GUILayout.Width(EditorGUIUtility.labelWidth - 4));
                EditorGUILayout.SelectableLabel(time.LongDateTimeString(), EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
            });
            GUILayoutHelper.Horizontal(() =>
            {
                EditorGUILayout.LabelField(new GUIContent("Player Environment"), GUILayout.Width(EditorGUIUtility.labelWidth - 4));
                EditorGUILayout.SelectableLabel(((Environments)currentSaveTree.Header.Environment).ToString(), EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
            });
            GUILayoutHelper.Horizontal(() =>
            {
                EditorGUILayout.LabelField(new GUIContent("RecordElement records"), GUILayout.Width(EditorGUIUtility.labelWidth - 4));
                EditorGUILayout.SelectableLabel(currentSaveTree.RecordDictionary.Count.ToString(), EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
            });
            //GUILayoutHelper.Horizontal(() =>
            //{
            //    EditorGUILayout.LabelField(new GUIContent("Header.Unknown"), GUILayout.Width(EditorGUIUtility.labelWidth - 4));
            //    EditorGUILayout.SelectableLabel(currentSaveTree.Header.Unknown.ToString(), EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
            //});
            //GUILayoutHelper.Horizontal(() =>
            //{
            //    EditorGUILayout.LabelField(new GUIContent("CharacterPosition.Unknown"), GUILayout.Width(EditorGUIUtility.labelWidth - 4));
            //    EditorGUILayout.SelectableLabel(currentSaveTree.Header.CharacterPosition.Unknown.ToString(), EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
            //});
        }
Example #9
0
        void StartFromClassicSave()
        {
            DaggerfallUnity.ResetUID();
            QuestMachine.Instance.ClearState();
            RaiseOnNewGameEvent();
            ResetWeaponManager();

            // Save index must be in range
            if (classicSaveIndex < 0 || classicSaveIndex >= 6)
            {
                throw new IndexOutOfRangeException("classicSaveIndex out of range.");
            }

            // Open saves in parent path of Arena2 folder
            string    path      = SaveLoadManager.Instance.DaggerfallSavePath;
            SaveGames saveGames = new SaveGames(path);

            if (!saveGames.IsPathOpen)
            {
                throw new Exception(string.Format("Could not open Daggerfall saves path {0}", path));
            }

            // Open save index
            if (!saveGames.TryOpenSave(classicSaveIndex))
            {
                string error = string.Format("Could not open classic save index {0}.", classicSaveIndex);
                DaggerfallUI.MessageBox(error);
                DaggerfallUnity.LogMessage(string.Format(error), true);
                return;
            }

            // Get required save data
            SaveTree saveTree = saveGames.SaveTree;
            SaveVars saveVars = saveGames.SaveVars;

            SaveTreeBaseRecord positionRecord = saveTree.FindRecord(RecordTypes.CharacterPositionRecord);

            if (NoWorld)
            {
                playerEnterExit.DisableAllParents();
            }
            else
            {
                // Set player to world position
                playerEnterExit.EnableExteriorParent();
                StreamingWorld streamingWorld = FindStreamingWorld();
                int            worldX         = positionRecord.RecordRoot.Position.WorldX;
                int            worldZ         = positionRecord.RecordRoot.Position.WorldZ;
                streamingWorld.TeleportToWorldCoordinates(worldX, worldZ);
                streamingWorld.suppressWorld = false;
            }

            GameObject      cameraObject = GameObject.FindGameObjectWithTag("MainCamera");
            PlayerMouseLook mouseLook    = cameraObject.GetComponent <PlayerMouseLook>();

            if (mouseLook)
            {
                // Classic save value ranges from -256 (looking up) to 256 (looking down).
                // The maximum up and down range of view in classic is similar to 45 degrees up and down in DF Unity.
                float pitch = positionRecord.RecordRoot.Pitch;
                if (pitch != 0)
                {
                    pitch = (pitch * 45 / 256);
                }
                mouseLook.Pitch = pitch;

                float yaw = positionRecord.RecordRoot.Yaw;
                // In classic saves 2048 units of yaw is 360 degrees.
                if (yaw != 0)
                {
                    yaw = (yaw * 360 / 2048);
                }
                mouseLook.Yaw = yaw;
            }

            // Set whether the player's weapon is drawn
            GameManager.Instance.WeaponManager.Sheathed = (!saveVars.WeaponDrawn);

            // Set game time
            DaggerfallUnity.Instance.WorldTime.Now.FromClassicDaggerfallTime(saveVars.GameTime);

            // Get character record
            List <SaveTreeBaseRecord> records = saveTree.FindRecords(RecordTypes.Character);

            if (records.Count != 1)
            {
                throw new Exception("SaveTree CharacterRecord not found.");
            }

            // Get prototypical character document data
            CharacterRecord characterRecord = (CharacterRecord)records[0];

            characterDocument = characterRecord.ToCharacterDocument();

            // Assign data to player entity
            PlayerEntity playerEntity = FindPlayerEntity();

            playerEntity.AssignCharacter(characterDocument, characterRecord.ParsedData.level, characterRecord.ParsedData.maxHealth, false);

            // Assign biography modifiers
            playerEntity.BiographyResistDiseaseMod = saveVars.BiographyResistDiseaseMod;
            playerEntity.BiographyResistMagicMod   = saveVars.BiographyResistMagicMod;
            playerEntity.BiographyAvoidHitMod      = saveVars.BiographyAvoidHitMod;
            playerEntity.BiographyResistPoisonMod  = saveVars.BiographyResistPoisonMod;
            playerEntity.BiographyFatigueMod       = saveVars.BiographyFatigueMod;

            // Assign faction data
            playerEntity.FactionData.ImportClassicReputation(saveVars);

            // Assign global variables
            playerEntity.GlobalVars.ImportClassicGlobalVars(saveVars);

            // Set time of last check for raising skills
            playerEntity.TimeOfLastSkillIncreaseCheck = saveVars.LastSkillCheckTime;

            // Assign items to player entity
            playerEntity.AssignItems(saveTree);

            // Assign gold pieces
            playerEntity.GoldPieces = (int)characterRecord.ParsedData.physicalGold;

            // GodMode setting
            playerEntity.GodMode = saveVars.GodMode;

            // Setup bank accounts
            var bankRecords = saveTree.FindRecord(RecordTypes.BankAccount);

            Banking.DaggerfallBankManager.ReadNativeBankData(bankRecords);

            // Get regional data.
            playerEntity.RegionData = saveVars.RegionData;

            // Set time tracked by playerEntity for game minute-based updates
            playerEntity.LastGameMinutes = saveVars.GameTime;

            // Start game
            DaggerfallUI.Instance.PopToHUD();
            GameManager.Instance.PauseGame(false);
            DaggerfallUI.Instance.FadeHUDFromBlack();
            DaggerfallUI.PostMessage(PostStartMessage);

            lastStartMethod = StartMethods.LoadClassicSave;
            SaveIndex       = -1;

            if (OnStartGame != null)
            {
                OnStartGame(this, null);
            }
        }