Skip to content

Commit

Permalink
1.1.0
Browse files Browse the repository at this point in the history
- Added ability to import homebrew monsters from an improved initiative JSON file
- Improved appearance of settings
  • Loading branch information
valentine195 committed Jun 4, 2021
1 parent 9c34f16 commit 4e53a62
Show file tree
Hide file tree
Showing 7 changed files with 336 additions and 117 deletions.
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "obsidian-5e-statblocks",
"name": "5e Statblocks",
"version": "1.0.0",
"version": "1.1.0",
"description": "Create 5e styled statblocks in Obsidian.md",
"minAppVersion": "0.12.0",
"author": "Jeremy Valentine",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "obsidian-5e-statblocks",
"version": "1.0.0",
"version": "1.1.0",
"description": "Create 5e styled statblocks in Obsidian.md",
"main": "main.js",
"scripts": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,76 +6,75 @@ import { StatBlockImporter } from "./StatBlockImporter"; */
import { Monster, Spell, Trait } from "@types";
import { titleCase } from "title-case";

export class DnDAppFilesImporter {
public ImportEntitiesFromXml = async (
...files: File[]
): Promise<Monster[]> => {
return new Promise((resolve) => {
for (let xmlFile of files) {
const reader = new FileReader();
export const ImportEntitiesFromXml = async (
...files: File[]
): Promise<Monster[]> => {
return new Promise((resolve) => {
for (let xmlFile of files) {
const reader = new FileReader();

reader.onload = async (event: any) => {
const xml: string = event.target.result;
reader.onload = async (event: any) => {
const xml: string = event.target.result;

const dom = new DOMParser().parseFromString(
xml,
"application/xml"
);
const monsters = dom.getElementsByTagName("monster");
const importedMonsters: Monster[] = [];
if (!monsters.length) return;
for (let monster of Array.from(monsters)) {
const importedMonster: Monster = {
name: getParameter(monster, "name"),
size: getSize(monster),
type: getParameter(monster, "type"),
subtype: getParameter(monster, "subtype"),
alignment: getParameter(monster, "alignment"),
ac: getAC(monster),
hp: Number(getHP(monster, "hp")),
hit_dice: getHP(monster, "hit_dice"),
speed: getParameter(monster, "speed"),
stats: [
Number(getParameter(monster, "str")),
Number(getParameter(monster, "dex")),
Number(getParameter(monster, "con")),
Number(getParameter(monster, "int")),
Number(getParameter(monster, "wis")),
Number(getParameter(monster, "cha"))
],
saves: getSaves(monster),
skillsaves: getSkillSaves(monster),
damage_vulnerabilities: getParameter(
monster,
"vulnerable"
),
damage_resistances: getParameter(monster, "resist"),
damage_immunities: getParameter(monster, "immune"),
condition_immunities: getParameter(
monster,
"conditionImmune"
),
senses: getParameter(monster, "senses"),
languages: getParameter(monster, "languages"),
cr: getParameter(monster, "cr"),
traits: getTraits(monster, "trait"),
spells: getSpells(monster),
actions: getTraits(monster, "action"),
legendary_actions: getTraits(monster, "legendary"),
reactions: getTraits(monster, "reaction"),
source: getSource(monster)
};
const dom = new DOMParser().parseFromString(
xml,
"application/xml"
);
const monsters = dom.getElementsByTagName("monster");
const importedMonsters: Monster[] = [];
if (!monsters.length) return;
for (let monster of Array.from(monsters)) {
const importedMonster: Monster = {
name: getParameter(monster, "name"),
size: getSize(monster),
type: getParameter(monster, "type"),
subtype: getParameter(monster, "subtype"),
alignment: getParameter(monster, "alignment"),
ac: getAC(monster),
hp: Number(getHP(monster, "hp")),
hit_dice: getHP(monster, "hit_dice"),
speed: getParameter(monster, "speed"),
stats: [
Number(getParameter(monster, "str")),
Number(getParameter(monster, "dex")),
Number(getParameter(monster, "con")),
Number(getParameter(monster, "int")),
Number(getParameter(monster, "wis")),
Number(getParameter(monster, "cha"))
],
saves: getSaves(monster),
skillsaves: getSkillSaves(monster),
damage_vulnerabilities: getParameter(
monster,
"vulnerable"
),
damage_resistances: getParameter(monster, "resist"),
damage_immunities: getParameter(monster, "immune"),
condition_immunities: getParameter(
monster,
"conditionImmune"
),
senses: getParameter(monster, "senses"),
languages: getParameter(monster, "languages"),
cr: getParameter(monster, "cr"),
traits: getTraits(monster, "trait"),
spells: getSpells(monster),
actions: getTraits(monster, "action"),
legendary_actions: getTraits(monster, "legendary"),
reactions: getTraits(monster, "reaction"),
source: getSource(monster)
};

importedMonsters.push(importedMonster);
}
resolve(importedMonsters);
};
importedMonsters.push(importedMonster);
}
resolve(importedMonsters);
};

reader.readAsText(xmlFile);
}
});
};

reader.readAsText(xmlFile);
}
});
};
}
function getParameter(monster: Element, tag: string): string {
const element = monster.getElementsByTagName(tag);
if (element && element.length) return element[0].textContent;
Expand Down Expand Up @@ -221,9 +220,5 @@ function getSource(monster: Element): string {
);
}
}
console.log(
"🚀 ~ file: DnDAppFilesImporter.ts ~ line 226 ~ getSource ~ source",
source
);
return source;
}
173 changes: 173 additions & 0 deletions src/importers/ImprovedInitiativeImport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import { Monster } from "@types";
const SAVES: Record<
string,
| "strength"
| "dexterity"
| "constitution"
| "intelligence"
| "wisdom"
| "charisma"
> = {
STR: "strength",
DEX: "dexterity",
CON: "constitution",
INT: "intelligence",
WIS: "wisdom",
CHA: "charisma"
};
export const ImportEntitiesFromImprovedInitiative = async (
...files: File[]
): Promise<Map<string, Monster>> => {
return new Promise((resolve, reject) => {
for (let file of files) {
const reader = new FileReader();

reader.onload = async (event: any) => {
const importedMonsters: Map<string, Monster> = new Map();
try {
let json = JSON.parse(event.target.result);
const monsters = Object.keys(json).filter((key) =>
/^Creatures/.test(key)
);
for (let key of monsters) {
try {
const monster = json[key];
const importedMonster: Monster = {
name: monster.Name,
source: monster.Source?.trim().length
? monster.Source.trim()
: "Unknown - Improved Initiative File",
type: monster.Type.split(/,\s?/)[0].trim(),
subtype: "",
size: "",
alignment: monster.Type.split(/,\s?/)[1].trim(),
hp: monster.HP.Value,
hit_dice: monster.HP.Notes.replace(
/([()])/,
""
).trim(),
ac: monster.AC.Value,
speed: monster.Speed.join(", ").trim(),
stats: Object.values(monster.Abilities) as [
number,
number,
number,
number,
number,
number
],
damage_immunities:
monster.DamageImmunities?.join("; ")
.toLowerCase()
.trim() ?? "",
damage_resistances:
monster.DamageResistances?.join(", ")
.toLowerCase()
.trim() ?? "",
damage_vulnerabilities:
monster.DamageVulnerabilities?.join(", ")
.toLowerCase()
.trim() ?? "",
condition_immunities:
monster.ConditionImmunities?.join(", ")
.toLowerCase()
.trim() ?? "",
saves:
monster.Saves?.map(
({
Name,
Modifier
}: {
Name: string;
Modifier: number;
}) => {
return {
[SAVES[Name]]: Modifier
};
}
) ?? [],
skillsaves:
monster.Skills?.map(
({
Name,
Modifier
}: {
Name: string;
Modifier: number;
}) => {
return {
[Name]: Modifier
};
}
) ?? [],
senses: monster.Senses?.join(", ").trim() ?? "",
languages:
monster.Languages?.join(", ").trim() ?? "",
cr: monster.Challenge?.trim() ?? "",
traits:
monster.Traits?.map(
(trait: {
Name: string;
Content: string;
}) => {
return {
name: trait.Name,
desc: trait.Content
};
}
) ?? [],
actions:
monster.Actions?.map(
(trait: {
Name: string;
Content: string;
}) => {
return {
name: trait.Name,
desc: trait.Content
};
}
) ?? [],
reactions:
monster.Reactions?.map(
(trait: {
Name: string;
Content: string;
}) => {
return {
name: trait.Name,
desc: trait.Content
};
}
) ?? [],
legendary_actions:
monster.LegendaryActions?.map(
(trait: {
Name: string;
Content: string;
}) => {
return {
name: trait.Name,
desc: trait.Content
};
}
) ?? []
};
importedMonsters.set(
importedMonster.name,
importedMonster
);
} catch (e) {
continue;
}
}
resolve(importedMonsters);
} catch (e) {
reject();
}
};

reader.readAsText(file);
}
});
};
2 changes: 2 additions & 0 deletions src/importers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./DnDAppFilesImport";
export * from "./ImprovedInitiativeImport";
8 changes: 8 additions & 0 deletions src/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@
border-top: 1px solid var(--background-modifier-border);
border-bottom: 0px solid var(--background-modifier-border);
padding: 18px 0 0 0;
background-color: inherit;
}

.statblock-monster-filter {
position: sticky;
top: -5px;
padding-top: 5px;
background-color: inherit;
}

.statblock-additional-container > .setting-item-heading:only-child {
Expand Down
Loading

0 comments on commit 4e53a62

Please sign in to comment.