diff --git a/.gitignore b/.gitignore
index 87de309..a840822 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
+/.idea/dictionaries
.DS_Store
/build
/captures
diff --git a/.idea/saveactions_settings.xml b/.idea/saveactions_settings.xml
new file mode 100644
index 0000000..57dd97c
--- /dev/null
+++ b/.idea/saveactions_settings.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 5ee600d..8d8816b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -87,4 +87,5 @@ dependencies {
// optional - Test helpers
//testImplementation "androidx.room:room-testing:$room_version"
+ implementation 'com.google.code.gson:gson:2.8.6'
}
\ No newline at end of file
diff --git a/app/schemas/com.majinnaibu.monstercards.AppDatabase/1.json b/app/schemas/com.majinnaibu.monstercards.AppDatabase/1.json
index f92e587..83ab2bc 100644
--- a/app/schemas/com.majinnaibu.monstercards.AppDatabase/1.json
+++ b/app/schemas/com.majinnaibu.monstercards.AppDatabase/1.json
@@ -2,11 +2,11 @@
"formatVersion": 1,
"database": {
"version": 1,
- "identityHash": "a9371223372fb64522cc40f5529ada09",
+ "identityHash": "db1293d2f490940b55ca1f4f56b21b1a",
"entities": [
{
"tableName": "Monster",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL DEFAULT '', PRIMARY KEY(`id`))",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL DEFAULT '', `size` TEXT NOT NULL DEFAULT '', `type` TEXT NOT NULL DEFAULT '', `subtype` TEXT NOT NULL DEFAULT '', `alignment` TEXT NOT NULL DEFAULT '', `strength_score` INTEGER NOT NULL DEFAULT 10, `strength_saving_throw_advantage` TEXT DEFAULT 'none', `strength_saving_throw_proficiency` TEXT DEFAULT 'none', `dexterity_score` INTEGER NOT NULL DEFAULT 10, `dexterity_saving_throw_advantage` TEXT DEFAULT 'none', `dexterity_saving_throw_proficiency` TEXT DEFAULT 'none', `constitution_score` INTEGER NOT NULL DEFAULT 10, `constitution_saving_throw_advantage` TEXT DEFAULT 'none', `constitution_saving_throw_proficiency` TEXT DEFAULT 'none', `intelligence_score` INTEGER NOT NULL DEFAULT 10, `intelligence_saving_throw_advantage` TEXT DEFAULT 'none', `intelligence_saving_throw_proficiency` TEXT DEFAULT 'none', `wisdom_score` INTEGER NOT NULL DEFAULT 10, `wisdom_saving_throw_advantage` TEXT DEFAULT 'none', `wisdom_saving_throw_proficiency` TEXT DEFAULT 'none', `charisma_score` INTEGER NOT NULL DEFAULT 10, `charisma_saving_throw_advantage` TEXT DEFAULT 'none', `charisma_saving_throw_proficiency` TEXT DEFAULT 'none', `armor_type` TEXT DEFAULT 'none', `shield_bonus` INTEGER NOT NULL DEFAULT 0, `natural_armor_bonus` INTEGER NOT NULL DEFAULT 0, `other_armor_description` TEXT DEFAULT '', `hit_dice` INTEGER NOT NULL DEFAULT 1, `has_custom_hit_points` INTEGER NOT NULL, `custom_hit_points_description` TEXT DEFAULT '', `walk_speed` INTEGER NOT NULL DEFAULT 0, `burrow_speed` INTEGER NOT NULL DEFAULT 0, `climb_speed` INTEGER NOT NULL DEFAULT 0, `fly_speed` INTEGER NOT NULL DEFAULT 0, `can_hover` INTEGER NOT NULL DEFAULT false, `swim_speed` INTEGER NOT NULL DEFAULT 0, `has_custom_speed` INTEGER NOT NULL DEFAULT false, `custom_speed_description` TEXT, `challenge_rating` TEXT DEFAULT '1', `custom_challenge_rating_description` TEXT DEFAULT '', `custom_proficiency_bonus` INTEGER NOT NULL DEFAULT 0, `blindsight_range` INTEGER NOT NULL DEFAULT 0, `is_blind_beyond_blindsight_range` INTEGER NOT NULL DEFAULT false, `darkvision_range` INTEGER NOT NULL DEFAULT 0, `tremorsense_range` INTEGER NOT NULL DEFAULT 0, `truesight_range` INTEGER NOT NULL DEFAULT 0, `telepathy_range` INTEGER NOT NULL DEFAULT 0, `understands_but_description` TEXT DEFAULT '', `skills` TEXT, `damage_immunities` TEXT, `damage_resistances` TEXT, `damage_vulnerabilities` TEXT, `condition_immunities` TEXT, `languages` TEXT, `abilities` TEXT, `actions` TEXT, `reactions` TEXT, `lair_actions` TEXT, `legendary_actions` TEXT, `regional_actions` TEXT, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
@@ -20,6 +20,405 @@
"affinity": "TEXT",
"notNull": true,
"defaultValue": "''"
+ },
+ {
+ "fieldPath": "size",
+ "columnName": "size",
+ "affinity": "TEXT",
+ "notNull": true,
+ "defaultValue": "''"
+ },
+ {
+ "fieldPath": "type",
+ "columnName": "type",
+ "affinity": "TEXT",
+ "notNull": true,
+ "defaultValue": "''"
+ },
+ {
+ "fieldPath": "subtype",
+ "columnName": "subtype",
+ "affinity": "TEXT",
+ "notNull": true,
+ "defaultValue": "''"
+ },
+ {
+ "fieldPath": "alignment",
+ "columnName": "alignment",
+ "affinity": "TEXT",
+ "notNull": true,
+ "defaultValue": "''"
+ },
+ {
+ "fieldPath": "strengthScore",
+ "columnName": "strength_score",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "10"
+ },
+ {
+ "fieldPath": "strengthSavingThrowAdvantage",
+ "columnName": "strength_saving_throw_advantage",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "'none'"
+ },
+ {
+ "fieldPath": "strengthSavingThrowProficiency",
+ "columnName": "strength_saving_throw_proficiency",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "'none'"
+ },
+ {
+ "fieldPath": "dexterityScore",
+ "columnName": "dexterity_score",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "10"
+ },
+ {
+ "fieldPath": "dexteritySavingThrowAdvantage",
+ "columnName": "dexterity_saving_throw_advantage",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "'none'"
+ },
+ {
+ "fieldPath": "dexteritySavingThrowProficiency",
+ "columnName": "dexterity_saving_throw_proficiency",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "'none'"
+ },
+ {
+ "fieldPath": "constitutionScore",
+ "columnName": "constitution_score",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "10"
+ },
+ {
+ "fieldPath": "constitutionSavingThrowAdvantage",
+ "columnName": "constitution_saving_throw_advantage",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "'none'"
+ },
+ {
+ "fieldPath": "constitutionSavingThrowProficiency",
+ "columnName": "constitution_saving_throw_proficiency",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "'none'"
+ },
+ {
+ "fieldPath": "intelligenceScore",
+ "columnName": "intelligence_score",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "10"
+ },
+ {
+ "fieldPath": "intelligenceSavingThrowAdvantage",
+ "columnName": "intelligence_saving_throw_advantage",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "'none'"
+ },
+ {
+ "fieldPath": "intelligenceSavingThrowProficiency",
+ "columnName": "intelligence_saving_throw_proficiency",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "'none'"
+ },
+ {
+ "fieldPath": "wisdomScore",
+ "columnName": "wisdom_score",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "10"
+ },
+ {
+ "fieldPath": "wisdomSavingThrowAdvantage",
+ "columnName": "wisdom_saving_throw_advantage",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "'none'"
+ },
+ {
+ "fieldPath": "wisdomSavingThrowProficiency",
+ "columnName": "wisdom_saving_throw_proficiency",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "'none'"
+ },
+ {
+ "fieldPath": "charismaScore",
+ "columnName": "charisma_score",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "10"
+ },
+ {
+ "fieldPath": "charismaSavingThrowAdvantage",
+ "columnName": "charisma_saving_throw_advantage",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "'none'"
+ },
+ {
+ "fieldPath": "charismaSavingThrowProficiency",
+ "columnName": "charisma_saving_throw_proficiency",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "'none'"
+ },
+ {
+ "fieldPath": "armorType",
+ "columnName": "armor_type",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "'none'"
+ },
+ {
+ "fieldPath": "shieldBonus",
+ "columnName": "shield_bonus",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "naturalArmorBonus",
+ "columnName": "natural_armor_bonus",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "otherArmorDescription",
+ "columnName": "other_armor_description",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "''"
+ },
+ {
+ "fieldPath": "hitDice",
+ "columnName": "hit_dice",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "1"
+ },
+ {
+ "fieldPath": "hasCustomHP",
+ "columnName": "has_custom_hit_points",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "customHPDescription",
+ "columnName": "custom_hit_points_description",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "''"
+ },
+ {
+ "fieldPath": "walkSpeed",
+ "columnName": "walk_speed",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "burrowSpeed",
+ "columnName": "burrow_speed",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "climbSpeed",
+ "columnName": "climb_speed",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "flySpeed",
+ "columnName": "fly_speed",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "canHover",
+ "columnName": "can_hover",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "false"
+ },
+ {
+ "fieldPath": "swimSpeed",
+ "columnName": "swim_speed",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "hasCustomSpeed",
+ "columnName": "has_custom_speed",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "false"
+ },
+ {
+ "fieldPath": "customSpeedDescription",
+ "columnName": "custom_speed_description",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "challengeRating",
+ "columnName": "challenge_rating",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "'1'"
+ },
+ {
+ "fieldPath": "customChallengeRatingDescription",
+ "columnName": "custom_challenge_rating_description",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "''"
+ },
+ {
+ "fieldPath": "customProficiencyBonus",
+ "columnName": "custom_proficiency_bonus",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "blindsightRange",
+ "columnName": "blindsight_range",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "isBlindBeyondBlindsightRange",
+ "columnName": "is_blind_beyond_blindsight_range",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "false"
+ },
+ {
+ "fieldPath": "darkvisionRange",
+ "columnName": "darkvision_range",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "tremorsenseRange",
+ "columnName": "tremorsense_range",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "truesightRange",
+ "columnName": "truesight_range",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "telepathyRange",
+ "columnName": "telepathy_range",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "understandsButDescription",
+ "columnName": "understands_but_description",
+ "affinity": "TEXT",
+ "notNull": false,
+ "defaultValue": "''"
+ },
+ {
+ "fieldPath": "skills",
+ "columnName": "skills",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "damageImmunities",
+ "columnName": "damage_immunities",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "damageResistances",
+ "columnName": "damage_resistances",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "damageVulnerabilities",
+ "columnName": "damage_vulnerabilities",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "conditionImmunities",
+ "columnName": "condition_immunities",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "languages",
+ "columnName": "languages",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "abilities",
+ "columnName": "abilities",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "actions",
+ "columnName": "actions",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "reactions",
+ "columnName": "reactions",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "lairActions",
+ "columnName": "lair_actions",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "legendaryActions",
+ "columnName": "legendary_actions",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "regionalActions",
+ "columnName": "regional_actions",
+ "affinity": "TEXT",
+ "notNull": false
}
],
"primaryKey": {
@@ -35,7 +434,7 @@
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
- "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'a9371223372fb64522cc40f5529ada09')"
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'db1293d2f490940b55ca1f4f56b21b1a')"
]
}
}
\ No newline at end of file
diff --git a/app/schemas/com.majinnaibu.monstercards.AppDatabase/schema-notes.md b/app/schemas/com.majinnaibu.monstercards.AppDatabase/schema-notes.md
new file mode 100644
index 0000000..24e4113
--- /dev/null
+++ b/app/schemas/com.majinnaibu.monstercards.AppDatabase/schema-notes.md
@@ -0,0 +1,73 @@
+## Monster
+id: UUID as TEXT // doesn't exist in the iOS model
+abilities: Set converted to JSON as TEXT
+actions: Set converted to JSON as TEXT
+alignment: String as TEXT
+armor_type: Enum as TEXT
+blindsight_range: int as INTEGER
+burrow_speed: int as INTEGER
+can_hover: boolean as INTEGER
+challenge_rating: Enum as TEXT
+charisma_saving_throw_advantage
+charisma_saving_throw_proficiency
+charisma_score: int as INTEGER
+climb_speed: int as INTEGER
+condition_immunities: Set converted to JSON as TEXT
+constitution_saving_throw_advantage
+constitution_saving_throw_proficiency
+constitution_score: int as INTEGER
+//other_armor_description: String as TEXT
+custom_challenge_rating_description: String as TEXT
+custom_hit_points_description: String
+custom_proficiency_bonus: int as INTEGER
+custom_speed_description: String as TEXT
+damage_immunities: Set converted to JSON as TEXT
+damage_resistances: Set converted to JSON as TEXT
+damage_vulnerabilities: Set converted to JSON as TEXT
+darkvision_range: int as INTEGER
+dexterity_saving_throw_advantage
+dexterity_saving_throw_proficiency
+dexterity_score: int as INTEGER
+fly_speed: int as INTEGER
+has_custom_hit_points: boolean as INTEGER
+has_custom_speed: boolean as INTEGER
+// has_shield
+hit_dice: int as INTEGER
+intelligence_saving_throw_advantage
+intelligence_saving_throw_proficiency
+intelligence_score: int as INTEGER
+is_blind_beyond_blindsight_range: boolean as INTEGER
+lair_actions
+languages: Set converted to JSON as TEXT
+legendary_actions
+name: String as TEXT
+natural_armor_bonus: int as INTEGER
+other_armor_description: String as TEXT
+reactions
+regional_actions
+// senses
+shield_bonus: int as INTEGER
+size: String as TEXT
+strength_saving_throw_advantage
+strength_saving_throw_proficiency
+strength_score: int as INTEGER
+tag: String as TEXT // subtype || tag
+swim_speed: int as INTEGER
+telepathy_range: int as INTEGER
+tremorsense_range: int as INTEGER
+truesight_range: int as INTEGER
+type: String as TEXT
+understands_but_description: String as TEXT
+walk_speed: int as INTEGER
+wisdom_saving_throw_advantage
+wisdom_saving_throw_proficiency
+wisdom_score: int as INTEGER
+
+// tracked as relationship (don't do this)
+skills: Set converted to JSON as TEXT
+
+## Skill
+// ability_score_name String defaults to "strength"
+// advantage String defaults to "none"
+// name String defaults to ""
+// proficiency String defaults to "none"
diff --git a/app/src/main/java/com/majinnaibu/monstercards/AppDatabase.java b/app/src/main/java/com/majinnaibu/monstercards/AppDatabase.java
index fc44923..3d21f3f 100644
--- a/app/src/main/java/com/majinnaibu/monstercards/AppDatabase.java
+++ b/app/src/main/java/com/majinnaibu/monstercards/AppDatabase.java
@@ -4,12 +4,29 @@ import androidx.room.Database;
import androidx.room.RoomDatabase;
import androidx.room.TypeConverters;
-import com.majinnaibu.monstercards.converters.UUIDConverter;
import com.majinnaibu.monstercards.data.MonsterDAO;
+import com.majinnaibu.monstercards.data.converters.ArmorTypeConverter;
+import com.majinnaibu.monstercards.data.converters.ChallengeRatingConverter;
+import com.majinnaibu.monstercards.data.converters.SetOfLanguageConverter;
+import com.majinnaibu.monstercards.data.converters.SetOfSavingThrowConverter;
+import com.majinnaibu.monstercards.data.converters.SetOfSkillConverter;
+import com.majinnaibu.monstercards.data.converters.SetOfStringConverter;
+import com.majinnaibu.monstercards.data.converters.SetOfTraitConverter;
+import com.majinnaibu.monstercards.data.converters.UUIDConverter;
import com.majinnaibu.monstercards.models.Monster;
-@Database(entities = {Monster.class}, version=1)
-@TypeConverters({UUIDConverter.class})
+@SuppressWarnings("unused")
+@Database(entities = {Monster.class}, version = 1)
+@TypeConverters({
+ ArmorTypeConverter.class,
+ ChallengeRatingConverter.class,
+ SetOfLanguageConverter.class,
+ SetOfSavingThrowConverter.class,
+ SetOfSkillConverter.class,
+ SetOfStringConverter.class,
+ SetOfTraitConverter.class,
+ UUIDConverter.class,
+})
public abstract class AppDatabase extends RoomDatabase {
public abstract MonsterDAO monsterDAO();
}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/data/converters/ArmorTypeConverter.java b/app/src/main/java/com/majinnaibu/monstercards/data/converters/ArmorTypeConverter.java
new file mode 100644
index 0000000..d3b63a3
--- /dev/null
+++ b/app/src/main/java/com/majinnaibu/monstercards/data/converters/ArmorTypeConverter.java
@@ -0,0 +1,18 @@
+package com.majinnaibu.monstercards.data.converters;
+
+import androidx.room.TypeConverter;
+
+import com.majinnaibu.monstercards.data.enums.ArmorType;
+
+public class ArmorTypeConverter {
+
+ @TypeConverter
+ public static String fromArmorType(ArmorType armorType) {
+ return armorType.stringValue;
+ }
+
+ @TypeConverter
+ public static ArmorType armorTypeFromStringValue(String stringValue) {
+ return ArmorType.valueOfString(stringValue);
+ }
+}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/data/converters/ChallengeRatingConverter.java b/app/src/main/java/com/majinnaibu/monstercards/data/converters/ChallengeRatingConverter.java
new file mode 100644
index 0000000..47b375b
--- /dev/null
+++ b/app/src/main/java/com/majinnaibu/monstercards/data/converters/ChallengeRatingConverter.java
@@ -0,0 +1,18 @@
+package com.majinnaibu.monstercards.data.converters;
+
+import androidx.room.TypeConverter;
+
+import com.majinnaibu.monstercards.data.enums.ChallengeRating;
+
+public class ChallengeRatingConverter {
+
+ @TypeConverter
+ public static String fromChallengeRating(ChallengeRating challengeRating) {
+ return challengeRating.stringValue;
+ }
+
+ @TypeConverter
+ public static ChallengeRating challengeRatingFromStringValue(String stringValue) {
+ return ChallengeRating.valueOfString(stringValue);
+ }
+}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/data/converters/SetOfLanguageConverter.java b/app/src/main/java/com/majinnaibu/monstercards/data/converters/SetOfLanguageConverter.java
new file mode 100644
index 0000000..b076a4d
--- /dev/null
+++ b/app/src/main/java/com/majinnaibu/monstercards/data/converters/SetOfLanguageConverter.java
@@ -0,0 +1,28 @@
+package com.majinnaibu.monstercards.data.converters;
+
+import androidx.room.TypeConverter;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.majinnaibu.monstercards.models.Language;
+
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+
+public class SetOfLanguageConverter {
+
+ @TypeConverter
+ public static String fromSetOfLanguage(Set languages) {
+ Gson gson = new Gson();
+ return gson.toJson(languages);
+ }
+
+ @TypeConverter
+ public static Set setOfLanguageFromString(String string) {
+ Gson gson = new Gson();
+ Type setType = new TypeToken>() {
+ }.getType();
+ return gson.fromJson(string, setType);
+ }
+}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/data/converters/SetOfSavingThrowConverter.java b/app/src/main/java/com/majinnaibu/monstercards/data/converters/SetOfSavingThrowConverter.java
new file mode 100644
index 0000000..a2ee9b6
--- /dev/null
+++ b/app/src/main/java/com/majinnaibu/monstercards/data/converters/SetOfSavingThrowConverter.java
@@ -0,0 +1,31 @@
+package com.majinnaibu.monstercards.data.converters;
+
+
+import androidx.room.TypeConverter;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.majinnaibu.monstercards.models.SavingThrow;
+
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+
+public class SetOfSavingThrowConverter {
+
+ @TypeConverter
+ public static String fromSetOfSavingThrow(Set savingThrows) {
+ Gson gson = new Gson();
+ SavingThrow[] saves = new SavingThrow[savingThrows.size()];
+ savingThrows.toArray(saves);
+ return gson.toJson(saves);
+ }
+
+ @TypeConverter
+ public static Set setOfSavingThrowFromString(String string) {
+ Gson gson = new Gson();
+ Type setType = new TypeToken>() {
+ }.getType();
+ return gson.fromJson(string, setType);
+ }
+}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/data/converters/SetOfSkillConverter.java b/app/src/main/java/com/majinnaibu/monstercards/data/converters/SetOfSkillConverter.java
new file mode 100644
index 0000000..6f2ee90
--- /dev/null
+++ b/app/src/main/java/com/majinnaibu/monstercards/data/converters/SetOfSkillConverter.java
@@ -0,0 +1,28 @@
+package com.majinnaibu.monstercards.data.converters;
+
+import androidx.room.TypeConverter;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.majinnaibu.monstercards.models.Skill;
+
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+
+public class SetOfSkillConverter {
+
+ @TypeConverter
+ public static String fromSetOfSkill(Set skills) {
+ Gson gson = new Gson();
+ return gson.toJson(skills);
+ }
+
+ @TypeConverter
+ public static Set setOfSkillFromString(String string) {
+ Gson gson = new Gson();
+ Type setType = new TypeToken>() {
+ }.getType();
+ return gson.fromJson(string, setType);
+ }
+}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/data/converters/SetOfStringConverter.java b/app/src/main/java/com/majinnaibu/monstercards/data/converters/SetOfStringConverter.java
new file mode 100644
index 0000000..c09dcaa
--- /dev/null
+++ b/app/src/main/java/com/majinnaibu/monstercards/data/converters/SetOfStringConverter.java
@@ -0,0 +1,27 @@
+package com.majinnaibu.monstercards.data.converters;
+
+import androidx.room.TypeConverter;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+
+public class SetOfStringConverter {
+
+ @TypeConverter
+ public static String fromSetOfString(Set strings) {
+ Gson gson = new Gson();
+ return gson.toJson(strings);
+ }
+
+ @TypeConverter
+ public static Set setOfStringFromString(String string) {
+ Gson gson = new Gson();
+ Type setType = new TypeToken>() {
+ }.getType();
+ return gson.fromJson(string, setType);
+ }
+}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/data/converters/SetOfTraitConverter.java b/app/src/main/java/com/majinnaibu/monstercards/data/converters/SetOfTraitConverter.java
new file mode 100644
index 0000000..029b102
--- /dev/null
+++ b/app/src/main/java/com/majinnaibu/monstercards/data/converters/SetOfTraitConverter.java
@@ -0,0 +1,27 @@
+package com.majinnaibu.monstercards.data.converters;
+
+import androidx.room.TypeConverter;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.majinnaibu.monstercards.models.Trait;
+
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+
+public class SetOfTraitConverter {
+ @TypeConverter
+ public static String fromSetOfTrait(Set traits) {
+ Gson gson = new Gson();
+ return gson.toJson(traits);
+ }
+
+ @TypeConverter
+ public static Set setOfTraitFromString(String string) {
+ Gson gson = new Gson();
+ Type setType = new TypeToken>() {
+ }.getType();
+ return gson.fromJson(string, setType);
+ }
+}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/converters/UUIDConverter.java b/app/src/main/java/com/majinnaibu/monstercards/data/converters/UUIDConverter.java
similarity index 85%
rename from app/src/main/java/com/majinnaibu/monstercards/converters/UUIDConverter.java
rename to app/src/main/java/com/majinnaibu/monstercards/data/converters/UUIDConverter.java
index b1effc8..07d5375 100644
--- a/app/src/main/java/com/majinnaibu/monstercards/converters/UUIDConverter.java
+++ b/app/src/main/java/com/majinnaibu/monstercards/data/converters/UUIDConverter.java
@@ -1,4 +1,4 @@
-package com.majinnaibu.monstercards.converters;
+package com.majinnaibu.monstercards.data.converters;
import androidx.room.TypeConverter;
diff --git a/app/src/main/java/com/majinnaibu/monstercards/data/enums/AbilityScore.java b/app/src/main/java/com/majinnaibu/monstercards/data/enums/AbilityScore.java
new file mode 100644
index 0000000..a155d8a
--- /dev/null
+++ b/app/src/main/java/com/majinnaibu/monstercards/data/enums/AbilityScore.java
@@ -0,0 +1,31 @@
+package com.majinnaibu.monstercards.data.enums;
+
+@SuppressWarnings("unused")
+public enum AbilityScore {
+ STRENGTH("strength", "Strength", "STR"),
+ DEXTERITY("dexterity", "Dexterity", "DEX"),
+ CONSTITUTION("constitution", "Constitution", "CON"),
+ INTELLIGENCE("intellligence", "Intelligence", "INT"),
+ WISDOM("wisdom", "Wisdom", "WIS"),
+ CHARISMA("charisma", "Charisma", "CHA"),
+ ;
+
+ public final String displayName;
+ public final String shortDisplayName;
+ public final String stringValue;
+
+ AbilityScore(String stringValue, String displayName, String shortDisplayName) {
+ this.displayName = displayName;
+ this.stringValue = stringValue;
+ this.shortDisplayName = shortDisplayName;
+ }
+
+ public static AbilityScore valueOfString(String string) {
+ for (AbilityScore abilityScore : values()) {
+ if (abilityScore.stringValue.equals(string)) {
+ return abilityScore;
+ }
+ }
+ return AbilityScore.STRENGTH;
+ }
+}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/data/enums/AdvantageType.java b/app/src/main/java/com/majinnaibu/monstercards/data/enums/AdvantageType.java
new file mode 100644
index 0000000..1405696
--- /dev/null
+++ b/app/src/main/java/com/majinnaibu/monstercards/data/enums/AdvantageType.java
@@ -0,0 +1,27 @@
+package com.majinnaibu.monstercards.data.enums;
+
+public enum AdvantageType {
+ NONE("none", "None", ""),
+ ADVANTAGE("advantage", "Advantage", "A"),
+ DISADVANTAGE("disadvantage", "Disadvantage", "D"),
+ ;
+
+ public final String displayName;
+ public final String stringValue;
+ public final String label;
+
+ AdvantageType(String stringValue, String displayName, String label) {
+ this.displayName = displayName;
+ this.stringValue = stringValue;
+ this.label = label;
+ }
+
+ public static AdvantageType valueOfString(String string) {
+ for (AdvantageType advantageType : values()) {
+ if (advantageType.stringValue.equals(string)) {
+ return advantageType;
+ }
+ }
+ return AdvantageType.NONE;
+ }
+}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/data/enums/ArmorType.java b/app/src/main/java/com/majinnaibu/monstercards/data/enums/ArmorType.java
new file mode 100644
index 0000000..67cf8ae
--- /dev/null
+++ b/app/src/main/java/com/majinnaibu/monstercards/data/enums/ArmorType.java
@@ -0,0 +1,41 @@
+package com.majinnaibu.monstercards.data.enums;
+
+@SuppressWarnings("unused")
+public enum ArmorType {
+ NONE("none", "None", 10),
+ NATURAL_ARMOR("natural armor", "Natural Armor", 10),
+ MAGE_ARMOR("mage armor", "Mage Armor", 10),
+ PADDED("padded", "Padded", 11),
+ LEATHER("leather", "Leather", 11),
+ STUDDED_LEATHER("studded", "Studded Leather", 12),
+ HIDE("hide", "Hide", 12),
+ CHAIN_SHIRT("chain shirt", "Chain Shirt", 13),
+ SCALE_MAIL("scale mail", "Scale Mail", 14),
+ BREASTPLATE("breastplate", "Breastplate", 14),
+ HALF_PLATE("half plate", "Half Plate", 15),
+ RING_MAIL("ring mail", "Ring Mail", 14),
+ CHAIN_MAIL("chain mail", "Chain Mail", 16),
+ SPLINT_MAIL("splint", "Splint Mail", 17),
+ PLATE_MAIL("plate", "Plate Mail", 18),
+ OTHER("other", "Other", 10),
+ ;
+
+ public final String displayName;
+ public final String stringValue;
+ public final int baseArmorClass;
+
+ ArmorType(String stringValue, String displayName, int baseArmorClass) {
+ this.displayName = displayName;
+ this.stringValue = stringValue;
+ this.baseArmorClass = baseArmorClass;
+ }
+
+ public static ArmorType valueOfString(String string) {
+ for (ArmorType armorType : values()) {
+ if (armorType.stringValue.equals(string)) {
+ return armorType;
+ }
+ }
+ return ArmorType.NONE;
+ }
+}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/data/enums/ChallengeRating.java b/app/src/main/java/com/majinnaibu/monstercards/data/enums/ChallengeRating.java
new file mode 100644
index 0000000..be8d87c
--- /dev/null
+++ b/app/src/main/java/com/majinnaibu/monstercards/data/enums/ChallengeRating.java
@@ -0,0 +1,60 @@
+package com.majinnaibu.monstercards.data.enums;
+
+@SuppressWarnings("unused")
+public enum ChallengeRating {
+ CUSTOM("custom", "Custom", 0),
+ ZERO("zero", "0 (10 XP)", 2),
+ ONE_EIGHTH("1/8", "1/8 (25 XP)", 2),
+ ONE_QUARTER("1/4", "1/4 (50 XP)", 2),
+ ONE_HALF("1/2", "1/2 (100 XP)", 2),
+ ONE("1", "1 (200 XP)", 2),
+ TWO("2", "2 (450 XP)", 2),
+ THREE("3", "3 (700 XP)", 2),
+ FOUR("4", "4 (1,100 XP)", 2),
+ FIVE("5", "5 (1,800 XP)", 3),
+ SIX("6", "6 (2,300 XP)", 3),
+ SEVEN("7", "7 (2,900 XP)", 3),
+ EIGHT("8", "8 (3,900 XP)", 3),
+ NINE("9", "9 (5,000 XP)", 4),
+ TEN("10", "10 (5,900 XP)", 4),
+ ELEVEN("11", "11 (7,200 XP)", 4),
+ TWELVE("12", "12 (8,400 XP)", 4),
+ THIRTEEN("13", "13 (10,000 XP)", 5),
+ FOURTEEN("14", "14 (11,500 XP)", 5),
+ FIFTEEN("15", "15 (13,000 XP)", 5),
+ SIXTEEN("16", "16 (15,000 XP)", 5),
+ SEVENTEEN("17", "17 (18,000 XP)", 6),
+ EIGHTEEN("18", "18 (20,000 XP)", 6),
+ NINETEEN("19", "19 (22,000 XP)", 6),
+ TWENTY("20", "20 (25,000 XP)", 6),
+ TWENTY_ONE("21", "21 (33,000 XP)", 7),
+ TWENTY_TWO("22", "22 (41,000 XP)", 7),
+ TWENTY_THREE("23", "23 (50,000 XP)", 7),
+ TWENTY_FOUR("24", "24 (62,000 XP)", 7),
+ TWENTY_FIVE("25", "25 (75,000 XP)", 8),
+ TWENTY_SIX("26", "26 (90,000 XP)", 8),
+ TWENTY_SEVEN("27", "27 (105,000 XP)", 8),
+ TWENTY_EIGHT("28", "28 (120,000 XP)", 8),
+ TWENTY_NINE("29", "29 (135,000 XP)", 9),
+ THIRTY("30", "30 (155,000 XP)", 9),
+ ;
+
+ public final String displayName;
+ public final String stringValue;
+ public final int proficiencyBonus;
+
+ ChallengeRating(String stringValue, String displayName, int proficiencyBonus) {
+ this.displayName = displayName;
+ this.stringValue = stringValue;
+ this.proficiencyBonus = proficiencyBonus;
+ }
+
+ public static ChallengeRating valueOfString(String string) {
+ for (ChallengeRating challengeRating : values()) {
+ if (challengeRating.stringValue.equals(string)) {
+ return challengeRating;
+ }
+ }
+ return ChallengeRating.ONE;
+ }
+}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/data/enums/ProficiencyType.java b/app/src/main/java/com/majinnaibu/monstercards/data/enums/ProficiencyType.java
new file mode 100644
index 0000000..76754bc
--- /dev/null
+++ b/app/src/main/java/com/majinnaibu/monstercards/data/enums/ProficiencyType.java
@@ -0,0 +1,27 @@
+package com.majinnaibu.monstercards.data.enums;
+
+public enum ProficiencyType {
+ NONE("none", "None", ""),
+ PROFICIENT("proficient", "Proficient", "P"),
+ EXPERTISE("experties", "Expertise", "Ex"),
+ ;
+
+ public final String displayName;
+ public final String stringValue;
+ public final String label;
+
+ ProficiencyType(String stringValue, String displayName, String label) {
+ this.displayName = displayName;
+ this.stringValue = stringValue;
+ this.label = label;
+ }
+
+ public static ProficiencyType valueOfString(String string) {
+ for (ProficiencyType proficiencyType : values()) {
+ if (proficiencyType.stringValue.equals(string)) {
+ return proficiencyType;
+ }
+ }
+ return ProficiencyType.NONE;
+ }
+}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/models/Ability.java b/app/src/main/java/com/majinnaibu/monstercards/models/Ability.java
deleted file mode 100644
index 9921b92..0000000
--- a/app/src/main/java/com/majinnaibu/monstercards/models/Ability.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.majinnaibu.monstercards.models;
-
-public class Ability {
-
- public Ability(String name, String description) {
- mName = name;
- mDescription = description;
- }
-
- private String mName;
-
- public String getName() {
- return mName;
- }
-
- public void setName(String name) {
- mName = name;
- }
-
- private String mDescription;
-
- public String getDescription() {
- return mDescription;
- }
-
- public void setDescription(String description) {
- mDescription = description;
- }
-}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/models/Action.java b/app/src/main/java/com/majinnaibu/monstercards/models/Action.java
deleted file mode 100644
index abb5036..0000000
--- a/app/src/main/java/com/majinnaibu/monstercards/models/Action.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.majinnaibu.monstercards.models;
-
-public class Action {
-
- public Action(String name, String description) {
- mName = name;
- mDescription = description;
- }
-
- private String mName;
-
- public String getName() {
- return mName;
- }
-
- public void setName(String name) {
- mName = name;
- }
-
- private String mDescription;
-
- public String getDescription() {
- return mDescription;
- }
-
- public void setDescription(String description) {
- mDescription = description;
- }
-}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/models/DamageType.java b/app/src/main/java/com/majinnaibu/monstercards/models/DamageType.java
deleted file mode 100644
index 73333b2..0000000
--- a/app/src/main/java/com/majinnaibu/monstercards/models/DamageType.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.majinnaibu.monstercards.models;
-
-public class DamageType {
-
- public DamageType(String name, String note, String type) {
- mName = name;
- mNote = note;
- mType = type;
- }
-
- private String mName;
-
- public String getName() {
- return mName;
- }
-
- public void setName(String value) {
- mName = value;
- }
-
- private String mNote;
-
- public String getNote() {
- return mNote;
- }
-
- public void setNote(String value) {
- mNote = value;
- }
-
- private String mType;
-
- public String getType() {
- return mType;
- }
-
- public void setType(String value) {
- mType = value;
- }
-
-}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/models/Monster.java b/app/src/main/java/com/majinnaibu/monstercards/models/Monster.java
index e755fed..630f0ea 100644
--- a/app/src/main/java/com/majinnaibu/monstercards/models/Monster.java
+++ b/app/src/main/java/com/majinnaibu/monstercards/models/Monster.java
@@ -1,11 +1,17 @@
package com.majinnaibu.monstercards.models;
+import android.annotation.SuppressLint;
+
import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
-import androidx.room.Ignore;
import androidx.room.PrimaryKey;
+import com.majinnaibu.monstercards.data.enums.AbilityScore;
+import com.majinnaibu.monstercards.data.enums.AdvantageType;
+import com.majinnaibu.monstercards.data.enums.ArmorType;
+import com.majinnaibu.monstercards.data.enums.ChallengeRating;
+import com.majinnaibu.monstercards.data.enums.ProficiencyType;
import com.majinnaibu.monstercards.helpers.StringHelper;
import java.util.ArrayList;
@@ -13,11 +19,12 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
-import java.util.Locale;
import java.util.Set;
import java.util.UUID;
@Entity
+@SuppressLint("DefaultLocale")
+@SuppressWarnings("unused")
public class Monster {
@PrimaryKey
@@ -28,71 +35,240 @@ public class Monster {
@ColumnInfo(defaultValue = "")
public String name;
+ @NonNull()
+ @ColumnInfo(defaultValue = "")
+ public String size;
+
+ @NonNull()
+ @ColumnInfo(defaultValue = "")
+ public String type;
+
+ @NonNull()
+ @ColumnInfo(defaultValue = "")
+ public String subtype;
+
+ @NonNull()
+ @ColumnInfo(defaultValue = "")
+ public String alignment;
+
+ @ColumnInfo(name = "strength_score", defaultValue = "10")
+ public int strengthScore;
+
+ @ColumnInfo(name = "strength_saving_throw_advantage", defaultValue = "none")
+ public AdvantageType strengthSavingThrowAdvantage;
+
+ @ColumnInfo(name = "strength_saving_throw_proficiency", defaultValue = "none")
+ public ProficiencyType strengthSavingThrowProficiency;
+
+ @ColumnInfo(name = "dexterity_score", defaultValue = "10")
+ public int dexterityScore;
+
+ @ColumnInfo(name = "dexterity_saving_throw_advantage", defaultValue = "none")
+ public AdvantageType dexteritySavingThrowAdvantage;
+
+ @ColumnInfo(name = "dexterity_saving_throw_proficiency", defaultValue = "none")
+ public ProficiencyType dexteritySavingThrowProficiency;
+
+ @ColumnInfo(name = "constitution_score", defaultValue = "10")
+ public int constitutionScore;
+
+ @ColumnInfo(name = "constitution_saving_throw_advantage", defaultValue = "none")
+ public AdvantageType constitutionSavingThrowAdvantage;
+
+ @ColumnInfo(name = "constitution_saving_throw_proficiency", defaultValue = "none")
+ public ProficiencyType constitutionSavingThrowProficiency;
+
+ @ColumnInfo(name = "intelligence_score", defaultValue = "10")
+ public int intelligenceScore;
+
+ @ColumnInfo(name = "intelligence_saving_throw_advantage", defaultValue = "none")
+ public AdvantageType intelligenceSavingThrowAdvantage;
+
+ @ColumnInfo(name = "intelligence_saving_throw_proficiency", defaultValue = "none")
+ public ProficiencyType intelligenceSavingThrowProficiency;
+
+ @ColumnInfo(name = "wisdom_score", defaultValue = "10")
+ public int wisdomScore;
+
+ @ColumnInfo(name = "wisdom_saving_throw_advantage", defaultValue = "none")
+ public AdvantageType wisdomSavingThrowAdvantage;
+
+ @ColumnInfo(name = "wisdom_saving_throw_proficiency", defaultValue = "none")
+ public ProficiencyType wisdomSavingThrowProficiency;
+
+ @ColumnInfo(name = "charisma_score", defaultValue = "10")
+ public int charismaScore;
+
+ @ColumnInfo(name = "charisma_saving_throw_advantage", defaultValue = "none")
+ public AdvantageType charismaSavingThrowAdvantage;
+
+ @ColumnInfo(name = "charisma_saving_throw_proficiency", defaultValue = "none")
+ public ProficiencyType charismaSavingThrowProficiency;
+
+ @ColumnInfo(name = "armor_type", defaultValue = "none"/* ArmorType.NONE.stringValue */)
+ public ArmorType armorType;
+
+ @ColumnInfo(name = "shield_bonus", defaultValue = "0")
+ public int shieldBonus;
+
+ @ColumnInfo(name = "natural_armor_bonus", defaultValue = "0")
+ public int naturalArmorBonus;
+
+ @ColumnInfo(name = "other_armor_description", defaultValue = "")
+ public String otherArmorDescription;
+
+ @ColumnInfo(name = "hit_dice", defaultValue = "1")
+ public int hitDice;
+
+ @ColumnInfo(name = "has_custom_hit_points", defaultValue = "")
+ public boolean hasCustomHP;
+
+ @ColumnInfo(name = "custom_hit_points_description", defaultValue = "")
+ public String customHPDescription;
+
+ @ColumnInfo(name = "walk_speed", defaultValue = "0")
+ public int walkSpeed;
+
+ @ColumnInfo(name = "burrow_speed", defaultValue = "0")
+ public int burrowSpeed;
+
+ @ColumnInfo(name = "climb_speed", defaultValue = "0")
+ public int climbSpeed;
+
+ @ColumnInfo(name = "fly_speed", defaultValue = "0")
+ public int flySpeed;
+
+ @ColumnInfo(name = "can_hover", defaultValue = "false")
+ public boolean canHover;
+
+ @ColumnInfo(name = "swim_speed", defaultValue = "0")
+ public int swimSpeed;
+
+ @ColumnInfo(name = "has_custom_speed", defaultValue = "false")
+ public boolean hasCustomSpeed;
+
+ @ColumnInfo(name = "custom_speed_description")
+ public String customSpeedDescription;
+
+ @ColumnInfo(name = "challenge_rating", defaultValue = "1")
+ public ChallengeRating challengeRating;
+
+ @ColumnInfo(name = "custom_challenge_rating_description", defaultValue = "")
+ public String customChallengeRatingDescription;
+
+ @ColumnInfo(name = "custom_proficiency_bonus", defaultValue = "0")
+ public int customProficiencyBonus;
+
+ @ColumnInfo(name = "blindsight_range", defaultValue = "0")
+ public int blindsightRange;
+
+ @ColumnInfo(name = "is_blind_beyond_blindsight_range", defaultValue = "false")
+ public boolean isBlindBeyondBlindsightRange;
+
+ @ColumnInfo(name = "darkvision_range", defaultValue = "0")
+ public int darkvisionRange;
+
+ @ColumnInfo(name = "tremorsense_range", defaultValue = "0")
+ public int tremorsenseRange;
+
+ @ColumnInfo(name = "truesight_range", defaultValue = "0")
+ public int truesightRange;
+
+ @ColumnInfo(name = "telepathy_range", defaultValue = "0")
+ public int telepathyRange;
+
+ @ColumnInfo(name = "understands_but_description", defaultValue = "")
+ public String understandsButDescription;
+
+ @ColumnInfo(name = "skills")
+ public Set skills;
+
+ @ColumnInfo(name = "damage_immunities")
+ public Set damageImmunities;
+
+ @ColumnInfo(name = "damage_resistances")
+ public Set damageResistances;
+
+ @ColumnInfo(name = "damage_vulnerabilities")
+ public Set damageVulnerabilities;
+
+ @ColumnInfo(name = "condition_immunities")
+ public Set conditionImmunities;
+
+ @ColumnInfo(name = "languages")
+ public Set languages;
+
+ @ColumnInfo(name = "abilities")
+ public Set abilities;
+
+ @ColumnInfo(name = "actions")
+ public Set actions;
+
+ @ColumnInfo(name = "reactions")
+ public Set reactions;
+
+ @ColumnInfo(name = "lair_actions")
+ public Set lairActions;
+
+ @ColumnInfo(name = "legendary_actions")
+ public Set legendaryActions;
+
+ @ColumnInfo(name = "regional_actions")
+ public Set regionalActions;
+
public Monster() {
+ id = UUID.randomUUID();
name = "";
- mAbilities = new ArrayList<>();
- mActions = new ArrayList<>();
- mConditionImmunities = new HashSet<>();
- mDamageTypes = new HashSet<>();
- mLanguages = new HashSet<>();
- mSavingThrows = new HashSet<>();
- mSkills = new HashSet<>();
- }
+ size = "";
+ type = "";
+ subtype = "";
+ alignment = "";
+ strengthScore = 10;
+ dexterityScore = 10;
+ constitutionScore = 10;
+ intelligenceScore = 10;
+ wisdomScore = 10;
+ charismaScore = 10;
+ armorType = ArmorType.NONE;
+ shieldBonus = 0;
+ naturalArmorBonus = 0;
+ otherArmorDescription = "";
+ hitDice = 1;
+ hasCustomHP = false;
+ customHPDescription = "";
+ walkSpeed = 0;
+ burrowSpeed = 0;
+ climbSpeed = 0;
+ flySpeed = 0;
+ canHover = false;
+ swimSpeed = 0;
+ hasCustomSpeed = false;
+ customSpeedDescription = "";
+ challengeRating = ChallengeRating.ONE;
+ customChallengeRatingDescription = "";
- @Ignore()
- private String mSize;
-
- public String getSize() {
- return mSize;
- }
-
- public void setSize(String value) {
- mSize = value;
- }
-
- @Ignore()
- private String mType;
-
- public String getType() {
- return mType;
- }
-
- public void setType(String value) {
- mType = value;
- }
-
- @Ignore()
- private String mTag;
-
- public String getTag() {
- return mTag;
- }
-
- public void setTag(String value) {
- mTag = value;
- }
-
- @Ignore()
- private String mAlignment;
-
- public String getAlignment() {
- return mAlignment;
- }
-
- public void setAlignment(String value) {
- mAlignment = value;
+ skills = new HashSet<>();
+ damageImmunities = new HashSet<>();
+ damageResistances = new HashSet<>();
+ damageVulnerabilities = new HashSet<>();
+ conditionImmunities = new HashSet<>();
+ languages = new HashSet<>();
+ abilities = new HashSet<>();
+ actions = new HashSet<>();
+ reactions = new HashSet<>();
+ lairActions = new HashSet<>();
+ legendaryActions = new HashSet<>();
+ regionalActions = new HashSet<>();
}
public String getMeta() {
StringBuilder sb = new StringBuilder();
boolean isFirstOutput = true;
- String size = getSize();
if (!StringHelper.isNullOrEmpty(size)) {
sb.append(size);
isFirstOutput = false;
}
- String type = getType();
if (!StringHelper.isNullOrEmpty(type)) {
if (!isFirstOutput) {
sb.append(" ");
@@ -101,18 +277,16 @@ public class Monster {
isFirstOutput = false;
}
- String tag = getTag();
- if (!StringHelper.isNullOrEmpty(tag)) {
+ if (!StringHelper.isNullOrEmpty(subtype)) {
if (!isFirstOutput) {
sb.append(" ");
}
sb.append("(");
- sb.append(tag);
+ sb.append(subtype);
sb.append(")");
isFirstOutput = false;
}
- String alignment = getAlignment();
if (!StringHelper.isNullOrEmpty(alignment)) {
if (!isFirstOutput) {
sb.append(", ");
@@ -123,21 +297,22 @@ public class Monster {
return sb.toString();
}
- public int getAbilityScore(String abilityScoreName) {
- if ("strength".equals(abilityScoreName) || "str".equals(abilityScoreName)) {
- return getStrengthScore();
- } else if ("dexterity".equals(abilityScoreName) || "dex".equals(abilityScoreName)) {
- return getDexterityScore();
- } else if ("constitution".equals(abilityScoreName) || "con".equals(abilityScoreName)) {
- return getConstitutionScore();
- } else if ("intelligence".equals(abilityScoreName) || "int".equals(abilityScoreName)) {
- return getIntelligenceScore();
- } else if ("wisdom".equals(abilityScoreName) || "wis".equals(abilityScoreName)) {
- return getWisdomScore();
- } else if ("charisma".equals(abilityScoreName) || "cha".equals(abilityScoreName)) {
- return getCharismaScore();
- } else {
- return 10;
+ public int getAbilityScore(AbilityScore abilityScore) {
+ switch (abilityScore) {
+ case STRENGTH:
+ return strengthScore;
+ case DEXTERITY:
+ return dexterityScore;
+ case CONSTITUTION:
+ return constitutionScore;
+ case INTELLIGENCE:
+ return intelligenceScore;
+ case WISDOM:
+ return wisdomScore;
+ case CHARISMA:
+ return charismaScore;
+ default:
+ return 10;
}
}
@@ -145,261 +320,155 @@ public class Monster {
return (int) Math.floor((score - 10) / 2.0);
}
- public int getAbilityModifier(String abilityScoreName) {
- int score = getAbilityScore(abilityScoreName);
- return getAbilityModifierForScore(score);
- }
-
- @Ignore()
- private int mStrengthScore;
-
- public int getStrengthScore() {
- return mStrengthScore;
- }
-
- public void setStrengthScore(int value) {
- mStrengthScore = value;
- }
-
- public int getStrengthModifier() {
- return getAbilityModifierForScore(getStrengthScore());
- }
-
- @Ignore()
- private int mDexterityScore;
-
- public int getDexterityScore() {
- return mDexterityScore;
- }
-
- public void setDexterityScore(int value) {
- mDexterityScore = value;
- }
-
- public int getDexterityModifier() {
- return getAbilityModifierForScore(getDexterityScore());
- }
-
- @Ignore()
- private int mConstitutionScore;
-
- public int getConstitutionScore() {
- return mConstitutionScore;
- }
-
- public void setConstitutionScore(int value) {
- mConstitutionScore = value;
- }
-
- public int getConstitutionModifier() {
- return getAbilityModifierForScore(getConstitutionScore());
- }
-
- @Ignore()
- private int mIntelligenceScore;
-
- public int getIntelligenceScore() {
- return mIntelligenceScore;
- }
-
- public void setIntelligenceScore(int value) {
- mIntelligenceScore = value;
- }
-
- public int getIntelligenceModifier() {
- return getAbilityModifierForScore(getIntelligenceScore());
- }
-
- @Ignore()
- private int mWisdomScore;
-
- public int getWisdomScore() {
- return mWisdomScore;
- }
-
- public void setWisdomScore(int value) {
- mWisdomScore = value;
- }
-
- public int getWisdomModifier() {
- return getAbilityModifierForScore(getWisdomScore());
- }
-
- @Ignore()
- private int mCharismaScore;
-
- public int getCharismaScore() {
- return mCharismaScore;
- }
-
- public void setCharismaScore(int value) {
- mCharismaScore = value;
- }
-
- public int getCharismaModifier() {
- return getAbilityModifierForScore(getCharismaScore());
- }
-
- @Ignore()
- private String mArmorName;
-
- public String getArmorName() {
- return mArmorName;
- }
-
- public void setArmorName(String value) {
- mArmorName = value;
- }
-
- @Ignore()
- private int mShieldBonus;
-
- public int getShieldBonus() {
- return mShieldBonus;
- }
-
- public void setShieldBonus(int value) {
- mShieldBonus = value;
- }
-
- @Ignore()
- private int mNaturalArmorBonus;
-
- public int getNaturalArmorBonus() {
- return mNaturalArmorBonus;
- }
-
- public void setNaturalArmorBonus(int value) {
- mNaturalArmorBonus = value;
- }
-
- @Ignore()
- private String mOtherArmorDescription;
-
- public String getOtherArmorDescription() {
- return mOtherArmorDescription;
- }
-
- public void setOtherArmorDescription(String value) {
- mOtherArmorDescription = value;
- }
-
- public String getArmorClass() {
- boolean hasShield = getShieldBonus() != 0;
- String armorName = getArmorName();
- if (StringHelper.isNullOrEmpty(armorName) || "none".equals(armorName)) {
- // 10 + dexMod + 2 for shieldBonus "15" or "17 (shield)"
- return String.format(Locale.US, "%d%s", BASE_ARMOR_CLASS + getDexterityModifier() + getShieldBonus(), hasShield ? " (shield)" : "");
- } else if ("natural armor".equals(armorName)) {
- // 10 + dexMod + naturalArmorBonus + 2 for shieldBonus "16 (natural armor)" or "18 (natural armor, shield)"
- return String.format(Locale.US, "%d (natural armor%s)", BASE_ARMOR_CLASS + getDexterityModifier() + getNaturalArmorBonus() + getShieldBonus(), hasShield ? ", shield" : "");
- } else if ("mage armor".equals(armorName)) {
- // 10 + dexMod + 2 for shield + 3 for mage armor "15 (18 with mage armor)" or 17 (shield, 20 with mage armor)
- return String.format(Locale.US, "%d (%s%d with mage armor)", BASE_ARMOR_CLASS + getDexterityModifier() + getShieldBonus(), hasShield ? "shield, " : "", MAGE_ARMOR_ARMOR_CLASS + getDexterityModifier() + getShieldBonus());
- } else if ("padded".equals(armorName)) {
- // 11 + dexMod + 2 for shield "18 (padded armor, shield)"
- return String.format(Locale.US, "%d (padded%s)", PADDED_ARMOR_ARMOR_CLASS + getDexterityModifier() + getShieldBonus(), hasShield ? ", shield" : "");
- } else if ("leather".equals(armorName)) {
- // 11 + dexMod + 2 for shield "18 (leather, shield)"
- return String.format(Locale.US, "%d (leather%s)", LEATHER_ARMOR_CLASS + getDexterityModifier() + getShieldBonus(), hasShield ? ", shield" : "");
- } else if ("studded".equals(armorName)) {
- // 12 + dexMod +2 for shield "17 (studded leather)"
- return String.format(Locale.US, "%d (studded leather%s)", STUDDED_LEATHER_ARMOR_CLASS + getDexterityModifier() + getShieldBonus(), hasShield ? ", shield" : "");
- } else if ("hide".equals(armorName)) {
- // 12 + Min(2, dexMod) + 2 for shield "12 (hide armor)"
- return String.format(Locale.US, "%d (hide%s)", HIDE_ARMOR_CLASS + Math.min(2, getDexterityModifier()) + getShieldBonus(), hasShield ? ", shield" : "");
- } else if ("chain shirt".equals(armorName)) {
- // 13 + Min(2, dexMod) + 2 for shield "12 (chain shirt)"
- return String.format(Locale.US, "%d (chain shirt%s)", CHAIN_SHIRT_ARMOR_CLASS + Math.min(2, getDexterityModifier()) + getShieldBonus(), hasShield ? ", shield" : "");
- } else if ("scale mail".equals(armorName)) {
- // 14 + Min(2, dexMod) + 2 for shield "14 (scale mail)"
- return String.format(Locale.US, "%d (scale mail%s)", SCALE_MAIL_ARMOR_CLASS + Math.min(2, getDexterityModifier()) + getShieldBonus(), hasShield ? ", shield" : "");
- } else if ("breastplate".equals(armorName)) {
- // 14 + Min(2, dexMod) + 2 for shield "16 (breastplate)"
- return String.format(Locale.US, "%d (breastplate%s)", BREASTPLATE_ARMOR_CLASS + Math.min(2, getDexterityModifier()) + getShieldBonus(), hasShield ? ", shield" : "");
- } else if ("half plate".equals(armorName)) {
- // 15 + Min(2, dexMod) + 2 for shield "17 (half plate)"
- return String.format(Locale.US, "%d (half plate%s)", HALF_PLATE_ARMOR_CLASS + Math.min(2, getDexterityModifier()) + getShieldBonus(), hasShield ? ", shield" : "");
- } else if ("ring mail".equals(armorName)) {
- // 14 + 2 for shield "14 (ring mail)
- return String.format(Locale.US, "%d (ring mail%s)", RING_MAIL_ARMOR_CLASS + getShieldBonus(), hasShield ? ", shield" : "");
- } else if ("chain mail".equals(armorName)) {
- // 16 + 2 for shield "16 (chain mail)"
- return String.format(Locale.US, "%d (chain mail%s)", CHAIN_MAIL_ARMOR_CLASS + getShieldBonus(), hasShield ? ", shield" : "");
- } else if ("splint".equals(armorName)) {
- // 17 + 2 for shield "17 (splint)"
- return String.format(Locale.US, "%d (splint%s)", SPLINT_ARMOR_CLASS + getShieldBonus(), hasShield ? ", shield" : "");
- } else if ("plate".equals(armorName)) {
- // 18 + 2 for shield "18 (plate)"
- return String.format(Locale.US, "%d (plate%s)", PLATE_ARMOR_CLASS + getShieldBonus(), hasShield ? ", shield" : "");
- } else if ("other".equals(armorName)) {
- // pure string value shield check does nothing just copies the string from otherArmorDesc
- return getOtherArmorDescription();
- } else {
- return "";
+ public int getAbilityModifier(AbilityScore abilityScore) {
+ switch (abilityScore) {
+ case STRENGTH:
+ return getStrengthModifier();
+ case DEXTERITY:
+ return getDexterityModifier();
+ case CONSTITUTION:
+ return getConstitutionModifier();
+ case INTELLIGENCE:
+ return getIntelligenceModifier();
+ case WISDOM:
+ return getWisdomModifier();
+ case CHARISMA:
+ return getCharismaModifier();
+ default:
+ return 0;
}
}
- private static final int BASE_ARMOR_CLASS = 10;
- private static final int MAGE_ARMOR_ARMOR_CLASS = BASE_ARMOR_CLASS + 3;
- private static final int PADDED_ARMOR_ARMOR_CLASS = BASE_ARMOR_CLASS + 1;
- private static final int LEATHER_ARMOR_CLASS = BASE_ARMOR_CLASS + 1;
- private static final int STUDDED_LEATHER_ARMOR_CLASS = BASE_ARMOR_CLASS + 2;
- private static final int HIDE_ARMOR_CLASS = BASE_ARMOR_CLASS + 2;
- private static final int CHAIN_SHIRT_ARMOR_CLASS = BASE_ARMOR_CLASS + 3;
- private static final int SCALE_MAIL_ARMOR_CLASS = BASE_ARMOR_CLASS + 4;
- private static final int BREASTPLATE_ARMOR_CLASS = BASE_ARMOR_CLASS + 4;
- private static final int HALF_PLATE_ARMOR_CLASS = BASE_ARMOR_CLASS + 5;
- private static final int RING_MAIL_ARMOR_CLASS = BASE_ARMOR_CLASS + 4;
- private static final int CHAIN_MAIL_ARMOR_CLASS = BASE_ARMOR_CLASS + 6;
- private static final int SPLINT_ARMOR_CLASS = BASE_ARMOR_CLASS + 7;
- private static final int PLATE_ARMOR_CLASS = BASE_ARMOR_CLASS + 8;
-
- @Ignore()
- private int mHitDice;
-
- public int getHitDice() {
- return mHitDice;
+ public AdvantageType getSavingThrowAdvantageType(AbilityScore abilityScore) {
+ switch (abilityScore) {
+ case STRENGTH:
+ return strengthSavingThrowAdvantage;
+ case DEXTERITY:
+ return dexteritySavingThrowAdvantage;
+ case CONSTITUTION:
+ return constitutionSavingThrowAdvantage;
+ case INTELLIGENCE:
+ return intelligenceSavingThrowAdvantage;
+ case WISDOM:
+ return wisdomSavingThrowAdvantage;
+ case CHARISMA:
+ return charismaSavingThrowAdvantage;
+ default:
+ return AdvantageType.NONE;
+ }
}
- public void setHitDice(int value) {
- mHitDice = value;
+ public ProficiencyType getSavingThrowProficiencyType(AbilityScore abilityScore) {
+ switch (abilityScore) {
+ case STRENGTH:
+ return strengthSavingThrowProficiency;
+ case DEXTERITY:
+ return dexteritySavingThrowProficiency;
+ case CONSTITUTION:
+ return constitutionSavingThrowProficiency;
+ case INTELLIGENCE:
+ return intelligenceSavingThrowProficiency;
+ case WISDOM:
+ return wisdomSavingThrowProficiency;
+ case CHARISMA:
+ return charismaSavingThrowProficiency;
+ default:
+ return ProficiencyType.NONE;
+ }
}
- @Ignore()
- private boolean mCustomHP;
-
- public boolean getCustomHP() {
- return mCustomHP;
+ public int getStrengthModifier() {
+ return getAbilityModifierForScore(strengthScore);
}
- public void setCustomHP(boolean value) {
- mCustomHP = value;
+ public int getDexterityModifier() {
+ return getAbilityModifierForScore(dexterityScore);
}
- @Ignore()
- private String mHPText;
-
- public String getHPText() {
- return mHPText;
+ public int getConstitutionModifier() {
+ return getAbilityModifierForScore(constitutionScore);
}
- public void setHPText(String value) {
- mHPText = value;
+ public int getIntelligenceModifier() {
+ return getAbilityModifierForScore(intelligenceScore);
+ }
+
+ public int getWisdomModifier() {
+ return getAbilityModifierForScore(wisdomScore);
+ }
+
+ public int getCharismaModifier() {
+ return getAbilityModifierForScore(charismaScore);
+ }
+
+ public String getArmorClass() {
+ boolean hasShield = shieldBonus != 0;
+ ArmorType armorType = this.armorType != null ? this.armorType : ArmorType.NONE;
+ switch (armorType) {
+ case NONE:
+ // 10 + dexMod + 2 for shieldBonus "15" or "17 (shield)"
+ return String.format("%d%s", armorType.baseArmorClass + getDexterityModifier() + shieldBonus, hasShield ? " (shield)" : "");
+ case NATURAL_ARMOR:
+ // 10 + dexMod + naturalArmorBonus + 2 for shieldBonus "16 (natural armor)" or "18 (natural armor, shield)"
+ return String.format("%d (natural armor%s)", armorType.baseArmorClass + getDexterityModifier() + naturalArmorBonus + shieldBonus, hasShield ? ", shield" : "");
+ case MAGE_ARMOR:
+ // 10 + dexMod + 2 for shield + 3 for mage armor "15 (18 with mage armor)" or 17 (shield, 20 with mage armor)
+ return String.format("%d (%s%d with mage armor)", armorType.baseArmorClass + getDexterityModifier() + shieldBonus, hasShield ? "shield, " : "", armorType.baseArmorClass + 3 + getDexterityModifier() + shieldBonus);
+ case PADDED:
+ // 11 + dexMod + 2 for shield "18 (padded armor, shield)"
+ return String.format("%d (padded%s)", armorType.baseArmorClass + getDexterityModifier() + shieldBonus, hasShield ? ", shield" : "");
+ case LEATHER:
+ // 11 + dexMod + 2 for shield "18 (leather, shield)"
+ return String.format("%d (leather%s)", armorType.baseArmorClass + getDexterityModifier() + shieldBonus, hasShield ? ", shield" : "");
+ case STUDDED_LEATHER:
+ // 12 + dexMod +2 for shield "17 (studded leather)"
+ return String.format("%d (studded leather%s)", armorType.baseArmorClass + getDexterityModifier() + shieldBonus, hasShield ? ", shield" : "");
+ case HIDE:
+ // 12 + Min(2, dexMod) + 2 for shield "12 (hide armor)"
+ return String.format("%d (hide%s)", armorType.baseArmorClass + Math.min(2, getDexterityModifier()) + shieldBonus, hasShield ? ", shield" : "");
+ case CHAIN_SHIRT:
+ // 13 + Min(2, dexMod) + 2 for shield "12 (chain shirt)"
+ return String.format("%d (chain shirt%s)", armorType.baseArmorClass + Math.min(2, getDexterityModifier()) + shieldBonus, hasShield ? ", shield" : "");
+ case SCALE_MAIL:
+ // 14 + Min(2, dexMod) + 2 for shield "14 (scale mail)"
+ return String.format("%d (scale mail%s)", armorType.baseArmorClass + Math.min(2, getDexterityModifier()) + shieldBonus, hasShield ? ", shield" : "");
+ case BREASTPLATE:
+ // 14 + Min(2, dexMod) + 2 for shield "16 (breastplate)"
+ return String.format("%d (breastplate%s)", armorType.baseArmorClass + Math.min(2, getDexterityModifier()) + shieldBonus, hasShield ? ", shield" : "");
+ case HALF_PLATE:
+ // 15 + Min(2, dexMod) + 2 for shield "17 (half plate)"
+ return String.format("%d (half plate%s)", armorType.baseArmorClass + Math.min(2, getDexterityModifier()) + shieldBonus, hasShield ? ", shield" : "");
+ case RING_MAIL:
+ // 14 + 2 for shield "14 (ring mail)
+ return String.format("%d (ring mail%s)", armorType.baseArmorClass + shieldBonus, hasShield ? ", shield" : "");
+ case CHAIN_MAIL:
+ // 16 + 2 for shield "16 (chain mail)"
+ return String.format("%d (chain mail%s)", armorType.baseArmorClass + shieldBonus, hasShield ? ", shield" : "");
+ case SPLINT_MAIL:
+ // 17 + 2 for shield "17 (splint)"
+ return String.format("%d (splint%s)", armorType.baseArmorClass + shieldBonus, hasShield ? ", shield" : "");
+ case PLATE_MAIL:
+ // 18 + 2 for shield "18 (plate)"
+ return String.format("%d (plate%s)", armorType.baseArmorClass + shieldBonus, hasShield ? ", shield" : "");
+ case OTHER:
+ // pure string value shield check does nothing just copies the string from otherArmorDesc
+ return otherArmorDescription;
+ default:
+ return "";
+ }
}
public String getHitPoints() {
- if (getCustomHP()) {
- return getHPText();
+ if (hasCustomHP) {
+ return customHPDescription;
} else {
- int hitDice = getHitDice();
- int dieSize = getHitDieForSize(getSize());
+ int dieSize = getHitDieForSize(size);
int conMod = getConstitutionModifier();
// For PC style calculations use this
//int hpTotal = (int) Math.max(1, Math.ceil(dieSize + conMod + (hitDice - 1) * ((dieSize + 1) / 2.0 + conMod)));
// For monster style calculations use this
int hpTotal = (int) Math.max(1, Math.ceil(hitDice * ((dieSize + 1) / 2.0 + conMod)));
- return String.format(Locale.US, "%d (%dd%d %+d)", hpTotal, hitDice, dieSize, conMod * hitDice);
+ return String.format("%d (%dd%d %+d)", hpTotal, hitDice, dieSize, conMod * hitDice);
}
}
@@ -421,308 +490,93 @@ public class Monster {
}
}
- @Ignore()
- private String mSpeed;
-
- public String getSpeed() {
- return mSpeed;
- }
-
- public void setSpeed(String value) {
- mSpeed = value;
- }
-
- @Ignore()
- private String mBurrowSpeed;
-
- public String getBurrowSpeed() {
- return mBurrowSpeed;
- }
-
- public void setBurrowSpeed(String value) {
- mBurrowSpeed = value;
- }
-
- @Ignore()
- private String mClimbSpeed;
-
- public String getClimbSpeed() {
- return mClimbSpeed;
- }
-
- public void setClimbSpeed(String value) {
- mClimbSpeed = value;
- }
-
- @Ignore()
- private String mFlySpeed;
-
- public String getFlySpeed() {
- return mFlySpeed;
- }
-
- public void setFlySpeed(String value) {
- mFlySpeed = value;
- }
-
- @Ignore()
- private boolean mHover;
-
- public boolean getHover() {
- return mHover;
- }
-
- public void setHover(boolean value) {
- mHover = value;
- }
-
- @Ignore()
- private String mSwimSpeed;
-
- public String getSwimSpeed() {
- return mSwimSpeed;
- }
-
- public void setSwimSpeed(String value) {
- mSwimSpeed = value;
- }
-
- @Ignore()
- private boolean mCustomSpeed;
-
- public boolean getCustomSpeed() {
- return mCustomSpeed;
- }
-
- public void setCustomSpeed(boolean value) {
- mCustomSpeed = value;
- }
-
- @Ignore()
- private String mSpeedDescription;
-
- public String getSpeedDescription() {
- return mSpeedDescription;
- }
-
- public void setSpeedDescription(String value) {
- mSpeedDescription = value;
- }
-
public String getSpeedText() {
- if (getCustomSpeed()) {
- return getSpeedDescription();
+ if (hasCustomSpeed) {
+ return customSpeedDescription;
} else {
ArrayList speedParts = new ArrayList<>();
- speedParts.add(String.format("%s ft.", getSpeed()));
- String burrowSpeed = getBurrowSpeed();
- if (!StringHelper.isNullOrEmpty(burrowSpeed) && !"0".equals(burrowSpeed)) {
- speedParts.add(String.format("burrow %s ft.", burrowSpeed));
+ if (walkSpeed > 0) {
+ speedParts.add(String.format("%d ft.", walkSpeed));
}
-
- String climbSpeed = getClimbSpeed();
- if (!StringHelper.isNullOrEmpty(climbSpeed) && !"0".equals(climbSpeed)) {
- speedParts.add(String.format("climb %s ft.", climbSpeed));
+ if (burrowSpeed > 0) {
+ speedParts.add(String.format("burrow %d ft.", burrowSpeed));
}
-
- String flySpeed = getFlySpeed();
- if (!StringHelper.isNullOrEmpty(flySpeed) && !"0".equals(flySpeed)) {
- speedParts.add(String.format("fly %s ft.%s", flySpeed, getHover() ? " (hover)" : ""));
+ if (climbSpeed > 0) {
+ speedParts.add(String.format("climb %d ft.", climbSpeed));
}
-
- String swimSpeed = getSwimSpeed();
- if (!StringHelper.isNullOrEmpty(swimSpeed) && !"0".equals(swimSpeed)) {
- speedParts.add(String.format("swim %s ft.", swimSpeed));
+ if (flySpeed > 0) {
+ speedParts.add(String.format("fly %d ft.%s", flySpeed, canHover ? " (hover)" : ""));
+ }
+ if (swimSpeed > 0) {
+ speedParts.add(String.format("swim %d ft.", swimSpeed));
}
-
return StringHelper.join(", ", speedParts);
}
}
public String getStrengthDescription() {
- return String.format(Locale.US, "%d (%+d)", getStrengthScore(), getStrengthModifier());
+ return String.format("%d (%+d)", strengthScore, getStrengthModifier());
}
public String getDexterityDescription() {
- return String.format(Locale.US, "%d (%+d)", getDexterityScore(), getDexterityModifier());
+ return String.format("%d (%+d)", dexterityScore, getDexterityModifier());
}
public String getConstitutionDescription() {
- return String.format(Locale.US, "%d (%+d)", getConstitutionScore(), getConstitutionModifier());
+ return String.format("%d (%+d)", constitutionScore, getConstitutionModifier());
}
public String getIntelligenceDescription() {
- return String.format(Locale.US, "%d (%+d)", getIntelligenceScore(), getIntelligenceModifier());
+ return String.format("%d (%+d)", intelligenceScore, getIntelligenceModifier());
}
public String getWisdomDescription() {
- return String.format(Locale.US, "%d (%+d)", getWisdomScore(), getWisdomModifier());
+ return String.format("%d (%+d)", wisdomScore, getWisdomModifier());
}
public String getCharismaDescription() {
- return String.format(Locale.US, "%d (%+d)", getCharismaScore(), getCharismaModifier());
- }
-
- @Ignore()
- private HashSet mSavingThrows;
-
- public Set getSavingThrows() {
- return mSavingThrows;
- }
-
- public void addSavingThrow(SavingThrow savingThrow) {
- mSavingThrows.add(savingThrow);
- }
-
- public void removeSavingThrow(SavingThrow savingThrow) {
- mSavingThrows.remove(savingThrow);
- }
-
- public void clearSavingThrows() {
- mSavingThrows.clear();
+ return String.format("%d (%+d)", charismaScore, getCharismaModifier());
}
public String getSavingThrowsDescription() {
- SavingThrow[] elements = new SavingThrow[mSavingThrows.size()];
- elements = mSavingThrows.toArray(elements);
- Arrays.sort(elements);
- StringBuilder sb = new StringBuilder();
- boolean isFirst = true;
- for (SavingThrow st : elements) {
- if (!isFirst) {
- sb.append(", ");
+ List parts = new ArrayList<>();
+ for (AbilityScore abilityScore : AbilityScore.values()) {
+ AdvantageType advantage = getSavingThrowAdvantageType(abilityScore);
+ ProficiencyType proficiency = getSavingThrowProficiencyType(abilityScore);
+ if (advantage != AdvantageType.NONE || proficiency != ProficiencyType.NONE) {
+ int bonus = getAbilityModifier(abilityScore) + getProficiencyBonus(proficiency);
+ String part = String.format("%s %+d%s", abilityScore.displayName, bonus, advantage != AdvantageType.NONE ? " " + advantage.label : "");
+ parts.add(part);
}
- String name = st.getName();
-
- sb.append(String.format(Locale.US, "%s%s %+d", name.substring(0, 1).toUpperCase(Locale.US), name.substring(1), getAbilityModifier(name) + getProficiencyBonus()));
- isFirst = false;
}
- return sb.toString();
+ return StringHelper.join(", ", parts);
}
public int getProficiencyBonus() {
- String challengeRating = getChallengeRating();
- if ("*".equals(challengeRating)) {
- return getCustomProficiencyBonus();
- } else if (
- "0".equals(challengeRating) ||
- "1/8".equals(challengeRating) ||
- "1/4".equals(challengeRating) ||
- "1/2".equals(challengeRating) ||
- "1".equals(challengeRating) ||
- "2".equals(challengeRating) ||
- "3".equals(challengeRating) ||
- "4".equals(challengeRating)
- ) {
- return 2;
- } else if (
- "5".equals(challengeRating) ||
- "6".equals(challengeRating) ||
- "7".equals(challengeRating) ||
- "8".equals(challengeRating)
- ) {
- return 3;
- } else if (
- "9".equals(challengeRating) ||
- "10".equals(challengeRating) ||
- "11".equals(challengeRating) ||
- "12".equals(challengeRating)
- ) {
- return 4;
- } else if (
- "13".equals(challengeRating) ||
- "14".equals(challengeRating) ||
- "15".equals(challengeRating) ||
- "16".equals(challengeRating)
- ) {
- return 5;
- } else if (
- "17".equals(challengeRating) ||
- "18".equals(challengeRating) ||
- "19".equals(challengeRating) ||
- "20".equals(challengeRating)
- ) {
- return 6;
- } else if (
- "21".equals(challengeRating) ||
- "22".equals(challengeRating) ||
- "23".equals(challengeRating) ||
- "24".equals(challengeRating)
- ) {
- return 7;
- } else if (
- "25".equals(challengeRating) ||
- "26".equals(challengeRating) ||
- "27".equals(challengeRating) ||
- "28".equals(challengeRating)
- ) {
- return 8;
- } else if (
- "29".equals(challengeRating) ||
- "30".equals(challengeRating)
- ) {
- return 9;
+ ChallengeRating challengeRating = this.challengeRating != null ? this.challengeRating : ChallengeRating.ONE;
+ if (challengeRating == ChallengeRating.CUSTOM) {
+ return customProficiencyBonus;
} else {
- return 0;
+ return challengeRating.proficiencyBonus;
}
}
- @Ignore()
- private String mChallengeRating;
+ public int getProficiencyBonus(ProficiencyType proficiencyType) {
+ switch (proficiencyType) {
+ case PROFICIENT:
+ return getProficiencyBonus();
+ case EXPERTISE:
+ return getProficiencyBonus() * 2;
+ case NONE:
+ default:
+ return 0;
+ }
- public String getChallengeRating() {
- return mChallengeRating;
- }
-
- public void setChallengeRating(String challengeRating) {
- mChallengeRating = challengeRating;
- // TODO: update proficiency bonus based on CR
- }
-
- @Ignore()
- private String mCustomChallengeRating;
-
- public String getCustomChallengeRating() {
- return mCustomChallengeRating;
- }
-
- public void setCustomChallengeRating(String challengeRating) {
- mCustomChallengeRating = challengeRating;
- }
-
- @Ignore()
- private int mCustomProficiencyBonus;
-
- public int getCustomProficiencyBonus() {
- return mCustomProficiencyBonus;
- }
-
- public void setCustomProficiencyBonus(int proficiencyBonus) {
- mCustomProficiencyBonus = proficiencyBonus;
- }
-
- @Ignore()
- private HashSet mSkills;
-
- public Set getSkills() {
- return mSkills;
- }
-
- public void addSkill(Skill skill) {
- mSkills.add(skill);
- }
-
- public void removeSkill(Skill skill) {
- mSkills.remove(skill);
- }
-
- public void clearSkill(Skill skill) {
- mSkills.clear();
}
public String getSkillsDescription() {
- Skill[] elements = new Skill[mSkills.size()];
- elements = mSkills.toArray(elements);
+ Skill[] elements = new Skill[skills.size()];
+ elements = skills.toArray(elements);
Arrays.sort(elements);
StringBuilder sb = new StringBuilder();
boolean isFirst = true;
@@ -730,38 +584,17 @@ public class Monster {
if (!isFirst) {
sb.append(", ");
}
- String name = skill.getName();
sb.append(skill.getText(this));
isFirst = false;
}
return sb.toString();
}
- @Ignore()
- private HashSet mDamageTypes;
-
- public Set getDamageTypes() {
- return mDamageTypes;
- }
-
- public void addDamageType(DamageType damageType) {
- // TODO: make this remove the damage type with the same name if it exists first
- mDamageTypes.add(damageType);
- }
-
- public void removeDamageType(DamageType damageType) {
- mDamageTypes.remove(damageType);
- }
-
- public void clearDamageTypes() {
- mDamageTypes.clear();
- }
-
public String getDamageVulnerabilitiesDescription() {
ArrayList vulnerabilities = new ArrayList<>();
- for (DamageType damageType : mDamageTypes) {
- if (damageType != null && "v".equals(damageType.getType()) && !StringHelper.isNullOrEmpty(damageType.getName())) {
- vulnerabilities.add(damageType.getName());
+ for (String damageType : damageVulnerabilities) {
+ if (!StringHelper.isNullOrEmpty(damageType)) {
+ vulnerabilities.add(damageType);
}
}
Collections.sort(vulnerabilities);
@@ -769,178 +602,56 @@ public class Monster {
}
public String getDamageResistancesDescription() {
- ArrayList vulnerabilities = new ArrayList<>();
- for (DamageType damageType : mDamageTypes) {
- if (damageType != null && "r".equals(damageType.getType()) && !StringHelper.isNullOrEmpty(damageType.getName())) {
- vulnerabilities.add(damageType.getName());
+ ArrayList resistances = new ArrayList<>();
+ for (String damageType : damageResistances) {
+ if (!StringHelper.isNullOrEmpty(damageType)) {
+ resistances.add(damageType);
}
}
- Collections.sort(vulnerabilities);
- return StringHelper.oxfordJoin(", ", ", and ", " and ", vulnerabilities);
+ Collections.sort(resistances);
+ return StringHelper.oxfordJoin(", ", ", and ", " and ", resistances);
}
public String getDamageImmunitiesDescription() {
- ArrayList vulnerabilities = new ArrayList<>();
- for (DamageType damageType : mDamageTypes) {
- if (damageType != null && "i".equals(damageType.getType()) && !StringHelper.isNullOrEmpty(damageType.getName())) {
- vulnerabilities.add(damageType.getName());
+ ArrayList immunities = new ArrayList<>();
+ for (String damageType : damageImmunities) {
+ if (!StringHelper.isNullOrEmpty(damageType)) {
+ immunities.add(damageType);
}
}
- Collections.sort(vulnerabilities);
- return StringHelper.oxfordJoin(", ", ", and ", " and ", vulnerabilities);
- }
-
- @Ignore()
- private HashSet mConditionImmunities;
-
- public Set getConditionImmunities() {
- return mConditionImmunities;
- }
-
- public void addConditionImmunity(String condition) {
- // TODO: filter out duplicates
- mConditionImmunities.add(condition);
- }
-
- public void removeConditionImmunity(String condition) {
- // TODO: make sure this works even though we're using strings
- mConditionImmunities.remove(condition);
- }
-
- public void clearConditionImmunities() {
- mConditionImmunities.clear();
- }
-
- public String getConditionImmunitiesDescription() {
- ArrayList immunities = new ArrayList<>(getConditionImmunities());
Collections.sort(immunities);
return StringHelper.oxfordJoin(", ", ", and ", " and ", immunities);
}
- @Ignore()
- private String mBlindsight;
-
- public String getBlindsight() {
- return mBlindsight;
- }
-
- public void setBlindsight(String value) {
- mBlindsight = value;
- }
-
- @Ignore()
- private boolean mIsBlind;
-
- public boolean getIsBlind() {
- return mIsBlind;
- }
-
- public void setIsBlind(boolean value) {
- mIsBlind = value;
- }
-
- @Ignore()
- private String mDarkvision;
-
- public String getDarkvision() {
- return mDarkvision;
- }
-
- public void setDarkvision(String value) {
- mDarkvision = value;
- }
-
- @Ignore()
- private String mTremorsense;
-
- public String getTremorsense() {
- return mTremorsense;
- }
-
- public void setTremorsense(String value) {
- mTremorsense = value;
- }
-
- @Ignore()
- private String mTruesight;
-
- public String getTruesight() {
- return mTruesight;
- }
-
- public void setTruesight(String value) {
- mTruesight = value;
+ public String getConditionImmunitiesDescription() {
+ ArrayList immunities = new ArrayList<>(conditionImmunities);
+ Collections.sort(immunities);
+ return StringHelper.oxfordJoin(", ", ", and ", " and ", immunities);
}
public String getSensesDescription() {
ArrayList parts = new ArrayList<>();
-
- String blindsight = getBlindsight();
- if (!StringHelper.isNullOrEmpty(blindsight) && !"0".equals(blindsight)) {
- parts.add(String.format(Locale.US, "blindsight %s ft.%s", blindsight, getIsBlind() ? " (blind beyond this radius)" : ""));
+ if (blindsightRange > 0) {
+ parts.add(String.format("blindsight %d ft.%s", blindsightRange, isBlindBeyondBlindsightRange ? " (blind beyond this radius)" : ""));
}
- String darkvision = getDarkvision();
- if (!StringHelper.isNullOrEmpty(darkvision) && !"0".equals(darkvision)) {
- parts.add(String.format(Locale.US, "darkvision %s ft.", darkvision));
+ if (darkvisionRange > 0) {
+ parts.add(String.format("darkvision %d ft.", darkvisionRange));
}
- String tremorsense = getTremorsense();
- if (!StringHelper.isNullOrEmpty(tremorsense) && !"0".equals(tremorsense)) {
- parts.add(String.format(Locale.US, "tremorsense %s ft.", tremorsense));
+ if (tremorsenseRange > 0) {
+ parts.add(String.format("tremorsense %d ft.", tremorsenseRange));
}
- String truesight = getTruesight();
- if (!StringHelper.isNullOrEmpty(truesight) && !"0".equals(truesight)) {
- parts.add(String.format(Locale.US, "truesight %s ft.", truesight));
+ if (truesightRange > 0) {
+ parts.add(String.format("truesight %d ft.", truesightRange));
}
- parts.add(String.format(Locale.US, "passive Perception %d", 10 + getWisdomModifier()));
+ parts.add(String.format("passive Perception %d", 10 + getWisdomModifier()));
return StringHelper.join(", ", parts);
}
- @Ignore()
- private HashSet mLanguages;
-
- public Set getLanguages() {
- return mLanguages;
- }
-
- public void addLanguage(Language value) {
- mLanguages.add(value);
- }
-
- public void removeLanguage(Language value) {
- mLanguages.remove(value);
- }
-
- public void clearLanguages() {
- mLanguages.clear();
- }
-
- @Ignore()
- private int mTelepathy;
-
- public int getTelepathy() {
- return mTelepathy;
- }
-
- public void setTelepathy(int value) {
- mTelepathy = value;
- }
-
- @Ignore()
- private String mUnderstandsBut;
-
- public String getUnderstandsBut() {
- return mUnderstandsBut;
- }
-
- public void setUnderstandsBut(String value) {
- mUnderstandsBut = value;
- }
-
public String getLanguagesDescription() {
ArrayList spokenLanguages = new ArrayList<>();
ArrayList understoodLanguages = new ArrayList<>();
- for (Language language : mLanguages) {
+ for (Language language : languages) {
if (language != null) {
if (language.getSpeaks()) {
spokenLanguages.add(language.getName());
@@ -955,11 +666,9 @@ public class Monster {
String spokenLanguagesString = StringHelper.oxfordJoin(", ", ", and ", " and ", spokenLanguages);
String understoodLanguagesString = StringHelper.oxfordJoin(", ", ", and ", " and ", understoodLanguages);
- String understandsBut = getUnderstandsBut();
- boolean hasUnderstandsBut = understandsBut.length() > 0;
- int telepathy = getTelepathy();
- boolean hasTelepathy = telepathy > 0;
- String telepathyString = String.format(Locale.US, ", telepathy %d ft.", telepathy);
+ boolean hasUnderstandsBut = understandsButDescription.length() > 0;
+ boolean hasTelepathy = telepathyRange > 0;
+ String telepathyString = String.format(", telepathy %d ft.", telepathyRange);
if (spokenLanguages.size() > 0) {
if (understoodLanguages.size() > 0) {
@@ -967,13 +676,13 @@ public class Monster {
"%s, understands %s%s%s",
spokenLanguagesString,
understoodLanguagesString,
- hasUnderstandsBut ? " but " + understandsBut : "",
+ hasUnderstandsBut ? " but " + understandsButDescription : "",
hasTelepathy ? telepathyString : "");
} else {
return String.format(
"%s%s%s",
spokenLanguagesString,
- hasUnderstandsBut ? " but " + understandsBut : "",
+ hasUnderstandsBut ? " but " + understandsButDescription : "",
hasTelepathy ? telepathyString : "");
}
} else {
@@ -981,185 +690,95 @@ public class Monster {
return String.format(
"understands %s%s%s",
understoodLanguagesString,
- hasUnderstandsBut ? " but " + understandsBut : "",
+ hasUnderstandsBut ? " but " + understandsButDescription : "",
hasTelepathy ? telepathyString : "");
} else {
return String.format(
"%S%s",
- hasUnderstandsBut ? "none but " + understandsBut : "",
+ hasUnderstandsBut ? "none but " + understandsButDescription : "",
hasTelepathy ? telepathyString : "");
}
}
}
public String getChallengeRatingDescription() {
- String challengeRating = getChallengeRating();
- if ("*".equals(challengeRating)) {
- // Custom CR
- return getCustomChallengeRating();
- } else if ("0".equals(challengeRating)) {
- return "0 (10 XP)";
- } else if ("1/8".equals(challengeRating)) {
- return "1/8 (25 XP)";
- } else if ("1/4".equals(challengeRating)) {
- return "1/4 (50 XP)";
- } else if ("1/2".equals(challengeRating)) {
- return "1/2 (100 XP)";
- } else if ("1".equals(challengeRating)) {
- return "1 (200 XP)";
- } else if ("2".equals(challengeRating)) {
- return "2 (450 XP)";
- } else if ("3".equals(challengeRating)) {
- return "3 (700 XP)";
- } else if ("4".equals(challengeRating)) {
- return "4 (1,100 XP)";
- } else if ("5".equals(challengeRating)) {
- return "5 (1,800 XP)";
- } else if ("6".equals(challengeRating)) {
- return "6 (2,300 XP)";
- } else if ("7".equals(challengeRating)) {
- return "7 (2,900 XP)";
- } else if ("8".equals(challengeRating)) {
- return "8 (3,900 XP)";
- } else if ("9".equals(challengeRating)) {
- return "9 (5,000 XP)";
- } else if ("10".equals(challengeRating)) {
- return "10 (5,900 XP)";
- } else if ("11".equals(challengeRating)) {
- return "11 (7,200 XP)";
- } else if ("12".equals(challengeRating)) {
- return "12 (8,400 XP)";
- } else if ("13".equals(challengeRating)) {
- return "13 (10,000 XP)";
- } else if ("14".equals(challengeRating)) {
- return "14 (11,500 XP)";
- } else if ("15".equals(challengeRating)) {
- return "15 (13,000 XP)";
- } else if ("16".equals(challengeRating)) {
- return "16 (15,000 XP)";
- } else if ("17".equals(challengeRating)) {
- return "17 (18,000 XP)";
- } else if ("18".equals(challengeRating)) {
- return "18 (20,000 XP)";
- } else if ("19".equals(challengeRating)) {
- return "19 (22,000 XP)";
- } else if ("20".equals(challengeRating)) {
- return "20 (25,000 XP)";
- } else if ("21".equals(challengeRating)) {
- return "21 (33,000 XP)";
- } else if ("22".equals(challengeRating)) {
- return "22 (41,000 XP)";
- } else if ("23".equals(challengeRating)) {
- return "23 (50,000 XP)";
- } else if ("24".equals(challengeRating)) {
- return "24 (62,000 XP)";
- } else if ("25".equals(challengeRating)) {
- return "25 (75,000 XP)";
- } else if ("26".equals(challengeRating)) {
- return "26 (90,000 XP)";
- } else if ("27".equals(challengeRating)) {
- return "27 (105,000 XP)";
- } else if ("28".equals(challengeRating)) {
- return "28 (120,000 XP)";
- } else if ("29".equals(challengeRating)) {
- return "29 (135,000 XP)";
- } else if ("30".equals(challengeRating)) {
- return "30 (155,000 XP)";
+ ChallengeRating challengeRating = this.challengeRating != null ? this.challengeRating : ChallengeRating.ONE;
+ if (challengeRating == ChallengeRating.CUSTOM) {
+ return customChallengeRatingDescription;
} else {
- return getCustomChallengeRating();
+ return challengeRating.displayName;
}
}
- @Ignore()
- private ArrayList mAbilities;
-
- public List getAbilities() {
- return mAbilities;
- }
-
- public void addAbility(Ability ability) {
- mAbilities.add(ability);
- }
-
- public void removeAbility(Ability ability) {
- mAbilities.remove(ability);
- }
-
- public void clearAbilities() {
- mAbilities.clear();
- }
-
public List getAbilityDescriptions() {
- ArrayList abilities = new ArrayList<>();
- for (Ability ability : getAbilities()) {
- abilities.add(getPlaceholderReplacedText(String.format("__%s__ %s", ability.getName(), ability.getDescription())));
+ ArrayList abilityDescriptions = new ArrayList<>();
+ for (Trait ability : abilities) {
+ abilityDescriptions.add(getPlaceholderReplacedText(String.format("__%s__ %s", ability.name, ability.description)));
}
- return abilities;
+ return abilityDescriptions;
}
public String getPlaceholderReplacedText(String rawText) {
return rawText
- .replaceAll("\\[STR SAVE]", String.format(Locale.US, "%+d", getSpellSaveDC("strength")))
- .replaceAll("\\[STR ATK]", String.format(Locale.US, "%+d", getAttackBonus("strength")))
- .replaceAll("\\[DEX SAVE]", String.format(Locale.US, "%+d", getSpellSaveDC("dexterity")))
- .replaceAll("\\[DEX ATK]", String.format(Locale.US, "%+d", getAttackBonus("dexterity")))
- .replaceAll("\\[CON SAVE]", String.format(Locale.US, "%+d", getSpellSaveDC("constitution")))
- .replaceAll("\\[CON ATK]", String.format(Locale.US, "%+d", getAttackBonus("constitution")))
- .replaceAll("\\[INT SAVE]", String.format(Locale.US, "%+d", getSpellSaveDC("intelligence")))
- .replaceAll("\\[INT ATK]", String.format(Locale.US, "%+d", getAttackBonus("intelligence")))
- .replaceAll("\\[WIS SAVE]", String.format(Locale.US, "%+d", getSpellSaveDC("wisdom")))
- .replaceAll("\\[WIS ATK]", String.format(Locale.US, "%+d", getAttackBonus("wisdom")))
- .replaceAll("\\[CHA SAVE]", String.format(Locale.US, "%+d", getSpellSaveDC("charisma")))
- .replaceAll("\\[CHA ATK]", String.format(Locale.US, "%+d", getAttackBonus("charisma")));
+ .replaceAll("\\[STR SAVE]", String.format("%+d", getSpellSaveDC(AbilityScore.STRENGTH)))
+ .replaceAll("\\[STR ATK]", String.format("%+d", getAttackBonus(AbilityScore.STRENGTH)))
+ .replaceAll("\\[DEX SAVE]", String.format("%+d", getSpellSaveDC(AbilityScore.DEXTERITY)))
+ .replaceAll("\\[DEX ATK]", String.format("%+d", getAttackBonus(AbilityScore.DEXTERITY)))
+ .replaceAll("\\[CON SAVE]", String.format("%+d", getSpellSaveDC(AbilityScore.CONSTITUTION)))
+ .replaceAll("\\[CON ATK]", String.format("%+d", getAttackBonus(AbilityScore.CONSTITUTION)))
+ .replaceAll("\\[INT SAVE]", String.format("%+d", getSpellSaveDC(AbilityScore.INTELLIGENCE)))
+ .replaceAll("\\[INT ATK]", String.format("%+d", getAttackBonus(AbilityScore.INTELLIGENCE)))
+ .replaceAll("\\[WIS SAVE]", String.format("%+d", getSpellSaveDC(AbilityScore.WISDOM)))
+ .replaceAll("\\[WIS ATK]", String.format("%+d", getAttackBonus(AbilityScore.WISDOM)))
+ .replaceAll("\\[CHA SAVE]", String.format("%+d", getSpellSaveDC(AbilityScore.CHARISMA)))
+ .replaceAll("\\[CHA ATK]", String.format("%+d", getAttackBonus(AbilityScore.CHARISMA)));
}
- public int getSavingThrow(String name) {
- Set sts = getSavingThrows();
- for (SavingThrow st : sts) {
- if (name.equals(st.getName())) {
- return getAbilityModifier(name) + getProficiencyBonus();
- }
- }
- return getAbilityModifier(name);
+ public int getSpellSaveDC(AbilityScore abilityScore) {
+ return 8 + getProficiencyBonus() + getAbilityModifier(abilityScore);
}
- public String getWisdomSave() {
- return String.format(Locale.US, "%+d", getSavingThrow("wis"));
- }
-
- public int getSpellSaveDC(String abilityScoreName) {
- return 8 + getProficiencyBonus() + getAbilityModifier(abilityScoreName);
- }
-
- public int getAttackBonus(String abilityScoreName) {
- return getProficiencyBonus() + getAbilityModifier(abilityScoreName);
+ public int getAttackBonus(AbilityScore abilityScore) {
+ return getProficiencyBonus() + getAbilityModifier(abilityScore);
}
public List getActionDescriptions() {
- ArrayList actions = new ArrayList<>();
- for (Action action : getActions()) {
- actions.add(getPlaceholderReplacedText(String.format("__%s__ %s", action.getName(), action.getDescription())));
+ ArrayList actionDescriptions = new ArrayList<>();
+ for (Trait action : actions) {
+ actionDescriptions.add(getPlaceholderReplacedText(String.format("__%s__ %s", action.name, action.description)));
}
- return actions;
+ return actionDescriptions;
}
- @Ignore()
- private ArrayList mActions;
-
- public List getActions() {
- return mActions;
+ public List getReactionDescriptions() {
+ ArrayList actionDescriptions = new ArrayList<>();
+ for (Trait action : reactions) {
+ actionDescriptions.add(getPlaceholderReplacedText(String.format("__%s__ %s", action.name, action.description)));
+ }
+ return actionDescriptions;
}
- public void addAction(Action ability) {
- mActions.add(ability);
+ public List getLegendaryActionDescriptions() {
+ ArrayList actionDescriptions = new ArrayList<>();
+ for (Trait action : legendaryActions) {
+ actionDescriptions.add(getPlaceholderReplacedText(String.format("__%s__ %s", action.name, action.description)));
+ }
+ return actionDescriptions;
}
- public void removeAction(Action ability) {
- mActions.remove(ability);
+ public List getLairActionDescriptions() {
+ ArrayList actionDescriptions = new ArrayList<>();
+ for (Trait action : lairActions) {
+ actionDescriptions.add(getPlaceholderReplacedText(String.format("__%s__ %s", action.name, action.description)));
+ }
+ return actionDescriptions;
}
- public void clearActions() {
- mActions.clear();
+ public List getRegionalActionDescriptions() {
+ ArrayList actionDescriptions = new ArrayList<>();
+ for (Trait action : regionalActions) {
+ actionDescriptions.add(getPlaceholderReplacedText(String.format("__%s__ %s", action.name, action.description)));
+ }
+ return actionDescriptions;
}
-
}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/models/Skill.java b/app/src/main/java/com/majinnaibu/monstercards/models/Skill.java
index 3580f0e..6553657 100644
--- a/app/src/main/java/com/majinnaibu/monstercards/models/Skill.java
+++ b/app/src/main/java/com/majinnaibu/monstercards/models/Skill.java
@@ -1,70 +1,69 @@
package com.majinnaibu.monstercards.models;
-import java.util.Comparator;
-import java.util.Locale;
+import android.annotation.SuppressLint;
+import com.majinnaibu.monstercards.data.enums.AbilityScore;
+import com.majinnaibu.monstercards.data.enums.AdvantageType;
+import com.majinnaibu.monstercards.data.enums.ProficiencyType;
+
+import java.util.Comparator;
+
+@SuppressLint("DefaultLocale")
public class Skill implements Comparator, Comparable {
- private String mName;
- private String mAbilityScoreName;
- private String mNote;
+ public String name;
+ public AbilityScore abilityScore;
+ public AdvantageType advantageType;
+ public ProficiencyType proficiencyType;
- public Skill(String name, String abilityScoreName) {
- mName = name;
- mAbilityScoreName = abilityScoreName;
- mNote = "";
+ public Skill(String name, AbilityScore abilityScore) {
+ this(name, abilityScore, AdvantageType.NONE, ProficiencyType.PROFICIENT);
}
- public Skill(String name, String abilityScoreName, String note) {
- mName = name;
- mAbilityScoreName = abilityScoreName;
- mNote = note;
+ public Skill(String name, AbilityScore abilityScore, AdvantageType advantageType) {
+ this(name, abilityScore, advantageType, ProficiencyType.PROFICIENT);
}
- public String getName() {
- return mName;
- }
-
- public void setName(String name) {
- mName = name;
- }
-
- public String getAbilityScoreName() {
- return mAbilityScoreName;
- }
-
- public void setAbilityScoreName(String abilityScoreName) {
- mAbilityScoreName = abilityScoreName;
- }
-
- public String getNote() {
- return mNote;
+ public Skill(String name, AbilityScore abilityScore, AdvantageType advantageType, ProficiencyType proficiencyType) {
+ this.name = name;
+ this.abilityScore = abilityScore;
+ this.advantageType = advantageType;
+ this.proficiencyType = proficiencyType;
}
public int getSkillBonus(Monster monster) {
- int bonus = monster.getAbilityModifier(mAbilityScoreName);
- if (" (ex)".equals(getNote())) {
- bonus += 2 * monster.getProficiencyBonus();
- } else {
- bonus += monster.getProficiencyBonus();
+ int modifier = monster.getAbilityModifier(abilityScore);
+ switch (proficiencyType) {
+ case PROFICIENT:
+ return modifier + monster.getProficiencyBonus();
+ case EXPERTISE:
+ return modifier + monster.getProficiencyBonus() * 2;
+ case NONE:
+ default:
+ return modifier;
}
- return bonus;
}
public String getText(Monster monster) {
int bonus = getSkillBonus(monster);
- return String.format(Locale.US, "%s%s %d", mName.substring(0, 1), mName.substring(1), bonus);
+ return String.format(
+ "%s%s %+d%s",
+ name.substring(0, 1),
+ name.substring(1),
+ bonus,
+ advantageType == AdvantageType.ADVANTAGE ? " A" : advantageType == AdvantageType.DISADVANTAGE ? " D" : ""
+ );
}
@Override
public int compareTo(Skill o) {
- return this.getName().compareToIgnoreCase(o.getName());
+ return this.name.compareToIgnoreCase(o.name);
}
@Override
public int compare(Skill o1, Skill o2) {
- return o1.getName().compareToIgnoreCase(o2.getName());
+ return o1.name.compareToIgnoreCase(o2.name);
}
}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/models/Trait.java b/app/src/main/java/com/majinnaibu/monstercards/models/Trait.java
new file mode 100644
index 0000000..61a5c55
--- /dev/null
+++ b/app/src/main/java/com/majinnaibu/monstercards/models/Trait.java
@@ -0,0 +1,12 @@
+package com.majinnaibu.monstercards.models;
+
+public class Trait {
+
+ public String name;
+ public String description;
+
+ public Trait(String name, String description) {
+ this.name = name;
+ this.description = description;
+ }
+}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterFragment.java b/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterFragment.java
index e587b77..d157ea2 100644
--- a/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterFragment.java
+++ b/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterFragment.java
@@ -14,23 +14,21 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
-import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import com.majinnaibu.monstercards.R;
+import com.majinnaibu.monstercards.data.enums.AbilityScore;
+import com.majinnaibu.monstercards.data.enums.AdvantageType;
+import com.majinnaibu.monstercards.data.enums.ArmorType;
+import com.majinnaibu.monstercards.data.enums.ChallengeRating;
+import com.majinnaibu.monstercards.data.enums.ProficiencyType;
import com.majinnaibu.monstercards.helpers.CommonMarkHelper;
import com.majinnaibu.monstercards.helpers.StringHelper;
-import com.majinnaibu.monstercards.models.Ability;
-import com.majinnaibu.monstercards.models.Action;
-import com.majinnaibu.monstercards.models.DamageType;
import com.majinnaibu.monstercards.models.Language;
import com.majinnaibu.monstercards.models.Monster;
-import com.majinnaibu.monstercards.models.SavingThrow;
import com.majinnaibu.monstercards.models.Skill;
-
-import java.util.List;
+import com.majinnaibu.monstercards.models.Trait;
@SuppressWarnings("FieldCanBeLocal")
public class MonsterFragment extends Fragment {
@@ -43,83 +41,96 @@ public class MonsterFragment extends Fragment {
// TODO: remove this block make the monster ID a parameter to the view and get the monster from saved data (sqlite)
Monster monster = new Monster();
// Name
- monster.name ="Pixie";
+ monster.name = "Pixie";
// Meta
- monster.setSize("tiny");
- monster.setType("fey");
- monster.setTag("");
- monster.setAlignment("neutral good");
+ monster.size = "tiny";
+ monster.type = "fey";
+ monster.subtype = "";
+ monster.alignment = "neutral good";
+ monster.armorType = ArmorType.NONE;
// Armor & Armor Class
- monster.setArmorName("none");
- monster.setShieldBonus(0);
- monster.setNaturalArmorBonus(7);
- monster.setOtherArmorDescription("14");
+ monster.shieldBonus = 0;
+ monster.naturalArmorBonus = 7;
+ monster.otherArmorDescription = "14";
// Hit Points
- monster.setHitDice(1);
- monster.setCustomHP(false);
- monster.setHPText("11 (2d8 + 2)");
- monster.setSpeed("10");
- monster.setBurrowSpeed("0");
- monster.setClimbSpeed("0");
- monster.setFlySpeed("30");
- monster.setHover(false);
- monster.setSwimSpeed("0");
- monster.setCustomSpeed(false);
- monster.setSpeedDescription("30 ft., swim 30 ft.");
+ monster.hitDice = 1;
+ monster.hasCustomHP = false;
+ monster.customHPDescription = "11 (2d8 + 2)";
+ monster.walkSpeed = 10;
+ monster.burrowSpeed = 0;
+ monster.climbSpeed = 0;
+ monster.flySpeed = 30;
+ monster.canHover = false;
+ monster.swimSpeed = 0;
+ monster.hasCustomSpeed = false;
+ monster.customSpeedDescription = "30 ft., swim 30 ft.";
// Ability Scores
- monster.setStrengthScore(Integer.parseInt("2"));
- monster.setDexterityScore(Integer.parseInt("20"));
- monster.setConstitutionScore(Integer.parseInt("8"));
- monster.setIntelligenceScore(Integer.parseInt("10"));
- monster.setWisdomScore(Integer.parseInt("14"));
- monster.setCharismaScore(Integer.parseInt("15"));
+ monster.strengthScore = Integer.parseInt("2");
+ monster.dexterityScore = Integer.parseInt("20");
+ monster.constitutionScore = Integer.parseInt("8");
+ monster.intelligenceScore = Integer.parseInt("10");
+ monster.wisdomScore = Integer.parseInt("14");
+ monster.charismaScore = Integer.parseInt("15");
+// monster.strengthScore = 10;
+// monster.dexterityScore = 10;
+// monster.constitutionScore = 10;
+// monster.intelligenceScore = 10;
+// monster.wisdomScore = 10;
+// monster.charismaScore = 10;
+
// Saving Throws
- monster.addSavingThrow(new SavingThrow("str", 0));
- monster.addSavingThrow(new SavingThrow("dex", 1));
- monster.addSavingThrow(new SavingThrow("con", 2));
- monster.addSavingThrow(new SavingThrow("int", 3));
- monster.addSavingThrow(new SavingThrow("wis", 4));
- monster.addSavingThrow(new SavingThrow("cha", 5));
+ monster.strengthSavingThrowAdvantage = AdvantageType.NONE;
+ monster.strengthSavingThrowProficiency = ProficiencyType.NONE;
+ monster.dexteritySavingThrowAdvantage = AdvantageType.ADVANTAGE;
+ monster.dexteritySavingThrowProficiency = ProficiencyType.PROFICIENT;
+ monster.constitutionSavingThrowAdvantage = AdvantageType.DISADVANTAGE;
+ monster.constitutionSavingThrowProficiency = ProficiencyType.EXPERTISE;
+ monster.intelligenceSavingThrowAdvantage = AdvantageType.NONE;
+ monster.intelligenceSavingThrowProficiency = ProficiencyType.EXPERTISE;
+ monster.wisdomSavingThrowAdvantage = AdvantageType.ADVANTAGE;
+ monster.wisdomSavingThrowProficiency = ProficiencyType.PROFICIENT;
+ monster.charismaSavingThrowAdvantage = AdvantageType.DISADVANTAGE;
+ monster.charismaSavingThrowProficiency = ProficiencyType.NONE;
//Skills
- monster.addSkill(new Skill("perception", "wis"));
- monster.addSkill(new Skill("stealth", "dexterity"));
+ monster.skills.add(new Skill("perception", AbilityScore.WISDOM));
+ monster.skills.add(new Skill("stealth", AbilityScore.DEXTERITY));
// Damage Types
- monster.addDamageType(new DamageType("acid", " (Vulnerable)", "v"));
- monster.addDamageType(new DamageType("bludgeoning", " (Vulnerable)", "v"));
- monster.addDamageType(new DamageType("cold", " (Resistant)", "r"));
- monster.addDamageType(new DamageType("fire", " (Resistant)", "r"));
- monster.addDamageType(new DamageType("force", " (Immune)", "i"));
- monster.addDamageType(new DamageType("lightning", " (Immune)", "i"));
- monster.addDamageType(new DamageType("necrotic", " (Vulnerable)", "v"));
- monster.addDamageType(new DamageType("piercing", " (Resistant)", "r"));
- monster.addDamageType(new DamageType("poison", " (Immune)", "i"));
+ monster.damageImmunities.add("force");
+ monster.damageImmunities.add("lightning");
+ monster.damageImmunities.add("poison");
+ monster.damageResistances.add("cold");
+ monster.damageResistances.add("fire");
+ monster.damageResistances.add("piercing");
+ monster.damageVulnerabilities.add("acid");
+ monster.damageVulnerabilities.add("bludgeoning");
+ monster.damageVulnerabilities.add("necrotic");
// Condition Immunities
- monster.addConditionImmunity("blinded");
+ monster.conditionImmunities.add("blinded");
// Senses
- monster.setBlindsight("10");
- monster.setIsBlind(true);
- monster.setDarkvision("20");
- monster.setTremorsense("30");
- monster.setTruesight("40");
- monster.setTelepathy(20);
- monster.setUnderstandsBut("doesn't care");
+ monster.blindsightRange = 10;
+ monster.isBlindBeyondBlindsightRange = true;
+ monster.darkvisionRange = 20;
+ monster.tremorsenseRange = 30;
+ monster.truesightRange = 40;
+ monster.telepathyRange = 20;
+ monster.understandsButDescription = "doesn't care";
// Languages
- monster.addLanguage(new Language("English", true));
- monster.addLanguage(new Language("Steve", false));
- monster.addLanguage(new Language("Spanish", true));
- monster.addLanguage(new Language("French", true));
- monster.addLanguage(new Language("Mermataur", false));
- monster.addLanguage(new Language("Goldfish", false));
+ monster.languages.add(new Language("English", true));
+ monster.languages.add(new Language("Steve", false));
+ monster.languages.add(new Language("Spanish", true));
+ monster.languages.add(new Language("French", true));
+ monster.languages.add(new Language("Mermataur", false));
+ monster.languages.add(new Language("Goldfish", false));
// Challenge Rating
- monster.setChallengeRating("*");
- monster.setCustomChallengeRating("Infinite (0XP)");
- monster.setCustomProficiencyBonus(4);
+ monster.challengeRating = ChallengeRating.CUSTOM;
+ monster.customChallengeRatingDescription = "Infinite (0XP)";
+ monster.customProficiencyBonus = 4;
// Abilities
- monster.addAbility(new Ability("Spellcasting", "The acolyte is a 1st-level spellcaster. Its spellcasting ability is Wisdom (spell save DC [WIS SAVE], [WIS ATK] to hit with spell attacks). The acolyte has following cleric spells prepared:\n\n\n> Cantrips (at will): _light, sacred flame, thaumaturgy_\n> 1st level (3 slots): _bless, cure wounds, sanctuary_"));
- monster.addAbility(new Ability("Amphibious", "The dragon can breathe air and water."));
- monster.addAbility(new Ability("Legendary Resistance (3/Day)", "If the dragon fails a saving throw, it can choose to succeed instead."));
+ monster.abilities.add(new Trait("Spellcasting", "The acolyte is a 1st-level spellcaster. Its spellcasting ability is Wisdom (spell save DC [WIS SAVE], [WIS ATK] to hit with spell attacks). The acolyte has following cleric spells prepared:\n\n\n> Cantrips (at will): _light, sacred flame, thaumaturgy_\n> 1st level (3 slots): _bless, cure wounds, sanctuary_"));
+ monster.abilities.add(new Trait("Amphibious", "The dragon can breathe air and water."));
+ monster.abilities.add(new Trait("Legendary Resistance (3/Day)", "If the dragon fails a saving throw, it can choose to succeed instead."));
// Actions
- monster.addAction(new Action("Club", "_Melee Weapon Attack:_ [STR ATK] to hit, reach 5 ft., one target. _Hit:_ 2 (1d4) bludgeoning damage."));
+ monster.actions.add(new Trait("Club", "_Melee Weapon Attack:_ [STR ATK] to hit, reach 5 ft., one target. _Hit:_ 2 (1d4) bludgeoning damage."));
// END remove block
monsterViewModel = new ViewModelProvider(this).get(MonsterViewModel.class);
@@ -127,256 +138,166 @@ public class MonsterFragment extends Fragment {
monsterViewModel.setMonster(monster);
final TextView monsterName = root.findViewById(R.id.name);
- monsterViewModel.getName().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(@Nullable String name) {
- monsterName.setText(name);
- }
- });
+ monsterViewModel.getName().observe(getViewLifecycleOwner(), name -> monsterName.setText(name));
final TextView monsterMeta = root.findViewById(R.id.meta);
- monsterViewModel.getMeta().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(@Nullable String metaText) {
- monsterMeta.setText(metaText);
- }
- });
+ monsterViewModel.getMeta().observe(getViewLifecycleOwner(), metaText -> monsterMeta.setText(metaText));
final TextView monsterArmorClass = root.findViewById(R.id.armor_class);
- monsterViewModel.getArmorClass().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(@Nullable String armorText) {
- monsterArmorClass.setText(Html.fromHtml("Armor Class " + armorText));
- }
- });
+ monsterViewModel.getArmorClass().observe(getViewLifecycleOwner(), armorText -> monsterArmorClass.setText(Html.fromHtml("Armor Class " + armorText)));
final TextView monsterHitPoints = root.findViewById(R.id.hit_points);
- monsterViewModel.getHitPoints().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String hitPoints) {
- monsterHitPoints.setText(Html.fromHtml("Hit Points " + hitPoints));
- }
- });
+ monsterViewModel.getHitPoints().observe(getViewLifecycleOwner(), hitPoints -> monsterHitPoints.setText(Html.fromHtml("Hit Points " + hitPoints)));
final TextView monsterSpeed = root.findViewById(R.id.speed);
- monsterViewModel.getSpeed().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String speed) {
- monsterSpeed.setText(Html.fromHtml("Speed " + speed));
- }
- });
+ monsterViewModel.getSpeed().observe(getViewLifecycleOwner(), speed -> monsterSpeed.setText(Html.fromHtml("Speed " + speed)));
final TextView monsterStrength = root.findViewById(R.id.strength);
- monsterViewModel.getStrength().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String strength) {
- monsterStrength.setText(strength);
- }
- });
+ monsterViewModel.getStrength().observe(getViewLifecycleOwner(), strength -> monsterStrength.setText(strength));
final TextView monsterDexterity = root.findViewById(R.id.dexterity);
- monsterViewModel.getDexterity().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String dexterity) {
- monsterDexterity.setText(dexterity);
- }
- });
+ monsterViewModel.getDexterity().observe(getViewLifecycleOwner(), dexterity -> monsterDexterity.setText(dexterity));
final TextView monsterConstitution = root.findViewById(R.id.constitution);
- monsterViewModel.getConstitution().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String constitution) {
- monsterConstitution.setText(constitution);
- }
- });
+ monsterViewModel.getConstitution().observe(getViewLifecycleOwner(), constitution -> monsterConstitution.setText(constitution));
final TextView monsterIntelligence = root.findViewById(R.id.intelligence);
- monsterViewModel.getIntelligence().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String intelligence) {
- monsterIntelligence.setText(intelligence);
- }
- });
+ monsterViewModel.getIntelligence().observe(getViewLifecycleOwner(), intelligence -> monsterIntelligence.setText(intelligence));
final TextView monsterWisdom = root.findViewById(R.id.wisdom);
- monsterViewModel.getWisdom().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String wisdom) {
- monsterWisdom.setText(wisdom);
- }
- });
+ monsterViewModel.getWisdom().observe(getViewLifecycleOwner(), wisdom -> monsterWisdom.setText(wisdom));
final TextView monsterCharisma = root.findViewById(R.id.charisma);
- monsterViewModel.getCharisma().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String charisma) {
- monsterCharisma.setText(charisma);
- }
- });
+ monsterViewModel.getCharisma().observe(getViewLifecycleOwner(), charisma -> monsterCharisma.setText(charisma));
final TextView monsterSavingThrows = root.findViewById(R.id.saving_throws);
- monsterViewModel.getSavingThrows().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String savingThrows) {
- if (StringHelper.isNullOrEmpty(savingThrows)) {
- monsterSavingThrows.setVisibility(View.GONE);
- } else {
- monsterSavingThrows.setVisibility(View.VISIBLE);
- }
- monsterSavingThrows.setText(Html.fromHtml("Saving Throws " + savingThrows));
+ monsterViewModel.getSavingThrows().observe(getViewLifecycleOwner(), savingThrows -> {
+ if (StringHelper.isNullOrEmpty(savingThrows)) {
+ monsterSavingThrows.setVisibility(View.GONE);
+ } else {
+ monsterSavingThrows.setVisibility(View.VISIBLE);
}
+ monsterSavingThrows.setText(Html.fromHtml("Saving Throws " + savingThrows));
});
final TextView monsterSkills = root.findViewById(R.id.skills);
- monsterViewModel.getSkills().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String skills) {
- if (StringHelper.isNullOrEmpty(skills)) {
- monsterSkills.setVisibility(View.GONE);
- } else {
- monsterSkills.setVisibility(View.VISIBLE);
- }
- monsterSkills.setText(Html.fromHtml("Skills " + skills));
+ monsterViewModel.getSkills().observe(getViewLifecycleOwner(), skills -> {
+ if (StringHelper.isNullOrEmpty(skills)) {
+ monsterSkills.setVisibility(View.GONE);
+ } else {
+ monsterSkills.setVisibility(View.VISIBLE);
}
+ monsterSkills.setText(Html.fromHtml("Skills " + skills));
});
final TextView monsterDamageVulnerabilities = root.findViewById(R.id.damage_vulnerabilities);
- monsterViewModel.getDamageVulnerabilities().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String damageType) {
- if (StringHelper.isNullOrEmpty(damageType)) {
- monsterDamageVulnerabilities.setVisibility(View.GONE);
- } else {
- monsterDamageVulnerabilities.setVisibility(View.VISIBLE);
- }
- monsterDamageVulnerabilities.setText(Html.fromHtml("Damage Vulnerabilities " + damageType));
+ monsterViewModel.getDamageVulnerabilities().observe(getViewLifecycleOwner(), damageType -> {
+ if (StringHelper.isNullOrEmpty(damageType)) {
+ monsterDamageVulnerabilities.setVisibility(View.GONE);
+ } else {
+ monsterDamageVulnerabilities.setVisibility(View.VISIBLE);
}
+ monsterDamageVulnerabilities.setText(Html.fromHtml("Damage Vulnerabilities " + damageType));
});
final TextView monsterDamageResistances = root.findViewById(R.id.damage_resistances);
- monsterViewModel.getDamageResistances().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String damageType) {
- if (StringHelper.isNullOrEmpty(damageType)) {
- monsterDamageResistances.setVisibility(View.GONE);
- } else {
- monsterDamageResistances.setVisibility(View.VISIBLE);
- }
- monsterDamageResistances.setText(Html.fromHtml("Damage Resistances " + damageType));
+ monsterViewModel.getDamageResistances().observe(getViewLifecycleOwner(), damageType -> {
+ if (StringHelper.isNullOrEmpty(damageType)) {
+ monsterDamageResistances.setVisibility(View.GONE);
+ } else {
+ monsterDamageResistances.setVisibility(View.VISIBLE);
}
+ monsterDamageResistances.setText(Html.fromHtml("Damage Resistances " + damageType));
});
final TextView monsterDamageImmunities = root.findViewById(R.id.damage_immunities);
- monsterViewModel.getDamageImmunities().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String damageType) {
- if (StringHelper.isNullOrEmpty(damageType)) {
- monsterDamageImmunities.setVisibility(View.GONE);
- } else {
- monsterDamageImmunities.setVisibility(View.VISIBLE);
- }
- monsterDamageImmunities.setText(Html.fromHtml("Damage Immunities " + damageType));
+ monsterViewModel.getDamageImmunities().observe(getViewLifecycleOwner(), damageType -> {
+ if (StringHelper.isNullOrEmpty(damageType)) {
+ monsterDamageImmunities.setVisibility(View.GONE);
+ } else {
+ monsterDamageImmunities.setVisibility(View.VISIBLE);
}
+ monsterDamageImmunities.setText(Html.fromHtml("Damage Immunities " + damageType));
});
final TextView monsterConditionImmunities = root.findViewById(R.id.condition_immunities);
- monsterViewModel.getConditionImmunities().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String conditionImmunities) {
- if (StringHelper.isNullOrEmpty(conditionImmunities)) {
- monsterConditionImmunities.setVisibility(View.GONE);
- } else {
- monsterConditionImmunities.setVisibility(View.VISIBLE);
- }
- monsterConditionImmunities.setText(Html.fromHtml("Condition Immunities " + conditionImmunities));
+ monsterViewModel.getConditionImmunities().observe(getViewLifecycleOwner(), conditionImmunities -> {
+ if (StringHelper.isNullOrEmpty(conditionImmunities)) {
+ monsterConditionImmunities.setVisibility(View.GONE);
+ } else {
+ monsterConditionImmunities.setVisibility(View.VISIBLE);
}
+ monsterConditionImmunities.setText(Html.fromHtml("Condition Immunities " + conditionImmunities));
});
final TextView monsterSenses = root.findViewById(R.id.senses);
- monsterViewModel.getSenses().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String senses) {
- if (StringHelper.isNullOrEmpty(senses)) {
- monsterSenses.setVisibility(View.GONE);
- } else {
- monsterSenses.setVisibility(View.VISIBLE);
- }
- monsterSenses.setText(Html.fromHtml("Senses " + senses));
+ monsterViewModel.getSenses().observe(getViewLifecycleOwner(), senses -> {
+ if (StringHelper.isNullOrEmpty(senses)) {
+ monsterSenses.setVisibility(View.GONE);
+ } else {
+ monsterSenses.setVisibility(View.VISIBLE);
}
+ monsterSenses.setText(Html.fromHtml("Senses " + senses));
});
final TextView monsterLanguages = root.findViewById(R.id.languages);
- monsterViewModel.getLanguages().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String languages) {
- if (StringHelper.isNullOrEmpty(languages)) {
- monsterLanguages.setVisibility(View.GONE);
- } else {
- monsterLanguages.setVisibility(View.VISIBLE);
- }
- monsterLanguages.setText(Html.fromHtml("Languages " + languages));
+ monsterViewModel.getLanguages().observe(getViewLifecycleOwner(), languages -> {
+ if (StringHelper.isNullOrEmpty(languages)) {
+ monsterLanguages.setVisibility(View.GONE);
+ } else {
+ monsterLanguages.setVisibility(View.VISIBLE);
}
+ monsterLanguages.setText(Html.fromHtml("Languages " + languages));
});
final TextView monsterChallenge = root.findViewById(R.id.challenge);
- monsterViewModel.getChallenge().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String challengeRating) {
- monsterChallenge.setText(Html.fromHtml("Challenge " + challengeRating));
- }
- });
+ monsterViewModel.getChallenge().observe(getViewLifecycleOwner(), challengeRating -> monsterChallenge.setText(Html.fromHtml("Challenge " + challengeRating)));
final LinearLayout monsterAbilities = root.findViewById(R.id.abilities);
- monsterViewModel.getAbilities().observe(getViewLifecycleOwner(), new Observer>() {
- @Override
- public void onChanged(List abilities) {
- Context context = getContext();
- DisplayMetrics displayMetrics = null;
- if (context != null) {
- Resources resources = context.getResources();
- if (resources != null) {
- displayMetrics = resources.getDisplayMetrics();
- }
+ monsterViewModel.getAbilities().observe(getViewLifecycleOwner(), abilities -> {
+ Context context = getContext();
+ DisplayMetrics displayMetrics = null;
+ if (context != null) {
+ Resources resources = context.getResources();
+ if (resources != null) {
+ displayMetrics = resources.getDisplayMetrics();
}
- monsterAbilities.removeAllViews();
- if (abilities != null) {
- for (String ability : abilities) {
- TextView tvAbility = new TextView(context);
- // TODO: Handle multiline block quotes specially so they stay multiline.
- // TODO: Replace QuoteSpans in the result of fromHtml with something like this https://stackoverflow.com/questions/7717567/how-to-style-blockquotes-in-android-textviews to make them indent as expected
- Spanned spannedText = Html.fromHtml(CommonMarkHelper.toHtml(ability));
- tvAbility.setText(spannedText);
- LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- layoutParams.topMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, displayMetrics);
- tvAbility.setLayoutParams(layoutParams);
- monsterAbilities.addView(tvAbility);
- }
+ }
+ monsterAbilities.removeAllViews();
+ if (abilities != null) {
+ for (String ability : abilities) {
+ TextView tvAbility = new TextView(context);
+ // TODO: Handle multiline block quotes specially so they stay multiline.
+ // TODO: Replace QuoteSpans in the result of fromHtml with something like this https://stackoverflow.com/questions/7717567/how-to-style-blockquotes-in-android-textviews to make them indent as expected
+ Spanned spannedText = Html.fromHtml(CommonMarkHelper.toHtml(ability));
+ tvAbility.setText(spannedText);
+ LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ layoutParams.topMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, displayMetrics);
+ tvAbility.setLayoutParams(layoutParams);
+ monsterAbilities.addView(tvAbility);
}
}
});
final LinearLayout monsterActions = root.findViewById(R.id.actions);
- monsterViewModel.getActions().observe(getViewLifecycleOwner(), new Observer>() {
- @Override
- public void onChanged(List actions) {
- Context context = getContext();
- DisplayMetrics displayMetrics = null;
- if (context != null) {
- Resources resources = context.getResources();
- if (resources != null) {
- displayMetrics = resources.getDisplayMetrics();
- }
+ monsterViewModel.getActions().observe(getViewLifecycleOwner(), actions -> {
+ Context context = getContext();
+ DisplayMetrics displayMetrics = null;
+ if (context != null) {
+ Resources resources = context.getResources();
+ if (resources != null) {
+ displayMetrics = resources.getDisplayMetrics();
}
- monsterActions.removeAllViews();
- if (actions != null) {
- for (String action : actions) {
- TextView tvAction = new TextView(getContext());
- tvAction.setText(Html.fromHtml(CommonMarkHelper.toHtml(action)));
- LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- layoutParams.topMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, displayMetrics);
- tvAction.setLayoutParams(layoutParams);
- monsterActions.addView(tvAction);
- }
+ }
+ monsterActions.removeAllViews();
+ if (actions != null) {
+ for (String action : actions) {
+ TextView tvAction = new TextView(getContext());
+ tvAction.setText(Html.fromHtml(CommonMarkHelper.toHtml(action)));
+ LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ layoutParams.topMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, displayMetrics);
+ tvAction.setLayoutParams(layoutParams);
+ monsterActions.addView(tvAction);
}
}
});