TeamOverviewController.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. using UnityEngine;
  2. using UnityEngine.UIElements;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using UnityEngine.SceneManagement;
  6. /// <summary>
  7. /// Controls the TeamOverview UI panel on the right side of the map scene.
  8. /// Displays current team information, stats, and provides navigation controls.
  9. /// Works with the main map UI document.
  10. /// </summary>
  11. public class TeamOverviewController : MonoBehaviour
  12. {
  13. [Header("Settings")]
  14. [SerializeField] public bool showDebugLogs = false;
  15. // UI Elements
  16. private VisualElement teamOverviewPanel;
  17. private ScrollView teamMembersList;
  18. private Button manageTeamButton;
  19. private Button saveGameButton;
  20. private Label memberCountLabel;
  21. private Label totalGoldLabel;
  22. private Label averageLevelLabel;
  23. // UI Document reference (shared with map)
  24. private UIDocument uiDocument;
  25. // Team data
  26. private List<TeamCharacter> currentTeam;
  27. void Awake()
  28. {
  29. // Get the UIDocument component from this GameObject
  30. uiDocument = GetComponent<UIDocument>();
  31. if (uiDocument == null)
  32. {
  33. Debug.LogError("❌ TeamOverviewController: No UIDocument component found on this GameObject!");
  34. }
  35. }
  36. void Start()
  37. {
  38. // Ensure GameStateManager has loaded data if it exists
  39. if (GameStateManager.Instance != null && PlayerPrefs.HasKey("GameSaved"))
  40. {
  41. GameStateManager.Instance.LoadGame();
  42. }
  43. SetupUI();
  44. LoadTeamData();
  45. ShowTeamOverview();
  46. }
  47. /// <summary>
  48. /// Sets up the UI elements and event handlers
  49. /// </summary>
  50. private void SetupUI()
  51. {
  52. if (uiDocument?.rootVisualElement == null)
  53. {
  54. Debug.LogError("❌ TeamOverviewController: UIDocument not found or has no root element!");
  55. return;
  56. }
  57. var root = uiDocument.rootVisualElement;
  58. // Find UI elements - using the correct button names from TeamOverview.uxml
  59. teamOverviewPanel = root.Q("TeamOverviewPanel");
  60. teamMembersList = root.Q<ScrollView>("TeamMembersList");
  61. manageTeamButton = root.Q<Button>("ReturnToTeamSelectButton");
  62. saveGameButton = root.Q<Button>("SaveGameButton");
  63. memberCountLabel = root.Q<Label>("MemberCountLabel");
  64. totalGoldLabel = root.Q<Label>("TotalGoldLabel");
  65. averageLevelLabel = root.Q<Label>("AverageLevelLabel");
  66. // Debug: Check which elements were found
  67. if (showDebugLogs)
  68. {
  69. Debug.Log($"🔍 UI Elements found:");
  70. Debug.Log($" TeamOverviewPanel: {teamOverviewPanel != null}");
  71. Debug.Log($" TeamMembersList: {teamMembersList != null}");
  72. Debug.Log($" ManageTeamButton: {manageTeamButton != null}");
  73. Debug.Log($" SaveGameButton: {saveGameButton != null}");
  74. Debug.Log($" MemberCountLabel: {memberCountLabel != null}");
  75. Debug.Log($" TotalGoldLabel: {totalGoldLabel != null}");
  76. Debug.Log($" AverageLevelLabel: {averageLevelLabel != null}");
  77. }
  78. // Setup event handlers
  79. if (manageTeamButton != null)
  80. {
  81. manageTeamButton.clicked += OnManageTeamClicked;
  82. }
  83. if (saveGameButton != null)
  84. {
  85. saveGameButton.clicked += OnSaveGameClicked;
  86. }
  87. if (showDebugLogs)
  88. {
  89. Debug.Log("✅ TeamOverviewController: UI setup complete");
  90. }
  91. }
  92. /// <summary>
  93. /// Loads current team data from the save system
  94. /// </summary>
  95. private void LoadTeamData()
  96. {
  97. currentTeam = new List<TeamCharacter>();
  98. // Method 1: Try to load from MainTeamSelectScript (if in TeamSelect scene)
  99. var teamSelectScript = FindFirstObjectByType<MainTeamSelectScript>();
  100. if (teamSelectScript != null)
  101. {
  102. currentTeam = teamSelectScript.GetConfiguredCharacters();
  103. if (showDebugLogs)
  104. {
  105. Debug.Log($"📋 Loaded team from MainTeamSelectScript: {currentTeam.Count} members");
  106. }
  107. return;
  108. }
  109. // Method 2: Try to load from GameStateManager
  110. if (GameStateManager.Instance != null && GameStateManager.Instance.savedTeam != null)
  111. {
  112. foreach (var character in GameStateManager.Instance.savedTeam)
  113. {
  114. if (character != null)
  115. {
  116. currentTeam.Add(character);
  117. }
  118. }
  119. if (currentTeam.Count > 0)
  120. {
  121. if (showDebugLogs)
  122. {
  123. Debug.Log($"📋 Loaded team from GameStateManager: {currentTeam.Count} members");
  124. }
  125. return;
  126. }
  127. }
  128. // Method 3: Try to load directly from PlayerPrefs (fallback)
  129. for (int i = 0; i < 4; i++)
  130. {
  131. string prefix = $"Character{i}_";
  132. if (PlayerPrefs.HasKey(prefix + "Exists") && PlayerPrefs.GetInt(prefix + "Exists") == 1)
  133. {
  134. var character = new TeamCharacter();
  135. character.name = PlayerPrefs.GetString(prefix + "Name", "");
  136. character.isMale = PlayerPrefs.GetInt(prefix + "IsMale", 1) == 1;
  137. character.strength = PlayerPrefs.GetInt(prefix + "Strength", 10);
  138. character.dexterity = PlayerPrefs.GetInt(prefix + "Dexterity", 10);
  139. character.constitution = PlayerPrefs.GetInt(prefix + "Constitution", 10);
  140. character.wisdom = PlayerPrefs.GetInt(prefix + "Wisdom", 10);
  141. character.perception = PlayerPrefs.GetInt(prefix + "Perception", 10);
  142. character.gold = PlayerPrefs.GetInt(prefix + "Gold", 25);
  143. character.silver = PlayerPrefs.GetInt(prefix + "Silver", 0);
  144. character.copper = PlayerPrefs.GetInt(prefix + "Copper", 0);
  145. if (!string.IsNullOrEmpty(character.name))
  146. {
  147. currentTeam.Add(character);
  148. }
  149. }
  150. }
  151. if (currentTeam.Count > 0)
  152. {
  153. if (showDebugLogs)
  154. {
  155. Debug.Log($"📋 Loaded team from PlayerPrefs: {currentTeam.Count} members");
  156. }
  157. }
  158. else
  159. {
  160. if (showDebugLogs)
  161. {
  162. Debug.Log("ℹ️ No team data found - this is normal for a new game");
  163. }
  164. }
  165. } /// <summary>
  166. /// Shows the team overview panel
  167. /// </summary>
  168. public void ShowTeamOverview()
  169. {
  170. if (teamOverviewPanel == null) return;
  171. teamOverviewPanel.style.display = DisplayStyle.Flex;
  172. UpdateTeamDisplay();
  173. if (showDebugLogs)
  174. {
  175. Debug.Log("👥 TeamOverviewController: Team overview panel shown");
  176. }
  177. }
  178. /// <summary>
  179. /// Hides the team overview panel
  180. /// </summary>
  181. public void HideTeamOverview()
  182. {
  183. if (teamOverviewPanel == null) return;
  184. teamOverviewPanel.style.display = DisplayStyle.None;
  185. if (showDebugLogs)
  186. {
  187. Debug.Log("👻 TeamOverviewController: Team overview panel hidden");
  188. }
  189. }
  190. /// <summary>
  191. /// Updates the team display with current data
  192. /// </summary>
  193. private void UpdateTeamDisplay()
  194. {
  195. if (currentTeam == null)
  196. {
  197. if (showDebugLogs)
  198. {
  199. Debug.Log("⚠️ UpdateTeamDisplay: currentTeam is null");
  200. }
  201. return;
  202. }
  203. if (teamMembersList == null)
  204. {
  205. if (showDebugLogs)
  206. {
  207. Debug.Log("⚠️ UpdateTeamDisplay: teamMembersList is null - UI elements not found");
  208. }
  209. return;
  210. }
  211. if (showDebugLogs)
  212. {
  213. Debug.Log($"🎨 UpdateTeamDisplay: Updating display for {currentTeam.Count} team members");
  214. }
  215. // Clear existing team member displays
  216. teamMembersList.Clear();
  217. // Add each team member
  218. foreach (var member in currentTeam)
  219. {
  220. if (member != null)
  221. {
  222. CreateTeamMemberCard(member);
  223. if (showDebugLogs)
  224. {
  225. Debug.Log($"📋 Added card for member: {member.name}");
  226. }
  227. }
  228. }
  229. // Update team stats
  230. UpdateTeamStats();
  231. if (showDebugLogs)
  232. {
  233. Debug.Log($"✅ UpdateTeamDisplay: Display updated with {currentTeam.Count} members");
  234. }
  235. }
  236. /// <summary>
  237. /// Creates a visual card for a team member
  238. /// </summary>
  239. private void CreateTeamMemberCard(TeamCharacter member)
  240. {
  241. var memberCard = new VisualElement();
  242. memberCard.style.backgroundColor = new StyleColor(new Color(0.3f, 0.3f, 0.3f, 0.8f));
  243. memberCard.style.borderTopColor = new StyleColor(new Color(0.5f, 0.5f, 0.5f));
  244. memberCard.style.borderBottomColor = new StyleColor(new Color(0.5f, 0.5f, 0.5f));
  245. memberCard.style.borderLeftColor = new StyleColor(new Color(0.5f, 0.5f, 0.5f));
  246. memberCard.style.borderRightColor = new StyleColor(new Color(0.5f, 0.5f, 0.5f));
  247. memberCard.style.borderTopWidth = 1;
  248. memberCard.style.borderBottomWidth = 1;
  249. memberCard.style.borderLeftWidth = 1;
  250. memberCard.style.borderRightWidth = 1;
  251. memberCard.style.borderTopLeftRadius = 4;
  252. memberCard.style.borderTopRightRadius = 4;
  253. memberCard.style.borderBottomLeftRadius = 4;
  254. memberCard.style.borderBottomRightRadius = 4;
  255. memberCard.style.marginBottom = 8;
  256. memberCard.style.paddingTop = 8;
  257. memberCard.style.paddingBottom = 8;
  258. memberCard.style.paddingLeft = 8;
  259. memberCard.style.paddingRight = 8;
  260. // Member header with name and level
  261. var memberHeader = new VisualElement();
  262. memberHeader.style.flexDirection = FlexDirection.Row;
  263. memberHeader.style.justifyContent = Justify.SpaceBetween;
  264. memberHeader.style.alignItems = Align.Center;
  265. memberHeader.style.marginBottom = 5;
  266. var nameLabel = new Label(member.name);
  267. nameLabel.style.color = new StyleColor(new Color(1f, 1f, 1f));
  268. nameLabel.style.fontSize = 12;
  269. nameLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
  270. var hpLabel = new Label($"HP: {member.HitPoints} | AC: {member.ArmorClass}");
  271. hpLabel.style.color = new StyleColor(new Color(0.8f, 0.8f, 1f));
  272. hpLabel.style.fontSize = 10;
  273. memberHeader.Add(nameLabel);
  274. memberHeader.Add(hpLabel);
  275. memberCard.Add(memberHeader);
  276. // Stats container
  277. var statsContainer = new VisualElement();
  278. statsContainer.style.flexDirection = FlexDirection.Row;
  279. statsContainer.style.flexWrap = Wrap.Wrap;
  280. statsContainer.style.justifyContent = Justify.SpaceBetween;
  281. // Add attribute stats in a compact layout
  282. AddCompactStatLabel(statsContainer, "STR", member.strength);
  283. AddCompactStatLabel(statsContainer, "DEX", member.dexterity);
  284. AddCompactStatLabel(statsContainer, "CON", member.constitution);
  285. AddCompactStatLabel(statsContainer, "WIS", member.wisdom);
  286. AddCompactStatLabel(statsContainer, "PER", member.perception);
  287. memberCard.Add(statsContainer);
  288. teamMembersList.Add(memberCard);
  289. }
  290. /// <summary>
  291. /// Adds a compact stat label to a container
  292. /// </summary>
  293. private void AddCompactStatLabel(VisualElement container, string statName, int statValue)
  294. {
  295. var statElement = new VisualElement();
  296. statElement.style.flexDirection = FlexDirection.Row;
  297. statElement.style.width = new StyleLength(new Length(18, LengthUnit.Percent));
  298. statElement.style.marginBottom = 1;
  299. var statLabel = new Label($"{statName}:");
  300. statLabel.style.color = new StyleColor(new Color(0.8f, 0.8f, 0.8f));
  301. statLabel.style.fontSize = 9;
  302. statLabel.style.width = new StyleLength(new Length(60, LengthUnit.Percent));
  303. var valueLabel = new Label(statValue.ToString());
  304. valueLabel.style.color = new StyleColor(new Color(1f, 1f, 1f));
  305. valueLabel.style.fontSize = 9;
  306. valueLabel.style.width = new StyleLength(new Length(40, LengthUnit.Percent));
  307. statElement.Add(statLabel);
  308. statElement.Add(valueLabel);
  309. container.Add(statElement);
  310. }
  311. /// <summary>
  312. /// Updates the team summary statistics
  313. /// </summary>
  314. private void UpdateTeamStats()
  315. {
  316. if (currentTeam == null) return;
  317. // Update member count
  318. if (memberCountLabel != null)
  319. {
  320. memberCountLabel.text = currentTeam.Count.ToString();
  321. }
  322. // Update total gold (assuming team shares resources)
  323. if (totalGoldLabel != null)
  324. {
  325. var totalGold = currentTeam.Sum(member => member.gold);
  326. totalGoldLabel.text = totalGold.ToString();
  327. }
  328. // Since TeamCharacter doesn't have level property, assume level 1 for all characters
  329. if (averageLevelLabel != null)
  330. {
  331. averageLevelLabel.text = "1";
  332. }
  333. }
  334. /// <summary>
  335. /// Handle manage team button click
  336. /// </summary>
  337. private void OnManageTeamClicked()
  338. {
  339. if (showDebugLogs)
  340. {
  341. Debug.Log("🔄 TeamOverviewController: Returning to Team Select scene");
  342. }
  343. // Load the Team Select scene
  344. var sceneManager = FindFirstObjectByType<SceneNavigationManager>();
  345. if (sceneManager != null)
  346. {
  347. sceneManager.GoToTeamSelect();
  348. }
  349. else
  350. {
  351. // Fallback to direct scene loading
  352. UnityEngine.SceneManagement.SceneManager.LoadScene("TeamSelect");
  353. }
  354. }
  355. /// <summary>
  356. /// Handle save game button click
  357. /// </summary>
  358. private void OnSaveGameClicked()
  359. {
  360. if (showDebugLogs)
  361. {
  362. Debug.Log("💾 TeamOverviewController: Saving game");
  363. }
  364. try
  365. {
  366. // Use GameStateManager to save current game state
  367. var gameStateManager = FindFirstObjectByType<GameStateManager>();
  368. if (gameStateManager != null)
  369. {
  370. gameStateManager.SaveGame();
  371. Debug.Log("✅ Game saved successfully!");
  372. }
  373. else
  374. {
  375. Debug.LogWarning("⚠️ GameStateManager not found!");
  376. }
  377. }
  378. catch (System.Exception e)
  379. {
  380. Debug.LogError($"❌ Failed to save game: {e.Message}");
  381. }
  382. }
  383. /// <summary>
  384. /// Refreshes the team data and display
  385. /// </summary>
  386. public void RefreshTeamData()
  387. {
  388. LoadTeamData();
  389. UpdateTeamDisplay();
  390. if (showDebugLogs)
  391. {
  392. Debug.Log("🔄 TeamOverviewController: Team data refreshed");
  393. }
  394. }
  395. /// <summary>
  396. /// Forces a reload of team data from all sources
  397. /// </summary>
  398. public void ForceReloadTeamData()
  399. {
  400. // Force GameStateManager to reload if possible
  401. if (GameStateManager.Instance != null && PlayerPrefs.HasKey("GameSaved"))
  402. {
  403. GameStateManager.Instance.LoadGame();
  404. }
  405. LoadTeamData();
  406. UpdateTeamDisplay();
  407. if (showDebugLogs)
  408. {
  409. Debug.Log("🔄 TeamOverviewController: Team data force reloaded");
  410. }
  411. }
  412. /// <summary>
  413. /// Context menu methods for debugging
  414. /// </summary>
  415. [ContextMenu("Show Team Overview")]
  416. public void TestShowTeamOverview()
  417. {
  418. ShowTeamOverview();
  419. }
  420. [ContextMenu("Hide Team Overview")]
  421. public void TestHideTeamOverview()
  422. {
  423. HideTeamOverview();
  424. }
  425. [ContextMenu("Refresh Team Data")]
  426. public void TestRefreshTeamData()
  427. {
  428. RefreshTeamData();
  429. }
  430. [ContextMenu("Force Reload Team Data")]
  431. public void TestForceReloadTeamData()
  432. {
  433. ForceReloadTeamData();
  434. }
  435. [ContextMenu("Debug Team Data Sources")]
  436. public void DebugTeamDataSources()
  437. {
  438. Debug.Log("=== TEAM DATA DEBUG ===");
  439. // Check MainTeamSelectScript
  440. var teamSelectScript = FindFirstObjectByType<MainTeamSelectScript>();
  441. Debug.Log($"MainTeamSelectScript found: {teamSelectScript != null}");
  442. if (teamSelectScript != null)
  443. {
  444. var characters = teamSelectScript.GetConfiguredCharacters();
  445. Debug.Log($"MainTeamSelectScript characters: {characters.Count}");
  446. }
  447. // Check GameStateManager
  448. Debug.Log($"GameStateManager.Instance: {GameStateManager.Instance != null}");
  449. if (GameStateManager.Instance != null)
  450. {
  451. Debug.Log($"GameStateManager.savedTeam: {GameStateManager.Instance.savedTeam != null}");
  452. if (GameStateManager.Instance.savedTeam != null)
  453. {
  454. int count = 0;
  455. foreach (var character in GameStateManager.Instance.savedTeam)
  456. {
  457. if (character != null) count++;
  458. }
  459. Debug.Log($"GameStateManager team count: {count}");
  460. }
  461. }
  462. // Check PlayerPrefs
  463. int playerPrefsCount = 0;
  464. for (int i = 0; i < 4; i++)
  465. {
  466. if (PlayerPrefs.HasKey($"Character{i}_Exists") && PlayerPrefs.GetInt($"Character{i}_Exists") == 1)
  467. {
  468. string name = PlayerPrefs.GetString($"Character{i}_Name", "");
  469. if (!string.IsNullOrEmpty(name))
  470. {
  471. playerPrefsCount++;
  472. Debug.Log($"PlayerPrefs Character {i}: {name}");
  473. }
  474. }
  475. }
  476. Debug.Log($"PlayerPrefs character count: {playerPrefsCount}");
  477. Debug.Log($"Current team loaded: {currentTeam?.Count ?? 0}");
  478. if (currentTeam != null)
  479. {
  480. foreach (var member in currentTeam)
  481. {
  482. Debug.Log($" - {member?.name ?? "null"} (STR:{member?.strength ?? 0}, DEX:{member?.dexterity ?? 0}, CON:{member?.constitution ?? 0}, WIS:{member?.wisdom ?? 0}, PER:{member?.perception ?? 0})");
  483. }
  484. }
  485. Debug.Log("=== END DEBUG ===");
  486. }
  487. [ContextMenu("Force Update Display")]
  488. public void ForceUpdateDisplay()
  489. {
  490. if (currentTeam != null && currentTeam.Count > 0)
  491. {
  492. Debug.Log($"🔄 Force updating display with {currentTeam.Count} team members");
  493. UpdateTeamDisplay();
  494. }
  495. else
  496. {
  497. Debug.Log("⚠️ No team data to display");
  498. }
  499. }
  500. }