ItemShopManager.cs 23 KB

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