diff --git a/Assets/LiveOpsExamples/Scripts/CozyCollectorConsts.cs b/Assets/LiveOpsExamples/Scripts/CozyCollectorConsts.cs index 040387b..235334e 100644 --- a/Assets/LiveOpsExamples/Scripts/CozyCollectorConsts.cs +++ b/Assets/LiveOpsExamples/Scripts/CozyCollectorConsts.cs @@ -23,6 +23,7 @@ namespace LiveOpsExamples public const string LeaderboardSlug = "cozy-collector-score"; public const string StoreSlug = "cozy-camp-shop"; public const string OfferId = "moonberry-boost"; + public const string QuestMetricCollectibles = "cozy_collectibles"; public const string StorageType = "cozy_fantasy_save"; public const string StorageId = "main"; public const string NicknamePrefsKey = "rudder_demo_nickname"; @@ -38,6 +39,7 @@ namespace LiveOpsExamples public const string CapabilityStorage = "storage"; public const string CapabilityInventory = "inventory"; public const string CapabilityWallet = "wallet"; + public const string CapabilityQuests = "quests"; public const string CapabilitySystem = "system"; /// Color used by the event inspector to tag a capability line. @@ -53,6 +55,7 @@ namespace LiveOpsExamples case CapabilityStorage: return new Color(0.56f, 0.87f, 0.87f); case CapabilityInventory: return new Color(0.78f, 0.86f, 0.55f); case CapabilityWallet: return new Color(1.00f, 0.88f, 0.63f); + case CapabilityQuests: return new Color(0.71f, 0.80f, 1.00f); default: return new Color(0.75f, 0.75f, 0.75f); } } diff --git a/Assets/LiveOpsExamples/Scripts/CozyCollectorController.cs b/Assets/LiveOpsExamples/Scripts/CozyCollectorController.cs index d56c318..9c83823 100644 --- a/Assets/LiveOpsExamples/Scripts/CozyCollectorController.cs +++ b/Assets/LiveOpsExamples/Scripts/CozyCollectorController.cs @@ -7,6 +7,7 @@ using RudderSdk.Core; using RudderSdk.Core.Models.Inventory; using RudderSdk.Core.Models.Leaderboards; using RudderSdk.Core.Models.Player; +using RudderSdk.Core.Models.Quests; using RudderSdk.Core.Models.Storage; using RudderSdk.Core.Models.Stores; using RudderSdk.Unity; @@ -249,6 +250,7 @@ namespace LiveOpsExamples await RefreshProfileAsync(); await RefreshStoresAsync(); await RefreshInventoryAsync(); + await RefreshQuestsAsync(); try { @@ -456,6 +458,11 @@ namespace LiveOpsExamples try { await RefreshInventoryAsync(); } catch (Exception exception) { Log(CozyCollectorConsts.CapabilityInventory, "Inventory refresh failed", exception.Message); } + + // Purchase metrics (purchase.offer:* / purchase.item:*) are reported + // server-side by the purchase fan-out; re-list to pick up new progress. + try { await RefreshQuestsAsync(); } + catch (Exception exception) { Log(CozyCollectorConsts.CapabilityQuests, "Quest refresh failed", exception.Message); } } // --------------------------------------------------------------- @@ -573,6 +580,63 @@ namespace LiveOpsExamples return mapped; } + // --------------------------------------------------------------- + // Global quests (distinct from scenario quest nodes / QuestSession) + // --------------------------------------------------------------- + + private async Task RefreshQuestsAsync() + { + var quests = await Rudder.Client.Quests.ListAsync(); + + var activeCount = 0; + if (quests != null) + { + foreach (var quest in quests) + { + if (quest.Status == "claimed") + continue; + + activeCount += 1; + Log(CozyCollectorConsts.CapabilityQuests, "Quest " + (quest.Status ?? "active"), QuestProgressSummary(quest)); + + if (quest.Status == "completed" && !string.IsNullOrEmpty(quest.Id)) + await ClaimQuestAsync(quest); + } + } + + Log(CozyCollectorConsts.CapabilityQuests, "Quests loaded", activeCount + " active"); + } + + private async Task ClaimQuestAsync(Quest quest) + { + var result = await Rudder.Client.Quests.ClaimAsync(quest.Id); + if (result == null || !result.Success) + { + Log(CozyCollectorConsts.CapabilityQuests, "Quest claim rejected", result?.Error); + return; + } + + if (!result.AlreadyClaimed) + Toast("Quest complete", quest.Name ?? quest.Id, CozyToastTone.Success); + Log(CozyCollectorConsts.CapabilityQuests, "Quest claimed", quest.Name ?? quest.Id); + await RefreshWalletsAsync(); + } + + private static string QuestProgressSummary(Quest quest) + { + var name = quest.Name ?? quest.Id; + if (quest.Objectives == null || quest.Objectives.Count == 0) + return name; + + var parts = new List(); + foreach (var objective in quest.Objectives) + { + parts.Add(objective.Metric + " " + objective.Current + "/" + objective.Target); + } + + return name + " · " + string.Join(" · ", parts); + } + // --------------------------------------------------------------- // Round flow // --------------------------------------------------------------- @@ -625,6 +689,23 @@ namespace LiveOpsExamples { Log(CozyCollectorConsts.CapabilityScenario, "Trigger failed", exception.Message); } + + try + { + var completedIds = await Rudder.Client.Quests.ReportProgressAsync( + CozyCollectorConsts.QuestMetricCollectibles, + collected); + Log( + CozyCollectorConsts.CapabilityQuests, + "Quest progress reported", + CozyCollectorConsts.QuestMetricCollectibles + " +" + collected + + (completedIds.Count > 0 ? " · completed " + completedIds.Count + " quest(s)" : string.Empty)); + await RefreshQuestsAsync(); + } + catch (Exception exception) + { + Log(CozyCollectorConsts.CapabilityQuests, "Quest progress failed", exception.Message); + } } public void PlayAgain() diff --git a/Assets/LiveOpsExamples/Scripts/UI/EventInspectorPanel.cs b/Assets/LiveOpsExamples/Scripts/UI/EventInspectorPanel.cs index ea3eafa..8f55cb9 100644 --- a/Assets/LiveOpsExamples/Scripts/UI/EventInspectorPanel.cs +++ b/Assets/LiveOpsExamples/Scripts/UI/EventInspectorPanel.cs @@ -16,6 +16,7 @@ namespace LiveOpsExamples { "storage", new Color(0.624f, 0.690f, 0.769f) }, { "inventory", new Color(0.898f, 0.604f, 0.796f) }, { "wallet", new Color(1f, 0.831f, 0.475f) }, + { "quests", new Color(0.710f, 0.800f, 1f) }, { "system", new Color(0.667f, 0.706f, 0.635f) }, }; @@ -29,6 +30,7 @@ namespace LiveOpsExamples { "storage", "Storage" }, { "inventory", "Items" }, { "wallet", "Wallet" }, + { "quests", "Quests" }, { "system", "System" }, };