using System.IO; using System.Text; using UnityEngine; using TMPro; public class StoryComputerSystem : MonoBehaviour { private enum SlotMode { None, Save, Load } [System.Serializable] public class AffectionUIBind { public CharacterData character; public HeartAffectionUI heartUI; } [System.Serializable] private class SlotPreviewData { public int MainProgress; } [Header("Computer State")] [SerializeField] private bool isPowerOn = false; [Header("Panel UI")] [SerializeField] private GameObject windowPanel; [SerializeField] private GameObject notePanel; [SerializeField] private GameObject slotPanel; [Header("Slot Text UI")] [SerializeField] private TMP_Text[] slotTexts; [Header("Affection Check Characters")] [SerializeField] private CharacterData[] characters; [Header("Status UI")] [SerializeField] private MainProgressUI mainProgressUI; [SerializeField] private AffectionUIBind[] affectionUIBinds; private SlotMode currentSlotMode = SlotMode.None; public bool IsPowerOn => isPowerOn; private static string BaseSavePath => Path.Combine(Application.persistentDataPath, "story_state.json"); private static string SlotSavePath(int slotIndex) => Path.Combine(Application.persistentDataPath, $"story_state_slot_{slotIndex}.json"); private void Start() { ApplyPowerState(); RefreshSlotTexts(); } public void TogglePower() { isPowerOn = !isPowerOn; ApplyPowerState(); if (isPowerOn) { RefreshStatusUI(); RefreshSlotTexts(); } Debug.Log(isPowerOn ? "[StoryComputer] 컴퓨터 전원이 켜졌습니다." : "[StoryComputer] 컴퓨터 전원이 꺼졌습니다."); } private void ApplyPowerState() { currentSlotMode = SlotMode.None; if (windowPanel != null) windowPanel.SetActive(isPowerOn); if (notePanel != null) notePanel.SetActive(false); if (slotPanel != null) slotPanel.SetActive(false); } public void OpenCurrentStatePanel() { if (!CanUseComputer()) return; currentSlotMode = SlotMode.None; if (slotPanel != null) slotPanel.SetActive(false); if (notePanel != null) notePanel.SetActive(true); RefreshStatusUI(); } public void OpenSaveSlotPanel() { if (!CanUseComputer()) return; currentSlotMode = SlotMode.Save; if (notePanel != null) notePanel.SetActive(false); if (slotPanel != null) slotPanel.SetActive(true); RefreshSlotTexts(); } public void OpenLoadSlotPanel() { if (!CanUseComputer()) return; currentSlotMode = SlotMode.Load; if (notePanel != null) notePanel.SetActive(false); if (slotPanel != null) slotPanel.SetActive(true); RefreshSlotTexts(); } public void SelectSlot1() { SelectSlot(1); } public void SelectSlot2() { SelectSlot(2); } public void SelectSlot3() { SelectSlot(3); } private void SelectSlot(int slotIndex) { if (!CanUseComputer()) return; if (currentSlotMode == SlotMode.Save) { SaveToSlot(slotIndex); } else if (currentSlotMode == SlotMode.Load) { LoadFromSlot(slotIndex); } else { Debug.LogWarning("[StoryComputer] 저장/불러오기 모드가 선택되지 않았습니다."); } } private void SaveToSlot(int slotIndex) { if (StoryManager.Instance == null) { Debug.LogWarning("[StoryComputer] StoryManager가 없습니다."); return; } StoryManager.Instance.Save(); if (!File.Exists(BaseSavePath)) { Debug.LogWarning("[StoryComputer] 기본 저장 파일이 생성되지 않았습니다."); return; } File.Copy(BaseSavePath, SlotSavePath(slotIndex), true); RefreshSlotTexts(); RefreshStatusUI(); Debug.Log($"[StoryComputer] 슬롯 {slotIndex}에 저장했습니다."); } private void LoadFromSlot(int slotIndex) { string slotPath = SlotSavePath(slotIndex); if (!File.Exists(slotPath)) { Debug.LogWarning($"[StoryComputer] 슬롯 {slotIndex}에 저장 파일이 없습니다."); return; } File.Copy(slotPath, BaseSavePath, true); bool success = StoryManager.Instance.Load(); if (!success) { Debug.LogWarning($"[StoryComputer] 슬롯 {slotIndex} 불러오기에 실패했습니다."); return; } currentSlotMode = SlotMode.None; if (slotPanel != null) slotPanel.SetActive(false); if (notePanel != null) notePanel.SetActive(true); RefreshSlotTexts(); RefreshStatusUI(); Debug.Log($"[StoryComputer] 슬롯 {slotIndex}에서 불러왔습니다."); } public void ResetStoryFromComputer() { if (!CanUseComputer()) return; StoryManager.Instance.ResetAll(); currentSlotMode = SlotMode.None; if (slotPanel != null) slotPanel.SetActive(false); if (notePanel != null) notePanel.SetActive(true); RefreshStatusUI(); Debug.Log("[StoryComputer] 스토리 상태를 초기화했습니다."); } public void CloseComputerWindow() { isPowerOn = false; currentSlotMode = SlotMode.None; if (notePanel != null) notePanel.SetActive(false); if (slotPanel != null) slotPanel.SetActive(false); if (windowPanel != null) windowPanel.SetActive(false); Debug.Log("[StoryComputer] 컴퓨터 UI 창을 닫고 전원을 껐습니다."); } public void SaveFromComputer() { OpenSaveSlotPanel(); } public void LoadFromComputer() { OpenLoadSlotPanel(); } private void RefreshSlotTexts() { if (slotTexts == null) return; for (int i = 0; i < slotTexts.Length; i++) { if (slotTexts[i] == null) continue; int slotIndex = i + 1; string slotPath = SlotSavePath(slotIndex); if (!File.Exists(slotPath)) { slotTexts[i].text = $"슬롯 {slotIndex}\n저장된 데이터 없음"; continue; } int progress = ReadSlotMainProgress(slotPath); slotTexts[i].text = $"슬롯 {slotIndex}\n저장됨 · 진행도 {progress}%"; } } private int ReadSlotMainProgress(string slotPath) { try { string json = File.ReadAllText(slotPath); SlotPreviewData data = JsonUtility.FromJson(json); if (data == null) return 0; return Mathf.Clamp(data.MainProgress, 0, 100); } catch { return 0; } } public void PrintCurrentState() { if (StoryManager.Instance == null) { Debug.LogWarning("[StoryComputer] StoryManager가 없습니다."); return; } StringBuilder sb = new StringBuilder(); sb.AppendLine("========== 현재 스토리 상태 =========="); sb.AppendLine($"메인 진행도: {StoryManager.Instance.MainProgress}"); sb.AppendLine(); sb.AppendLine("공룡별 호감도:"); if (characters == null || characters.Length == 0) { sb.AppendLine("- 등록된 캐릭터 없음"); } else { foreach (CharacterData character in characters) { if (character == null) continue; int affection = StoryManager.Instance.GetAffection(character); sb.AppendLine($"- {character.name}: {affection}"); } } sb.AppendLine("===================================="); Debug.Log(sb.ToString()); } private void RefreshStatusUI() { if (StoryManager.Instance == null) { Debug.LogWarning("[StoryComputer] StoryManager가 없어서 UI를 갱신할 수 없습니다."); return; } if (mainProgressUI != null) { mainProgressUI.SetProgress(StoryManager.Instance.MainProgress); } if (affectionUIBinds != null) { foreach (AffectionUIBind bind in affectionUIBinds) { if (bind == null) continue; if (bind.character == null) continue; if (bind.heartUI == null) continue; int affection = StoryManager.Instance.GetAffection(bind.character); bind.heartUI.SetAffection(affection); } } } private bool CanUseComputer() { if (!isPowerOn) { Debug.LogWarning("[StoryComputer] 컴퓨터 전원이 꺼져 있어서 사용할 수 없습니다."); return false; } if (StoryManager.Instance == null) { Debug.LogWarning("[StoryComputer] StoryManager가 씬에 없습니다."); return false; } return true; } }