diff --git a/iOS/MonsterCards/Helpers/StringHelper.swift b/iOS/MonsterCards/Helpers/StringHelper.swift
index b395ce7..927c8dd 100644
--- a/iOS/MonsterCards/Helpers/StringHelper.swift
+++ b/iOS/MonsterCards/Helpers/StringHelper.swift
@@ -45,4 +45,12 @@ class StringHelper {
return str!.containsCaseInsensitive(match)
}
+
+ static func safeEqualsIgnoreCase(_ str: String?, _ match: String) -> Bool {
+ if (str == nil) {
+ return false
+ }
+
+ return str!.lowercased() == match.lowercased()
+ }
}
diff --git a/iOS/MonsterCards/Models/Monster+CoreDataClass.swift b/iOS/MonsterCards/Models/Monster+CoreDataClass.swift
index 295d127..c485a98 100644
--- a/iOS/MonsterCards/Models/Monster+CoreDataClass.swift
+++ b/iOS/MonsterCards/Models/Monster+CoreDataClass.swift
@@ -625,7 +625,7 @@ public class Monster: NSManagedObject {
}
}
- // MARK: OTHER
+ // MARK: Immunities, Resistances, and Vulnerabilities
var damageVulnerabilitiesDescription: String {
get {
@@ -656,6 +656,40 @@ public class Monster: NSManagedObject {
}
}
+ // MARK: OTHER
+
+ var passivePerception: Int {
+ get {
+ let perceptionSkill = skillsArray.first(where: {
+ StringHelper.safeEqualsIgnoreCase($0.name, "Perception")
+ })
+ if (perceptionSkill == nil) {
+ return wisdomModifier
+ } else if (perceptionSkill?.wrappedProficiency == ProficiencyType.expertise) {
+ return wisdomModifier + proficiencyBonus + proficiencyBonus
+ } else if (perceptionSkill?.wrappedProficiency == ProficiencyType.proficient) {
+ return wisdomModifier + proficiencyBonus
+ } else {
+ return wisdomModifier
+ }
+ }
+ }
+
+ var sensesDescription: String {
+ get {
+ var modifiedSenses = self.senses?.sorted() ?? []
+ let hasPassivePerceptionSense = modifiedSenses.contains(where: {
+ $0.starts(with: "passive Perception")
+ })
+ if (!hasPassivePerceptionSense) {
+ let calculatedPassivePerception = String(format: "passive Perception %+d", passivePerception)
+ modifiedSenses.append(calculatedPassivePerception)
+ }
+
+ return modifiedSenses.sorted().joined(separator: ", ")
+ }
+ }
+
var languagesArray: [String] {
get {
return ["Common", "Goblin"]
diff --git a/iOS/MonsterCards/Models/MonsterViewModel.swift b/iOS/MonsterCards/Models/MonsterViewModel.swift
index 1d65613..ab893d6 100644
--- a/iOS/MonsterCards/Models/MonsterViewModel.swift
+++ b/iOS/MonsterCards/Models/MonsterViewModel.swift
@@ -53,6 +53,7 @@ class MonsterViewModel: ObservableObject {
@Published var damageResistances: [StringViewModel]
@Published var damageVulnerabilities: [StringViewModel]
@Published var conditionImmunities: [StringViewModel]
+ @Published var senses: [StringViewModel]
init(_ rawMonster: Monster? = nil) {
self.name = ""
@@ -98,6 +99,7 @@ class MonsterViewModel: ObservableObject {
self.damageResistances = []
self.damageVulnerabilities = []
self.conditionImmunities = []
+ self.senses = []
if (rawMonster != nil) {
self.copyFromMonster(monster: rawMonster!)
@@ -160,6 +162,10 @@ class MonsterViewModel: ObservableObject {
self.conditionImmunities = (monster.conditionImmunities ?? [])
.map {StringViewModel($0)}
.sorted()
+
+ self.senses = (monster.senses ?? [])
+ .map {StringViewModel($0)}
+ .sorted()
}
func copyToMonster(monster: Monster) {
@@ -226,5 +232,6 @@ class MonsterViewModel: ObservableObject {
monster.damageImmunities = damageImmunities.map {$0.name}
monster.damageResistances = damageResistances.map {$0.name}
monster.damageVulnerabilities = damageVulnerabilities.map {$0.name}
+ monster.senses = senses.map {$0.name}
}
}
diff --git a/iOS/MonsterCards/Models/Skill+CoreDataClass.swift b/iOS/MonsterCards/Models/Skill+CoreDataClass.swift
index 4ad1772..da583db 100644
--- a/iOS/MonsterCards/Models/Skill+CoreDataClass.swift
+++ b/iOS/MonsterCards/Models/Skill+CoreDataClass.swift
@@ -48,17 +48,17 @@ public class Skill: NSManagedObject {
}
}
- var modifier: Int64 {
+ var modifier: Int {
get {
let proficiencyBonus = Double(monster?.proficiencyBonus ?? 0)
let abilityScoreModifier = Double(monster?.abilityModifierForAbilityScore(wrappedAbilityScore) ?? 0)
switch wrappedProficiency {
case .none:
- return Int64(abilityScoreModifier)
+ return Int(abilityScoreModifier)
case .proficient:
- return Int64(abilityScoreModifier + proficiencyBonus)
+ return Int(abilityScoreModifier + proficiencyBonus)
case .expertise:
- return Int64(abilityScoreModifier + 2 * proficiencyBonus)
+ return Int(abilityScoreModifier + 2 * proficiencyBonus)
}
}
}
diff --git a/iOS/MonsterCards/MonsterCards.xcdatamodeld/MonsterCards.xcdatamodel/contents b/iOS/MonsterCards/MonsterCards.xcdatamodeld/MonsterCards.xcdatamodel/contents
index 528df97..43c88b7 100644
--- a/iOS/MonsterCards/MonsterCards.xcdatamodeld/MonsterCards.xcdatamodel/contents
+++ b/iOS/MonsterCards/MonsterCards.xcdatamodeld/MonsterCards.xcdatamodel/contents
@@ -39,6 +39,7 @@
+
@@ -63,7 +64,7 @@
-
+
\ No newline at end of file
diff --git a/iOS/MonsterCards/Views/EditMonster.swift b/iOS/MonsterCards/Views/EditMonster.swift
index ea62540..3eb7ac4 100644
--- a/iOS/MonsterCards/Views/EditMonster.swift
+++ b/iOS/MonsterCards/Views/EditMonster.swift
@@ -20,45 +20,53 @@ struct EditMonster: View {
var body: some View {
List {
- NavigationLink(
- "Basic Info",
- destination: EditBasicInfo(monsterViewModel: monsterViewModel))
+ Group {
+ NavigationLink(
+ "Basic Info",
+ destination: EditBasicInfo(monsterViewModel: monsterViewModel))
+
+ NavigationLink(
+ "Armor",
+ destination: EditArmor(monsterViewModel: monsterViewModel))
+
+ NavigationLink(
+ "Speed",
+ destination: EditSpeed(monsterViewModel: monsterViewModel))
+
+ NavigationLink(
+ "Ability Scores",
+ destination: EditAbilityScores(monsterViewModel: monsterViewModel))
+
+ NavigationLink(
+ "Saving Throws",
+ destination: EditSavingThrows(monsterViewModel: monsterViewModel))
+
+ NavigationLink(
+ "Skills",
+ destination: EditSkills(monsterViewModel: monsterViewModel))
+
+ NavigationLink(
+ "Condition Immunities",
+ destination: EditStrings(viewModel: monsterViewModel, path: \.conditionImmunities, title: "Condition Immunities"))
+
+ NavigationLink(
+ "Damage Immunities",
+ destination: EditStrings(viewModel: monsterViewModel, path: \.damageImmunities, title: "Damage Immunities"))
+
+ NavigationLink(
+ "Damage Resistances",
+ destination: EditStrings(viewModel: monsterViewModel, path: \.damageResistances, title: "Damage Resistances"))
+
+ NavigationLink(
+ "Damage Vulnerabilities",
+ destination: EditStrings(viewModel: monsterViewModel, path: \.damageVulnerabilities, title: "Damage Vulnerabilities"))
+ }
+ Group {
+ NavigationLink(
+ "Senses",
+ destination: EditStrings(viewModel: monsterViewModel, path: \.senses, title: "Senses"))
+ }
- NavigationLink(
- "Armor",
- destination: EditArmor(monsterViewModel: monsterViewModel))
-
- NavigationLink(
- "Speed",
- destination: EditSpeed(monsterViewModel: monsterViewModel))
-
- NavigationLink(
- "Ability Scores",
- destination: EditAbilityScores(monsterViewModel: monsterViewModel))
-
- NavigationLink(
- "Saving Throws",
- destination: EditSavingThrows(monsterViewModel: monsterViewModel))
-
- NavigationLink(
- "Skills",
- destination: EditSkills(monsterViewModel: monsterViewModel))
-
- NavigationLink(
- "Condition Immunities",
- destination: EditStrings(viewModel: monsterViewModel, path: \.conditionImmunities, title: "Condition Immunities"))
-
- NavigationLink(
- "Damage Immunities",
- destination: EditStrings(viewModel: monsterViewModel, path: \.damageImmunities, title: "Damage Immunities"))
-
- NavigationLink(
- "Damage Resistances",
- destination: EditStrings(viewModel: monsterViewModel, path: \.damageResistances, title: "Damage Resistances"))
-
- NavigationLink(
- "Damage Vulnerabilities",
- destination: EditStrings(viewModel: monsterViewModel, path: \.damageVulnerabilities, title: "Damage Vulnerabilities"))
}
.onAppear(perform: copyMonsterToLocal)
.toolbar(content: {
diff --git a/iOS/MonsterCards/Views/MonsterDetail.swift b/iOS/MonsterCards/Views/MonsterDetail.swift
index b2786b7..0b0c921 100644
--- a/iOS/MonsterCards/Views/MonsterDetail.swift
+++ b/iOS/MonsterCards/Views/MonsterDetail.swift
@@ -137,6 +137,7 @@ struct ResistancesAndImmunitiesView: View {
let monsterDamageResistancesDescription = monster.damageResistancesDescription
let monsterDamageImmunitiesDescription = monster.damageImmunitiesDescription
let monsterConditionImmunitiesDescription = monster.conditionImmunitiesDescription
+ let monsterSensesDescription = monster.sensesDescription
// Damage Vulnerabilities
if (!monsterDamageVulnerabilitiesDescription.isEmpty) {
@@ -165,6 +166,13 @@ struct ResistancesAndImmunitiesView: View {
Text(monsterConditionImmunitiesDescription)
}
}
+
+ // Senses
+ if (!monsterSensesDescription.isEmpty) {
+ LabeledField("Senses") {
+ Text(monsterSensesDescription)
+ }
+ }
}
}