Adds lair actions, regional actions, and reactions to the data model. Renames baseSpeed to walkSpeed.

This commit is contained in:
2021-04-04 03:27:00 -07:00
parent c55b6e8f0d
commit 885b0e08f7
7 changed files with 58 additions and 16 deletions

View File

@@ -100,8 +100,8 @@ public class Monster: NSManagedObject {
} else { } else {
var parts: [String] = [] var parts: [String] = []
if (baseSpeed > 0) { if (walkSpeed > 0) {
parts.append("\(baseSpeed) ft.") parts.append("\(walkSpeed) ft.")
} }
if (burrowSpeed > 0) { if (burrowSpeed > 0) {
parts.append("burrow \(burrowSpeed) ft.") parts.append("burrow \(burrowSpeed) ft.")

View File

@@ -24,7 +24,7 @@ class MonsterViewModel: ObservableObject {
} }
@Published var naturalArmorBonus: Int64 @Published var naturalArmorBonus: Int64
@Published var customArmor: String @Published var customArmor: String
@Published var baseSpeed: Int64 @Published var walkSpeed: Int64
@Published var burrowSpeed: Int64 @Published var burrowSpeed: Int64
@Published var climbSpeed: Int64 @Published var climbSpeed: Int64
@Published var flySpeed: Int64 @Published var flySpeed: Int64
@@ -65,6 +65,10 @@ class MonsterViewModel: ObservableObject {
@Published var abilities: [AbilityViewModel] @Published var abilities: [AbilityViewModel]
@Published var actions: [AbilityViewModel] @Published var actions: [AbilityViewModel]
@Published var legendaryActions: [AbilityViewModel] @Published var legendaryActions: [AbilityViewModel]
@Published var lairActions: [AbilityViewModel]
@Published var regionalActions: [AbilityViewModel]
@Published var reactions: [AbilityViewModel]
@Published var isBlind: Bool
private var shieldBonus: Int private var shieldBonus: Int
private var otherArmorDescription: String private var otherArmorDescription: String
@@ -97,7 +101,7 @@ class MonsterViewModel: ObservableObject {
self.hasShield = false self.hasShield = false
self.naturalArmorBonus = 0 self.naturalArmorBonus = 0
self.customArmor = "" self.customArmor = ""
self.baseSpeed = 0 self.walkSpeed = 0
self.burrowSpeed = 0 self.burrowSpeed = 0
self.climbSpeed = 0 self.climbSpeed = 0
self.flySpeed = 0 self.flySpeed = 0
@@ -138,6 +142,10 @@ class MonsterViewModel: ObservableObject {
self.abilities = [] self.abilities = []
self.actions = [] self.actions = []
self.legendaryActions = [] self.legendaryActions = []
self.lairActions = []
self.regionalActions = []
self.reactions = []
self.isBlind = false
// Private properties // Private properties
self.shieldBonus = 0 self.shieldBonus = 0
@@ -162,7 +170,7 @@ class MonsterViewModel: ObservableObject {
self.hasShield = monster.hasShield self.hasShield = monster.hasShield
self.naturalArmorBonus = monster.naturalArmorBonus self.naturalArmorBonus = monster.naturalArmorBonus
self.customArmor = monster.customArmor ?? "" self.customArmor = monster.customArmor ?? ""
self.baseSpeed = monster.baseSpeed self.walkSpeed = monster.walkSpeed
self.burrowSpeed = monster.burrowSpeed self.burrowSpeed = monster.burrowSpeed
self.climbSpeed = monster.climbSpeed self.climbSpeed = monster.climbSpeed
self.flySpeed = monster.flySpeed self.flySpeed = monster.flySpeed
@@ -193,6 +201,7 @@ class MonsterViewModel: ObservableObject {
self.challengeRating = monster.challengeRatingEnum self.challengeRating = monster.challengeRatingEnum
self.customChallengeRating = monster.customChallengeRating ?? "" self.customChallengeRating = monster.customChallengeRating ?? ""
self.customProficiencyBonus = monster.customProficiencyBonus self.customProficiencyBonus = monster.customProficiencyBonus
self.isBlind = monster.isBlind
self.skills = (monster.skills?.allObjects.map {SkillViewModel(($0 as! Skill))})!.sorted() self.skills = (monster.skills?.allObjects.map {SkillViewModel(($0 as! Skill))})!.sorted()
@@ -230,6 +239,15 @@ class MonsterViewModel: ObservableObject {
self.legendaryActions = (monster.legendaryActions ?? []) self.legendaryActions = (monster.legendaryActions ?? [])
.map {AbilityViewModel($0.name, $0.abilityDescription)} .map {AbilityViewModel($0.name, $0.abilityDescription)}
self.lairActions = (monster.lairActions ?? [])
.map {AbilityViewModel($0.name, $0.abilityDescription)}
self.regionalActions = (monster.regionalActions ?? [])
.map {AbilityViewModel($0.name, $0.abilityDescription)}
self.reactions = (monster.reactions ?? [])
.map {AbilityViewModel($0.name, $0.abilityDescription)}
// Private fields // Private fields
self.shieldBonus = Int(monster.shieldBonus) self.shieldBonus = Int(monster.shieldBonus)
@@ -249,7 +267,7 @@ class MonsterViewModel: ObservableObject {
monster.hasShield = hasShield monster.hasShield = hasShield
monster.naturalArmorBonus = naturalArmorBonus monster.naturalArmorBonus = naturalArmorBonus
monster.customArmor = customArmor monster.customArmor = customArmor
monster.baseSpeed = baseSpeed monster.walkSpeed = walkSpeed
monster.burrowSpeed = burrowSpeed monster.burrowSpeed = burrowSpeed
monster.climbSpeed = climbSpeed monster.climbSpeed = climbSpeed
monster.flySpeed = flySpeed monster.flySpeed = flySpeed
@@ -280,6 +298,7 @@ class MonsterViewModel: ObservableObject {
monster.challengeRatingEnum = challengeRating monster.challengeRatingEnum = challengeRating
monster.customChallengeRating = customChallengeRating monster.customChallengeRating = customChallengeRating
monster.customProficiencyBonus = customProficiencyBonus monster.customProficiencyBonus = customProficiencyBonus
monster.isBlind = isBlind
// Remove missing skills from raw monster // Remove missing skills from raw monster
monster.skills?.forEach {s in monster.skills?.forEach {s in
@@ -316,6 +335,12 @@ class MonsterViewModel: ObservableObject {
monster.legendaryActions = legendaryActions.map {AbilityViewModel($0.name, $0.abilityDescription)} monster.legendaryActions = legendaryActions.map {AbilityViewModel($0.name, $0.abilityDescription)}
monster.lairActions = lairActions.map {AbilityViewModel($0.name, $0.abilityDescription)}
monster.regionalActions = regionalActions.map {AbilityViewModel($0.name, $0.abilityDescription)}
monster.reactions = reactions.map {AbilityViewModel($0.name, $0.abilityDescription)}
monster.shieldBonus = Int64(shieldBonus) monster.shieldBonus = Int64(shieldBonus)
monster.otherArmorDescription = otherArmorDescription monster.otherArmorDescription = otherArmorDescription
} }
@@ -382,8 +407,8 @@ class MonsterViewModel: ObservableObject {
} else { } else {
var parts: [String] = [] var parts: [String] = []
if (baseSpeed > 0) { if (walkSpeed > 0) {
parts.append("\(baseSpeed) ft.") parts.append("\(walkSpeed) ft.")
} }
if (burrowSpeed > 0) { if (burrowSpeed > 0) {
parts.append("burrow \(burrowSpeed) ft.") parts.append("burrow \(burrowSpeed) ft.")
@@ -467,7 +492,6 @@ class MonsterViewModel: ObservableObject {
var armorClassDescription: String { var armorClassDescription: String {
get { get {
let hasShield = shieldBonus != 0
var armorClassTotal = 0 var armorClassTotal = 0
if (armorType == ArmorType.none) { if (armorType == ArmorType.none) {
// 10 + dexMod + 2 for shieldBonus "15" or "17 (shield)" // 10 + dexMod + 2 for shieldBonus "15" or "17 (shield)"

View File

@@ -65,6 +65,13 @@ class SkillViewModel: ObservableObject, Comparable, Hashable, Identifiable {
} }
} }
init(_ name: String, _ abilityScore: AbilityScore, _ proficiency: ProficiencyType = .proficient, _ advantage: AdvantageType = .none) {
_name = name
_abilityScore = abilityScore
_proficiency = proficiency
_advantage = advantage
}
private var _name: String = "" private var _name: String = ""
var name: String { var name: String {
get { get {

View File

@@ -5,7 +5,6 @@
<attribute name="actions" optional="YES" attributeType="Transformable" valueTransformerName="AbilityViewModelValueTransformer" customClassName="[AbilityViewModel]"/> <attribute name="actions" optional="YES" attributeType="Transformable" valueTransformerName="AbilityViewModelValueTransformer" customClassName="[AbilityViewModel]"/>
<attribute name="alignment" attributeType="String" defaultValueString=""/> <attribute name="alignment" attributeType="String" defaultValueString=""/>
<attribute name="armorType" attributeType="String" defaultValueString=""/> <attribute name="armorType" attributeType="String" defaultValueString=""/>
<attribute name="baseSpeed" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="blindsightDistance" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/> <attribute name="blindsightDistance" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="burrowSpeed" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/> <attribute name="burrowSpeed" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="canHover" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> <attribute name="canHover" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
@@ -39,11 +38,14 @@
<attribute name="intelligenceSavingThrowProficiency" attributeType="String" defaultValueString="none"/> <attribute name="intelligenceSavingThrowProficiency" attributeType="String" defaultValueString="none"/>
<attribute name="intelligenceScore" attributeType="Integer 64" defaultValueString="10" usesScalarValueType="YES"/> <attribute name="intelligenceScore" attributeType="Integer 64" defaultValueString="10" usesScalarValueType="YES"/>
<attribute name="isBlind" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> <attribute name="isBlind" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="lairActions" optional="YES" attributeType="Transformable" valueTransformerName="AbilityViewModelValueTransformer" customClassName="[AbilityViewModel]"/>
<attribute name="languages" optional="YES" attributeType="Transformable" valueTransformerName="LanguageViewModelValueTransformer" customClassName="[LanguageViewModel]"/> <attribute name="languages" optional="YES" attributeType="Transformable" valueTransformerName="LanguageViewModelValueTransformer" customClassName="[LanguageViewModel]"/>
<attribute name="legendaryActions" optional="YES" attributeType="Transformable" valueTransformerName="AbilityViewModelValueTransformer" customClassName="[AbilityViewModel]"/> <attribute name="legendaryActions" optional="YES" attributeType="Transformable" valueTransformerName="AbilityViewModelValueTransformer" customClassName="[AbilityViewModel]"/>
<attribute name="name" attributeType="String" defaultValueString="Unnamed Monster"/> <attribute name="name" attributeType="String" defaultValueString="Unnamed Monster"/>
<attribute name="naturalArmorBonus" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/> <attribute name="naturalArmorBonus" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="otherArmorDescription" attributeType="String" defaultValueString=""/> <attribute name="otherArmorDescription" attributeType="String" defaultValueString=""/>
<attribute name="reactions" optional="YES" attributeType="Transformable" valueTransformerName="AbilityViewModelValueTransformer" customClassName="[AbilityViewModel]"/>
<attribute name="regionalActions" optional="YES" attributeType="Transformable" valueTransformerName="AbilityViewModelValueTransformer" customClassName="[AbilityViewModel]"/>
<attribute name="senses" optional="YES" attributeType="Transformable" valueTransformerName="NSSecureUnarchiveFromDataTransformerName" customClassName="[String]"/> <attribute name="senses" optional="YES" attributeType="Transformable" valueTransformerName="NSSecureUnarchiveFromDataTransformerName" customClassName="[String]"/>
<attribute name="shieldBonus" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/> <attribute name="shieldBonus" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="size" attributeType="String" defaultValueString=""/> <attribute name="size" attributeType="String" defaultValueString=""/>
@@ -57,6 +59,7 @@
<attribute name="truesightDistance" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/> <attribute name="truesightDistance" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="type" attributeType="String" defaultValueString=""/> <attribute name="type" attributeType="String" defaultValueString=""/>
<attribute name="understandsBut" attributeType="String" defaultValueString=""/> <attribute name="understandsBut" attributeType="String" defaultValueString=""/>
<attribute name="walkSpeed" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="wisdomSavingThrowAdvantage" attributeType="String" defaultValueString="none"/> <attribute name="wisdomSavingThrowAdvantage" attributeType="String" defaultValueString="none"/>
<attribute name="wisdomSavingThrowProficiency" attributeType="String" defaultValueString="none"/> <attribute name="wisdomSavingThrowProficiency" attributeType="String" defaultValueString="none"/>
<attribute name="wisdomScore" attributeType="Integer 64" defaultValueString="10" usesScalarValueType="YES"/> <attribute name="wisdomScore" attributeType="Integer 64" defaultValueString="10" usesScalarValueType="YES"/>
@@ -70,7 +73,7 @@
<relationship name="monster" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Monster" inverseName="skills" inverseEntity="Monster"/> <relationship name="monster" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Monster" inverseName="skills" inverseEntity="Monster"/>
</entity> </entity>
<elements> <elements>
<element name="Monster" positionX="-63" positionY="-18" width="128" height="929"/> <element name="Monster" positionX="-63" positionY="-18" width="128" height="974"/>
<element name="Skill" positionX="-63" positionY="135" width="128" height="14"/> <element name="Skill" positionX="-63" positionY="135" width="128" height="14"/>
</elements> </elements>
</model> </model>

View File

@@ -9,7 +9,11 @@ import CoreData
import SwiftUI import SwiftUI
struct EditMonster: View { struct EditMonster: View {
// TODO: add challengeRating/challengeRatingEnum and customChallengeRating maybe in basicInfo // TODO: Add challengeRating/challengeRatingEnum and customChallengeRating maybe in basicInfo
// TODO: Add a way to edit the monster being blind. Probably a header section to the senses section.
// TODO: Add a way to edit lair actions
// TODO: Add a way to edit regional actions
// TODO: Add a way to edit reactions
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode> @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@Environment(\.managedObjectContext) private var viewContext @Environment(\.managedObjectContext) private var viewContext
@@ -141,7 +145,7 @@ struct EditMonster_Previews: PreviewProvider {
monster.hitDice = 6 monster.hitDice = 6
monster.hasCustomHP = true monster.hasCustomHP = true
monster.customHP = "12 (1d10)+2" monster.customHP = "12 (1d10)+2"
monster.baseSpeed = 5 monster.walkSpeed = 5
monster.burrowSpeed = 10 monster.burrowSpeed = 10
monster.climbSpeed = 15 monster.climbSpeed = 15
monster.flySpeed = 20 monster.flySpeed = 20

View File

@@ -12,12 +12,12 @@ struct EditSpeed: View {
var body: some View { var body: some View {
List { List {
// Number bound to monster.baseSpeed // Number bound to monster.walkSpeed
MCStepperField( MCStepperField(
label: "Base", label: "Base",
step: 5, step: 5,
suffix: " ft.", suffix: " ft.",
value: $monsterViewModel.baseSpeed) value: $monsterViewModel.walkSpeed)
// Number bound to monster.burrowSpeed // Number bound to monster.burrowSpeed
MCStepperField( MCStepperField(

View File

@@ -293,6 +293,10 @@ struct MonsterDetailView: View {
} }
struct MonsterDetailWrapper: View { struct MonsterDetailWrapper: View {
// TODO: Add display for when the monster is blind
// TODO: Add display for lair actions
// TODO: Add display for regional actions
// TODO: Add display for reactions
let kTextColor: Color = Color(hex: 0x982818) let kTextColor: Color = Color(hex: 0x982818)
@ObservedObject var monster: Monster @ObservedObject var monster: Monster
@@ -330,7 +334,7 @@ struct MonsterDetailWrapper_Previews: PreviewProvider {
monster.hitDice = 6 monster.hitDice = 6
monster.hasCustomHP = true monster.hasCustomHP = true
monster.customHP = "12 (1d10)+2" monster.customHP = "12 (1d10)+2"
monster.baseSpeed = 5 monster.walkSpeed = 5
monster.burrowSpeed = 10 monster.burrowSpeed = 10
monster.climbSpeed = 15 monster.climbSpeed = 15
monster.flySpeed = 20 monster.flySpeed = 20