任务系统一半多,商城筛选功能,一些细节和免费包

This commit is contained in:
FloatGaming
2026-03-15 04:27:21 +08:00
parent 416190b23e
commit ec42f2e34b
344 changed files with 32225 additions and 6481 deletions
+333 -11
View File
@@ -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