feat: 成就 dlc (#15288)

* feat: 成就描述与翻译

* feat: 开着日志悬浮窗完成一次任务

* feat: 在公开招募中刷新标签 50 次

* feat: 累计开启线索交流 20/50 次

* feat: 累计向好友发送 20/50 次线索

* feat: 单次运行中,勾选超过 7 个任务

* feat: 在更新发布后 1 天/1 小时 内完成更新

* feat: 完成{key=Combat}时刚好消耗完所有理智

* feat: 设置并使用一个超过 4 个修饰键的热键组合

* feat: 仓库识别功能识别到仓库内某种材料数量超过 5000 个(不包括作战记录!)

* perf: 优化界面布局

* chore: 调整触发条件

* fix: 部分成就弹窗无法显示

* feat: 单轮公招任务连续招募 10/20 次

* feat: 支持组内排序

* perf: 优化成就排序

* feat: 干员识别中包含干员“帕拉斯”

* feat: 使用远程协议调用错误的任务 id

* feat: 尝试切换界面语言

* feat: 设置开机启动 MAA

* feat: 连续 7 天每天集齐并开启线索交流

* feat: 325

* chore: 调整 325 触发条件
This commit is contained in:
uye
2026-01-05 20:30:26 +08:00
committed by GitHub
parent c6037cc4d7
commit 3d42e5e55f
20 changed files with 794 additions and 156 deletions

View File

@@ -46,6 +46,19 @@ public static class AchievementIds
public const string SanityExpire = "SanityExpire";
public const string OverLimitAgent = "OverLimitAgent";
public const string RecruitGambler = "RecruitGambler";
public const string ClueUseGroup = "ClueUse";
public const string ClueCollector = "ClueCollector";
public const string CluePhilosopher = "CluePhilosopher";
public const string ClueSendGroup = "ClueSend";
public const string ClueSharer = "ClueSharer";
public const string CluePhilanthropist = "CluePhilanthropist";
public const string ClueObsession = "ClueObsession";
public const string ClueObsessionCustomDataKey = "LastOpeningData";
#endregion
#region
@@ -69,6 +82,19 @@ public static class AchievementIds
public const string PeekScreen = "PeekScreen";
public const string CustomizationMaster = "CustomizationMaster";
public const string LogSupervisor = "LogSupervisor";
public const string TaskChainKing = "TaskChainKing";
public const string HotkeyMagician = "HotkeyMagician";
public const string WarehouseMiser = "WarehouseMiser";
public const string HrManager = "HrManager";
public const string HrSpecialist = "HrSpecialist";
public const string HrSeniorSpecialist = "HrSeniorSpecialist";
public const string NotFound404 = "NotFound404";
public const string Linguist = "Linguist";
public const string StartupBoot = "StartupBoot";
#endregion
#region
@@ -108,6 +134,8 @@ public static class AchievementIds
public const string SnapshotChallenge5 = "SnapshotChallenge5"; // 10
public const string SnapshotChallenge6 = "SnapshotChallenge6"; // 5
public const string Time325 = "Time325"; // 325
#endregion
#region BUG
@@ -134,6 +162,10 @@ public static class AchievementIds
public const string UseDaily2 = "UseDaily2"; // 30 天
public const string UseDaily3 = "UseDaily3"; // 365 天
public const string UpdateGroup = "Update";
public const string UpdateObsession = "UpdateObsession";
public const string UpdateEarlyBird = "UpdateEarlyBird";
#endregion
#region
@@ -147,5 +179,8 @@ public static class AchievementIds
public const string MidnightLaunch = "MidnightLaunch";
public const string LunarNewYear = "LunarNewYear";
public const string SanityPlanner = "SanityPlanner";
public const string WarehouseKeeper = "WarehouseKeeper";
#endregion
}

View File

