diff --git a/src/MaaWpfGui/Configuration/Single/MaaTask/FightTask.cs b/src/MaaWpfGui/Configuration/Single/MaaTask/FightTask.cs
index a1b4c9eecb..833c39b820 100644
--- a/src/MaaWpfGui/Configuration/Single/MaaTask/FightTask.cs
+++ b/src/MaaWpfGui/Configuration/Single/MaaTask/FightTask.cs
@@ -16,6 +16,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
+using MaaWpfGui.Constants.Enums;
using static MaaWpfGui.Main.AsstProxy;
namespace MaaWpfGui.Configuration.Single.MaaTask;
@@ -127,6 +128,8 @@ public class FightTask : BaseTask, IJsonOnDeserialized
///
public bool HideSeries { get; set; }
+ public FightStageResetMode StageResetMode { get; set; } = FightStageResetMode.Current;
+
///
/// Gets or sets a value indicating whether 是否启用周计划
///
diff --git a/src/MaaWpfGui/Constants/Enums/FightStageResetMode.cs b/src/MaaWpfGui/Constants/Enums/FightStageResetMode.cs
new file mode 100644
index 0000000000..4484c4588f
--- /dev/null
+++ b/src/MaaWpfGui/Constants/Enums/FightStageResetMode.cs
@@ -0,0 +1,27 @@
+//
+// Part of the MaaWpfGui project, maintained by the MaaAssistantArknights team (Maa Team)
+// Copyright (C) 2021-2025 MaaAssistantArknights Contributors
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License v3.0 only as published by
+// the Free Software Foundation, either version 3 of the License, or
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY
+//
+
+namespace MaaWpfGui.Constants.Enums;
+
+public enum FightStageResetMode
+{
+ ///
+ /// 当前 / 上次
+ ///
+ Current,
+
+ ///
+ /// 无效关卡
+ ///
+ Invalid,
+}
diff --git a/src/MaaWpfGui/Res/Localizations/en-us.xaml b/src/MaaWpfGui/Res/Localizations/en-us.xaml
index 07a04a0fd4..71d5b2e741 100644
--- a/src/MaaWpfGui/Res/Localizations/en-us.xaml
+++ b/src/MaaWpfGui/Res/Localizations/en-us.xaml
@@ -587,6 +587,7 @@ Then delete the entries corresponding to the paths.
Use alternative stage
Unlimited use of expiring (<48h) sanity potion
Hide today's not open stages
+ Unopened stage is reset to
Hide series
Variable function button
Manual entry of stage names
@@ -738,14 +739,15 @@ If the number of battles is not enough to complete the set multiplier (such as o
• {key=NotSwitch}:
Do not adjust the proxy multiplier setting in the game
Stage
- Alternative
- Add stage
+ Candidates
+ Add candidate
Remaining Sanity
No Use
Cur/Last
+ Invalid
The event is not open
Unsupported stages
Old Version, Update required
diff --git a/src/MaaWpfGui/Res/Localizations/ja-jp.xaml b/src/MaaWpfGui/Res/Localizations/ja-jp.xaml
index f064d124b3..c40c05bf3b 100644
--- a/src/MaaWpfGui/Res/Localizations/ja-jp.xaml
+++ b/src/MaaWpfGui/Res/Localizations/ja-jp.xaml
@@ -586,7 +586,8 @@ HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Notifications\Settin
この機能は危険な機能と見なされます。「{key=Confirm}」ボタンを押すと、リスクを理解し、受け入れることに同意したと見なされます。
代替ステージを選択可能にする
48時間以内に期限が切れる回復剤を無制限に使用
- 当日開放されないステージを隠す
+ リストに当日開放されないステージを隠す
+ 未開放のレベルをこれにリセットする
連戦回数を隠します
スタート画面に表示する便利ボタン
ステージ名を入力する
@@ -747,6 +748,7 @@ C:\\leidian\\LDPlayer9
現在/前回
+ 無効なレベル
ステージが未公開か既に終了している
未サポートステージ
バージョンの更新が必要
diff --git a/src/MaaWpfGui/Res/Localizations/ko-kr.xaml b/src/MaaWpfGui/Res/Localizations/ko-kr.xaml
index 0d6e6a7295..c88bc14a7f 100644
--- a/src/MaaWpfGui/Res/Localizations/ko-kr.xaml
+++ b/src/MaaWpfGui/Res/Localizations/ko-kr.xaml
@@ -587,6 +587,7 @@ HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Notifications\Settin
대체 스테이지 사용
48시간 미만 이성 회복제 사용
미개방 스테이지 숨기기
+ 미개방 스테이지 재설정
{key=Series} 숨기기
메인 화면 버튼의 기능
스테이지 코드 수동 입력
@@ -748,7 +749,8 @@ C:\\leidian\\LDPlayer9
현재/최근
- 이벤트가 닫혀 있습니다
+ 잘못된 스테이지
+ 미개방 스테이지
미지원 스테이지
낮은 버전
최소 요구사항:
diff --git a/src/MaaWpfGui/Res/Localizations/zh-cn.xaml b/src/MaaWpfGui/Res/Localizations/zh-cn.xaml
index a704d1fb06..8ac7a94e5a 100644
--- a/src/MaaWpfGui/Res/Localizations/zh-cn.xaml
+++ b/src/MaaWpfGui/Res/Localizations/zh-cn.xaml
@@ -586,7 +586,8 @@ HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Notifications\Settin
该功能属于危险功能。按下 「{key=Confirm}」 键即视为你了解并愿意承担可能出现的风险。
使用备选关卡
无限吃 48 小时内过期的理智药
- 隐藏当日不开放关卡
+ 下拉框中隐藏当日不开放关卡
+ 未开放关卡重置为
隐藏代理倍率
主界面可选择按钮功能
手动输入关卡名
@@ -738,15 +739,16 @@ C:\\leidian\\LDPlayer9。\n
• {key=NotSwitch}:
不调整游戏内代理倍率设定
- 关卡选择
- 关卡备选
- 添加关卡
+ 关卡指定
+ 候选关卡
+ 添加候选
剩余理智
不使用
当前/上次
+ 无效关卡
活动未开放
不支持的关卡
版本过低
diff --git a/src/MaaWpfGui/Res/Localizations/zh-tw.xaml b/src/MaaWpfGui/Res/Localizations/zh-tw.xaml
index 5df1d2ead2..f67c34cb00 100644
--- a/src/MaaWpfGui/Res/Localizations/zh-tw.xaml
+++ b/src/MaaWpfGui/Res/Localizations/zh-tw.xaml
@@ -586,7 +586,8 @@ HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Notifications\Settin
該功能屬於危險功能。按下 「{key=Confirm}」 鍵即視為您了解並願意承擔可能出現的風險。
使用備選關卡
無限吃 48 小時內過期的理智藥
- 隱藏當日不開放關卡
+ 下拉選單中隱藏當日不開放關卡
+ 未開放關卡重設為
隱藏代理倍率
主介面可選擇按鈕功能
手動輸入關卡名稱
@@ -740,13 +741,14 @@ C:\\leidian\\LDPlayer9\n
不調整遊戲內代理倍率設定
關卡選擇
備選
- 新增關卡
+ 新增備選
剩餘理智
不選擇
目前/上次
+ 無效關卡
活動未開放
不支援的關卡
版本過低
diff --git a/src/MaaWpfGui/ViewModels/UserControl/TaskQueue/FightSettingsUserControlModel.cs b/src/MaaWpfGui/ViewModels/UserControl/TaskQueue/FightSettingsUserControlModel.cs
index eb23568205..a35cd632db 100644
--- a/src/MaaWpfGui/ViewModels/UserControl/TaskQueue/FightSettingsUserControlModel.cs
+++ b/src/MaaWpfGui/ViewModels/UserControl/TaskQueue/FightSettingsUserControlModel.cs
@@ -22,6 +22,7 @@ using JetBrains.Annotations;
using MaaWpfGui.Configuration.Factory;
using MaaWpfGui.Configuration.Single.MaaTask;
using MaaWpfGui.Constants;
+using MaaWpfGui.Constants.Enums;
using MaaWpfGui.Helper;
using MaaWpfGui.Models;
using MaaWpfGui.Models.AsstTasks;
@@ -91,6 +92,8 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
{ "炭", "SK-5" },
};
+ private readonly StageSourceItem InvalidStage = new() { Display = LocalizationHelper.GetString("InvalidStage"), Value = "__INVALID__", IsOpen = false, IsVisible = false };
+
public ObservableCollection StagePlan { get => field; set => SetAndNotify(ref field, value); } = [new()];
// UI 绑定的方法
@@ -386,11 +389,11 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
foreach (var task in ConfigFactory.CurrentConfig.TaskQueue.OfType())
{
if (AllDrops.FirstOrDefault(i => i.Value == task.DropId) is not { } item)
- {
+ {
task.DropId = string.Empty;
+ }
}
}
- }
///
/// Gets or private sets the list of drops.
@@ -461,7 +464,10 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
public string AnnihilationStage
{
get => GetTaskConfig().AnnihilationStage;
- set => SetTaskConfig(t => t.AnnihilationStage == value, t => t.AnnihilationStage = value);
+ set {
+ SetTaskConfig(t => t.AnnihilationStage == value, t => t.AnnihilationStage = value);
+ StageListSource.FirstOrDefault(i => i.Value == "Annihilation")?.Display = UseCustomAnnihilation ? (AnnihilationModeList.FirstOrDefault(i => i.Value == value).Key ?? LocalizationHelper.GetString("Annihilation.Current")) : LocalizationHelper.GetString("Annihilation.Current");
+ }
}
///
@@ -484,6 +490,7 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
if (value)
{
HideUnavailableStage = false;
+ StageResetMode = FightStageResetMode.Invalid;
}
else
{
@@ -549,14 +556,27 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
if (value)
{
UseAlternateStage = false;
+ StageResetMode = FightStageResetMode.Current;
}
if (update)
{
- UpdateStageList();
+ RefreshStageList();
}
}
}
+ public List> StageResetModeList { get; } =
+ [
+ new() { Display = LocalizationHelper.GetString("DefaultStage"), Value = FightStageResetMode.Current },
+ new() { Display = LocalizationHelper.GetString("InvalidStage"), Value = FightStageResetMode.Invalid },
+ ];
+
+ public FightStageResetMode StageResetMode
+ {
+ get => GetTaskConfig().StageResetMode;
+ set => SetTaskConfig(t => t.StageResetMode == value, t => t.StageResetMode = value);
+ }
+
///
/// Gets or sets a value indicating whether to hide series.
///
@@ -617,8 +637,9 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
public static string? GetFightStage(IEnumerable stageNames)
{
- var stage = stageNames.FirstOrDefault(Instances.TaskQueueViewModel.IsStageOpen);
- stage ??= stageNames.FirstOrDefault();
+ var list = stageNames.Where(i => i != Instance.InvalidStage.Value);
+ var stage = list.FirstOrDefault(Instances.TaskQueueViewModel.IsStageOpen);
+ stage ??= list.FirstOrDefault();
return stage;
}
@@ -633,7 +654,7 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
{
fight.StagePlan.Add(string.Empty);
}
- UpdateStageList(); // 临时修复, 应为同步
+ RefreshStageList();
RefreshCurrentStagePlan();
RefreshWeeklySchedule();
RefreshDropName();
@@ -680,12 +701,12 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
private bool? SetFightParams()
{
- if (TaskSettingVisibilityInfo.CurrentTask is not FightTask fight)
+ if (IsRefreshingUI || TaskSettingVisibilityInfo.CurrentTask is not FightTask fight)
{
return null;
}
- if (ConfigFactory.CurrentConfig.TaskQueue.IndexOf(fight) is int index && index > -1)
+ if (ConfigFactory.CurrentConfig.TaskQueue.IndexOf(fight) is int index && index > -1 && Instances.TaskQueueViewModel.TaskItemViewModels[index].TaskId > 0)
{
return SerializeTask(fight, Instances.TaskQueueViewModel.TaskItemViewModels[index].TaskId);
}
@@ -695,7 +716,7 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
public override bool? SerializeTask(BaseTask? baseTask, int? taskId = null)
{
- if (baseTask is not FightTask fight)
+ if (baseTask is not FightTask fight || taskId is int and <= 0)
{
return null;
}
@@ -766,39 +787,48 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
Execute.PostToUIThreadAsync(() => {
_logger.Information("Updating stage list...");
using var scope = _lock.EnterScope();
- bool isFightTaskShow = TaskSettingVisibilityInfo.CurrentTask is FightTask;
- var hideUnavailble = isFightTaskShow && HideUnavailableStage;
- var stageList = Instances.StageManager.GetStageList().ToList();
- var listCurrent = StagePlan.Select(i => i.Value).ToList();
-
- var listSource = stageList.Select(i => new StageSourceItem() { Display = i.Display, Value = i.Value, IsVisible = !hideUnavailble || i.IsStageOpen(Instances.TaskQueueViewModel.CurDayOfWeek), IsOpen = Instances.StageManager.GetStageList().FirstOrDefault(p => p.Value == i.Value)?.IsStageOpen(Instances.TaskQueueViewModel.CurDayOfWeek) ?? true }).ToList();
- if (isFightTaskShow)
- {
- foreach (var item in listCurrent.Where(i => !listSource.Any(p => p.Value == i))) // 补未开放进来
- {
- listSource.Add(new StageSourceItem() { Display = item, Value = item, IsOpen = false, IsVisible = false });
- }
- }
- StageListSource = new ObservableCollection(listSource);
-
- if (TaskSettingVisibilityInfo.CurrentTask is FightTask current)
- {
- current.StagePlan = listCurrent;
- }
+ var stageList = Instances.StageManager.GetStageList();
+ RefreshStageList();
foreach (var task in ConfigFactory.CurrentConfig.TaskQueue.Where(i => i is FightTask fight && !fight.IsStageManually).OfType())
{
- var removeList = task.StagePlan.Where(i => !stageList.Any(p => p.Value == i)).ToList();
- if (removeList.Count != 0)
+ for (int i = 0; i < task.StagePlan.Count; i++)
{
- _logger.Information("Removed non-existing stage from plan: {Stage}", removeList);
- task.StagePlan = [.. task.StagePlan.Where(i => stageList.Any(p => p.Value == i))];
+ var stage = task.StagePlan[i];
+ if (stage != InvalidStage.Value && !stageList.Any(p => p.Value == stage))
+ {
+ task.StagePlan[i] = task.StageResetMode switch {
+ FightStageResetMode.Current => string.Empty,
+ FightStageResetMode.Invalid => InvalidStage.Value,
+ _ => string.Empty,
+ };
+ _logger.Information("Reset non-existing stage from plan: {Stage} to {}", stage, task.StagePlan[i]);
+ }
}
}
-
RefreshCurrentStagePlan();
});
}
+ private void RefreshStageList()
+ {
+ if (TaskSettingVisibilityInfo.CurrentTask is not FightTask current)
+ {
+ return;
+ }
+ var stageList = Instances.StageManager.GetStageList().ToList();
+ var listCurrent = StagePlan.Select(i => i.Value).ToList();
+
+ var listSource = stageList.Select(i => new StageSourceItem() { Display = i.Display, Value = i.Value, IsVisible = !HideUnavailableStage || i.IsStageOpen(Instances.TaskQueueViewModel.CurDayOfWeek), IsOpen = Instances.StageManager.GetStageList().FirstOrDefault(p => p.Value == i.Value)?.IsStageOpen(Instances.TaskQueueViewModel.CurDayOfWeek) ?? true }).ToList();
+ foreach (var item in listCurrent.Where(i => !listSource.Any(p => p.Value == i))) // 补未开放进来
+ {
+ listSource.Add(new StageSourceItem() { Display = item, Value = item, IsOpen = false, IsVisible = false });
+ }
+ listSource.Add(InvalidStage); // 无效关卡
+ listSource.FirstOrDefault(i => i.Value == "Annihilation")?.Display = current.UseCustomAnnihilation ? (AnnihilationModeList.FirstOrDefault(i => i.Value == current.AnnihilationStage).Key ?? LocalizationHelper.GetString("Annihilation.Current")) : LocalizationHelper.GetString("Annihilation.Current");
+ StageListSource = new ObservableCollection(listSource);
+ current.StagePlan = listCurrent; // StageListSource更新后, 恢复StagePlan
+ }
+
private void RefreshCurrentStagePlan()
{
if (TaskSettingVisibilityInfo.CurrentTask is not FightTask)
@@ -895,7 +925,7 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
public class StageSourceItem : PropertyChangedBase
{
- public string Display { get; set; } = string.Empty;
+ public string Display { get => field; set => SetAndNotify(ref field, value); } = string.Empty;
public string Value { get; set; } = string.Empty;
@@ -925,7 +955,15 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
return;
}
- IsOpen = Instances.StageManager.GetStageList().FirstOrDefault(p => p.Value == value)?.IsStageOpen(Instances.TaskQueueViewModel.CurDayOfWeek) ?? true;
+ if (value == Instance.InvalidStage.Value)
+ {
+ IsOpen = false;
+ }
+ else
+ {
+ IsOpen = Instances.StageManager.GetStageList().FirstOrDefault(p => p.Value == value)?.IsStageOpen(Instances.TaskQueueViewModel.CurDayOfWeek) ?? true;
+ }
+ Instance.SetFightParams();
}
} = string.Empty;
diff --git a/src/MaaWpfGui/Views/UserControl/TaskQueue/FightSettingsUserControl.xaml b/src/MaaWpfGui/Views/UserControl/TaskQueue/FightSettingsUserControl.xaml
index 42785ac046..056b500137 100644
--- a/src/MaaWpfGui/Views/UserControl/TaskQueue/FightSettingsUserControl.xaml
+++ b/src/MaaWpfGui/Views/UserControl/TaskQueue/FightSettingsUserControl.xaml
@@ -398,6 +398,20 @@
+
+
+
+
+