| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602 |
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.UIElements;
- public class SimpleShopManager : MonoBehaviour
- {
- [Header("Shop Settings")]
- public string shopName = "General Store";
- [Header("Available Items (Simple Version)")]
- public List<SimpleShopItem> weapons = new List<SimpleShopItem>();
- public List<SimpleShopItem> armor = new List<SimpleShopItem>();
- public List<SimpleShopItem> miscItems = new List<SimpleShopItem>();
- 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()
- {
- // Initialize default items first
- InitializeDefaultItems();
- }
- void Start()
- {
- // Initialize UI in Start() to ensure UIDocument is ready
- uiDocument = GetComponent<UIDocument>();
- if (uiDocument == null)
- {
- Debug.LogError("SimpleShopManager requires a UIDocument component");
- return;
- }
- if (uiDocument.visualTreeAsset == null)
- {
- Debug.LogError("SimpleShopManager: UIDocument needs a Visual Tree Asset assigned! Please assign ShopUI.uxml");
- return;
- }
- InitializeUI();
- }
- void InitializeDefaultItems()
- {
- // Initialize with some default items if lists are empty
- if (weapons.Count == 0)
- {
- weapons.Add(new SimpleShopItem("Simple Sword", "A basic sword for beginners.", ShopItemType.Weapon, 10, 0, 0, "sword,melee,blade,basic",
- new ItemStats { damageBonus = 1 }));
- weapons.Add(new SimpleShopItem("Simple Bow", "A basic bow for shooting arrows.", ShopItemType.Weapon, 15, 0, 0, "bow,ranged,arrow,basic",
- new ItemStats { damageBonus = 1 }));
- weapons.Add(new SimpleShopItem("Iron Sword", "A well-crafted iron sword.", ShopItemType.Weapon, 25, 0, 0, "sword,melee,blade,iron",
- new ItemStats { damageBonus = 2 }));
- weapons.Add(new SimpleShopItem("Composite Bow", "A bow made of multiple materials.", ShopItemType.Weapon, 35, 0, 0, "bow,ranged,arrow,composite",
- new ItemStats { damageBonus = 2 }));
- }
- if (armor.Count == 0)
- {
- armor.Add(new SimpleShopItem("Leather Helmet", "Basic head protection.", ShopItemType.Armor, 5, 0, 0, "helmet,head,leather,light"));
- armor.Add(new SimpleShopItem("Leather Vest", "Simple chest protection.", ShopItemType.Armor, 12, 0, 0, "vest,chest,leather,light",
- new ItemStats { acBonus = 1 }));
- armor.Add(new SimpleShopItem("Iron Chainmail", "Chainmail made of iron rings.", ShopItemType.Armor, 30, 0, 0, "chainmail,chest,iron,medium",
- new ItemStats { acBonus = 2 }));
- }
- if (miscItems.Count == 0)
- {
- miscItems.Add(new SimpleShopItem("Health Potion", "Restores 15 health points.", ShopItemType.Miscellaneous, 3, 0, 0, "potion,health,healing,consumable",
- new ItemStats { healthBonus = 15 }));
- miscItems.Add(new SimpleShopItem("Hemp Rope", "50 feet of sturdy rope.", ShopItemType.Miscellaneous, 0, 8, 0, "rope,hemp,utility,tool"));
- miscItems.Add(new SimpleShopItem("Torch", "Provides light in dark places.", ShopItemType.Miscellaneous, 0, 2, 0, "torch,light,utility"));
- }
- }
- void InitializeUI()
- {
- var root = uiDocument.rootVisualElement;
- Debug.Log("SimpleShopManager: 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", "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("SimpleShopManager: Shop initially hidden");
- }
- // Debug UI layering information
- DebugUILayering();
- }
- void DebugUILayering()
- {
- if (uiDocument != null)
- {
- var panelSettings = uiDocument.panelSettings;
- if (panelSettings != null)
- {
- Debug.Log($"Shop Panel Settings - sortingOrder: {panelSettings.sortingOrder}");
- }
- else
- {
- Debug.LogWarning("Shop UIDocument has no Panel Settings! This will cause layering issues.");
- }
- Debug.Log($"Shop UIDocument - sortingOrder: {uiDocument.sortingOrder}");
- }
- // Check for other UIDocuments in the scene for comparison
- 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($"UIDocument '{doc.gameObject.name}' - sortingOrder: {doc.sortingOrder}, PanelSettings sortingOrder: {panelSort}");
- }
- }
- [ContextMenu("Fix UI Layering")]
- public void FixUILayering()
- {
- if (uiDocument != null)
- {
- // Set the UIDocument sortingOrder to a higher value
- uiDocument.sortingOrder = 10;
- // If Panel Settings exist, also set their sortingOrder
- if (uiDocument.panelSettings != null)
- {
- uiDocument.panelSettings.sortingOrder = 10;
- Debug.Log("Updated Panel Settings sortingOrder to 10");
- }
- Debug.Log("Updated Shop UIDocument sortingOrder to 10 - Shop should now render on top!");
- }
- else
- {
- Debug.LogError("No UIDocument found on SimpleShopManager!");
- }
- }
- public void OpenShop(TeamCharacter customer)
- {
- if (customer == null)
- {
- Debug.LogError("Cannot open shop: customer is null");
- return;
- }
- Debug.Log($"SimpleShopManager: Opening shop for {customer.name}");
- if (uiDocument == null)
- {
- Debug.LogError("SimpleShopManager: UIDocument is null!");
- return;
- }
- if (shopContainer == null)
- {
- Debug.LogError("SimpleShopManager: shopContainer is null! Make sure ShopUI.uxml is assigned to the UIDocument.");
- 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("SimpleShopManager: Shop container visibility set to Flex");
- }
- 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<SimpleShopItem> GetFilteredItems()
- {
- var allItems = new List<SimpleShopItem>();
- // Add items based on category filter
- if (currentCategory == "All" || currentCategory == "Weapons")
- {
- allItems.AddRange(weapons);
- }
- if (currentCategory == "All" || currentCategory == "Armor")
- {
- allItems.AddRange(armor);
- }
- if (currentCategory == "All" || currentCategory == "Miscellaneous")
- {
- allItems.AddRange(miscItems);
- }
- // Apply search filter
- if (!string.IsNullOrEmpty(currentSearchTerm))
- {
- var searchTerm = currentSearchTerm.ToLower();
- allItems = allItems.FindAll(item =>
- item.name.ToLower().Contains(searchTerm) ||
- item.description.ToLower().Contains(searchTerm) ||
- item.searchTags.ToLower().Contains(searchTerm)
- );
- }
- return allItems;
- }
- private VisualElement CreateItemElement(SimpleShopItem item)
- {
- var container = new VisualElement();
- container.style.flexDirection = FlexDirection.Row;
- container.style.justifyContent = Justify.SpaceBetween;
- container.style.alignItems = Align.Center;
- container.style.paddingLeft = 10;
- container.style.paddingRight = 10;
- container.style.paddingTop = 10;
- container.style.paddingBottom = 10;
- container.style.marginBottom = 5;
- container.style.backgroundColor = new Color(0.95f, 0.95f, 0.95f);
- container.style.borderTopLeftRadius = 5;
- container.style.borderTopRightRadius = 5;
- container.style.borderBottomLeftRadius = 5;
- container.style.borderBottomRightRadius = 5;
- // Item info section
- var infoSection = new VisualElement();
- infoSection.style.flexGrow = 1;
- var nameLabel = new Label(item.name);
- nameLabel.style.fontSize = 16;
- nameLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
- nameLabel.style.color = Color.black;
- infoSection.Add(nameLabel);
- var descriptionLabel = new Label(item.description);
- descriptionLabel.style.fontSize = 12;
- descriptionLabel.style.color = new Color(0.3f, 0.3f, 0.3f);
- infoSection.Add(descriptionLabel);
- container.Add(infoSection);
- // Price and buy section
- var buySection = new VisualElement();
- buySection.style.flexDirection = FlexDirection.Row;
- buySection.style.alignItems = Align.Center;
- var priceLabel = new Label(item.GetCostString());
- priceLabel.style.fontSize = 14;
- priceLabel.style.color = new Color(0, 0.5f, 0);
- priceLabel.style.marginRight = 10;
- buySection.Add(priceLabel);
- var buyButton = new Button(() => PurchaseItem(item));
- buyButton.text = "Buy";
- buyButton.style.width = 60;
- buyButton.style.height = 25;
- // Check if player can afford the item
- bool canAfford = item.CanAfford(currentCustomer);
- buyButton.SetEnabled(canAfford);
- if (!canAfford)
- {
- buyButton.style.backgroundColor = new Color(0.5f, 0.5f, 0.5f);
- buyButton.text = "Can't Afford";
- }
- else
- {
- buyButton.style.backgroundColor = new Color(0, 0.6f, 0);
- buyButton.style.color = Color.white;
- }
- buySection.Add(buyButton);
- container.Add(buySection);
- return container;
- }
- private void PurchaseItem(SimpleShopItem item)
- {
- if (currentCustomer == null || item == null)
- {
- Debug.LogError("Cannot purchase item: missing customer or item");
- return;
- }
- if (!item.CanAfford(currentCustomer))
- {
- Debug.LogWarning($"Cannot afford {item.name}");
- return;
- }
- Debug.Log($"Before purchase: {currentCustomer.name} has {currentCustomer.gold}g {currentCustomer.silver}s {currentCustomer.copper}c");
- // Complete the purchase
- item.Purchase(currentCustomer);
- Debug.Log($"After purchase: {currentCustomer.name} has {currentCustomer.gold}g {currentCustomer.silver}s {currentCustomer.copper}c");
- // Add item to customer's inventory
- if (weapons.Contains(item))
- {
- currentCustomer.weapons.Add(item.name);
- Debug.Log($"Added {item.name} to weapons list. Total weapons: {currentCustomer.weapons.Count}");
- }
- else if (armor.Contains(item))
- {
- currentCustomer.armor.Add(item.name);
- Debug.Log($"Added {item.name} to armor list. Total armor: {currentCustomer.armor.Count}");
- }
- else if (miscItems.Contains(item))
- {
- currentCustomer.miscItems.Add(item.name);
- Debug.Log($"Added {item.name} to misc items list. Total misc items: {currentCustomer.miscItems.Count}");
- }
- // Recalculate all equipment bonuses from inventory (temporary solution)
- currentCustomer.RecalculateEquipmentBonuses();
- if (item.stats != null && !string.IsNullOrEmpty(item.GetStatsString()))
- {
- Debug.Log($"Item {item.name} provides bonuses: {item.GetStatsString()}");
- }
- UpdatePlayerMoney();
- RefreshItemList(); // Refresh to update affordability
- // Notify that character data has changed
- Debug.Log("Triggering OnCharacterDataChanged callback...");
- OnCharacterDataChanged?.Invoke(currentCustomer);
- Debug.Log($"Purchased {item.name} for {currentCustomer.name}");
- }
- private void ApplyItemStats(TeamCharacter character, ItemStats stats)
- {
- if (character == null || stats == null) return;
- // Apply equipment modifiers (these affect final stats calculations)
- character.strengthModifier += stats.strengthBonus;
- character.dexterityModifier += stats.dexterityBonus;
- character.constitutionModifier += stats.constitutionBonus;
- character.wisdomModifier += stats.wisdomBonus;
- character.perceptionModifier += stats.perceptionBonus;
- character.acModifier += stats.acBonus; // Apply direct AC bonuses
- // Note: AC and HP are calculated properties using Final stats (base + modifiers),
- // so they will automatically update when the modifiers change.
- // Log what bonuses were applied
- if (stats.acBonus > 0)
- {
- Debug.Log($"Item provides +{stats.acBonus} AC bonus (applied to AC modifier)");
- }
- if (stats.damageBonus > 0)
- {
- Debug.Log($"Item provides +{stats.damageBonus} damage bonus (applied during combat)");
- }
- if (stats.healthBonus > 0)
- {
- Debug.Log($"Item provides +{stats.healthBonus} health bonus (applied through CON bonus)");
- }
- if (stats.movementBonus > 0)
- {
- Debug.Log($"Item provides +{stats.movementBonus} movement bonus");
- }
- if (stats.initiativeBonus != 0)
- {
- Debug.Log($"Item provides {stats.initiativeBonus:+0;-0;0} initiative bonus");
- }
- }
- private void UpdatePlayerMoney()
- {
- if (playerMoney != null && currentCustomer != null)
- {
- string moneyString = "";
- if (currentCustomer.gold > 0) moneyString += $"{currentCustomer.gold}g ";
- if (currentCustomer.silver > 0) moneyString += $"{currentCustomer.silver}s ";
- if (currentCustomer.copper > 0) moneyString += $"{currentCustomer.copper}c";
- playerMoney.text = moneyString.Trim();
- }
- }
- }
- [System.Serializable]
- public class SimpleShopItem
- {
- [Header("Basic Info")]
- public string name;
- public string description;
- public ShopItemType itemType;
- [Header("Price")]
- public int goldCost;
- public int silverCost;
- public int copperCost;
- [Header("Item Properties")]
- public ItemStats stats = new ItemStats();
- public string searchTags;
- public SimpleShopItem(string itemName, string itemDescription, ShopItemType type, int gold, int silver, int copper, string tags, ItemStats itemStats = null)
- {
- name = itemName;
- description = itemDescription;
- itemType = type;
- goldCost = gold;
- silverCost = silver;
- copperCost = copper;
- searchTags = tags;
- stats = itemStats ?? new ItemStats();
- }
- public bool CanAfford(TeamCharacter customer)
- {
- if (customer == null) return false;
- int totalCopperCost = goldCost * 100 + silverCost * 10 + copperCost;
- int totalCopperAvailable = customer.gold * 100 + customer.silver * 10 + customer.copper;
- return totalCopperAvailable >= totalCopperCost;
- }
- public void Purchase(TeamCharacter customer)
- {
- if (!CanAfford(customer))
- {
- Debug.LogWarning($"Cannot afford {name}");
- return;
- }
- // Convert everything to copper for easier calculation
- int totalCopperCost = goldCost * 100 + silverCost * 10 + copperCost;
- int totalCopperAvailable = customer.gold * 100 + customer.silver * 10 + customer.copper;
- int remainingCopper = totalCopperAvailable - totalCopperCost;
- // Convert back to gold, silver, copper
- customer.gold = remainingCopper / 100;
- remainingCopper %= 100;
- customer.silver = remainingCopper / 10;
- customer.copper = remainingCopper % 10;
- Debug.Log($"Purchased {name} for {goldCost}g {silverCost}s {copperCost}c");
- }
- public string GetCostString()
- {
- string cost = "";
- if (goldCost > 0) cost += $"{goldCost}g ";
- if (silverCost > 0) cost += $"{silverCost}s ";
- if (copperCost > 0) cost += $"{copperCost}c";
- return cost.Trim();
- }
- public string GetStatsString()
- {
- var statStrings = new List<string>();
- if (stats.damageBonus != 0) statStrings.Add($"Damage: +{stats.damageBonus}");
- if (stats.acBonus != 0) statStrings.Add($"AC: +{stats.acBonus}");
- if (stats.strengthBonus != 0) statStrings.Add($"STR: +{stats.strengthBonus}");
- if (stats.dexterityBonus != 0) statStrings.Add($"DEX: +{stats.dexterityBonus}");
- if (stats.constitutionBonus != 0) statStrings.Add($"CON: +{stats.constitutionBonus}");
- if (stats.wisdomBonus != 0) statStrings.Add($"WIS: +{stats.wisdomBonus}");
- if (stats.perceptionBonus != 0) statStrings.Add($"PER: +{stats.perceptionBonus}");
- if (stats.movementBonus != 0) statStrings.Add($"Move: +{stats.movementBonus}");
- if (stats.healthBonus != 0) statStrings.Add($"HP: +{stats.healthBonus}");
- return statStrings.Count > 0 ? string.Join(", ", statStrings) : "";
- }
- }
- [System.Serializable]
- public class ItemStats
- {
- [Header("Combat Stats")]
- public int damageBonus = 0;
- public int acBonus = 0;
- [Header("Attribute Bonuses")]
- public int strengthBonus = 0;
- public int dexterityBonus = 0;
- public int constitutionBonus = 0;
- public int wisdomBonus = 0;
- public int perceptionBonus = 0;
- [Header("Other Bonuses")]
- public int movementBonus = 0;
- public int healthBonus = 0;
- public int initiativeBonus = 0;
- }
- [System.Serializable]
- public enum ShopItemType
- {
- Weapon,
- Armor,
- Miscellaneous
- }
|