CapersProject/Assets/Plugins/Pixel Crushers/Dialogue System/Scripts/Save System/GameSaver.cs

286 lines
10 KiB
C#

// Copyright (c) Pixel Crushers. All rights reserved.
using UnityEngine;
namespace PixelCrushers.DialogueSystem
{
/// <summary>
/// Allows you to save and load games to the SaveSystem or PlayerPrefs without writing any scripts.
/// To use this component:
///
/// -# Add this component to a game object.
/// -# Set the playerPrefs key (i.e., saved game slot) where the game will be saved and loaded.
/// To make multiple slots, you can add more GamerSaver components to change the playerPrefsKey
/// field.
/// -# To save a game, send the message "SaveGame" to this component (or call it from a script).
/// For example, you can use the SendMessageOnConversation component to send the message.
/// -# To load a game, send the message "LoadGame" to this component (or call it from a script).
/// -# To restart the game, send the message "RestartGame" (or call it from a script).
/// -# To record the state of the game without saving, for example when changing levels, send
/// the "Record" message.
/// -# To apply the saved state of the game, for example when returning to a level, send the
/// "Apply" message.
/// -# You can also configure this component to save or load when the player "uses" the game
/// object. To do this:
/// - Set Function On Use to Save or Load. This tells the component whether to save or load
/// when it receives an OnUse message.
/// - Send the message "OnUse" to this component or game object. For example, the sample
/// Selector component sends OnUse when the player hits spacebar over the object.
/// -# If you tick Apply Game State When Loading Levels, then this component will automatically
/// apply the recorded game state as soon as the level is loaded. You're responsible for
/// issuing the "Record" message before loading the level. You can use PersistentDataManager to
/// do this.
/// -# If the scene contains a LevelManager, it will load using the LevelManager
/// instead of just applying the saved-game data.
/// </summary>
[AddComponentMenu("")] // Use wrapper.
public class GameSaver : MonoBehaviour
{
public enum FunctionOnUse { None, Save, Load, Restart };
/// <summary>
/// The root of the PlayerPrefs key where the game will be saved and loaded.
/// </summary>
public string playerPrefsKey = "savedgame";
/// <summary>
/// The default slot. This number is appended to playerPrefsKey to make the complete
/// PlayerPrefs key.
/// </summary>
public int slot = 0;
/// <summary>
/// The function (save or load) to perform when receiving the "OnUse" message.
/// </summary>
public FunctionOnUse functionOnUse = FunctionOnUse.None;
/// <summary>
/// If <c>true</c>, saved-game data will include all item fields. If <c>false</c>,
/// it will only include quests' State and Track fields.
/// </summary>
public bool includeAllItemData = false;
/// <summary>
/// If <c>true</c>, saved-game data will include all location fields. If <c>false</c>,
/// it will not include any location fields.
/// </summary>
public bool includeLocationData = false;
/// <summary>
/// If <c>true</c>, saved-game data will include the offered/spoken status of
/// all dialogue entries.
/// </summary>
public bool includeSimStatus = false;
/// <summary>
/// The starting level to use when restarting the game.
/// </summary>
public string startingLevel = string.Empty;
/// <summary>
/// If <c>true</c>, this game object isn't destroyed when you load a new level.
/// </summary>
public bool dontDestroyOnLoad = false;
public void Awake()
{
if (dontDestroyOnLoad)
{
this.transform.parent = null;
DontDestroyOnLoad(this.gameObject);
}
PersistentDataManager.includeAllItemData = includeAllItemData;
PersistentDataManager.includeLocationData = includeLocationData;
PersistentDataManager.includeSimStatus = includeSimStatus;
}
/// <summary>
/// Upon receiving an "OnUse" message, this method saves, loads, or does nothing, based on
/// the value of functionOnUse.
/// </summary>
public void OnUse()
{
switch (functionOnUse)
{
case FunctionOnUse.Save:
SaveGame(); break;
case FunctionOnUse.Load:
LoadGame(); break;
default:
break;
}
}
/// <summary>
/// Saves the game under the PlayerPrefs key, adding the slot number to support multiple
/// save game slots.
/// </summary>
/// <param name='slot'>
/// The slot to use.
/// </param>
public void SaveGame(int slot)
{
if (SaveSystem.instance != null)
{
SaveSystem.SaveToSlot(slot);
}
else
{
if (string.IsNullOrEmpty(playerPrefsKey))
{
if (DialogueDebug.logWarnings) Debug.LogWarning(string.Format("{0}: PlayerPrefs Key isn't set. Not saving.", new System.Object[] { DialogueDebug.Prefix }));
return;
}
if (DialogueDebug.logInfo) Debug.Log(string.Format("{0}: Saving game in slot {1}.", new System.Object[] { DialogueDebug.Prefix, slot }));
string key = playerPrefsKey + slot.ToString();
PlayerPrefs.SetString(key, PersistentDataManager.GetSaveData());
}
}
/// <summary>
/// Saves the game in default slot 0.
/// </summary>
public void SaveGame()
{
SaveGame(slot);
}
/// <summary>
/// Loads the game from the data saved under the PlayerPrefs key.
/// </summary>
public void LoadGame(int slot)
{
if (SaveSystem.instance != null)
{
SaveSystem.LoadFromSlot(slot);
}
else
{
if (string.IsNullOrEmpty(playerPrefsKey))
{
if (DialogueDebug.logWarnings) Debug.LogWarning(string.Format("{0}: PlayerPrefs Key isn't set. Not loading.", new System.Object[] { DialogueDebug.Prefix }));
return;
}
string key = playerPrefsKey + slot.ToString();
if (!PlayerPrefs.HasKey(key))
{
if (DialogueDebug.logWarnings) Debug.LogWarning(string.Format("{0}: No saved game in PlayerPrefs key '{1}'. Not loading.", new System.Object[] { DialogueDebug.Prefix, key }));
return;
}
if (DialogueDebug.logInfo) Debug.Log(string.Format("{0}: Loading save data from slot {1} and applying it.", new System.Object[] { DialogueDebug.Prefix, slot }));
// Load using the LevelManager if available; otherwise just apply saved-game data:
string saveData = PlayerPrefs.GetString(key);
LevelManager levelManager = FindLevelManager();
if (levelManager != null)
{
levelManager.LoadGame(saveData);
}
else
{
PersistentDataManager.ApplySaveData(saveData, DatabaseResetOptions.KeepAllLoaded);
DialogueManager.SendUpdateTracker(); // Update quest tracker HUD.
}
}
}
/// <summary>
/// Loads the game from default slot 0.
/// </summary>
public void LoadGame()
{
LoadGame(slot);
}
/// <summary>
/// Saves the game using a string parameter for the slot number.
/// </summary>
/// <param name='slotString'>
/// Slot string to convert to an int.
/// </param>
public void SaveGame(string slotString)
{
SaveGame(StringToSlot(slotString));
}
/// <summary>
/// Loads the game using a string parameter for the slot number.
/// </summary>
/// <param name='slotString'>
/// Slot string to convert to an int.
/// </param>
public void LoadGame(string slotString)
{
LoadGame(StringToSlot(slotString));
}
/// <summary>
/// Restarts the game.
/// </summary>
public void RestartGame()
{
LevelManager levelManager = FindLevelManager();
if (SaveSystem.instance != null)
{
var startingSceneName = (levelManager != null && !string.IsNullOrEmpty(levelManager.defaultStartingLevel)) ? levelManager.defaultStartingLevel : startingLevel;
SaveSystem.RestartGame(startingSceneName);
}
else
{
if (levelManager != null)
{
levelManager.RestartGame();
}
else
{
DialogueManager.ResetDatabase(DatabaseResetOptions.RevertToDefault);
if (string.IsNullOrEmpty(startingLevel))
{
Tools.LoadLevel(0);
}
else
{
Tools.LoadLevel(startingLevel);
}
// Update quest tracker HUD:
DialogueManager.SendUpdateTracker();
}
}
}
private LevelManager FindLevelManager()
{
var levelManager = GetComponentInChildren<LevelManager>();
if (levelManager == null) levelManager = GameObjectUtility.FindFirstObjectByType<LevelManager>();
return levelManager;
}
private int StringToSlot(string slotString)
{
int slot = 0;
int.TryParse(slotString, out slot);
return slot;
}
/// <summary>
/// Records the state of the game.
/// </summary>
public void Record()
{
PersistentDataManager.Record();
}
/// <summary>
/// Applies the recorded state of the game to the current scene.
/// </summary>
public void Apply()
{
PersistentDataManager.Apply();
}
}
}