Files
bansonic_beta_main/Assets/scripts/dailyTask/dailyTaskManager.cs
T
2026-07-20 22:19:25 +08:00

514 lines
15 KiB
C#

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<GameObject> spawnedTaskItems = new List<GameObject>();
private readonly Dictionary<int, Sprite> rewardSpriteByItemId = new Dictionary<int, Sprite>();
private readonly Dictionary<int, storeItemSO> rewardStoreItemByItemId = new Dictionary<int, storeItemSO>();
private Coroutine layoutRefreshRoutine;
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();
RequestTaskListLayoutRebuild();
}
private void SpawnTaskItem(int index, DailyTaskViewData taskView)
{
if (dailyTaskItemPrefab == null || dailyTaskItemParent == null)
{
return;
}
var instance = Instantiate(dailyTaskItemPrefab, dailyTaskItemParent);
spawnedTaskItems.Add(instance);
UI_OrderedEntryAnimator.PlayFadeOnly(instance, index, 0.16f, 0.012f, true);
var controller = instance.GetComponent<taskPrefabController>();
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<gItemGet.ItemEntry>();
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<DailyTaskViewData> 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 void RequestTaskListLayoutRebuild()
{
if (dailyTaskItemParent == null)
{
return;
}
if (layoutRefreshRoutine != null)
{
StopCoroutine(layoutRefreshRoutine);
layoutRefreshRoutine = null;
}
if (isActiveAndEnabled)
{
layoutRefreshRoutine = StartCoroutine(RebuildTaskListLayoutNextFrame());
return;
}
RebuildTaskListLayoutNow();
}
private System.Collections.IEnumerator RebuildTaskListLayoutNextFrame()
{
yield return null;
RebuildTaskListLayoutNow();
layoutRefreshRoutine = null;
}
private void RebuildTaskListLayoutNow()
{
RectTransform target = dailyTaskItemParent as RectTransform;
if (target == null)
{
return;
}
Canvas.ForceUpdateCanvases();
LayoutRebuilder.ForceRebuildLayoutImmediate(target);
Canvas.ForceUpdateCanvases();
}
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;
}
}
}