ItemShopManager.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using UnityEngine.UIElements;
  4. using System.Linq;
  5. public class ItemShopManager : MonoBehaviour
  6. {
  7. [Header("Shop Settings")]
  8. public string shopName = "General Store";
  9. [Header("Shop Items (ScriptableObjects)")]
  10. [SerializeField] private List<Item> availableItems = new List<Item>();
  11. private UIDocument uiDocument;
  12. private TeamCharacter currentCustomer;
  13. // Callback for when character data changes
  14. public System.Action<TeamCharacter> OnCharacterDataChanged;
  15. // UI Elements
  16. private VisualElement shopContainer;
  17. private TextField searchField;
  18. private DropdownField categoryFilter;
  19. private ScrollView itemList;
  20. private Label shopTitle;
  21. private Label playerMoney;
  22. private Button closeButton;
  23. // Current filter state
  24. private string currentCategory = "All";
  25. private string currentSearchTerm = "";
  26. void Awake()
  27. {
  28. // Load all Item ScriptableObjects from Resources
  29. LoadAllItems();
  30. }
  31. void Start()
  32. {
  33. // Initialize UI in Start() to ensure UIDocument is ready
  34. uiDocument = GetComponent<UIDocument>();
  35. if (uiDocument == null)
  36. {
  37. Debug.LogError("ItemShopManager requires a UIDocument component");
  38. return;
  39. }
  40. if (uiDocument.visualTreeAsset == null)
  41. {
  42. Debug.LogError("ItemShopManager: UIDocument needs a Visual Tree Asset assigned! Please assign ShopUI.uxml");
  43. return;
  44. }
  45. // Ensure panel settings and proper sorting order are set
  46. EnsurePanelSettings();
  47. InitializeUI();
  48. }
  49. void LoadAllItems()
  50. {
  51. availableItems.Clear();
  52. // Load all Item ScriptableObjects from Resources/Items folder and subfolders
  53. Item[] allItems = Resources.LoadAll<Item>("Items");
  54. if (allItems.Length == 0)
  55. {
  56. Debug.LogWarning("No Item ScriptableObjects found in Resources/Items folder. Creating some default items...");
  57. CreateDefaultItems();
  58. }
  59. else
  60. {
  61. availableItems.AddRange(allItems);
  62. Debug.Log($"Loaded {allItems.Length} items from Resources/Items folder");
  63. }
  64. // Also check for items in the direct Resources folder
  65. Item[] directItems = Resources.LoadAll<Item>("");
  66. foreach (Item item in directItems)
  67. {
  68. if (!availableItems.Contains(item))
  69. {
  70. availableItems.Add(item);
  71. }
  72. }
  73. Debug.Log($"Total items available in shop: {availableItems.Count}");
  74. foreach (Item item in availableItems)
  75. {
  76. Debug.Log($"- {item.itemName} ({item.itemType})");
  77. }
  78. }
  79. void CreateDefaultItems()
  80. {
  81. // Create some default items if none are found
  82. // These will be temporary runtime items, but you should create proper ScriptableObject assets
  83. // Note: This creates runtime instances, not asset files
  84. var simpleSword = ScriptableObject.CreateInstance<WeaponItem>();
  85. simpleSword.itemName = "Simple Sword";
  86. simpleSword.description = "A basic sword for beginners.";
  87. simpleSword.itemType = ItemType.Weapon;
  88. simpleSword.goldCost = 10;
  89. simpleSword.minDamage = 1;
  90. simpleSword.maxDamage = 6;
  91. simpleSword.weaponType = WeaponType.Sword;
  92. simpleSword.searchTags = new string[] { "sword", "melee", "blade", "basic" };
  93. availableItems.Add(simpleSword);
  94. var simpleBow = ScriptableObject.CreateInstance<WeaponItem>();
  95. simpleBow.itemName = "Simple Bow";
  96. simpleBow.description = "A basic bow for shooting arrows.";
  97. simpleBow.itemType = ItemType.Weapon;
  98. simpleBow.goldCost = 15;
  99. simpleBow.minDamage = 1;
  100. simpleBow.maxDamage = 4;
  101. simpleBow.range = 150;
  102. simpleBow.weaponType = WeaponType.Bow;
  103. simpleBow.searchTags = new string[] { "bow", "ranged", "arrow", "basic" };
  104. availableItems.Add(simpleBow);
  105. var leatherArmor = ScriptableObject.CreateInstance<ArmorItem>();
  106. leatherArmor.itemName = "Leather Armor";
  107. leatherArmor.description = "Basic leather protection.";
  108. leatherArmor.itemType = ItemType.Armor;
  109. leatherArmor.goldCost = 12;
  110. leatherArmor.armorClass = 1;
  111. leatherArmor.armorType = ArmorType.Light;
  112. leatherArmor.armorSlot = ArmorSlot.Chest;
  113. leatherArmor.searchTags = new string[] { "leather", "armor", "chest", "light" };
  114. availableItems.Add(leatherArmor);
  115. var healthPotion = ScriptableObject.CreateInstance<MiscellaneousItem>();
  116. healthPotion.itemName = "Health Potion";
  117. healthPotion.description = "Restores health when consumed.";
  118. healthPotion.itemType = ItemType.Consumable;
  119. healthPotion.goldCost = 3;
  120. healthPotion.isConsumable = true;
  121. healthPotion.healthDiceCount = 1;
  122. healthPotion.healthDiceType = 6;
  123. healthPotion.healthBonus = 1;
  124. healthPotion.searchTags = new string[] { "potion", "health", "healing", "consumable" };
  125. availableItems.Add(healthPotion);
  126. Debug.Log("Created default runtime items since no ScriptableObject assets were found.");
  127. }
  128. void InitializeUI()
  129. {
  130. var root = uiDocument.rootVisualElement;
  131. Debug.Log("ItemShopManager: Initializing UI elements...");
  132. shopContainer = root.Q<VisualElement>("ShopContainer");
  133. searchField = root.Q<TextField>("SearchField");
  134. categoryFilter = root.Q<DropdownField>("CategoryFilter");
  135. itemList = root.Q<ScrollView>("ItemList");
  136. shopTitle = root.Q<Label>("ShopTitle");
  137. playerMoney = root.Q<Label>("PlayerMoney");
  138. closeButton = root.Q<Button>("CloseButton");
  139. // Debug which elements were found
  140. Debug.Log($"ShopContainer found: {shopContainer != null}");
  141. Debug.Log($"SearchField found: {searchField != null}");
  142. Debug.Log($"CategoryFilter found: {categoryFilter != null}");
  143. Debug.Log($"ItemList found: {itemList != null}");
  144. Debug.Log($"ShopTitle found: {shopTitle != null}");
  145. Debug.Log($"PlayerMoney found: {playerMoney != null}");
  146. Debug.Log($"CloseButton found: {closeButton != null}");
  147. // Setup category filter
  148. if (categoryFilter != null)
  149. {
  150. categoryFilter.choices = new List<string> { "All", "Weapons", "Armor", "Consumables", "Tools", "Accessories", "Miscellaneous" };
  151. categoryFilter.value = "All";
  152. categoryFilter.RegisterValueChangedCallback(OnCategoryChanged);
  153. }
  154. // Setup search field
  155. if (searchField != null)
  156. {
  157. searchField.RegisterValueChangedCallback(OnSearchChanged);
  158. }
  159. // Setup close button
  160. if (closeButton != null)
  161. {
  162. closeButton.clicked += CloseShop;
  163. }
  164. // Hide shop initially
  165. if (shopContainer != null)
  166. {
  167. shopContainer.style.display = DisplayStyle.None;
  168. Debug.Log("ItemShopManager: Shop initially hidden");
  169. }
  170. }
  171. public void OpenShop(TeamCharacter customer)
  172. {
  173. if (customer == null)
  174. {
  175. Debug.LogError("Cannot open shop: customer is null");
  176. return;
  177. }
  178. Debug.Log($"ItemShopManager: Opening shop for {customer.name}");
  179. // Ensure UIDocument is initialized
  180. if (uiDocument == null)
  181. {
  182. uiDocument = GetComponent<UIDocument>();
  183. }
  184. if (uiDocument == null)
  185. {
  186. Debug.LogError("ItemShopManager: UIDocument component not found! Please add a UIDocument component to this GameObject.");
  187. Debug.LogError($"GameObject name: {gameObject.name}");
  188. return;
  189. }
  190. if (uiDocument.visualTreeAsset == null)
  191. {
  192. Debug.LogError("ItemShopManager: UIDocument needs a Visual Tree Asset assigned! Please assign ShopUI.uxml");
  193. return;
  194. }
  195. // Ensure UI is initialized
  196. if (shopContainer == null)
  197. {
  198. Debug.Log("ItemShopManager: UI not initialized, initializing now...");
  199. InitializeUI();
  200. }
  201. if (shopContainer == null)
  202. {
  203. Debug.LogError("ItemShopManager: shopContainer is null! Make sure ShopUI.uxml is assigned to the UIDocument and contains a 'ShopContainer' element.");
  204. return;
  205. }
  206. currentCustomer = customer;
  207. // Update UI
  208. if (shopTitle != null)
  209. {
  210. shopTitle.text = shopName;
  211. }
  212. UpdatePlayerMoney();
  213. RefreshItemList();
  214. // Show shop
  215. if (shopContainer != null)
  216. {
  217. shopContainer.style.display = DisplayStyle.Flex;
  218. Debug.Log("ItemShopManager: Shop container visibility set to Flex");
  219. // Additional debugging
  220. Debug.Log($"Shop container style.display: {shopContainer.style.display}");
  221. Debug.Log($"Shop container resolvedStyle.display: {shopContainer.resolvedStyle.display}");
  222. Debug.Log($"Shop container visible: {shopContainer.visible}");
  223. Debug.Log($"Shop container position: {shopContainer.style.position}");
  224. Debug.Log($"Shop container width: {shopContainer.resolvedStyle.width}");
  225. Debug.Log($"Shop container height: {shopContainer.resolvedStyle.height}");
  226. }
  227. Debug.Log($"Opened {shopName} for {customer.name}");
  228. }
  229. public void CloseShop()
  230. {
  231. if (shopContainer != null)
  232. {
  233. shopContainer.style.display = DisplayStyle.None;
  234. }
  235. currentCustomer = null;
  236. Debug.Log("Closed shop");
  237. }
  238. private void OnCategoryChanged(ChangeEvent<string> evt)
  239. {
  240. currentCategory = evt.newValue;
  241. RefreshItemList();
  242. }
  243. private void OnSearchChanged(ChangeEvent<string> evt)
  244. {
  245. currentSearchTerm = evt.newValue;
  246. RefreshItemList();
  247. }
  248. private void RefreshItemList()
  249. {
  250. if (itemList == null) return;
  251. itemList.Clear();
  252. var filteredItems = GetFilteredItems();
  253. foreach (var item in filteredItems)
  254. {
  255. var itemElement = CreateItemElement(item);
  256. itemList.Add(itemElement);
  257. }
  258. }
  259. private List<Item> GetFilteredItems()
  260. {
  261. var filteredItems = new List<Item>(availableItems);
  262. // Apply category filter
  263. if (currentCategory != "All")
  264. {
  265. ItemType filterType;
  266. switch (currentCategory)
  267. {
  268. case "Weapons":
  269. filterType = ItemType.Weapon;
  270. break;
  271. case "Armor":
  272. filterType = ItemType.Armor;
  273. break;
  274. case "Consumables":
  275. filterType = ItemType.Consumable;
  276. break;
  277. case "Tools":
  278. filterType = ItemType.Tool;
  279. break;
  280. case "Accessories":
  281. filterType = ItemType.Accessory;
  282. break;
  283. case "Miscellaneous":
  284. filterType = ItemType.Miscellaneous;
  285. break;
  286. default:
  287. filterType = ItemType.Miscellaneous;
  288. break;
  289. }
  290. filteredItems = filteredItems.Where(item => item.itemType == filterType).ToList();
  291. }
  292. // Apply search filter
  293. if (!string.IsNullOrEmpty(currentSearchTerm))
  294. {
  295. filteredItems = filteredItems.Where(item => item.MatchesSearch(currentSearchTerm)).ToList();
  296. }
  297. return filteredItems;
  298. }
  299. private VisualElement CreateItemElement(Item item)
  300. {
  301. var itemContainer = new VisualElement();
  302. itemContainer.AddToClassList("shop-item");
  303. // Item header with name and cost
  304. var header = new VisualElement();
  305. header.AddToClassList("item-header");
  306. header.style.flexDirection = FlexDirection.Row;
  307. header.style.justifyContent = Justify.SpaceBetween;
  308. var nameLabel = new Label(item.itemName);
  309. nameLabel.AddToClassList("item-name");
  310. header.Add(nameLabel);
  311. var costLabel = new Label(item.GetCostString());
  312. costLabel.AddToClassList("item-cost");
  313. header.Add(costLabel);
  314. itemContainer.Add(header);
  315. // Item description
  316. var descriptionLabel = new Label(item.description);
  317. descriptionLabel.AddToClassList("item-description");
  318. descriptionLabel.style.whiteSpace = WhiteSpace.Normal;
  319. itemContainer.Add(descriptionLabel);
  320. // Item stats (if applicable)
  321. string statsString = GetItemStatsString(item);
  322. if (!string.IsNullOrEmpty(statsString))
  323. {
  324. var statsLabel = new Label(statsString);
  325. statsLabel.AddToClassList("item-stats");
  326. itemContainer.Add(statsLabel);
  327. }
  328. // Purchase button
  329. var purchaseButton = new Button(() => PurchaseItem(item));
  330. purchaseButton.text = "Buy";
  331. purchaseButton.AddToClassList("purchase-button");
  332. // Check if player can afford the item
  333. bool canAfford = currentCustomer != null && CanCustomerAfford(item);
  334. purchaseButton.SetEnabled(canAfford);
  335. if (!canAfford)
  336. {
  337. purchaseButton.AddToClassList("purchase-button-disabled");
  338. }
  339. itemContainer.Add(purchaseButton);
  340. return itemContainer;
  341. }
  342. private string GetItemStatsString(Item item)
  343. {
  344. var statStrings = new List<string>();
  345. if (item is WeaponItem weapon)
  346. {
  347. statStrings.Add($"Damage: {weapon.minDamage}-{weapon.maxDamage}");
  348. if (weapon.range > 0)
  349. statStrings.Add($"Range: {weapon.range}");
  350. if (weapon.weaponModifier != 0)
  351. statStrings.Add($"Weapon Mod: {weapon.weaponModifier:+0;-0}");
  352. }
  353. else if (item is ArmorItem armor)
  354. {
  355. if (armor.armorClass > 0)
  356. statStrings.Add($"AC: +{armor.armorClass}");
  357. if (armor.strengthModifier != 0)
  358. statStrings.Add($"STR: {armor.strengthModifier:+0;-0}");
  359. if (armor.dexterityModifier != 0)
  360. statStrings.Add($"DEX: {armor.dexterityModifier:+0;-0}");
  361. if (armor.constitutionModifier != 0)
  362. statStrings.Add($"CON: {armor.constitutionModifier:+0;-0}");
  363. if (armor.wisdomModifier != 0)
  364. statStrings.Add($"WIS: {armor.wisdomModifier:+0;-0}");
  365. }
  366. else if (item is MiscellaneousItem misc && misc.isConsumable)
  367. {
  368. if (misc.healthDiceCount > 0)
  369. {
  370. string healthEffect = $"Heals {misc.healthDiceCount}d{misc.healthDiceType}";
  371. if (misc.healthBonus != 0)
  372. healthEffect += $"{misc.healthBonus:+0;-0}";
  373. statStrings.Add(healthEffect);
  374. }
  375. else if (misc.healthRestoreMin > 0 || misc.healthRestoreMax > 0)
  376. {
  377. statStrings.Add($"Heals {misc.healthRestoreMin}-{misc.healthRestoreMax}");
  378. }
  379. if (misc.manaDiceCount > 0)
  380. {
  381. string manaEffect = $"Restores {misc.manaDiceCount}d{misc.manaDiceType}";
  382. if (misc.manaBonus != 0)
  383. manaEffect += $"{misc.manaBonus:+0;-0}";
  384. statStrings.Add($"{manaEffect} mana");
  385. }
  386. else if (misc.manaRestoreMin > 0 || misc.manaRestoreMax > 0)
  387. {
  388. statStrings.Add($"Restores {misc.manaRestoreMin}-{misc.manaRestoreMax} mana");
  389. }
  390. }
  391. return statStrings.Count > 0 ? string.Join(", ", statStrings) : "";
  392. }
  393. private void PurchaseItem(Item item)
  394. {
  395. if (currentCustomer == null)
  396. {
  397. Debug.LogError("No customer set!");
  398. return;
  399. }
  400. // Check if customer can afford the item directly
  401. if (!CanCustomerAfford(item))
  402. {
  403. Debug.LogWarning($"Cannot afford {item.itemName}");
  404. return;
  405. }
  406. // Calculate and deduct the cost
  407. DeductItemCost(item);
  408. // Add item to customer's inventory (you'll need to implement this based on your inventory system)
  409. AddItemToCustomerInventory(item);
  410. // Refresh UI
  411. UpdatePlayerMoney();
  412. RefreshItemList();
  413. // Notify listeners that character data changed
  414. OnCharacterDataChanged?.Invoke(currentCustomer);
  415. Debug.Log($"Successfully purchased {item.itemName}");
  416. }
  417. private bool CanCustomerAfford(Item item)
  418. {
  419. if (currentCustomer == null) return false;
  420. int totalCopperCost = item.goldCost * 100 + item.silverCost * 10 + item.copperCost;
  421. int totalCopperAvailable = currentCustomer.gold * 100 + currentCustomer.silver * 10 + currentCustomer.copper;
  422. return totalCopperAvailable >= totalCopperCost;
  423. }
  424. private void DeductItemCost(Item item)
  425. {
  426. // Convert everything to copper for easier calculation
  427. int totalCopperCost = item.goldCost * 100 + item.silverCost * 10 + item.copperCost;
  428. int totalCopperAvailable = currentCustomer.gold * 100 + currentCustomer.silver * 10 + currentCustomer.copper;
  429. int remainingCopper = totalCopperAvailable - totalCopperCost;
  430. // Convert back to gold, silver, copper
  431. currentCustomer.gold = remainingCopper / 100;
  432. remainingCopper %= 100;
  433. currentCustomer.silver = remainingCopper / 10;
  434. currentCustomer.copper = remainingCopper % 10;
  435. Debug.Log($"Purchased {item.itemName} for {item.goldCost}g {item.silverCost}s {item.copperCost}c");
  436. }
  437. private void AddItemToCustomerInventory(Item item)
  438. {
  439. if (currentCustomer == null) return;
  440. // Initialize lists if they're null
  441. if (currentCustomer.weapons == null)
  442. currentCustomer.weapons = new System.Collections.Generic.List<string>();
  443. if (currentCustomer.armor == null)
  444. currentCustomer.armor = new System.Collections.Generic.List<string>();
  445. if (currentCustomer.miscItems == null)
  446. currentCustomer.miscItems = new System.Collections.Generic.List<string>();
  447. // Add item to appropriate inventory list based on type
  448. switch (item.itemType)
  449. {
  450. case ItemType.Weapon:
  451. currentCustomer.weapons.Add(item.itemName);
  452. Debug.Log($"Added weapon '{item.itemName}' to {currentCustomer.name}'s weapon inventory");
  453. break;
  454. case ItemType.Armor:
  455. currentCustomer.armor.Add(item.itemName);
  456. Debug.Log($"Added armor '{item.itemName}' to {currentCustomer.name}'s armor inventory");
  457. break;
  458. case ItemType.Miscellaneous:
  459. case ItemType.Consumable:
  460. case ItemType.Tool:
  461. case ItemType.Accessory:
  462. currentCustomer.miscItems.Add(item.itemName);
  463. Debug.Log($"Added item '{item.itemName}' to {currentCustomer.name}'s misc inventory");
  464. break;
  465. default:
  466. currentCustomer.miscItems.Add(item.itemName);
  467. Debug.LogWarning($"Unknown item type for '{item.itemName}', added to misc items");
  468. break;
  469. }
  470. // Trigger UI update in MainTeamSelectScript if available
  471. TriggerInventoryUIUpdate();
  472. }
  473. private void TriggerInventoryUIUpdate()
  474. {
  475. // The OnCharacterDataChanged event is already invoked in PurchaseItem()
  476. // This should trigger any listeners to update their UI
  477. // MainTeamSelectScript should listen to this event to refresh inventory displays
  478. Debug.Log("Character inventory updated - OnCharacterDataChanged event will be triggered");
  479. }
  480. private void UpdatePlayerMoney()
  481. {
  482. if (playerMoney != null && currentCustomer != null)
  483. {
  484. playerMoney.text = $"{currentCustomer.gold}g {currentCustomer.silver}s {currentCustomer.copper}c";
  485. }
  486. }
  487. [ContextMenu("Reload Items")]
  488. public void ReloadItems()
  489. {
  490. LoadAllItems();
  491. if (shopContainer != null && shopContainer.style.display == DisplayStyle.Flex)
  492. {
  493. RefreshItemList();
  494. }
  495. }
  496. // Public methods to get items by category (for compatibility with old system)
  497. public List<Item> GetWeapons()
  498. {
  499. return availableItems.Where(item => item.itemType == ItemType.Weapon).ToList();
  500. }
  501. public List<Item> GetArmor()
  502. {
  503. return availableItems.Where(item => item.itemType == ItemType.Armor).ToList();
  504. }
  505. public List<Item> GetMiscItems()
  506. {
  507. return availableItems.Where(item =>
  508. item.itemType == ItemType.Miscellaneous ||
  509. item.itemType == ItemType.Consumable ||
  510. item.itemType == ItemType.Tool ||
  511. item.itemType == ItemType.Accessory).ToList();
  512. }
  513. public List<Item> GetAllItems()
  514. {
  515. return new List<Item>(availableItems);
  516. }
  517. [ContextMenu("Check Shop Setup")]
  518. public void CheckShopSetup()
  519. {
  520. Debug.Log("=== ItemShopManager Setup Check ===");
  521. // Check UIDocument
  522. var uiDoc = GetComponent<UIDocument>();
  523. if (uiDoc == null)
  524. {
  525. Debug.LogError("❌ No UIDocument component found on this GameObject!");
  526. Debug.LogError("➤ Add a UIDocument component to fix this.");
  527. return;
  528. }
  529. else
  530. {
  531. Debug.Log("✓ UIDocument component found");
  532. }
  533. // Check Visual Tree Asset
  534. if (uiDoc.visualTreeAsset == null)
  535. {
  536. Debug.LogError("❌ UIDocument has no Visual Tree Asset assigned!");
  537. Debug.LogError("➤ Assign ShopUI.uxml to the UIDocument component.");
  538. return;
  539. }
  540. else
  541. {
  542. Debug.Log($"✓ Visual Tree Asset assigned: {uiDoc.visualTreeAsset.name}");
  543. }
  544. // Check UI elements
  545. var root = uiDoc.rootVisualElement;
  546. var container = root?.Q<VisualElement>("ShopContainer");
  547. if (container == null)
  548. {
  549. Debug.LogError("❌ ShopContainer element not found in the UXML!");
  550. Debug.LogError("➤ Make sure you're using the correct ShopUI.uxml file.");
  551. return;
  552. }
  553. else
  554. {
  555. Debug.Log("✓ ShopContainer element found in UXML");
  556. }
  557. // Check items
  558. Debug.Log($"✓ {availableItems.Count} items loaded for shop");
  559. Debug.Log("=== Setup Check Complete - Shop should work! ===");
  560. }
  561. [ContextMenu("Force Initialize UI")]
  562. public void ForceInitializeUI()
  563. {
  564. uiDocument = GetComponent<UIDocument>();
  565. if (uiDocument != null && uiDocument.visualTreeAsset != null)
  566. {
  567. InitializeUI();
  568. Debug.Log("UI forcefully initialized");
  569. }
  570. else
  571. {
  572. Debug.LogError("Cannot initialize UI - missing UIDocument or Visual Tree Asset");
  573. }
  574. }
  575. [ContextMenu("Debug UI State")]
  576. public void DebugUIState()
  577. {
  578. Debug.Log("=== UI State Debug ===");
  579. if (uiDocument == null)
  580. {
  581. Debug.LogError("uiDocument is null");
  582. return;
  583. }
  584. Debug.Log($"UIDocument sorting order: {uiDocument.sortingOrder}");
  585. if (uiDocument.panelSettings != null)
  586. {
  587. Debug.Log($"Panel settings sorting order: {uiDocument.panelSettings.sortingOrder}");
  588. }
  589. else
  590. {
  591. Debug.LogWarning("Panel settings is null");
  592. }
  593. var root = uiDocument.rootVisualElement;
  594. Debug.Log($"Root element child count: {root.childCount}");
  595. if (shopContainer != null)
  596. {
  597. Debug.Log($"Shop container display: {shopContainer.style.display}");
  598. Debug.Log($"Shop container resolved display: {shopContainer.resolvedStyle.display}");
  599. Debug.Log($"Shop container visible: {shopContainer.visible}");
  600. Debug.Log($"Shop container opacity: {shopContainer.resolvedStyle.opacity}");
  601. Debug.Log($"Shop container position: {shopContainer.style.position}");
  602. Debug.Log($"Shop container worldBound: {shopContainer.worldBound}");
  603. }
  604. else
  605. {
  606. Debug.LogError("shopContainer is null");
  607. }
  608. // Check for other UIDocuments that might be covering this one
  609. var allUIDocuments = FindObjectsByType<UIDocument>(FindObjectsSortMode.None);
  610. Debug.Log($"Found {allUIDocuments.Length} UIDocuments in scene:");
  611. foreach (var doc in allUIDocuments)
  612. {
  613. var panelSort = doc.panelSettings?.sortingOrder ?? -999;
  614. Debug.Log($" - '{doc.gameObject.name}' sortingOrder: {doc.sortingOrder}, panelSettings: {panelSort}");
  615. }
  616. }
  617. [ContextMenu("Force Open Shop (Test)")]
  618. public void ForceOpenShopTest()
  619. {
  620. // Create a test character for debugging
  621. var testCharacter = new TeamCharacter();
  622. testCharacter.name = "Test Character";
  623. testCharacter.gold = 100;
  624. testCharacter.silver = 50;
  625. testCharacter.copper = 25;
  626. Debug.Log("Opening shop with test character...");
  627. OpenShop(testCharacter);
  628. }
  629. void EnsurePanelSettings()
  630. {
  631. if (uiDocument.panelSettings == null || uiDocument.sortingOrder <= 2)
  632. {
  633. // Try to find and reuse existing panel settings from other UI
  634. var existingUI = GameObject.Find("TravelUI")?.GetComponent<UIDocument>();
  635. if (existingUI?.panelSettings != null)
  636. {
  637. uiDocument.panelSettings = existingUI.panelSettings;
  638. Debug.Log("✓ ItemShopManager: Panel Settings assigned from TravelUI");
  639. }
  640. else
  641. {
  642. // Try to find from MainTeamSelectScript or other UI components
  643. var mainTeamSelect = FindFirstObjectByType<MainTeamSelectScript>();
  644. if (mainTeamSelect != null)
  645. {
  646. var mainUIDoc = mainTeamSelect.GetComponent<UIDocument>();
  647. if (mainUIDoc?.panelSettings != null)
  648. {
  649. uiDocument.panelSettings = mainUIDoc.panelSettings;
  650. Debug.Log("✓ ItemShopManager: Panel Settings assigned from MainTeamSelectScript");
  651. }
  652. }
  653. }
  654. // Set proper sorting order (> 2 as requested)
  655. uiDocument.sortingOrder = 5; // Higher than 2 to ensure shop displays on top
  656. if (uiDocument.panelSettings != null)
  657. {
  658. // Make sure panel settings also have a high sorting order
  659. uiDocument.panelSettings.sortingOrder = 5;
  660. Debug.Log($"✓ ItemShopManager: Sorting order set to {uiDocument.sortingOrder}");
  661. }
  662. else
  663. {
  664. Debug.LogWarning("⚠ ItemShopManager: Could not assign Panel Settings. Shop may not display properly.");
  665. }
  666. }
  667. }
  668. }