next step

This commit is contained in:
Rory Hinnen
2026-09-13 18:08:11 -05:00
parent 2034dbab40
commit e4e7c9fa0d
9 changed files with 56 additions and 68 deletions
-4
View File
@@ -13,7 +13,6 @@
7619A15A3055ABB600E6F277 /* ArmourCalculatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7619A1593055ABB600E6F277 /* ArmourCalculatorView.swift */; }; 7619A15A3055ABB600E6F277 /* ArmourCalculatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7619A1593055ABB600E6F277 /* ArmourCalculatorView.swift */; };
7619A15C3055AF2400E6F277 /* StatePickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7619A15B3055AF2400E6F277 /* StatePickerView.swift */; }; 7619A15C3055AF2400E6F277 /* StatePickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7619A15B3055AF2400E6F277 /* StatePickerView.swift */; };
7619A15E3055AF2A00E6F277 /* RollSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7619A15D3055AF2A00E6F277 /* RollSummaryView.swift */; }; 7619A15E3055AF2A00E6F277 /* RollSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7619A15D3055AF2A00E6F277 /* RollSummaryView.swift */; };
7619A1603055AF3100E6F277 /* DieView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7619A15F3055AF3100E6F277 /* DieView.swift */; };
7619A1623055AF3300E6F277 /* DiePoolView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7619A1613055AF3300E6F277 /* DiePoolView.swift */; }; 7619A1623055AF3300E6F277 /* DiePoolView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7619A1613055AF3300E6F277 /* DiePoolView.swift */; };
7619A1643055AF3900E6F277 /* InfoAreaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7619A1633055AF3900E6F277 /* InfoAreaView.swift */; }; 7619A1643055AF3900E6F277 /* InfoAreaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7619A1633055AF3900E6F277 /* InfoAreaView.swift */; };
7619A1663055AF3D00E6F277 /* ButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7619A1653055AF3D00E6F277 /* ButtonView.swift */; }; 7619A1663055AF3D00E6F277 /* ButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7619A1653055AF3D00E6F277 /* ButtonView.swift */; };
@@ -61,7 +60,6 @@
7619A1593055ABB600E6F277 /* ArmourCalculatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArmourCalculatorView.swift; sourceTree = "<group>"; }; 7619A1593055ABB600E6F277 /* ArmourCalculatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArmourCalculatorView.swift; sourceTree = "<group>"; };
7619A15B3055AF2400E6F277 /* StatePickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatePickerView.swift; sourceTree = "<group>"; }; 7619A15B3055AF2400E6F277 /* StatePickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatePickerView.swift; sourceTree = "<group>"; };
7619A15D3055AF2A00E6F277 /* RollSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RollSummaryView.swift; sourceTree = "<group>"; }; 7619A15D3055AF2A00E6F277 /* RollSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RollSummaryView.swift; sourceTree = "<group>"; };
7619A15F3055AF3100E6F277 /* DieView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DieView.swift; sourceTree = "<group>"; };
7619A1613055AF3300E6F277 /* DiePoolView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiePoolView.swift; sourceTree = "<group>"; }; 7619A1613055AF3300E6F277 /* DiePoolView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiePoolView.swift; sourceTree = "<group>"; };
7619A1633055AF3900E6F277 /* InfoAreaView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoAreaView.swift; sourceTree = "<group>"; }; 7619A1633055AF3900E6F277 /* InfoAreaView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoAreaView.swift; sourceTree = "<group>"; };
7619A1653055AF3D00E6F277 /* ButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonView.swift; sourceTree = "<group>"; }; 7619A1653055AF3D00E6F277 /* ButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonView.swift; sourceTree = "<group>"; };
@@ -124,7 +122,6 @@
7619A1593055ABB600E6F277 /* ArmourCalculatorView.swift */, 7619A1593055ABB600E6F277 /* ArmourCalculatorView.swift */,
7619A15B3055AF2400E6F277 /* StatePickerView.swift */, 7619A15B3055AF2400E6F277 /* StatePickerView.swift */,
7619A15D3055AF2A00E6F277 /* RollSummaryView.swift */, 7619A15D3055AF2A00E6F277 /* RollSummaryView.swift */,
7619A15F3055AF3100E6F277 /* DieView.swift */,
7619A1613055AF3300E6F277 /* DiePoolView.swift */, 7619A1613055AF3300E6F277 /* DiePoolView.swift */,
7619A1633055AF3900E6F277 /* InfoAreaView.swift */, 7619A1633055AF3900E6F277 /* InfoAreaView.swift */,
7619A1653055AF3D00E6F277 /* ButtonView.swift */, 7619A1653055AF3D00E6F277 /* ButtonView.swift */,
@@ -384,7 +381,6 @@
981AD0C027C30E31005A6492 /* ContentView.swift in Sources */, 981AD0C027C30E31005A6492 /* ContentView.swift in Sources */,
988B1519285566AD0082C2C5 /* OnboardingView.swift in Sources */, 988B1519285566AD0082C2C5 /* OnboardingView.swift in Sources */,
981AD0E927C31208005A6492 /* Dice.swift in Sources */, 981AD0E927C31208005A6492 /* Dice.swift in Sources */,
7619A1603055AF3100E6F277 /* DieView.swift in Sources */,
7619A1583055ABB400E6F277 /* WoundCalculatorView.swift in Sources */, 7619A1583055ABB400E6F277 /* WoundCalculatorView.swift in Sources */,
98F001D5284F86F1004F5140 /* AddToPool.swift in Sources */, 98F001D5284F86F1004F5140 /* AddToPool.swift in Sources */,
988B150F2854E9170082C2C5 /* HistoryView.swift in Sources */, 988B150F2854E9170082C2C5 /* HistoryView.swift in Sources */,
+5
View File
@@ -32,6 +32,11 @@ extension CaseIterable where Self: Equatable {
} }
} }
extension EnvironmentValues {
@Entry var dieColorSelected: Color = .brown
@Entry var dieColorPrimary: Color = .cyan
}
extension View { extension View {
func disabledWithOpacity(_ condition: Bool) -> some View { func disabledWithOpacity(_ condition: Bool) -> some View {
self.disabled(condition).opacity(condition ? 0.4 : 1.0) self.disabled(condition).opacity(condition ? 0.4 : 1.0)
@@ -15,6 +15,39 @@ struct DiePoolView: View {
} }
} }
private struct DieView: View {
let whichDie: Dice.DiceType
@EnvironmentObject var current: Roll
@Environment(\.dieColorSelected) var colorSelected
@Environment(\.dieColorPrimary) var colorPrimary
var body: some View {
let size = 42.0
let displayColorHit = (whichDie.rawValue >= current.cutoff.rawValue) ? colorSelected : colorPrimary
let displayColorArmor = (whichDie.rawValue <= current.cutoff.rawValue) ? colorSelected : colorPrimary
let displayColorArmorText = (whichDie.rawValue < current.cutoff.rawValue) ? colorSelected : colorPrimary
VStack(spacing: 2) {
Text(String(current.dice.value(which: whichDie)))
.foregroundColor(current.state == .armour ? displayColorArmorText : displayColorHit)
.frame(minWidth: 30, alignment: .center)
Image(systemName: "die.face." + String(whichDie.rawValue) + ".fill")
.foregroundColor(current.state == .armour ? displayColorArmor : displayColorHit)
}
.font(.system(size: size))
.padding(4)
.frame(maxWidth: .infinity)
.gesture(TapGesture().onEnded {
if current.state == .hit {
if whichDie.rawValue != 1 {
current.hitCutoff = whichDie
}
} else if current.state == .armour {
current.armourSave = Int(whichDie.rawValue)
}
})
}
}
#Preview { #Preview {
DiePoolView() DiePoolView()
.environmentObject(Roll()) .environmentObject(Roll())
-45
View File
@@ -1,45 +0,0 @@
//
// DieView.swift
// Bunch O' Dice
//
import SwiftUI
struct DieView: View {
let whichDie: Dice.DiceType
@EnvironmentObject var current: Roll
var colorSelected: Color = Color.green.opacity(0.75)
var colorPrimary: Color = Color.yellow
var body: some View {
let size = 42.0
let displayColorHit = (whichDie.rawValue >= current.cutoff.rawValue) ? colorSelected : colorPrimary
let displayColorArmor = (whichDie.rawValue <= current.cutoff.rawValue) ? colorSelected : colorPrimary
let displayColorArmorText = (whichDie.rawValue < current.cutoff.rawValue) ? colorSelected : colorPrimary
VStack(spacing: 2) {
Text(String(current.dice.value(which: whichDie)))
.foregroundColor(current.state == .armour ? displayColorArmorText : displayColorHit)
.frame(minWidth: 30, alignment: .center)
Image(systemName: "die.face." + String(whichDie.rawValue) + ".fill")
.foregroundColor(current.state == .armour ? displayColorArmor : displayColorHit)
}
.font(.system(size: size))
.padding(4)
.frame(maxWidth: .infinity)
.gesture(TapGesture().onEnded {
if current.state == .hit {
if whichDie.rawValue != 1 {
current.hitCutoff = whichDie
}
} else if current.state == .armour {
current.armourSave = Int(whichDie.rawValue)
}
})
}
}
#Preview {
DieView(whichDie: .four)
.environmentObject(Roll())
}
@@ -16,9 +16,9 @@ struct HitCalculatorView: View {
HStack(alignment: .top) { HStack(alignment: .top) {
Spacer() Spacer()
StatStepper( StatStepper(
top: "Hit", top: "Hit Modifier",
value: (current.modifier.rawValue > 0 ? "+" : "") + String(current.modifier.rawValue), value: (current.modifier.rawValue > 0 ? "+" : "") + String(current.modifier.rawValue),
bottom: "Modifier", bottom: "",
increment: { current.modifier = current.modifier.add() }, increment: { current.modifier = current.modifier.add() },
decrement: { current.modifier = current.modifier.remove() } decrement: { current.modifier = current.modifier.remove() }
) )
+6 -6
View File
@@ -9,29 +9,29 @@ struct InfoAreaView: View {
@EnvironmentObject var current: Roll @EnvironmentObject var current: Roll
var body: some View { var body: some View {
VStack(alignment: .leading, spacing: 6) { HStack() {
switch current.state { switch current.state {
case .hit: case .hit:
if current.lethalHits || current.sustainedHits { if current.lethalHits || current.sustainedHits {
Text("Crits (6s): \(current.critHitCount)") Text("Crits (6s): \(current.critHitCount)")
.fontWeight(.semibold) .fontWeight(.semibold)
.foregroundColor(.orange) .foregroundColor(.red)
} }
if current.antiX { if current.antiX {
Text("Anti-X (\(current.antiXThreshold)+): \(current.antiXCount)") Text("Anti-X (\(current.antiXThreshold)+): \(current.antiXCount)")
.fontWeight(.semibold) .fontWeight(.semibold)
.foregroundColor(.orange) .foregroundColor(.red)
} }
case .wound: case .wound:
if current.autoWoundsCarried > 0 { if current.autoWoundsCarried > 0 {
Text("Auto-wounds carried: \(current.autoWoundsCarried) (skip wound roll)") Text("Auto-wounds carried: \(current.autoWoundsCarried) (skip wound roll)")
.fontWeight(.semibold) .fontWeight(.semibold)
.foregroundColor(.orange) .foregroundColor(.red)
} }
if current.devastatingWounds { if current.devastatingWounds {
Text("Mortals (6s): \(current.critWoundCount)") Text("Mortal wounds: \(current.critWoundCount)")
.fontWeight(.semibold) .fontWeight(.semibold)
.foregroundColor(.orange) .foregroundColor(.red)
} }
case .armour: case .armour:
EmptyView() EmptyView()
@@ -8,6 +8,9 @@ import SwiftUI
struct RollSummaryView: View { struct RollSummaryView: View {
@EnvironmentObject var current: Roll @EnvironmentObject var current: Roll
@State private var showFillView = false @State private var showFillView = false
@Environment(\.dieColorSelected) var colorSelected
@Environment(\.dieColorPrimary) var colorPrimary
var body: some View { var body: some View {
VStack{ VStack{
@@ -24,7 +27,7 @@ struct RollSummaryView: View {
.padding(.vertical, 12) .padding(.vertical, 12)
.clipShape(Circle()) .clipShape(Circle())
.foregroundColor(.black) .foregroundColor(.black)
.glassEffect(.clear.tint(Color.blue.opacity(0.7))) .glassEffect(.clear.tint(colorPrimary))
} }
} }
.sheet(isPresented: $showFillView, .sheet(isPresented: $showFillView,
@@ -51,7 +54,7 @@ struct RollSummaryView: View {
.padding(.vertical, 12) .padding(.vertical, 12)
.clipShape(Circle()) .clipShape(Circle())
.foregroundColor(.black) .foregroundColor(.black)
.glassEffect(.clear.tint(Color.red.opacity(0.7))) .glassEffect(.clear.tint(colorSelected))
} }
} }
@@ -16,22 +16,19 @@ struct StatePickerView: View {
if current.state == .hit { circle() } if current.state == .hit { circle() }
Text(RollState.hit.print()) Text(RollState.hit.print())
} }
} }.padding(10)
.glassEffect()
Button(action: { current.state = .wound }) { Button(action: { current.state = .wound }) {
ZStack { ZStack {
if current.state == .wound { circle() } if current.state == .wound { circle() }
Text(RollState.wound.print()) Text(RollState.wound.print())
} }
} }.padding(10)
.glassEffect()
Button(action: { current.state = .armour }) { Button(action: { current.state = .armour }) {
ZStack { ZStack {
if current.state == .armour { circle() } if current.state == .armour { circle() }
Text(RollState.armour.print()) Text(RollState.armour.print())
} }
} }.padding(10)
.glassEffect()
} }
.font(.system(size: 60)) .font(.system(size: 60))
} }
+2 -3
View File
@@ -29,9 +29,8 @@ struct MainView: View {
var body: some View { var body: some View {
VStack { VStack {
StatePickerView() StatePickerView()
VStack(spacing: 12) { VStack(spacing: 8) {
RollSummaryView() RollSummaryView()
// DiePoolView()
switch current.state { switch current.state {
case .wound: WoundCalculatorView() case .wound: WoundCalculatorView()
case .armour: ArmourCalculatorView() case .armour: ArmourCalculatorView()
@@ -39,7 +38,7 @@ struct MainView: View {
} }
InfoAreaView() InfoAreaView()
Spacer() Spacer()
}.padding() }
} }
.toolbar { .toolbar {
ToolbarItemGroup(placement: .bottomBar) { ToolbarItemGroup(placement: .bottomBar) {