CheckpointSystem.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. using TMPro;
  4. /// <summary>
  5. /// Manages checkpoint saving and loading for the respawn system.
  6. /// Automatically captures player's start position as fallback respawn point.
  7. /// </summary>
  8. public class CheckpointSystem : MonoBehaviour
  9. {
  10. public static CheckpointSystem Instance { get; private set; }
  11. [Header("References")]
  12. public TeamCohesionManager cohesionManager;
  13. public Transform playerTransform;
  14. public GridMovement playerMovement;
  15. [Header("Settings")]
  16. public bool autoSaveOnCheckpoint = true;
  17. public float checkpointRadius = 3f;
  18. public Vector3 respawnRotation = new Vector3(0, 90, 0); // to look east at respawnss
  19. [Header("Respawn UI")]
  20. public TextMeshProUGUI respawnText;
  21. public CanvasGroup respawnCanvasGroup;
  22. public string respawnMessage = "Respawned at Checkpoint";
  23. [Header("Fade Animation")]
  24. public float fadeDuration = 0.5f;
  25. public float displayDuration = 2f;
  26. private Vector3 savedPlayerPosition;
  27. private int savedFloorLevel;
  28. private List<SavedCharacterData> savedCharacters = new List<SavedCharacterData>();
  29. private bool hasCheckpoint = false;
  30. [System.Serializable] // This class is used to save the characters data when the checkpoint is saved
  31. private class SavedCharacterData
  32. {
  33. public CharacterInGroup character;
  34. public int hp;
  35. public int fatigue;
  36. public int mana;
  37. public int gridX;
  38. public int gridY;
  39. public SavedCharacterData(CharacterInGroup chara)
  40. {
  41. character = chara;
  42. hp = chara.currentHP;
  43. fatigue = chara.currentFatigue;
  44. mana = chara.currentMana;
  45. gridX = chara.gridX;
  46. gridY = chara.gridY;
  47. }
  48. }
  49. #region Initialization
  50. private void Awake()
  51. {
  52. if (Instance != null && Instance != this)
  53. {
  54. Destroy(gameObject);
  55. return;
  56. }
  57. Instance = this;
  58. }
  59. private void Start()
  60. {
  61. FindReferences();
  62. SaveInitialCheckpoint();
  63. }
  64. private void FindReferences()
  65. {
  66. if (cohesionManager == null)
  67. cohesionManager = FindFirstObjectByType<TeamCohesionManager>();
  68. if (playerTransform == null)
  69. {
  70. GameObject player = GameObject.FindGameObjectWithTag("Player");
  71. if (player != null)
  72. playerTransform = player.transform;
  73. }
  74. if (playerMovement == null)
  75. playerMovement = FindFirstObjectByType<GridMovement>();
  76. }
  77. private void SaveInitialCheckpoint()
  78. {
  79. // Wait a frame to ensure all systems are initialized
  80. StartCoroutine(SaveInitialCheckpointDelayed());
  81. }
  82. private System.Collections.IEnumerator SaveInitialCheckpointDelayed()
  83. {
  84. yield return new WaitForSeconds(0.5f);
  85. // Save the starting position as initial checkpoint
  86. SaveCheckpoint();
  87. Debug.Log("[CheckpointSystem] Initial checkpoint saved at start position");
  88. }
  89. #endregion
  90. #region Checkpoint Save
  91. public void SaveCheckpoint()
  92. {
  93. if (playerTransform == null || cohesionManager == null)
  94. {
  95. Debug.LogWarning("[CheckpointSystem] Cannot save checkpoint: missing references");
  96. return;
  97. }
  98. savedPlayerPosition = playerTransform.position;
  99. if (playerMovement != null)
  100. savedFloorLevel = playerMovement.currentFloorLevel;
  101. savedCharacters.Clear();
  102. foreach (var character in cohesionManager.groupMembers)
  103. {
  104. savedCharacters.Add(new SavedCharacterData(character));
  105. }
  106. hasCheckpoint = true;
  107. Debug.Log($"[CheckpointSystem] Checkpoint saved with {savedCharacters.Count} characters");
  108. }
  109. public void SaveCheckpointAt(Vector3 position)
  110. {
  111. savedPlayerPosition = position;
  112. if (playerMovement != null)
  113. savedFloorLevel = playerMovement.currentFloorLevel;
  114. savedCharacters.Clear();
  115. if (cohesionManager != null)
  116. {
  117. foreach (var character in cohesionManager.groupMembers)
  118. {
  119. savedCharacters.Add(new SavedCharacterData(character));
  120. }
  121. }
  122. hasCheckpoint = true;
  123. Debug.Log($"[CheckpointSystem] Manual checkpoint saved at {savedPlayerPosition}");
  124. }
  125. #endregion
  126. #region Checkpoint Load
  127. public void LoadCheckpoint()
  128. {
  129. if (!hasCheckpoint)
  130. {
  131. Debug.LogWarning("[CheckpointSystem] No checkpoint available");
  132. return;
  133. }
  134. if (playerTransform != null)
  135. {
  136. playerTransform.position = savedPlayerPosition;
  137. playerTransform.rotation = Quaternion.Euler(respawnRotation);
  138. }
  139. if (playerMovement != null)
  140. playerMovement.currentFloorLevel = savedFloorLevel;
  141. RestoreCharacters();
  142. // Show respawn UI message
  143. ShowRespawnMessage();
  144. }
  145. private void RestoreCharacters()
  146. {
  147. if (cohesionManager == null) return;
  148. cohesionManager.groupMembers.Clear();
  149. foreach (var saved in savedCharacters)
  150. {
  151. CharacterInGroup character = saved.character;
  152. character.currentHP = character.maxHP;
  153. character.currentFatigue = character.maxFatigue;
  154. character.currentMana = character.maxMana;
  155. character.gridX = saved.gridX;
  156. character.gridY = saved.gridY;
  157. cohesionManager.groupMembers.Add(character);
  158. }
  159. RecreatePartyUI();
  160. }
  161. private void RecreatePartyUI()
  162. {
  163. PartyUIManager partyUI = FindFirstObjectByType<PartyUIManager>();
  164. if (partyUI != null)
  165. {
  166. partyUI.DisplayPartyUI();
  167. }
  168. }
  169. #endregion
  170. #region Checkpoint Triggers
  171. private void OnTriggerEnter(Collider other)
  172. {
  173. if (other.CompareTag("Checkpoint") && autoSaveOnCheckpoint)
  174. {
  175. SaveCheckpoint();
  176. }
  177. }
  178. #endregion
  179. #region Public API
  180. public bool HasCheckpoint() => hasCheckpoint;
  181. public Vector3 GetCheckpointPosition() => savedPlayerPosition;
  182. #endregion
  183. #region Respawn UI
  184. private void ShowRespawnMessage()
  185. {
  186. if (respawnText != null && respawnCanvasGroup != null)
  187. {
  188. respawnText.text = respawnMessage;
  189. respawnText.gameObject.SetActive(true);
  190. StartCoroutine(FadeRespawnTextInOut());
  191. }
  192. }
  193. private System.Collections.IEnumerator FadeRespawnTextInOut()
  194. {
  195. // Fade in from 0 to 1
  196. float elapsed = 0f;
  197. while (elapsed < fadeDuration)
  198. {
  199. elapsed += Time.deltaTime;
  200. respawnCanvasGroup.alpha = Mathf.Lerp(0f, 1f, elapsed / fadeDuration);
  201. yield return null;
  202. }
  203. respawnCanvasGroup.alpha = 1f;
  204. // Display at full opacity
  205. yield return new WaitForSeconds(displayDuration);
  206. // Fade out from 1 to 0
  207. elapsed = 0f;
  208. while (elapsed < fadeDuration)
  209. {
  210. elapsed += Time.deltaTime;
  211. respawnCanvasGroup.alpha = Mathf.Lerp(1f, 0f, elapsed / fadeDuration);
  212. yield return null;
  213. }
  214. respawnCanvasGroup.alpha = 0f;
  215. // Deactivate text object
  216. respawnText.gameObject.SetActive(false);
  217. }
  218. #endregion
  219. }