251 lines
9.4 KiB
C#

using System;
using UnityEngine;
using static BulletHellTemplate.PlayerSave;
namespace BulletHellTemplate
{
/// <summary>
/// Manages daily rewards UI and claiming logic.
/// Firebase calls are delegated to BackendManager for server saving,
/// while local data is stored in PlayerSave.
/// </summary>
public class DayleRewardManager : MonoBehaviour
{
[Header("UI Prefabs and Containers")]
[Tooltip("All daily reward items for each day.")]
public RewardItem[] rewardItems;
[Tooltip("Prefab used to display each reward entry.")]
public RewardEntry rewardEntryPrefab;
[Tooltip("Parent transform to hold all spawned reward entries.")]
public Transform rewardsContainer;
[Tooltip("Popup shown when a reward is claimed.")]
public RewardPopup rewardPopup;
private DailyRewardsData localDailyData;
private int currentDayIndex;
private string currentLang;
/// <summary>
/// Called when the object becomes enabled.
/// Ensures data is loaded from Firebase if needed,
/// then displays the local daily rewards data.
/// </summary>
private async void OnEnable()
{
currentLang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage();
// Load daily rewards data from local storage
localDailyData = PlayerSave.GetDailyRewardsLocal();
Debug.Log($"[DayleRewardManager] Now (local) = {DateTime.Now} / " +
$"firstClaimDate (localDailyData) = {localDailyData.firstClaimDate} / " +
$"(Now.Date - firstClaimDate.Date) = {(DateTime.Now.Date - localDailyData.firstClaimDate.Date).TotalDays}");
// Calculate how many days have passed since firstClaimDate
TimeSpan timeSinceFirstClaim = DateTime.Now.Date - localDailyData.firstClaimDate.Date;
currentDayIndex = (int)timeSinceFirstClaim.TotalDays;
Debug.Log($"[DayleRewardManager] currentDayIndex = {currentDayIndex}");
// Check if user surpassed total daily rewards
if (currentDayIndex >= rewardItems.Length)
{
currentDayIndex = rewardItems.Length - 1;
}
// Build UI
DisplayRewards();
}
/// <summary>
/// Builds the UI for daily rewards, enabling claim when appropriate.
/// </summary>
private void DisplayRewards()
{
// Clear old entries
if (rewardsContainer != null)
{
foreach (Transform child in rewardsContainer)
{
Destroy(child.gameObject);
}
}
if (rewardItems == null || rewardItems.Length == 0)
{
Debug.LogWarning("No daily rewards configured.");
return;
}
for (int i = 0; i < rewardItems.Length; i++)
{
RewardEntry entry = Instantiate(rewardEntryPrefab, rewardsContainer);
entry.Setup(
rewardItems[i].icon,
rewardItems[i].title,
rewardItems[i].description,
$"Day {i + 1}",
i + 1
);
// If already claimed
if (localDailyData.claimedRewards.Contains(i))
{
entry.SetClaimed();
}
// If day index is within or equal to currentDayIndex, enable claim (if not claimed)
else if (i <= currentDayIndex)
{
int dayIndex = i;
entry.EnableClaimButton(() => ClaimReward(dayIndex));
}
else
{
// Future days
entry.SetLocked();
}
}
}
/// <summary>
/// Claims the specified daily reward day,
/// then saves locally and on Firebase.
/// </summary>
private async void ClaimReward(int dayIndex)
{
// Already claimed?
if (localDailyData.claimedRewards.Contains(dayIndex))
{
Debug.LogWarning($"Reward for day {dayIndex + 1} is already claimed.");
return;
}
// If it's a future day, do not allow
if (dayIndex > currentDayIndex)
{
Debug.LogWarning($"Cannot claim day {dayIndex + 1} yet.");
return;
}
// Add to claimed
localDailyData.claimedRewards.Add(dayIndex);
// Show popup
RewardItem reward = rewardItems[dayIndex];
if (rewardPopup != null)
{
string titleTranslated = GetTranslatedString(
reward.titleTranslated,
reward.title,
currentLang
);
string descriptionTranslated = GetTranslatedString(
reward.descriptionTranslated,
reward.description,
currentLang
);
rewardPopup.Setup(reward.icon, titleTranslated, descriptionTranslated);
}
// Award in-game
AwardReward(reward);
// Save locally
PlayerSave.SetDailyRewardsLocal(localDailyData);
// Refresh UI
DisplayRewards();
// Also save to Firebase
await BackendManager.Singleton.SaveDailyRewardsDataAsync(localDailyData);
}
/// <summary>
/// Gives the actual reward to the player, e.g. currency or items.
/// </summary>
private void AwardReward(RewardItem reward)
{
switch (reward.rewardType)
{
case RewardType.Currency:
int currentAmount = MonetizationManager.GetCurrency(reward.currencyRewards[0].coinID);
int newAmount = currentAmount + reward.amount;
MonetizationManager.SetCurrency(reward.currencyRewards[0].coinID, newAmount);
break;
default:
BattlePassItem tempPassItem = ScriptableObject.CreateInstance<BattlePassItem>();
tempPassItem.passId = "Reward_" + reward.rewardId;
tempPassItem.itemTitle = reward.title;
tempPassItem.itemDescription = reward.description ?? "Reward from Daily Rewards.";
tempPassItem.itemIcon = reward.icon;
tempPassItem.rewardTier = BattlePassItem.RewardTier.Free;
switch (reward.rewardType)
{
case RewardType.Icon:
tempPassItem.rewardType = BattlePassItem.RewardType.IconReward;
tempPassItem.iconReward = reward.iconRewards[0];
break;
case RewardType.Frame:
tempPassItem.rewardType = BattlePassItem.RewardType.FrameReward;
tempPassItem.frameReward = reward.frameRewards[0];
break;
case RewardType.Character:
tempPassItem.rewardType = BattlePassItem.RewardType.CharacterReward;
tempPassItem.characterData = new CharacterData[] { reward.characterRewards[0] };
break;
case RewardType.InventoryItem:
tempPassItem.rewardType = BattlePassItem.RewardType.InventoryItemReward;
tempPassItem.inventoryItems = new InventoryItem[] { reward.inventoryItems[0] };
break;
}
MonetizationManager.Singleton.BattlePassUnlockItem(tempPassItem);
break;
}
}
/// <summary>
/// Retrieves a translated string or returns the fallback if not found.
/// </summary>
public string GetTranslatedString(NameTranslatedByLanguage[] translations, string fallback, string currentLang)
{
if (translations != null)
{
foreach (var trans in translations)
{
if (!string.IsNullOrEmpty(trans.LanguageId)
&& trans.LanguageId.Equals(currentLang)
&& !string.IsNullOrEmpty(trans.Translate))
{
return trans.Translate;
}
}
}
return fallback;
}
/// <summary>
/// Retrieves a translated description string or returns the fallback if not found.
/// </summary>
public string GetTranslatedString(DescriptionTranslatedByLanguage[] translations, string fallback, string currentLang)
{
if (translations != null)
{
foreach (var trans in translations)
{
if (!string.IsNullOrEmpty(trans.LanguageId)
&& trans.LanguageId.Equals(currentLang)
&& !string.IsNullOrEmpty(trans.Translate))
{
return trans.Translate;
}
}
}
return fallback;
}
}
}