using System.Collections.Generic; using Bansonic; using UnityEngine; using UnityEngine.UI; public class dailyTaskManager : MonoBehaviour { [Header("任务池so")] public userTasksPool taskPool; [Header("player data")] public Player_SO playerData; [Header("今日进度")] public Slider todayProgressSlider; public Text todayProgressPercent; public Text todayProgressText; public Text notasksanymore; [Header("一键领取")] public Button oneKeyRewardBtn; [Header("刷新任务")] public Button refreshTaskBtn; [Header("任务配置")] [Tooltip("任务列表最大容量")] public int taskMaxSize = 5; [Tooltip("最大刷新次数")] public int refreshMaxTimes = 3; [Header("prefabs")] public GameObject dailyTaskItemPrefab; public Transform dailyTaskItemParent; [Header("reward sprites")] public Sprite coinRewardSprite; [Header("reward availability visuals")] [SerializeField] private Material unavailableRewardMaterial; private readonly List spawnedTaskItems = new List(); private readonly Dictionary rewardSpriteByItemId = new Dictionary(); private readonly Dictionary rewardStoreItemByItemId = new Dictionary(); private void Start() { CacheRewardSpritesFromStoreItems(); var taskService = DailyTaskService.EnsureInstance(); taskService.Configure(taskPool, taskMaxSize, refreshMaxTimes); taskService.OnTasksChanged += RefreshTaskUi; if (oneKeyRewardBtn != null) { oneKeyRewardBtn.onClick.RemoveAllListeners(); oneKeyRewardBtn.onClick.AddListener(OnOneKeyRewardClicked); } if (refreshTaskBtn != null) { refreshTaskBtn.onClick.RemoveAllListeners(); refreshTaskBtn.onClick.AddListener(OnRefreshTaskClicked); } RefreshTaskUi(); } private void OnDestroy() { if (DailyTaskService.Instance != null) { DailyTaskService.Instance.OnTasksChanged -= RefreshTaskUi; } } private void RefreshTaskUi() { ClearSpawnedItems(); var tasks = DailyTaskService.EnsureInstance().GetActiveTaskViews(); if (notasksanymore != null) { notasksanymore.gameObject.SetActive(tasks.Count == 0); notasksanymore.text = tasks.Count == 0 ? LocalizationService.Get("daily.no_tasks", "今日暂无任务") : string.Empty; } int completedCount = 0; for (int i = 0; i < tasks.Count; i++) { var taskView = tasks[i]; if (taskView == null || taskView.definition == null || taskView.runtimeEntry == null) { continue; } if (taskView.runtimeEntry.isCompleted) { completedCount += 1; } SpawnTaskItem(i, taskView); } UpdateTodayProgress(tasks.Count, completedCount); RefreshOneKeyRewardButtonState(tasks); RefreshTaskButtonState(); } private void SpawnTaskItem(int index, DailyTaskViewData taskView) { if (dailyTaskItemPrefab == null || dailyTaskItemParent == null) { return; } var instance = Instantiate(dailyTaskItemPrefab, dailyTaskItemParent); spawnedTaskItems.Add(instance); var controller = instance.GetComponent(); if (controller == null) { return; } controller.Setup( taskView, index + 1, ResolveRewardSprite(taskView.definition), () => OnSingleRewardClicked(taskView.runtimeEntry.taskID), unavailableRewardMaterial); } private void UpdateTodayProgress(int totalTaskCount, int completedCount) { float progress = totalTaskCount <= 0 ? 0f : (float)completedCount / totalTaskCount; if (todayProgressSlider != null) { todayProgressSlider.value = progress; } if (todayProgressPercent != null) { todayProgressPercent.text = (progress * 100f).ToString("F0") + "%"; } if (todayProgressText != null) { todayProgressText.text = completedCount + "/" + totalTaskCount; } } private void ClearSpawnedItems() { for (int i = spawnedTaskItems.Count - 1; i >= 0; i--) { if (spawnedTaskItems[i] != null) { Destroy(spawnedTaskItems[i]); } } spawnedTaskItems.Clear(); } private void OnSingleRewardClicked(string taskID) { var rewardEntry = BuildRewardEntryForTask(taskID); string failureMessage; if (!DailyTaskService.EnsureInstance().TryClaimReward(taskID, playerData, out failureMessage)) { if (!string.IsNullOrEmpty(failureMessage)) { gNotice.warning.display(failureMessage); } return; } if (rewardEntry.HasValue) { gItemGet.display(rewardEntry.Value); } RefreshTaskUi(); } private void OnOneKeyRewardClicked() { var taskService = DailyTaskService.EnsureInstance(); var tasks = taskService.GetActiveTaskViews(); var grantedEntries = new List(); string failureMessage = string.Empty; int claimedCount = 0; for (int i = 0; i < tasks.Count; i++) { var taskView = tasks[i]; if (taskView == null || taskView.runtimeEntry == null || taskView.definition == null) { continue; } if (!taskView.runtimeEntry.isCompleted || taskView.runtimeEntry.isClaimed) { continue; } string claimError; if (!taskService.TryClaimReward(taskView.runtimeEntry.taskID, playerData, out claimError)) { if (claimedCount <= 0 && string.IsNullOrEmpty(failureMessage)) { failureMessage = claimError; } continue; } claimedCount += 1; grantedEntries.Add(BuildRewardEntry(taskView.definition)); } if (claimedCount <= 0) { if (string.IsNullOrEmpty(failureMessage)) { failureMessage = LocalizationService.Get("daily.no_claimable_reward", "暂无可领取奖励"); } if (!string.IsNullOrEmpty(failureMessage)) { gNotice.warning.display(failureMessage); } return; } if (grantedEntries.Count > 0) { gItemGet.display(grantedEntries); } RefreshTaskUi(); } private void RefreshOneKeyRewardButtonState(IReadOnlyList tasks) { if (oneKeyRewardBtn == null) { return; } bool hasClaimableReward = false; for (int i = 0; i < tasks.Count; i++) { var taskView = tasks[i]; if (taskView == null || taskView.runtimeEntry == null) { continue; } if (taskView.runtimeEntry.isCompleted && !taskView.runtimeEntry.isClaimed) { hasClaimableReward = true; break; } } oneKeyRewardBtn.interactable = hasClaimableReward; } private void OnRefreshTaskClicked() { if (taskPool == null) { gNotice.warning.display(LocalizationService.Get("daily.pool_missing", "未配置任务池")); return; } var taskService = DailyTaskService.EnsureInstance(); if (!taskService.TryRefreshTasks()) { if (taskService.GetRemainingRefreshCount() <= 0) { gNotice.warning.display("今日刷新次数已用尽"); } else { gNotice.warning.display(LocalizationService.Get("daily.refresh_failed", "刷新失败")); } RefreshTaskButtonState(); return; } gNotice.message.display($"刷新成功,剩余刷新次数:{taskService.GetRemainingRefreshCount()}"); RefreshTaskUi(); } private void RefreshTaskButtonState() { if (refreshTaskBtn == null) { return; } refreshTaskBtn.interactable = taskPool != null && DailyTaskService.EnsureInstance().GetRemainingRefreshCount() > 0; } private Sprite ResolveRewardSprite(userTasksPool.TaskDefinition definition) { if (definition == null) { return null; } switch (definition.rewardType) { case userTasksPool.RewardType.coins: return coinRewardSprite; case userTasksPool.RewardType.expBottle: return GetRewardSpriteByItemId(GetExpBottleRewardItemId(definition.rewardExpBottleKind)); case userTasksPool.RewardType.dushMaterial: return GetRewardSpriteByItemId(GetDushMaterialRewardItemId(definition.rewardDushMaterialKind)); default: return null; } } private void CacheRewardSpritesFromStoreItems() { rewardSpriteByItemId.Clear(); rewardStoreItemByItemId.Clear(); var rewardStoreItems = RuntimeResourcesCache.LoadAllStoreItems(); for (int i = 0; i < rewardStoreItems.Length; i++) { var itemSO = rewardStoreItems[i]; if (itemSO == null) { continue; } if (itemSO.itemIcon != null) { rewardSpriteByItemId[itemSO.itemID] = itemSO.itemIcon; } rewardStoreItemByItemId[itemSO.itemID] = itemSO; } } private Sprite GetRewardSpriteByItemId(int itemId) { if (itemId <= 0) { return null; } Sprite sprite; return rewardSpriteByItemId.TryGetValue(itemId, out sprite) ? sprite : null; } private gItemGet.ItemEntry? BuildRewardEntryForTask(string taskID) { if (string.IsNullOrWhiteSpace(taskID)) { return null; } var tasks = DailyTaskService.EnsureInstance().GetActiveTaskViews(); for (int i = 0; i < tasks.Count; i++) { var taskView = tasks[i]; if (taskView == null || taskView.runtimeEntry == null || taskView.definition == null) { continue; } if (string.Equals(taskView.runtimeEntry.taskID, taskID, System.StringComparison.Ordinal)) { return BuildRewardEntry(taskView.definition); } } return null; } private gItemGet.ItemEntry BuildRewardEntry(userTasksPool.TaskDefinition definition) { if (definition == null) { return gItemGet.Create(LocalizationService.Get("item.unknown.reward", "未知奖励"), null, 1, ItemRarity.None); } switch (definition.rewardType) { case userTasksPool.RewardType.coins: return gItemGet.Create("算力", coinRewardSprite, Mathf.Max(1, definition.rewardAmount), ItemRarity.Common); case userTasksPool.RewardType.expBottle: { int itemId = GetExpBottleRewardItemId(definition.rewardExpBottleKind); storeItemSO itemSO; if (rewardStoreItemByItemId.TryGetValue(itemId, out itemSO) && itemSO != null) { return gItemGet.FromStoreItem(itemSO, Mathf.Max(1, definition.rewardAmount)); } return gItemGet.Create( ExpBottleCatalog.GetDisplayName(definition.rewardExpBottleKind), GetRewardSpriteByItemId(itemId), Mathf.Max(1, definition.rewardAmount), ItemRarity.None); } case userTasksPool.RewardType.dushMaterial: { int itemId = GetDushMaterialRewardItemId(definition.rewardDushMaterialKind); storeItemSO itemSO; if (rewardStoreItemByItemId.TryGetValue(itemId, out itemSO) && itemSO != null) { return gItemGet.FromStoreItem(itemSO, Mathf.Max(1, definition.rewardAmount)); } return gItemGet.Create( DushMaterialCatalog.GetDisplayName(definition.rewardDushMaterialKind), GetRewardSpriteByItemId(itemId), Mathf.Max(1, definition.rewardAmount), ItemRarity.None); } default: return gItemGet.Create(LocalizationService.Get("item.unknown.reward", "未知奖励"), null, Mathf.Max(1, definition.rewardAmount), ItemRarity.None); } } private static int GetExpBottleRewardItemId(ExpBottleKind kind) { switch (kind) { case ExpBottleKind.Common: return 78001; case ExpBottleKind.Medium: return 78002; case ExpBottleKind.Superior: return 78003; case ExpBottleKind.Supreme: return 78004; case ExpBottleKind.Extraordinary: return 78005; case ExpBottleKind.Celestial: return 78006; case ExpBottleKind.RainAll: return 78011; case ExpBottleKind.AdvancedRainAll: return 78012; case ExpBottleKind.SuperRainAll: return 78013; default: return 0; } } private static int GetDushMaterialRewardItemId(DushMaterialKind kind) { switch (kind) { case DushMaterialKind.Material78021: return 78021; case DushMaterialKind.Material78022: return 78022; case DushMaterialKind.Material78023: return 78023; case DushMaterialKind.Material78024: return 78024; default: return 0; } } }