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 {
var parts: [String] = []
if (baseSpeed > 0) {
parts.append("\(baseSpeed) ft.")
if (walkSpeed > 0) {
parts.append("\(walkSpeed) ft.")
}
if (burrowSpeed > 0) {
parts.append("burrow \(burrowSpeed) ft.")

View File

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

View File

@@ -5,7 +5,6 @@
<attribute name="actions" optional="YES" attributeType="Transformable" valueTransformerName="AbilityViewModelValueTransformer" customClassName="[AbilityViewModel]"/>
<attribute name="alignment" 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="burrowSpeed" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="canHover" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
@@ -39,11 +38,14 @@
<attribute name="intelligenceSavingThrowProficiency" attributeType="String" defaultValueString="none"/>
<attribute name="intelligenceScore" attributeType="Integer 64" defaultValueString="10" 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="legendaryActions" optional="YES" attributeType="Transformable" valueTransformerName="AbilityViewModelValueTransformer" customClassName="[AbilityViewModel]"/>
<attribute name="name" attributeType="String" defaultValueString="Unnamed Monster"/>
<attribute name="naturalArmorBonus" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<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="shieldBonus" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="size" attributeType="String" defaultValueString=""/>
@@ -57,6 +59,7 @@
<attribute name="truesightDistance" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="type" 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="wisdomSavingThrowProficiency" attributeType="String" defaultValueString="none"/>
<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"/>
</entity>
<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"/>
</elements>
</model>

View File

@@ -9,7 +9,11 @@ import CoreData
import SwiftUI
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(\.managedObjectContext) private var viewContext
@@ -141,7 +145,7 @@ struct EditMonster_Previews: PreviewProvider {
monster.hitDice = 6
monster.hasCustomHP = true
monster.customHP = "12 (1d10)+2"
monster.baseSpeed = 5
monster.walkSpeed = 5
monster.burrowSpeed = 10
monster.climbSpeed = 15
monster.flySpeed = 20

View File

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

View File

@@ -293,6 +293,10 @@ struct MonsterDetailView: 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)
@ObservedObject var monster: Monster
@@ -330,7 +334,7 @@ struct MonsterDetailWrapper_Previews: PreviewProvider {
monster.hitDice = 6
monster.hasCustomHP = true
monster.customHP = "12 (1d10)+2"
monster.baseSpeed = 5
monster.walkSpeed = 5
monster.burrowSpeed = 10
monster.climbSpeed = 15
monster.flySpeed = 20