GameStateManager.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. using UnityEngine;
  2. using UnityEngine.SceneManagement;
  3. public class GameStateManager : MonoBehaviour
  4. {
  5. public static GameStateManager Instance { get; private set; }
  6. [Header("Game State")]
  7. public bool hasActiveGame = false;
  8. public string currentSceneName = "";
  9. public int gameVersion = 1;
  10. [Header("Team Data")]
  11. public TeamCharacter[] savedTeam = new TeamCharacter[4];
  12. public bool teamSetupComplete = false;
  13. [Header("Progress Data")]
  14. public int currentLevel = 1;
  15. public int totalGoldEarned = 0;
  16. public int battlesWon = 0;
  17. public int battlesLost = 0;
  18. [Header("Map Data")]
  19. public bool hasGeneratedMap = false;
  20. public int mapSeed = 0;
  21. public int mapWidth = 100;
  22. public int mapHeight = 100;
  23. public float mapNoiseScale = 5f;
  24. public float mapOceanThreshold = 0.3f;
  25. public float mapMountainThreshold = 0.7f;
  26. public float mapForestThreshold = 0.5f;
  27. [Header("New Game Flags")]
  28. public bool isNewGame = false; // Flag to indicate this is a new game (not a load)
  29. private void Awake()
  30. {
  31. // Implement singleton pattern
  32. if (Instance == null)
  33. {
  34. Instance = this;
  35. DontDestroyOnLoad(gameObject);
  36. // Restore new game flag from PlayerPrefs in case instance was recreated
  37. isNewGame = PlayerPrefs.GetInt("IsNewGame", 0) == 1;
  38. // Subscribe to scene loading events
  39. SceneManager.sceneLoaded += OnSceneLoaded;
  40. }
  41. else
  42. {
  43. Destroy(gameObject);
  44. }
  45. }
  46. private void OnDestroy()
  47. {
  48. if (Instance == this)
  49. {
  50. SceneManager.sceneLoaded -= OnSceneLoaded;
  51. }
  52. }
  53. private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
  54. {
  55. currentSceneName = scene.name;
  56. // Auto-save when moving between scenes (if we have an active game)
  57. if (hasActiveGame && currentSceneName != "TitleScreen")
  58. {
  59. AutoSave();
  60. }
  61. }
  62. public void StartNewGame()
  63. {
  64. // Reset all game state
  65. hasActiveGame = true;
  66. teamSetupComplete = false;
  67. currentLevel = 1;
  68. totalGoldEarned = 0;
  69. battlesWon = 0;
  70. battlesLost = 0;
  71. // Clear team data
  72. savedTeam = new TeamCharacter[4];
  73. // Clear map data
  74. hasGeneratedMap = false;
  75. mapSeed = Random.Range(0, 999999);
  76. // Set new game flag - this will force random team placement
  77. isNewGame = true;
  78. PlayerPrefs.SetInt("IsNewGame", 1); // Store in PlayerPrefs to persist across scenes
  79. PlayerPrefs.Save(); // Force immediate save
  80. // Clear any existing save data
  81. ClearSaveData();
  82. // Mark that we have a new game started
  83. PlayerPrefs.SetInt("GameSaved", 1);
  84. PlayerPrefs.Save();
  85. }
  86. public void SaveGame()
  87. {
  88. if (!hasActiveGame)
  89. {
  90. Debug.LogWarning("No active game to save!");
  91. return;
  92. }
  93. // Save basic game state
  94. PlayerPrefs.SetInt("GameSaved", 1);
  95. PlayerPrefs.SetInt("GameVersion", gameVersion);
  96. PlayerPrefs.SetString("CurrentScene", currentSceneName);
  97. PlayerPrefs.SetInt("TeamSetupComplete", teamSetupComplete ? 1 : 0);
  98. PlayerPrefs.SetInt("CurrentLevel", currentLevel);
  99. PlayerPrefs.SetInt("TotalGoldEarned", totalGoldEarned);
  100. PlayerPrefs.SetInt("BattlesWon", battlesWon);
  101. PlayerPrefs.SetInt("BattlesLost", battlesLost);
  102. // Save team data
  103. SaveTeamData();
  104. // Save map data
  105. SaveMapData();
  106. PlayerPrefs.Save();
  107. }
  108. public void LoadGame()
  109. {
  110. if (!PlayerPrefs.HasKey("GameSaved"))
  111. {
  112. Debug.LogWarning("No saved game found!");
  113. return;
  114. }
  115. // Load basic game state
  116. hasActiveGame = true;
  117. gameVersion = PlayerPrefs.GetInt("GameVersion", 1);
  118. currentSceneName = PlayerPrefs.GetString("CurrentScene", "MainTeamSelectScene");
  119. teamSetupComplete = PlayerPrefs.GetInt("TeamSetupComplete", 0) == 1;
  120. currentLevel = PlayerPrefs.GetInt("CurrentLevel", 1);
  121. totalGoldEarned = PlayerPrefs.GetInt("TotalGoldEarned", 0);
  122. battlesWon = PlayerPrefs.GetInt("BattlesWon", 0);
  123. battlesLost = PlayerPrefs.GetInt("BattlesLost", 0);
  124. // Clear new game flag - this is a load operation, use saved positions
  125. isNewGame = false;
  126. PlayerPrefs.SetInt("IsNewGame", 0); // Clear from PlayerPrefs too
  127. PlayerPrefs.Save(); // Force immediate save
  128. // Load team data
  129. LoadTeamData();
  130. // Load map data
  131. LoadMapData();
  132. }
  133. public void AutoSave()
  134. {
  135. if (hasActiveGame)
  136. {
  137. SaveGame();
  138. }
  139. }
  140. public void SaveTeam(TeamCharacter[] team)
  141. {
  142. if (team == null) return;
  143. for (int i = 0; i < Mathf.Min(team.Length, savedTeam.Length); i++)
  144. {
  145. if (team[i] != null)
  146. {
  147. savedTeam[i] = team[i].CreateCopy();
  148. }
  149. }
  150. teamSetupComplete = true;
  151. if (hasActiveGame)
  152. {
  153. SaveGame();
  154. }
  155. }
  156. public TeamCharacter[] GetSavedTeam()
  157. {
  158. return savedTeam;
  159. }
  160. private void SaveTeamData()
  161. {
  162. for (int i = 0; i < savedTeam.Length; i++)
  163. {
  164. string prefix = $"Character{i}_";
  165. if (savedTeam[i] != null)
  166. {
  167. PlayerPrefs.SetInt(prefix + "Exists", 1);
  168. PlayerPrefs.SetString(prefix + "Name", savedTeam[i].name);
  169. PlayerPrefs.SetInt(prefix + "IsMale", savedTeam[i].isMale ? 1 : 0);
  170. PlayerPrefs.SetInt(prefix + "Strength", savedTeam[i].strength);
  171. PlayerPrefs.SetInt(prefix + "Dexterity", savedTeam[i].dexterity);
  172. PlayerPrefs.SetInt(prefix + "Constitution", savedTeam[i].constitution);
  173. PlayerPrefs.SetInt(prefix + "Wisdom", savedTeam[i].wisdom);
  174. PlayerPrefs.SetInt(prefix + "Gold", savedTeam[i].gold);
  175. PlayerPrefs.SetInt(prefix + "Silver", savedTeam[i].silver);
  176. PlayerPrefs.SetInt(prefix + "Copper", savedTeam[i].copper);
  177. PlayerPrefs.SetString(prefix + "EquippedWeapon", savedTeam[i].equippedWeapon);
  178. PlayerPrefs.SetString(prefix + "EquippedArmor", savedTeam[i].equippedArmor);
  179. // Save inventory lists as comma-separated strings
  180. PlayerPrefs.SetString(prefix + "Weapons", string.Join(",", savedTeam[i].weapons));
  181. PlayerPrefs.SetString(prefix + "Armor", string.Join(",", savedTeam[i].armor));
  182. PlayerPrefs.SetString(prefix + "MiscItems", string.Join(",", savedTeam[i].miscItems));
  183. }
  184. else
  185. {
  186. PlayerPrefs.SetInt(prefix + "Exists", 0);
  187. }
  188. }
  189. }
  190. private void LoadTeamData()
  191. {
  192. savedTeam = new TeamCharacter[4];
  193. for (int i = 0; i < savedTeam.Length; i++)
  194. {
  195. string prefix = $"Character{i}_";
  196. if (PlayerPrefs.GetInt(prefix + "Exists", 0) == 1)
  197. {
  198. savedTeam[i] = new TeamCharacter();
  199. savedTeam[i].name = PlayerPrefs.GetString(prefix + "Name", "");
  200. savedTeam[i].isMale = PlayerPrefs.GetInt(prefix + "IsMale", 1) == 1;
  201. savedTeam[i].strength = PlayerPrefs.GetInt(prefix + "Strength", 10);
  202. savedTeam[i].dexterity = PlayerPrefs.GetInt(prefix + "Dexterity", 10);
  203. savedTeam[i].constitution = PlayerPrefs.GetInt(prefix + "Constitution", 10);
  204. savedTeam[i].wisdom = PlayerPrefs.GetInt(prefix + "Wisdom", 10);
  205. savedTeam[i].gold = PlayerPrefs.GetInt(prefix + "Gold", 25);
  206. savedTeam[i].silver = PlayerPrefs.GetInt(prefix + "Silver", 0);
  207. savedTeam[i].copper = PlayerPrefs.GetInt(prefix + "Copper", 0);
  208. savedTeam[i].equippedWeapon = PlayerPrefs.GetString(prefix + "EquippedWeapon", "");
  209. savedTeam[i].equippedArmor = PlayerPrefs.GetString(prefix + "EquippedArmor", "");
  210. // Load inventory lists
  211. string weaponsStr = PlayerPrefs.GetString(prefix + "Weapons", "");
  212. string armorStr = PlayerPrefs.GetString(prefix + "Armor", "");
  213. string miscStr = PlayerPrefs.GetString(prefix + "MiscItems", "");
  214. savedTeam[i].weapons = new System.Collections.Generic.List<string>();
  215. savedTeam[i].armor = new System.Collections.Generic.List<string>();
  216. savedTeam[i].miscItems = new System.Collections.Generic.List<string>();
  217. if (!string.IsNullOrEmpty(weaponsStr))
  218. savedTeam[i].weapons.AddRange(weaponsStr.Split(','));
  219. if (!string.IsNullOrEmpty(armorStr))
  220. savedTeam[i].armor.AddRange(armorStr.Split(','));
  221. if (!string.IsNullOrEmpty(miscStr))
  222. savedTeam[i].miscItems.AddRange(miscStr.Split(','));
  223. }
  224. }
  225. }
  226. private void ClearSaveData()
  227. {
  228. // Clear main save indicators
  229. PlayerPrefs.DeleteKey("GameSaved");
  230. PlayerPrefs.DeleteKey("GameVersion");
  231. PlayerPrefs.DeleteKey("CurrentScene");
  232. PlayerPrefs.DeleteKey("TeamSetupComplete");
  233. PlayerPrefs.DeleteKey("CurrentLevel");
  234. PlayerPrefs.DeleteKey("TotalGoldEarned");
  235. PlayerPrefs.DeleteKey("BattlesWon");
  236. PlayerPrefs.DeleteKey("BattlesLost");
  237. // Note: We DON'T clear "IsNewGame" here because it should persist until team placement is done
  238. // Clear team data
  239. for (int i = 0; i < 4; i++)
  240. {
  241. string prefix = $"Character{i}_";
  242. PlayerPrefs.DeleteKey(prefix + "Exists");
  243. PlayerPrefs.DeleteKey(prefix + "Name");
  244. PlayerPrefs.DeleteKey(prefix + "IsMale");
  245. PlayerPrefs.DeleteKey(prefix + "Strength");
  246. PlayerPrefs.DeleteKey(prefix + "Dexterity");
  247. PlayerPrefs.DeleteKey(prefix + "Constitution");
  248. PlayerPrefs.DeleteKey(prefix + "Wisdom");
  249. PlayerPrefs.DeleteKey(prefix + "Gold");
  250. PlayerPrefs.DeleteKey(prefix + "Silver");
  251. PlayerPrefs.DeleteKey(prefix + "Copper");
  252. PlayerPrefs.DeleteKey(prefix + "EquippedWeapon");
  253. PlayerPrefs.DeleteKey(prefix + "EquippedArmor");
  254. PlayerPrefs.DeleteKey(prefix + "Weapons");
  255. PlayerPrefs.DeleteKey(prefix + "Armor");
  256. PlayerPrefs.DeleteKey(prefix + "MiscItems");
  257. }
  258. // Clear map data
  259. PlayerPrefs.DeleteKey("MapSeed");
  260. PlayerPrefs.DeleteKey("MapWidth");
  261. PlayerPrefs.DeleteKey("MapHeight");
  262. PlayerPrefs.DeleteKey("MapNoiseScale");
  263. PlayerPrefs.DeleteKey("MapOceanThreshold");
  264. PlayerPrefs.DeleteKey("MapMountainThreshold");
  265. PlayerPrefs.DeleteKey("MapForestThreshold");
  266. PlayerPrefs.DeleteKey("HasGeneratedMap");
  267. PlayerPrefs.Save();
  268. }
  269. // Method to check if we're currently in a game
  270. public bool IsInGame()
  271. {
  272. return hasActiveGame && currentSceneName != "TitleScreen";
  273. }
  274. // Method to return to title screen
  275. public void ReturnToTitle()
  276. {
  277. SceneManager.LoadScene("TitleScreen");
  278. }
  279. private void SaveMapData()
  280. {
  281. PlayerPrefs.SetInt("MapSeed", mapSeed);
  282. PlayerPrefs.SetInt("MapWidth", mapWidth);
  283. PlayerPrefs.SetInt("MapHeight", mapHeight);
  284. PlayerPrefs.SetFloat("MapNoiseScale", mapNoiseScale);
  285. PlayerPrefs.SetFloat("MapOceanThreshold", mapOceanThreshold);
  286. PlayerPrefs.SetFloat("MapMountainThreshold", mapMountainThreshold);
  287. PlayerPrefs.SetFloat("MapForestThreshold", mapForestThreshold);
  288. PlayerPrefs.SetInt("HasGeneratedMap", hasGeneratedMap ? 1 : 0);
  289. }
  290. private void LoadMapData()
  291. {
  292. mapSeed = PlayerPrefs.GetInt("MapSeed", Random.Range(0, 999999));
  293. mapWidth = PlayerPrefs.GetInt("MapWidth", 100);
  294. mapHeight = PlayerPrefs.GetInt("MapHeight", 100);
  295. mapNoiseScale = PlayerPrefs.GetFloat("MapNoiseScale", 5f);
  296. mapOceanThreshold = PlayerPrefs.GetFloat("MapOceanThreshold", 0.3f);
  297. mapMountainThreshold = PlayerPrefs.GetFloat("MapMountainThreshold", 0.7f);
  298. mapForestThreshold = PlayerPrefs.GetFloat("MapForestThreshold", 0.5f);
  299. hasGeneratedMap = PlayerPrefs.GetInt("HasGeneratedMap", 0) == 1;
  300. }
  301. public void GenerateNewMap()
  302. {
  303. mapSeed = Random.Range(0, 999999);
  304. hasGeneratedMap = true;
  305. SaveMapData();
  306. }
  307. public bool HasSavedMap()
  308. {
  309. return PlayerPrefs.HasKey("MapSeed");
  310. }
  311. /// <summary>
  312. /// Check if this is a new game that should force random team placement
  313. /// </summary>
  314. public bool IsNewGameForceRandom()
  315. {
  316. // Check both the instance variable and PlayerPrefs in case of timing issues
  317. bool instanceFlag = isNewGame;
  318. bool playerPrefsFlag = PlayerPrefs.GetInt("IsNewGame", 0) == 1;
  319. bool result = instanceFlag || playerPrefsFlag;
  320. return result;
  321. }
  322. /// <summary>
  323. /// Clear the new game flag after initial team placement is complete
  324. /// </summary>
  325. public void ClearNewGameFlag()
  326. {
  327. isNewGame = false;
  328. PlayerPrefs.SetInt("IsNewGame", 0); // Clear from PlayerPrefs too
  329. PlayerPrefs.Save();
  330. }
  331. }