任务系统一半多,商城筛选功能,一些细节和免费包
This commit is contained in:
@@ -7,9 +7,18 @@ using UnityEngine.UI;
|
||||
|
||||
public class storeSystem : MonoBehaviour
|
||||
{
|
||||
private const string ShowOnlyPurchasablePrefKey = "store.show_only_can_purchase";
|
||||
private const string SortDropdownPrefKey = "store.sort_dropdown_value";
|
||||
[Header("Player Data")]
|
||||
[SerializeField] private Player_SO playerData;
|
||||
|
||||
[Header("closeButton")]
|
||||
public Button closeButton;
|
||||
|
||||
[Header("filter")]
|
||||
public Toggle show_only_canPurchase;
|
||||
public Dropdown sortDropdown;
|
||||
|
||||
[Header("list toggles")]
|
||||
public ToggleGroup toggleGroup;
|
||||
public Toggle allItems_toggle;
|
||||
@@ -45,6 +54,7 @@ public class storeSystem : MonoBehaviour
|
||||
|
||||
private const int MinPurchaseAmount = 1;
|
||||
private const int MaxPurchaseAmount = 999999;
|
||||
private static readonly Color InsufficientCostColor = new Color(0.45f, 0.08f, 0.08f, 1f);
|
||||
|
||||
private readonly List<storeItemSO> cachedItems = new List<storeItemSO>();
|
||||
private readonly List<Toggle> toggles = new List<Toggle>();
|
||||
@@ -54,6 +64,7 @@ public class storeSystem : MonoBehaviour
|
||||
private int currentSelectedItemId = -1;
|
||||
private int currentPurchaseAmount = MinPurchaseAmount;
|
||||
private bool suppressAmountInputCallback;
|
||||
private Color defaultSumCostColor = Color.white;
|
||||
|
||||
private string SaveFilePath
|
||||
{
|
||||
@@ -62,14 +73,23 @@ public class storeSystem : MonoBehaviour
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (p_sumCostText != null)
|
||||
{
|
||||
defaultSumCostColor = p_sumCostText.color;
|
||||
}
|
||||
|
||||
CacheToggles();
|
||||
RegisterHeaderControlCallbacks();
|
||||
RegisterToggleCallbacks();
|
||||
RegisterPurchasePanelCallbacks();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
PlayerEconomyLedger.EnsureInstance().AttachPlayerData(playerData);
|
||||
ExpBottleLedger.EnsureInstance().AttachPlayerData(playerData);
|
||||
ResetPriceImageObjects();
|
||||
LoadFilterPreferences();
|
||||
SetDefaultToggleState();
|
||||
LoadPersistedState();
|
||||
LoadAllStoreItems();
|
||||
@@ -79,6 +99,7 @@ public class storeSystem : MonoBehaviour
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
UnregisterHeaderControlCallbacks();
|
||||
UnregisterToggleCallbacks();
|
||||
UnregisterPurchasePanelCallbacks();
|
||||
}
|
||||
@@ -111,6 +132,42 @@ public class storeSystem : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
private void RegisterHeaderControlCallbacks()
|
||||
{
|
||||
if (closeButton != null)
|
||||
{
|
||||
closeButton.onClick.AddListener(OnCloseButtonClicked);
|
||||
}
|
||||
|
||||
if (show_only_canPurchase != null)
|
||||
{
|
||||
show_only_canPurchase.onValueChanged.AddListener(OnShowOnlyCanPurchaseChanged);
|
||||
}
|
||||
|
||||
if (sortDropdown != null)
|
||||
{
|
||||
sortDropdown.onValueChanged.AddListener(OnSortDropdownValueChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private void UnregisterHeaderControlCallbacks()
|
||||
{
|
||||
if (closeButton != null)
|
||||
{
|
||||
closeButton.onClick.RemoveListener(OnCloseButtonClicked);
|
||||
}
|
||||
|
||||
if (show_only_canPurchase != null)
|
||||
{
|
||||
show_only_canPurchase.onValueChanged.RemoveListener(OnShowOnlyCanPurchaseChanged);
|
||||
}
|
||||
|
||||
if (sortDropdown != null)
|
||||
{
|
||||
sortDropdown.onValueChanged.RemoveListener(OnSortDropdownValueChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private void UnregisterToggleCallbacks()
|
||||
{
|
||||
for (int i = 0; i < toggles.Count; i++)
|
||||
@@ -122,6 +179,21 @@ public class storeSystem : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadFilterPreferences()
|
||||
{
|
||||
if (show_only_canPurchase != null)
|
||||
{
|
||||
show_only_canPurchase.SetIsOnWithoutNotify(PlayerPrefs.GetInt(ShowOnlyPurchasablePrefKey, 0) == 1);
|
||||
}
|
||||
|
||||
if (sortDropdown != null)
|
||||
{
|
||||
int savedValue = PlayerPrefs.GetInt(SortDropdownPrefKey, 0);
|
||||
int safeValue = Mathf.Clamp(savedValue, 0, Mathf.Max(0, sortDropdown.options.Count - 1));
|
||||
sortDropdown.SetValueWithoutNotify(safeValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void RegisterPurchasePanelCallbacks()
|
||||
{
|
||||
if (p_iAmount_plus != null)
|
||||
@@ -136,7 +208,12 @@ public class storeSystem : MonoBehaviour
|
||||
|
||||
if (p_iAmount_input != null)
|
||||
{
|
||||
p_iAmount_input.onEndEdit.AddListener(OnPurchaseAmountInputEndEdit);
|
||||
p_iAmount_input.onValueChanged.AddListener(OnPurchaseAmountInputValueChanged);
|
||||
}
|
||||
|
||||
if (purchaseButton != null)
|
||||
{
|
||||
purchaseButton.onClick.AddListener(OnPurchaseButtonClicked);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +231,12 @@ public class storeSystem : MonoBehaviour
|
||||
|
||||
if (p_iAmount_input != null)
|
||||
{
|
||||
p_iAmount_input.onEndEdit.RemoveListener(OnPurchaseAmountInputEndEdit);
|
||||
p_iAmount_input.onValueChanged.RemoveListener(OnPurchaseAmountInputValueChanged);
|
||||
}
|
||||
|
||||
if (purchaseButton != null)
|
||||
{
|
||||
purchaseButton.onClick.RemoveListener(OnPurchaseButtonClicked);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,6 +248,32 @@ public class storeSystem : MonoBehaviour
|
||||
RefreshCurrentView();
|
||||
}
|
||||
|
||||
private void OnShowOnlyCanPurchaseChanged(bool isOn)
|
||||
{
|
||||
PlayerPrefs.SetInt(ShowOnlyPurchasablePrefKey, isOn ? 1 : 0);
|
||||
PlayerPrefs.Save();
|
||||
currentSelectedItem = null;
|
||||
currentSelectedItemId = -1;
|
||||
currentPurchaseAmount = MinPurchaseAmount;
|
||||
RefreshCurrentView();
|
||||
}
|
||||
|
||||
private void OnSortDropdownValueChanged(int _)
|
||||
{
|
||||
if (sortDropdown != null)
|
||||
{
|
||||
PlayerPrefs.SetInt(SortDropdownPrefKey, sortDropdown.value);
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
|
||||
RefreshCurrentView();
|
||||
}
|
||||
|
||||
private void OnCloseButtonClicked()
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
private void SetDefaultToggleState()
|
||||
{
|
||||
if (allItems_toggle == null)
|
||||
@@ -306,7 +414,13 @@ public class storeSystem : MonoBehaviour
|
||||
}
|
||||
|
||||
visibleItems.Add(itemSO);
|
||||
SpawnItem(itemSO);
|
||||
}
|
||||
|
||||
SortVisibleItems(visibleItems);
|
||||
|
||||
for (int i = 0; i < visibleItems.Count; i++)
|
||||
{
|
||||
SpawnItem(visibleItems[i]);
|
||||
}
|
||||
|
||||
ResolveVisibleSelection(visibleItems);
|
||||
@@ -324,6 +438,11 @@ public class storeSystem : MonoBehaviour
|
||||
return false;
|
||||
}
|
||||
|
||||
if (show_only_canPurchase != null && show_only_canPurchase.isOn && !IsCurrentlyPurchasable(itemSO))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (recentlyHot_toggle != null && recentlyHot_toggle.isOn)
|
||||
{
|
||||
return itemSO.isHot;
|
||||
@@ -357,6 +476,153 @@ public class storeSystem : MonoBehaviour
|
||||
return allItems_toggle == null || allItems_toggle.isOn;
|
||||
}
|
||||
|
||||
private void SortVisibleItems(List<storeItemSO> visibleItems)
|
||||
{
|
||||
if (visibleItems == null || visibleItems.Count <= 1 || sortDropdown == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (sortDropdown.value == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
visibleItems.Sort(CompareStoreItems);
|
||||
}
|
||||
|
||||
private int CompareStoreItems(storeItemSO left, storeItemSO right)
|
||||
{
|
||||
if (left == right)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (left == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (right == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int result;
|
||||
switch (sortDropdown != null ? sortDropdown.value : 0)
|
||||
{
|
||||
case 1:
|
||||
result = ComparePriceAscending(left, right);
|
||||
break;
|
||||
case 2:
|
||||
result = ComparePriceDescending(left, right);
|
||||
break;
|
||||
case 3:
|
||||
result = CompareAscending((int)left.itemType, (int)right.itemType);
|
||||
break;
|
||||
case 4:
|
||||
result = CompareDescending((int)left.itemType, (int)right.itemType);
|
||||
break;
|
||||
case 5:
|
||||
result = CompareQuotaAscending(left, right);
|
||||
break;
|
||||
case 6:
|
||||
result = CompareQuotaDescending(left, right);
|
||||
break;
|
||||
default:
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return CompareAscending(left.itemID, right.itemID);
|
||||
}
|
||||
|
||||
private static int CompareAscending(int left, int right)
|
||||
{
|
||||
return left.CompareTo(right);
|
||||
}
|
||||
|
||||
private static int CompareDescending(int left, int right)
|
||||
{
|
||||
return right.CompareTo(left);
|
||||
}
|
||||
|
||||
private static int CompareQuotaAscending(storeItemSO left, storeItemSO right)
|
||||
{
|
||||
bool leftUnlimited = left.itemPurchaseQuota < 0;
|
||||
bool rightUnlimited = right.itemPurchaseQuota < 0;
|
||||
if (leftUnlimited != rightUnlimited)
|
||||
{
|
||||
return leftUnlimited ? 1 : -1;
|
||||
}
|
||||
|
||||
return CompareAscending(left.itemPurchaseQuota, right.itemPurchaseQuota);
|
||||
}
|
||||
|
||||
private static int CompareQuotaDescending(storeItemSO left, storeItemSO right)
|
||||
{
|
||||
bool leftUnlimited = left.itemPurchaseQuota < 0;
|
||||
bool rightUnlimited = right.itemPurchaseQuota < 0;
|
||||
if (leftUnlimited != rightUnlimited)
|
||||
{
|
||||
return leftUnlimited ? -1 : 1;
|
||||
}
|
||||
|
||||
return CompareDescending(left.itemPurchaseQuota, right.itemPurchaseQuota);
|
||||
}
|
||||
|
||||
private static int ComparePriceAscending(storeItemSO left, storeItemSO right)
|
||||
{
|
||||
bool leftHasCost = HasSortableCost(left);
|
||||
bool rightHasCost = HasSortableCost(right);
|
||||
if (leftHasCost != rightHasCost)
|
||||
{
|
||||
return leftHasCost ? -1 : 1;
|
||||
}
|
||||
|
||||
return CompareAscending(GetPrimaryCostAmount(left), GetPrimaryCostAmount(right));
|
||||
}
|
||||
|
||||
private static int ComparePriceDescending(storeItemSO left, storeItemSO right)
|
||||
{
|
||||
bool leftHasCost = HasSortableCost(left);
|
||||
bool rightHasCost = HasSortableCost(right);
|
||||
if (leftHasCost != rightHasCost)
|
||||
{
|
||||
return leftHasCost ? -1 : 1;
|
||||
}
|
||||
|
||||
return CompareDescending(GetPrimaryCostAmount(left), GetPrimaryCostAmount(right));
|
||||
}
|
||||
|
||||
private static bool HasSortableCost(storeItemSO itemSO)
|
||||
{
|
||||
return itemSO != null && itemSO.costRequirements != null && itemSO.costRequirements.Count > 0;
|
||||
}
|
||||
|
||||
private static int GetPrimaryCostAmount(storeItemSO itemSO)
|
||||
{
|
||||
if (!HasSortableCost(itemSO))
|
||||
{
|
||||
return int.MaxValue;
|
||||
}
|
||||
|
||||
return itemSO.costRequirements[0].amount;
|
||||
}
|
||||
|
||||
private bool IsCurrentlyPurchasable(storeItemSO itemSO)
|
||||
{
|
||||
return itemSO != null
|
||||
&& itemSO.canbepurchased
|
||||
&& !IsSoldOut(itemSO)
|
||||
&& HasCoinRequirement(itemSO);
|
||||
}
|
||||
|
||||
private void SpawnItem(storeItemSO itemSO)
|
||||
{
|
||||
var instance = Instantiate(itemPrefab, contentParent);
|
||||
@@ -496,6 +762,7 @@ public class storeSystem : MonoBehaviour
|
||||
if (p_sumCostText != null)
|
||||
{
|
||||
p_sumCostText.text = string.Empty;
|
||||
p_sumCostText.color = defaultSumCostColor;
|
||||
}
|
||||
|
||||
SetPriceImageState(p_sumCostImage, null, false);
|
||||
@@ -515,13 +782,20 @@ public class storeSystem : MonoBehaviour
|
||||
SetPurchaseAmount(currentPurchaseAmount - 1, true);
|
||||
}
|
||||
|
||||
private void OnPurchaseAmountInputEndEdit(string value)
|
||||
private void OnPurchaseAmountInputValueChanged(string value)
|
||||
{
|
||||
if (suppressAmountInputCallback)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
currentPurchaseAmount = MinPurchaseAmount;
|
||||
RefreshPurchaseSummary();
|
||||
return;
|
||||
}
|
||||
|
||||
long parsedValue;
|
||||
if (!long.TryParse((value ?? string.Empty).Trim(), out parsedValue))
|
||||
{
|
||||
@@ -542,7 +816,23 @@ public class storeSystem : MonoBehaviour
|
||||
safeValue = (int)parsedValue;
|
||||
}
|
||||
|
||||
SetPurchaseAmount(safeValue, true);
|
||||
bool reachedUpperLimit = safeValue > MaxPurchaseAmount;
|
||||
bool reachedLowerLimit = safeValue < MinPurchaseAmount;
|
||||
int clampedValue = Mathf.Clamp(safeValue, MinPurchaseAmount, MaxPurchaseAmount);
|
||||
|
||||
currentPurchaseAmount = clampedValue;
|
||||
RefreshPurchaseSummary();
|
||||
|
||||
if (reachedUpperLimit)
|
||||
{
|
||||
gNotice.warning.display("达到单次购买限额");
|
||||
UpdatePurchaseAmountInput();
|
||||
}
|
||||
else if (reachedLowerLimit)
|
||||
{
|
||||
gNotice.warning.display("本店禁止无实物交易");
|
||||
UpdatePurchaseAmountInput();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetPurchaseAmount(int amount, bool showWarnings)
|
||||
@@ -592,6 +882,7 @@ public class storeSystem : MonoBehaviour
|
||||
if (p_sumCostText != null)
|
||||
{
|
||||
p_sumCostText.text = string.Empty;
|
||||
p_sumCostText.color = defaultSumCostColor;
|
||||
}
|
||||
|
||||
SetPriceImageState(p_sumCostImage, null, false);
|
||||
@@ -604,6 +895,7 @@ public class storeSystem : MonoBehaviour
|
||||
if (p_sumCostText != null)
|
||||
{
|
||||
p_sumCostText.text = "不可购买";
|
||||
p_sumCostText.color = defaultSumCostColor;
|
||||
}
|
||||
|
||||
SetCannotBuyImageState(p_sumCostImage);
|
||||
@@ -617,6 +909,7 @@ public class storeSystem : MonoBehaviour
|
||||
if (p_sumCostText != null)
|
||||
{
|
||||
p_sumCostText.text = totalCost.ToString();
|
||||
p_sumCostText.color = CanAffordCurrentSelection(totalCost) ? defaultSumCostColor : InsufficientCostColor;
|
||||
}
|
||||
|
||||
SetPriceImageState(p_sumCostImage, GetCurrencySprite(cost.currencyType), true);
|
||||
@@ -705,6 +998,30 @@ public class storeSystem : MonoBehaviour
|
||||
purchaseButton.interactable = CanPurchaseCurrentSelection(currentSelectedItem);
|
||||
}
|
||||
|
||||
private void OnPurchaseButtonClicked()
|
||||
{
|
||||
if (currentSelectedItem == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string failureMessage;
|
||||
int grantedCount;
|
||||
if (!StoreExpBottlePurchaseService.TryPurchase(playerData, currentSelectedItem, currentPurchaseAmount, out failureMessage, out grantedCount))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(failureMessage))
|
||||
{
|
||||
gNotice.warning.display(failureMessage);
|
||||
}
|
||||
|
||||
RefreshPurchaseSummary();
|
||||
return;
|
||||
}
|
||||
|
||||
RegisterPurchasedCount(currentSelectedItem.itemID, grantedCount);
|
||||
RefreshPurchaseSummary();
|
||||
}
|
||||
|
||||
private string GetAmountAndQuotaText(storeItemSO itemSO)
|
||||
{
|
||||
string prefix = itemSO.itemSinglePurchaseQty == 1 ? string.Empty : $"{itemSO.itemSinglePurchaseQty}个装/";
|
||||
@@ -758,10 +1075,17 @@ public class storeSystem : MonoBehaviour
|
||||
|
||||
private bool CanPurchaseCurrentSelection(storeItemSO itemSO)
|
||||
{
|
||||
return itemSO != null
|
||||
&& itemSO.canbepurchased
|
||||
&& !IsSoldOut(itemSO)
|
||||
&& HasCoinRequirement(itemSO);
|
||||
return IsCurrentlyPurchasable(itemSO);
|
||||
}
|
||||
|
||||
private bool CanAffordCurrentSelection(long totalCost)
|
||||
{
|
||||
if (totalCost <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return PlayerEconomyLedger.EnsureInstance().HasEnoughCoins(totalCost);
|
||||
}
|
||||
|
||||
private void SetupAvailabilityState(storeItemPrefab itemView, storeItemSO itemSO)
|
||||
@@ -1002,8 +1326,6 @@ public class storeSystem : MonoBehaviour
|
||||
{
|
||||
UnityEditor.EditorUtility.SetDirty(cachedItems[i]);
|
||||
}
|
||||
|
||||
UnityEditor.AssetDatabase.SaveAssets();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user