208 lines
7.0 KiB
C#
208 lines
7.0 KiB
C#
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using AK.Wwise;
|
||
using Ichni.RhythmGame;
|
||
using Sirenix.OdinInspector;
|
||
using SLSUtilities.WwiseAssistance;
|
||
using UnityEngine;
|
||
using UnityEngine.Serialization;
|
||
|
||
namespace Ichni.Menu
|
||
{
|
||
[CreateAssetMenu(fileName = "DefaultChapter", menuName = "Ichni/UI/ChapterSelectionUnit", order = 0)]
|
||
public partial class ChapterSelectionUnit : SerializedScriptableObject
|
||
{
|
||
public string chapterIndex;
|
||
public string chapterName;
|
||
public string chapterSubtitle;
|
||
public Color themeColor;
|
||
public Sprite avatar;
|
||
public Switch chapterSwitch;
|
||
|
||
/// <summary>
|
||
/// 章节剧情入口与选曲入口共用的内容解锁规则。
|
||
/// 留空表示章节从新档开始即可访问;需要锁定时请使用 <see cref="UnlockRequirement"/>,
|
||
/// 并遵守 <see cref="UnlockSaveModule.KeyNamingRule"/> 中的下划线 Key 规则。
|
||
/// </summary>
|
||
[LabelText("Unlock Requirement")]
|
||
public UnlockRequirement unlockRequirement = new UnlockRequirement();
|
||
|
||
[Searchable]
|
||
public List<SongItemData> songs = new List<SongItemData>();
|
||
|
||
[Button]
|
||
public void SetUpDefaultDifficulties()
|
||
{
|
||
foreach (SongItemData song in songs)
|
||
{
|
||
if (song.difficultyDataList.All(d => d.difficultyName != "Easy"))
|
||
{
|
||
song.difficultyDataList.Add(new DifficultyData(
|
||
0, "Easy", "Easy", 0, "",
|
||
new Color(0f, 0.7f, 0.2f, 1f)));
|
||
}
|
||
|
||
if (song.difficultyDataList.All(d => d.difficultyName != "Hard"))
|
||
{
|
||
song.difficultyDataList.Add(new DifficultyData(
|
||
1, "Hard", "Hard", 0, "",
|
||
new Color(1f, 0.2f, 0.2f, 1f)));
|
||
}
|
||
}
|
||
}
|
||
|
||
[Button]
|
||
public void SelectSwitch()
|
||
{
|
||
AudioManager.SetSwitch(chapterSwitch);
|
||
}
|
||
}
|
||
|
||
public partial class ChapterSelectionUnit
|
||
{
|
||
public (int, int, int, int, int) GetChapterSaveInfo()
|
||
{
|
||
int beatmapCount = 0;
|
||
int finishedSongCount = 0;
|
||
int finishedBeatmapCount = 0;
|
||
int fullComboCount = 0;
|
||
int allPerfectCount = 0;
|
||
|
||
foreach (SongItemData song in songs)
|
||
{
|
||
if (GameSaveManager.instance.SongSaveModule.songStatusSaves.TryGetValue(song.songName, out var songStatus))
|
||
{
|
||
bool thisSongFinished = false;
|
||
foreach (DifficultyData difficulty in song.difficultyDataList)
|
||
{
|
||
if (difficulty == null || difficulty.saveDifficultyId < 0)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
beatmapCount++;
|
||
if (!songStatus.TryGetBeatmapSave(difficulty.saveDifficultyId, out BeatmapSave beatmapSave))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
if (!beatmapSave.IsEmpty())
|
||
{
|
||
thisSongFinished = true;
|
||
finishedBeatmapCount++;
|
||
|
||
if (beatmapSave.isFullCombo)
|
||
{
|
||
fullComboCount++;
|
||
}
|
||
|
||
if (beatmapSave.isAllPerfect)
|
||
{
|
||
allPerfectCount++;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (thisSongFinished)
|
||
{
|
||
finishedSongCount++;
|
||
}
|
||
}
|
||
}
|
||
|
||
return (beatmapCount, finishedSongCount, finishedBeatmapCount, fullComboCount, allPerfectCount);
|
||
}
|
||
}
|
||
|
||
[InlineProperty]
|
||
[Serializable]
|
||
public class SongItemData
|
||
{
|
||
[FoldoutGroup("$songName", false)]
|
||
public string songName;
|
||
|
||
[FoldoutGroup("$songName")]
|
||
public string displaySongName;
|
||
|
||
[FoldoutGroup("$songName")]
|
||
public string composer;
|
||
|
||
[FoldoutGroup("$songName")]
|
||
public Switch songSwitch;
|
||
|
||
[FoldoutGroup("$songName")]
|
||
public Sprite illustration;
|
||
|
||
[FoldoutGroup("$songName")]
|
||
public string illustratorName;
|
||
|
||
[FoldoutGroup("$songName")]
|
||
public string additionalInformation;
|
||
|
||
[FoldoutGroup("$songName")]
|
||
public List<DifficultyData> difficultyDataList;
|
||
|
||
/// <summary>
|
||
/// 歌曲自身的内容解锁规则。章节是否开放由 <see cref="ChapterSelectionUnit.unlockRequirement"/> 单独判断;
|
||
/// 真正进入歌曲时两者必须同时满足。
|
||
/// </summary>
|
||
[FoldoutGroup("$songName")]
|
||
[LabelText("Unlock Requirement")]
|
||
public UnlockRequirement unlockRequirement = new UnlockRequirement();
|
||
}
|
||
|
||
[Serializable]
|
||
public class DifficultyData
|
||
{
|
||
/// <summary>
|
||
/// 歌曲成绩的稳定 ID,不等同于选曲 UI 的难度列表位置。
|
||
/// 发布后不要更改或复用既有 ID;新增难度必须使用从未分配过的非负 ID。
|
||
/// </summary>
|
||
[FormerlySerializedAs("difficultyIndex")]
|
||
public int saveDifficultyId;
|
||
public string difficultyName;
|
||
public string displayDifficultyName;
|
||
public int difficultyValue;
|
||
public string charterName;
|
||
public Color color;
|
||
public bool isAvailable;
|
||
public bool ForceFullScreenJudge = false;
|
||
|
||
[MinValue(1)]
|
||
[Tooltip("仅当 Note、Timing 或判定规则变化,导致成绩不可与旧谱面比较时递增;UI、文本、封面和音量调整不递增。")]
|
||
public int chartRevision = 1;
|
||
|
||
public DifficultyData()
|
||
{
|
||
|
||
}
|
||
|
||
public DifficultyData(int saveDifficultyId, string difficultyName, string displayDifficultyName, int difficultyValue, string charterName, Color color, bool ForceFullScreenJudge = false)
|
||
{
|
||
this.saveDifficultyId = saveDifficultyId;
|
||
this.difficultyName = difficultyName;
|
||
this.displayDifficultyName = displayDifficultyName;
|
||
this.charterName = charterName;
|
||
this.difficultyValue = difficultyValue;
|
||
this.color = color;
|
||
this.isAvailable = true;
|
||
this.ForceFullScreenJudge = ForceFullScreenJudge;
|
||
}
|
||
|
||
public string GetDifficultyName()
|
||
{
|
||
return string.IsNullOrEmpty(displayDifficultyName) ? difficultyName : displayDifficultyName;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 返回合法的 Revision。配置侧始终至少使用 1;0 只会被视为未初始化值并被钳制。
|
||
/// </summary>
|
||
public int GetChartRevision()
|
||
{
|
||
return Mathf.Max(1, chartRevision);
|
||
}
|
||
}
|
||
}
|