ADded fusion and new SDK
This commit is contained in:
parent
1b12c8ab46
commit
344c0cdde3
8
.idea/.idea.BulletHell/.idea/indexLayout.xml
generated
Normal file
8
.idea/.idea.BulletHell/.idea/indexLayout.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders />
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
</project>
|
6
.idea/.idea.BulletHell/.idea/vcs.xml
generated
Normal file
6
.idea/.idea.BulletHell/.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed70b82c28b9c144cb980dfa5702e03b
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/RewardDailyEntry.prefab
|
||||
uploadId: 777582
|
@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6fda033c0738a634eb415877fd65058d
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/RewardNewEntry.prefab
|
||||
uploadId: 777582
|
@ -0,0 +1,28 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DailyReward 1
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward1
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a278160a6c7f8544a3768e0bcc4553d
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/Rewards/DailyReward 1.asset
|
||||
uploadId: 777582
|
@ -0,0 +1,28 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DailyReward 10
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward10
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 500 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 500
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 06c0221dd1e929c47b05ee18757fe798
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/Rewards/DailyReward 10.asset
|
||||
uploadId: 777582
|
@ -0,0 +1,28 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DailyReward 2
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward2
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7bb80a829634a834f9581e598abec835
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/Rewards/DailyReward 2.asset
|
||||
uploadId: 777582
|
@ -0,0 +1,28 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DailyReward 3
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward3
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8772999151e122244a4b4e1e0740ae46
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/Rewards/DailyReward 3.asset
|
||||
uploadId: 777582
|
@ -0,0 +1,28 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DailyReward 4
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward4
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 425913de335469442b2439a25a78a172
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/Rewards/DailyReward 4.asset
|
||||
uploadId: 777582
|
@ -0,0 +1,28 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DailyReward 5
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward5
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 69da3ac32b731d2488c0f41a860c1498
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/Rewards/DailyReward 5.asset
|
||||
uploadId: 777582
|
@ -0,0 +1,28 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DailyReward 6
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward6
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 115596442aeedba44a43288cfc2796d5
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/Rewards/DailyReward 6.asset
|
||||
uploadId: 777582
|
@ -0,0 +1,28 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DailyReward 7
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward7
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4641227f3470f34c9a62b08d0dc99a4
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/Rewards/DailyReward 7.asset
|
||||
uploadId: 777582
|
@ -0,0 +1,28 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DailyReward 8
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward8
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6698d9bc522453a42a9edccae0d42f1f
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/Rewards/DailyReward 8.asset
|
||||
uploadId: 777582
|
@ -0,0 +1,28 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DailyReward 9
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward9
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a1b7ad7800274e42b157224b6e73e6a
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/Rewards/DailyReward 9.asset
|
||||
uploadId: 777582
|
@ -0,0 +1,367 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using static BulletHellTemplate.PlayerSave;
|
||||
|
||||
namespace BulletHellTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Displays and claims **Daily Rewards** using a *local-first, server-confirmed* flow.
|
||||
///
|
||||
/// Workflow:
|
||||
/// 1. UI is built from locally cached <see cref="DailyRewardsData"/> (PlayerSave).
|
||||
/// 2. When the player presses "Claim", minimal local validation runs (already claimed? already today? correct sequence?).
|
||||
/// 3. If local checks pass, a server claim is sent via <see cref="BackendManager.Service"/>.
|
||||
/// 4. On server success, reward is applied (inside the backend claim extension) and local cache is updated.
|
||||
/// 5. UI refreshes.
|
||||
///
|
||||
/// This approach reduces server calls while keeping the server authoritative over the final grant.
|
||||
/// </summary>
|
||||
public sealed class DailyRewardManager : MonoBehaviour
|
||||
{
|
||||
/*────────────────────────── Inspector ──────────────────────────*/
|
||||
|
||||
[Header("UI Prefabs & Containers")]
|
||||
[Tooltip("Prefab used to display each daily reward entry.")]
|
||||
public RewardEntry rewardEntryPrefab;
|
||||
|
||||
[Tooltip("Parent transform that will hold all spawned daily reward entries.")]
|
||||
public Transform rewardsContainer;
|
||||
|
||||
[Tooltip("Popup shown when a reward is successfully claimed.")]
|
||||
public RewardPopup rewardPopup;
|
||||
|
||||
/*────────────────────────── Private State ──────────────────────*/
|
||||
|
||||
private DailyRewardsData localDailyData;
|
||||
private RewardItem[] rewardItems;
|
||||
private string currentLang;
|
||||
|
||||
// Cached flags used when building UI
|
||||
private bool _alreadyClaimedToday;
|
||||
private int _nextIndex; // index expected to be claimed next (sequential)
|
||||
private int _daysSinceFirstClaim; // used only for visual gating
|
||||
|
||||
/*────────────────────────── Unity Events ───────────────────────*/
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
currentLang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage();
|
||||
rewardItems = GameInstance.Singleton.dailyRewardItems;
|
||||
|
||||
// Pull local cache
|
||||
localDailyData = PlayerSave.GetDailyRewardsLocal();
|
||||
|
||||
// Optionally perform a lazy local reset if the cycle completed AND at least 1 new day has passed.
|
||||
TryLocalCycleResetIfNeeded();
|
||||
|
||||
// Precompute visual gating values
|
||||
_alreadyClaimedToday = localDailyData.lastClaimDate != DateTime.MinValue &&
|
||||
localDailyData.lastClaimDate.Date == DateTime.Now.Date;
|
||||
|
||||
_nextIndex = localDailyData.claimedRewards.Count;
|
||||
|
||||
if (localDailyData.firstClaimDate != DateTime.MinValue)
|
||||
{
|
||||
_daysSinceFirstClaim = Mathf.Max(
|
||||
0,
|
||||
(int)(DateTime.Now.Date - localDailyData.firstClaimDate.Date).TotalDays
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
_daysSinceFirstClaim = 0;
|
||||
}
|
||||
|
||||
BuildUI();
|
||||
}
|
||||
|
||||
/*────────────────────────── UI Build ───────────────────────────*/
|
||||
|
||||
/// <summary>
|
||||
/// Spawns one entry per configured daily reward and wires up claim buttons
|
||||
/// according to the current local state.
|
||||
/// </summary>
|
||||
private void BuildUI()
|
||||
{
|
||||
// Clear previous children
|
||||
if (rewardsContainer != null)
|
||||
{
|
||||
for (int i = rewardsContainer.childCount - 1; i >= 0; --i)
|
||||
Destroy(rewardsContainer.GetChild(i).gameObject);
|
||||
}
|
||||
|
||||
if (rewardItems == null || rewardItems.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("[DailyRewardManager] No daily rewards configured.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < rewardItems.Length; i++)
|
||||
{
|
||||
var def = rewardItems[i];
|
||||
RewardEntry entry = Instantiate(rewardEntryPrefab, rewardsContainer);
|
||||
|
||||
// Localized display strings
|
||||
string title = GetTranslatedString(def.titleTranslated, def.title, currentLang);
|
||||
string description = GetTranslatedString(def.descriptionTranslated, def.description, currentLang);
|
||||
|
||||
// Display day label (1-based for player clarity)
|
||||
entry.Setup(
|
||||
def.icon,
|
||||
title,
|
||||
description,
|
||||
$"Day {i + 1}",
|
||||
i + 1
|
||||
);
|
||||
|
||||
// State assignment
|
||||
if (localDailyData.claimedRewards.Contains(i))
|
||||
{
|
||||
entry.SetClaimed();
|
||||
continue;
|
||||
}
|
||||
|
||||
// If already claimed today, everything else is locked
|
||||
if (_alreadyClaimedToday)
|
||||
{
|
||||
entry.SetLocked();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Sequential gating: allow claim only for the next expected index
|
||||
if (i == _nextIndex && i <= _daysSinceFirstClaim)
|
||||
{
|
||||
int capture = i; // closure
|
||||
entry.EnableClaimButton(() => OnClaimButtonPressed(capture));
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.SetLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*────────────────────────── Claim Flow ─────────────────────────*/
|
||||
|
||||
/// <summary>
|
||||
/// Called by UI button; runs local validation and (if passed) performs an async server claim.
|
||||
/// </summary>
|
||||
private async void OnClaimButtonPressed(int dayIndex)
|
||||
{
|
||||
// Fast local validation; reduces unnecessary server requests.
|
||||
if (!LocalCanClaim(dayIndex, out var failCode))
|
||||
{
|
||||
HandleClaimFail(failCode, dayIndex, isPreServer: true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Build a temporary BattlePassItem to describe reward for local application & popup visuals.
|
||||
RewardItem rewardDef = rewardItems[dayIndex];
|
||||
BattlePassItem bpItem = BuildBattlePassMirror(rewardDef);
|
||||
|
||||
// Perform server-authorized claim.
|
||||
RequestResult result = await BackendManager.Service.ClaimDailyRewardAsync(dayIndex, bpItem);
|
||||
|
||||
if (!result.Success)
|
||||
{
|
||||
HandleClaimFail(result.Reason, dayIndex, isPreServer: false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update local cache on success
|
||||
if (!localDailyData.claimedRewards.Contains(dayIndex))
|
||||
localDailyData.claimedRewards.Add(dayIndex);
|
||||
|
||||
if (localDailyData.claimedRewards.Count == 1)
|
||||
localDailyData.firstClaimDate = DateTime.Now.Date;
|
||||
|
||||
localDailyData.lastClaimDate = DateTime.Now.Date;
|
||||
PlayerSave.SetDailyRewardsLocal(localDailyData);
|
||||
|
||||
// Show popup (optional)
|
||||
if (rewardPopup != null)
|
||||
{
|
||||
string title = GetTranslatedString(rewardDef.titleTranslated, rewardDef.title, currentLang);
|
||||
string description = GetTranslatedString(rewardDef.descriptionTranslated, rewardDef.description, currentLang);
|
||||
rewardPopup.Setup(rewardDef.icon, title, description);
|
||||
}
|
||||
|
||||
// Rebuild UI with updated data
|
||||
OnEnable(); // quick refresh
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Minimal local validation: already claimed? already claimed today? correct sequence?
|
||||
/// failCode: "0" (already) / "1" (not available) / null (ok).
|
||||
/// </summary>
|
||||
private bool LocalCanClaim(int dayIndex, out string failCode)
|
||||
{
|
||||
failCode = null;
|
||||
|
||||
int total = rewardItems?.Length ?? 0;
|
||||
if (dayIndex < 0 || dayIndex >= total)
|
||||
{
|
||||
failCode = "1";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (localDailyData.claimedRewards.Contains(dayIndex))
|
||||
{
|
||||
failCode = "0";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (localDailyData.lastClaimDate != DateTime.MinValue &&
|
||||
localDailyData.lastClaimDate.Date == DateTime.Now.Date)
|
||||
{
|
||||
failCode = "0"; // already claimed today
|
||||
return false;
|
||||
}
|
||||
|
||||
int expected = localDailyData.claimedRewards.Count;
|
||||
if (dayIndex > expected)
|
||||
{
|
||||
failCode = "1"; // trying to skip days
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles failed claim attempts (local or server) with consistent logging.
|
||||
/// </summary>
|
||||
private void HandleClaimFail(string reasonCode, int dayIndex, bool isPreServer)
|
||||
{
|
||||
string prefix = isPreServer ? "[DailyRewardManager][Local]" : "[DailyRewardManager][Server]";
|
||||
switch (reasonCode)
|
||||
{
|
||||
case "0":
|
||||
Debug.LogWarning($"{prefix} Day {dayIndex + 1} already claimed.");
|
||||
break;
|
||||
case "1":
|
||||
Debug.LogWarning($"{prefix} Day {dayIndex + 1} not available yet.");
|
||||
break;
|
||||
default:
|
||||
Debug.LogWarning($"{prefix} Claim failed (code:{reasonCode}).");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*────────────────────────── Reward Construction ─────────────────*/
|
||||
|
||||
/// <summary>
|
||||
/// Builds a minimal <see cref="BattlePassItem"/> mirror from a <see cref="RewardItem"/> definition.
|
||||
/// Used only to route through shared reward‑apply code paths.
|
||||
/// </summary>
|
||||
private BattlePassItem BuildBattlePassMirror(RewardItem reward)
|
||||
{
|
||||
BattlePassItem temp = ScriptableObject.CreateInstance<BattlePassItem>();
|
||||
temp.passId = "DailyReward_" + reward.rewardId;
|
||||
temp.itemTitle = reward.title;
|
||||
temp.itemDescription = reward.description ?? "Daily reward.";
|
||||
temp.itemIcon = reward.icon;
|
||||
temp.rewardTier = BattlePassItem.RewardTier.Free;
|
||||
|
||||
switch (reward.rewardType)
|
||||
{
|
||||
case RewardType.Currency:
|
||||
temp.rewardType = BattlePassItem.RewardType.CurrencyReward;
|
||||
temp.currencyReward = new CurrencyReward
|
||||
{
|
||||
currency = reward.currencyRewards[0],
|
||||
amount = reward.amount
|
||||
};
|
||||
break;
|
||||
|
||||
case RewardType.Icon:
|
||||
temp.rewardType = BattlePassItem.RewardType.IconReward;
|
||||
temp.iconReward = reward.iconRewards[0];
|
||||
break;
|
||||
|
||||
case RewardType.Frame:
|
||||
temp.rewardType = BattlePassItem.RewardType.FrameReward;
|
||||
temp.frameReward = reward.frameRewards[0];
|
||||
break;
|
||||
|
||||
case RewardType.Character:
|
||||
temp.rewardType = BattlePassItem.RewardType.CharacterReward;
|
||||
temp.characterData = new CharacterData[] { reward.characterRewards[0] };
|
||||
break;
|
||||
|
||||
case RewardType.InventoryItem:
|
||||
temp.rewardType = BattlePassItem.RewardType.InventoryItemReward;
|
||||
temp.inventoryItems = new InventoryItem[] { reward.inventoryItems[0] };
|
||||
break;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
/*────────────────────────── Helpers ─────────────────────────────*/
|
||||
|
||||
/// <summary>
|
||||
/// For UX: after a full cycle is completed, clear local progress if at least one new calendar day has passed.
|
||||
/// This does NOT contact the server; server still validates claims.
|
||||
/// </summary>
|
||||
private void TryLocalCycleResetIfNeeded()
|
||||
{
|
||||
int total = GameInstance.Singleton.dailyRewardItems?.Length ?? 0;
|
||||
if (total <= 0) return;
|
||||
|
||||
if (localDailyData == null)
|
||||
localDailyData = PlayerSave.GetDailyRewardsLocal();
|
||||
|
||||
// Completed cycle?
|
||||
if (localDailyData.claimedRewards.Count < total)
|
||||
return;
|
||||
|
||||
// Wait at least one day after the last claim before resetting locally.
|
||||
if (localDailyData.lastClaimDate == DateTime.MinValue)
|
||||
return;
|
||||
|
||||
if ((DateTime.Now.Date - localDailyData.lastClaimDate.Date).TotalDays < 1d)
|
||||
return;
|
||||
|
||||
localDailyData.claimedRewards.Clear();
|
||||
localDailyData.firstClaimDate = DateTime.Now.Date;
|
||||
localDailyData.lastClaimDate = DateTime.MinValue;
|
||||
PlayerSave.SetDailyRewardsLocal(localDailyData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a translated string (title) or the fallback if not found.
|
||||
/// </summary>
|
||||
public string GetTranslatedString(NameTranslatedByLanguage[] translations, string fallback, string lang)
|
||||
{
|
||||
if (translations != null)
|
||||
{
|
||||
foreach (var t in translations)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(t.LanguageId) &&
|
||||
t.LanguageId.Equals(lang, StringComparison.OrdinalIgnoreCase) &&
|
||||
!string.IsNullOrEmpty(t.Translate))
|
||||
return t.Translate;
|
||||
}
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a translated string (description) or the fallback if not found.
|
||||
/// </summary>
|
||||
public string GetTranslatedString(DescriptionTranslatedByLanguage[] translations, string fallback, string lang)
|
||||
{
|
||||
if (translations != null)
|
||||
{
|
||||
foreach (var t in translations)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(t.LanguageId) &&
|
||||
t.LanguageId.Equals(lang, StringComparison.OrdinalIgnoreCase) &&
|
||||
!string.IsNullOrEmpty(t.Translate))
|
||||
return t.Translate;
|
||||
}
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 380ed0821da70594d9810d7ef704eda5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/Scripts/DailyRewardManager.cs
|
||||
uploadId: 777582
|
@ -0,0 +1,351 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using static BulletHellTemplate.PlayerSave;
|
||||
|
||||
namespace BulletHellTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Displays and claims **New Player Rewards** with a *one-claim-per-day* rule.
|
||||
///
|
||||
/// Design:
|
||||
/// • Rewards unlock over time based on days since account creation.
|
||||
/// • Player may fall behind (missed logins) but can only claim **one** unclaimed day per calendar day.
|
||||
/// (Catch-up over multiple days.)
|
||||
/// • UI is built from locally cached <see cref="NewPlayerRewardsData"/>.
|
||||
/// • On claim click → local validation → server validation → local cache update → UI refresh.
|
||||
/// </summary>
|
||||
public sealed class NewPlayerRewardManager : MonoBehaviour
|
||||
{
|
||||
/*────────────────────────── Inspector ──────────────────────────*/
|
||||
|
||||
[Header("UI Prefabs & Containers")]
|
||||
[Tooltip("Prefab used to display each new-player reward entry.")]
|
||||
public RewardEntry rewardEntryPrefab;
|
||||
|
||||
[Tooltip("Parent transform that will hold all spawned new-player reward entries.")]
|
||||
public Transform rewardsContainer;
|
||||
|
||||
[Tooltip("Popup shown when a new-player reward is successfully claimed.")]
|
||||
public RewardPopup rewardPopup;
|
||||
|
||||
[Header("Settings")]
|
||||
[Tooltip("Optional hard cap for new-player reward days. If <=0, GameInstance data length is used.")]
|
||||
public int totalRewardDaysOverride = 0;
|
||||
|
||||
/*────────────────────────── Private State ──────────────────────*/
|
||||
|
||||
private NewPlayerRewardsData localNewPlayerData;
|
||||
private RewardItem[] rewardItems;
|
||||
private string currentLang;
|
||||
|
||||
// Cached per-enable state
|
||||
private bool _alreadyClaimedToday;
|
||||
private int _daysSinceCreation;
|
||||
private int _nextUnclaimedIndex; // sequential catch-up target
|
||||
|
||||
/*────────────────────────── Unity Events ───────────────────────*/
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
currentLang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage();
|
||||
rewardItems = GameInstance.Singleton.newPlayerRewardItems;
|
||||
|
||||
// Pull local cache
|
||||
localNewPlayerData = PlayerSave.GetNewPlayerRewardsLocal();
|
||||
|
||||
// Days since account creation
|
||||
if (localNewPlayerData.accountCreationDate != DateTime.MinValue)
|
||||
{
|
||||
_daysSinceCreation = Mathf.Max(
|
||||
0,
|
||||
(int)(DateTime.Now.Date - localNewPlayerData.accountCreationDate.Date).TotalDays
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
_daysSinceCreation = 0;
|
||||
}
|
||||
|
||||
// 1/day gating: already claimed today?
|
||||
_alreadyClaimedToday = localNewPlayerData.lastClaimDate != DateTime.MinValue &&
|
||||
localNewPlayerData.lastClaimDate.Date == DateTime.Now.Date;
|
||||
|
||||
// Next unclaimed reward index (sequential catch-up)
|
||||
_nextUnclaimedIndex = localNewPlayerData.claimedRewards.Count;
|
||||
|
||||
BuildUI();
|
||||
}
|
||||
|
||||
/*────────────────────────── UI Build ───────────────────────────*/
|
||||
|
||||
/// <summary>
|
||||
/// Spawns UI entries for each configured new-player reward and enables the claim
|
||||
/// button only on the **next unclaimed** day (if unlocked by time and not claimed today).
|
||||
/// </summary>
|
||||
private void BuildUI()
|
||||
{
|
||||
// Clear previous
|
||||
if (rewardsContainer != null)
|
||||
{
|
||||
for (int i = rewardsContainer.childCount - 1; i >= 0; --i)
|
||||
Destroy(rewardsContainer.GetChild(i).gameObject);
|
||||
}
|
||||
|
||||
if (rewardItems == null || rewardItems.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("[NewPlayerRewardManager] No new-player rewards configured.");
|
||||
return;
|
||||
}
|
||||
|
||||
int totalCap = totalRewardDaysOverride > 0
|
||||
? Mathf.Min(totalRewardDaysOverride, rewardItems.Length)
|
||||
: rewardItems.Length;
|
||||
|
||||
for (int i = 0; i < totalCap; i++)
|
||||
{
|
||||
var def = rewardItems[i];
|
||||
RewardEntry entry = Instantiate(rewardEntryPrefab, rewardsContainer);
|
||||
|
||||
// Localized UI text
|
||||
string title = GetTranslatedString(def.titleTranslated, def.title, currentLang);
|
||||
string description = GetTranslatedString(def.descriptionTranslated, def.description, currentLang);
|
||||
|
||||
entry.Setup(
|
||||
def.icon,
|
||||
title,
|
||||
description,
|
||||
$"Day {i + 1}",
|
||||
i + 1
|
||||
);
|
||||
|
||||
// Already claimed?
|
||||
if (localNewPlayerData.claimedRewards.Contains(i))
|
||||
{
|
||||
entry.SetClaimed();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Locked because already claimed today's new-player reward?
|
||||
if (_alreadyClaimedToday)
|
||||
{
|
||||
entry.SetLocked();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only the NEXT unclaimed reward can be claimed today (catch-up)
|
||||
if (i == _nextUnclaimedIndex && i <= _daysSinceCreation)
|
||||
{
|
||||
int capture = i;
|
||||
entry.EnableClaimButton(() => OnClaimButtonPressed(capture));
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.SetLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*────────────────────────── Claim Flow ─────────────────────────*/
|
||||
|
||||
/// <summary>
|
||||
/// Triggered by UI button; runs local validation then performs server claim.
|
||||
/// </summary>
|
||||
private async void OnClaimButtonPressed(int dayIndex)
|
||||
{
|
||||
if (!LocalCanClaim(dayIndex, out var failCode))
|
||||
{
|
||||
HandleClaimFail(failCode, dayIndex, isPreServer: true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Build a BattlePass mirror so we can reuse reward-apply logic
|
||||
RewardItem rewardDef = rewardItems[dayIndex];
|
||||
BattlePassItem bpItem = BuildBattlePassMirror(rewardDef);
|
||||
|
||||
// Server validation + grant
|
||||
RequestResult result = await BackendManager.Service.ClaimNewPlayerRewardAsync(dayIndex, bpItem);
|
||||
|
||||
if (!result.Success)
|
||||
{
|
||||
HandleClaimFail(result.Reason, dayIndex, isPreServer: false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update local cache
|
||||
if (!localNewPlayerData.claimedRewards.Contains(dayIndex))
|
||||
localNewPlayerData.claimedRewards.Add(dayIndex);
|
||||
localNewPlayerData.lastClaimDate = DateTime.Now.Date;
|
||||
PlayerSave.SetNewPlayerRewardsLocal(localNewPlayerData);
|
||||
|
||||
// Popup
|
||||
if (rewardPopup != null)
|
||||
{
|
||||
string title = GetTranslatedString(rewardDef.titleTranslated, rewardDef.title, currentLang);
|
||||
string description = GetTranslatedString(rewardDef.descriptionTranslated, rewardDef.description, currentLang);
|
||||
rewardPopup.Setup(rewardDef.icon, title, description);
|
||||
}
|
||||
|
||||
// Refresh UI
|
||||
OnEnable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Minimal local gating for *one-per-day* catch-up.
|
||||
/// failCode: "0" (already) / "1" (not available) / null (ok).
|
||||
/// </summary>
|
||||
private bool LocalCanClaim(int dayIndex, out string failCode)
|
||||
{
|
||||
failCode = null;
|
||||
|
||||
int totalCap = totalRewardDaysOverride > 0
|
||||
? Mathf.Min(totalRewardDaysOverride, rewardItems.Length)
|
||||
: rewardItems.Length;
|
||||
|
||||
// Range
|
||||
if (dayIndex < 0 || dayIndex >= totalCap)
|
||||
{
|
||||
failCode = "1";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Already claimed?
|
||||
if (localNewPlayerData.claimedRewards.Contains(dayIndex))
|
||||
{
|
||||
failCode = "0";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Already claimed a new-player reward today?
|
||||
if (localNewPlayerData.lastClaimDate != DateTime.MinValue &&
|
||||
localNewPlayerData.lastClaimDate.Date == DateTime.Now.Date)
|
||||
{
|
||||
failCode = "0"; // already today
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sequential catch-up: must be the next unclaimed index
|
||||
int expected = localNewPlayerData.claimedRewards.Count;
|
||||
if (dayIndex != expected)
|
||||
{
|
||||
failCode = "1";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Must be unlocked by time
|
||||
if (dayIndex > _daysSinceCreation)
|
||||
{
|
||||
failCode = "1";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles failed claim attempts (local or server) with consistent logging.
|
||||
/// </summary>
|
||||
private void HandleClaimFail(string reasonCode, int dayIndex, bool isPreServer)
|
||||
{
|
||||
string prefix = isPreServer ? "[NewPlayerRewardManager][Local]" : "[NewPlayerRewardManager][Server]";
|
||||
switch (reasonCode)
|
||||
{
|
||||
case "0":
|
||||
Debug.LogWarning($"{prefix} Day {dayIndex + 1} already claimed.");
|
||||
break;
|
||||
case "1":
|
||||
Debug.LogWarning($"{prefix} Day {dayIndex + 1} not available yet.");
|
||||
break;
|
||||
default:
|
||||
Debug.LogWarning($"{prefix} Claim failed (code:{reasonCode}).");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*────────────────────────── Reward Construction ─────────────────*/
|
||||
|
||||
/// <summary>
|
||||
/// Builds a minimal <see cref="BattlePassItem"/> mirror from a <see cref="RewardItem"/> definition.
|
||||
/// Used only to route through shared reward‑apply code paths.
|
||||
/// </summary>
|
||||
private BattlePassItem BuildBattlePassMirror(RewardItem reward)
|
||||
{
|
||||
BattlePassItem temp = ScriptableObject.CreateInstance<BattlePassItem>();
|
||||
temp.passId = "NewPlayerReward_" + reward.rewardId;
|
||||
temp.itemTitle = reward.title;
|
||||
temp.itemDescription = reward.description ?? "New-player reward.";
|
||||
temp.itemIcon = reward.icon;
|
||||
temp.rewardTier = BattlePassItem.RewardTier.Free;
|
||||
|
||||
switch (reward.rewardType)
|
||||
{
|
||||
case RewardType.Currency:
|
||||
temp.rewardType = BattlePassItem.RewardType.CurrencyReward;
|
||||
temp.currencyReward = new CurrencyReward
|
||||
{
|
||||
currency = reward.currencyRewards[0],
|
||||
amount = reward.amount
|
||||
};
|
||||
break;
|
||||
|
||||
case RewardType.Icon:
|
||||
temp.rewardType = BattlePassItem.RewardType.IconReward;
|
||||
temp.iconReward = reward.iconRewards[0];
|
||||
break;
|
||||
|
||||
case RewardType.Frame:
|
||||
temp.rewardType = BattlePassItem.RewardType.FrameReward;
|
||||
temp.frameReward = reward.frameRewards[0];
|
||||
break;
|
||||
|
||||
case RewardType.Character:
|
||||
temp.rewardType = BattlePassItem.RewardType.CharacterReward;
|
||||
temp.characterData = new CharacterData[] { reward.characterRewards[0] };
|
||||
break;
|
||||
|
||||
case RewardType.InventoryItem:
|
||||
temp.rewardType = BattlePassItem.RewardType.InventoryItemReward;
|
||||
temp.inventoryItems = new InventoryItem[] { reward.inventoryItems[0] };
|
||||
break;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
/*────────────────────────── Helpers ─────────────────────────────*/
|
||||
|
||||
/// <summary>
|
||||
/// Returns a translated string (title) or the fallback if not found.
|
||||
/// </summary>
|
||||
public string GetTranslatedString(NameTranslatedByLanguage[] translations, string fallback, string lang)
|
||||
{
|
||||
if (translations != null)
|
||||
{
|
||||
foreach (var t in translations)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(t.LanguageId) &&
|
||||
t.LanguageId.Equals(lang, StringComparison.OrdinalIgnoreCase) &&
|
||||
!string.IsNullOrEmpty(t.Translate))
|
||||
return t.Translate;
|
||||
}
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a translated string (description) or the fallback if not found.
|
||||
/// </summary>
|
||||
public string GetTranslatedString(DescriptionTranslatedByLanguage[] translations, string fallback, string lang)
|
||||
{
|
||||
if (translations != null)
|
||||
{
|
||||
foreach (var t in translations)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(t.LanguageId) &&
|
||||
t.LanguageId.Equals(lang, StringComparison.OrdinalIgnoreCase) &&
|
||||
!string.IsNullOrEmpty(t.Translate))
|
||||
return t.Translate;
|
||||
}
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da920075f2f1e8a4f9ad88a4f9e512c5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/Scripts/NewAccountRewardManager.cs
|
||||
uploadId: 777582
|
@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd7692836f72bef4f96f118bce19c72a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/Scripts/RewardEntry.cs
|
||||
uploadId: 777582
|
@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c700776657e0bb34b81e9f4b04bef575
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/Scripts/RewardItem.cs
|
||||
uploadId: 777582
|
@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 054a15360702db9439f4a29003cc3fa2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/Scripts/RewardPopup.cs
|
||||
uploadId: 777582
|
@ -0,0 +1,47 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BulletHellTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles saving and loading reward data from Firebase and PlayerPrefs.
|
||||
/// Prevents multiple calls to Firebase during initialization.
|
||||
/// </summary>
|
||||
public static class RewardSaveManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Loads rewards from Firestore for a specified collection and invokes a callback with the data.
|
||||
/// </summary>
|
||||
public static void LoadRewards(string collectionName, System.Action<Dictionary<string, object>> onLoaded)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves rewards to Firestore for a specified collection, and also stores them locally in PlayerPrefs.
|
||||
/// </summary>
|
||||
public static void SaveRewards(string collectionName, Dictionary<string, object> data)
|
||||
{
|
||||
SaveRewardsLocally(collectionName, data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves rewards data locally in PlayerPrefs as JSON.
|
||||
/// </summary>
|
||||
private static void SaveRewardsLocally(string collectionName, Dictionary<string, object> data)
|
||||
{
|
||||
string json = JsonUtility.ToJson(data);
|
||||
PlayerPrefs.SetString(collectionName, json);
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads rewards data from PlayerPrefs if available.
|
||||
/// </summary>
|
||||
public static Dictionary<string, object> LoadRewardsLocally(string collectionName)
|
||||
{
|
||||
string json = PlayerPrefs.GetString(collectionName, null);
|
||||
return string.IsNullOrEmpty(json) ? null : JsonUtility.FromJson<Dictionary<string, object>>(json);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14a1f9538dc44a444b86779f45b4962e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/Scripts/RewardSaveManager.cs
|
||||
uploadId: 777582
|
@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 20e295e3dffe0ec4488423fbac55e740
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/DailyRewards/UINewAccountReward.prefab
|
||||
uploadId: 777582
|
@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed70b82c28b9c144cb980dfa5702e03b
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6fda033c0738a634eb415877fd65058d
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,28 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DayleReward 1
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward1
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a278160a6c7f8544a3768e0bcc4553d
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,28 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DayleReward 10
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward10
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 500 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 500
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 06c0221dd1e929c47b05ee18757fe798
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,28 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DayleReward 2
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward2
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7bb80a829634a834f9581e598abec835
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,28 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DayleReward 3
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward3
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8772999151e122244a4b4e1e0740ae46
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,28 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DayleReward 4
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward4
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 425913de335469442b2439a25a78a172
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,28 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DayleReward 5
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward5
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 69da3ac32b731d2488c0f41a860c1498
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,28 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DayleReward 6
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward6
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 115596442aeedba44a43288cfc2796d5
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,28 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DayleReward 7
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward7
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4641227f3470f34c9a62b08d0dc99a4
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,28 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DayleReward 8
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward8
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6698d9bc522453a42a9edccae0d42f1f
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,28 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c700776657e0bb34b81e9f4b04bef575, type: 3}
|
||||
m_Name: DayleReward 9
|
||||
m_EditorClassIdentifier:
|
||||
rewardId: reward9
|
||||
icon: {fileID: 21300000, guid: 8b4ed5f113462ce44a28290ff3d5f8e7, type: 3}
|
||||
title: Diamond
|
||||
titleTranslated: []
|
||||
description: Receive 15 diamonds
|
||||
descriptionTranslated: []
|
||||
rewardType: 0
|
||||
amount: 15
|
||||
currencyRewards:
|
||||
- {fileID: 11400000, guid: b0d79ad1b68bf714f987f3ac5cebb447, type: 2}
|
||||
iconRewards: []
|
||||
frameRewards: []
|
||||
characterRewards: []
|
||||
inventoryItems: []
|
@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a1b7ad7800274e42b157224b6e73e6a
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,250 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74a2deb9e3aaf2549a4286b575d3f7d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,258 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using static BulletHellTemplate.PlayerSave;
|
||||
|
||||
namespace BulletHellTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages the new-account rewards UI and claiming logic.
|
||||
/// All Firebase calls have been moved to BackendManager for server saving,
|
||||
/// and PlayerSave for local data storage.
|
||||
/// </summary>
|
||||
public class NewAccountRewardManager : MonoBehaviour
|
||||
{
|
||||
[Header("Rewards Configuration")]
|
||||
[Tooltip("Rewards for new players, typically one per day.")]
|
||||
public RewardItem[] rewardItems;
|
||||
|
||||
[Header("UI Elements")]
|
||||
[Tooltip("Prefab for displaying each reward in the list.")]
|
||||
public RewardEntry rewardEntryPrefab;
|
||||
|
||||
[Tooltip("Container to hold the reward entries.")]
|
||||
public Transform rewardsContainer;
|
||||
|
||||
[Tooltip("Popup shown when a reward is claimed.")]
|
||||
public RewardPopup rewardPopup;
|
||||
|
||||
[Header("Settings")]
|
||||
[Tooltip("Total days the new player rewards are available.")]
|
||||
public int totalRewardDays = 7;
|
||||
|
||||
private NewPlayerRewardsData localNewPlayerData;
|
||||
private int currentDayIndex;
|
||||
private string currentLang;
|
||||
|
||||
/// <summary>
|
||||
/// Called when the GameObject becomes enabled and active.
|
||||
/// Loads local new-player reward data and displays them.
|
||||
/// </summary>
|
||||
private void OnEnable()
|
||||
{
|
||||
// Retrieve the new-player reward data from local storage
|
||||
localNewPlayerData = PlayerSave.GetNewPlayerRewardsLocal();
|
||||
|
||||
currentLang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage();
|
||||
|
||||
// Calculate how many days since account creation
|
||||
TimeSpan timeSinceCreation = DateTime.Now.Date - localNewPlayerData.accountCreationDate.Date;
|
||||
currentDayIndex = (int)timeSinceCreation.TotalDays;
|
||||
|
||||
DisplayNewPlayerRewards();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays the new player rewards in the UI, enabling claim where applicable.
|
||||
/// </summary>
|
||||
private void DisplayNewPlayerRewards()
|
||||
{
|
||||
// Clear existing entries
|
||||
if (rewardsContainer != null)
|
||||
{
|
||||
foreach (Transform child in rewardsContainer)
|
||||
{
|
||||
Destroy(child.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
if (rewardItems == null || rewardItems.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("No new player rewards are configured.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create entries for each reward day
|
||||
for (int i = 0; i < rewardItems.Length; i++)
|
||||
{
|
||||
RewardEntry entry = Instantiate(rewardEntryPrefab, rewardsContainer);
|
||||
|
||||
// Translate reward title/description
|
||||
string titleTranslated = GetTranslatedString(
|
||||
rewardItems[i].titleTranslated,
|
||||
rewardItems[i].title,
|
||||
currentLang
|
||||
);
|
||||
string descriptionTranslated = GetTranslatedString(
|
||||
rewardItems[i].descriptionTranslated,
|
||||
rewardItems[i].description,
|
||||
currentLang
|
||||
);
|
||||
|
||||
// Setup the UI element
|
||||
entry.Setup(
|
||||
rewardItems[i].icon,
|
||||
titleTranslated,
|
||||
descriptionTranslated,
|
||||
rewardItems[i].rewardId,
|
||||
i + 1
|
||||
);
|
||||
|
||||
// If already claimed
|
||||
if (localNewPlayerData.claimedRewards.Contains(i))
|
||||
{
|
||||
entry.SetClaimed();
|
||||
}
|
||||
// If day index <= currentDayIndex and within totalRewardDays
|
||||
else if (i <= currentDayIndex && i < totalRewardDays)
|
||||
{
|
||||
int dayIndex = i;
|
||||
entry.EnableClaimButton(() => ClaimNewPlayerReward(dayIndex));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Lock
|
||||
entry.SetLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Claims a new player reward for the specified day and updates local + server data.
|
||||
/// </summary>
|
||||
private async void ClaimNewPlayerReward(int dayIndex)
|
||||
{
|
||||
// If already claimed
|
||||
if (localNewPlayerData.claimedRewards.Contains(dayIndex))
|
||||
{
|
||||
Debug.LogWarning($"Reward for day {dayIndex + 1} has already been claimed.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure it's not a future day
|
||||
if (dayIndex > currentDayIndex)
|
||||
{
|
||||
Debug.LogWarning($"Cannot claim reward for day {dayIndex + 1} yet.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark as claimed
|
||||
localNewPlayerData.claimedRewards.Add(dayIndex);
|
||||
|
||||
// Award the in-game reward
|
||||
RewardItem reward = rewardItems[dayIndex];
|
||||
AwardReward(reward);
|
||||
|
||||
// Optionally show a popup
|
||||
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);
|
||||
}
|
||||
|
||||
// Save locally
|
||||
PlayerSave.SetNewPlayerRewardsLocal(localNewPlayerData);
|
||||
|
||||
// Refresh UI
|
||||
DisplayNewPlayerRewards();
|
||||
|
||||
// Also save to server
|
||||
await BackendManager.Singleton.SaveNewPlayerRewardsDataAsync(localNewPlayerData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Grants the reward to the player via MonetizationManager or other systems.
|
||||
/// </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 New Player 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da920075f2f1e8a4f9ad88a4f9e512c5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd7692836f72bef4f96f118bce19c72a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c700776657e0bb34b81e9f4b04bef575
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 054a15360702db9439f4a29003cc3fa2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,85 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Firebase.Firestore;
|
||||
using Firebase.Auth;
|
||||
using Firebase.Extensions;
|
||||
|
||||
namespace BulletHellTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles saving and loading reward data from Firebase and PlayerPrefs.
|
||||
/// Prevents multiple calls to Firebase during initialization.
|
||||
/// </summary>
|
||||
public static class RewardSaveManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Loads rewards from Firestore for a specified collection and invokes a callback with the data.
|
||||
/// </summary>
|
||||
public static void LoadRewards(string collectionName, System.Action<Dictionary<string, object>> onLoaded)
|
||||
{
|
||||
FirebaseUser user = FirebaseAuth.DefaultInstance.CurrentUser;
|
||||
if (user == null) return;
|
||||
|
||||
FirebaseFirestore db = FirebaseFirestore.DefaultInstance;
|
||||
DocumentReference docRef = db.Collection("Players").Document(user.UserId).Collection(collectionName).Document("RewardData");
|
||||
docRef.GetSnapshotAsync().ContinueWithOnMainThread(task =>
|
||||
{
|
||||
if (task.IsCompleted && task.Result.Exists)
|
||||
{
|
||||
Dictionary<string, object> data = task.Result.ToDictionary();
|
||||
onLoaded?.Invoke(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Failed to load reward data.");
|
||||
onLoaded?.Invoke(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves rewards to Firestore for a specified collection, and also stores them locally in PlayerPrefs.
|
||||
/// </summary>
|
||||
public static void SaveRewards(string collectionName, Dictionary<string, object> data)
|
||||
{
|
||||
FirebaseUser user = FirebaseAuth.DefaultInstance.CurrentUser;
|
||||
if (user == null) return;
|
||||
|
||||
FirebaseFirestore db = FirebaseFirestore.DefaultInstance;
|
||||
DocumentReference docRef = db.Collection("Players").Document(user.UserId).Collection(collectionName).Document("RewardData");
|
||||
docRef.SetAsync(data).ContinueWithOnMainThread(task =>
|
||||
{
|
||||
if (task.IsCompleted)
|
||||
{
|
||||
Debug.Log($"{collectionName} rewards saved successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"Failed to save {collectionName} rewards: {task.Exception}");
|
||||
}
|
||||
});
|
||||
|
||||
// Save locally
|
||||
SaveRewardsLocally(collectionName, data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves rewards data locally in PlayerPrefs as JSON.
|
||||
/// </summary>
|
||||
private static void SaveRewardsLocally(string collectionName, Dictionary<string, object> data)
|
||||
{
|
||||
string json = JsonUtility.ToJson(data);
|
||||
PlayerPrefs.SetString(collectionName, json);
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads rewards data from PlayerPrefs if available.
|
||||
/// </summary>
|
||||
public static Dictionary<string, object> LoadRewardsLocally(string collectionName)
|
||||
{
|
||||
string json = PlayerPrefs.GetString(collectionName, null);
|
||||
return string.IsNullOrEmpty(json) ? null : JsonUtility.FromJson<Dictionary<string, object>>(json);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14a1f9538dc44a444b86779f45b4962e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f804f902a78cff145807640e51740dbb
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 20e295e3dffe0ec4488423fbac55e740
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Armors/ArmorCommon.asset
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Armors/ArmorEpic.asset
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Armors/ArmorLegendary.asset
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Armors/ArmorRare.asset
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Armors/ArmorUncommon.asset
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Hat/HatCommon.asset
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Hat/HatEpic.asset
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Hat/HatLegendary.asset
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Hat/HatRare.asset
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Hat/HatUncommon.asset
|
||||
uploadId: 777582
|
||||
|
@ -5,3 +5,10 @@ PrefabImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/InventoryEntryPrefab.prefab
|
||||
uploadId: 777582
|
||||
|
@ -5,3 +5,10 @@ PrefabImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/ItemApplyEntryPrefab.prefab
|
||||
uploadId: 777582
|
||||
|
@ -5,3 +5,10 @@ PrefabImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/ItemSlotEntryPrefab.prefab
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Pants/PantsCommon.asset
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Pants/PantsEpic.asset
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Pants/PantsLegendary.asset
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Pants/PantsRare.asset
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Pants/PantsUncommon.asset
|
||||
uploadId: 777582
|
||||
|
@ -5,3 +5,10 @@ PrefabImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/RuneEntryApply.prefab
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Runes/RuneAttackCommon.asset
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Runes/RuneAttackEpic.asset
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Runes/RuneDefenseRare.asset
|
||||
uploadId: 777582
|
||||
|
@ -6,3 +6,10 @@ NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 293814
|
||||
packageName: BulletHell Elemental Template
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Assets/BulletHellTemplate/Addons/Inventory/Resources/Runes/RuneSupportLegendary.asset
|
||||
uploadId: 777582
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user