IEnumerator LoadGame(string path)
        {
            GameManager.Instance.PlayerDeath.ClearDeathAnimation();
            GameManager.Instance.PlayerMotor.CancelMovement = true;
            InputManager.Instance.ClearAllActions();
            QuestMachine.Instance.ClearState();
            stateManager.ClearSceneCache();
            PlayerEntity playerEntity = GameManager.Instance.PlayerEntity;

            playerEntity.Reset();

            // Read save data from files
            string saveDataJson         = ReadSaveFile(Path.Combine(path, saveDataFilename));
            string factionDataJson      = ReadSaveFile(Path.Combine(path, factionDataFilename));
            string questDataJson        = ReadSaveFile(Path.Combine(path, questDataFilename));
            string discoveryDataJson    = ReadSaveFile(Path.Combine(path, discoveryDataFilename));
            string conversationDataJson = ReadSaveFile(Path.Combine(path, conversationDataFilename));
            string notebookDataJson     = ReadSaveFile(Path.Combine(path, notebookDataFilename));

            // Load backstory text
            playerEntity.BackStory = new List <string>();
            if (File.Exists(Path.Combine(path, bioFileName)))
            {
                StreamReader file = new StreamReader(Path.Combine(path, bioFileName).ToString());
                string       line;
                while ((line = file.ReadLine()) != null)
                {
                    playerEntity.BackStory.Add(line);
                }
                file.Close();
            }

            // Deserialize JSON strings
            SaveData_v1 saveData = Deserialize(typeof(SaveData_v1), saveDataJson) as SaveData_v1;

            // Must have a serializable player
            if (!stateManager.SerializablePlayer)
            {
                yield break;
            }

            // Call start load event
            RaiseOnStartLoadEvent(saveData);

            // Immediately set date so world is loaded with correct season
            RestoreDateTimeData(saveData.dateAndTime);

            // Restore discovery data
            if (!string.IsNullOrEmpty(discoveryDataJson))
            {
                Dictionary <int, PlayerGPS.DiscoveredLocation> discoveryData =
                    Deserialize(typeof(Dictionary <int, PlayerGPS.DiscoveredLocation>), discoveryDataJson) as Dictionary <int, PlayerGPS.DiscoveredLocation>;
                GameManager.Instance.PlayerGPS.RestoreDiscoveryData(discoveryData);
            }
            else
            {
                // Clear discovery data when not in save, or live state will be retained from previous session
                GameManager.Instance.PlayerGPS.ClearDiscoveryData();
            }

            // Must have PlayerEnterExit to respawn player at saved location
            PlayerEnterExit playerEnterExit = stateManager.SerializablePlayer.GetComponent <PlayerEnterExit>();

            if (!playerEnterExit)
            {
                yield break;
            }

            // Restore building summary, house ownership, and guild membership early for interior layout code
            if (saveData.playerData.playerPosition.insideBuilding)
            {
                playerEnterExit.BuildingDiscoveryData  = saveData.playerData.playerPosition.buildingDiscoveryData;
                playerEnterExit.IsPlayerInsideOpenShop = saveData.playerData.playerPosition.insideOpenShop;
                if (saveData.bankDeeds != null)
                {
                    RestoreHousesData(saveData.bankDeeds.houses);
                }
                GameManager.Instance.GuildManager.RestoreMembershipData(saveData.playerData.guildMemberships);
            }

            // Restore faction data to player entity
            // This is done early as later objects may require faction information on restore
            if (!string.IsNullOrEmpty(factionDataJson))
            {
                FactionData_v2 factionData = Deserialize(typeof(FactionData_v2), factionDataJson) as FactionData_v2;
                stateManager.RestoreFactionData(factionData);
                Debug.Log("LoadGame() restored faction state from save.");
            }
            else
            {
                Debug.Log("LoadGame() did not find saved faction data. Player will resume with default faction state.");
            }

            // Restore quest machine state
            if (!string.IsNullOrEmpty(questDataJson))
            {
                QuestMachine.QuestMachineData_v1 questData = Deserialize(typeof(QuestMachine.QuestMachineData_v1), questDataJson) as QuestMachine.QuestMachineData_v1;
                QuestMachine.Instance.RestoreSaveData(questData);
            }

            // Restore conversation data (must be done after quest data restoration)
            if (!string.IsNullOrEmpty(conversationDataJson))
            {
                TalkManager.SaveDataConversation conversationData = Deserialize(typeof(TalkManager.SaveDataConversation), conversationDataJson) as TalkManager.SaveDataConversation;
                GameManager.Instance.TalkManager.RestoreConversationData(conversationData);
            }
            else
            {
                GameManager.Instance.TalkManager.RestoreConversationData(null);
            }

            // Restore notebook data
            if (!string.IsNullOrEmpty(notebookDataJson))
            {
                PlayerNotebook.NotebookData_v1 notebookData = Deserialize(typeof(PlayerNotebook.NotebookData_v1), notebookDataJson) as PlayerNotebook.NotebookData_v1;
                playerEntity.Notebook.RestoreNotebookData(notebookData);
            }

            // Restore player position to world
            playerEnterExit.RestorePositionHelper(saveData.playerData.playerPosition, true, false);

            //Restore Travel Map settings
            DaggerfallUI.Instance.DfTravelMapWindow.SetTravelMapFromSaveData(saveData.travelMapData);

            // Smash to black while respawning
            DaggerfallUI.Instance.FadeBehaviour.SmashHUDToBlack();

            // Keep yielding frames until world is ready again
            while (playerEnterExit.IsRespawning)
            {
                yield return(new WaitForEndOfFrame());
            }

            // Wait another frame so everthing has a chance to register
            yield return(new WaitForEndOfFrame());

            // Restore save data to objects in newly spawned world
            RestoreSaveData(saveData);

            // Load automap state
            try
            {
                string automapDataJson = ReadSaveFile(Path.Combine(path, automapDataFilename));
                Dictionary <string, Automap.AutomapDungeonState> automapState = null;

                if (!string.IsNullOrEmpty(automapDataJson))
                {
                    automapState = Deserialize(typeof(Dictionary <string, Automap.AutomapDungeonState>), automapDataJson) as Dictionary <string, Automap.AutomapDungeonState>;
                }

                if (automapState != null)
                {
                    GameManager.Instance.InteriorAutomap.SetState(automapState);
                }
            }
            catch (Exception ex)
            {
                string message = string.Format("Failed to load automap state. Message: {0}", ex.Message);
                Debug.Log(message);
            }

            // Clear any orphaned quest items
            RemoveAllOrphanedItems();

            // Check mod manager is available
            if (ModManager.Instance != null)
            {
                // Restore mod data
                foreach (Mod mod in ModManager.Instance.GetAllModsWithSaveData())
                {
                    string modDataPath = Path.Combine(path, GetModDataFilename(mod));
                    object modData;
                    if (File.Exists(modDataPath))
                    {
                        modData = Deserialize(mod.SaveDataInterface.SaveDataType, ReadSaveFile(modDataPath));
                    }
                    else
                    {
                        modData = mod.SaveDataInterface.NewSaveData();
                    }
                    mod.SaveDataInterface.RestoreSaveData(modData);
                }
            }

            // Clamp legal reputation
            playerEntity.ClampLegalReputations();

            // Lower load in progress flag
            loadInProgress = false;

            // Fade out from black
            DaggerfallUI.Instance.FadeBehaviour.FadeHUDFromBlack(1.0f);

            // Raise OnLoad event
            RaiseOnLoadEvent(saveData);
        }
