|
|
@@ -0,0 +1,699 @@
|
|
|
+using System.Collections.Generic;
|
|
|
+using UnityEngine;
|
|
|
+using UnityEngine.UIElements;
|
|
|
+using System.Linq;
|
|
|
+
|
|
|
+public class ItemShopManager : MonoBehaviour
|
|
|
+{
|
|
|
+ [Header("Shop Settings")]
|
|
|
+ public string shopName = "General Store";
|
|
|
+
|
|
|
+ [Header("Shop Items (ScriptableObjects)")]
|
|
|
+ [SerializeField] private List<Item> availableItems = new List<Item>();
|
|
|
+
|
|
|
+ private UIDocument uiDocument;
|
|
|
+ private TeamCharacter currentCustomer;
|
|
|
+
|
|
|
+ // Callback for when character data changes
|
|
|
+ public System.Action<TeamCharacter> OnCharacterDataChanged;
|
|
|
+
|
|
|
+ // UI Elements
|
|
|
+ private VisualElement shopContainer;
|
|
|
+ private TextField searchField;
|
|
|
+ private DropdownField categoryFilter;
|
|
|
+ private ScrollView itemList;
|
|
|
+ private Label shopTitle;
|
|
|
+ private Label playerMoney;
|
|
|
+ private Button closeButton;
|
|
|
+
|
|
|
+ // Current filter state
|
|
|
+ private string currentCategory = "All";
|
|
|
+ private string currentSearchTerm = "";
|
|
|
+
|
|
|
+ void Awake()
|
|
|
+ {
|
|
|
+ // Load all Item ScriptableObjects from Resources
|
|
|
+ LoadAllItems();
|
|
|
+ }
|
|
|
+
|
|
|
+ void Start()
|
|
|
+ {
|
|
|
+ // Initialize UI in Start() to ensure UIDocument is ready
|
|
|
+ uiDocument = GetComponent<UIDocument>();
|
|
|
+ if (uiDocument == null)
|
|
|
+ {
|
|
|
+ Debug.LogError("ItemShopManager requires a UIDocument component");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (uiDocument.visualTreeAsset == null)
|
|
|
+ {
|
|
|
+ Debug.LogError("ItemShopManager: UIDocument needs a Visual Tree Asset assigned! Please assign ShopUI.uxml");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ InitializeUI();
|
|
|
+ }
|
|
|
+
|
|
|
+ void LoadAllItems()
|
|
|
+ {
|
|
|
+ availableItems.Clear();
|
|
|
+
|
|
|
+ // Load all Item ScriptableObjects from Resources/Items folder and subfolders
|
|
|
+ Item[] allItems = Resources.LoadAll<Item>("Items");
|
|
|
+
|
|
|
+ if (allItems.Length == 0)
|
|
|
+ {
|
|
|
+ Debug.LogWarning("No Item ScriptableObjects found in Resources/Items folder. Creating some default items...");
|
|
|
+ CreateDefaultItems();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ availableItems.AddRange(allItems);
|
|
|
+ Debug.Log($"Loaded {allItems.Length} items from Resources/Items folder");
|
|
|
+ }
|
|
|
+
|
|
|
+ // Also check for items in the direct Resources folder
|
|
|
+ Item[] directItems = Resources.LoadAll<Item>("");
|
|
|
+ foreach (Item item in directItems)
|
|
|
+ {
|
|
|
+ if (!availableItems.Contains(item))
|
|
|
+ {
|
|
|
+ availableItems.Add(item);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Debug.Log($"Total items available in shop: {availableItems.Count}");
|
|
|
+ foreach (Item item in availableItems)
|
|
|
+ {
|
|
|
+ Debug.Log($"- {item.itemName} ({item.itemType})");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void CreateDefaultItems()
|
|
|
+ {
|
|
|
+ // Create some default items if none are found
|
|
|
+ // These will be temporary runtime items, but you should create proper ScriptableObject assets
|
|
|
+
|
|
|
+ // Note: This creates runtime instances, not asset files
|
|
|
+ var simpleSword = ScriptableObject.CreateInstance<WeaponItem>();
|
|
|
+ simpleSword.itemName = "Simple Sword";
|
|
|
+ simpleSword.description = "A basic sword for beginners.";
|
|
|
+ simpleSword.itemType = ItemType.Weapon;
|
|
|
+ simpleSword.goldCost = 10;
|
|
|
+ simpleSword.minDamage = 1;
|
|
|
+ simpleSword.maxDamage = 6;
|
|
|
+ simpleSword.weaponType = WeaponType.Sword;
|
|
|
+ simpleSword.searchTags = new string[] { "sword", "melee", "blade", "basic" };
|
|
|
+ availableItems.Add(simpleSword);
|
|
|
+
|
|
|
+ var simpleBow = ScriptableObject.CreateInstance<WeaponItem>();
|
|
|
+ simpleBow.itemName = "Simple Bow";
|
|
|
+ simpleBow.description = "A basic bow for shooting arrows.";
|
|
|
+ simpleBow.itemType = ItemType.Weapon;
|
|
|
+ simpleBow.goldCost = 15;
|
|
|
+ simpleBow.minDamage = 1;
|
|
|
+ simpleBow.maxDamage = 4;
|
|
|
+ simpleBow.range = 150;
|
|
|
+ simpleBow.weaponType = WeaponType.Bow;
|
|
|
+ simpleBow.searchTags = new string[] { "bow", "ranged", "arrow", "basic" };
|
|
|
+ availableItems.Add(simpleBow);
|
|
|
+
|
|
|
+ var leatherArmor = ScriptableObject.CreateInstance<ArmorItem>();
|
|
|
+ leatherArmor.itemName = "Leather Armor";
|
|
|
+ leatherArmor.description = "Basic leather protection.";
|
|
|
+ leatherArmor.itemType = ItemType.Armor;
|
|
|
+ leatherArmor.goldCost = 12;
|
|
|
+ leatherArmor.armorClass = 1;
|
|
|
+ leatherArmor.armorType = ArmorType.Light;
|
|
|
+ leatherArmor.armorSlot = ArmorSlot.Chest;
|
|
|
+ leatherArmor.searchTags = new string[] { "leather", "armor", "chest", "light" };
|
|
|
+ availableItems.Add(leatherArmor);
|
|
|
+
|
|
|
+ var healthPotion = ScriptableObject.CreateInstance<MiscellaneousItem>();
|
|
|
+ healthPotion.itemName = "Health Potion";
|
|
|
+ healthPotion.description = "Restores health when consumed.";
|
|
|
+ healthPotion.itemType = ItemType.Consumable;
|
|
|
+ healthPotion.goldCost = 3;
|
|
|
+ healthPotion.isConsumable = true;
|
|
|
+ healthPotion.healthDiceCount = 1;
|
|
|
+ healthPotion.healthDiceType = 6;
|
|
|
+ healthPotion.healthBonus = 1;
|
|
|
+ healthPotion.searchTags = new string[] { "potion", "health", "healing", "consumable" };
|
|
|
+ availableItems.Add(healthPotion);
|
|
|
+
|
|
|
+ Debug.Log("Created default runtime items since no ScriptableObject assets were found.");
|
|
|
+ }
|
|
|
+
|
|
|
+ void InitializeUI()
|
|
|
+ {
|
|
|
+ var root = uiDocument.rootVisualElement;
|
|
|
+ Debug.Log("ItemShopManager: Initializing UI elements...");
|
|
|
+
|
|
|
+ shopContainer = root.Q<VisualElement>("ShopContainer");
|
|
|
+ searchField = root.Q<TextField>("SearchField");
|
|
|
+ categoryFilter = root.Q<DropdownField>("CategoryFilter");
|
|
|
+ itemList = root.Q<ScrollView>("ItemList");
|
|
|
+ shopTitle = root.Q<Label>("ShopTitle");
|
|
|
+ playerMoney = root.Q<Label>("PlayerMoney");
|
|
|
+ closeButton = root.Q<Button>("CloseButton");
|
|
|
+
|
|
|
+ // Debug which elements were found
|
|
|
+ Debug.Log($"ShopContainer found: {shopContainer != null}");
|
|
|
+ Debug.Log($"SearchField found: {searchField != null}");
|
|
|
+ Debug.Log($"CategoryFilter found: {categoryFilter != null}");
|
|
|
+ Debug.Log($"ItemList found: {itemList != null}");
|
|
|
+ Debug.Log($"ShopTitle found: {shopTitle != null}");
|
|
|
+ Debug.Log($"PlayerMoney found: {playerMoney != null}");
|
|
|
+ Debug.Log($"CloseButton found: {closeButton != null}");
|
|
|
+
|
|
|
+ // Setup category filter
|
|
|
+ if (categoryFilter != null)
|
|
|
+ {
|
|
|
+ categoryFilter.choices = new List<string> { "All", "Weapons", "Armor", "Consumables", "Tools", "Accessories", "Miscellaneous" };
|
|
|
+ categoryFilter.value = "All";
|
|
|
+ categoryFilter.RegisterValueChangedCallback(OnCategoryChanged);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Setup search field
|
|
|
+ if (searchField != null)
|
|
|
+ {
|
|
|
+ searchField.RegisterValueChangedCallback(OnSearchChanged);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Setup close button
|
|
|
+ if (closeButton != null)
|
|
|
+ {
|
|
|
+ closeButton.clicked += CloseShop;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Hide shop initially
|
|
|
+ if (shopContainer != null)
|
|
|
+ {
|
|
|
+ shopContainer.style.display = DisplayStyle.None;
|
|
|
+ Debug.Log("ItemShopManager: Shop initially hidden");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void OpenShop(TeamCharacter customer)
|
|
|
+ {
|
|
|
+ if (customer == null)
|
|
|
+ {
|
|
|
+ Debug.LogError("Cannot open shop: customer is null");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Debug.Log($"ItemShopManager: Opening shop for {customer.name}");
|
|
|
+
|
|
|
+ // Ensure UIDocument is initialized
|
|
|
+ if (uiDocument == null)
|
|
|
+ {
|
|
|
+ uiDocument = GetComponent<UIDocument>();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (uiDocument == null)
|
|
|
+ {
|
|
|
+ Debug.LogError("ItemShopManager: UIDocument component not found! Please add a UIDocument component to this GameObject.");
|
|
|
+ Debug.LogError($"GameObject name: {gameObject.name}");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (uiDocument.visualTreeAsset == null)
|
|
|
+ {
|
|
|
+ Debug.LogError("ItemShopManager: UIDocument needs a Visual Tree Asset assigned! Please assign ShopUI.uxml");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Ensure UI is initialized
|
|
|
+ if (shopContainer == null)
|
|
|
+ {
|
|
|
+ Debug.Log("ItemShopManager: UI not initialized, initializing now...");
|
|
|
+ InitializeUI();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (shopContainer == null)
|
|
|
+ {
|
|
|
+ Debug.LogError("ItemShopManager: shopContainer is null! Make sure ShopUI.uxml is assigned to the UIDocument and contains a 'ShopContainer' element.");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ currentCustomer = customer;
|
|
|
+
|
|
|
+ // Update UI
|
|
|
+ if (shopTitle != null)
|
|
|
+ {
|
|
|
+ shopTitle.text = shopName;
|
|
|
+ }
|
|
|
+
|
|
|
+ UpdatePlayerMoney();
|
|
|
+ RefreshItemList();
|
|
|
+
|
|
|
+ // Show shop
|
|
|
+ if (shopContainer != null)
|
|
|
+ {
|
|
|
+ shopContainer.style.display = DisplayStyle.Flex;
|
|
|
+ Debug.Log("ItemShopManager: Shop container visibility set to Flex");
|
|
|
+
|
|
|
+ // Additional debugging
|
|
|
+ Debug.Log($"Shop container style.display: {shopContainer.style.display}");
|
|
|
+ Debug.Log($"Shop container resolvedStyle.display: {shopContainer.resolvedStyle.display}");
|
|
|
+ Debug.Log($"Shop container visible: {shopContainer.visible}");
|
|
|
+ Debug.Log($"Shop container position: {shopContainer.style.position}");
|
|
|
+ Debug.Log($"Shop container width: {shopContainer.resolvedStyle.width}");
|
|
|
+ Debug.Log($"Shop container height: {shopContainer.resolvedStyle.height}");
|
|
|
+ }
|
|
|
+
|
|
|
+ Debug.Log($"Opened {shopName} for {customer.name}");
|
|
|
+ }
|
|
|
+
|
|
|
+ public void CloseShop()
|
|
|
+ {
|
|
|
+ if (shopContainer != null)
|
|
|
+ {
|
|
|
+ shopContainer.style.display = DisplayStyle.None;
|
|
|
+ }
|
|
|
+
|
|
|
+ currentCustomer = null;
|
|
|
+ Debug.Log("Closed shop");
|
|
|
+ }
|
|
|
+
|
|
|
+ private void OnCategoryChanged(ChangeEvent<string> evt)
|
|
|
+ {
|
|
|
+ currentCategory = evt.newValue;
|
|
|
+ RefreshItemList();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void OnSearchChanged(ChangeEvent<string> evt)
|
|
|
+ {
|
|
|
+ currentSearchTerm = evt.newValue;
|
|
|
+ RefreshItemList();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void RefreshItemList()
|
|
|
+ {
|
|
|
+ if (itemList == null) return;
|
|
|
+
|
|
|
+ itemList.Clear();
|
|
|
+
|
|
|
+ var filteredItems = GetFilteredItems();
|
|
|
+
|
|
|
+ foreach (var item in filteredItems)
|
|
|
+ {
|
|
|
+ var itemElement = CreateItemElement(item);
|
|
|
+ itemList.Add(itemElement);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<Item> GetFilteredItems()
|
|
|
+ {
|
|
|
+ var filteredItems = new List<Item>(availableItems);
|
|
|
+
|
|
|
+ // Apply category filter
|
|
|
+ if (currentCategory != "All")
|
|
|
+ {
|
|
|
+ ItemType filterType;
|
|
|
+ switch (currentCategory)
|
|
|
+ {
|
|
|
+ case "Weapons":
|
|
|
+ filterType = ItemType.Weapon;
|
|
|
+ break;
|
|
|
+ case "Armor":
|
|
|
+ filterType = ItemType.Armor;
|
|
|
+ break;
|
|
|
+ case "Consumables":
|
|
|
+ filterType = ItemType.Consumable;
|
|
|
+ break;
|
|
|
+ case "Tools":
|
|
|
+ filterType = ItemType.Tool;
|
|
|
+ break;
|
|
|
+ case "Accessories":
|
|
|
+ filterType = ItemType.Accessory;
|
|
|
+ break;
|
|
|
+ case "Miscellaneous":
|
|
|
+ filterType = ItemType.Miscellaneous;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ filterType = ItemType.Miscellaneous;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ filteredItems = filteredItems.Where(item => item.itemType == filterType).ToList();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Apply search filter
|
|
|
+ if (!string.IsNullOrEmpty(currentSearchTerm))
|
|
|
+ {
|
|
|
+ filteredItems = filteredItems.Where(item => item.MatchesSearch(currentSearchTerm)).ToList();
|
|
|
+ }
|
|
|
+
|
|
|
+ return filteredItems;
|
|
|
+ }
|
|
|
+
|
|
|
+ private VisualElement CreateItemElement(Item item)
|
|
|
+ {
|
|
|
+ var itemContainer = new VisualElement();
|
|
|
+ itemContainer.AddToClassList("shop-item");
|
|
|
+
|
|
|
+ // Item header with name and cost
|
|
|
+ var header = new VisualElement();
|
|
|
+ header.AddToClassList("item-header");
|
|
|
+ header.style.flexDirection = FlexDirection.Row;
|
|
|
+ header.style.justifyContent = Justify.SpaceBetween;
|
|
|
+
|
|
|
+ var nameLabel = new Label(item.itemName);
|
|
|
+ nameLabel.AddToClassList("item-name");
|
|
|
+ header.Add(nameLabel);
|
|
|
+
|
|
|
+ var costLabel = new Label(item.GetCostString());
|
|
|
+ costLabel.AddToClassList("item-cost");
|
|
|
+ header.Add(costLabel);
|
|
|
+
|
|
|
+ itemContainer.Add(header);
|
|
|
+
|
|
|
+ // Item description
|
|
|
+ var descriptionLabel = new Label(item.description);
|
|
|
+ descriptionLabel.AddToClassList("item-description");
|
|
|
+ descriptionLabel.style.whiteSpace = WhiteSpace.Normal;
|
|
|
+ itemContainer.Add(descriptionLabel);
|
|
|
+
|
|
|
+ // Item stats (if applicable)
|
|
|
+ string statsString = GetItemStatsString(item);
|
|
|
+ if (!string.IsNullOrEmpty(statsString))
|
|
|
+ {
|
|
|
+ var statsLabel = new Label(statsString);
|
|
|
+ statsLabel.AddToClassList("item-stats");
|
|
|
+ itemContainer.Add(statsLabel);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Purchase button
|
|
|
+ var purchaseButton = new Button(() => PurchaseItem(item));
|
|
|
+ purchaseButton.text = "Buy";
|
|
|
+ purchaseButton.AddToClassList("purchase-button");
|
|
|
+
|
|
|
+ // Check if player can afford the item
|
|
|
+ bool canAfford = currentCustomer != null && CanCustomerAfford(item);
|
|
|
+ purchaseButton.SetEnabled(canAfford);
|
|
|
+
|
|
|
+ if (!canAfford)
|
|
|
+ {
|
|
|
+ purchaseButton.AddToClassList("purchase-button-disabled");
|
|
|
+ }
|
|
|
+
|
|
|
+ itemContainer.Add(purchaseButton);
|
|
|
+
|
|
|
+ return itemContainer;
|
|
|
+ }
|
|
|
+
|
|
|
+ private string GetItemStatsString(Item item)
|
|
|
+ {
|
|
|
+ var statStrings = new List<string>();
|
|
|
+
|
|
|
+ if (item is WeaponItem weapon)
|
|
|
+ {
|
|
|
+ statStrings.Add($"Damage: {weapon.minDamage}-{weapon.maxDamage}");
|
|
|
+ if (weapon.range > 0)
|
|
|
+ statStrings.Add($"Range: {weapon.range}");
|
|
|
+ if (weapon.weaponModifier != 0)
|
|
|
+ statStrings.Add($"Weapon Mod: {weapon.weaponModifier:+0;-0}");
|
|
|
+ }
|
|
|
+ else if (item is ArmorItem armor)
|
|
|
+ {
|
|
|
+ if (armor.armorClass > 0)
|
|
|
+ statStrings.Add($"AC: +{armor.armorClass}");
|
|
|
+ if (armor.strengthModifier != 0)
|
|
|
+ statStrings.Add($"STR: {armor.strengthModifier:+0;-0}");
|
|
|
+ if (armor.dexterityModifier != 0)
|
|
|
+ statStrings.Add($"DEX: {armor.dexterityModifier:+0;-0}");
|
|
|
+ if (armor.constitutionModifier != 0)
|
|
|
+ statStrings.Add($"CON: {armor.constitutionModifier:+0;-0}");
|
|
|
+ if (armor.wisdomModifier != 0)
|
|
|
+ statStrings.Add($"WIS: {armor.wisdomModifier:+0;-0}");
|
|
|
+ }
|
|
|
+ else if (item is MiscellaneousItem misc && misc.isConsumable)
|
|
|
+ {
|
|
|
+ if (misc.healthDiceCount > 0)
|
|
|
+ {
|
|
|
+ string healthEffect = $"Heals {misc.healthDiceCount}d{misc.healthDiceType}";
|
|
|
+ if (misc.healthBonus != 0)
|
|
|
+ healthEffect += $"{misc.healthBonus:+0;-0}";
|
|
|
+ statStrings.Add(healthEffect);
|
|
|
+ }
|
|
|
+ else if (misc.healthRestoreMin > 0 || misc.healthRestoreMax > 0)
|
|
|
+ {
|
|
|
+ statStrings.Add($"Heals {misc.healthRestoreMin}-{misc.healthRestoreMax}");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (misc.manaDiceCount > 0)
|
|
|
+ {
|
|
|
+ string manaEffect = $"Restores {misc.manaDiceCount}d{misc.manaDiceType}";
|
|
|
+ if (misc.manaBonus != 0)
|
|
|
+ manaEffect += $"{misc.manaBonus:+0;-0}";
|
|
|
+ statStrings.Add($"{manaEffect} mana");
|
|
|
+ }
|
|
|
+ else if (misc.manaRestoreMin > 0 || misc.manaRestoreMax > 0)
|
|
|
+ {
|
|
|
+ statStrings.Add($"Restores {misc.manaRestoreMin}-{misc.manaRestoreMax} mana");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return statStrings.Count > 0 ? string.Join(", ", statStrings) : "";
|
|
|
+ }
|
|
|
+
|
|
|
+ private void PurchaseItem(Item item)
|
|
|
+ {
|
|
|
+ if (currentCustomer == null)
|
|
|
+ {
|
|
|
+ Debug.LogError("No customer set!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check if customer can afford the item directly
|
|
|
+ if (!CanCustomerAfford(item))
|
|
|
+ {
|
|
|
+ Debug.LogWarning($"Cannot afford {item.itemName}");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Calculate and deduct the cost
|
|
|
+ DeductItemCost(item);
|
|
|
+
|
|
|
+ // Add item to customer's inventory (you'll need to implement this based on your inventory system)
|
|
|
+ AddItemToCustomerInventory(item);
|
|
|
+
|
|
|
+ // Refresh UI
|
|
|
+ UpdatePlayerMoney();
|
|
|
+ RefreshItemList();
|
|
|
+
|
|
|
+ // Notify listeners that character data changed
|
|
|
+ OnCharacterDataChanged?.Invoke(currentCustomer);
|
|
|
+
|
|
|
+ Debug.Log($"Successfully purchased {item.itemName}");
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool CanCustomerAfford(Item item)
|
|
|
+ {
|
|
|
+ if (currentCustomer == null) return false;
|
|
|
+
|
|
|
+ int totalCopperCost = item.goldCost * 100 + item.silverCost * 10 + item.copperCost;
|
|
|
+ int totalCopperAvailable = currentCustomer.gold * 100 + currentCustomer.silver * 10 + currentCustomer.copper;
|
|
|
+ return totalCopperAvailable >= totalCopperCost;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void DeductItemCost(Item item)
|
|
|
+ {
|
|
|
+ // Convert everything to copper for easier calculation
|
|
|
+ int totalCopperCost = item.goldCost * 100 + item.silverCost * 10 + item.copperCost;
|
|
|
+ int totalCopperAvailable = currentCustomer.gold * 100 + currentCustomer.silver * 10 + currentCustomer.copper;
|
|
|
+
|
|
|
+ int remainingCopper = totalCopperAvailable - totalCopperCost;
|
|
|
+
|
|
|
+ // Convert back to gold, silver, copper
|
|
|
+ currentCustomer.gold = remainingCopper / 100;
|
|
|
+ remainingCopper %= 100;
|
|
|
+ currentCustomer.silver = remainingCopper / 10;
|
|
|
+ currentCustomer.copper = remainingCopper % 10;
|
|
|
+
|
|
|
+ Debug.Log($"Purchased {item.itemName} for {item.goldCost}g {item.silverCost}s {item.copperCost}c");
|
|
|
+ }
|
|
|
+
|
|
|
+ private void AddItemToCustomerInventory(Item item)
|
|
|
+ {
|
|
|
+ // This method needs to be implemented based on your inventory system
|
|
|
+ // For now, let's just log what would happen
|
|
|
+ Debug.Log($"Would add {item.itemName} to {currentCustomer.name}'s inventory");
|
|
|
+
|
|
|
+ // If you have an inventory system, add the item here
|
|
|
+ // For example:
|
|
|
+ // currentCustomer.inventory.AddItem(item);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void UpdatePlayerMoney()
|
|
|
+ {
|
|
|
+ if (playerMoney != null && currentCustomer != null)
|
|
|
+ {
|
|
|
+ playerMoney.text = $"{currentCustomer.gold}g {currentCustomer.silver}s {currentCustomer.copper}c";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ [ContextMenu("Reload Items")]
|
|
|
+ public void ReloadItems()
|
|
|
+ {
|
|
|
+ LoadAllItems();
|
|
|
+ if (shopContainer != null && shopContainer.style.display == DisplayStyle.Flex)
|
|
|
+ {
|
|
|
+ RefreshItemList();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Public methods to get items by category (for compatibility with old system)
|
|
|
+ public List<Item> GetWeapons()
|
|
|
+ {
|
|
|
+ return availableItems.Where(item => item.itemType == ItemType.Weapon).ToList();
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<Item> GetArmor()
|
|
|
+ {
|
|
|
+ return availableItems.Where(item => item.itemType == ItemType.Armor).ToList();
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<Item> GetMiscItems()
|
|
|
+ {
|
|
|
+ return availableItems.Where(item =>
|
|
|
+ item.itemType == ItemType.Miscellaneous ||
|
|
|
+ item.itemType == ItemType.Consumable ||
|
|
|
+ item.itemType == ItemType.Tool ||
|
|
|
+ item.itemType == ItemType.Accessory).ToList();
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<Item> GetAllItems()
|
|
|
+ {
|
|
|
+ return new List<Item>(availableItems);
|
|
|
+ }
|
|
|
+
|
|
|
+ [ContextMenu("Check Shop Setup")]
|
|
|
+ public void CheckShopSetup()
|
|
|
+ {
|
|
|
+ Debug.Log("=== ItemShopManager Setup Check ===");
|
|
|
+
|
|
|
+ // Check UIDocument
|
|
|
+ var uiDoc = GetComponent<UIDocument>();
|
|
|
+ if (uiDoc == null)
|
|
|
+ {
|
|
|
+ Debug.LogError("❌ No UIDocument component found on this GameObject!");
|
|
|
+ Debug.LogError("➤ Add a UIDocument component to fix this.");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Debug.Log("✓ UIDocument component found");
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check Visual Tree Asset
|
|
|
+ if (uiDoc.visualTreeAsset == null)
|
|
|
+ {
|
|
|
+ Debug.LogError("❌ UIDocument has no Visual Tree Asset assigned!");
|
|
|
+ Debug.LogError("➤ Assign ShopUI.uxml to the UIDocument component.");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Debug.Log($"✓ Visual Tree Asset assigned: {uiDoc.visualTreeAsset.name}");
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check UI elements
|
|
|
+ var root = uiDoc.rootVisualElement;
|
|
|
+ var container = root?.Q<VisualElement>("ShopContainer");
|
|
|
+ if (container == null)
|
|
|
+ {
|
|
|
+ Debug.LogError("❌ ShopContainer element not found in the UXML!");
|
|
|
+ Debug.LogError("➤ Make sure you're using the correct ShopUI.uxml file.");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Debug.Log("✓ ShopContainer element found in UXML");
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check items
|
|
|
+ Debug.Log($"✓ {availableItems.Count} items loaded for shop");
|
|
|
+
|
|
|
+ Debug.Log("=== Setup Check Complete - Shop should work! ===");
|
|
|
+ }
|
|
|
+
|
|
|
+ [ContextMenu("Force Initialize UI")]
|
|
|
+ public void ForceInitializeUI()
|
|
|
+ {
|
|
|
+ uiDocument = GetComponent<UIDocument>();
|
|
|
+ if (uiDocument != null && uiDocument.visualTreeAsset != null)
|
|
|
+ {
|
|
|
+ InitializeUI();
|
|
|
+ Debug.Log("UI forcefully initialized");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Debug.LogError("Cannot initialize UI - missing UIDocument or Visual Tree Asset");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ [ContextMenu("Debug UI State")]
|
|
|
+ public void DebugUIState()
|
|
|
+ {
|
|
|
+ Debug.Log("=== UI State Debug ===");
|
|
|
+
|
|
|
+ if (uiDocument == null)
|
|
|
+ {
|
|
|
+ Debug.LogError("uiDocument is null");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Debug.Log($"UIDocument sorting order: {uiDocument.sortingOrder}");
|
|
|
+ if (uiDocument.panelSettings != null)
|
|
|
+ {
|
|
|
+ Debug.Log($"Panel settings sorting order: {uiDocument.panelSettings.sortingOrder}");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Debug.LogWarning("Panel settings is null");
|
|
|
+ }
|
|
|
+
|
|
|
+ var root = uiDocument.rootVisualElement;
|
|
|
+ Debug.Log($"Root element child count: {root.childCount}");
|
|
|
+
|
|
|
+ if (shopContainer != null)
|
|
|
+ {
|
|
|
+ Debug.Log($"Shop container display: {shopContainer.style.display}");
|
|
|
+ Debug.Log($"Shop container resolved display: {shopContainer.resolvedStyle.display}");
|
|
|
+ Debug.Log($"Shop container visible: {shopContainer.visible}");
|
|
|
+ Debug.Log($"Shop container opacity: {shopContainer.resolvedStyle.opacity}");
|
|
|
+ Debug.Log($"Shop container position: {shopContainer.style.position}");
|
|
|
+ Debug.Log($"Shop container worldBound: {shopContainer.worldBound}");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Debug.LogError("shopContainer is null");
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check for other UIDocuments that might be covering this one
|
|
|
+ var allUIDocuments = FindObjectsByType<UIDocument>(FindObjectsSortMode.None);
|
|
|
+ Debug.Log($"Found {allUIDocuments.Length} UIDocuments in scene:");
|
|
|
+ foreach (var doc in allUIDocuments)
|
|
|
+ {
|
|
|
+ var panelSort = doc.panelSettings?.sortingOrder ?? -999;
|
|
|
+ Debug.Log($" - '{doc.gameObject.name}' sortingOrder: {doc.sortingOrder}, panelSettings: {panelSort}");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ [ContextMenu("Force Open Shop (Test)")]
|
|
|
+ public void ForceOpenShopTest()
|
|
|
+ {
|
|
|
+ // Create a test character for debugging
|
|
|
+ var testCharacter = new TeamCharacter();
|
|
|
+ testCharacter.name = "Test Character";
|
|
|
+ testCharacter.gold = 100;
|
|
|
+ testCharacter.silver = 50;
|
|
|
+ testCharacter.copper = 25;
|
|
|
+
|
|
|
+ Debug.Log("Opening shop with test character...");
|
|
|
+ OpenShop(testCharacter);
|
|
|
+ }
|
|
|
+}
|