加入用户最近100场战绩记录并实现展示
This commit is contained in:
@@ -9,12 +9,13 @@
|
||||
});
|
||||
}
|
||||
|
||||
public static void ReportPlaySong()
|
||||
public static void ReportPlaySong(int songID = 0)
|
||||
{
|
||||
DailyTaskService.EnsureInstance().ReportEvent(new DailyTaskEventData
|
||||
{
|
||||
taskType = userTasksPool.TaskType.PlaySong,
|
||||
amount = 1f
|
||||
amount = 1f,
|
||||
songID = songID
|
||||
});
|
||||
}
|
||||
|
||||
@@ -36,6 +37,15 @@
|
||||
});
|
||||
}
|
||||
|
||||
public static void ReportWatchStory()
|
||||
{
|
||||
DailyTaskService.EnsureInstance().ReportEvent(new DailyTaskEventData
|
||||
{
|
||||
taskType = userTasksPool.TaskType.WatchStory,
|
||||
amount = 1f
|
||||
});
|
||||
}
|
||||
|
||||
public static void ReportUseItem(int amount)
|
||||
{
|
||||
DailyTaskService.EnsureInstance().ReportEvent(new DailyTaskEventData
|
||||
@@ -54,11 +64,29 @@
|
||||
});
|
||||
}
|
||||
|
||||
public static void ReportGameDuration(float durationSeconds)
|
||||
public static void ReportSingleRunCombo(int combo)
|
||||
{
|
||||
DailyTaskService.EnsureInstance().ReportEvent(new DailyTaskEventData
|
||||
{
|
||||
taskType = userTasksPool.TaskType.GameDuration,
|
||||
taskType = userTasksPool.TaskType.SingleRunCombo,
|
||||
amount = combo
|
||||
});
|
||||
}
|
||||
|
||||
public static void ReportSingleRunScore(float totalScore)
|
||||
{
|
||||
DailyTaskService.EnsureInstance().ReportEvent(new DailyTaskEventData
|
||||
{
|
||||
taskType = userTasksPool.TaskType.SingleRunScore,
|
||||
amount = totalScore
|
||||
});
|
||||
}
|
||||
|
||||
public static void ReportOnlineDuration(float durationSeconds)
|
||||
{
|
||||
DailyTaskService.EnsureInstance().ReportEvent(new DailyTaskEventData
|
||||
{
|
||||
taskType = userTasksPool.TaskType.OnlineDuration,
|
||||
amount = durationSeconds
|
||||
});
|
||||
}
|
||||
|
||||
@@ -14,15 +14,25 @@ public class DailyTaskRuntimeEntry
|
||||
public class DailyTaskSaveData
|
||||
{
|
||||
public string dateKey;
|
||||
public int dateStamp;
|
||||
public int refreshUsedCount;
|
||||
public int trustedDateStamp;
|
||||
public int lastRefreshDateStamp;
|
||||
public long lastRefreshLocalTicks;
|
||||
public long lastRefreshUtcTicks;
|
||||
public long lastSeenLocalTicks;
|
||||
public long lastSeenUtcTicks;
|
||||
public int timeRollbackDetections;
|
||||
public List<DailyTaskRuntimeEntry> activeTasks = new List<DailyTaskRuntimeEntry>();
|
||||
public List<DailyTaskAccumulatedProgress> accumulatedProgress = new List<DailyTaskAccumulatedProgress>();
|
||||
public List<DailyTaskUniqueIntProgress> uniqueIntProgress = new List<DailyTaskUniqueIntProgress>();
|
||||
}
|
||||
|
||||
public struct DailyTaskEventData
|
||||
{
|
||||
public userTasksPool.TaskType taskType;
|
||||
public float amount;
|
||||
public int songID;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
@@ -32,6 +42,13 @@ public class DailyTaskAccumulatedProgress
|
||||
public float progress;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class DailyTaskUniqueIntProgress
|
||||
{
|
||||
public int taskType;
|
||||
public List<int> values = new List<int>();
|
||||
}
|
||||
|
||||
public sealed class DailyTaskViewData
|
||||
{
|
||||
public userTasksPool.TaskDefinition definition;
|
||||
|
||||
@@ -4,23 +4,25 @@ using UnityEngine;
|
||||
|
||||
public static class DailyTaskSaveService
|
||||
{
|
||||
private static string SaveFilePath
|
||||
private const string SaveCategory = "daily_task";
|
||||
private const string SaveKey = "runtime";
|
||||
|
||||
private static string LegacySaveFilePath
|
||||
{
|
||||
get { return Path.Combine(Application.persistentDataPath, "daily_tasks.json"); }
|
||||
}
|
||||
|
||||
public static DailyTaskSaveData Load()
|
||||
{
|
||||
if (!File.Exists(SaveFilePath))
|
||||
{
|
||||
return new DailyTaskSaveData();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var json = File.ReadAllText(SaveFilePath);
|
||||
var data = JsonUtility.FromJson<DailyTaskSaveData>(json);
|
||||
return data ?? new DailyTaskSaveData();
|
||||
DailyTaskSaveData data;
|
||||
if (SecureSaveVault.TryLoadJson(SaveCategory, SaveKey, out data, LegacySaveFilePath))
|
||||
{
|
||||
return data ?? new DailyTaskSaveData();
|
||||
}
|
||||
|
||||
return new DailyTaskSaveData();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -38,8 +40,7 @@ public static class DailyTaskSaveService
|
||||
|
||||
try
|
||||
{
|
||||
var json = JsonUtility.ToJson(data, true);
|
||||
File.WriteAllText(SaveFilePath, json);
|
||||
SecureSaveVault.SaveJson(SaveCategory, SaveKey, data, LegacySaveFilePath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,14 @@ public sealed class DailyTaskService : MonoBehaviour
|
||||
|
||||
public event Action OnTasksChanged;
|
||||
|
||||
private enum ProgressCombineMode
|
||||
{
|
||||
Sum,
|
||||
Max
|
||||
}
|
||||
|
||||
private const float OnlineDurationFlushStepSeconds = 5f;
|
||||
|
||||
private readonly Queue<DailyTaskEventData> pendingEvents = new Queue<DailyTaskEventData>();
|
||||
private readonly Dictionary<string, userTasksPool.TaskDefinition> definitionById = new Dictionary<string, userTasksPool.TaskDefinition>(StringComparer.Ordinal);
|
||||
|
||||
@@ -18,6 +26,8 @@ public sealed class DailyTaskService : MonoBehaviour
|
||||
private int configuredTaskMaxSize = 5;
|
||||
private int configuredRefreshMaxTimes = 3;
|
||||
private bool initialized;
|
||||
private bool appFocused = true;
|
||||
private float pendingOnlineDurationSeconds;
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
private static void Bootstrap()
|
||||
@@ -54,10 +64,53 @@ public sealed class DailyTaskService : MonoBehaviour
|
||||
InitializeStorageIfNeeded();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!Application.isPlaying || !appFocused)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pendingOnlineDurationSeconds += Time.unscaledDeltaTime;
|
||||
if (pendingOnlineDurationSeconds >= OnlineDurationFlushStepSeconds)
|
||||
{
|
||||
float flushSeconds = Mathf.Floor(pendingOnlineDurationSeconds);
|
||||
pendingOnlineDurationSeconds = Mathf.Max(0f, pendingOnlineDurationSeconds - flushSeconds);
|
||||
ReportEvent(new DailyTaskEventData
|
||||
{
|
||||
taskType = userTasksPool.TaskType.OnlineDuration,
|
||||
amount = flushSeconds
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void OnApplicationFocus(bool hasFocus)
|
||||
{
|
||||
appFocused = hasFocus;
|
||||
if (!hasFocus)
|
||||
{
|
||||
FlushPendingOnlineDuration();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnApplicationPause(bool pauseStatus)
|
||||
{
|
||||
if (pauseStatus)
|
||||
{
|
||||
FlushPendingOnlineDuration();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnApplicationQuit()
|
||||
{
|
||||
FlushPendingOnlineDuration();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (Instance == this)
|
||||
{
|
||||
FlushPendingOnlineDuration();
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
}
|
||||
}
|
||||
@@ -117,42 +170,39 @@ public sealed class DailyTaskService : MonoBehaviour
|
||||
}
|
||||
|
||||
EnsureTodayTasks();
|
||||
float accumulatedIncrement = GetAccumulatedIncrement(eventData);
|
||||
if (accumulatedIncrement <= 0f)
|
||||
|
||||
bool changed = ApplyEventToTrackedProgress(eventData);
|
||||
|
||||
if (saveData != null && saveData.activeTasks != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float accumulatedValue = AddAccumulatedProgress(eventData.taskType, accumulatedIncrement);
|
||||
|
||||
bool changed = false;
|
||||
for (int i = 0; i < saveData.activeTasks.Count; i++)
|
||||
{
|
||||
var runtimeEntry = saveData.activeTasks[i];
|
||||
if (runtimeEntry == null || runtimeEntry.isClaimed)
|
||||
for (int i = 0; i < saveData.activeTasks.Count; i++)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var runtimeEntry = saveData.activeTasks[i];
|
||||
if (runtimeEntry == null || runtimeEntry.isClaimed)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
userTasksPool.TaskDefinition definition;
|
||||
if (!definitionById.TryGetValue(runtimeEntry.taskID, out definition))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
userTasksPool.TaskDefinition definition;
|
||||
if (!definitionById.TryGetValue(runtimeEntry.taskID, out definition))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!IsEventMatch(definition, eventData))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!IsEventMatch(definition, eventData))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float previousProgress = runtimeEntry.progress;
|
||||
bool previousCompleted = runtimeEntry.isCompleted;
|
||||
runtimeEntry.progress = GetInitialProgress(definition, accumulatedValue);
|
||||
runtimeEntry.isCompleted = runtimeEntry.progress >= Mathf.Max(0.0001f, definition.targetValue);
|
||||
float nextProgress = CalculateProgressForDefinition(definition);
|
||||
bool nextCompleted = nextProgress >= Mathf.Max(0.0001f, definition.targetValue);
|
||||
|
||||
if (!Mathf.Approximately(previousProgress, runtimeEntry.progress) || previousCompleted != runtimeEntry.isCompleted)
|
||||
{
|
||||
changed = true;
|
||||
if (!Mathf.Approximately(runtimeEntry.progress, nextProgress) || runtimeEntry.isCompleted != nextCompleted)
|
||||
{
|
||||
runtimeEntry.progress = nextProgress;
|
||||
runtimeEntry.isCompleted = nextCompleted;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,6 +227,7 @@ public sealed class DailyTaskService : MonoBehaviour
|
||||
}
|
||||
|
||||
saveData.refreshUsedCount += 1;
|
||||
StampRefreshUsage();
|
||||
GenerateDailyTasks();
|
||||
Save();
|
||||
NotifyTasksChanged();
|
||||
@@ -278,11 +329,7 @@ public sealed class DailyTaskService : MonoBehaviour
|
||||
{
|
||||
if (string.Equals(scene.name, "UI_UI", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
ReportEvent(new DailyTaskEventData
|
||||
{
|
||||
taskType = userTasksPool.TaskType.Login,
|
||||
amount = 1f
|
||||
});
|
||||
DailyTaskEventHub.ReportLogin();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,6 +341,7 @@ public sealed class DailyTaskService : MonoBehaviour
|
||||
}
|
||||
|
||||
saveData = DailyTaskSaveService.Load() ?? new DailyTaskSaveData();
|
||||
EnsureRuntimeCollections();
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@@ -306,25 +354,36 @@ public sealed class DailyTaskService : MonoBehaviour
|
||||
return;
|
||||
}
|
||||
|
||||
string todayKey = GetTodayKey();
|
||||
bool timeStateChanged;
|
||||
int effectiveTodayStamp = GetEffectiveTodayStamp(out timeStateChanged);
|
||||
string todayKey = FormatDateKey(effectiveTodayStamp);
|
||||
if (saveData == null)
|
||||
{
|
||||
saveData = new DailyTaskSaveData();
|
||||
}
|
||||
|
||||
bool needRegenerate = !string.Equals(saveData.dateKey, todayKey, StringComparison.Ordinal)
|
||||
EnsureRuntimeCollections();
|
||||
|
||||
bool needRegenerate = saveData.dateStamp != effectiveTodayStamp
|
||||
|| !string.Equals(saveData.dateKey, todayKey, StringComparison.Ordinal)
|
||||
|| saveData.activeTasks == null
|
||||
|| saveData.activeTasks.Count == 0;
|
||||
|
||||
if (!needRegenerate)
|
||||
{
|
||||
EnsureAccumulatedProgressCompatibility();
|
||||
if (timeStateChanged)
|
||||
{
|
||||
Save();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
saveData.dateKey = todayKey;
|
||||
saveData.dateStamp = effectiveTodayStamp;
|
||||
saveData.refreshUsedCount = 0;
|
||||
saveData.accumulatedProgress = new List<DailyTaskAccumulatedProgress>();
|
||||
saveData.uniqueIntProgress = new List<DailyTaskUniqueIntProgress>();
|
||||
GenerateDailyTasks();
|
||||
Save();
|
||||
}
|
||||
@@ -348,7 +407,8 @@ public sealed class DailyTaskService : MonoBehaviour
|
||||
}
|
||||
|
||||
int pickCount = Mathf.Min(configuredTaskMaxSize, candidates.Count);
|
||||
var random = new System.Random(unchecked(GetTodayKey().GetHashCode() + saveData.refreshUsedCount * 397));
|
||||
int dateSeed = saveData.dateStamp > 0 ? saveData.dateStamp : GetLocalDateStamp(DateTime.Now);
|
||||
var random = new System.Random(unchecked(dateSeed + saveData.refreshUsedCount * 397));
|
||||
var selectedDefinitions = new List<userTasksPool.TaskDefinition>();
|
||||
|
||||
while (selectedDefinitions.Count < pickCount && candidates.Count > 0)
|
||||
@@ -374,7 +434,7 @@ public sealed class DailyTaskService : MonoBehaviour
|
||||
for (int i = 0; i < selectedDefinitions.Count; i++)
|
||||
{
|
||||
var definition = selectedDefinitions[i];
|
||||
float currentProgress = GetInitialProgress(definition, GetAccumulatedProgress(definition.taskType));
|
||||
float currentProgress = CalculateProgressForDefinition(definition);
|
||||
saveData.activeTasks.Add(new DailyTaskRuntimeEntry
|
||||
{
|
||||
taskID = definition.taskID,
|
||||
@@ -415,15 +475,7 @@ public sealed class DailyTaskService : MonoBehaviour
|
||||
|
||||
private void EnsureAccumulatedProgressCompatibility()
|
||||
{
|
||||
if (saveData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (saveData.accumulatedProgress == null)
|
||||
{
|
||||
saveData.accumulatedProgress = new List<DailyTaskAccumulatedProgress>();
|
||||
}
|
||||
EnsureRuntimeCollections();
|
||||
|
||||
if (saveData.accumulatedProgress.Count > 0 || saveData.activeTasks == null || saveData.activeTasks.Count == 0)
|
||||
{
|
||||
@@ -445,8 +497,12 @@ public sealed class DailyTaskService : MonoBehaviour
|
||||
continue;
|
||||
}
|
||||
|
||||
AddAccumulatedProgress(definition.taskType, Mathf.Max(0f, runtimeEntry.progress));
|
||||
changed = true;
|
||||
if (definition.taskType == userTasksPool.TaskType.DifferentSongs)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
changed |= AddOrCombineProgress(definition.taskType, Mathf.Max(0f, runtimeEntry.progress), GetCombineMode(definition.taskType));
|
||||
}
|
||||
|
||||
if (changed)
|
||||
@@ -468,23 +524,74 @@ public sealed class DailyTaskService : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsEventMatch(userTasksPool.TaskDefinition definition, DailyTaskEventData eventData)
|
||||
private bool ApplyEventToTrackedProgress(DailyTaskEventData eventData)
|
||||
{
|
||||
return definition != null && definition.taskType == eventData.taskType;
|
||||
switch (eventData.taskType)
|
||||
{
|
||||
case userTasksPool.TaskType.Login:
|
||||
case userTasksPool.TaskType.PlaySong:
|
||||
case userTasksPool.TaskType.FullCombo:
|
||||
case userTasksPool.TaskType.WatchStory:
|
||||
case userTasksPool.TaskType.UseItem:
|
||||
case userTasksPool.TaskType.ShareGame:
|
||||
{
|
||||
bool changed = AddOrCombineProgress(eventData.taskType, Mathf.Max(1f, eventData.amount), ProgressCombineMode.Sum);
|
||||
if (eventData.taskType == userTasksPool.TaskType.PlaySong && eventData.songID > 0)
|
||||
{
|
||||
changed |= AddUniqueIntValue(userTasksPool.TaskType.DifferentSongs, eventData.songID);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
case userTasksPool.TaskType.TotalScore:
|
||||
case userTasksPool.TaskType.SpendCoins:
|
||||
case userTasksPool.TaskType.GameDuration:
|
||||
case userTasksPool.TaskType.OnlineDuration:
|
||||
return AddOrCombineProgress(eventData.taskType, Mathf.Max(0f, eventData.amount), ProgressCombineMode.Sum);
|
||||
case userTasksPool.TaskType.SingleRunCombo:
|
||||
case userTasksPool.TaskType.SingleRunScore:
|
||||
return AddOrCombineProgress(eventData.taskType, Mathf.Max(0f, eventData.amount), ProgressCombineMode.Max);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private float AddAccumulatedProgress(userTasksPool.TaskType taskType, float amount)
|
||||
private static bool IsEventMatch(userTasksPool.TaskDefinition definition, DailyTaskEventData eventData)
|
||||
{
|
||||
if (saveData == null)
|
||||
if (definition == null)
|
||||
{
|
||||
saveData = new DailyTaskSaveData();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (saveData.accumulatedProgress == null)
|
||||
if (definition.taskType == eventData.taskType)
|
||||
{
|
||||
saveData.accumulatedProgress = new List<DailyTaskAccumulatedProgress>();
|
||||
return true;
|
||||
}
|
||||
|
||||
return definition.taskType == userTasksPool.TaskType.DifferentSongs && eventData.taskType == userTasksPool.TaskType.PlaySong;
|
||||
}
|
||||
|
||||
private float CalculateProgressForDefinition(userTasksPool.TaskDefinition definition)
|
||||
{
|
||||
if (definition == null)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
float targetValue = Mathf.Max(0.0001f, definition.targetValue);
|
||||
switch (definition.taskType)
|
||||
{
|
||||
case userTasksPool.TaskType.DifferentSongs:
|
||||
return Mathf.Min(GetUniqueIntCount(userTasksPool.TaskType.DifferentSongs), targetValue);
|
||||
default:
|
||||
return Mathf.Min(Mathf.Max(0f, GetAccumulatedProgress(definition.taskType)), targetValue);
|
||||
}
|
||||
}
|
||||
|
||||
private bool AddOrCombineProgress(userTasksPool.TaskType taskType, float amount, ProgressCombineMode combineMode)
|
||||
{
|
||||
EnsureRuntimeCollections();
|
||||
|
||||
int taskTypeValue = (int)taskType;
|
||||
for (int i = 0; i < saveData.accumulatedProgress.Count; i++)
|
||||
{
|
||||
@@ -494,17 +601,25 @@ public sealed class DailyTaskService : MonoBehaviour
|
||||
continue;
|
||||
}
|
||||
|
||||
entry.progress = Mathf.Max(0f, entry.progress + amount);
|
||||
return entry.progress;
|
||||
float nextValue = combineMode == ProgressCombineMode.Max
|
||||
? Mathf.Max(entry.progress, amount)
|
||||
: Mathf.Max(0f, entry.progress + amount);
|
||||
|
||||
if (Mathf.Approximately(entry.progress, nextValue))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
entry.progress = nextValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
var newEntry = new DailyTaskAccumulatedProgress
|
||||
saveData.accumulatedProgress.Add(new DailyTaskAccumulatedProgress
|
||||
{
|
||||
taskType = taskTypeValue,
|
||||
progress = Mathf.Max(0f, amount)
|
||||
};
|
||||
saveData.accumulatedProgress.Add(newEntry);
|
||||
return newEntry.progress;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private float GetAccumulatedProgress(userTasksPool.TaskType taskType)
|
||||
@@ -529,14 +644,151 @@ public sealed class DailyTaskService : MonoBehaviour
|
||||
return 0f;
|
||||
}
|
||||
|
||||
private static float GetInitialProgress(userTasksPool.TaskDefinition definition, float accumulatedValue)
|
||||
private bool AddUniqueIntValue(userTasksPool.TaskType taskType, int value)
|
||||
{
|
||||
if (definition == null)
|
||||
if (value <= 0)
|
||||
{
|
||||
return 0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
return Mathf.Min(Mathf.Max(0f, accumulatedValue), Mathf.Max(0.0001f, definition.targetValue));
|
||||
EnsureRuntimeCollections();
|
||||
int taskTypeValue = (int)taskType;
|
||||
for (int i = 0; i < saveData.uniqueIntProgress.Count; i++)
|
||||
{
|
||||
var entry = saveData.uniqueIntProgress[i];
|
||||
if (entry == null || entry.taskType != taskTypeValue)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.values == null)
|
||||
{
|
||||
entry.values = new List<int>();
|
||||
}
|
||||
|
||||
if (entry.values.Contains(value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
entry.values.Add(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
saveData.uniqueIntProgress.Add(new DailyTaskUniqueIntProgress
|
||||
{
|
||||
taskType = taskTypeValue,
|
||||
values = new List<int> { value }
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private int GetUniqueIntCount(userTasksPool.TaskType taskType)
|
||||
{
|
||||
if (saveData == null || saveData.uniqueIntProgress == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int taskTypeValue = (int)taskType;
|
||||
for (int i = 0; i < saveData.uniqueIntProgress.Count; i++)
|
||||
{
|
||||
var entry = saveData.uniqueIntProgress[i];
|
||||
if (entry == null || entry.taskType != taskTypeValue || entry.values == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return entry.values.Count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static ProgressCombineMode GetCombineMode(userTasksPool.TaskType taskType)
|
||||
{
|
||||
switch (taskType)
|
||||
{
|
||||
case userTasksPool.TaskType.SingleRunCombo:
|
||||
case userTasksPool.TaskType.SingleRunScore:
|
||||
return ProgressCombineMode.Max;
|
||||
default:
|
||||
return ProgressCombineMode.Sum;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureRuntimeCollections()
|
||||
{
|
||||
if (saveData == null)
|
||||
{
|
||||
saveData = new DailyTaskSaveData();
|
||||
}
|
||||
|
||||
if (saveData.activeTasks == null)
|
||||
{
|
||||
saveData.activeTasks = new List<DailyTaskRuntimeEntry>();
|
||||
}
|
||||
|
||||
if (saveData.accumulatedProgress == null)
|
||||
{
|
||||
saveData.accumulatedProgress = new List<DailyTaskAccumulatedProgress>();
|
||||
}
|
||||
|
||||
if (saveData.uniqueIntProgress == null)
|
||||
{
|
||||
saveData.uniqueIntProgress = new List<DailyTaskUniqueIntProgress>();
|
||||
}
|
||||
}
|
||||
|
||||
private int GetEffectiveTodayStamp(out bool stateChanged)
|
||||
{
|
||||
stateChanged = false;
|
||||
if (saveData == null)
|
||||
{
|
||||
saveData = new DailyTaskSaveData();
|
||||
}
|
||||
|
||||
int currentStamp = GetLocalDateStamp(DateTime.Now);
|
||||
long nowLocalTicks = DateTime.Now.Ticks;
|
||||
long nowUtcTicks = DateTime.UtcNow.Ticks;
|
||||
|
||||
if (saveData.trustedDateStamp <= 0)
|
||||
{
|
||||
saveData.trustedDateStamp = currentStamp;
|
||||
stateChanged = true;
|
||||
}
|
||||
else if (currentStamp < saveData.trustedDateStamp)
|
||||
{
|
||||
saveData.timeRollbackDetections += 1;
|
||||
currentStamp = saveData.trustedDateStamp;
|
||||
stateChanged = true;
|
||||
}
|
||||
else if (currentStamp > saveData.trustedDateStamp)
|
||||
{
|
||||
saveData.trustedDateStamp = currentStamp;
|
||||
stateChanged = true;
|
||||
}
|
||||
|
||||
if (saveData.lastSeenLocalTicks != nowLocalTicks)
|
||||
{
|
||||
saveData.lastSeenLocalTicks = nowLocalTicks;
|
||||
stateChanged = true;
|
||||
}
|
||||
|
||||
if (saveData.lastSeenUtcTicks != nowUtcTicks)
|
||||
{
|
||||
saveData.lastSeenUtcTicks = nowUtcTicks;
|
||||
stateChanged = true;
|
||||
}
|
||||
|
||||
return Mathf.Max(currentStamp, saveData.trustedDateStamp);
|
||||
}
|
||||
|
||||
private void StampRefreshUsage()
|
||||
{
|
||||
saveData.lastRefreshDateStamp = saveData.dateStamp;
|
||||
saveData.lastRefreshLocalTicks = DateTime.Now.Ticks;
|
||||
saveData.lastRefreshUtcTicks = DateTime.UtcNow.Ticks;
|
||||
}
|
||||
|
||||
private bool TryGetTaskPair(string taskID, out DailyTaskRuntimeEntry runtimeEntry, out userTasksPool.TaskDefinition definition)
|
||||
@@ -627,27 +879,33 @@ public sealed class DailyTaskService : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
private static float GetAccumulatedIncrement(DailyTaskEventData eventData)
|
||||
private void FlushPendingOnlineDuration()
|
||||
{
|
||||
switch (eventData.taskType)
|
||||
if (pendingOnlineDurationSeconds <= 0f)
|
||||
{
|
||||
case userTasksPool.TaskType.TotalScore:
|
||||
case userTasksPool.TaskType.SpendCoins:
|
||||
case userTasksPool.TaskType.GameDuration:
|
||||
return Mathf.Max(0f, eventData.amount);
|
||||
case userTasksPool.TaskType.Login:
|
||||
case userTasksPool.TaskType.PlaySong:
|
||||
case userTasksPool.TaskType.FullCombo:
|
||||
case userTasksPool.TaskType.UseItem:
|
||||
return Mathf.Max(1f, eventData.amount);
|
||||
default:
|
||||
return Mathf.Max(0f, eventData.amount);
|
||||
return;
|
||||
}
|
||||
|
||||
float flushSeconds = pendingOnlineDurationSeconds;
|
||||
pendingOnlineDurationSeconds = 0f;
|
||||
ReportEvent(new DailyTaskEventData
|
||||
{
|
||||
taskType = userTasksPool.TaskType.OnlineDuration,
|
||||
amount = flushSeconds
|
||||
});
|
||||
}
|
||||
|
||||
private static string GetTodayKey()
|
||||
private static int GetLocalDateStamp(DateTime dateTime)
|
||||
{
|
||||
return DateTime.Now.ToString("yyyy-MM-dd");
|
||||
return dateTime.Year * 10000 + dateTime.Month * 100 + dateTime.Day;
|
||||
}
|
||||
|
||||
private static string FormatDateKey(int dateStamp)
|
||||
{
|
||||
int year = dateStamp / 10000;
|
||||
int month = (dateStamp / 100) % 100;
|
||||
int day = dateStamp % 100;
|
||||
return year.ToString("D4") + "-" + month.ToString("D2") + "-" + day.ToString("D2");
|
||||
}
|
||||
|
||||
private void Save()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
%YAML 1.1
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
@@ -14,78 +14,111 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
tasks:
|
||||
- taskID: 10101
|
||||
description: "\u767B\u5F55\u6E38\u620Fv50"
|
||||
description: 登录游戏 1 次
|
||||
taskType: 0
|
||||
refreshFrequency: 1
|
||||
targetValue: 1
|
||||
rewardType: 0
|
||||
rewardAmount: 50
|
||||
rewardAmount: 1
|
||||
rewardExpBottleKind: 0
|
||||
rewardDushMaterialKind: 0
|
||||
addToTaskPool: 1
|
||||
selectionWeight: 1
|
||||
- taskID: 10102
|
||||
description: "\u5B8C\u62103\u9996\u6B4C\u66F2"
|
||||
description: 完成任意歌曲 3 首
|
||||
taskType: 1
|
||||
refreshFrequency: 1
|
||||
targetValue: 3
|
||||
rewardType: 0
|
||||
rewardAmount: 0
|
||||
rewardAmount: 1
|
||||
rewardExpBottleKind: 0
|
||||
rewardDushMaterialKind: 0
|
||||
addToTaskPool: 1
|
||||
selectionWeight: 1
|
||||
- taskID: 10103
|
||||
description: "\u8FBE\u62101\u6B21Full Combo"
|
||||
taskType: 2
|
||||
description: 单局达到 99 连击
|
||||
taskType: 9
|
||||
refreshFrequency: 1
|
||||
targetValue: 1
|
||||
targetValue: 99
|
||||
rewardType: 0
|
||||
rewardAmount: 0
|
||||
rewardAmount: 1
|
||||
rewardExpBottleKind: 0
|
||||
rewardDushMaterialKind: 0
|
||||
addToTaskPool: 1
|
||||
selectionWeight: 1
|
||||
- taskID: 10104
|
||||
description: "\u7D2F\u8BA1\u83B7\u5F971000000\u5206"
|
||||
taskType: 3
|
||||
description: 单局总分达到 1000000
|
||||
taskType: 10
|
||||
refreshFrequency: 1
|
||||
targetValue: 1000000
|
||||
rewardType: 1
|
||||
rewardAmount: 4
|
||||
rewardType: 0
|
||||
rewardAmount: 1
|
||||
rewardExpBottleKind: 0
|
||||
rewardDushMaterialKind: 0
|
||||
addToTaskPool: 1
|
||||
selectionWeight: 1
|
||||
- taskID: 10105
|
||||
description: "\u4F7F\u7528\u4EFB\u610F\u7C7B\u578B\u7ECF\u9A8C\u74F6\u4E00\u6B21"
|
||||
taskType: 5
|
||||
description: 今日累计分数达到 10000000
|
||||
taskType: 3
|
||||
refreshFrequency: 1
|
||||
targetValue: 1
|
||||
targetValue: 10000000
|
||||
rewardType: 0
|
||||
rewardAmount: 0
|
||||
rewardAmount: 1
|
||||
rewardExpBottleKind: 0
|
||||
rewardDushMaterialKind: 0
|
||||
addToTaskPool: 1
|
||||
selectionWeight: 1
|
||||
- taskID: 10106
|
||||
description: "\u82B1\u8D391000\u91D1\u5E01"
|
||||
taskType: 7
|
||||
description: 阅读剧情 1 次
|
||||
taskType: 4
|
||||
refreshFrequency: 1
|
||||
targetValue: 1000
|
||||
targetValue: 1
|
||||
rewardType: 0
|
||||
rewardAmount: 0
|
||||
rewardAmount: 1
|
||||
rewardExpBottleKind: 0
|
||||
rewardDushMaterialKind: 0
|
||||
addToTaskPool: 1
|
||||
selectionWeight: 1
|
||||
- taskID: 10107
|
||||
description: "\u6E38\u620F\u65F6\u957F\u8FBE\u523030\u5206\u949F"
|
||||
taskType: 8
|
||||
description: 使用任意经验提升或突破材料 1 次
|
||||
taskType: 5
|
||||
refreshFrequency: 1
|
||||
targetValue: 1800
|
||||
targetValue: 1
|
||||
rewardType: 0
|
||||
rewardAmount: 0
|
||||
rewardAmount: 1
|
||||
rewardExpBottleKind: 0
|
||||
rewardDushMaterialKind: 0
|
||||
addToTaskPool: 1
|
||||
selectionWeight: 1
|
||||
- taskID: 10108
|
||||
description: 在线 15 分钟
|
||||
taskType: 11
|
||||
refreshFrequency: 1
|
||||
targetValue: 900
|
||||
rewardType: 0
|
||||
rewardAmount: 1
|
||||
rewardExpBottleKind: 0
|
||||
rewardDushMaterialKind: 0
|
||||
addToTaskPool: 1
|
||||
selectionWeight: 1
|
||||
- taskID: 10109
|
||||
description: 消费 2000 coins
|
||||
taskType: 7
|
||||
refreshFrequency: 1
|
||||
targetValue: 2000
|
||||
rewardType: 0
|
||||
rewardAmount: 1
|
||||
rewardExpBottleKind: 0
|
||||
rewardDushMaterialKind: 0
|
||||
addToTaskPool: 1
|
||||
selectionWeight: 1
|
||||
- taskID: 10110
|
||||
description: 游玩 3 首不同的歌曲
|
||||
taskType: 12
|
||||
refreshFrequency: 1
|
||||
targetValue: 3
|
||||
rewardType: 0
|
||||
rewardAmount: 1
|
||||
rewardExpBottleKind: 0
|
||||
rewardDushMaterialKind: 0
|
||||
addToTaskPool: 1
|
||||
|
||||
@@ -55,7 +55,11 @@ public class userTasksPool : ScriptableObject
|
||||
UseItem,
|
||||
ShareGame,
|
||||
SpendCoins,
|
||||
GameDuration
|
||||
GameDuration,
|
||||
SingleRunCombo,
|
||||
SingleRunScore,
|
||||
OnlineDuration,
|
||||
DifferentSongs
|
||||
}
|
||||
|
||||
public enum RewardType
|
||||
|
||||
Reference in New Issue
Block a user