Updates monster imports from tetra cube.
This commit is contained in:
@@ -0,0 +1,663 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 6,
|
||||
"identityHash": "0ab331e246de46304f847d7ed2d10124",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "monsters",
|
||||
"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, `telepathy_range` INTEGER NOT NULL DEFAULT 0, `understands_but_description` TEXT DEFAULT '', `senses` TEXT DEFAULT '[]', `skills` TEXT DEFAULT '[]', `damage_immunities` TEXT DEFAULT '[]', `damage_resistances` TEXT DEFAULT '[]', `damage_vulnerabilities` TEXT DEFAULT '[]', `condition_immunities` TEXT DEFAULT '[]', `languages` TEXT DEFAULT '[]', `abilities` TEXT DEFAULT '[]', `actions` TEXT DEFAULT '[]', `reactions` TEXT DEFAULT '[]', `lair_actions` TEXT DEFAULT '[]', `legendary_actions` TEXT DEFAULT '[]', `regional_actions` TEXT DEFAULT '[]', `source_url` TEXT DEFAULT '', `bonus_actions` TEXT DEFAULT '[]', `mythic_actions` TEXT DEFAULT '[]', `legendary_actions_description` TEXT DEFAULT '', `lair_actions_description` TEXT DEFAULT '', `lair_actions_end_note` TEXT DEFAULT '', `regional_actions_description` TEXT DEFAULT '', `regional_actions_end_note` TEXT DEFAULT '', `mythic_actions_description` TEXT DEFAULT '', PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"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",
|
||||
"defaultValue": "'none'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "strengthSavingThrowProficiency",
|
||||
"columnName": "strength_saving_throw_proficiency",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'none'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "dexterityScore",
|
||||
"columnName": "dexterity_score",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "10"
|
||||
},
|
||||
{
|
||||
"fieldPath": "dexteritySavingThrowAdvantage",
|
||||
"columnName": "dexterity_saving_throw_advantage",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'none'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "dexteritySavingThrowProficiency",
|
||||
"columnName": "dexterity_saving_throw_proficiency",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'none'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "constitutionScore",
|
||||
"columnName": "constitution_score",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "10"
|
||||
},
|
||||
{
|
||||
"fieldPath": "constitutionSavingThrowAdvantage",
|
||||
"columnName": "constitution_saving_throw_advantage",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'none'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "constitutionSavingThrowProficiency",
|
||||
"columnName": "constitution_saving_throw_proficiency",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'none'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "intelligenceScore",
|
||||
"columnName": "intelligence_score",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "10"
|
||||
},
|
||||
{
|
||||
"fieldPath": "intelligenceSavingThrowAdvantage",
|
||||
"columnName": "intelligence_saving_throw_advantage",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'none'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "intelligenceSavingThrowProficiency",
|
||||
"columnName": "intelligence_saving_throw_proficiency",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'none'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "wisdomScore",
|
||||
"columnName": "wisdom_score",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "10"
|
||||
},
|
||||
{
|
||||
"fieldPath": "wisdomSavingThrowAdvantage",
|
||||
"columnName": "wisdom_saving_throw_advantage",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'none'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "wisdomSavingThrowProficiency",
|
||||
"columnName": "wisdom_saving_throw_proficiency",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'none'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "charismaScore",
|
||||
"columnName": "charisma_score",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "10"
|
||||
},
|
||||
{
|
||||
"fieldPath": "charismaSavingThrowAdvantage",
|
||||
"columnName": "charisma_saving_throw_advantage",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'none'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "charismaSavingThrowProficiency",
|
||||
"columnName": "charisma_saving_throw_proficiency",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'none'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "armorType",
|
||||
"columnName": "armor_type",
|
||||
"affinity": "TEXT",
|
||||
"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",
|
||||
"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",
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"fieldPath": "challengeRating",
|
||||
"columnName": "challenge_rating",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'1'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "customChallengeRatingDescription",
|
||||
"columnName": "custom_challenge_rating_description",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "''"
|
||||
},
|
||||
{
|
||||
"fieldPath": "customProficiencyBonus",
|
||||
"columnName": "custom_proficiency_bonus",
|
||||
"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",
|
||||
"defaultValue": "''"
|
||||
},
|
||||
{
|
||||
"fieldPath": "senses",
|
||||
"columnName": "senses",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'[]'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "skills",
|
||||
"columnName": "skills",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'[]'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "damageImmunities",
|
||||
"columnName": "damage_immunities",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'[]'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "damageResistances",
|
||||
"columnName": "damage_resistances",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'[]'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "damageVulnerabilities",
|
||||
"columnName": "damage_vulnerabilities",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'[]'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "conditionImmunities",
|
||||
"columnName": "condition_immunities",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'[]'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "languages",
|
||||
"columnName": "languages",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'[]'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "abilities",
|
||||
"columnName": "abilities",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'[]'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "actions",
|
||||
"columnName": "actions",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'[]'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "reactions",
|
||||
"columnName": "reactions",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'[]'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lairActions",
|
||||
"columnName": "lair_actions",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'[]'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "legendaryActions",
|
||||
"columnName": "legendary_actions",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'[]'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "regionalActions",
|
||||
"columnName": "regional_actions",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'[]'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sourceUrl",
|
||||
"columnName": "source_url",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "''"
|
||||
},
|
||||
{
|
||||
"fieldPath": "bonusActions",
|
||||
"columnName": "bonus_actions",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'[]'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "mythicActions",
|
||||
"columnName": "mythic_actions",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "'[]'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "legendaryActionsDescription",
|
||||
"columnName": "legendary_actions_description",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "''"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lairActionsDescription",
|
||||
"columnName": "lair_actions_description",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "''"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lairActionsEndNote",
|
||||
"columnName": "lair_actions_end_note",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "''"
|
||||
},
|
||||
{
|
||||
"fieldPath": "regionalActionsDescription",
|
||||
"columnName": "regional_actions_description",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "''"
|
||||
},
|
||||
{
|
||||
"fieldPath": "regionalActionsEndNote",
|
||||
"columnName": "regional_actions_end_note",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "''"
|
||||
},
|
||||
{
|
||||
"fieldPath": "mythicActionsDescription",
|
||||
"columnName": "mythic_actions_description",
|
||||
"affinity": "TEXT",
|
||||
"defaultValue": "''"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "monsters_fts",
|
||||
"createSql": "CREATE VIRTUAL TABLE IF NOT EXISTS `${TABLE_NAME}` USING FTS4(`name` TEXT, `size` TEXT, `type` TEXT, `subtype` TEXT, `alignment` TEXT, content=`monsters`)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "size",
|
||||
"columnName": "size",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "subtype",
|
||||
"columnName": "subtype",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "alignment",
|
||||
"columnName": "alignment",
|
||||
"affinity": "TEXT"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": []
|
||||
},
|
||||
"ftsVersion": "FTS4",
|
||||
"ftsOptions": {
|
||||
"tokenizer": "simple",
|
||||
"tokenizerArgs": [],
|
||||
"contentTable": "monsters",
|
||||
"languageIdColumnName": "",
|
||||
"matchInfo": "FTS4",
|
||||
"notIndexedColumns": [],
|
||||
"prefixSizes": [],
|
||||
"preferredOrder": "ASC"
|
||||
},
|
||||
"contentSyncTriggers": [
|
||||
"CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_monsters_fts_BEFORE_UPDATE BEFORE UPDATE ON `monsters` BEGIN DELETE FROM `monsters_fts` WHERE `docid`=OLD.`rowid`; END",
|
||||
"CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_monsters_fts_BEFORE_DELETE BEFORE DELETE ON `monsters` BEGIN DELETE FROM `monsters_fts` WHERE `docid`=OLD.`rowid`; END",
|
||||
"CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_monsters_fts_AFTER_UPDATE AFTER UPDATE ON `monsters` BEGIN INSERT INTO `monsters_fts`(`docid`, `name`, `size`, `type`, `subtype`, `alignment`) VALUES (NEW.`rowid`, NEW.`name`, NEW.`size`, NEW.`type`, NEW.`subtype`, NEW.`alignment`); END",
|
||||
"CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_monsters_fts_AFTER_INSERT AFTER INSERT ON `monsters` BEGIN INSERT INTO `monsters_fts`(`docid`, `name`, `size`, `type`, `subtype`, `alignment`) VALUES (NEW.`rowid`, NEW.`name`, NEW.`size`, NEW.`type`, NEW.`subtype`, NEW.`alignment`); END"
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "collections",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL DEFAULT '', `description` TEXT NOT NULL DEFAULT '', PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true,
|
||||
"defaultValue": "''"
|
||||
},
|
||||
{
|
||||
"fieldPath": "description",
|
||||
"columnName": "description",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true,
|
||||
"defaultValue": "''"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "collection_monsters",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `collection_id` TEXT NOT NULL, `monster_id` TEXT NOT NULL, `ordinal` INTEGER NOT NULL DEFAULT 0, FOREIGN KEY(`collection_id`) REFERENCES `collections`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`monster_id`) REFERENCES `monsters`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "collectionId",
|
||||
"columnName": "collection_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "monsterId",
|
||||
"columnName": "monster_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "ordinal",
|
||||
"columnName": "ordinal",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "0"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_collection_monsters_collection_id",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"collection_id"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_collection_monsters_collection_id` ON `${TABLE_NAME}` (`collection_id`)"
|
||||
},
|
||||
{
|
||||
"name": "index_collection_monsters_monster_id",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"monster_id"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_collection_monsters_monster_id` ON `${TABLE_NAME}` (`monster_id`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "collections",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"collection_id"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
},
|
||||
{
|
||||
"table": "monsters",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"monster_id"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "dashboard_monsters",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `monster_id` TEXT NOT NULL, `ordinal` INTEGER NOT NULL DEFAULT 0, FOREIGN KEY(`monster_id`) REFERENCES `monsters`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "monsterId",
|
||||
"columnName": "monster_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "ordinal",
|
||||
"columnName": "ordinal",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "0"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_dashboard_monsters_monster_id",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"monster_id"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_dashboard_monsters_monster_id` ON `${TABLE_NAME}` (`monster_id`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "monsters",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"monster_id"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"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, '0ab331e246de46304f847d7ed2d10124')"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import com.majinnaibu.monstercards.models.DashboardMonster;
|
||||
import com.majinnaibu.monstercards.models.Monster;
|
||||
import com.majinnaibu.monstercards.models.MonsterFTS;
|
||||
|
||||
@Database(entities = {Monster.class, MonsterFTS.class, Collection.class, CollectionMonster.class, DashboardMonster.class}, version = 5)
|
||||
@Database(entities = {Monster.class, MonsterFTS.class, Collection.class, CollectionMonster.class, DashboardMonster.class}, version = 6)
|
||||
@TypeConverters({
|
||||
ArmorTypeConverter.class,
|
||||
ChallengeRatingConverter.class,
|
||||
|
||||
@@ -52,6 +52,20 @@ public class MonsterCardsApplication extends Application {
|
||||
database.execSQL("INSERT INTO dashboard_monsters(monster_id, ordinal) SELECT id, 0 FROM monsters");
|
||||
}
|
||||
};
|
||||
private static final Migration MIGRATION_5_6 = new Migration(5, 6) {
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
database.execSQL("ALTER TABLE monsters ADD COLUMN `source_url` TEXT DEFAULT ''");
|
||||
database.execSQL("ALTER TABLE monsters ADD COLUMN `bonus_actions` TEXT DEFAULT '[]'");
|
||||
database.execSQL("ALTER TABLE monsters ADD COLUMN `mythic_actions` TEXT DEFAULT '[]'");
|
||||
database.execSQL("ALTER TABLE monsters ADD COLUMN `legendary_actions_description` TEXT DEFAULT ''");
|
||||
database.execSQL("ALTER TABLE monsters ADD COLUMN `lair_actions_description` TEXT DEFAULT ''");
|
||||
database.execSQL("ALTER TABLE monsters ADD COLUMN `lair_actions_end_note` TEXT DEFAULT ''");
|
||||
database.execSQL("ALTER TABLE monsters ADD COLUMN `regional_actions_description` TEXT DEFAULT ''");
|
||||
database.execSQL("ALTER TABLE monsters ADD COLUMN `regional_actions_end_note` TEXT DEFAULT ''");
|
||||
database.execSQL("ALTER TABLE monsters ADD COLUMN `mythic_actions_description` TEXT DEFAULT ''");
|
||||
}
|
||||
};
|
||||
private MonsterRepository m_monsterLibraryRepository;
|
||||
|
||||
|
||||
@@ -75,6 +89,7 @@ public class MonsterCardsApplication extends Application {
|
||||
.addMigrations(MIGRATION_2_3)
|
||||
.addMigrations(MIGRATION_3_4)
|
||||
.addMigrations(MIGRATION_4_5)
|
||||
.addMigrations(MIGRATION_5_6)
|
||||
.fallbackToDestructiveMigrationOnDowngrade()
|
||||
// .fallbackToDestructiveMigration()
|
||||
.build();
|
||||
|
||||
@@ -36,7 +36,9 @@ public class TetraCubeMonsterImporter implements EntityImporter<Monster> {
|
||||
return false;
|
||||
}
|
||||
JsonObject rootDict = element.getAsJsonObject();
|
||||
return rootDict.has("hitDice") || rootDict.has("armorName") || rootDict.has("strPoints");
|
||||
return rootDict.has("hitDice") || rootDict.has("armorName") || rootDict.has("strPoints")
|
||||
|| rootDict.has("bonusActions") || rootDict.has("isLegendary") || rootDict.has("isMythic")
|
||||
|| rootDict.has("legendariesDescription");
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
@@ -85,10 +87,46 @@ public class TetraCubeMonsterImporter implements EntityImporter<Monster> {
|
||||
|
||||
monster.abilities = getListOfTraits(rootDict, "abilities");
|
||||
monster.actions = getListOfTraits(rootDict, "actions");
|
||||
monster.bonusActions = getListOfTraits(rootDict, "bonusActions");
|
||||
monster.reactions = getListOfTraits(rootDict, "reactions");
|
||||
monster.legendaryActions = getListOfTraits(rootDict, "legendaries");
|
||||
monster.mythicActions = getListOfTraits(rootDict, "mythics");
|
||||
monster.lairActions = getListOfTraits(rootDict, "lairs");
|
||||
monster.regionalActions = getListOfTraits(rootDict, "regionals");
|
||||
|
||||
monster.legendaryActionsDescription = getString(rootDict, "legendariesDescription");
|
||||
if (!monster.legendaryActionsDescription.isEmpty()) {
|
||||
monster.legendaryActions.add(0, new Trait("Legendary Actions", monster.legendaryActionsDescription));
|
||||
}
|
||||
|
||||
monster.mythicActionsDescription = getString(rootDict, "mythicDescription");
|
||||
if (!monster.mythicActionsDescription.isEmpty() || !monster.mythicActions.isEmpty()) {
|
||||
if (!monster.mythicActionsDescription.isEmpty()) {
|
||||
monster.legendaryActions.add(new Trait("Mythic Actions", monster.mythicActionsDescription));
|
||||
}
|
||||
for (Trait mythic : monster.mythicActions) {
|
||||
String traitName = mythic.name;
|
||||
if (!traitName.toLowerCase(Locale.ROOT).startsWith("mythic action")) {
|
||||
traitName = "Mythic Action: " + traitName;
|
||||
}
|
||||
monster.legendaryActions.add(new Trait(traitName, mythic.description));
|
||||
}
|
||||
}
|
||||
|
||||
monster.lairActionsDescription = getString(rootDict, "lairDescription");
|
||||
monster.lairActionsEndNote = getString(rootDict, "lairDescriptionEnd");
|
||||
String fullLairDesc = combineDescriptions(monster.lairActionsDescription, monster.lairActionsEndNote);
|
||||
if (!fullLairDesc.isEmpty()) {
|
||||
monster.lairActions.add(0, new Trait("Lair Actions", fullLairDesc));
|
||||
}
|
||||
|
||||
monster.regionalActionsDescription = getString(rootDict, "regionalDescription");
|
||||
monster.regionalActionsEndNote = getString(rootDict, "regionalDescriptionEnd");
|
||||
String fullRegionalDesc = combineDescriptions(monster.regionalActionsDescription, monster.regionalActionsEndNote);
|
||||
if (!fullRegionalDesc.isEmpty()) {
|
||||
monster.regionalActions.add(0, new Trait("Regional Effects", fullRegionalDesc));
|
||||
}
|
||||
|
||||
addSavingThrows(monster, rootDict);
|
||||
monster.skills = getSetOfSkills(rootDict);
|
||||
monster.damageImmunities = getSetOfDamageTypes(rootDict, "damageTypes", "i");
|
||||
@@ -104,6 +142,17 @@ public class TetraCubeMonsterImporter implements EntityImporter<Monster> {
|
||||
return monster;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static String combineDescriptions(String desc1, String desc2) {
|
||||
if (!desc1.isEmpty() && !desc2.isEmpty()) {
|
||||
return desc1 + "\n\n" + desc2;
|
||||
} else if (!desc1.isEmpty()) {
|
||||
return desc1;
|
||||
} else {
|
||||
return desc2;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getString(JsonObject dict, String name) {
|
||||
return getString(dict, name, "");
|
||||
}
|
||||
@@ -169,7 +218,11 @@ public class TetraCubeMonsterImporter implements EntityImporter<Monster> {
|
||||
private static void addSense(Monster monster, JsonObject root, String name) {
|
||||
int distance = getInt(root, name);
|
||||
if (distance > 0) {
|
||||
monster.senses.add(formatDistance(name, distance));
|
||||
String senseStr = formatDistance(name, distance);
|
||||
if ("blindsight".equals(name) && getBool(root, "blind")) {
|
||||
senseStr += " (blind beyond this radius)";
|
||||
}
|
||||
monster.senses.add(senseStr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -206,6 +206,33 @@ public class Monster {
|
||||
@ColumnInfo(name = "regional_actions", defaultValue = "[]")
|
||||
public List<Trait> regionalActions;
|
||||
|
||||
@ColumnInfo(name = "source_url", defaultValue = "")
|
||||
public String sourceUrl;
|
||||
|
||||
@ColumnInfo(name = "bonus_actions", defaultValue = "[]")
|
||||
public List<Trait> bonusActions;
|
||||
|
||||
@ColumnInfo(name = "mythic_actions", defaultValue = "[]")
|
||||
public List<Trait> mythicActions;
|
||||
|
||||
@ColumnInfo(name = "legendary_actions_description", defaultValue = "")
|
||||
public String legendaryActionsDescription;
|
||||
|
||||
@ColumnInfo(name = "lair_actions_description", defaultValue = "")
|
||||
public String lairActionsDescription;
|
||||
|
||||
@ColumnInfo(name = "lair_actions_end_note", defaultValue = "")
|
||||
public String lairActionsEndNote;
|
||||
|
||||
@ColumnInfo(name = "regional_actions_description", defaultValue = "")
|
||||
public String regionalActionsDescription;
|
||||
|
||||
@ColumnInfo(name = "regional_actions_end_note", defaultValue = "")
|
||||
public String regionalActionsEndNote;
|
||||
|
||||
@ColumnInfo(name = "mythic_actions_description", defaultValue = "")
|
||||
public String mythicActionsDescription;
|
||||
|
||||
public Monster() {
|
||||
id = UUID.randomUUID();
|
||||
name = "";
|
||||
@@ -266,6 +293,15 @@ public class Monster {
|
||||
lairActions = new ArrayList<>();
|
||||
legendaryActions = new ArrayList<>();
|
||||
regionalActions = new ArrayList<>();
|
||||
bonusActions = new ArrayList<>();
|
||||
mythicActions = new ArrayList<>();
|
||||
sourceUrl = "";
|
||||
legendaryActionsDescription = "";
|
||||
lairActionsDescription = "";
|
||||
lairActionsEndNote = "";
|
||||
regionalActionsDescription = "";
|
||||
regionalActionsEndNote = "";
|
||||
mythicActionsDescription = "";
|
||||
}
|
||||
|
||||
public String getMeta() {
|
||||
@@ -783,6 +819,22 @@ public class Monster {
|
||||
return actionDescriptions;
|
||||
}
|
||||
|
||||
public List<String> getBonusActionDescriptions() {
|
||||
ArrayList<String> actionDescriptions = new ArrayList<>();
|
||||
for (Trait action : bonusActions) {
|
||||
actionDescriptions.add(getPlaceholderReplacedText(String.format("__%s__ %s", action.name, action.description)));
|
||||
}
|
||||
return actionDescriptions;
|
||||
}
|
||||
|
||||
public List<String> getMythicActionDescriptions() {
|
||||
ArrayList<String> actionDescriptions = new ArrayList<>();
|
||||
for (Trait action : mythicActions) {
|
||||
actionDescriptions.add(getPlaceholderReplacedText(String.format("__%s__ %s", action.name, action.description)));
|
||||
}
|
||||
return actionDescriptions;
|
||||
}
|
||||
|
||||
public List<String> getReactionDescriptions() {
|
||||
ArrayList<String> actionDescriptions = new ArrayList<>();
|
||||
for (Trait action : reactions) {
|
||||
|
||||
@@ -33,6 +33,8 @@ public class TetraCubeMonsterImporterTest {
|
||||
+ "\"cr\": \"1/4\""
|
||||
+ "}";
|
||||
|
||||
private static final String ANCIENT_BLACK_DRAGON_JSON = "{\"name\":\"Ancient Black Dragon\",\"size\":\"gargantuan\",\"type\":\"Dragon\",\"tag\":\"\",\"alignment\":\"chaotic evil\",\"hitDice\":\"21\",\"armorName\":\"natural armor\",\"shieldBonus\":0,\"natArmorBonus\":10,\"otherArmorDesc\":\"22 (natural armor)\",\"speed\":\"40\",\"burrowSpeed\":\"0\",\"climbSpeed\":\"0\",\"flySpeed\":\"80\",\"hover\":false,\"swimSpeed\":\"40\",\"customHP\":false,\"customSpeed\":false,\"hpText\":\"367 (21d20 + 147)\",\"speedDesc\":\"40 ft., fly 80 ft., swim 40 ft.\",\"strPoints\":\"27\",\"dexPoints\":\"14\",\"conPoints\":\"25\",\"intPoints\":\"16\",\"wisPoints\":\"15\",\"chaPoints\":\"19\",\"blindsight\":\"60\",\"blind\":false,\"darkvision\":\"120\",\"tremorsense\":\"0\",\"truesight\":\"0\",\"telepathy\":0,\"cr\":\"21\",\"customCr\":\"21 (33,000 XP)\",\"customProf\":7,\"isLegendary\":true,\"legendariesDescription\":\"The dragon can take 3 legendary actions, choosing from the options below. Only one legendary action option can be used at a time and only at the end of another creature's turn. The dragon regains spent legendary actions at the start of its turn.\",\"isLair\":true,\"lairDescription\":\"When fighting inside its lair, the ancient black dragon can invoke the ambient magic to take lair actions. On initiative count 20 (losing initiative ties), the ancient black dragon can take one lair action to cause one of the following effects:\",\"lairDescriptionEnd\":\"The goblin can't repeat an effect until they have all been used, and it can't use the same effect two rounds in a row.\",\"isMythic\":true,\"mythicDescription\":\"If the ancient black dragon's mythic trait is active, it can use the options below as legendary actions for 1 hour after using {Some Ability}.\",\"isRegional\":true,\"regionalDescription\":\"The region containing the ancient black dragon's lair is warped by the creature's presence, which creates one or more of the following effects:\",\"regionalDescriptionEnd\":\"If the ancient black dragon dies, the first two effects fade over the course of 3d10 days.\",\"properties\":[],\"abilities\":[{\"name\":\"Amphibious\",\"desc\":\"The dragon can breathe air and water.\"},{\"name\":\"Legendary Resistance (3/Day)\",\"desc\":\"If the dragon fails a saving throw, it can choose to succeed instead.\"}],\"actions\":[{\"name\":\"Multiattack\",\"desc\":\"The dragon can use its Frightful Presence. It then makes three attacks: one with its bite and two with its claws.\"},{\"name\":\"Bite\",\"desc\":\"_Melee Weapon Attack:_ +15 to hit, reach 15 ft., one target. _Hit:_ 19 (2d10 + 8) piercing damage plus 9 (2d8) acid damage.\"},{\"name\":\"Claw\",\"desc\":\"_Melee Weapon Attack:_ +15 to hit, reach 10 ft., one target. _Hit:_ 15 (2d6 + 8) slashing damage.\"},{\"name\":\"Tail\",\"desc\":\"_Melee Weapon Attack:_ +15 to hit, reach 20 ft., one target. _Hit:_ 17 (2d8 + 8) bludgeoning damage.\"},{\"name\":\"Frightful Presence\",\"desc\":\"Each creature of the dragon's choice that is within 120 feet of the dragon and aware of it must succeed on a DC 19 Wisdom saving throw or become frightened for 1 minute. A creature can repeat the saving throw at the end of each of its turns, ending the effect on itself on a success. If a creature's saving throw is successful or the effect ends for it, the creature is immune to the dragon's Frightful Presence for the next 24 hours.\"},{\"name\":\"Acid Breath (Recharge 5-6)\",\"desc\":\"The dragon exhales acid in a 90-foot line that is 10 feet wide. Each creature in that line must make a DC 22 Dexterity saving throw, taking 67 (15d8) acid damage on a failed save, or half as much damage on a successful one.\"}],\"bonusActions\":[],\"reactions\":[],\"legendaries\":[{\"name\":\"Detect\",\"desc\":\"The dragon makes a Wisdom (Perception) check.\"},{\"name\":\"Tail Attack\",\"desc\":\"The dragon makes a tail attack.\"},{\"name\":\"Wing Attack (Costs 2 Actions)\",\"desc\":\"The dragon beats its wings. Each creature within 15 ft. of the dragon must succeed on a DC 23 Dexterity saving throw or take 15 (2d6 + 8) bludgeoning damage and be knocked prone. The dragon can then fly up to half its flying speed.\"}],\"mythics\":[],\"lairs\":[],\"regionals\":[],\"sthrows\":[{\"name\":\"dex\",\"order\":1},{\"name\":\"con\",\"order\":2},{\"name\":\"wis\",\"order\":4},{\"name\":\"cha\",\"order\":5}],\"skills\":[{\"name\":\"perception\",\"stat\":\"wis\",\"note\":\" (ex)\"},{\"name\":\"stealth\",\"stat\":\"dex\"}],\"damagetypes\":[{\"name\":\"acid\",\"note\":\" (Immune)\",\"type\":\"i\"}],\"specialdamage\":[],\"conditions\":[],\"languages\":[{\"name\":\"Common\",\"speaks\":true},{\"name\":\"Draconic\",\"speaks\":true}],\"understandsBut\":\"\",\"shortName\":\"\",\"pluralName\":\"\",\"doubleColumns\":false,\"separationPoint\":5,\"damage\":[]}";
|
||||
|
||||
@Test
|
||||
public void canImport_validTetraCubeJson_returnsTrue() {
|
||||
assertTrue(importer.canImport(SAMPLE_TETRACUBE_JSON));
|
||||
@@ -68,6 +70,106 @@ public class TetraCubeMonsterImporterTest {
|
||||
assertEquals(14, monster.dexterityScore);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parse_bonusActions_populatesBonusActions() throws Exception {
|
||||
String json = "{"
|
||||
+ "\"name\": \"Goblin Boss\","
|
||||
+ "\"hitDice\": 4,"
|
||||
+ "\"bonusActions\": [{\"name\": \"Nimble Escape\", \"desc\": \"Disengage or Hide as bonus action.\"}]"
|
||||
+ "}";
|
||||
Monster monster = importer.parse(json);
|
||||
assertNotNull(monster);
|
||||
assertEquals(1, monster.bonusActions.size());
|
||||
assertEquals("Nimble Escape", monster.bonusActions.get(0).name);
|
||||
assertEquals("Disengage or Hide as bonus action.", monster.bonusActions.get(0).description);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parse_blindsightWithBlindFlag_appendsNote() throws Exception {
|
||||
String json = "{"
|
||||
+ "\"name\": \"Grimlock\","
|
||||
+ "\"hitDice\": 3,"
|
||||
+ "\"blindsight\": 30,"
|
||||
+ "\"blind\": true"
|
||||
+ "}";
|
||||
Monster monster = importer.parse(json);
|
||||
assertNotNull(monster);
|
||||
assertTrue(monster.senses.contains("blindsight 30 ft. (blind beyond this radius)"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parse_legendaryAndMythicDescriptions_parsedCorrectly() throws Exception {
|
||||
String json = "{"
|
||||
+ "\"name\": \"Ancient Dragon\","
|
||||
+ "\"hitDice\": 20,"
|
||||
+ "\"legendariesDescription\": \"The dragon can take 3 legendary actions.\","
|
||||
+ "\"mythicDescription\": \"If mythic trait is active...\","
|
||||
+ "\"mythics\": [{\"name\": \"Grasp\", \"desc\": \"Grabs a creature.\"}]"
|
||||
+ "}";
|
||||
Monster monster = importer.parse(json);
|
||||
assertNotNull(monster);
|
||||
assertEquals(3, monster.legendaryActions.size());
|
||||
assertEquals("Legendary Actions", monster.legendaryActions.get(0).name);
|
||||
assertEquals("Mythic Actions", monster.legendaryActions.get(1).name);
|
||||
assertEquals("Mythic Action: Grasp", monster.legendaryActions.get(2).name);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parse_lairAndRegionalDescriptions_parsedCorrectly() throws Exception {
|
||||
String json = "{"
|
||||
+ "\"name\": \"Lich\","
|
||||
+ "\"hitDice\": 18,"
|
||||
+ "\"lairDescription\": \"Lair intro.\","
|
||||
+ "\"lairDescriptionEnd\": \"Lair end.\","
|
||||
+ "\"regionalDescription\": \"Regional intro.\","
|
||||
+ "\"regionalDescriptionEnd\": \"Regional end.\""
|
||||
+ "}";
|
||||
Monster monster = importer.parse(json);
|
||||
assertNotNull(monster);
|
||||
assertEquals(1, monster.lairActions.size());
|
||||
assertEquals("Lair Actions", monster.lairActions.get(0).name);
|
||||
assertEquals("Lair intro.\n\nLair end.", monster.lairActions.get(0).description);
|
||||
assertEquals(1, monster.regionalActions.size());
|
||||
assertEquals("Regional Effects", monster.regionalActions.get(0).name);
|
||||
assertEquals("Regional intro.\n\nRegional end.", monster.regionalActions.get(0).description);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parse_ancientBlackDragonExport_populatesAllSections() throws Exception {
|
||||
Monster monster = importer.parse(ANCIENT_BLACK_DRAGON_JSON);
|
||||
assertNotNull(monster);
|
||||
assertEquals("Ancient Black Dragon", monster.name);
|
||||
assertEquals("gargantuan", monster.size);
|
||||
assertEquals("Dragon", monster.type);
|
||||
assertEquals("chaotic evil", monster.alignment);
|
||||
assertEquals(27, monster.strengthScore);
|
||||
|
||||
// Abilities
|
||||
assertEquals(2, monster.abilities.size());
|
||||
assertEquals("Amphibious", monster.abilities.get(0).name);
|
||||
|
||||
// Actions
|
||||
assertEquals(6, monster.actions.size());
|
||||
assertEquals("Multiattack", monster.actions.get(0).name);
|
||||
|
||||
// Legendary + Mythic Actions
|
||||
// 1 legendary intro + 3 legendary actions + 1 mythic intro = 5 items
|
||||
assertEquals(5, monster.legendaryActions.size());
|
||||
assertEquals("Legendary Actions", monster.legendaryActions.get(0).name);
|
||||
assertEquals("Detect", monster.legendaryActions.get(1).name);
|
||||
assertEquals("Mythic Actions", monster.legendaryActions.get(4).name);
|
||||
|
||||
// Lair Actions
|
||||
assertEquals(1, monster.lairActions.size());
|
||||
assertEquals("Lair Actions", monster.lairActions.get(0).name);
|
||||
assertTrue(monster.lairActions.get(0).description.contains("invoke the ambient magic"));
|
||||
|
||||
// Regional Effects
|
||||
assertEquals(1, monster.regionalActions.size());
|
||||
assertEquals("Regional Effects", monster.regionalActions.get(0).name);
|
||||
assertTrue(monster.regionalActions.get(0).description.contains("warped by the creature's presence"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void monsterImportHelper_fromJSON_delegatesToImporter() {
|
||||
Monster monster = MonsterImportHelper.fromJSON(SAMPLE_TETRACUBE_JSON);
|
||||
|
||||
Reference in New Issue
Block a user