Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 64 additions & 6 deletions MeoAsstMac/Task Configurations/CopilotConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,75 @@

import Foundation

struct RegularCopilotConfiguration: Codable {
struct RegularCopilotConfiguration: Codable, Hashable {
var enable = true

var filename: String

struct CopilotItem: Codable, Hashable {
let filename: String
let stage_name: String
let is_raid: Bool
}

var copilot_list: [CopilotItem]

var loop_times = 1

var use_sanity_potion = false

var formation = false
var formation_index = 0
static let formationCount = 4

struct UserUnit: Codable, Hashable {
let name: String
let skill: Int
}

var user_additional = [UserUnit]()

var add_trust = false
var ignore_requirements = false

enum SupportUnitUsage: Int, CaseIterable, Codable {
/// 不加助战干员
case none = 0
/// 如果仅缺一名干员则尝试补助战
case whenNeeded = 1
/// 如果仅缺一名干员则尝试补助战,如无缺失则随机加一个助战干员
case random = 3
/// 如果仅缺一名干员则尝试补助战,如无缺失则使用指定助战干员
case specific = 2

var description: String {
switch self {
case .none:
return String(localized: "不借", comment: "")
case .whenNeeded:
return String(localized: "补漏", comment: "")
case .specific:
return String(localized: "指定", comment: "")
case .random:
return String(localized: "随机", comment: "")
}
}
}

var support_unit_usage: SupportUnitUsage = .none
var support_unit_name = ""
}

struct SSSCopilotConfiguration: Codable {
var enable = true
var filename: String
var loop_times = 1
typealias SSSCopilotConfiguration = RegularCopilotConfiguration

extension RegularCopilotConfiguration {
init(filename: String) {
self.init(filename: filename, copilot_list: [])
}

init(copilotList: [CopilotItem]) {
self.init(filename: "", copilot_list: copilotList)
}
}

struct VideoRecognitionConfiguration: Codable {
Expand All @@ -29,7 +87,7 @@ struct VideoRecognitionConfiguration: Codable {
}
}

enum CopilotConfiguration {
enum CopilotConfiguration: Hashable {
case regular(RegularCopilotConfiguration)
case sss(SSSCopilotConfiguration)

Expand Down
127 changes: 98 additions & 29 deletions MeoAsstMac/Views/CopilotView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,16 @@ struct CopilotView: View {
var body: some View {
if let copilot = MAACopilot(url: url) {
VStack(spacing: 20) {
pilotConfiguration()
CopilotConfigView(config: $viewModel.copilot).padding(.top)

Divider()

ScrollView {
pilotDescription(pilot: copilot)
CopilotDescriptionView(pilot: copilot)
}
}
.task(id: url) { updateCopilot() }
.animation(.default, value: formation)
} else {
Text("文件格式错误")
}
Expand All @@ -41,41 +42,96 @@ struct CopilotView: View {
MAACopilot(url: url)
}

// MARK: - Copilot Config

@ViewBuilder private func pilotConfiguration() -> some View {
private var formation: Bool {
switch viewModel.copilot {
case .regular(let innerConfig):
let binding = Binding<RegularCopilotConfiguration> {
innerConfig.formation
default:
false
}
}
}

// MARK: - Copilot Config

private struct CopilotConfigView: View {
@Binding var config: CopilotConfiguration?

var body: some View {
switch config {
case .regular(let innerConfig):
let binding = Binding {
innerConfig
} set: { newValue in
viewModel.copilot = .regular(newValue)
self.config = .regular(newValue)
}
HStack {
Toggle("自动编队", isOn: binding.formation)
Toggle("信赖干员", isOn: binding.add_trust)
}

RegularCopilotConfigView(config: binding)
case .sss(let innerConfig):
let binding = Binding<SSSCopilotConfiguration> {
let binding = Binding {
innerConfig
} set: { newValue in
viewModel.copilot = .sss(newValue)
self.config = .sss(newValue)
}
HStack {
Text("循环次数")
TextField("1", value: binding.loop_times, format: .number)
}
.frame(maxWidth: 130)

SSSCopilotConfigView(config: binding)
case .none:
EmptyView()
}
}
}

// MARK: - Copilot Document
private struct RegularCopilotConfigView: View {
@Binding var config: RegularCopilotConfiguration

@ViewBuilder private func pilotDescription(pilot: MAACopilot) -> some View {
var body: some View {
VStack {
Toggle("自动编队", isOn: $config.formation)
if config.formation {
HStack {
Picker("编队栏位", selection: $config.formation_index) {
Text("当前").tag(0)
ForEach(0..<RegularCopilotConfiguration.formationCount, id: \.self) { index in
Text("\(index + 1)").tag(index + 1)
}
}
.pickerStyle(.menu)
Toggle("忽视干员属性要求", isOn: $config.ignore_requirements)
Toggle("补充低信赖干员", isOn: $config.add_trust)
}
HStack {
Picker("助战模式", selection: $config.support_unit_usage) {
ForEach(RegularCopilotConfiguration.SupportUnitUsage.allCases, id: \.self) {
Text($0.description).tag($0)
}
}
if config.support_unit_usage == .specific {
TextField("干员名称", text: $config.support_unit_name)
.frame(maxWidth: 150)
}
}
.animation(.default, value: config.support_unit_usage)
}
}
}
}

private struct SSSCopilotConfigView: View {
@Binding var config: SSSCopilotConfiguration

var body: some View {
HStack {
Text("循环次数")
TextField("1", value: $config.loop_times, format: .number)
}
.frame(maxWidth: 130)
}
}

// MARK: - Copilot Document

private struct CopilotDescriptionView: View {
let pilot: MAACopilot

var body: some View {
if let title = pilot.doc?.title {
Text(title).font(.title2)
}
Expand Down Expand Up @@ -114,17 +170,30 @@ struct CopilotView: View {
}
}

struct CopilotView_Previews: PreviewProvider {
static let url = Bundle.main.resourceURL!
#Preview("Regular Copilot Config") {
let url = Bundle.main.resourceURL!
.appendingPathComponent("resource")
.appendingPathComponent("copilot")
.appendingPathComponent("OF-1_credit_fight")
.appendingPathExtension("json")

VStack {
CopilotView(url: url)
}
.environmentObject(MAAViewModel())
}

#Preview("SSS Copilot Config") {
let url = Bundle.main.resourceURL!
.appendingPathComponent("resource")
.appendingPathComponent("copilot")
.appendingPathComponent("old")
.appendingPathComponent("约翰老妈新建地块_Mama_Johns_New_Plate")
.appendingPathComponent("SSS_约翰老妈新建地块")
.appendingPathExtension("json")

static var previews: some View {
VStack {
CopilotView(url: url)
}
.environmentObject(MAAViewModel())
VStack {
CopilotView(url: url)
}
.environmentObject(MAAViewModel())
}
37 changes: 37 additions & 0 deletions Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -1783,6 +1783,9 @@
}
}
}
},
"不借" : {

},
"不切换" : {
"localizations" : {
Expand Down Expand Up @@ -2048,6 +2051,7 @@
}
},
"信赖干员" : {
"extractionState" : "stale",
"localizations" : {
"ko" : {
"stringUnit" : {
Expand Down Expand Up @@ -2586,6 +2590,9 @@
}
}
}
},
"助战模式" : {

},
"单设施最优解" : {
"localizations" : {
Expand Down Expand Up @@ -2738,6 +2745,9 @@
}
}
}
},
"地图太复杂了,先整个简单的刷钱脚本。\n在右下角有开始探索的界面开始。\n使用特勤分队 + 开局给的结构性原理(鹿精二后卖 10 个零件解锁的招募精通II 效果提升II,不是天赋的召唤物)跳节点。\n之前有手动刷过开局低保或者有襁褓生灵的自己开一把直接放弃。" : {

},
"基建工作心情阈值: %.0f%%" : {
"localizations" : {
Expand Down Expand Up @@ -2988,6 +2998,9 @@
}
}
}
},
"干员名称" : {

},
"干员寻访" : {
"localizations" : {
Expand Down Expand Up @@ -3098,6 +3111,9 @@
}
}
}
},
"当前" : {

},
"当前/上次" : {
"localizations" : {
Expand Down Expand Up @@ -3138,6 +3154,9 @@
}
}
}
},
"忽视干员属性要求" : {

},
"我已知晓,继续" : {
"localizations" : {
Expand Down Expand Up @@ -3227,6 +3246,9 @@
}
}
}
},
"指定" : {

},
"指定材料" : {
"localizations" : {
Expand Down Expand Up @@ -4119,6 +4141,9 @@
}
}
}
},
"编队栏位" : {

},
"繁中服(txwy)" : {
"localizations" : {
Expand Down Expand Up @@ -4389,6 +4414,12 @@
}
}
}
},
"补充低信赖干员" : {

},
"补漏" : {

},
"装备:" : {
"localizations" : {
Expand Down Expand Up @@ -4788,6 +4819,9 @@
}
}
}
},
"随机" : {

},
"随机奖励" : {
"localizations" : {
Expand Down Expand Up @@ -4918,6 +4952,9 @@
}
}
}
},
"黑流树海刷钱" : {

},
"默认兼容模式" : {

Expand Down