示例#2
0
        IEnumerator SaveGame(string saveName, string path)
        {
            // Build save data
            SaveData_v1 saveData = BuildSaveData();

            // Build save info
            SaveInfo_v1 saveInfo = new SaveInfo_v1();

            saveInfo.saveVersion   = LatestSaveVersion;
            saveInfo.saveName      = saveName;
            saveInfo.characterName = saveData.playerData.playerEntity.name;
            saveInfo.dateAndTime   = saveData.dateAndTime;

            // Build faction data
            FactionData_v2 factionData = stateManager.GetPlayerFactionData();

            // Build quest data
            QuestMachine.QuestMachineData_v1 questData = QuestMachine.Instance.GetSaveData();

            // Get discovery data
            Dictionary <int, PlayerGPS.DiscoveredLocation> discoveryData = GameManager.Instance.PlayerGPS.GetDiscoverySaveData();

            // Get conversation data
            TalkManager.SaveDataConversation conversationData = GameManager.Instance.TalkManager.GetConversationSaveData();

            // Serialize save data to JSON strings
            string saveDataJson         = Serialize(saveData.GetType(), saveData);
            string saveInfoJson         = Serialize(saveInfo.GetType(), saveInfo);
            string factionDataJson      = Serialize(factionData.GetType(), factionData);
            string questDataJson        = Serialize(questData.GetType(), questData);
            string discoveryDataJson    = Serialize(discoveryData.GetType(), discoveryData);
            string conversationDataJson = Serialize(conversationData.GetType(), conversationData);

            // Create screenshot for save
            // TODO: Hide UI for screenshot or use a different method
            yield return(new WaitForEndOfFrame());

            Texture2D screenshot = new Texture2D(Screen.width, Screen.height);

            screenshot.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
            screenshot.Apply();

            // Save data to files
            WriteSaveFile(Path.Combine(path, saveDataFilename), saveDataJson);
            WriteSaveFile(Path.Combine(path, saveInfoFilename), saveInfoJson);
            WriteSaveFile(Path.Combine(path, factionDataFilename), factionDataJson);
            WriteSaveFile(Path.Combine(path, questDataFilename), questDataJson);
            WriteSaveFile(Path.Combine(path, discoveryDataFilename), discoveryDataJson);
            WriteSaveFile(Path.Combine(path, conversationDataFilename), conversationDataJson);

            // Save automap state
            try
            {
                Dictionary <string, DaggerfallAutomap.AutomapGeometryDungeonState> automapState = GameManager.Instance.InteriorAutomap.GetState();
                string automapDataJson = Serialize(automapState.GetType(), automapState);
                WriteSaveFile(Path.Combine(path, automapDataFilename), automapDataJson);
            }
            catch (Exception ex)
            {
                string message = string.Format("Failed to save automap state. Message: {0}", ex.Message);
                Debug.Log(message);
            }

            // Save screenshot
            byte[] bytes = screenshot.EncodeToJPG();
            File.WriteAllBytes(Path.Combine(path, screenshotFilename), bytes);

            // Raise OnSaveEvent
            RaiseOnSaveEvent(saveData);

            // Notify
            DaggerfallUI.Instance.PopupMessage(HardStrings.gameSaved);
        }
        IEnumerator SaveGame(string saveName, string path, bool instantReload = false)
        {
            // Build save data
            SaveData_v1 saveData = BuildSaveData();

            // Build save info
            SaveInfo_v1 saveInfo = new SaveInfo_v1();

            saveInfo.saveVersion   = LatestSaveVersion;
            saveInfo.saveName      = saveName;
            saveInfo.characterName = saveData.playerData.playerEntity.name;
            saveInfo.dateAndTime   = saveData.dateAndTime;

            // Build faction data
            FactionData_v2 factionData = stateManager.GetPlayerFactionData();

            // Build quest data
            QuestMachine.QuestMachineData_v1 questData = QuestMachine.Instance.GetSaveData();

            // Get discovery data
            Dictionary <int, PlayerGPS.DiscoveredLocation> discoveryData = GameManager.Instance.PlayerGPS.GetDiscoverySaveData();

            // Get conversation data
            TalkManager.SaveDataConversation conversationData = GameManager.Instance.TalkManager.GetConversationSaveData();

            // Get notebook data
            PlayerNotebook.NotebookData_v1 notebookData = GameManager.Instance.PlayerEntity.Notebook.GetNotebookSaveData();

            // Serialize save data to JSON strings
            string saveDataJson         = Serialize(saveData.GetType(), saveData);
            string saveInfoJson         = Serialize(saveInfo.GetType(), saveInfo);
            string factionDataJson      = Serialize(factionData.GetType(), factionData);
            string questDataJson        = Serialize(questData.GetType(), questData);
            string discoveryDataJson    = Serialize(discoveryData.GetType(), discoveryData);
            string conversationDataJson = Serialize(conversationData.GetType(), conversationData);
            string notebookDataJson     = Serialize(notebookData.GetType(), notebookData);

            //// Attempt to hide UI for screenshot
            //bool rawImageEnabled = false;
            //UnityEngine.UI.RawImage rawImage = GUI.GetDiegeticCanvasRawImage();
            //if (rawImage)
            //{
            //    rawImageEnabled = rawImage.enabled;
            //    rawImage.enabled = false;
            //}

            // Create screenshot for save
            // TODO: Hide UI for screenshot or use a different method
            yield return(new WaitForEndOfFrame());

            yield return(new WaitForEndOfFrame());

            Texture2D screenshot = new Texture2D(Screen.width, Screen.height);

            screenshot.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
            screenshot.Apply();

            //// Restore UI after screenshot
            //if (rawImageEnabled)
            //{
            //    rawImage.enabled = true;
            //}

            // Save data to files
            WriteSaveFile(Path.Combine(path, saveDataFilename), saveDataJson);
            WriteSaveFile(Path.Combine(path, saveInfoFilename), saveInfoJson);
            WriteSaveFile(Path.Combine(path, factionDataFilename), factionDataJson);
            WriteSaveFile(Path.Combine(path, questDataFilename), questDataJson);
            WriteSaveFile(Path.Combine(path, discoveryDataFilename), discoveryDataJson);
            WriteSaveFile(Path.Combine(path, conversationDataFilename), conversationDataJson);
            WriteSaveFile(Path.Combine(path, notebookDataFilename), notebookDataJson);

            // Save backstory text
            if (!File.Exists(Path.Combine(path, bioFileName)))
            {
                StreamWriter file = new StreamWriter(Path.Combine(path, bioFileName).ToString());
                foreach (string line in GameManager.Instance.PlayerEntity.BackStory)
                {
                    file.WriteLine(line);
                }
                file.Close();
            }

            // Save automap state
            try
            {
                Dictionary <string, Automap.AutomapDungeonState> automapState = GameManager.Instance.InteriorAutomap.GetState();
                string automapDataJson = Serialize(automapState.GetType(), automapState);
                WriteSaveFile(Path.Combine(path, automapDataFilename), automapDataJson);
            }
            catch (Exception ex)
            {
                string message = string.Format("Failed to save automap state. Message: {0}", ex.Message);
                Debug.Log(message);
            }

            // Save mod data
            if (ModManager.Instance != null)
            {
                foreach (Mod mod in ModManager.Instance.GetAllModsWithSaveData())
                {
                    object modData = mod.SaveDataInterface.GetSaveData();
                    if (modData != null)
                    {
                        string modDataJson = Serialize(modData.GetType(), modData);
                        WriteSaveFile(Path.Combine(path, GetModDataFilename(mod)), modDataJson);
                    }
                    else
                    {
                        File.Delete(Path.Combine(path, GetModDataFilename(mod)));
                    }
                }
            }

            // Save screenshot
            byte[] bytes = screenshot.EncodeToJPG();
            File.WriteAllBytes(Path.Combine(path, screenshotFilename), bytes);

            // Raise OnSaveEvent
            RaiseOnSaveEvent(saveData);

            // Notify
            DaggerfallUI.Instance.PopupMessage(HardStrings.gameSaved);

            // Reload this save instantly if requested
            if (instantReload)
            {
                Load(saveData.playerData.playerEntity.name, saveName);
            }
        }
