From 16b286542277f8818caf1ba1c7a9642ac5e7e50d Mon Sep 17 00:00:00 2001 From: 0auBSQ <58159635+0auBSQ@users.noreply.github.com> Date: Sun, 23 Jun 2024 08:55:00 +0900 Subject: [PATCH] Unlockables extra stuff --- .../Global/Characters/04 - Kuro/Unlock.json | 6 +- .../Characters/10 - AItritus/Unlock.json | 4 +- .../PuchiChara/01 - Template/Unlock.json | 7 +++ OpenTaiko/src/Databases/DBUnlockables.cs | 56 +++++++++++++++++-- OpenTaiko/src/I18N/CLang_en.cs | 3 + OpenTaiko/src/I18N/CLang_jp.cs | 30 +++++++++- OpenTaiko/src/Stages/11.Heya/CStageHeya.cs | 22 +++++--- OpenTaiko/src/Stages/CActNewHeya.cs | 8 +-- 8 files changed, 114 insertions(+), 22 deletions(-) create mode 100644 OpenTaiko/Global/PuchiChara/01 - Template/Unlock.json diff --git a/OpenTaiko/Global/Characters/04 - Kuro/Unlock.json b/OpenTaiko/Global/Characters/04 - Kuro/Unlock.json index e74a0e40..b41c0491 100644 --- a/OpenTaiko/Global/Characters/04 - Kuro/Unlock.json +++ b/OpenTaiko/Global/Characters/04 - Kuro/Unlock.json @@ -1,7 +1,9 @@ { - "condition": "ch", + "condition": "dp", "type": "me", "values": [ - 960, + 3, + 3, + 10 ], } \ No newline at end of file diff --git a/OpenTaiko/Global/Characters/10 - AItritus/Unlock.json b/OpenTaiko/Global/Characters/10 - AItritus/Unlock.json index d0cbae0d..05e1d50a 100644 --- a/OpenTaiko/Global/Characters/10 - AItritus/Unlock.json +++ b/OpenTaiko/Global/Characters/10 - AItritus/Unlock.json @@ -1,7 +1,7 @@ { - "condition": "ch", + "condition": "ap", "type": "me", "values": [ - 4444, + 100, ], } \ No newline at end of file diff --git a/OpenTaiko/Global/PuchiChara/01 - Template/Unlock.json b/OpenTaiko/Global/PuchiChara/01 - Template/Unlock.json new file mode 100644 index 00000000..08e45088 --- /dev/null +++ b/OpenTaiko/Global/PuchiChara/01 - Template/Unlock.json @@ -0,0 +1,7 @@ +{ + "condition": "tp", + "type": "me", + "values": [ + 1, + ], +} \ No newline at end of file diff --git a/OpenTaiko/src/Databases/DBUnlockables.cs b/OpenTaiko/src/Databases/DBUnlockables.cs index 9cf4630f..77c5cb84 100644 --- a/OpenTaiko/src/Databases/DBUnlockables.cs +++ b/OpenTaiko/src/Databases/DBUnlockables.cs @@ -68,6 +68,7 @@ namespace TJAPlayer3 } /* + * (Note: Currently only me is relevant, the other types might be used in the future) * == Types of conditions == * l : "Less than" * le : "Less or equal" @@ -114,7 +115,7 @@ namespace TJAPlayer3 * ig : "Impossible to Get", (not recommanded) used to be able to have content in database that is impossible to unlock, no values * */ - public (bool, string) tConditionMetWrapper(int player, EScreen screen = EScreen.MyRoom) + public (bool, string?) tConditionMetWrapper(int player, EScreen screen = EScreen.MyRoom) { if (RequiredArgCount < 0 && RequiredArgs.ContainsKey(Condition)) RequiredArgCount = RequiredArgs[Condition]; @@ -170,7 +171,7 @@ namespace TJAPlayer3 } - public (bool, string) tConditionMet(int[] inputValues, EScreen screen) + public (bool, string?) tConditionMet(int[] inputValues, EScreen screen) { // Trying to unlock an item from the My Room menu (If my room buy => check if enough coints, else => Display a hint to how to get the item) if (screen == EScreen.MyRoom) @@ -182,8 +183,8 @@ namespace TJAPlayer3 this.Type = "me"; bool fulfiled = this.tValueRequirementMet(inputValues[0], this.Values[0]); return (fulfiled, CLangManager.LangInstance.GetString(90003 + ((fulfiled == false) ? 1 : 0))); - case "cs": - return (false, CLangManager.LangInstance.GetString(90001)); // Will be buyable later from the randomized shop + default: + return (false, null); // Return the same text if my room } } // Unlockables from result screen or specific events (If any buy event => Invalid command, else check) @@ -252,6 +253,7 @@ namespace TJAPlayer3 // Only the player loaded as 1P can check unlockables in real time var SaveData = TJAPlayer3.SaveFileInstances[TJAPlayer3.SaveFile].data; + var ChartStats = SaveData.bestPlaysStats; switch (this.Condition) { @@ -260,8 +262,52 @@ namespace TJAPlayer3 case "cs": return (CLangManager.LangInstance.GetString(90001)); // Will be buyable later from the randomized shop case "ce": - return CLangManager.LangInstance.GetString(90006).SafeFormat(this.Values[0]); + return CLangManager.LangInstance.GetString(90006).SafeFormat(this.Values[0], SaveData.TotalEarnedMedals); + case "ap": + return CLangManager.LangInstance.GetString(90007).SafeFormat(this.Values[0], SaveData.AIBattleModePlaycount); + case "aw": + return CLangManager.LangInstance.GetString(90008).SafeFormat(this.Values[0], SaveData.AIBattleModeWins); + case "tp": + return CLangManager.LangInstance.GetString(90009).SafeFormat(this.Values[0], SaveData.TotalPlaycount); + case "dp": + { + var _aimedDifficulty = this.Values[0]; + var _aimedStatus = this.Values[1]; + + if (_aimedStatus < (int)EClearStatus.NONE || _aimedStatus >= (int)EClearStatus.TOTAL) return (CLangManager.LangInstance.GetString(90000)); + if (_aimedDifficulty < (int)Difficulty.Easy || _aimedDifficulty > (int)Difficulty.Edit) return (CLangManager.LangInstance.GetString(90000)); + + var _table = ChartStats.ClearStatuses[_aimedDifficulty]; + var _ura = ChartStats.ClearStatuses[(int)Difficulty.Edit]; + int _count = 0; + for (int i = _aimedStatus; i < (int)EClearStatus.TOTAL; i++) + { + _count += _table[i]; + if (_aimedDifficulty == (int)Difficulty.Oni) _count += _ura[i]; + } + var diffString = (_aimedDifficulty == (int)Difficulty.Oni) ? CLangManager.LangInstance.GetString(92013) : CLangManager.LangInstance.GetString(92000 + _aimedDifficulty); + var statusString = CLangManager.LangInstance.GetString(91010 + _aimedStatus); + return CLangManager.LangInstance.GetString(90010).SafeFormat(statusString, this.Values[2], diffString, _count); + } + case "lp": + { + var _aimedDifficulty = this.Values[0]; + var _aimedStatus = this.Values[1]; + + if (_aimedStatus < (int)EClearStatus.NONE || _aimedStatus >= (int)EClearStatus.TOTAL) return (CLangManager.LangInstance.GetString(90000)); + + int _count = 0; + if (_aimedStatus == (int)EClearStatus.NONE) _count = ChartStats.LevelPlays.TryGetValue(_aimedDifficulty, out var value) ? value : 0; + else if (_aimedStatus <= (int)EClearStatus.CLEAR) _count = ChartStats.LevelClears.TryGetValue(_aimedDifficulty, out var value) ? value : 0; + else if (_aimedStatus == (int)EClearStatus.FC) _count = ChartStats.LevelFCs.TryGetValue(_aimedDifficulty, out var value) ? value : 0; + else _count = ChartStats.LevelPerfects.TryGetValue(_aimedDifficulty, out var value) ? value : 0; + + var statusString = CLangManager.LangInstance.GetString(91010 + _aimedStatus); + return CLangManager.LangInstance.GetString(90011).SafeFormat(statusString, this.Values[2], _aimedDifficulty, _count); + } + } + // Includes cm or ig which are not supposed to be displayed in My Room return (CLangManager.LangInstance.GetString(90000)); } diff --git a/OpenTaiko/src/I18N/CLang_en.cs b/OpenTaiko/src/I18N/CLang_en.cs index 33cdf345..e2058758 100644 --- a/OpenTaiko/src/I18N/CLang_en.cs +++ b/OpenTaiko/src/I18N/CLang_en.cs @@ -496,6 +496,7 @@ namespace TJAPlayer3 [90011] = "{0} {1} songs with a star rating of {2} to unlock this item! ({3}/{1})", // lp [91000] = "Play", + [91010] = "Play", [91001] = "Get an Assisted Clear on", [91011] = "Get at least an Assisted Clear on", [91002] = "Get a Clear on", @@ -503,6 +504,7 @@ namespace TJAPlayer3 [91003] = "Get a Full Combo on", [91013] = "Get at least a Full Combo on", [91004] = "Get a Perfect on", + [91014] = "Get a Perfect on", [92000] = "Easy", [92001] = "Normal", @@ -512,6 +514,7 @@ namespace TJAPlayer3 [92013] = "Extreme/Extra Extreme", [92005] = "Tower", [92006] = "Dan", + [92100] = "Any", [900] = "Resume", [901] = "Restart", diff --git a/OpenTaiko/src/I18N/CLang_jp.cs b/OpenTaiko/src/I18N/CLang_jp.cs index 115a8e8c..1d5420e4 100644 --- a/OpenTaiko/src/I18N/CLang_jp.cs +++ b/OpenTaiko/src/I18N/CLang_jp.cs @@ -558,7 +558,35 @@ namespace TJAPlayer3 [90004] = "コインが足りません !", [90005] = "下記の条件 : ", - [900] = "もどる", + [90006] = "{0}コインを稼ぎましょう! ({1}/{0})", // ce + [90007] = "AI演奏バトルを{0}回挑戦しましょう! ({1}/{0})", // ap + [90008] = "AI演奏バトルを{0}回勝利しましょう! ({1}/{0})", // aw + [90009] = "{0}回プレイしましょう! ({1}/{0})", // tp + [90010] = "{2}で{1}譜面を{0}しましょう! ({3}/{1})", // dp + [90011] = "{2}★の{1}譜面を{0}しましょう! ({3}/{1})", // lp + + [91000] = "プレイ", + [91010] = "プレイ", + [91001] = "仮クリア", + [91011] = "仮クリア(以上)", + [91002] = "クリア", + [91012] = "クリア(以上)", + [91003] = "フルコンボ", + [91013] = "フルコンボ(以上)", + [91004] = "全良", + [91014] = "全良", + + [92000] = "かんたん", + [92001] = "ふつう", + [92002] = "むずかしい", + [92003] = "おに(表)", + [92004] = "おに(裏)", + [92013] = "おに", + [92005] = "タワー", + [92006] = "段位", + [92100] = "難易度問わず", + + [900] = "もどる", [901] = "やりなおす", [902] = "演奏中止", diff --git a/OpenTaiko/src/Stages/11.Heya/CStageHeya.cs b/OpenTaiko/src/Stages/11.Heya/CStageHeya.cs index ca64dbfb..f702d4c6 100644 --- a/OpenTaiko/src/Stages/11.Heya/CStageHeya.cs +++ b/OpenTaiko/src/Stages/11.Heya/CStageHeya.cs @@ -893,8 +893,11 @@ namespace TJAPlayer3 if (TJAPlayer3.Tx.Characters[iCharacterCurrent].unlock != null && !TJAPlayer3.SaveFileInstances[iPlayer].data.UnlockedCharacters.Contains(TJAPlayer3.Skin.Characters_DirName[iCharacterCurrent])) { - this.ttkInfoSection = new TitleTextureKey(TJAPlayer3.Tx.Characters[iCharacterCurrent].unlock.tConditionMessage() - , this.pfHeyaFont, Color.White, Color.Black, 1000); + string _cond = "???"; + if (HRarity.tRarityToModalInt(TJAPlayer3.Tx.Characters[iCharacterCurrent].metadata.Rarity) + < HRarity.tRarityToModalInt("Epic")) + _cond = TJAPlayer3.Tx.Characters[iCharacterCurrent].unlock.tConditionMessage(); + this.ttkInfoSection = new TitleTextureKey(_cond, this.pfHeyaFont, Color.White, Color.Black, 1000); } else this.ttkInfoSection = null; @@ -908,7 +911,7 @@ namespace TJAPlayer3 if (TJAPlayer3.Tx.Characters[iCharacterCurrent].unlock != null && !TJAPlayer3.SaveFileInstances[iPlayer].data.UnlockedCharacters.Contains(TJAPlayer3.Skin.Characters_DirName[iCharacterCurrent])) { - (bool, string) response = TJAPlayer3.Tx.Characters[iCharacterCurrent].unlock.tConditionMetWrapper(TJAPlayer3.SaveFile); + (bool, string?) response = TJAPlayer3.Tx.Characters[iCharacterCurrent].unlock.tConditionMetWrapper(TJAPlayer3.SaveFile); //TJAPlayer3.Tx.Characters[iCharacterCurrent].unlock.tConditionMet( //new int[] { TJAPlayer3.SaveFileInstances[TJAPlayer3.SaveFile].data.Medals }); @@ -916,7 +919,7 @@ namespace TJAPlayer3 // Send coins here for the unlock, considering that only coin-paid puchicharas can be unlocked directly from the Heya menu - this.ttkInfoSection = new TitleTextureKey(response.Item2, this.pfHeyaFont, responseColor, Color.Black, 1000); + this.ttkInfoSection = new TitleTextureKey(response.Item2 ?? this.ttkInfoSection.str文字, this.pfHeyaFont, responseColor, Color.Black, 1000); return (response.Item1) ? ESelectStatus.SUCCESS : ESelectStatus.FAILED; } @@ -935,8 +938,11 @@ namespace TJAPlayer3 if (TJAPlayer3.Tx.Puchichara[iPuchiCharaCurrent].unlock != null && !TJAPlayer3.SaveFileInstances[iPlayer].data.UnlockedPuchicharas.Contains(TJAPlayer3.Skin.Puchicharas_Name[iPuchiCharaCurrent])) { - this.ttkInfoSection = new TitleTextureKey(TJAPlayer3.Tx.Puchichara[iPuchiCharaCurrent].unlock.tConditionMessage() - , this.pfHeyaFont, Color.White, Color.Black, 1000); + string _cond = "???"; + if (HRarity.tRarityToModalInt(TJAPlayer3.Tx.Puchichara[iPuchiCharaCurrent].metadata.Rarity) + < HRarity.tRarityToModalInt("Epic")) + _cond = TJAPlayer3.Tx.Puchichara[iPuchiCharaCurrent].unlock.tConditionMessage(); + this.ttkInfoSection = new TitleTextureKey(_cond, this.pfHeyaFont, Color.White, Color.Black, 1000); } else this.ttkInfoSection = null; @@ -951,7 +957,7 @@ namespace TJAPlayer3 if (TJAPlayer3.Tx.Puchichara[iPuchiCharaCurrent].unlock != null && !TJAPlayer3.SaveFileInstances[iPlayer].data.UnlockedPuchicharas.Contains(TJAPlayer3.Skin.Puchicharas_Name[iPuchiCharaCurrent])) { - (bool, string) response = TJAPlayer3.Tx.Puchichara[iPuchiCharaCurrent].unlock.tConditionMetWrapper(TJAPlayer3.SaveFile); + (bool, string?) response = TJAPlayer3.Tx.Puchichara[iPuchiCharaCurrent].unlock.tConditionMetWrapper(TJAPlayer3.SaveFile); //tConditionMet( //new int[] { TJAPlayer3.SaveFileInstances[TJAPlayer3.SaveFile].data.Medals }); @@ -959,7 +965,7 @@ namespace TJAPlayer3 // Send coins here for the unlock, considering that only coin-paid puchicharas can be unlocked directly from the Heya menu - this.ttkInfoSection = new TitleTextureKey(response.Item2, this.pfHeyaFont, responseColor, Color.Black, 1000); + this.ttkInfoSection = new TitleTextureKey(response.Item2 ?? this.ttkInfoSection.str文字, this.pfHeyaFont, responseColor, Color.Black, 1000); return (response.Item1) ? ESelectStatus.SUCCESS : ESelectStatus.FAILED; } diff --git a/OpenTaiko/src/Stages/CActNewHeya.cs b/OpenTaiko/src/Stages/CActNewHeya.cs index 7e15b747..cd46b50e 100644 --- a/OpenTaiko/src/Stages/CActNewHeya.cs +++ b/OpenTaiko/src/Stages/CActNewHeya.cs @@ -704,7 +704,7 @@ namespace TJAPlayer3 if (TJAPlayer3.Tx.Puchichara[CurrentIndex].unlock != null && !TJAPlayer3.SaveFileInstances[CurrentPlayer].data.UnlockedPuchicharas.Contains(TJAPlayer3.Skin.Puchicharas_Name[CurrentIndex])) { - (bool, string) response = TJAPlayer3.Tx.Puchichara[CurrentIndex].unlock.tConditionMetWrapper(TJAPlayer3.SaveFile); + (bool, string?) response = TJAPlayer3.Tx.Puchichara[CurrentIndex].unlock.tConditionMetWrapper(TJAPlayer3.SaveFile); //tConditionMet( //new int[] { TJAPlayer3.SaveFileInstances[TJAPlayer3.SaveFile].data.Medals }); @@ -712,7 +712,7 @@ namespace TJAPlayer3 // Send coins here for the unlock, considering that only coin-paid puchicharas can be unlocked directly from the Heya menu - this.ttkInfoSection = new CActSelect曲リスト.TitleTextureKey(response.Item2, this.MenuFont, responseColor, Color.Black, 1000); + this.ttkInfoSection = new CActSelect曲リスト.TitleTextureKey(response.Item2 ?? this.ttkInfoSection.str文字, this.MenuFont, responseColor, Color.Black, 1000); return (response.Item1) ? ESelectStatus.SUCCESS : ESelectStatus.FAILED; } @@ -759,7 +759,7 @@ namespace TJAPlayer3 if (TJAPlayer3.Tx.Characters[CurrentIndex].unlock != null && !TJAPlayer3.SaveFileInstances[CurrentPlayer].data.UnlockedCharacters.Contains(TJAPlayer3.Skin.Characters_DirName[CurrentIndex])) { - (bool, string) response = TJAPlayer3.Tx.Characters[CurrentIndex].unlock.tConditionMetWrapper(TJAPlayer3.SaveFile); + (bool, string?) response = TJAPlayer3.Tx.Characters[CurrentIndex].unlock.tConditionMetWrapper(TJAPlayer3.SaveFile); //TJAPlayer3.Tx.Characters[iCharacterCurrent].unlock.tConditionMet( //new int[] { TJAPlayer3.SaveFileInstances[TJAPlayer3.SaveFile].data.Medals }); @@ -767,7 +767,7 @@ namespace TJAPlayer3 // Send coins here for the unlock, considering that only coin-paid puchicharas can be unlocked directly from the Heya menu - this.ttkInfoSection = new CActSelect曲リスト.TitleTextureKey(response.Item2, this.MenuFont, responseColor, Color.Black, 1000); + this.ttkInfoSection = new CActSelect曲リスト.TitleTextureKey(response.Item2 ?? this.ttkInfoSection.str文字, this.MenuFont, responseColor, Color.Black, 1000); return (response.Item1) ? ESelectStatus.SUCCESS : ESelectStatus.FAILED; }