@@ -42,15 +42,39 @@ public class AchievementTrackerHelper : PropertyChangedBase
Sort();
if (Instances.MainWindowManager is not null)
{
Instances.MainWindowManager.WindowRestored += (_, _) =>
{
TryShowPendingGrowls();
AttachWindowRestoredHandler();
}
else
{
// 这里可以简化,因为事件触发时 MainWindowManager 肯定不为 null
Instances.MainWindowManagerInstantiated += (_, _) => {
var win = Instances.MainWindowManager?.GetWindowIfVisible();
if (win == null)
{
AttachWindowRestoredHandler();
}
else
{
TryShowPendingGrowls();
}
};
}
SearchCmd = new RelayCommand<string>(Search);
}
private void AttachWindowRestoredHandler()
{
// 防止重复订阅
Instances.MainWindowManager.WindowRestored -= OnWindowRestored;
Instances.MainWindowManager.WindowRestored += OnWindowRestored;
}
private void OnWindowRestored(object? sender, EventArgs e)
{
TryShowPendingGrowls();
}
public static AchievementTrackerHelper Instance { get; } = new();
private Dictionary<string, Achievement> _achievements = [];
@@ -58,8 +82,7 @@ public class AchievementTrackerHelper : PropertyChangedBase
public Dictionary<string, Achievement> Achievements
{
get => _achievements;
set
{
set {
SetAndNotify(ref _achievements, value);
NotifyOfPropertyChange(nameof(UnlockedCount));
NotifyOfPropertyChange(nameof(VisibleAchievements));
@@ -142,6 +165,7 @@ public class AchievementTrackerHelper : PropertyChangedBase
.ThenByDescending(kv => kv.Value.IsNewUnlock) // 新解锁的排前面
.ThenBy(kv => kv.Value.Category) // 按类别分组
.ThenBy(kv => kv.Value.Group)
.ThenBy(kv => kv.Value.GroupIndex) // 组内排序
.ThenBy(kv => kv.Value.Id) // 最后按 Id
.ToDictionary(kv => kv.Key, kv => kv.Value);
}
@@ -186,8 +210,7 @@ public class AchievementTrackerHelper : PropertyChangedBase
achievement.IsNewUnlock = true;
Save();
var growlInfo = new GrowlInfo
{
var growlInfo = new GrowlInfo {
IsCustom = true,
Message = $"{LocalizationHelper.GetString("AchievementCelebrate")}: {achievement.Title}\n{achievement.Description}",
StaysOpen = forceStayOpen || (staysOpen && !SettingsViewModel.AchievementSettings.AchievementPopupAutoClose),
@@ -195,7 +218,7 @@ public class AchievementTrackerHelper : PropertyChangedBase
IconKey = "HangoverGeometry",
IconBrushKey = achievement.MedalBrushKey,
};
ShowInfo(growlInfo);
ShowInfo(growlInfo, forceStayOpen: forceStayOpen);
}
public async Task UnlockAll()
@@ -250,17 +273,16 @@ public class AchievementTrackerHelper : PropertyChangedBase
private static readonly List<GrowlInfo> _pending = [];
public static void ShowInfo(GrowlInfo info)
public static void ShowInfo(GrowlInfo info, bool forceStayOpen = false)
{
// 检查是否禁用了成就通知
if (SettingsViewModel.AchievementSettings.AchievementPopupDisabled)
if (SettingsViewModel.AchievementSettings.AchievementPopupDisabled && !forceStayOpen)
{
return;
}
Execute.OnUIThread(() =>
{
var win = Instances.MainWindowManager.GetWindowIfVisible();
Execute.OnUIThread(() => {
var win = Instances.MainWindowManager?.GetWindowIfVisible();
if (win == null)
{
_pending.Add(info);
@@ -273,12 +295,14 @@ public class AchievementTrackerHelper : PropertyChangedBase
public static void TryShowPendingGrowls()
{
foreach (var info in _pending)
{
Growl.Info(info);
}
Execute.OnUIThread(() => {
foreach (var info in _pending)
{
Growl.Info(info);
}
_pending.Clear();
_pending.Clear();
});
}
private void CheckProgressUnlock(Achievement achievement)
@@ -305,14 +329,37 @@ public class AchievementTrackerHelper : PropertyChangedBase
Save();
}
public void AddProgressToGroup(string groupPrefix, int amount = 1)
public void AddProgressToGroup(string group, int amount = 1)
{
foreach (var achievement in _achievements.Values.Where(achievement => achievement.Group == groupPrefix))
foreach (var achievement in _achievements.Values.Where(achievement => achievement.Group == group))
{
AddProgress(achievement.Id, amount);
}
}
public int GetProgress(string id)
{
if (!_achievements.TryGetValue(id, out var achievement))
{
return 0;
}
return achievement.Progress;
}
public int GetProgressToGroup(string group)
{
var maxProgress = 0;
foreach (var achievement in _achievements.Values.Where(achievement => achievement.Group == group))
{
if (achievement.Progress > maxProgress)
{
maxProgress = achievement.Progress;
}
}
return maxProgress;
}
public void SetProgress(string id, int progress)
{
if (!_achievements.TryGetValue(id, out var achievement))
@@ -325,9 +372,9 @@ public class AchievementTrackerHelper : PropertyChangedBase
Save();
}
public void SetProgressToGroup(string groupPrefix, int progress)
public void SetProgressToGroup(string group, int progress)
{
foreach (var achievement in _achievements.Values.Where(achievement => achievement.Group == groupPrefix))
foreach (var achievement in _achievements.Values.Where(achievement => achievement.Group == group))
{
SetProgress(achievement.Id, progress);
}
@@ -372,26 +419,26 @@ public class AchievementTrackerHelper : PropertyChangedBase
#region
private static Achievement BasicUsage(string id, string group = "", int? target = null, bool isHidden = false, bool isRare = false)
=> new() { Id = id, Group = group, Target = target ?? 0, IsHidden = isHidden, Category = AchievementCategory.BasicUsage, IsRare = isRare };
private static Achievement BasicUsage(string id, string group = "", int? target = null, bool isHidden = false, bool isRare = false, int groupIndex = int.MaxValue)
=> new() { Id = id, Group = group, Target = target ?? 0, IsHidden = isHidden, Category = AchievementCategory.BasicUsage, IsRare = isRare, GroupIndex = groupIndex };
private static Achievement FeatureExploration(string id, string group = "", int? target = null, bool isHidden = false, bool isRare = false)
=> new() { Id = id, Group = group, Target = target ?? 0, IsHidden = isHidden, Category = AchievementCategory.FeatureExploration, IsRare = isRare };
private static Achievement FeatureExploration(string id, string group = "", int? target = null, bool isHidden = false, bool isRare = false, int groupIndex = int.MaxValue)
=> new() { Id = id, Group = group, Target = target ?? 0, IsHidden = isHidden, Category = AchievementCategory.FeatureExploration, IsRare = isRare, GroupIndex = groupIndex };
private static Achievement AutoBattle(string id, string group = "", int? target = null, bool isHidden = false, bool isRare = false)
=> new() { Id = id, Group = group, Target = target ?? 0, IsHidden = isHidden, Category = AchievementCategory.AutoBattle, IsRare = isRare };
private static Achievement AutoBattle(string id, string group = "", int? target = null, bool isHidden = false, bool isRare = false, int groupIndex = int.MaxValue)
=> new() { Id = id, Group = group, Target = target ?? 0, IsHidden = isHidden, Category = AchievementCategory.AutoBattle, IsRare = isRare, GroupIndex = groupIndex };
private static Achievement Humor(string id, string group = "", int? target = null, bool isHidden = false, bool isRare = false)
=> new() { Id = id, Group = group, Target = target ?? 0, IsHidden = isHidden, Category = AchievementCategory.Humor, IsRare = isRare };
private static Achievement Humor(string id, string group = "", int? target = null, bool isHidden = false, bool isRare = false, int groupIndex = int.MaxValue)
=> new() { Id = id, Group = group, Target = target ?? 0, IsHidden = isHidden, Category = AchievementCategory.Humor, IsRare = isRare, GroupIndex = groupIndex };
private static Achievement BugRelated(string id, string group = "", int? target = null, bool isHidden = false, bool isRare = false)
=> new() { Id = id, Group = group, Target = target ?? 0, IsHidden = isHidden, Category = AchievementCategory.BugRelated, IsRare = isRare };
private static Achievement BugRelated(string id, string group = "", int? target = null, bool isHidden = false, bool isRare = false, int groupIndex = int.MaxValue)
=> new() { Id = id, Group = group, Target = target ?? 0, IsHidden = isHidden, Category = AchievementCategory.BugRelated, IsRare = isRare, GroupIndex = groupIndex };
private static Achievement Behavior(string id, string group = "", int? target = null, bool isHidden = false, bool isRare = false)
=> new() { Id = id, Group = group, Target = target ?? 0, IsHidden = isHidden, Category = AchievementCategory.Behavior, IsRare = isRare };
private static Achievement Behavior(string id, string group = "", int? target = null, bool isHidden = false, bool isRare = false, int groupIndex = int.MaxValue)
=> new() { Id = id, Group = group, Target = target ?? 0, IsHidden = isHidden, Category = AchievementCategory.Behavior, IsRare = isRare, GroupIndex = groupIndex };
private static Achievement EasterEgg(string id, string group = "", int? target = null, bool isHidden = false, bool isRare = false)
=> new() { Id = id, Group = group, Target = target ?? 0, IsHidden = isHidden, Category = AchievementCategory.EasterEgg, IsRare = isRare };
private static Achievement EasterEgg(string id, string group = "", int? target = null, bool isHidden = false, bool isRare = false, int groupIndex = int.MaxValue)
=> new() { Id = id, Group = group, Target = target ?? 0, IsHidden = isHidden, Category = AchievementCategory.EasterEgg, IsRare = isRare, GroupIndex = groupIndex };
#endregion
@@ -399,22 +446,22 @@ public class AchievementTrackerHelper : PropertyChangedBase
[
#region 基础使用类
BasicUsage(id: AchievementIds.SanitySpender1, group: AchievementIds.SanitySpenderGroup, target: 10), // 理智作战次数
BasicUsage(id: AchievementIds.SanitySpender2, group: AchievementIds.SanitySpenderGroup, target: 100),
BasicUsage(id: AchievementIds.SanitySpender3, group: AchievementIds.SanitySpenderGroup, target: 1000),
BasicUsage(id: AchievementIds.SanitySpender1, group: AchievementIds.SanitySpenderGroup, target: 10, groupIndex: 1), // 理智作战次数
BasicUsage(id: AchievementIds.SanitySpender2, group: AchievementIds.SanitySpenderGroup, target: 100, groupIndex: 2),
BasicUsage(id: AchievementIds.SanitySpender3, group: AchievementIds.SanitySpenderGroup, target: 1000, groupIndex: 3),
BasicUsage(id: AchievementIds.SanitySaver1, group: AchievementIds.SanitySaverGroup, target: 1), // 使用理智药数
BasicUsage(id: AchievementIds.SanitySaver2, group: AchievementIds.SanitySaverGroup, target: 10),
BasicUsage(id: AchievementIds.SanitySaver3, group: AchievementIds.SanitySaverGroup, target: 50),
BasicUsage(id: AchievementIds.SanitySaver1, group: AchievementIds.SanitySaverGroup, target: 1, groupIndex: 1), // 使用理智药数
BasicUsage(id: AchievementIds.SanitySaver2, group: AchievementIds.SanitySaverGroup, target: 10, groupIndex: 2),
BasicUsage(id: AchievementIds.SanitySaver3, group: AchievementIds.SanitySaverGroup, target: 50, groupIndex: 3),
BasicUsage(id: AchievementIds.RoguelikeGamePass1, group: AchievementIds.RoguelikeGamePassGroup, target: 1), // 使用牛牛通关肉鸽
BasicUsage(id: AchievementIds.RoguelikeGamePass2, group: AchievementIds.RoguelikeGamePassGroup, target: 5),
BasicUsage(id: AchievementIds.RoguelikeGamePass3, group: AchievementIds.RoguelikeGamePassGroup, target: 10),
BasicUsage(id: AchievementIds.RoguelikeGamePass1, group: AchievementIds.RoguelikeGamePassGroup, target: 1, groupIndex: 1), // 使用牛牛通关肉鸽
BasicUsage(id: AchievementIds.RoguelikeGamePass2, group: AchievementIds.RoguelikeGamePassGroup, target: 5, groupIndex: 2),
BasicUsage(id: AchievementIds.RoguelikeGamePass3, group: AchievementIds.RoguelikeGamePassGroup, target: 10, groupIndex: 3),
BasicUsage(id: AchievementIds.RoguelikeN04, group: AchievementIds.RoguelikeNGroup), // 肉鸽 难度 通关
BasicUsage(id: AchievementIds.RoguelikeN08, group: AchievementIds.RoguelikeNGroup),
BasicUsage(id: AchievementIds.RoguelikeN12, group: AchievementIds.RoguelikeNGroup),
BasicUsage(id: AchievementIds.RoguelikeN15, group: AchievementIds.RoguelikeNGroup, isRare: true),
BasicUsage(id: AchievementIds.RoguelikeN04, group: AchievementIds.RoguelikeNGroup, groupIndex: 1), // 肉鸽 难度 通关
BasicUsage(id: AchievementIds.RoguelikeN08, group: AchievementIds.RoguelikeNGroup, groupIndex: 2),
BasicUsage(id: AchievementIds.RoguelikeN12, group: AchievementIds.RoguelikeNGroup, groupIndex: 3),
BasicUsage(id: AchievementIds.RoguelikeN15, group: AchievementIds.RoguelikeNGroup, isRare: true, groupIndex: 4),
BasicUsage(id: AchievementIds.RoguelikeRetreat, group: AchievementIds.RoguelikeGroup, target: 100), // 牛牛放弃探索 100 次
BasicUsage(id: AchievementIds.RoguelikeGoldMax, group: AchievementIds.RoguelikeGroup, target: 999), // 肉鸽源石锭到达 999
@@ -422,33 +469,54 @@ public class AchievementTrackerHelper : PropertyChangedBase
BasicUsage(id: AchievementIds.FirstLaunch), // 首次启动
BasicUsage(id: AchievementIds.SanityExpire, target: 8), // 单次消耗 8 瓶快过期的理智药
BasicUsage(id: AchievementIds.OverLimitAgent, target: 100, isHidden: true), // 单次代理 100 关
BasicUsage(id: AchievementIds.RecruitGambler, target: 50), // 公招赌徒
BasicUsage(id: AchievementIds.ClueCollector, group: AchievementIds.ClueUseGroup, target: 20, groupIndex: 1), // 线索搜集
BasicUsage(id: AchievementIds.CluePhilosopher, group: AchievementIds.ClueUseGroup, target: 50, groupIndex: 2), // 线索哲学家
BasicUsage(id: AchievementIds.ClueObsession, target: 7, isRare: true, groupIndex: 3), // 线索强迫症
BasicUsage(id: AchievementIds.ClueSharer, group: AchievementIds.ClueSendGroup, target: 20, groupIndex: 1), // 线索分享
BasicUsage(id: AchievementIds.CluePhilanthropist, group: AchievementIds.ClueSendGroup, target: 50, groupIndex: 2), // 线索慈善家
#endregion
#region 功能探索类
FeatureExploration(id: AchievementIds.ScheduleMaster1, group: AchievementIds.ScheduleMasterGroup, target: 1), // 定时执行
FeatureExploration(id: AchievementIds.ScheduleMaster2, group: AchievementIds.ScheduleMasterGroup, target: 100),
FeatureExploration(id: AchievementIds.ScheduleMaster1, group: AchievementIds.ScheduleMasterGroup, target: 1, groupIndex: 1), // 定时执行
FeatureExploration(id: AchievementIds.ScheduleMaster2, group: AchievementIds.ScheduleMasterGroup, target: 100, groupIndex: 2),
FeatureExploration(id: AchievementIds.MirrorChyanFirstUse, group: AchievementIds.MirrorChyanGroup, isHidden: true), // 第一次成功使用 MirrorChyan 下载
FeatureExploration(id: AchievementIds.MirrorChyanCdkError, group: AchievementIds.MirrorChyanGroup, isHidden: true), // MirrorChyan CDK 错误
FeatureExploration(id: AchievementIds.Pioneer1, group: AchievementIds.PioneerGroup), // 将 MAA 更新至公测版
FeatureExploration(id: AchievementIds.Pioneer2, group: AchievementIds.PioneerGroup, isHidden: true), // 将 MAA 更新至内测版(隐藏)
FeatureExploration(id: AchievementIds.Pioneer3, group: AchievementIds.PioneerGroup, isHidden: true), // 使用未发布版本的 MAA隐藏
FeatureExploration(id: AchievementIds.Pioneer1, group: AchievementIds.PioneerGroup, groupIndex: 1), // 将 MAA 更新至公测版
FeatureExploration(id: AchievementIds.Pioneer2, group: AchievementIds.PioneerGroup, isHidden: true, groupIndex: 2), // 将 MAA 更新至内测版(隐藏)
FeatureExploration(id: AchievementIds.Pioneer3, group: AchievementIds.PioneerGroup, isHidden: true, groupIndex: 3), // 使用未发布版本的 MAA隐藏
FeatureExploration(id: AchievementIds.MosquitoLeg, target: 5), // 使用「借助战打 OF-1」功能超过 5 次
FeatureExploration(id: AchievementIds.RealGacha, isHidden: true), // 真正的抽卡
FeatureExploration(id: AchievementIds.PeekScreen, isHidden: true), // 窥屏
FeatureExploration(id: AchievementIds.CustomizationMaster, isHidden: true), // 自定义背景
FeatureExploration(id: AchievementIds.LogSupervisor), // 超级监工
FeatureExploration(id: AchievementIds.TaskChainKing, target: 7), // 任务链王
FeatureExploration(id: AchievementIds.HotkeyMagician), // 热键魔术师
FeatureExploration(id: AchievementIds.WarehouseMiser, target: 10000), // 仓库守财奴
FeatureExploration(id: AchievementIds.HrSpecialist, group: AchievementIds.HrManager, target: 10, groupIndex: 1), // 人事部专员
FeatureExploration(id: AchievementIds.HrSeniorSpecialist, group: AchievementIds.HrManager, target: 20, groupIndex: 2), // 人事部高级专员
FeatureExploration(id: AchievementIds.NotFound404, isHidden: true), // 404
FeatureExploration(id: AchievementIds.Linguist), // 语言学家
FeatureExploration(id: AchievementIds.StartupBoot), // 开机启动
#endregion
#region 自动战斗
AutoBattle(id: AchievementIds.UseCopilot1, group: AchievementIds.UseCopilotGroup, target: 1), // 自动战斗
AutoBattle(id: AchievementIds.UseCopilot2, group: AchievementIds.UseCopilotGroup, target: 10),
AutoBattle(id: AchievementIds.UseCopilot3, group: AchievementIds.UseCopilotGroup, target: 100),
AutoBattle(id: AchievementIds.UseCopilot1, group: AchievementIds.UseCopilotGroup, target: 1, groupIndex: 1), // 自动战斗
AutoBattle(id: AchievementIds.UseCopilot2, group: AchievementIds.UseCopilotGroup, target: 10, groupIndex: 2),
AutoBattle(id: AchievementIds.UseCopilot3, group: AchievementIds.UseCopilotGroup, target: 100, groupIndex: 3),
AutoBattle(id: AchievementIds.CopilotLikeGiven1, group: AchievementIds.CopilotLikeGroup, target: 1), // 点赞 1 次
AutoBattle(id: AchievementIds.CopilotLikeGiven2, group: AchievementIds.CopilotLikeGroup, target: 10), // 点赞 10 次
AutoBattle(id: AchievementIds.CopilotLikeGiven3, group: AchievementIds.CopilotLikeGroup, target: 50), // 点赞 50 次
AutoBattle(id: AchievementIds.CopilotLikeGiven1, group: AchievementIds.CopilotLikeGroup, target: 1, groupIndex: 1), // 点赞 1 次
AutoBattle(id: AchievementIds.CopilotLikeGiven2, group: AchievementIds.CopilotLikeGroup, target: 10, groupIndex: 2), // 点赞 10 次
AutoBattle(id: AchievementIds.CopilotLikeGiven3, group: AchievementIds.CopilotLikeGroup, target: 50, groupIndex: 3), // 点赞 50 次
AutoBattle(id: AchievementIds.CopilotError), // 代理作战出现失误
AutoBattle(id: AchievementIds.MapOutdated, isHidden: true), // 提示需要更新地图资源
@@ -456,20 +524,22 @@ public class AchievementTrackerHelper : PropertyChangedBase
#endregion
#region 搞笑/梗类成就
Humor(id: AchievementIds.SnapshotChallenge1, group: AchievementIds.SnapshotChallengeGroup, isHidden: true), // 平均截图用时超过 800ms高 ping 战士)
Humor(id: AchievementIds.SnapshotChallenge2, group: AchievementIds.SnapshotChallengeGroup, isHidden: true), // 平均截图用时在 400ms 到 800ms 之间(是不是有点太慢了)
Humor(id: AchievementIds.SnapshotChallenge3, group: AchievementIds.SnapshotChallengeGroup), // 平均截图用时小于 400ms截图挑战 · Normal
Humor(id: AchievementIds.SnapshotChallenge4, group: AchievementIds.SnapshotChallengeGroup), // 平均截图用时小于 100ms截图挑战 · Fast
Humor(id: AchievementIds.SnapshotChallenge5, group: AchievementIds.SnapshotChallengeGroup), // 平均截图用时小于 10ms截图挑战 · Ultra
Humor(id: AchievementIds.SnapshotChallenge6, group: AchievementIds.SnapshotChallengeGroup, isHidden: true, isRare: true), // 平均截图用时小于 5ms
Humor(id: AchievementIds.SnapshotChallenge1, group: AchievementIds.SnapshotChallengeGroup, isHidden: true, groupIndex: 6), // 平均截图用时超过 800ms高 ping 战士)
Humor(id: AchievementIds.SnapshotChallenge2, group: AchievementIds.SnapshotChallengeGroup, isHidden: true, groupIndex: 5), // 平均截图用时在 400ms 到 800ms 之间(是不是有点太慢了)
Humor(id: AchievementIds.SnapshotChallenge3, group: AchievementIds.SnapshotChallengeGroup, groupIndex: 1), // 平均截图用时小于 400ms截图挑战 · Normal
Humor(id: AchievementIds.SnapshotChallenge4, group: AchievementIds.SnapshotChallengeGroup, groupIndex: 2), // 平均截图用时小于 100ms截图挑战 · Fast
Humor(id: AchievementIds.SnapshotChallenge5, group: AchievementIds.SnapshotChallengeGroup, groupIndex: 3), // 平均截图用时小于 10ms截图挑战 · Ultra
Humor(id: AchievementIds.SnapshotChallenge6, group: AchievementIds.SnapshotChallengeGroup, isHidden: true, isRare: true, groupIndex: 4), // 平均截图用时小于 5ms
Humor(id: AchievementIds.QuickCloser, isHidden: true), // 快速关闭弹窗
Humor(id: AchievementIds.TacticalRetreat), // 停止任务
Humor(id: AchievementIds.Martian, isHidden: true), // 90 天没更新
Humor(id: AchievementIds.AnnouncementStubbornClick, isHidden: true), // 不看公告
Humor(id: AchievementIds.RecruitNoSixStar, group: AchievementIds.RecruitGroup, target: 500), // 公招中累计 500 次没出现六星tag
Humor(id: AchievementIds.RecruitNoSixStarStreak, group: AchievementIds.RecruitGroup, target: 500, isHidden: true), // 公招中连续 500 次没出现六星tag
Humor(id: AchievementIds.RecruitNoSixStar, group: AchievementIds.RecruitGroup, target: 500, groupIndex: 1), // 公招中累计 500 次没出现六星tag
Humor(id: AchievementIds.RecruitNoSixStarStreak, group: AchievementIds.RecruitGroup, target: 500, isHidden: true, groupIndex: 2), // 公招中连续 500 次没出现六星tag
Humor(id: AchievementIds.Time325, isHidden: true), // 325
#endregion
#region BUG 相关
@@ -486,9 +556,12 @@ public class AchievementTrackerHelper : PropertyChangedBase
Behavior(id: AchievementIds.TaskStartCancel, isHidden: true), // 在开始任务后马上又停止
Behavior(id: AchievementIds.AfkWatcher), // 窗口尺寸最小化后长时间不操作
Behavior(id: AchievementIds.UseDaily1, group: AchievementIds.UseDailyGroup, target: 7), // 连续使用时间
Behavior(id: AchievementIds.UseDaily2, group: AchievementIds.UseDailyGroup, target: 30),
Behavior(id: AchievementIds.UseDaily3, group: AchievementIds.UseDailyGroup, target: 365, isRare: true),
Behavior(id: AchievementIds.UseDaily1, group: AchievementIds.UseDailyGroup, target: 7, groupIndex: 1), // 连续使用时间
Behavior(id: AchievementIds.UseDaily2, group: AchievementIds.UseDailyGroup, target: 30, groupIndex: 2),
Behavior(id: AchievementIds.UseDaily3, group: AchievementIds.UseDailyGroup, target: 365, isRare: true, groupIndex: 3),
Behavior(id: AchievementIds.UpdateObsession, group: AchievementIds.UpdateGroup, groupIndex: 1), // 更新强迫症
Behavior(id: AchievementIds.UpdateEarlyBird, group: AchievementIds.UpdateGroup, isHidden: true, groupIndex: 2), // 更新尝鲜者
#endregion
#region 彩蛋类
@@ -500,6 +573,9 @@ public class AchievementTrackerHelper : PropertyChangedBase
EasterEgg(id: AchievementIds.LunarNewYear, AchievementIds.LoginGroup, isHidden: true), // 春节
EasterEgg(id: AchievementIds.Lucky, isHidden: true, isRare: true), // 启动 MAA 时有极小概率触发
EasterEgg(id: AchievementIds.SanityPlanner, isRare: true), // 理智规划师
EasterEgg(id: AchievementIds.WarehouseKeeper, isHidden: true), // 我是仓管!
#endregion
];
@@ -513,6 +589,9 @@ public class AchievementTrackerHelper : PropertyChangedBase
#region CustomData
/// <summary>
/// 一天开启 3 次任务
/// </summary>
public void MissionStartCountAdd()
{
const string Id = AchievementIds.MissionStartCount;
@@ -532,6 +611,9 @@ public class AchievementTrackerHelper : PropertyChangedBase
}
}
/// <summary>
/// 连续使用 365 天
/// </summary>
public void UseDailyAdd()
{
// group 是不注册的,从第一个成就取 CustomData
@@ -563,6 +645,34 @@ public class AchievementTrackerHelper : PropertyChangedBase
SetAchievementCustomData(Id, Key, JToken.FromObject(today));
}
/// <summary>
/// 连续 7 天开启线索交流
/// </summary>
public void ClueObsessionAdd()
{
const string Id = AchievementIds.ClueObsession;
const string Key = AchievementIds.ClueObsessionCustomDataKey;
var today = DateTime.UtcNow.ToYjDate().Date;
DateTime? lastDate = GetAchievementCustomData(Id, Key)?.ToObject<DateTime>();
if (lastDate.HasValue) {
var delta = (today - lastDate.Value).TotalDays;
switch (delta) {
case 1:
AddProgress(Id);
break;
case > 1:
SetProgress(Id, 1);
break;
}
}
else
{
SetProgress(Id, 1);
}
SetAchievementCustomData(Id, Key, JToken.FromObject(today));
}
#endregion
public static class Events
@@ -581,6 +691,16 @@ public class AchievementTrackerHelper : PropertyChangedBase
Instance.Unlock(AchievementIds.Martian);
}
var totalHours = (DateTime.UtcNow - VersionUpdateSettingsUserControlModel.BuildDateTime).TotalHours;
if (totalHours <= 1)
{
Instance.Unlock(AchievementIds.UpdateEarlyBird);
}
if (totalHours <= 24)
{
Instance.Unlock(AchievementIds.UpdateObsession);
}
if (Instances.VersionUpdateViewModel.IsDebugVersion())
{
Instance.Unlock(AchievementIds.Pioneer3);

View File

@@ -13,6 +13,7 @@
#pragma warning disable SA1401
using System;
using GlobalHotKey;
using MaaWpfGui.Main;
using MaaWpfGui.Services;
@@ -34,13 +35,15 @@ public static class Instances
{
public static class Data
{
public static int MedicineUsedTimes { get; set; }
public static int MedicineUsedTimes { get; set; } = 0;
public static int ExpiringMedicineUsedTimes { get; set; }
public static int ExpiringMedicineUsedTimes { get; set; } = 0;
public static int StoneUsedTimes { get; set; }
public static int StoneUsedTimes { get; set; } = 0;
public static bool HasPrintedScreencapWarning { get; set; }
public static bool HasPrintedScreencapWarning { get; set; } = false;
public static int RecruitConfirmTime { get; set; } = 0;
public static void ClearCache()
{
@@ -48,6 +51,7 @@ public static class Instances
MedicineUsedTimes = 0;
ExpiringMedicineUsedTimes = 0;
StoneUsedTimes = 0;
RecruitConfirmTime = 0;
HasPrintedScreencapWarning = false;
}
}
@@ -84,6 +88,8 @@ public static class Instances
public static IMainWindowManager MainWindowManager { get; private set; }
public static event EventHandler MainWindowManagerInstantiated;
public static IHttpService HttpService { get; private set; }
public static IMaaApiService MaaApiService { get; private set; }
@@ -120,5 +126,6 @@ public static class Instances
public static void InstantiateOnRootViewDisplayed(IContainer container)
{
MainWindowManager = container.Get<MainWindowManager>();
MainWindowManagerInstantiated?.Invoke(null, EventArgs.Empty);
}
}

View File

@@ -1080,6 +1080,11 @@ public class AsstProxy
{
var sanityLog = "\n" + string.Format(LocalizationHelper.GetString("CurrentSanity"), FightTask.SanityReport.SanityCurrent, FightTask.SanityReport.SanityMax);
Instances.TaskQueueViewModel.AddLog(LocalizationHelper.GetString("CompleteTask") + LocalizationHelper.GetString(taskChain) + sanityLog);
if (FightTask.SanityReport.SanityCurrent == 0)
{
AchievementTrackerHelper.Instance.Unlock(AchievementIds.SanityPlanner);
}
}
else
{
@@ -1232,6 +1237,11 @@ public class AsstProxy
// Instances.TaskQueueViewModel.CheckAndShutdown();
_ = Instances.TaskQueueViewModel.CheckAfterCompleted();
if (Instances.OverlayViewModel.IsCreated)
{
AchievementTrackerHelper.Instance.Unlock(AchievementIds.LogSupervisor);
}
}
else if (isCopilotTaskChain)
{
@@ -1502,6 +1512,12 @@ public class AsstProxy
break;
case "RecruitConfirm":
RecruitConfirmTime++;
if (RecruitConfirmTime > AchievementTrackerHelper.Instance.GetProgressToGroup(AchievementIds.HrManager))
{
AchievementTrackerHelper.Instance.AddProgressToGroup(AchievementIds.HrManager);
}
Instances.TaskQueueViewModel.AddLog(LocalizationHelper.GetString("RecruitConfirm"), UiLogColor.Info);
break;
@@ -1628,12 +1644,29 @@ public class AsstProxy
switch (subTask)
{
case "ProcessTask":
var taskchain = details["taskchain"]?.ToString();
switch (taskchain)
var taskName = details["details"]?["task"]?.ToString();
var taskChain = details["taskchain"]?.ToString();
switch (taskChain)
{
case "Infrast":
{
switch (taskName)
{
case "UnlockClues":
Instances.TaskQueueViewModel.AddLog(LocalizationHelper.GetString("ClueExchangeUnlocked"));
AchievementTrackerHelper.Instance.AddProgressToGroup(AchievementIds.ClueUseGroup);
AchievementTrackerHelper.Instance.ClueObsessionAdd();
break;
case "SendClues":
AchievementTrackerHelper.Instance.AddProgressToGroup(AchievementIds.ClueSendGroup);
break;
}
break;
}
case "Roguelike":
{
var taskName = details!["details"]!["task"]!.ToString();
int execTimes = (int)details!["details"]!["exec_times"]!;
if (taskName == "StartExplore")
@@ -1646,7 +1679,6 @@ public class AsstProxy
case "Mall":
{
var taskName = details["details"]!["task"]!.ToString();
switch (taskName)
{
case "EndOfActionThenStop":
@@ -1875,6 +1907,7 @@ public class AsstProxy
{
int refreshCount = (int)subTaskDetails!["count"]!;
Instances.TaskQueueViewModel.AddLog(LocalizationHelper.GetString("Refreshed") + refreshCount + LocalizationHelper.GetString("UnitTime"));
AchievementTrackerHelper.Instance.AddProgress(AchievementIds.RecruitGambler);
break;
}

View File

@@ -83,6 +83,9 @@ public class Achievement
[JsonIgnore]
public string Group { get; set; } = string.Empty;
[JsonIgnore]
public int GroupIndex { get; set; } = int.MaxValue;
[JsonIgnore]
public string MedalBrushKey
{

View File

@@ -12,11 +12,12 @@
// </copyright>
using System;
using System.Globalization;
namespace MaaWpfGui.Properties;
[AttributeUsage(AttributeTargets.Assembly)]
public class BuildDateTimeAttribute(string date) : Attribute
{
public DateTime BuildDateTime { get; } = DateTime.ParseExact(date, "O", null);
public DateTime BuildDateTime { get; } = DateTime.ParseExact(date, "O", null, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
}

View File

@@ -122,6 +122,7 @@
<system:String x:Key="OriginiumShardAutoReplenishment">Originium Shard auto replenishment</system:String>
<system:String x:Key="InfrastReceptionMessageBoardReceive">Credit collection from message board in Reception Room</system:String>
<system:String x:Key="InfrastReceptionClueExchange">Conduct Clue Exchange</system:String>
<system:String x:Key="ClueExchangeUnlocked">Clue Exchange Unlocked</system:String>
<system:String x:Key="InfrastReceptionSendClue">Send Clues</system:String>
<system:String x:Key="ReceptionOptionsRequireInfrast">Requires Infrastructure Shift</system:String>
<system:String x:Key="ContinueTraining">After training is complete, try to continue mastering the current skill</system:String>
@@ -1595,6 +1596,86 @@ If you want to run multiple MAA at the same time, please copy the whole MAA and
<system:String x:Key="Achievement.RoguelikeN15.Title">Immortal Arts Cup Contestant</system:String>
<system:String x:Key="Achievement.RoguelikeN15.Description">Immortal MAA truly immortal.</system:String>
<system:String x:Key="Achievement.RoguelikeN15.Conditions">Clear any I.S. at N15 difficulty or above using 「{key=AutoRoguelike}」</system:String>
<system:String x:Key="Achievement.LogSupervisor.Title">Supervisor</system:String>
<system:String x:Key="Achievement.LogSupervisor.Description">They say watching MAA's logs can effectively improve auto-battle success rate.</system:String>
<system:String x:Key="Achievement.LogSupervisor.Conditions">Complete a task with the log floating window open</system:String>
<system:String x:Key="Achievement.RecruitGambler.Title">Recruitment Gambler</system:String>
<system:String x:Key="Achievement.RecruitGambler.Description">All in! Turn a bicycle into a motorcycle.</system:String>
<system:String x:Key="Achievement.RecruitGambler.Conditions">Refresh tags 50 times in public recruitment</system:String>
<system:String x:Key="Achievement.ClueCollector.Title">Clue Collector</system:String>
<system:String x:Key="Achievement.ClueCollector.Description">Rhodes Island socialite.</system:String>
<system:String x:Key="Achievement.ClueCollector.Conditions">Open clue exchange 20 times in total</system:String>
<system:String x:Key="Achievement.CluePhilosopher.Title">Clue Philosopher</system:String>
<system:String x:Key="Achievement.CluePhilosopher.Description">What is the meaning of gathering?</system:String>
<system:String x:Key="Achievement.CluePhilosopher.Conditions">Open clue exchange 50 times in total</system:String>
<system:String x:Key="Achievement.ClueSharer.Title">Clue Sharer</system:String>
<system:String x:Key="Achievement.ClueSharer.Description">Good things should be shared with friends.</system:String>
<system:String x:Key="Achievement.ClueSharer.Conditions">Send clues to friends 20 times in total</system:String>
<system:String x:Key="Achievement.CluePhilanthropist.Title">Clue Philanthropist</system:String>
<system:String x:Key="Achievement.CluePhilanthropist.Description">Take it, no need to thank me.</system:String>
<system:String x:Key="Achievement.CluePhilanthropist.Conditions">Send clues to friends 50 times in total</system:String>
<system:String x:Key="Achievement.TaskChainKing.Title">Task Chain King</system:String>
<system:String x:Key="Achievement.TaskChainKing.Description">One click to start, everything done.</system:String>
<system:String x:Key="Achievement.TaskChainKing.Conditions">Select more than 7 tasks in a single run</system:String>
<system:String x:Key="Achievement.UpdateObsession.Title">Update Obsession</system:String>
<system:String x:Key="Achievement.UpdateObsession.Description">Update available? Update!</system:String>
<system:String x:Key="Achievement.UpdateObsession.Conditions">Complete update within 1 day after release</system:String>
<system:String x:Key="Achievement.UpdateEarlyBird.Title">Update Early Bird</system:String>
<system:String x:Key="Achievement.UpdateEarlyBird.Description">Be the first to experience!</system:String>
<system:String x:Key="Achievement.UpdateEarlyBird.Conditions">Complete update within 1 hour after release</system:String>
<system:String x:Key="Achievement.SanityPlanner.Title">Sanity Planner</system:String>
<system:String x:Key="Achievement.SanityPlanner.Description">Precise, perfect, not a single point off.</system:String>
<system:String x:Key="Achievement.SanityPlanner.Conditions">Complete {key=Combat} with exactly all sanity consumed</system:String>
<system:String x:Key="Achievement.HotkeyMagician.Title">Hotkey Magician</system:String>
<system:String x:Key="Achievement.HotkeyMagician.Description">Ctrl + Shift + Alt + Win + F13</system:String>
<system:String x:Key="Achievement.HotkeyMagician.Conditions">Set and use a hotkey combination with more than 4 modifier keys</system:String>
<system:String x:Key="Achievement.WarehouseMiser.Title">Warehouse Miser</system:String>
<system:String x:Key="Achievement.WarehouseMiser.Description">Not a single one shall be used!</system:String>
<system:String x:Key="Achievement.WarehouseMiser.Conditions">Warehouse recognition detects more than 10000 of a material</system:String>
<system:String x:Key="Achievement.HrSpecialist.Title">HR Specialist</system:String>
<system:String x:Key="Achievement.HrSpecialist.Description">Why are they all Reserve Action Teams!</system:String>
<system:String x:Key="Achievement.HrSpecialist.Conditions">Recruit 10 times consecutively in a single recruitment task</system:String>
<system:String x:Key="Achievement.HrSeniorSpecialist.Title">HR Senior Specialist</system:String>
<system:String x:Key="Achievement.HrSeniorSpecialist.Description">Where is the Senior Operator tag? Where is it?🎶</system:String>
<system:String x:Key="Achievement.HrSeniorSpecialist.Conditions">Recruit 20 times consecutively in a single recruitment task</system:String>
<system:String x:Key="Achievement.WarehouseKeeper.Title">I'm the Warehouse Keeper!</system:String>
<system:String x:Key="Achievement.WarehouseKeeper.Description">MAA found MAA!</system:String>
<system:String x:Key="Achievement.WarehouseKeeper.Conditions">Operator recognition includes operator "Pallas"</system:String>
<system:String x:Key="Achievement.NotFound404.Title">404!</system:String>
<system:String x:Key="Achievement.NotFound404.Description">This task seems to be missing</system:String>
<system:String x:Key="Achievement.NotFound404.Conditions">Use remote protocol to call a task with incorrect id</system:String>
<system:String x:Key="Achievement.Linguist.Title">Linguist</system:String>
<system:String x:Key="Achievement.Linguist.Description">MAA, but internationalized.</system:String>
<system:String x:Key="Achievement.Linguist.Conditions">Try switching interface language</system:String>
<system:String x:Key="Achievement.StartupBoot.Title">Startup Boot</system:String>
<system:String x:Key="Achievement.StartupBoot.Description">Theoretically, your boot time just got a bit slower</system:String>
<system:String x:Key="Achievement.StartupBoot.Conditions">Set MAA to start on boot</system:String>
<system:String x:Key="Achievement.ClueObsession.Title">Clue Obsession</system:String>
<system:String x:Key="Achievement.ClueObsession.Description">Seven-color team, assemble!</system:String>
<system:String x:Key="Achievement.ClueObsession.Conditions">Collect and open clue exchange every day for 7 consecutive days</system:String>
<system:String x:Key="Achievement.Time325.Title">325</system:String>
<system:String x:Key="Achievement.Time325.Description">You know what this number means, right?</system:String>
<system:String x:Key="Achievement.Time325.Conditions">Still using MAA at 3/13/23:25</system:String>
<!-- !Achievement -->
<!-- BadModules -->

View File

@@ -122,6 +122,7 @@
<system:String x:Key="OriginiumShardAutoReplenishment">源石の欠片を自動で補充</system:String>
<system:String x:Key="InfrastReceptionMessageBoardReceive">受付室の掲示板からのクレジット収集</system:String>
<system:String x:Key="InfrastReceptionClueExchange">手がかり交換を実施</system:String>
<system:String x:Key="ClueExchangeUnlocked">手がかり交換を開始しました</system:String>
<system:String x:Key="InfrastReceptionSendClue">手がかりを贈る</system:String>
<system:String x:Key="ReceptionOptionsRequireInfrast">インフラシフト実行が必要</system:String>
<system:String x:Key="ContinueTraining">訓練完了後に現在スキルの継続特化を試みます</system:String>
@@ -1596,6 +1597,86 @@ MAA を複数開くには、新しい MAA を他のフォルダにコピーし
<system:String x:Key="Achievement.RoguelikeN15.Title">仙術杯選手</system:String>
<system:String x:Key="Achievement.RoguelikeN15.Description">本物の仙術だなあ。</system:String>
<system:String x:Key="Achievement.RoguelikeN15.Conditions">「{key=AutoRoguelike}」で、任意のテーマで N15 難易度以上をクリアする</system:String>
<system:String x:Key="Achievement.LogSupervisor.Title">スーパーバイザー</system:String>
<system:String x:Key="Achievement.LogSupervisor.Description">MAAのログを見つめていると、自動戦闘の成功率が上がるらしい。</system:String>
<system:String x:Key="Achievement.LogSupervisor.Conditions">ログフローティングウィンドウを開いた状態でタスクを1回完了する</system:String>
<system:String x:Key="Achievement.RecruitGambler.Title">公開採用ギャンブラー</system:String>
<system:String x:Key="Achievement.RecruitGambler.Description">一か八か、自転車がバイクに。</system:String>
<system:String x:Key="Achievement.RecruitGambler.Conditions">公開採用でタグを50回リフレッシュする</system:String>
<system:String x:Key="Achievement.ClueCollector.Title">手がかり収集家</system:String>
<system:String x:Key="Achievement.ClueCollector.Description">ロドス島の社交界の花。</system:String>
<system:String x:Key="Achievement.ClueCollector.Conditions">手がかり交換を累計20回開く</system:String>
<system:String x:Key="Achievement.CluePhilosopher.Title">手がかり哲学者</system:String>
<system:String x:Key="Achievement.CluePhilosopher.Description">集まりの意味とは何か?</system:String>
<system:String x:Key="Achievement.CluePhilosopher.Conditions">手がかり交換を累計50回開く</system:String>
<system:String x:Key="Achievement.ClueSharer.Title">手がかりシェアラー</system:String>
<system:String x:Key="Achievement.ClueSharer.Description">良いものは友達と分かち合う。</system:String>
<system:String x:Key="Achievement.ClueSharer.Conditions">友達に手がかりを累計20回送る</system:String>
<system:String x:Key="Achievement.CluePhilanthropist.Title">手がかり慈善家</system:String>
<system:String x:Key="Achievement.CluePhilanthropist.Description">持って行って、どういたしまして。</system:String>
<system:String x:Key="Achievement.CluePhilanthropist.Conditions">友達に手がかりを累計50回送る</system:String>
<system:String x:Key="Achievement.TaskChainKing.Title">タスクチェーン王</system:String>
<system:String x:Key="Achievement.TaskChainKing.Description">ワンクリックで起動、全部完了。</system:String>
<system:String x:Key="Achievement.TaskChainKing.Conditions">1回の実行で7個以上のタスクを選択する</system:String>
<system:String x:Key="Achievement.UpdateObsession.Title">更新強迫症</system:String>
<system:String x:Key="Achievement.UpdateObsession.Description">更新がある?更新する!</system:String>
<system:String x:Key="Achievement.UpdateObsession.Conditions">更新リリース後1日以内に更新を完了する</system:String>
<system:String x:Key="Achievement.UpdateEarlyBird.Title">更新アーリーバード</system:String>
<system:String x:Key="Achievement.UpdateEarlyBird.Description">いち早く体験!</system:String>
<system:String x:Key="Achievement.UpdateEarlyBird.Conditions">更新リリース後1時間以内に更新を完了する</system:String>
<system:String x:Key="Achievement.SanityPlanner.Title">理性プランナー</system:String>
<system:String x:Key="Achievement.SanityPlanner.Description">精密、完璧、寸分の狂いもない。</system:String>
<system:String x:Key="Achievement.SanityPlanner.Conditions">{key=Combat}を完了した時、すべての理性をちょうど使い切る</system:String>
<system:String x:Key="Achievement.HotkeyMagician.Title">ホットキーマジシャン</system:String>
<system:String x:Key="Achievement.HotkeyMagician.Description">Ctrl + Shift + Alt + Win + F13</system:String>
<system:String x:Key="Achievement.HotkeyMagician.Conditions">修飾キーが4つ以上のホットキー組み合わせを設定して使用する</system:String>
<system:String x:Key="Achievement.WarehouseMiser.Title">倉庫の守銭奴</system:String>
<system:String x:Key="Achievement.WarehouseMiser.Description">一つも使わせない!</system:String>
<system:String x:Key="Achievement.WarehouseMiser.Conditions">倉庫認識機能が倉庫内の特定の材料が10000個以上あることを検出する</system:String>
<system:String x:Key="Achievement.HrSpecialist.Title">人事部専門員</system:String>
<system:String x:Key="Achievement.HrSpecialist.Description">どうして全部予備行動チームなんだ!</system:String>
<system:String x:Key="Achievement.HrSpecialist.Conditions">1回の公開採用タスクで連続10回採用する</system:String>
<system:String x:Key="Achievement.HrSeniorSpecialist.Title">人事部上級専門員</system:String>
<system:String x:Key="Achievement.HrSeniorSpecialist.Description">上級オペレータータグはどこだ?どこだ?🎶</system:String>
<system:String x:Key="Achievement.HrSeniorSpecialist.Conditions">1回の公開採用タスクで連続20回採用する</system:String>
<system:String x:Key="Achievement.WarehouseKeeper.Title">私は倉庫管理員!</system:String>
<system:String x:Key="Achievement.WarehouseKeeper.Description">MAAがMAAを見つけた</system:String>
<system:String x:Key="Achievement.WarehouseKeeper.Conditions">オペレーター認識にオペレーター「パラス」が含まれる</system:String>
<system:String x:Key="Achievement.NotFound404.Title">404</system:String>
<system:String x:Key="Achievement.NotFound404.Description">このタスクは見つからないようです</system:String>
<system:String x:Key="Achievement.NotFound404.Conditions">リモートプロトコルで間違ったタスクidを呼び出す</system:String>
<system:String x:Key="Achievement.Linguist.Title">言語学者</system:String>
<system:String x:Key="Achievement.Linguist.Description">MAA、しかし国際化。</system:String>
<system:String x:Key="Achievement.Linguist.Conditions">インターフェース言語を切り替えてみる</system:String>
<system:String x:Key="Achievement.StartupBoot.Title">起動時起動</system:String>
<system:String x:Key="Achievement.StartupBoot.Description">理論的には、起動時間が少し遅くなった</system:String>
<system:String x:Key="Achievement.StartupBoot.Conditions">MAAを起動時に起動するように設定する</system:String>
<system:String x:Key="Achievement.ClueObsession.Title">手がかり強迫症</system:String>
<system:String x:Key="Achievement.ClueObsession.Description">七色戦隊、集合!</system:String>
<system:String x:Key="Achievement.ClueObsession.Conditions">7日連続で毎日手がかりを集めて手がかり交換を開く</system:String>
<system:String x:Key="Achievement.Time325.Title">325</system:String>
<system:String x:Key="Achievement.Time325.Description">この数字の意味を知っているでしょう?</system:String>
<system:String x:Key="Achievement.Time325.Conditions">3/13/23時25分にまだMAAを使用している</system:String>
<!-- !Achievement -->
<!-- BadModules -->

View File

@@ -122,6 +122,7 @@
<system:String x:Key="OriginiumShardAutoReplenishment">오리지늄 조각 자동 보충</system:String>
<system:String x:Key="InfrastReceptionMessageBoardReceive">응접실 게시판에서 크레딧 수집</system:String>
<system:String x:Key="InfrastReceptionClueExchange">단서 교환 수행</system:String>
<system:String x:Key="ClueExchangeUnlocked">단서 교환 시작</system:String>
<system:String x:Key="InfrastReceptionSendClue">단서 보내기</system:String>
<system:String x:Key="ReceptionOptionsRequireInfrast">인프라 교대 필요</system:String>
<system:String x:Key="ContinueTraining">스킬 훈련 완료 시 이어서 훈련 시도</system:String>
@@ -1597,6 +1598,86 @@ MAA를 독립된 새 폴더에 압축 해제하거나, MAA에 속하지 않는 D
<system:String x:Key="Achievement.RoguelikeN15.Title">마스터피스</system:String>
<system:String x:Key="Achievement.RoguelikeN15.Description">방금 제 플레이 보셨나요? 이건 기록으로 남겨야 해요!</system:String>
<system:String x:Key="Achievement.RoguelikeN15.Conditions">「{key=AutoRoguelike}」 기능으로 {key=AutoRoguelike} 난이도 15 이상 클리어</system:String>
<system:String x:Key="Achievement.LogSupervisor.Title">슈퍼바이저</system:String>
<system:String x:Key="Achievement.LogSupervisor.Description">MAA의 로그를 지켜보면 자동 전투 성공률이 효과적으로 향상된다고 합니다.</system:String>
<system:String x:Key="Achievement.LogSupervisor.Conditions">로그 플로팅 창을 열고 작업을 1회 완료</system:String>
<system:String x:Key="Achievement.RecruitGambler.Title">공개 모집 도박꾼</system:String>
<system:String x:Key="Achievement.RecruitGambler.Description">한 번 해보자, 자전거가 오토바이가 된다.</system:String>
<system:String x:Key="Achievement.RecruitGambler.Conditions">공개 모집에서 태그를 50회 새로고침</system:String>
<system:String x:Key="Achievement.ClueCollector.Title">단서 수집가</system:String>
<system:String x:Key="Achievement.ClueCollector.Description">로도스 아일랜드 사교계의 꽃.</system:String>
<system:String x:Key="Achievement.ClueCollector.Conditions">단서 교환을 누적 20회 열기</system:String>
<system:String x:Key="Achievement.CluePhilosopher.Title">단서 철학자</system:String>
<system:String x:Key="Achievement.CluePhilosopher.Description">모임의 의미는 무엇인가?</system:String>
<system:String x:Key="Achievement.CluePhilosopher.Conditions">단서 교환을 누적 50회 열기</system:String>
<system:String x:Key="Achievement.ClueSharer.Title">단서 공유자</system:String>
<system:String x:Key="Achievement.ClueSharer.Description">좋은 것은 친구와 나눠야 해요.</system:String>
<system:String x:Key="Achievement.ClueSharer.Conditions">친구에게 단서를 누적 20회 보내기</system:String>
<system:String x:Key="Achievement.CluePhilanthropist.Title">단서 자선가</system:String>
<system:String x:Key="Achievement.CluePhilanthropist.Description">가져가세요, 감사 인사는 필요 없어요.</system:String>
<system:String x:Key="Achievement.CluePhilanthropist.Conditions">친구에게 단서를 누적 50회 보내기</system:String>
<system:String x:Key="Achievement.TaskChainKing.Title">작업 체인 왕</system:String>
<system:String x:Key="Achievement.TaskChainKing.Description">한 번의 클릭으로 시작, 모두 완료.</system:String>
<system:String x:Key="Achievement.TaskChainKing.Conditions">단일 실행에서 7개 이상의 작업 선택</system:String>
<system:String x:Key="Achievement.UpdateObsession.Title">업데이트 강박증</system:String>
<system:String x:Key="Achievement.UpdateObsession.Description">업데이트가 있나? 업데이트!</system:String>
<system:String x:Key="Achievement.UpdateObsession.Conditions">업데이트 출시 후 1일 이내에 업데이트 완료</system:String>
<system:String x:Key="Achievement.UpdateEarlyBird.Title">업데이트 얼리버드</system:String>
<system:String x:Key="Achievement.UpdateEarlyBird.Description">먼저 체험하기!</system:String>
<system:String x:Key="Achievement.UpdateEarlyBird.Conditions">업데이트 출시 후 1시간 이내에 업데이트 완료</system:String>
<system:String x:Key="Achievement.SanityPlanner.Title">이성 플래너</system:String>
<system:String x:Key="Achievement.SanityPlanner.Description">정밀하고, 완벽하고, 한 푼도 어긋나지 않아요.</system:String>
<system:String x:Key="Achievement.SanityPlanner.Conditions">{key=Combat} 완료 시 모든 이성을 정확히 소진</system:String>
<system:String x:Key="Achievement.HotkeyMagician.Title">단축키 마법사</system:String>
<system:String x:Key="Achievement.HotkeyMagician.Description">Ctrl + Shift + Alt + Win + F13</system:String>
<system:String x:Key="Achievement.HotkeyMagician.Conditions">수정 키가 4개 이상인 단축키 조합을 설정하고 사용</system:String>
<system:String x:Key="Achievement.WarehouseMiser.Title">창고 수전노</system:String>
<system:String x:Key="Achievement.WarehouseMiser.Description">하나도 쓰지 말아요!</system:String>
<system:String x:Key="Achievement.WarehouseMiser.Conditions">창고 인식 기능이 창고 내 특정 재료가 10000개 이상임을 감지</system:String>
<system:String x:Key="Achievement.HrSpecialist.Title">인사부 전문가</system:String>
<system:String x:Key="Achievement.HrSpecialist.Description">왜 다 예비 행동팀이에요!</system:String>
<system:String x:Key="Achievement.HrSpecialist.Conditions">단일 공개 모집 작업에서 연속 10회 모집</system:String>
<system:String x:Key="Achievement.HrSeniorSpecialist.Title">인사부 고급 전문가</system:String>
<system:String x:Key="Achievement.HrSeniorSpecialist.Description">고급 오퍼레이터 태그는 어디 있나요? 어디 있나요?🎶</system:String>
<system:String x:Key="Achievement.HrSeniorSpecialist.Conditions">단일 공개 모집 작업에서 연속 20회 모집</system:String>
<system:String x:Key="Achievement.WarehouseKeeper.Title">저는 창고 관리원이에요!</system:String>
<system:String x:Key="Achievement.WarehouseKeeper.Description">MAA가 MAA를 찾았어요!</system:String>
<system:String x:Key="Achievement.WarehouseKeeper.Conditions">오퍼레이터 인식에 오퍼레이터 "팔라스" 포함</system:String>
<system:String x:Key="Achievement.NotFound404.Title">404</system:String>
<system:String x:Key="Achievement.NotFound404.Description">이 작업을 찾을 수 없는 것 같아요</system:String>
<system:String x:Key="Achievement.NotFound404.Conditions">원격 프로토콜로 잘못된 작업 id 호출</system:String>
<system:String x:Key="Achievement.Linguist.Title">언어학자</system:String>
<system:String x:Key="Achievement.Linguist.Description">MAA, 하지만 국제화.</system:String>
<system:String x:Key="Achievement.Linguist.Conditions">인터페이스 언어 전환 시도</system:String>
<system:String x:Key="Achievement.StartupBoot.Title">부팅 시 시작</system:String>
<system:String x:Key="Achievement.StartupBoot.Description">이론적으로 부팅 속도가 조금 느려졌어요</system:String>
<system:String x:Key="Achievement.StartupBoot.Conditions">MAA를 부팅 시 시작하도록 설정</system:String>
<system:String x:Key="Achievement.ClueObsession.Title">단서 강박증</system:String>
<system:String x:Key="Achievement.ClueObsession.Description">칠색 전대, 집합!</system:String>
<system:String x:Key="Achievement.ClueObsession.Conditions">7일 연속으로 매일 단서를 모아 단서 교환 열기</system:String>
<system:String x:Key="Achievement.Time325.Title">325</system:String>
<system:String x:Key="Achievement.Time325.Description">이 숫자가 무슨 의미인지 아시죠?</system:String>
<system:String x:Key="Achievement.Time325.Conditions">3/13/23시 25분에 여전히 MAA 사용 중</system:String>
<!-- !Achievement -->
<!-- BadModules -->

View File

@@ -122,6 +122,7 @@
<system:String x:Key="OriginiumShardAutoReplenishment">源石碎片自动补货</system:String>
<system:String x:Key="InfrastReceptionMessageBoardReceive">会客室信息板收取信用</system:String>
<system:String x:Key="InfrastReceptionClueExchange">进行线索交流</system:String>
<system:String x:Key="ClueExchangeUnlocked">已开启线索交流</system:String>
<system:String x:Key="InfrastReceptionSendClue">赠送线索</system:String>
<system:String x:Key="ReceptionOptionsRequireInfrast">需执行基建换班</system:String>
<system:String x:Key="ContinueTraining">训练完成后继续尝试专精当前技能</system:String>
@@ -1596,6 +1597,86 @@ C:\\leidian\\LDPlayer9。\n
<system:String x:Key="Achievement.RoguelikeN15.Title">仙术杯选手</system:String>
<system:String x:Key="Achievement.RoguelikeN15.Description">仙术牛牛真仙术。</system:String>
<system:String x:Key="Achievement.RoguelikeN15.Conditions">使用 「{key=AutoRoguelike}」 通关任意肉鸽 N15 及以上难度</system:String>
<system:String x:Key="Achievement.LogSupervisor.Title">超级监工</system:String>
<system:String x:Key="Achievement.LogSupervisor.Description">据说盯着MAA的日志能够有效提高代理成功率。</system:String>
<system:String x:Key="Achievement.LogSupervisor.Conditions">开着日志悬浮窗完成一次任务</system:String>
<system:String x:Key="Achievement.RecruitGambler.Title">公招赌徒</system:String>
<system:String x:Key="Achievement.RecruitGambler.Description">搏一搏,单车变摩托。</system:String>
<system:String x:Key="Achievement.RecruitGambler.Conditions">在公开招募中刷新标签 50 次</system:String>
<system:String x:Key="Achievement.ClueCollector.Title">线索搜集</system:String>
<system:String x:Key="Achievement.ClueCollector.Description">罗德岛交际花。</system:String>
<system:String x:Key="Achievement.ClueCollector.Conditions">累计开启线索交流 20 次</system:String>
<system:String x:Key="Achievement.CluePhilosopher.Title">线索哲学家</system:String>
<system:String x:Key="Achievement.CluePhilosopher.Description">聚会的意义是什么?</system:String>
<system:String x:Key="Achievement.CluePhilosopher.Conditions">累计开启线索交流 50 次</system:String>
<system:String x:Key="Achievement.ClueSharer.Title">线索分享</system:String>
<system:String x:Key="Achievement.ClueSharer.Description">好东西要和朋友分享。</system:String>
<system:String x:Key="Achievement.ClueSharer.Conditions">累计向好友发送 20 次线索</system:String>
<system:String x:Key="Achievement.CluePhilanthropist.Title">线索慈善家</system:String>
<system:String x:Key="Achievement.CluePhilanthropist.Description">拿去花,不用谢。</system:String>
<system:String x:Key="Achievement.CluePhilanthropist.Conditions">累计向好友发送 50 次线索</system:String>
<system:String x:Key="Achievement.TaskChainKing.Title">任务链王</system:String>
<system:String x:Key="Achievement.TaskChainKing.Description">一键启动,全部搞定。</system:String>
<system:String x:Key="Achievement.TaskChainKing.Conditions">单次运行中,勾选超过 7 个任务</system:String>
<system:String x:Key="Achievement.UpdateObsession.Title">更新强迫症</system:String>
<system:String x:Key="Achievement.UpdateObsession.Description">有更新?更!</system:String>
<system:String x:Key="Achievement.UpdateObsession.Conditions">在更新发布后 1 天内完成更新</system:String>
<system:String x:Key="Achievement.UpdateEarlyBird.Title">更新尝鲜者</system:String>
<system:String x:Key="Achievement.UpdateEarlyBird.Description">抢先体验!</system:String>
<system:String x:Key="Achievement.UpdateEarlyBird.Conditions">在更新发布后 1 小时内完成更新</system:String>
<system:String x:Key="Achievement.SanityPlanner.Title">理智规划师</system:String>
<system:String x:Key="Achievement.SanityPlanner.Description">精确,完美,分毫不差。</system:String>
<system:String x:Key="Achievement.SanityPlanner.Conditions">完成{key=Combat}时刚好消耗完所有理智</system:String>
<system:String x:Key="Achievement.HotkeyMagician.Title">热键魔术师</system:String>
<system:String x:Key="Achievement.HotkeyMagician.Description">Ctrl + Shift + Alt + Win + F13</system:String>
<system:String x:Key="Achievement.HotkeyMagician.Conditions">设置并使用一个超过 4 个修饰键的热键组合</system:String>
<system:String x:Key="Achievement.WarehouseMiser.Title">仓库守财奴</system:String>
<system:String x:Key="Achievement.WarehouseMiser.Description">一个都不许用!</system:String>
<system:String x:Key="Achievement.WarehouseMiser.Conditions">仓库识别功能识别到仓库内某种材料数量超过 10000 个</system:String>
<system:String x:Key="Achievement.HrSpecialist.Title">人事部专员</system:String>
<system:String x:Key="Achievement.HrSpecialist.Description">怎么全是预备行动组啊!</system:String>
<system:String x:Key="Achievement.HrSpecialist.Conditions">单轮公招任务连续招募 10 次</system:String>
<system:String x:Key="Achievement.HrSeniorSpecialist.Title">人事部高级专员</system:String>
<system:String x:Key="Achievement.HrSeniorSpecialist.Description">高资在哪里啊高资在哪里🎶</system:String>
<system:String x:Key="Achievement.HrSeniorSpecialist.Conditions">单轮公招任务连续招募 20 次</system:String>
<system:String x:Key="Achievement.WarehouseKeeper.Title">我是仓管!</system:String>
<system:String x:Key="Achievement.WarehouseKeeper.Description">牛牛找到了牛牛!</system:String>
<system:String x:Key="Achievement.WarehouseKeeper.Conditions">干员识别中包含干员"帕拉斯"</system:String>
<system:String x:Key="Achievement.NotFound404.Title">404</system:String>
<system:String x:Key="Achievement.NotFound404.Description">这个任务似乎找不到了</system:String>
<system:String x:Key="Achievement.NotFound404.Conditions">使用远程协议调用错误的任务 id</system:String>
<system:String x:Key="Achievement.Linguist.Title">语言学家</system:String>
<system:String x:Key="Achievement.Linguist.Description">MAA但国际化。</system:String>
<system:String x:Key="Achievement.Linguist.Conditions">尝试切换界面语言</system:String>
<system:String x:Key="Achievement.StartupBoot.Title">开机启动</system:String>
<system:String x:Key="Achievement.StartupBoot.Description">理论上你的开机速度又慢了一点</system:String>
<system:String x:Key="Achievement.StartupBoot.Conditions">设置开机启动 MAA</system:String>
<system:String x:Key="Achievement.ClueObsession.Title">线索强迫症</system:String>
<system:String x:Key="Achievement.ClueObsession.Description">七色战队,集合!</system:String>
<system:String x:Key="Achievement.ClueObsession.Conditions">连续 7 天每天集齐并开启线索交流</system:String>
<system:String x:Key="Achievement.Time325.Title">325</system:String>
<system:String x:Key="Achievement.Time325.Description">你知道这个数字是什么意思对吧</system:String>
<system:String x:Key="Achievement.Time325.Conditions">在 3/13/23 点 25 分还在使用 MAA</system:String>
<!-- !Achievement -->
<!-- BadModules -->

View File

@@ -122,6 +122,7 @@
<system:String x:Key="OriginiumShardAutoReplenishment">源石碎片自動補貨</system:String>
<system:String x:Key="InfrastReceptionMessageBoardReceive">會客室資訊板收取信用</system:String>
<system:String x:Key="InfrastReceptionClueExchange">進行線索交流</system:String>
<system:String x:Key="ClueExchangeUnlocked">已開啟線索交流</system:String>
<system:String x:Key="InfrastReceptionSendClue">贈送線索</system:String>
<system:String x:Key="ReceptionOptionsRequireInfrast">需執行基建換班</system:String>
<system:String x:Key="ContinueTraining">訓練完成後繼續嘗試專精目前技能</system:String>
@@ -1596,6 +1597,86 @@ C:\\leidian\\LDPlayer9。\n
<system:String x:Key="Achievement.RoguelikeN15.Title">仙術杯選手</system:String>
<system:String x:Key="Achievement.RoguelikeN15.Description">仙術牛牛真仙術。</system:String>
<system:String x:Key="Achievement.RoguelikeN15.Conditions">使用 「{key=AutoRoguelike}」 通關任意肉鴿 N15 及以上難度</system:String>
<system:String x:Key="Achievement.LogSupervisor.Title">超級監工</system:String>
<system:String x:Key="Achievement.LogSupervisor.Description">據說盯著MAA的日誌能夠有效提高代理成功率。</system:String>
<system:String x:Key="Achievement.LogSupervisor.Conditions">開著日誌懸浮窗完成一次任務</system:String>
<system:String x:Key="Achievement.RecruitGambler.Title">公招賭徒</system:String>
<system:String x:Key="Achievement.RecruitGambler.Description">搏一搏,單車變摩托。</system:String>
<system:String x:Key="Achievement.RecruitGambler.Conditions">在公開招募中刷新標籤 50 次</system:String>
<system:String x:Key="Achievement.ClueCollector.Title">線索搜集</system:String>
<system:String x:Key="Achievement.ClueCollector.Description">羅德島交際花。</system:String>
<system:String x:Key="Achievement.ClueCollector.Conditions">累計開啟線索交流 20 次</system:String>
<system:String x:Key="Achievement.CluePhilosopher.Title">線索哲學家</system:String>
<system:String x:Key="Achievement.CluePhilosopher.Description">聚會的意義是什麼?</system:String>
<system:String x:Key="Achievement.CluePhilosopher.Conditions">累計開啟線索交流 50 次</system:String>
<system:String x:Key="Achievement.ClueSharer.Title">線索分享</system:String>
<system:String x:Key="Achievement.ClueSharer.Description">好東西要和朋友分享。</system:String>
<system:String x:Key="Achievement.ClueSharer.Conditions">累計向好友發送 20 次線索</system:String>
<system:String x:Key="Achievement.CluePhilanthropist.Title">線索慈善家</system:String>
<system:String x:Key="Achievement.CluePhilanthropist.Description">拿去花,不用謝。</system:String>
<system:String x:Key="Achievement.CluePhilanthropist.Conditions">累計向好友發送 50 次線索</system:String>
<system:String x:Key="Achievement.TaskChainKing.Title">任務鏈王</system:String>
<system:String x:Key="Achievement.TaskChainKing.Description">一鍵啟動,全部搞定。</system:String>
<system:String x:Key="Achievement.TaskChainKing.Conditions">單次運行中,勾選超過 7 個任務</system:String>
<system:String x:Key="Achievement.UpdateObsession.Title">更新強迫症</system:String>
<system:String x:Key="Achievement.UpdateObsession.Description">有更新?更!</system:String>
<system:String x:Key="Achievement.UpdateObsession.Conditions">在更新發布後 1 天內完成更新</system:String>
<system:String x:Key="Achievement.UpdateEarlyBird.Title">更新嘗鮮者</system:String>
<system:String x:Key="Achievement.UpdateEarlyBird.Description">搶先體驗!</system:String>
<system:String x:Key="Achievement.UpdateEarlyBird.Conditions">在更新發布後 1 小時內完成更新</system:String>
<system:String x:Key="Achievement.SanityPlanner.Title">理智規劃師</system:String>
<system:String x:Key="Achievement.SanityPlanner.Description">精確,完美,分毫不差。</system:String>
<system:String x:Key="Achievement.SanityPlanner.Conditions">完成{key=Combat}時剛好消耗完所有理智</system:String>
<system:String x:Key="Achievement.HotkeyMagician.Title">熱鍵魔術師</system:String>
<system:String x:Key="Achievement.HotkeyMagician.Description">Ctrl + Shift + Alt + Win + F13</system:String>
<system:String x:Key="Achievement.HotkeyMagician.Conditions">設置並使用一個超過 4 個修飾鍵的熱鍵組合</system:String>
<system:String x:Key="Achievement.WarehouseMiser.Title">倉庫守財奴</system:String>
<system:String x:Key="Achievement.WarehouseMiser.Description">一個都不許用!</system:String>
<system:String x:Key="Achievement.WarehouseMiser.Conditions">倉庫識別功能識別到倉庫內某種材料數量超過 10000 個</system:String>
<system:String x:Key="Achievement.HrSpecialist.Title">人事部專員</system:String>
<system:String x:Key="Achievement.HrSpecialist.Description">怎麼全是預備行動組啊!</system:String>
<system:String x:Key="Achievement.HrSpecialist.Conditions">單輪公招任務連續招募 10 次</system:String>
<system:String x:Key="Achievement.HrSeniorSpecialist.Title">人事部高級專員</system:String>
<system:String x:Key="Achievement.HrSeniorSpecialist.Description">高資在哪裡啊高資在哪裡🎶</system:String>
<system:String x:Key="Achievement.HrSeniorSpecialist.Conditions">單輪公招任務連續招募 20 次</system:String>
<system:String x:Key="Achievement.WarehouseKeeper.Title">我是倉管!</system:String>
<system:String x:Key="Achievement.WarehouseKeeper.Description">牛牛找到了牛牛!</system:String>
<system:String x:Key="Achievement.WarehouseKeeper.Conditions">幹員識別中包含幹員"帕拉斯"</system:String>
<system:String x:Key="Achievement.NotFound404.Title">404</system:String>
<system:String x:Key="Achievement.NotFound404.Description">這個任務似乎找不到了</system:String>
<system:String x:Key="Achievement.NotFound404.Conditions">使用遠程協議調用錯誤的任務 id</system:String>
<system:String x:Key="Achievement.Linguist.Title">語言學家</system:String>
<system:String x:Key="Achievement.Linguist.Description">MAA但國際化。</system:String>
<system:String x:Key="Achievement.Linguist.Conditions">嘗試切換界面語言</system:String>
<system:String x:Key="Achievement.StartupBoot.Title">開機啟動</system:String>
<system:String x:Key="Achievement.StartupBoot.Description">理論上你的開機速度又慢了一點</system:String>
<system:String x:Key="Achievement.StartupBoot.Conditions">設置開機啟動 MAA</system:String>
<system:String x:Key="Achievement.ClueObsession.Title">線索強迫症</system:String>
<system:String x:Key="Achievement.ClueObsession.Description">七色戰隊,集合!</system:String>
<system:String x:Key="Achievement.ClueObsession.Conditions">連續 7 天每天集齊並開啟線索交流</system:String>
<system:String x:Key="Achievement.Time325.Title">325</system:String>
<system:String x:Key="Achievement.Time325.Description">你知道這個數字是什麼意思對吧</system:String>
<system:String x:Key="Achievement.Time325.Conditions">在 3/13/23 點 25 分還在使用 MAA</system:String>
<!-- !Achievement -->
<!-- BadModules -->

View File

@@ -153,10 +153,7 @@ public class RemoteControlService
private static T GetPrivateFieldValue<T>(object instance, string fieldName)
{
if (instance == null)
{
throw new ArgumentNullException(nameof(instance));
}
ArgumentNullException.ThrowIfNull(instance);
if (string.IsNullOrEmpty(fieldName))
{
@@ -164,13 +161,7 @@ public class RemoteControlService
}
Type type = instance.GetType();
FieldInfo fieldInfo = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldInfo == null)
{
throw new ArgumentException($"Field '{fieldName}' not found in type '{type.FullName}'.");
}
FieldInfo fieldInfo = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new ArgumentException($"Field '{fieldName}' not found in type '{type.FullName}'.");
if (!typeof(T).IsAssignableFrom(fieldInfo.FieldType))
{
throw new ArgumentException($"Field '{fieldName}' is not of type {typeof(T)}.");
@@ -181,10 +172,7 @@ public class RemoteControlService
private static void InvokeInstanceMethod(object instance, string methodName)
{
if (instance == null)
{
throw new ArgumentNullException(nameof(instance));
}
ArgumentNullException.ThrowIfNull(instance);
if (string.IsNullOrEmpty(methodName))
{
@@ -192,22 +180,13 @@ public class RemoteControlService
}
Type type = instance.GetType();
MethodInfo methodInfo = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
if (methodInfo == null)
{
throw new ArgumentException($"Method '{methodName}' not found in type '{type.FullName}'.");
}
MethodInfo methodInfo = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new ArgumentException($"Method '{methodName}' not found in type '{type.FullName}'.");
methodInfo.Invoke(instance, null);
}
private static T InvokeInstanceFunction<T>(object instance, string methodName)
{
if (instance == null)
{
throw new ArgumentNullException(nameof(instance));
}
ArgumentNullException.ThrowIfNull(instance);
if (string.IsNullOrEmpty(methodName))
{
@@ -215,13 +194,7 @@ public class RemoteControlService
}
Type type = instance.GetType();
MethodInfo methodInfo = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
if (methodInfo == null)
{
throw new ArgumentException($"Method '{methodName}' not found in type '{type.FullName}'.");
}
MethodInfo methodInfo = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new ArgumentException($"Method '{methodName}' not found in type '{type.FullName}'.");
if (!typeof(T).IsAssignableFrom(methodInfo.ReturnType))
{
throw new ArgumentException($"Method '{methodName}' is not {typeof(T)}.");
@@ -232,10 +205,7 @@ public class RemoteControlService
private static async Task<T> InvokeInstanceAsyncFunction<T>(object instance, string methodName)
{
if (instance == null)
{
throw new ArgumentNullException(nameof(instance));
}
ArgumentNullException.ThrowIfNull(instance);
if (string.IsNullOrEmpty(methodName))
{
@@ -243,12 +213,7 @@ public class RemoteControlService
}
Type type = instance.GetType();
MethodInfo methodInfo = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
if (methodInfo == null)
{
throw new ArgumentException($"Method '{methodName}' not found in type '{type.FullName}'.");
}
MethodInfo methodInfo = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new ArgumentException($"Method '{methodName}' not found in type '{type.FullName}'.");
// 检查方法是否是异步方法 (返回Task或Task<T>)
if (!typeof(Task).IsAssignableFrom(methodInfo.ReturnType))
@@ -261,10 +226,7 @@ public class RemoteControlService
private static TResult InvokeStaticFunction<TResult>(Type staticType, string methodName)
{
if (staticType == null)
{
throw new ArgumentNullException(nameof(staticType));
}
ArgumentNullException.ThrowIfNull(staticType);
if (string.IsNullOrEmpty(methodName))
{
@@ -273,12 +235,9 @@ public class RemoteControlService
MethodInfo methodInfo = staticType.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Static);
if (methodInfo == null)
{
throw new ArgumentException($"Method '{methodName}' not found in type '{staticType.FullName}'.");
}
return (TResult)methodInfo.Invoke(null, null);
return methodInfo == null
? throw new ArgumentException($"Method '{methodName}' not found in type '{staticType.FullName}'.")
: (TResult)methodInfo.Invoke(null, null);
}
#endregion
@@ -348,6 +307,9 @@ public class RemoteControlService
case "StopTask":
_instantTaskQueue.Enqueue(task);
break;
default:
AchievementTrackerHelper.Instance.Unlock(AchievementIds.NotFound404);
break;
}
}
}
@@ -459,11 +421,8 @@ public class RemoteControlService
TaskQueueViewModel.FightTask.Stage1 = data;
});
break;
// ReSharper disable once RedundantEmptySwitchSection
default:
// 未知的Type统一直接发给MAACore
// No! 未知的任务一概不处理
AchievementTrackerHelper.Instance.Unlock(AchievementIds.NotFound404);
break;
}
@@ -555,10 +514,8 @@ public class RemoteControlService
break;
}
// ReSharper disable once RedundantEmptySwitchSection
default:
// 未知的Type统一直接发给MAACore
// No! 未知的任务一概不处理
AchievementTrackerHelper.Instance.Unlock(AchievementIds.NotFound404);
break;
}

View File

@@ -641,6 +641,11 @@ public class TaskQueueViewModel : Screen
_lastTimerElapsed = currentTime;
if ((currentTime.Hour == 3 || currentTime.Hour == 13 || currentTime.Hour == 23) && currentTime.Minute == 25 && !Idle)
{
AchievementTrackerHelper.Instance.Unlock(AchievementIds.Time325);
}
VersionUpdateSettingsUserControlModel.Instance.RefreshMirrorChyanCdkRemaining();
HandleDatePromptUpdate();
HandleCheckForUpdates();
@@ -1641,6 +1646,8 @@ public class TaskQueueViewModel : Screen
return;
}
AchievementTrackerHelper.Instance.SetProgress(AchievementIds.TaskChainKing, count);
taskRet &= Instances.AsstProxy.AsstStart();
if (taskRet)

View File

@@ -489,20 +489,35 @@ public class ToolboxViewModel : Screen
foreach (var item in sortedItems)
{
var id = (string?)item["id"];
if (id == null)
if (string.IsNullOrEmpty(id))
{
continue;
}
int count = -1;
bool hasValidCount = false;
if (item["have"] != null)
{
var haveValue = item["have"]?.ToString();
hasValidCount = int.TryParse(haveValue, out count);
}
string countStr = hasValidCount ? count.FormatNumber(false) : "-1";
DepotResultDate result = new() {
Id = id,
Name = ItemListHelper.GetItemName(id),
Image = ItemListHelper.GetItemImage(id),
Count = item["have"] != null && int.TryParse(item["have"]?.ToString() ?? "-1", out int haveValue)
? haveValue.FormatNumber(false)
: "-1",
Count = countStr,
};
if (hasValidCount && count > 0 &&
count > AchievementTrackerHelper.Instance.GetProgress(AchievementIds.WarehouseMiser))
{
AchievementTrackerHelper.Instance.SetProgress(AchievementIds.WarehouseMiser, count);
}
DepotResult.Add(result);
}
@@ -695,6 +710,11 @@ public class ToolboxViewModel : Screen
if (ids.Contains(id))
{
OperBoxHaveList.Add(new Operator(id, name, oper.Rarity));
if (id == "char_485_pallas")
{
AchievementTrackerHelper.Instance.Unlock(AchievementIds.WarehouseKeeper);
}
}
else
{
@@ -733,6 +753,10 @@ public class ToolboxViewModel : Screen
{
var name = DataHelper.GetLocalizedCharacterName(DataHelper.Operators.FirstOrDefault(i => i.Key == oper.Id).Value) ?? "???";
OperBoxHaveList.Add(new Operator(oper.Id, name, oper.Rarity));
if (oper.Id == "char_485_pallas")
{
AchievementTrackerHelper.Instance.Unlock(AchievementIds.WarehouseKeeper);
}
}
}

View File

@@ -339,8 +339,9 @@ public class GuiSettingsUserControlModel : PropertyChangedBase
// var backup = _language;
ConfigurationHelper.SetGlobalValue(ConfigurationKeys.Localization, value);
var mainWindow = Application.Current.MainWindow;
AchievementTrackerHelper.Instance.Unlock(AchievementIds.Linguist);
var mainWindow = Application.Current.MainWindow;
if (mainWindow != null)
{
mainWindow.Show();

View File

@@ -71,6 +71,7 @@ public class StartSettingsUserControlModel : PropertyChangedBase
}
SetAndNotify(ref _startSelf, value);
AchievementTrackerHelper.Instance.Unlock(AchievementIds.StartupBoot);
}
}

View File

@@ -9,7 +9,7 @@
Title="{DynamicResource AchievementList}"
Width="600"
Height="400"
MinWidth="250"
MinWidth="300"
Background="{DynamicResource MdXamlBackground}">
<Grid>
<ListBox
@@ -22,14 +22,18 @@
VirtualizingPanel.ScrollUnit="Pixel">
<ListBox.ItemTemplate>
<DataTemplate>
<VirtualizingStackPanel Orientation="Horizontal" Visibility="{c:Binding 'IsUnlocked or !IsHidden'}">
<Grid Visibility="{c:Binding 'IsUnlocked or !IsHidden'}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Path
Width="40"
Height="40"
uiBehaviors:ResourceReferenceHelper.FillResourceKey="{Binding MedalBrushKey}"
Data="{DynamicResource HangoverGeometry}"
Stretch="Uniform" />
<VirtualizingStackPanel Margin="8" HorizontalAlignment="Left">
<VirtualizingStackPanel Grid.Column="1" Margin="8">
<VirtualizingStackPanel
HorizontalAlignment="Left"
Background="{DynamicResource MdXamlBackground}"
@@ -45,10 +49,30 @@
Foreground="{DynamicResource TraceLogBrush}"
Text="{Binding Description}"
TextWrapping="Wrap" />
<TextBlock
Foreground="{DynamicResource InfoLogBrush}"
Text="{Binding Conditions}"
TextWrapping="Wrap" />
<Grid HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
Foreground="{DynamicResource InfoLogBrush}"
Text="{Binding Conditions}"
TextWrapping="Wrap" />
<TextBlock
Grid.Column="1"
Margin="5,0,0,0"
VerticalAlignment="Center"
Foreground="{DynamicResource InfoLogBrush}"
Opacity="0.7"
Visibility="{c:Binding '!IsUnlocked and IsProgressive'}">
<TextBlock.Text>
<MultiBinding StringFormat="{}({0:F0}/{1:F0})">
<Binding Path="Progress" />
<Binding Path="Target" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Grid>
<ProgressBar
Width="200"
Height="12"
@@ -69,7 +93,7 @@
TextWrapping="Wrap" />
</VirtualizingStackPanel>
</VirtualizingStackPanel>
</VirtualizingStackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>

View File

@@ -385,7 +385,7 @@
VerticalAlignment="Center"
Command="{s:Action StartDepot}"
Content="{DynamicResource StartToDepotRecognition}"
IsEnabled="{Binding 'Idle and Inited'}" />
IsEnabled="{c:Binding 'Idle and Inited'}" />
</StackPanel>
</Grid>
</TabItem>

View File

@@ -5,11 +5,11 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="UserControl"
d:DesignWidth="180"
d:DesignWidth="200"
mc:Ignorable="d">
<TextBox
x:Name="HotKeyTextBox"
Width="180"
Width="200"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
InputMethod.IsInputMethodEnabled="False"

View File

@@ -15,6 +15,8 @@
using System.Windows;
using System.Windows.Input;
using MaaWpfGui.Constants;
using MaaWpfGui.Helper;
using MaaWpfGui.Services.HotKeys;
namespace MaaWpfGui.Views.UserControl;
@@ -42,6 +44,18 @@ public partial class HotKeyEditorUserControl : System.Windows.Controls.UserContr
InitializeComponent();
}
private static int CountModifierKeys(ModifierKeys modifiers)
{
int count = 0;
#pragma warning disable SA1503 // Braces should not be omitted
if ((modifiers & ModifierKeys.Control) != 0) count++;
if ((modifiers & ModifierKeys.Alt) != 0) count++;
if ((modifiers & ModifierKeys.Shift) != 0) count++;
if ((modifiers & ModifierKeys.Windows) != 0) count++;
#pragma warning restore SA1503 // Braces should not be omitted
return count;
}
private void HotKeyTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
// Don't let the event pass further
@@ -84,6 +98,12 @@ public partial class HotKeyEditorUserControl : System.Windows.Controls.UserContr
return;
}
int modifierCount = CountModifierKeys(modifiers);
if (modifierCount >= 4)
{
AchievementTrackerHelper.Instance.Unlock(AchievementIds.HotkeyMagician);
}
// Update the value
HotKey = new MaaHotKey(key, modifiers);
}