示例#4
0
        IEnumerator LoadGame(string path)
        {
            GameManager.Instance.PlayerDeath.ClearDeathAnimation();
            GameManager.Instance.PlayerMotor.CancelMovement = true;
            InputManager.Instance.ClearAllActions();
            QuestMachine.Instance.ClearState();
            stateManager.ClearSceneCache();

            // Read save data from files
            string saveDataJson         = ReadSaveFile(Path.Combine(path, saveDataFilename));
            string factionDataJson      = ReadSaveFile(Path.Combine(path, factionDataFilename));
            string questDataJson        = ReadSaveFile(Path.Combine(path, questDataFilename));
            string discoveryDataJson    = ReadSaveFile(Path.Combine(path, discoveryDataFilename));
            string conversationDataJson = ReadSaveFile(Path.Combine(path, conversationDataFilename));

            // Deserialize JSON strings
            SaveData_v1 saveData = Deserialize(typeof(SaveData_v1), saveDataJson) as SaveData_v1;

            // Must have a serializable player
            if (!stateManager.SerializablePlayer)
            {
                yield break;
            }

            // Call start load event
            RaiseOnStartLoadEvent(saveData);

            // Immediately set date so world is loaded with correct season
            RestoreDateTimeData(saveData.dateAndTime);

            // Restore discovery data
            if (!string.IsNullOrEmpty(discoveryDataJson))
            {
                Dictionary <int, PlayerGPS.DiscoveredLocation> discoveryData = Deserialize(typeof(Dictionary <int, PlayerGPS.DiscoveredLocation>), discoveryDataJson) as Dictionary <int, PlayerGPS.DiscoveredLocation>;
                GameManager.Instance.PlayerGPS.RestoreDiscoveryData(discoveryData);
            }
            else
            {
                // Clear discovery data when not in save, or live state will be retained from previous session
                GameManager.Instance.PlayerGPS.ClearDiscoveryData();
            }

            // Restore conversation data
            if (!string.IsNullOrEmpty(conversationDataJson))
            {
                TalkManager.SaveDataConversation conversationData = Deserialize(typeof(TalkManager.SaveDataConversation), conversationDataJson) as TalkManager.SaveDataConversation;
                GameManager.Instance.TalkManager.RestoreConversationData(conversationData);
            }
            else
            {
                GameManager.Instance.TalkManager.RestoreConversationData(null);
            }

            // Must have PlayerEnterExit to respawn player at saved location
            PlayerEnterExit playerEnterExit = stateManager.SerializablePlayer.GetComponent <PlayerEnterExit>();

            if (!playerEnterExit)
            {
                yield break;
            }

            // Check exterior doors are included in save, we need these to exit building
            bool hasExteriorDoors;

            if (saveData.playerData.playerPosition.exteriorDoors == null || saveData.playerData.playerPosition.exteriorDoors.Length == 0)
            {
                hasExteriorDoors = false;
            }
            else
            {
                hasExteriorDoors = true;
            }

            // Restore building summary & house ownership early for interior layout code
            if (saveData.playerData.playerPosition.insideBuilding)
            {
                playerEnterExit.BuildingDiscoveryData  = saveData.playerData.playerPosition.buildingDiscoveryData;
                playerEnterExit.IsPlayerInsideOpenShop = saveData.playerData.playerPosition.insideOpenShop;
                if (saveData.bankDeeds != null)
                {
                    RestoreHousesData(saveData.bankDeeds.houses);
                }
            }

            // Restore faction data to player entity
            // This is done early as later objects may require faction information on restore
            if (!string.IsNullOrEmpty(factionDataJson))
            {
                FactionData_v2 factionData = Deserialize(typeof(FactionData_v2), factionDataJson) as FactionData_v2;
                stateManager.RestoreFactionData(factionData);
                Debug.Log("LoadGame() restored faction state from save.");
            }
            else
            {
                Debug.Log("LoadGame() did not find saved faction data. Player will resume with default faction state.");
            }

            // Restore quest machine state
            if (!string.IsNullOrEmpty(questDataJson))
            {
                QuestMachine.QuestMachineData_v1 questData = Deserialize(typeof(QuestMachine.QuestMachineData_v1), questDataJson) as QuestMachine.QuestMachineData_v1;
                QuestMachine.Instance.RestoreSaveData(questData);
            }

            // Raise reposition flag if terrain sampler changed
            // This is required as changing terrain samplers will invalidate serialized player coordinates
            bool repositionPlayer = false;

            if (saveData.playerData.playerPosition.terrainSamplerName != DaggerfallUnity.Instance.TerrainSampler.ToString() ||
                saveData.playerData.playerPosition.terrainSamplerVersion != DaggerfallUnity.Instance.TerrainSampler.Version)
            {
                repositionPlayer = true;
                if (DaggerfallUI.Instance.DaggerfallHUD != null)
                {
                    DaggerfallUI.Instance.DaggerfallHUD.PopupText.AddText("Terrain sampler changed. Repositioning player.");
                }
            }

            // Raise reposition flag if player is supposed to start indoors but building has no doors
            if (saveData.playerData.playerPosition.insideBuilding && !hasExteriorDoors)
            {
                repositionPlayer = true;
                if (DaggerfallUI.Instance.DaggerfallHUD != null)
                {
                    DaggerfallUI.Instance.DaggerfallHUD.PopupText.AddText("Building has no exterior doors. Repositioning player.");
                }
            }

            // Start the respawn process based on saved player location
            if (saveData.playerData.playerPosition.insideDungeon && !repositionPlayer)
            {
                // Start in dungeon
                playerEnterExit.RespawnPlayer(
                    saveData.playerData.playerPosition.worldPosX,
                    saveData.playerData.playerPosition.worldPosZ,
                    true,
                    false);
            }
            else if (saveData.playerData.playerPosition.insideBuilding && hasExteriorDoors && !repositionPlayer)
            {
                // Start in building
                playerEnterExit.RespawnPlayer(
                    saveData.playerData.playerPosition.worldPosX,
                    saveData.playerData.playerPosition.worldPosZ,
                    saveData.playerData.playerPosition.insideDungeon,
                    saveData.playerData.playerPosition.insideBuilding,
                    saveData.playerData.playerPosition.exteriorDoors);
            }
            else
            {
                // Start outside
                playerEnterExit.RespawnPlayer(
                    saveData.playerData.playerPosition.worldPosX,
                    saveData.playerData.playerPosition.worldPosZ,
                    false,
                    false,
                    null,
                    repositionPlayer);
            }

            // Smash to black while respawning
            DaggerfallUI.Instance.SmashHUDToBlack();

            // Keep yielding frames until world is ready again
            while (playerEnterExit.IsRespawning)
            {
                yield return(new WaitForEndOfFrame());
            }

            // Wait another frame so everthing has a chance to register
            yield return(new WaitForEndOfFrame());

            // Restore save data to objects in newly spawned world
            RestoreSaveData(saveData);

            // Load automap state
            try
            {
                string automapDataJson = ReadSaveFile(Path.Combine(path, automapDataFilename));
                Dictionary <string, DaggerfallAutomap.AutomapGeometryDungeonState> automapState = null;

                if (!string.IsNullOrEmpty(automapDataJson))
                {
                    automapState = Deserialize(typeof(Dictionary <string, DaggerfallAutomap.AutomapGeometryDungeonState>), automapDataJson) as Dictionary <string, DaggerfallAutomap.AutomapGeometryDungeonState>;
                }

                if (automapState != null)
                {
                    GameManager.Instance.InteriorAutomap.SetState(automapState);
                }
            }
            catch (Exception ex)
            {
                string message = string.Format("Failed to load automap state. Message: {0}", ex.Message);
                Debug.Log(message);
            }

            // Clear any orphaned quest items
            RemoveAllOrphanedQuestItems();

            // Lower load in progress flag
            loadInProgress = false;

            // Fade out from black
            DaggerfallUI.Instance.FadeHUDFromBlack(1.0f);

            // Raise OnLoad event
            RaiseOnLoadEvent(saveData);
        }