1206 lines
34 KiB
C#
1206 lines
34 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using Bansonic;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
|
|
public class equipSmelt : MonoBehaviour
|
|
{
|
|
private static readonly List<equipmentSO> SmeltPoolEquipments = new List<equipmentSO>();
|
|
private static readonly HashSet<equipmentSO> SmeltPoolLookup = new HashSet<equipmentSO>();
|
|
private static readonly HashSet<string> ConsumedSmeltEquipmentIds = new HashSet<string>(StringComparer.Ordinal);
|
|
private static readonly HashSet<equipmentSO> ConsumedSmeltEquipments = new HashSet<equipmentSO>();
|
|
private const string SmeltStatePrefsKey = "equip_smelt_state_v1";
|
|
private static bool persistenceLoaded;
|
|
private static readonly List<equipSmelt> Instances = new List<equipSmelt>();
|
|
|
|
private static bool isSmeltingState;
|
|
private static bool smeltCompletedState;
|
|
private static int gamesRequiredForCurrentBatchState;
|
|
private static int gamesCompletedForCurrentBatchState;
|
|
private static int pendingDirectFragmentsState;
|
|
private static int pendingStoredFragmentsState;
|
|
private static int storedSmeltEnergyState;
|
|
|
|
[Serializable]
|
|
private sealed class SmeltPersistentState
|
|
{
|
|
public bool isSmelting;
|
|
public bool smeltCompleted;
|
|
public int gamesRequired;
|
|
public int gamesCompleted;
|
|
public int pendingDirectFragments;
|
|
public int pendingStoredFragments;
|
|
public int storedSmeltEnergy;
|
|
public string[] consumedEquipmentIds;
|
|
}
|
|
|
|
[Header("so")]
|
|
public smeltStageRewardSO ssrso;
|
|
|
|
[Header("sprites")]
|
|
public Sprite memoryFragment;
|
|
public Sprite coins;
|
|
|
|
[Header("selection and progress")]
|
|
public GameObject smeltPool;
|
|
public GameObject smeltProgress;
|
|
|
|
[Header("drag")]
|
|
public GameObject dragObj;
|
|
|
|
[Header("smeltPool")]
|
|
public GameObject smeltPoolItemPrefab;
|
|
public Transform smeltPoolContent;
|
|
|
|
[Header("smeltTimeProgress")]
|
|
public Slider stpSlider;
|
|
public Text smeltStatusText;
|
|
public Button quickFinishButton;
|
|
public Text qf_cost_text;
|
|
|
|
[Header("smelt Rewards")]
|
|
public Text rewardGenProgress;
|
|
public Image rewardProgressImage;
|
|
public Dropdown selectAReward;
|
|
public Button getReward;
|
|
|
|
[Header("smelt notice")]
|
|
public Image d_mf_img;
|
|
public Text d_mf_Amount;
|
|
public Image s_mf_img;
|
|
public Text s_mf_Amount;
|
|
public Text smeltNoticeText;
|
|
|
|
[Header("cost and start")]
|
|
public Text costText;
|
|
public Text reasonWhy;
|
|
public Button startSmeltButton;
|
|
|
|
[Header("choose type and skill")]
|
|
public GameObject ctasPrefab;
|
|
public Transform ctasParent;
|
|
|
|
private readonly List<GameObject> spawnedPoolItems = new List<GameObject>();
|
|
private GameObject activeCtasInstance;
|
|
|
|
private void Awake()
|
|
{
|
|
EnsurePersistentStateLoaded();
|
|
RegisterInstance();
|
|
BindButtons();
|
|
RefreshAllUi();
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
RegisterInstance();
|
|
BindButtons();
|
|
RefreshAllUi();
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
CloseActiveCtas();
|
|
Instances.Remove(this);
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
CloseActiveCtas();
|
|
Instances.Remove(this);
|
|
}
|
|
|
|
public static bool IsEquipmentAssignedToSmeltPool(equipmentSO equipment)
|
|
{
|
|
EnsurePersistentStateLoaded();
|
|
return equipment != null && SmeltPoolLookup.Contains(equipment);
|
|
}
|
|
|
|
public static bool IsEquipmentConsumedBySmelt(equipmentSO equipment)
|
|
{
|
|
EnsurePersistentStateLoaded();
|
|
return equipment != null && ConsumedSmeltEquipments.Contains(equipment);
|
|
}
|
|
|
|
public static bool ShouldHideConsumedEquipment(equipmentSO equipment)
|
|
{
|
|
EnsurePersistentStateLoaded();
|
|
return equipment != null
|
|
&& (ConsumedSmeltEquipments.Contains(equipment)
|
|
|| (!string.IsNullOrWhiteSpace(equipment.name) && ConsumedSmeltEquipmentIds.Contains(equipment.name)));
|
|
}
|
|
|
|
public static bool RemoveEquipmentFromSmeltPool(equipmentSO equipment)
|
|
{
|
|
EnsurePersistentStateLoaded();
|
|
if (equipment == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!SmeltPoolLookup.Remove(equipment))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
SmeltPoolEquipments.Remove(equipment);
|
|
SavePersistentState();
|
|
RefreshAllSmeltPools();
|
|
RefreshAllEquipBags();
|
|
return true;
|
|
}
|
|
|
|
public static bool TryHandleQuickTransfer(equipmentSO equipment)
|
|
{
|
|
EnsurePersistentStateLoaded();
|
|
if (equipment == null || IsEquipmentConsumedBySmelt(equipment))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
equipSmelt activeSmelt = GetActivePoolInstance();
|
|
if (activeSmelt == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (IsEquipmentAssignedToSmeltPool(equipment))
|
|
{
|
|
return RemoveEquipmentFromSmeltPool(equipment);
|
|
}
|
|
|
|
activeSmelt.AcceptDraggedEquipment(equipment);
|
|
return IsEquipmentAssignedToSmeltPool(equipment);
|
|
}
|
|
|
|
public static void ReinstateRewardEquipment(equipmentSO equipment)
|
|
{
|
|
EnsurePersistentStateLoaded();
|
|
if (equipment == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ConsumedSmeltEquipments.Remove(equipment);
|
|
if (!string.IsNullOrWhiteSpace(equipment.name))
|
|
{
|
|
ConsumedSmeltEquipmentIds.Remove(equipment.name);
|
|
}
|
|
|
|
SavePersistentState();
|
|
}
|
|
|
|
public void RefreshPlayerSkillAdjustedUi()
|
|
{
|
|
RefreshAllUi();
|
|
}
|
|
|
|
public void SetDragPreviewVisible(bool visible)
|
|
{
|
|
if (dragObj == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!IsPoolOpenForTransfers())
|
|
{
|
|
dragObj.SetActive(false);
|
|
return;
|
|
}
|
|
|
|
bool shouldShow = visible || SmeltPoolEquipments.Count == 0;
|
|
dragObj.SetActive(shouldShow);
|
|
}
|
|
|
|
public bool IsPointerOverDropArea(Vector2 screenPoint, Camera eventCamera)
|
|
{
|
|
if (dragObj == null || !dragObj.activeInHierarchy || !IsPoolOpenForTransfers())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
RectTransform[] rects = dragObj.GetComponentsInChildren<RectTransform>(true);
|
|
if (rects == null || rects.Length == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
for (int i = 0; i < rects.Length; i++)
|
|
{
|
|
RectTransform rect = rects[i];
|
|
if (rect == null || !rect.gameObject.activeInHierarchy)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (RectTransformUtility.RectangleContainsScreenPoint(rect, screenPoint, eventCamera))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public void AcceptDraggedEquipment(equipmentSO equipment)
|
|
{
|
|
EnsurePersistentStateLoaded();
|
|
if (equipment == null || IsEquipmentConsumedBySmelt(equipment) || !IsPoolOpenForTransfers())
|
|
{
|
|
return;
|
|
}
|
|
|
|
int capacity = GetSmeltEquipmentCapacity();
|
|
if (capacity <= 0 || SmeltPoolEquipments.Count >= capacity)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (SmeltPoolLookup.Add(equipment))
|
|
{
|
|
SmeltPoolEquipments.Add(equipment);
|
|
SavePersistentState();
|
|
RefreshAllUi();
|
|
RefreshAllEquipBags();
|
|
}
|
|
}
|
|
|
|
private void BindButtons()
|
|
{
|
|
if (startSmeltButton != null)
|
|
{
|
|
startSmeltButton.onClick.RemoveListener(HandleStartSmeltClicked);
|
|
startSmeltButton.onClick.AddListener(HandleStartSmeltClicked);
|
|
}
|
|
|
|
if (quickFinishButton != null)
|
|
{
|
|
quickFinishButton.onClick.RemoveListener(HandleQuickFinishClicked);
|
|
quickFinishButton.onClick.AddListener(HandleQuickFinishClicked);
|
|
}
|
|
|
|
if (getReward != null)
|
|
{
|
|
getReward.onClick.RemoveListener(HandleGetRewardClicked);
|
|
getReward.onClick.AddListener(HandleGetRewardClicked);
|
|
}
|
|
|
|
if (selectAReward != null)
|
|
{
|
|
selectAReward.onValueChanged.RemoveListener(HandleRewardSelectionChanged);
|
|
selectAReward.onValueChanged.AddListener(HandleRewardSelectionChanged);
|
|
}
|
|
}
|
|
|
|
private void HandleStartSmeltClicked()
|
|
{
|
|
if (smeltCompletedState)
|
|
{
|
|
ClaimCurrentBatchRewards();
|
|
return;
|
|
}
|
|
|
|
if (isSmeltingState || SmeltPoolEquipments.Count <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int startCost = GetStartSmeltCost();
|
|
if (!PlayerEconomyLedger.EnsureInstance().TrySpendCoins(startCost))
|
|
{
|
|
RefreshAllUi();
|
|
return;
|
|
}
|
|
|
|
isSmeltingState = true;
|
|
smeltCompletedState = false;
|
|
gamesCompletedForCurrentBatchState = 0;
|
|
gamesRequiredForCurrentBatchState = Mathf.Max(1, Mathf.CeilToInt(SmeltPoolEquipments.Count / 20f));
|
|
|
|
int totalFragments = CalculateTotalFragmentsForCurrentPool();
|
|
pendingDirectFragmentsState = Mathf.FloorToInt(totalFragments * 0.7f);
|
|
pendingStoredFragmentsState = Mathf.Max(0, totalFragments - pendingDirectFragmentsState);
|
|
|
|
ConsumeCurrentPoolEquipments();
|
|
SavePersistentState();
|
|
RefreshAllUi();
|
|
RefreshAllEquipBags();
|
|
}
|
|
|
|
private void HandleQuickFinishClicked()
|
|
{
|
|
if (!isSmeltingState || smeltCompletedState)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int cost = GetQuickFinishCost();
|
|
if (!PlayerEconomyLedger.EnsureInstance().TrySpendCoins(cost))
|
|
{
|
|
return;
|
|
}
|
|
|
|
gamesCompletedForCurrentBatchState = gamesRequiredForCurrentBatchState;
|
|
smeltCompletedState = true;
|
|
SavePersistentState();
|
|
RefreshAllUi();
|
|
}
|
|
|
|
public static void NotifySettlementCompleted()
|
|
{
|
|
if (!isSmeltingState || smeltCompletedState)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (GameConfig.autoPlayEnabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
gamesCompletedForCurrentBatchState = Mathf.Min(gamesRequiredForCurrentBatchState, gamesCompletedForCurrentBatchState + 1);
|
|
if (gamesCompletedForCurrentBatchState >= gamesRequiredForCurrentBatchState)
|
|
{
|
|
smeltCompletedState = true;
|
|
ClaimCurrentBatchRewardsStatic();
|
|
return;
|
|
}
|
|
|
|
SavePersistentState();
|
|
RefreshAllSmeltPools();
|
|
}
|
|
|
|
private void ClaimCurrentBatchRewards()
|
|
{
|
|
ClaimCurrentBatchRewardsStatic();
|
|
}
|
|
|
|
private static void ClaimCurrentBatchRewardsStatic()
|
|
{
|
|
if (!smeltCompletedState)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int grantedFragments = Mathf.Max(0, pendingDirectFragmentsState);
|
|
if (pendingDirectFragmentsState > 0)
|
|
{
|
|
PlayerEconomyLedger.EnsureInstance().AddMaterial(pendingDirectFragmentsState);
|
|
}
|
|
|
|
storedSmeltEnergyState = Mathf.Clamp(storedSmeltEnergyState + pendingStoredFragmentsState, 0, GetSmeltStorageCapacityStatic());
|
|
|
|
pendingDirectFragmentsState = 0;
|
|
pendingStoredFragmentsState = 0;
|
|
gamesRequiredForCurrentBatchState = 0;
|
|
gamesCompletedForCurrentBatchState = 0;
|
|
isSmeltingState = false;
|
|
smeltCompletedState = false;
|
|
SavePersistentState();
|
|
RefreshAllSmeltPools();
|
|
RefreshAllEquipBags();
|
|
|
|
if (grantedFragments > 0)
|
|
{
|
|
gItemGet.display(gItemGet.Create("记忆碎片", ResolveMemoryFragmentSprite(), grantedFragments, ItemRarity.Uncommon));
|
|
}
|
|
}
|
|
|
|
private void HandleGetRewardClicked()
|
|
{
|
|
smeltStageRewardSO.SmeltStageRewardRequirement requirement = GetSelectedRewardRequirement();
|
|
if (requirement == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int requiredAmount = Mathf.Max(0, requirement.requiredAmount);
|
|
if (requiredAmount > storedSmeltEnergyState)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (RequiresRewardSelection(requirement))
|
|
{
|
|
OpenRewardSelector(requirement);
|
|
return;
|
|
}
|
|
|
|
GrantReward(requirement, null, 0);
|
|
}
|
|
|
|
private void HandleRewardSelectionChanged(int _)
|
|
{
|
|
RefreshButtons();
|
|
}
|
|
|
|
private bool RequiresRewardSelection(smeltStageRewardSO.SmeltStageRewardRequirement requirement)
|
|
{
|
|
if (requirement == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return RequiresTypeSelection(requirement)
|
|
|| RequiresSkillSelection(requirement);
|
|
}
|
|
|
|
private bool RequiresTypeSelection(smeltStageRewardSO.SmeltStageRewardRequirement requirement)
|
|
{
|
|
if (requirement == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (requirement.equipmentType == smeltStageRewardSO.equipType.selfChosenType)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return !string.IsNullOrWhiteSpace(requirement.equipRewardName)
|
|
&& requirement.equipRewardName.Contains("自选", StringComparison.Ordinal);
|
|
}
|
|
|
|
private bool RequiresSkillSelection(smeltStageRewardSO.SmeltStageRewardRequirement requirement)
|
|
{
|
|
return requirement != null
|
|
&& requirement.skillRequirement == smeltStageRewardSO.skillOwned.selfChosen;
|
|
}
|
|
|
|
private void OpenRewardSelector(smeltStageRewardSO.SmeltStageRewardRequirement requirement)
|
|
{
|
|
if (ctasPrefab == null || ctasParent == null || ssrso == null || ssrso.rewardRandomConfig == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CloseActiveCtas();
|
|
|
|
GameObject instance = Instantiate(ctasPrefab, ctasParent);
|
|
activeCtasInstance = instance;
|
|
|
|
global::ctasPrefab selector = instance.GetComponent<global::ctasPrefab>();
|
|
if (selector == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
equipmentSO selectionTemplate = ssrso.rewardTemplate != null
|
|
? UnityEngine.Object.Instantiate(ssrso.rewardTemplate)
|
|
: ScriptableObject.CreateInstance<equipmentSO>();
|
|
selectionTemplate.hideFlags = HideFlags.DontSave;
|
|
selectionTemplate.sa_skillID = 0;
|
|
selectionTemplate.ia_skillID = 0;
|
|
bool requireTypeSelection = RequiresTypeSelection(requirement);
|
|
bool requireSkillSelection = RequiresSkillSelection(requirement);
|
|
|
|
if (requireTypeSelection)
|
|
{
|
|
selectionTemplate.skillType = requirement.chosenSkillType;
|
|
}
|
|
|
|
selector.Initialize(
|
|
selectionTemplate,
|
|
ssrso.rewardRandomConfig,
|
|
requireTypeSelection,
|
|
requireSkillSelection,
|
|
(selectedType, selectedSkillGroupId) => HandleRewardSelectionConfirmed(requirement, selectedType, selectedSkillGroupId),
|
|
HandleRewardSelectorClosed);
|
|
}
|
|
|
|
private void HandleRewardSelectionConfirmed(smeltStageRewardSO.SmeltStageRewardRequirement requirement, equipmentSO.EquipmentSkillType selectedType, int selectedSkillGroupId)
|
|
{
|
|
activeCtasInstance = null;
|
|
GrantReward(requirement, selectedType, selectedSkillGroupId);
|
|
}
|
|
|
|
private void GrantReward(smeltStageRewardSO.SmeltStageRewardRequirement requirement, equipmentSO.EquipmentSkillType? selectedTypeOverride, int selectedSkillGroupId)
|
|
{
|
|
if (requirement == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int requiredAmount = Mathf.Max(0, requirement.requiredAmount);
|
|
if (requiredAmount > storedSmeltEnergyState)
|
|
{
|
|
return;
|
|
}
|
|
|
|
equipmentSO generated = equipmentGenerator.GenerateFromSmeltReward(ssrso, requirement, selectedTypeOverride, selectedSkillGroupId);
|
|
if (generated == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ReinstateRewardEquipment(generated);
|
|
storedSmeltEnergyState = Mathf.Max(0, storedSmeltEnergyState - requiredAmount);
|
|
SavePersistentState();
|
|
gItemGet.display(gItemGet.FromEquipment(generated, 1));
|
|
RefreshAllUi();
|
|
RefreshAllEquipBags();
|
|
}
|
|
|
|
private static Sprite ResolveMemoryFragmentSprite()
|
|
{
|
|
equipSmelt[] instances = FindObjectsByType<equipSmelt>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
|
if (instances == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
for (int i = 0; i < instances.Length; i++)
|
|
{
|
|
if (instances[i] != null && instances[i].memoryFragment != null)
|
|
{
|
|
return instances[i].memoryFragment;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private void HandleRewardSelectorClosed()
|
|
{
|
|
activeCtasInstance = null;
|
|
RefreshButtons();
|
|
}
|
|
|
|
private void CloseActiveCtas()
|
|
{
|
|
if (activeCtasInstance != null)
|
|
{
|
|
Destroy(activeCtasInstance);
|
|
activeCtasInstance = null;
|
|
}
|
|
}
|
|
|
|
private void ConsumeCurrentPoolEquipments()
|
|
{
|
|
if (SmeltPoolEquipments.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < SmeltPoolEquipments.Count; i++)
|
|
{
|
|
equipmentSO equipment = SmeltPoolEquipments[i];
|
|
if (equipment == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ConsumedSmeltEquipments.Add(equipment);
|
|
if (!string.IsNullOrWhiteSpace(equipment.name))
|
|
{
|
|
ConsumedSmeltEquipmentIds.Add(equipment.name);
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
string assetPath = AssetDatabase.GetAssetPath(equipment);
|
|
if (!string.IsNullOrWhiteSpace(assetPath) && assetPath.StartsWith("Assets/Resources/so/uEquip/", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
AssetDatabase.DeleteAsset(assetPath);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
SmeltPoolEquipments.Clear();
|
|
SmeltPoolLookup.Clear();
|
|
|
|
#if UNITY_EDITOR
|
|
AssetDatabase.SaveAssets();
|
|
AssetDatabase.Refresh();
|
|
#endif
|
|
|
|
SavePersistentState();
|
|
}
|
|
|
|
private void RefreshAllUi()
|
|
{
|
|
ApplySmeltViewState();
|
|
RebuildSmeltPool();
|
|
RefreshRewardPreview();
|
|
RefreshStoredEnergyDisplay();
|
|
RefreshRewardDropdown();
|
|
RefreshProgressDisplay();
|
|
RefreshButtons();
|
|
RefreshReasonWhy();
|
|
}
|
|
|
|
private void ApplySmeltViewState()
|
|
{
|
|
if (smeltPool != null)
|
|
{
|
|
smeltPool.SetActive(!isSmeltingState);
|
|
}
|
|
|
|
if (smeltProgress != null)
|
|
{
|
|
smeltProgress.SetActive(isSmeltingState);
|
|
}
|
|
|
|
SetDragPreviewVisible(false);
|
|
}
|
|
|
|
private bool IsPoolOpenForTransfers()
|
|
{
|
|
return gameObject.activeInHierarchy && smeltPool != null && smeltPool.activeInHierarchy && !isSmeltingState;
|
|
}
|
|
|
|
private void RebuildSmeltPool()
|
|
{
|
|
ClearSmeltPoolItems();
|
|
|
|
if (smeltPoolItemPrefab == null || smeltPoolContent == null)
|
|
{
|
|
SetDragPreviewVisible(false);
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < SmeltPoolEquipments.Count; i++)
|
|
{
|
|
equipmentSO equipment = SmeltPoolEquipments[i];
|
|
if (equipment == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
GameObject instance = Instantiate(smeltPoolItemPrefab, smeltPoolContent);
|
|
instance.name = string.IsNullOrWhiteSpace(equipment.GetCurrentTierDisplayName()) ? equipment.name : equipment.GetCurrentTierDisplayName();
|
|
instance.SetActive(true);
|
|
spawnedPoolItems.Add(instance);
|
|
|
|
equipItemPrefab item = instance.GetComponent<equipItemPrefab>();
|
|
if (item != null)
|
|
{
|
|
item.Bind(equipment);
|
|
}
|
|
}
|
|
|
|
int placeholderToSpawn = Mathf.Max(0, GetSmeltEquipmentCapacity() - SmeltPoolEquipments.Count);
|
|
for (int i = 0; i < placeholderToSpawn; i++)
|
|
{
|
|
GameObject instance = Instantiate(smeltPoolItemPrefab, smeltPoolContent);
|
|
instance.name = $"SmeltPlaceholder_{i:00}";
|
|
instance.SetActive(true);
|
|
spawnedPoolItems.Add(instance);
|
|
|
|
equipItemPrefab item = instance.GetComponent<equipItemPrefab>();
|
|
if (item != null)
|
|
{
|
|
item.Bind(null);
|
|
if (item.itemButton != null)
|
|
{
|
|
item.itemButton.interactable = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
SetDragPreviewVisible(false);
|
|
}
|
|
|
|
private void RefreshRewardPreview()
|
|
{
|
|
bool useLockedBatchReward = isSmeltingState || smeltCompletedState;
|
|
|
|
int directReward;
|
|
int savedReward;
|
|
|
|
if (useLockedBatchReward)
|
|
{
|
|
directReward = Mathf.Max(0, pendingDirectFragmentsState);
|
|
savedReward = Mathf.Max(0, pendingStoredFragmentsState);
|
|
}
|
|
else
|
|
{
|
|
int totalFragments = CalculateTotalFragmentsForCurrentPool();
|
|
directReward = Mathf.FloorToInt(totalFragments * 0.7f);
|
|
savedReward = Mathf.Max(0, totalFragments - directReward);
|
|
}
|
|
|
|
if (d_mf_Amount != null)
|
|
{
|
|
d_mf_Amount.text = directReward.ToString();
|
|
}
|
|
|
|
if (s_mf_Amount != null)
|
|
{
|
|
s_mf_Amount.text = savedReward.ToString();
|
|
}
|
|
}
|
|
|
|
private void RefreshProgressDisplay()
|
|
{
|
|
if (costText != null)
|
|
{
|
|
costText.text = GetStartSmeltCost().ToString();
|
|
}
|
|
|
|
if (qf_cost_text != null)
|
|
{
|
|
qf_cost_text.text = GetQuickFinishCost().ToString();
|
|
}
|
|
|
|
if (stpSlider != null)
|
|
{
|
|
int required = Mathf.Max(1, gamesRequiredForCurrentBatchState);
|
|
stpSlider.minValue = 0f;
|
|
stpSlider.maxValue = required;
|
|
stpSlider.value = Mathf.Clamp(gamesCompletedForCurrentBatchState, 0, required);
|
|
|
|
Text sliderText = stpSlider.GetComponentInChildren<Text>(true);
|
|
if (sliderText != null)
|
|
{
|
|
sliderText.text = $"融合进度{Mathf.Clamp(gamesCompletedForCurrentBatchState, 0, required)}/{required}";
|
|
}
|
|
}
|
|
|
|
if (smeltStatusText != null)
|
|
{
|
|
if (!isSmeltingState)
|
|
{
|
|
smeltStatusText.text = string.Empty;
|
|
}
|
|
else if (smeltCompletedState)
|
|
{
|
|
smeltStatusText.text = "融合完毕,可以收获结果";
|
|
}
|
|
else
|
|
{
|
|
int remain = Mathf.Max(0, gamesRequiredForCurrentBatchState - gamesCompletedForCurrentBatchState);
|
|
smeltStatusText.text = $"正在融合,还需{remain}场比赛";
|
|
}
|
|
}
|
|
}
|
|
|
|
private void RefreshStoredEnergyDisplay()
|
|
{
|
|
int capacity = GetSmeltStorageCapacity();
|
|
if (rewardGenProgress != null)
|
|
{
|
|
rewardGenProgress.text = $"{storedSmeltEnergyState}/{capacity}";
|
|
}
|
|
|
|
if (rewardProgressImage != null)
|
|
{
|
|
rewardProgressImage.fillAmount = capacity <= 0 ? 0f : Mathf.Clamp01((float)storedSmeltEnergyState / capacity);
|
|
}
|
|
}
|
|
|
|
private void RefreshRewardDropdown()
|
|
{
|
|
if (selectAReward == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int previousValue = selectAReward.options != null && selectAReward.options.Count > 0
|
|
? Mathf.Max(0, selectAReward.value)
|
|
: 0;
|
|
|
|
selectAReward.ClearOptions();
|
|
if (selectAReward.captionText != null)
|
|
{
|
|
selectAReward.captionText.supportRichText = true;
|
|
}
|
|
|
|
if (selectAReward.itemText != null)
|
|
{
|
|
selectAReward.itemText.supportRichText = true;
|
|
}
|
|
|
|
var options = new List<Dropdown.OptionData>();
|
|
if (ssrso != null && ssrso.rewardRequirements != null)
|
|
{
|
|
for (int i = 0; i < ssrso.rewardRequirements.Length; i++)
|
|
{
|
|
smeltStageRewardSO.SmeltStageRewardRequirement requirement = ssrso.rewardRequirements[i];
|
|
string optionName = requirement != null ? requirement.equipRewardName : string.Empty;
|
|
int requiredAmount = requirement != null ? Mathf.Max(0, requirement.requiredAmount) : 0;
|
|
string color = string.IsNullOrWhiteSpace(optionName)
|
|
? "#808080"
|
|
: (requiredAmount > storedSmeltEnergyState ? "#FF0000" : "#FFFFFF");
|
|
options.Add(new Dropdown.OptionData($"<color={color}>{(string.IsNullOrWhiteSpace(optionName) ? "未命名奖励" : optionName)}</color>"));
|
|
}
|
|
}
|
|
|
|
if (options.Count == 0)
|
|
{
|
|
options.Add(new Dropdown.OptionData("<color=#808080>暂无奖励</color>"));
|
|
}
|
|
|
|
selectAReward.AddOptions(options);
|
|
selectAReward.value = Mathf.Clamp(previousValue, 0, options.Count - 1);
|
|
selectAReward.RefreshShownValue();
|
|
}
|
|
|
|
private void RefreshButtons()
|
|
{
|
|
if (startSmeltButton != null)
|
|
{
|
|
bool canStart = !isSmeltingState
|
|
&& SmeltPoolEquipments.Count > 0
|
|
&& PlayerEconomyLedger.EnsureInstance().HasEnoughCoins(GetStartSmeltCost());
|
|
startSmeltButton.interactable = smeltCompletedState || canStart;
|
|
Text startButtonText = startSmeltButton.GetComponentInChildren<Text>(true);
|
|
if (startButtonText != null)
|
|
{
|
|
startButtonText.text = smeltCompletedState ? "领取碎片" : "开始融合";
|
|
}
|
|
}
|
|
|
|
if (quickFinishButton != null)
|
|
{
|
|
quickFinishButton.interactable = isSmeltingState && !smeltCompletedState && PlayerEconomyLedger.EnsureInstance().HasEnoughCoins(GetQuickFinishCost());
|
|
}
|
|
|
|
if (getReward != null)
|
|
{
|
|
smeltStageRewardSO.SmeltStageRewardRequirement requirement = GetSelectedRewardRequirement();
|
|
getReward.interactable = (activeCtasInstance == null) && requirement != null && Mathf.Max(0, requirement.requiredAmount) <= storedSmeltEnergyState;
|
|
}
|
|
}
|
|
|
|
private void RefreshReasonWhy()
|
|
{
|
|
if (reasonWhy == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (smeltCompletedState)
|
|
{
|
|
reasonWhy.text = string.Empty;
|
|
return;
|
|
}
|
|
|
|
if (isSmeltingState)
|
|
{
|
|
reasonWhy.text = "正在融合中";
|
|
return;
|
|
}
|
|
|
|
if (GetSmeltEquipmentCapacity() <= 0)
|
|
{
|
|
reasonWhy.text = "熔炉容量为0";
|
|
return;
|
|
}
|
|
|
|
if (SmeltPoolEquipments.Count <= 0)
|
|
{
|
|
reasonWhy.text = "需要投入记忆";
|
|
return;
|
|
}
|
|
|
|
reasonWhy.text = string.Empty;
|
|
|
|
if (!PlayerEconomyLedger.EnsureInstance().HasEnoughCoins(GetStartSmeltCost()))
|
|
{
|
|
reasonWhy.text = "算力不足";
|
|
return;
|
|
}
|
|
}
|
|
|
|
private int CalculateTotalFragmentsForCurrentPool()
|
|
{
|
|
int totalFragments = 0;
|
|
for (int i = 0; i < SmeltPoolEquipments.Count; i++)
|
|
{
|
|
equipmentSO equipment = SmeltPoolEquipments[i];
|
|
if (equipment == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
totalFragments += GetFragmentReward(equipment);
|
|
}
|
|
|
|
return totalFragments;
|
|
}
|
|
|
|
private int GetFragmentReward(equipmentSO equipment)
|
|
{
|
|
if (equipment == null)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int skillCount = 0;
|
|
if (equipment.sa_skillID > 0)
|
|
{
|
|
skillCount++;
|
|
}
|
|
|
|
if (equipment.ia_skillID > 0)
|
|
{
|
|
skillCount++;
|
|
}
|
|
|
|
int simpleReward = ssrso != null ? ssrso.simpleRewardAmount : 40;
|
|
int oneSkillReward = ssrso != null ? ssrso._1skillRewardAmount : 100;
|
|
int twoSkillReward = ssrso != null ? ssrso._2skillRewardAmount : 300;
|
|
|
|
switch (skillCount)
|
|
{
|
|
case 0: return simpleReward;
|
|
case 1: return oneSkillReward;
|
|
default: return twoSkillReward;
|
|
}
|
|
}
|
|
|
|
private int GetSmeltEquipmentCapacity()
|
|
{
|
|
if (ssrso == null)
|
|
{
|
|
return 60;
|
|
}
|
|
|
|
return Mathf.Clamp(ssrso.smeltEquipmentCapacity, 0, 100);
|
|
}
|
|
|
|
private int GetSmeltStorageCapacity()
|
|
{
|
|
if (ssrso == null)
|
|
{
|
|
return 5000;
|
|
}
|
|
|
|
return Mathf.Clamp(ssrso.smeltStorageCapacity, 0, 5000);
|
|
}
|
|
|
|
private static int GetSmeltStorageCapacityStatic()
|
|
{
|
|
for (int i = 0; i < Instances.Count; i++)
|
|
{
|
|
equipSmelt instance = Instances[i];
|
|
if (instance != null && instance.ssrso != null)
|
|
{
|
|
return Mathf.Clamp(instance.ssrso.smeltStorageCapacity, 0, 5000);
|
|
}
|
|
}
|
|
|
|
return 5000;
|
|
}
|
|
|
|
private int GetQuickFinishCost()
|
|
{
|
|
int baseCost = ssrso != null ? Mathf.Max(0, ssrso.quickFinishCost) : 0;
|
|
return PlayerSkillService.ModifySmeltCoinCost(baseCost);
|
|
}
|
|
|
|
private int GetStartSmeltCost()
|
|
{
|
|
int baseCost = ssrso != null ? Mathf.Max(0, ssrso.startSmeltCost) : 0;
|
|
return PlayerSkillService.ModifySmeltCoinCost(baseCost);
|
|
}
|
|
|
|
private smeltStageRewardSO.SmeltStageRewardRequirement GetSelectedRewardRequirement()
|
|
{
|
|
if (ssrso == null || ssrso.rewardRequirements == null || ssrso.rewardRequirements.Length == 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
int selectedIndex = selectAReward != null ? Mathf.Clamp(selectAReward.value, 0, ssrso.rewardRequirements.Length - 1) : 0;
|
|
return ssrso.rewardRequirements[selectedIndex];
|
|
}
|
|
|
|
private static equipSmelt GetActivePoolInstance()
|
|
{
|
|
for (int i = 0; i < Instances.Count; i++)
|
|
{
|
|
equipSmelt instance = Instances[i];
|
|
if (instance != null && instance.IsPoolOpenForTransfers())
|
|
{
|
|
return instance;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private void ClearSmeltPoolItems()
|
|
{
|
|
for (int i = smeltPoolContent != null ? smeltPoolContent.childCount - 1 : -1; i >= 0; i--)
|
|
{
|
|
Transform child = smeltPoolContent.GetChild(i);
|
|
if (child == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying)
|
|
{
|
|
DestroyImmediate(child.gameObject);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
Destroy(child.gameObject);
|
|
}
|
|
}
|
|
|
|
spawnedPoolItems.Clear();
|
|
}
|
|
|
|
private void RegisterInstance()
|
|
{
|
|
if (!Instances.Contains(this))
|
|
{
|
|
Instances.Add(this);
|
|
}
|
|
}
|
|
|
|
private void OnApplicationPause(bool pauseStatus)
|
|
{
|
|
if (pauseStatus)
|
|
{
|
|
SavePersistentState();
|
|
}
|
|
}
|
|
|
|
private void OnApplicationQuit()
|
|
{
|
|
SavePersistentState();
|
|
}
|
|
|
|
private static void EnsurePersistentStateLoaded()
|
|
{
|
|
if (persistenceLoaded)
|
|
{
|
|
return;
|
|
}
|
|
|
|
persistenceLoaded = true;
|
|
ConsumedSmeltEquipmentIds.Clear();
|
|
|
|
if (!PlayerPrefs.HasKey(SmeltStatePrefsKey))
|
|
{
|
|
return;
|
|
}
|
|
|
|
string json = PlayerPrefs.GetString(SmeltStatePrefsKey, string.Empty);
|
|
if (string.IsNullOrWhiteSpace(json))
|
|
{
|
|
return;
|
|
}
|
|
|
|
SmeltPersistentState state = null;
|
|
try
|
|
{
|
|
state = JsonUtility.FromJson<SmeltPersistentState>(json);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.LogWarning($"[equipSmelt] Failed to parse persistent state: {ex.Message}");
|
|
}
|
|
|
|
if (state == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
isSmeltingState = state.isSmelting;
|
|
smeltCompletedState = state.smeltCompleted;
|
|
gamesRequiredForCurrentBatchState = Mathf.Max(0, state.gamesRequired);
|
|
gamesCompletedForCurrentBatchState = Mathf.Clamp(state.gamesCompleted, 0, gamesRequiredForCurrentBatchState);
|
|
pendingDirectFragmentsState = Mathf.Max(0, state.pendingDirectFragments);
|
|
pendingStoredFragmentsState = Mathf.Max(0, state.pendingStoredFragments);
|
|
storedSmeltEnergyState = Mathf.Max(0, state.storedSmeltEnergy);
|
|
|
|
if (state.consumedEquipmentIds != null)
|
|
{
|
|
for (int i = 0; i < state.consumedEquipmentIds.Length; i++)
|
|
{
|
|
string id = state.consumedEquipmentIds[i];
|
|
if (!string.IsNullOrWhiteSpace(id))
|
|
{
|
|
ConsumedSmeltEquipmentIds.Add(id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void SavePersistentState()
|
|
{
|
|
if (!persistenceLoaded)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var state = new SmeltPersistentState
|
|
{
|
|
isSmelting = isSmeltingState,
|
|
smeltCompleted = smeltCompletedState,
|
|
gamesRequired = gamesRequiredForCurrentBatchState,
|
|
gamesCompleted = gamesCompletedForCurrentBatchState,
|
|
pendingDirectFragments = pendingDirectFragmentsState,
|
|
pendingStoredFragments = pendingStoredFragmentsState,
|
|
storedSmeltEnergy = storedSmeltEnergyState,
|
|
consumedEquipmentIds = ConsumedSmeltEquipmentIds.Count > 0 ? ConsumedSmeltEquipmentIds.ToArray() : Array.Empty<string>()
|
|
};
|
|
|
|
PlayerPrefs.SetString(SmeltStatePrefsKey, JsonUtility.ToJson(state));
|
|
PlayerPrefs.Save();
|
|
}
|
|
|
|
public static void ClearPersistentState()
|
|
{
|
|
SmeltPoolEquipments.Clear();
|
|
SmeltPoolLookup.Clear();
|
|
ConsumedSmeltEquipments.Clear();
|
|
ConsumedSmeltEquipmentIds.Clear();
|
|
|
|
isSmeltingState = false;
|
|
smeltCompletedState = false;
|
|
gamesRequiredForCurrentBatchState = 0;
|
|
gamesCompletedForCurrentBatchState = 0;
|
|
pendingDirectFragmentsState = 0;
|
|
pendingStoredFragmentsState = 0;
|
|
storedSmeltEnergyState = 0;
|
|
|
|
persistenceLoaded = true;
|
|
PlayerPrefs.DeleteKey(SmeltStatePrefsKey);
|
|
PlayerPrefs.Save();
|
|
|
|
RefreshAllSmeltPools();
|
|
RefreshAllEquipBags();
|
|
}
|
|
|
|
private static void RefreshAllSmeltPools()
|
|
{
|
|
for (int i = 0; i < Instances.Count; i++)
|
|
{
|
|
if (Instances[i] != null)
|
|
{
|
|
Instances[i].RefreshAllUi();
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void RefreshAllEquipBags()
|
|
{
|
|
equipBag[] bags = UnityEngine.Object.FindObjectsByType<equipBag>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
|
if (bags == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < bags.Length; i++)
|
|
{
|
|
if (bags[i] != null)
|
|
{
|
|
bags[i].Rebuild();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|