装备系统完结,修复并加入很多
This commit is contained in:
@@ -41,6 +41,7 @@ public class storeSystem : MonoBehaviour
|
||||
|
||||
[Header("sprites")]
|
||||
public Sprite coinSprite;
|
||||
public Sprite materialSprite;
|
||||
public Sprite cannotBuySprite;
|
||||
|
||||
[Header("selecting item purchase")]
|
||||
@@ -54,6 +55,10 @@ public class storeSystem : MonoBehaviour
|
||||
public Button purchaseButton;
|
||||
public Text p_detailedDescriptionText;
|
||||
|
||||
[Header("selectable equipment reward")]
|
||||
public GameObject ctasPrefab;
|
||||
public Transform ctasParent;
|
||||
|
||||
private const int MinPurchaseAmount = 1;
|
||||
private const int MaxPurchaseAmount = 999999;
|
||||
private static readonly Color InsufficientCostColor = new Color(0.45f, 0.08f, 0.08f, 1f);
|
||||
@@ -67,6 +72,7 @@ public class storeSystem : MonoBehaviour
|
||||
private int currentPurchaseAmount = MinPurchaseAmount;
|
||||
private bool suppressAmountInputCallback;
|
||||
private Color defaultSumCostColor = Color.white;
|
||||
private GameObject activeCtasInstance;
|
||||
|
||||
private string LegacySaveFilePath
|
||||
{
|
||||
@@ -102,6 +108,7 @@ public class storeSystem : MonoBehaviour
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
CloseActiveCtas();
|
||||
UnregisterHeaderControlCallbacks();
|
||||
UnregisterToggleCallbacks();
|
||||
UnregisterPurchasePanelCallbacks();
|
||||
@@ -274,6 +281,7 @@ public class storeSystem : MonoBehaviour
|
||||
|
||||
private void OnCloseButtonClicked()
|
||||
{
|
||||
CloseActiveCtas();
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
@@ -624,7 +632,7 @@ public class storeSystem : MonoBehaviour
|
||||
&& itemSO.canbepurchased
|
||||
&& !IsAssociatedContentUnlocked(itemSO)
|
||||
&& !IsSoldOut(itemSO)
|
||||
&& HasCoinRequirement(itemSO);
|
||||
&& HasSupportedRequirement(itemSO);
|
||||
}
|
||||
|
||||
private void SpawnItem(storeItemSO itemSO)
|
||||
@@ -732,7 +740,7 @@ public class storeSystem : MonoBehaviour
|
||||
: itemSO.itemDetailedDescription;
|
||||
}
|
||||
|
||||
if (resetAmount)
|
||||
if (resetAmount || IsSelectableEquipmentRewardItem(itemSO))
|
||||
{
|
||||
SetPurchaseAmount(MinPurchaseAmount, false);
|
||||
}
|
||||
@@ -742,6 +750,7 @@ public class storeSystem : MonoBehaviour
|
||||
RefreshPurchaseSummary();
|
||||
}
|
||||
|
||||
UpdatePurchaseAmountControlsState(itemSO);
|
||||
RefreshPurchaseButtonState();
|
||||
}
|
||||
|
||||
@@ -773,6 +782,7 @@ public class storeSystem : MonoBehaviour
|
||||
|
||||
currentPurchaseAmount = MinPurchaseAmount;
|
||||
UpdatePurchaseAmountInput();
|
||||
UpdatePurchaseAmountControlsState(null);
|
||||
RefreshPurchaseButtonState();
|
||||
}
|
||||
|
||||
@@ -839,6 +849,26 @@ public class storeSystem : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePurchaseAmountControlsState(storeItemSO itemSO)
|
||||
{
|
||||
bool forceSinglePurchase = IsSelectableEquipmentRewardItem(itemSO);
|
||||
|
||||
if (p_iAmount_plus != null)
|
||||
{
|
||||
p_iAmount_plus.interactable = !forceSinglePurchase;
|
||||
}
|
||||
|
||||
if (p_iAmount_minus != null)
|
||||
{
|
||||
p_iAmount_minus.interactable = !forceSinglePurchase;
|
||||
}
|
||||
|
||||
if (p_iAmount_input != null)
|
||||
{
|
||||
p_iAmount_input.interactable = !forceSinglePurchase;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetPurchaseAmount(int amount, bool showWarnings)
|
||||
{
|
||||
int clampedAmount = amount;
|
||||
@@ -927,10 +957,15 @@ public class storeSystem : MonoBehaviour
|
||||
return coinSprite;
|
||||
}
|
||||
|
||||
if (currencyType == storeItemSO.CurrencyType.material)
|
||||
{
|
||||
return materialSprite;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool HasCoinRequirement(storeItemSO itemSO)
|
||||
private bool HasSupportedRequirement(storeItemSO itemSO)
|
||||
{
|
||||
if (itemSO == null || itemSO.costRequirements == null || itemSO.costRequirements.Count == 0)
|
||||
{
|
||||
@@ -1009,6 +1044,12 @@ public class storeSystem : MonoBehaviour
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsSelectableEquipmentRewardItem(currentSelectedItem))
|
||||
{
|
||||
HandleSelectableEquipmentPurchaseClicked(currentSelectedItem);
|
||||
return;
|
||||
}
|
||||
|
||||
string failureMessage;
|
||||
int grantedCount;
|
||||
if (!StoreExpBottlePurchaseService.TryPurchase(playerData, currentSelectedItem, currentPurchaseAmount, out failureMessage, out grantedCount))
|
||||
@@ -1026,6 +1067,125 @@ public class storeSystem : MonoBehaviour
|
||||
RefreshCurrentView();
|
||||
}
|
||||
|
||||
private void HandleSelectableEquipmentPurchaseClicked(storeItemSO itemSO)
|
||||
{
|
||||
if (itemSO == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentPurchaseAmount != 1)
|
||||
{
|
||||
SetPurchaseAmount(1, false);
|
||||
gNotice.warning.display("该物品仅支持单份购买");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryGetSelectableEquipmentRequirement(itemSO, out smeltStageRewardSO rewardSource, out smeltStageRewardSO.SmeltStageRewardRequirement requirement))
|
||||
{
|
||||
gNotice.warning.display("当前未配置发放逻辑");
|
||||
return;
|
||||
}
|
||||
|
||||
bool requireTypeSelection = RequiresTypeSelection(requirement);
|
||||
bool requireSkillSelection = RequiresSkillSelection(requirement);
|
||||
|
||||
if (!requireTypeSelection && !requireSkillSelection)
|
||||
{
|
||||
TryCompleteSelectableEquipmentPurchase(itemSO, rewardSource, requirement, null, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctasPrefab == null || ctasParent == null || rewardSource == null || rewardSource.rewardRandomConfig == null)
|
||||
{
|
||||
gNotice.warning.display("选择器未配置");
|
||||
return;
|
||||
}
|
||||
|
||||
CloseActiveCtas();
|
||||
|
||||
GameObject instance = Instantiate(ctasPrefab, ctasParent);
|
||||
activeCtasInstance = instance;
|
||||
|
||||
global::ctasPrefab selector = instance.GetComponent<global::ctasPrefab>();
|
||||
if (selector == null)
|
||||
{
|
||||
Destroy(instance);
|
||||
activeCtasInstance = null;
|
||||
gNotice.warning.display("选择器未配置");
|
||||
return;
|
||||
}
|
||||
|
||||
equipmentSO selectionTemplate = rewardSource.rewardTemplate != null
|
||||
? Instantiate(rewardSource.rewardTemplate)
|
||||
: ScriptableObject.CreateInstance<equipmentSO>();
|
||||
selectionTemplate.hideFlags = HideFlags.DontSave;
|
||||
selectionTemplate.sa_skillID = 0;
|
||||
selectionTemplate.ia_skillID = 0;
|
||||
selectionTemplate.skillType = requirement.chosenSkillType;
|
||||
|
||||
selector.Initialize(
|
||||
selectionTemplate,
|
||||
rewardSource.rewardRandomConfig,
|
||||
requireTypeSelection,
|
||||
requireSkillSelection,
|
||||
(selectedType, selectedSkillGroupId) =>
|
||||
{
|
||||
activeCtasInstance = null;
|
||||
TryCompleteSelectableEquipmentPurchase(itemSO, rewardSource, requirement, selectedType, selectedSkillGroupId);
|
||||
},
|
||||
() => { activeCtasInstance = null; });
|
||||
}
|
||||
|
||||
private void TryCompleteSelectableEquipmentPurchase(
|
||||
storeItemSO itemSO,
|
||||
smeltStageRewardSO rewardSource,
|
||||
smeltStageRewardSO.SmeltStageRewardRequirement requirement,
|
||||
equipmentSO.EquipmentSkillType? selectedType,
|
||||
int selectedSkillGroupId)
|
||||
{
|
||||
if (itemSO == null || rewardSource == null || requirement == null || itemSO.costRequirements == null || itemSO.costRequirements.Count == 0)
|
||||
{
|
||||
gNotice.warning.display("商品数据丢失");
|
||||
return;
|
||||
}
|
||||
|
||||
var primaryCost = itemSO.costRequirements[0];
|
||||
int totalCost = Mathf.Max(0, primaryCost.amount);
|
||||
string insufficientMessage = primaryCost.currencyType == storeItemSO.CurrencyType.material ? "记忆碎片不足" : "货币不足";
|
||||
|
||||
if (!HasEnoughCurrency(primaryCost.currencyType, totalCost))
|
||||
{
|
||||
gNotice.warning.display(insufficientMessage);
|
||||
RefreshPurchaseSummary();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TrySpendCurrency(primaryCost.currencyType, totalCost))
|
||||
{
|
||||
gNotice.warning.display(insufficientMessage);
|
||||
RefreshPurchaseSummary();
|
||||
return;
|
||||
}
|
||||
|
||||
equipmentSO generated = equipmentGenerator.GenerateFromSmeltReward(
|
||||
rewardSource,
|
||||
requirement,
|
||||
selectedType,
|
||||
selectedSkillGroupId);
|
||||
|
||||
if (generated == null)
|
||||
{
|
||||
RefundCurrency(primaryCost.currencyType, totalCost);
|
||||
gNotice.warning.display("装备发放失败");
|
||||
RefreshPurchaseSummary();
|
||||
return;
|
||||
}
|
||||
|
||||
RegisterPurchasedCount(itemSO.itemID, 1);
|
||||
RefreshAllEquipBags();
|
||||
}
|
||||
|
||||
private string GetAmountAndQuotaText(storeItemSO itemSO)
|
||||
{
|
||||
string prefix = itemSO.itemSinglePurchaseQty == 1 ? string.Empty : $"{itemSO.itemSinglePurchaseQty}个装/";
|
||||
@@ -1064,7 +1224,7 @@ public class storeSystem : MonoBehaviour
|
||||
|
||||
private string GetPriceAmountText(storeItemSO itemSO)
|
||||
{
|
||||
if (itemSO == null || !itemSO.canbepurchased || IsAssociatedContentUnlocked(itemSO) || !HasCoinRequirement(itemSO))
|
||||
if (itemSO == null || !itemSO.canbepurchased || IsAssociatedContentUnlocked(itemSO) || !HasSupportedRequirement(itemSO))
|
||||
{
|
||||
return "不可购买";
|
||||
}
|
||||
@@ -1074,22 +1234,156 @@ public class storeSystem : MonoBehaviour
|
||||
|
||||
private bool ShouldShowPriceIcon(storeItemSO itemSO)
|
||||
{
|
||||
return itemSO != null && itemSO.canbepurchased && !IsAssociatedContentUnlocked(itemSO) && HasCoinRequirement(itemSO);
|
||||
return itemSO != null && itemSO.canbepurchased && !IsAssociatedContentUnlocked(itemSO) && HasSupportedRequirement(itemSO);
|
||||
}
|
||||
|
||||
private bool CanPurchaseCurrentSelection(storeItemSO itemSO)
|
||||
{
|
||||
return IsCurrentlyPurchasable(itemSO);
|
||||
return IsCurrentlyPurchasable(itemSO)
|
||||
&& (!IsSelectableEquipmentRewardItem(itemSO) || currentPurchaseAmount == 1);
|
||||
}
|
||||
|
||||
private bool CanAffordCurrentSelection(long totalCost)
|
||||
{
|
||||
if (totalCost <= 0)
|
||||
if (currentSelectedItem == null || totalCost <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return PlayerEconomyLedger.EnsureInstance().HasEnoughCoins(totalCost);
|
||||
var cost = currentSelectedItem.costRequirements != null && currentSelectedItem.costRequirements.Count > 0
|
||||
? currentSelectedItem.costRequirements[0]
|
||||
: null;
|
||||
if (cost == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (cost.currencyType)
|
||||
{
|
||||
case storeItemSO.CurrencyType.coins:
|
||||
return PlayerEconomyLedger.EnsureInstance().HasEnoughCoins(totalCost);
|
||||
case storeItemSO.CurrencyType.material:
|
||||
return PlayerEconomyLedger.EnsureInstance().HasEnoughMaterial(totalCost);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsSelectableEquipmentRewardItem(storeItemSO itemSO)
|
||||
{
|
||||
return itemSO != null
|
||||
&& itemSO.associatedSelectableEquipmentRewardSource != null
|
||||
&& itemSO.associatedSelectableEquipmentRewardIndex >= 0;
|
||||
}
|
||||
|
||||
private bool TryGetSelectableEquipmentRequirement(
|
||||
storeItemSO itemSO,
|
||||
out smeltStageRewardSO rewardSource,
|
||||
out smeltStageRewardSO.SmeltStageRewardRequirement requirement)
|
||||
{
|
||||
rewardSource = null;
|
||||
requirement = null;
|
||||
|
||||
if (!IsSelectableEquipmentRewardItem(itemSO))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
rewardSource = itemSO.associatedSelectableEquipmentRewardSource;
|
||||
if (rewardSource.rewardRequirements == null
|
||||
|| itemSO.associatedSelectableEquipmentRewardIndex >= rewardSource.rewardRequirements.Length)
|
||||
{
|
||||
rewardSource = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
requirement = rewardSource.rewardRequirements[itemSO.associatedSelectableEquipmentRewardIndex];
|
||||
return requirement != null;
|
||||
}
|
||||
|
||||
private bool RequiresTypeSelection(smeltStageRewardSO.SmeltStageRewardRequirement requirement)
|
||||
{
|
||||
if (requirement == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (requirement.equipmentType == smeltStageRewardSO.equipType.selfChosenType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return !string.IsNullOrEmpty(requirement.equipRewardName)
|
||||
&& requirement.equipRewardName.Contains("自选");
|
||||
}
|
||||
|
||||
private bool RequiresSkillSelection(smeltStageRewardSO.SmeltStageRewardRequirement requirement)
|
||||
{
|
||||
return requirement != null
|
||||
&& requirement.skillRequirement == smeltStageRewardSO.skillOwned.selfChosen;
|
||||
}
|
||||
|
||||
private bool HasEnoughCurrency(storeItemSO.CurrencyType currencyType, int amount)
|
||||
{
|
||||
switch (currencyType)
|
||||
{
|
||||
case storeItemSO.CurrencyType.coins:
|
||||
return PlayerEconomyLedger.EnsureInstance().HasEnoughCoins(amount);
|
||||
case storeItemSO.CurrencyType.material:
|
||||
return PlayerEconomyLedger.EnsureInstance().HasEnoughMaterial(amount);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool TrySpendCurrency(storeItemSO.CurrencyType currencyType, int amount)
|
||||
{
|
||||
switch (currencyType)
|
||||
{
|
||||
case storeItemSO.CurrencyType.coins:
|
||||
return PlayerEconomyLedger.EnsureInstance().TrySpendCoins(amount);
|
||||
case storeItemSO.CurrencyType.material:
|
||||
return PlayerEconomyLedger.EnsureInstance().TrySpendMaterial(amount);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void RefundCurrency(storeItemSO.CurrencyType currencyType, int amount)
|
||||
{
|
||||
switch (currencyType)
|
||||
{
|
||||
case storeItemSO.CurrencyType.coins:
|
||||
PlayerEconomyLedger.EnsureInstance().AddCoins(amount);
|
||||
break;
|
||||
case storeItemSO.CurrencyType.material:
|
||||
PlayerEconomyLedger.EnsureInstance().AddMaterial(amount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseActiveCtas()
|
||||
{
|
||||
if (activeCtasInstance != null)
|
||||
{
|
||||
Destroy(activeCtasInstance);
|
||||
activeCtasInstance = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void RefreshAllEquipBags()
|
||||
{
|
||||
equipBag[] bags = Resources.FindObjectsOfTypeAll<equipBag>();
|
||||
for (int i = 0; i < bags.Length; i++)
|
||||
{
|
||||
equipBag bag = bags[i];
|
||||
if (bag == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bag.Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupAvailabilityState(storeItemPrefab itemView, storeItemSO itemSO)
|
||||
|
||||
Reference in New Issue
Block a user