| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- using UnityEngine;
- using System.Collections.Generic;
- using System.Linq;
- public enum ShopType
- {
- Weapons,
- Armor,
- Potions,
- General,
- Magic,
- Tools
- }
- [System.Serializable]
- public class TownShop : TownBuilding
- {
- [Header("Shop Configuration")]
- public ShopType shopType = ShopType.General;
- public string shopkeeperName = "Merchant";
- public float profitMargin = 1.2f; // 20% markup on base item prices
- public float sellbackRate = 0.6f; // Player gets 60% of base price when selling
- [Header("Shop Inventory")]
- public List<Item> baseInventory = new List<Item>();
- public int maxInventorySize = 20;
- public bool restockDaily = true;
- [Header("Shop Filters")]
- public List<ItemType> acceptedItemTypes = new List<ItemType>();
- public List<ItemRarity> acceptedRarities = new List<ItemRarity>();
- public List<ShopInventoryItem> currentInventory = new List<ShopInventoryItem>();
- private System.DateTime lastRestockTime;
- protected override void Start()
- {
- base.Start();
- buildingType = BuildingType.Shop;
- InitializeShop();
- }
- private void InitializeShop()
- {
- // Set default accepted item types based on shop type
- if (acceptedItemTypes.Count == 0)
- {
- switch (shopType)
- {
- case ShopType.Weapons:
- acceptedItemTypes.Add(ItemType.Weapon);
- break;
- case ShopType.Armor:
- acceptedItemTypes.Add(ItemType.Armor);
- acceptedItemTypes.Add(ItemType.Accessory);
- break;
- case ShopType.Potions:
- acceptedItemTypes.Add(ItemType.Consumable);
- break;
- case ShopType.General:
- acceptedItemTypes.AddRange(System.Enum.GetValues(typeof(ItemType)).Cast<ItemType>());
- break;
- case ShopType.Tools:
- acceptedItemTypes.Add(ItemType.Tool);
- acceptedItemTypes.Add(ItemType.Miscellaneous);
- break;
- }
- }
- // Initialize inventory
- RestockInventory();
- // Set building colors based on shop type
- switch (shopType)
- {
- case ShopType.Weapons:
- buildingColor = new Color(0.8f, 0.2f, 0.2f); // Red
- break;
- case ShopType.Armor:
- buildingColor = new Color(0.2f, 0.2f, 0.8f); // Blue
- break;
- case ShopType.Potions:
- buildingColor = new Color(0.2f, 0.8f, 0.2f); // Green
- break;
- case ShopType.General:
- buildingColor = new Color(0.6f, 0.4f, 0.2f); // Brown
- break;
- default:
- buildingColor = Color.gray;
- break;
- }
- }
- public void RestockInventory()
- {
- currentInventory.Clear();
- // Add base inventory items with markup
- foreach (var item in baseInventory)
- {
- if (item != null)
- {
- var shopItem = new ShopInventoryItem(item, profitMargin);
- currentInventory.Add(shopItem);
- }
- }
- // Add some random items based on shop type
- AddRandomItems();
- lastRestockTime = System.DateTime.Now;
- Debug.Log($"{buildingName} restocked with {currentInventory.Count} items");
- }
- private void AddRandomItems()
- {
- // Get all items of appropriate types from Resources
- var allItems = Resources.LoadAll<Item>("Items");
- var filteredItems = allItems.Where(item =>
- acceptedItemTypes.Contains(item.itemType) &&
- (acceptedRarities.Count == 0 || acceptedRarities.Contains(item.rarity))
- ).ToList();
- // Add 3-5 random items
- int randomItemCount = Random.Range(3, 6);
- for (int i = 0; i < randomItemCount && currentInventory.Count < maxInventorySize; i++)
- {
- if (filteredItems.Count > 0)
- {
- var randomItem = filteredItems[Random.Range(0, filteredItems.Count)];
- var shopItem = new ShopInventoryItem(randomItem, profitMargin);
- currentInventory.Add(shopItem);
- }
- }
- }
- public List<ShopInventoryItem> GetInventory()
- {
- // Check if restock is needed
- if (restockDaily && (System.DateTime.Now - lastRestockTime).TotalDays >= 1)
- {
- RestockInventory();
- }
- return new List<ShopInventoryItem>(currentInventory);
- }
- public bool CanBuyItem(Item item)
- {
- return acceptedItemTypes.Contains(item.itemType) &&
- (acceptedRarities.Count == 0 || acceptedRarities.Contains(item.rarity));
- }
- public int GetSellPrice(Item item)
- {
- if (!CanBuyItem(item)) return 0;
- int basePrice = item.goldCost * 100 + item.silverCost * 10 + item.copperCost;
- return Mathf.RoundToInt(basePrice * sellbackRate);
- }
- public void SellItemToShop(Item item, TeamCharacter seller)
- {
- if (!CanBuyItem(item)) return;
- int sellPrice = GetSellPrice(item);
- // Convert copper to gold/silver/copper
- int gold = sellPrice / 100;
- sellPrice %= 100;
- int silver = sellPrice / 10;
- int copper = sellPrice % 10;
- // Add money to seller
- seller.gold += gold;
- seller.silver += silver;
- seller.copper += copper;
- // Normalize currency (convert excess copper/silver)
- if (seller.copper >= 10)
- {
- seller.silver += seller.copper / 10;
- seller.copper %= 10;
- }
- if (seller.silver >= 10)
- {
- seller.gold += seller.silver / 10;
- seller.silver %= 10;
- }
- Debug.Log($"Sold {item.itemName} to {buildingName} for {gold}g {silver}s {copper}c");
- }
- /// <summary>
- /// Update shop names after initialization (called by TownShopManager)
- /// </summary>
- public void UpdateNames(string newBuildingName, string newShopkeeperName)
- {
- this.buildingName = newBuildingName;
- this.shopkeeperName = newShopkeeperName;
- Debug.Log($"TownShop: Updated names to '{this.buildingName}' run by '{this.shopkeeperName}'");
- }
- }
- [System.Serializable]
- public class ShopInventoryItem
- {
- public Item item;
- public int markupGold;
- public int markupSilver;
- public int markupCopper;
- public int quantity;
- public bool isUnlimited;
- public ShopInventoryItem(Item baseItem, float profitMargin, int qty = 1, bool unlimited = false)
- {
- item = baseItem;
- quantity = qty;
- isUnlimited = unlimited;
- // Calculate markup prices
- int baseCopperPrice = baseItem.goldCost * 100 + baseItem.silverCost * 10 + baseItem.copperCost;
- int markupCopperPrice = Mathf.RoundToInt(baseCopperPrice * profitMargin);
- markupGold = markupCopperPrice / 100;
- markupCopperPrice %= 100;
- markupSilver = markupCopperPrice / 10;
- markupCopper = markupCopperPrice % 10;
- }
- public bool CanAfford(TeamCharacter customer)
- {
- if (customer == null || quantity <= 0) return false;
- int totalCopperCost = markupGold * 100 + markupSilver * 10 + markupCopper;
- int totalCopperAvailable = customer.gold * 100 + customer.silver * 10 + customer.copper;
- return totalCopperAvailable >= totalCopperCost;
- }
- public void Purchase(TeamCharacter customer)
- {
- if (!CanAfford(customer) || quantity <= 0) return;
- // Deduct money
- int totalCopperCost = markupGold * 100 + markupSilver * 10 + markupCopper;
- int totalCopperAvailable = customer.gold * 100 + customer.silver * 10 + customer.copper;
- int remainingCopper = totalCopperAvailable - totalCopperCost;
- customer.gold = remainingCopper / 100;
- remainingCopper %= 100;
- customer.silver = remainingCopper / 10;
- customer.copper = remainingCopper % 10;
- // Add item to customer inventory
- // This will be handled by the shop UI
- // Reduce quantity
- if (!isUnlimited)
- quantity--;
- Debug.Log($"Purchased {item.itemName} for {markupGold}g {markupSilver}s {markupCopper}c");
- }
- public string GetPriceString()
- {
- string price = "";
- if (markupGold > 0) price += $"{markupGold}g ";
- if (markupSilver > 0) price += $"{markupSilver}s ";
- if (markupCopper > 0) price += $"{markupCopper}c";
- return price.Trim();
- }
- }
|