You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Driftology/Assets/Scripts/ShopManager.cs

314 lines
8.6 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Purchasing;
using TMPro;
using UnityEngine.UI;
using DG.Tweening;
using UnityEngine.Purchasing.Extension;
using static UnityEditor.Progress;
[Serializable]
public class ConsumableItem
{
public string Name;
public string Id;
public string desc;
public float price;
}
[Serializable]
public class CarItem
{
public int carId;
public int price;
public CarData carData;
public Button carButton; // CarTile main selection
public Image backgroundImage;
public GameObject lockIcon;
public Button priceButton; // Button shown on locked cars
public TextMeshProUGUI priceText; // Text inside price button
}
public class ShopManager : MonoBehaviour, IDetailedStoreListener
{
IStoreController m_StoreController;
[Header("Consumables")]
public List<ConsumableItem> cItem;
public List<int> CashRewards;
public GameObject LoadingScreen;
public TextMeshProUGUI CashTxt;
[Header("Car Store")]
public List<CarItem> carItems;
public Sprite selectedSprite;
public Sprite unselectedSprite;
[Header("Car Info UI")]
public TextMeshProUGUI carNameText;
public List<Button> colorButtons;
public Image[] colorIndicators;
public TextMeshProUGUI nitroText;
public TextMeshProUGUI powerText;
public TextMeshProUGUI handlingText;
public TextMeshProUGUI tractionText;
[Header("Car Stat Bars")]
public Image nitroBar;
public Image powerBar;
public Image handlingBar;
public Image tractionBar;
void Start()
{
CashTxt.text = GameConstants.Cash.ToString();
SetupBuilder();
InitializeCarStore();
}
#region Unity IAP Setup
void SetupBuilder()
{
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
for (int i = 0; i < cItem.Count; i++)
{
builder.AddProduct(cItem[i].Id, ProductType.Consumable);
}
UnityPurchasing.Initialize(this, builder);
}
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
m_StoreController = controller;
Debug.Log("Unity IAP Initialized");
}
public void OnInitializeFailed(InitializationFailureReason error)
{
LoadingScreen.SetActive(false);
Debug.LogError("IAP Initialization Failed: " + error);
}
public void OnInitializeFailed(InitializationFailureReason error, string message)
{
LoadingScreen.SetActive(false);
Debug.LogError("IAP Initialization Failed: " + error + ", Message: " + message);
}
#endregion
#region Purchase Flow
public void BuyCashItem(int index)
{
if (index < cItem.Count)
{
LoadingScreen.SetActive(true);
m_StoreController.InitiatePurchase(cItem[index].Id);
}
}
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{
LoadingScreen.SetActive(false);
var productId = args.purchasedProduct.definition.id;
for (int i = 0; i < cItem.Count; i++)
{
if (productId == cItem[i].Id)
{
AddCash(i);
Debug.Log("Cash Item Purchased: " + cItem[i].Name);
break;
}
}
return PurchaseProcessingResult.Complete;
}
public void OnPurchaseFailed(Product product, PurchaseFailureReason reason)
{
LoadingScreen.SetActive(false);
Debug.LogWarning("Purchase Failed: " + product.definition.id + ", Reason: " + reason);
}
public void OnPurchaseFailed(Product product, PurchaseFailureDescription description)
{
LoadingScreen.SetActive(false);
Debug.LogWarning("Purchase Failed: " + description.message);
}
#endregion
#region Cash Logic
void AddCash(int index)
{
int amount = CashRewards[index];
int currentCash = GameConstants.Cash;
int newCash = currentCash + amount;
GameConstants.Cash = newCash;
StartCoroutine(AnimateCashChange(currentCash, newCash, 0.5f));
}
void SubtractCash(int amount)
{
int cash = GameConstants.Cash;
int newCash = cash - amount;
GameConstants.Cash = newCash;
StartCoroutine(AnimateCashChange(cash, newCash, 0.5f));
}
float val;
IEnumerator AnimateCashChange(int oldValue, int newValue, float duration)
{
float elapsed = 0f;
CashTxt.transform.DOShakePosition(0.5f);
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float t = elapsed / duration;
val = Mathf.Lerp(oldValue, newValue, t);
CashTxt.text = ((int)(val)).ToString();
yield return null;
}
CashTxt.text = newValue.ToString();
}
#endregion
#region Car Store Logic
void InitializeCarStore()
{
int selectedIndex = GameConstants.CarSelected;
for (int i = 0; i < carItems.Count; i++)
{
int index = i;
CarItem item = carItems[i];
bool isUnlocked = GameConstants.IsCarUnlocked(index);
bool isSelected = (index == selectedIndex);
// Main car tile button (selects car if unlocked)
item.carButton.onClick.RemoveAllListeners();
item.carButton.onClick.AddListener(() => OnCarClicked(index));
// Price button (shown only if car is locked)
item.priceButton.gameObject.SetActive(!isUnlocked);
item.priceButton.onClick.RemoveAllListeners();
item.priceButton.onClick.AddListener(() => TryBuyCar(index));
item.priceText.text = "<sprite name=\"cash\"> $" + item.price.ToString();
// Lock icon
item.lockIcon.SetActive(!isUnlocked);
// Background sprite
item.backgroundImage.sprite = isSelected ? selectedSprite : unselectedSprite;
}
UpdateCarInfo(selectedIndex);
}
void OnCarClicked(int index)
{
bool isUnlocked = GameConstants.IsCarUnlocked(index);
int selected = GameConstants.CarSelected;
// Ignore if already selected
if (index == selected)
return;
// Only allow selecting unlocked cars
if (isUnlocked)
{
SelectCar(index);
}
else
{
Debug.Log("Car is locked. Click the price button to buy.");
}
}
void SelectCar(int index)
{
for (int i = 0; i < carItems.Count; i++)
{
bool isUnlocked = GameConstants.IsCarUnlocked(i);
bool isSelected = (i == index);
carItems[i].lockIcon.SetActive(!isUnlocked);
carItems[i].backgroundImage.sprite = isSelected ? selectedSprite : unselectedSprite;
}
GameConstants.CarSelected = index;
UpdateCarInfo(index);
}
void UpdateCarInfo(int index)
{
CarData data = carItems[index].carData;
if (data == null)
{
Debug.LogWarning("Missing CarData for car index: " + index);
return;
}
carNameText.text = data.carName;
nitroText.text = data.nitro.ToString("0.00");
powerText.text = data.power.ToString();
handlingText.text = data.handling.ToString();
tractionText.text = data.traction.ToString("0.00");
// Update fill amounts using normalized values
nitroBar.fillAmount = Mathf.InverseLerp(0.1f, 2f, data.nitro);
powerBar.fillAmount = Mathf.InverseLerp(500f, 2000f, data.power);
handlingBar.fillAmount = Mathf.InverseLerp(3f, 10f, data.handling);
tractionBar.fillAmount = Mathf.InverseLerp(3f, 10f, data.traction);
HighlightSelectedColor(GameConstants.CarColorIndex);
}
void TryBuyCar(int index)
{
int cash = GameConstants.Cash;
int price = carItems[index].price;
if (cash >= price)
{
SubtractCash(price);
GameConstants.UnlockCar(index);
SelectCar(index);
InitializeCarStore(); // Refresh visuals
}
else
{
Debug.Log("Not enough cash to buy car.");
}
}
public void OnColorSelected(int colorIndex)
{
GameConstants.CarColorIndex = colorIndex;
HighlightSelectedColor(colorIndex);
Debug.Log("Color selected: " + colorIndex);
}
void HighlightSelectedColor(int colorIndex)
{
for (int i = 0; i < colorIndicators.Length; i++)
{
colorIndicators[i].enabled = (i == colorIndex);
}
}
#endregion
}