diff --git a/sheet.js b/sheet.js
deleted file mode 100644
index b7f13c3..0000000
--- a/sheet.js
+++ /dev/null
@@ -1,407 +0,0 @@
-import {serializeFormData, deserializeFormData, storeData, getData} from "./utils.js";
-
-window.addEventListener("DOMContentLoaded", init);
-
-let combatModifiers = [
- {
- category: "Saves",
- items: [
- {
- name: "Resilience",
- type: "full",
- value: function (e) { return Math.max(e.STR, e.END) + e.training + (e.mb * e.mastery); }
-
- },
- {
- name: "Reflex",
- type: "full",
- value: function (e) { return Math.max(e.AGI, e.WIT) + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Resolve",
- type: "full",
- value: function (e) { return Math.max(e.INT, e.CHA) + e.training + (e.mb * e.mastery); }
- }
- ]
- },
- {
- category: "Weapon",
- items: [
- {
- name: "Simple",
- type: "full",
- value: function (e) { return Math.max(e.STR, e.AGI) + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Brawl",
- type: "full",
- value: function (e) { return Math.max(e.STR, e.AGI) + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Bludgeon",
- type: "full",
- value: function (e) { return Math.max(e.STR, e.AGI) + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Axe",
- type: "full",
- value: function (e) { return Math.max(e.STR, e.AGI) + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Polearm",
- type: "full",
- value: function (e) { return Math.max(e.STR, e.AGI) + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Sword",
- type: "full",
- value: function (e) { return Math.max(e.STR, e.AGI) + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Archery",
- type: "full",
- value: function (e) { return Math.max(e.STR, e.AGI) + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Firearm",
- type: "full",
- value: function (e) { return Math.max(e.STR, e.AGI) + e.training + (e.mb * e.mastery); }
- }
- ]
- },
- {
- category: "Armor",
- items: [
- {
- name: "Unarmored",
- type: "training-only",
- value: function (e) { return }
- },
- {
- name: "Light",
- type: "training-only",
- value: function (e) { return }
- },
- {
- name: "Medium",
- type: "training-only",
- value: function (e) { return }
- },
- {
- name: "Heavy",
- type: "training-only",
- value: function (e) { return }
- }
- ]
- }
-]
-
-let rpModifiers = [
- {
- category: "Skills",
- items: [
- {
- name: "Athletics",
- type: "full",
- value: function (e) { return e.STR + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Fortitude",
- type: "full",
- value: function (e) { return e.END + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Acrobatics",
- type: "full",
- value: function (e) { return e.AGI + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Stealth",
- type: "full",
- value: function (e) { return e.AGI + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Thievery",
- type: "full",
- value: function (e) { return e.AGI + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Animal_Handling",
- display: "Animal Handling",
- type: "full",
- value: function (e) { return e.WIT + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Intuition",
- type: "full",
- value: function (e) { return e.WIT + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Perception",
- type: "full",
- value: function (e) { return e.WIT + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Streetwise",
- type: "full",
- value: function (e) { return e.WIT + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Survival",
- type: "full",
- value: function (e) { return e.WIT + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Arcana",
- type: "full",
- value: function (e) { return e.INT + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Crafting",
- type: "full",
- value: function (e) { return e.INT + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Investigation",
- type: "full",
- value: function (e) { return e.INT + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Medicine",
- type: "full",
- value: function (e) { return e.INT + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Deception",
- type: "full",
- value: function (e) { return e.CHA + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Intimidation",
- type: "full",
- value: function (e) { return e.CHA + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Performance",
- type: "full",
- value: function (e) { return e.CHA + e.training + (e.mb * e.mastery); }
- },
- {
- name: "Persuasion",
- type: "full",
- value: function (e) { return e.CHA + e.training + (e.mb * e.mastery); }
- }
- ]
- }
-]
-
-let features = [
- {
- name: "Core Species",
- level: 1
- },
- {
- name: "Species",
- level: 1
- },
- {
- name: "Cornerstone",
- level: 1
- },
- {
- name: "Cornerstone",
- level: 1
- },
- {
- name: "Novice",
- level: 1
- },
- {
- name: "Novice",
- level: 2
- },
- {
- name: "Novice",
- level: 3
- },
- {
- name: "Novice",
- level: 4
- },
- {
- name: "Apprentice",
- level: 5
- },
- {
- name: "Apprentice",
- level: 6
- },
- {
- name: "Apprentice",
- level: 7
- },
- {
- name: "Journeyman",
- level: 9
- },
- {
- name: "Journeyman",
- level: 10
- },
- {
- name: "Journeyman",
- level: 11
- },
- {
- name: "Expert",
- level: 13
- },
- {
- name: "Expert",
- level: 14
- },
- {
- name: "Expert",
- level: 15
- },
- {
- name: "Master",
- level: 17
- },
- {
- name: "Master",
- level: 18
- },
- {
- name: "Capstone",
- level: 20
- }
-
-]
-
-let spellSlots = 20
-
-function init () {
- buildModifiers("#combat-modifiers", combatModifiers);
- buildModifiers("#rp-modifiers", rpModifiers);
- buildFeatures("#features", features);
- buildSpells("#spellcasting-spells", spellSlots);
-
- let data = getData();
- deserializeFormData("#character-data", data);
-
- calculateModifiers(combatModifiers);
- calculateModifiers(rpModifiers)
- calculateSpellCasting();;
-
- let inputs = document.querySelectorAll("input, select, textarea");
- for (let i = 0; i < inputs.length; i++) {
- inputs[i].addEventListener("input", refresh);
- }
-}
-
-function refresh () {
- calculateModifiers(combatModifiers);
- calculateModifiers(rpModifiers);
- calculateSpellCasting();
-
- let data = serializeFormData("#character-data");
- storeData(data);
-}
-
-function buildModifiers(container, data) {
- let area = document.querySelector(container);
- for (let i in data) {
- let category = data[i];
- let categoryDiv = document.createElement("div");
- area.append(categoryDiv);
- categoryDiv.style = "display: contents;";
- categoryDiv.innerHTML = `
${category.category}
`;
- for (let j in data[i].items) {
- let item = data[i].items[j];
- if (item.type === "full") {
- categoryDiv.innerHTML += `
-
-
${item.display ? item.display : item.name}
-
-
-
-
- `;
- }
- else if (item.type === "training-only"){
- categoryDiv.innerHTML += `
-
-
${item.display ? item.display : item.name}
-
-
-
-
- `;
- }
- }
- }
-}
-
-function buildFeatures (container) {
- let area = document.querySelector(container);
- for (let i in features) {
- let feature = features[i];
- area.innerHTML += `
- ${feature.name}
- ${feature.level}
-
-
-
- `;
- }
-}
-
-function buildSpells (container, numSpells) {
- let area = document.querySelector(container);
- for (let i = 0; i < numSpells; i++) {
- area.innerHTML += `
-
-
-
-
- `;
- }
-}
-
-function calculateModifiers (data) {
- for (let i in data) {
- let category = data[i];
- for (let j in data[i].items) {
- let item = data[i].items[j];
- setModifierVal(category.category, item.name, item.value);
- }
- }
-}
-
-function calculateSpellCasting () {
- let attribute = document.querySelector("#spellcasting-attribute").value;
- let baseVal = 0;
- if (attribute === "int") { baseVal = Number(document.querySelector("#int").value); }
- else if (attribute === "cha") { baseVal = Number(document.querySelector("#cha").value); }
- let training = Number(document.querySelector("#spellcasting-training").value);
- let mb = Number(document.querySelector("#spellcasting-mb").checked);
- let mastery = Number(document.querySelector("#mastery").value);
- let modifier = baseVal + training + (mb * mastery);
- document.querySelector("#spellcasting-modifier").innerText = ` = ${modifier}`;
- document.querySelector("#spellcasting-dc").innerText = ` = ${8 + modifier}`;
-}
-
-function setModifierVal (category, name, value) {
- let e = {};
- e.STR = Number(document.querySelector("#str").value);
- e.END = Number(document.querySelector("#end").value);
- e.AGI = Number(document.querySelector("#agi").value);
- e.WIT = Number(document.querySelector("#wit").value);
- e.INT = Number(document.querySelector("#int").value);
- e.CHA = Number(document.querySelector("#cha").value);
- e.training = Number(document.querySelector(`#${category}-${name}-training`).value);
- e.mb = Number(document.querySelector(`#${category}-${name}-mb`).checked);
- e.mastery = Number(document.querySelector("#mastery").value);
- document.querySelector(`#${category}-${name}-result`).innerText = ` = ${value(e)}`;
-}
\ No newline at end of file
diff --git a/songs-meta.js b/songs-meta.js
new file mode 100644
index 0000000..d178815
--- /dev/null
+++ b/songs-meta.js
@@ -0,0 +1,278 @@
+export let combatModifiers = [
+ {
+ category: "Saves",
+ items: [
+ {
+ name: "Resilience",
+ type: "full",
+ value: function (e) { return Math.max(e.STR, e.END) + e.training + (e.mb * e.mastery); }
+
+ },
+ {
+ name: "Reflex",
+ type: "full",
+ value: function (e) { return Math.max(e.AGI, e.WIT) + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Resolve",
+ type: "full",
+ value: function (e) { return Math.max(e.INT, e.CHA) + e.training + (e.mb * e.mastery); }
+ }
+ ]
+ },
+ {
+ category: "Weapon",
+ items: [
+ {
+ name: "Simple",
+ type: "full",
+ value: function (e) { return Math.max(e.STR, e.AGI) + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Brawl",
+ type: "full",
+ value: function (e) { return Math.max(e.STR, e.AGI) + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Bludgeon",
+ type: "full",
+ value: function (e) { return Math.max(e.STR, e.AGI) + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Axe",
+ type: "full",
+ value: function (e) { return Math.max(e.STR, e.AGI) + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Polearm",
+ type: "full",
+ value: function (e) { return Math.max(e.STR, e.AGI) + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Sword",
+ type: "full",
+ value: function (e) { return Math.max(e.STR, e.AGI) + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Archery",
+ type: "full",
+ value: function (e) { return Math.max(e.STR, e.AGI) + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Firearm",
+ type: "full",
+ value: function (e) { return Math.max(e.STR, e.AGI) + e.training + (e.mb * e.mastery); }
+ }
+ ]
+ },
+ {
+ category: "Armor",
+ items: [
+ {
+ name: "Unarmored",
+ type: "training-only",
+ value: function (e) { return }
+ },
+ {
+ name: "Light",
+ type: "training-only",
+ value: function (e) { return }
+ },
+ {
+ name: "Medium",
+ type: "training-only",
+ value: function (e) { return }
+ },
+ {
+ name: "Heavy",
+ type: "training-only",
+ value: function (e) { return }
+ }
+ ]
+ }
+]
+
+export let rpModifiers = [
+ {
+ category: "Skills",
+ items: [
+ {
+ name: "Athletics",
+ type: "full",
+ value: function (e) { return e.STR + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Fortitude",
+ type: "full",
+ value: function (e) { return e.END + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Acrobatics",
+ type: "full",
+ value: function (e) { return e.AGI + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Stealth",
+ type: "full",
+ value: function (e) { return e.AGI + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Thievery",
+ type: "full",
+ value: function (e) { return e.AGI + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Animal_Handling",
+ display: "Animal Handling",
+ type: "full",
+ value: function (e) { return e.WIT + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Intuition",
+ type: "full",
+ value: function (e) { return e.WIT + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Perception",
+ type: "full",
+ value: function (e) { return e.WIT + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Streetwise",
+ type: "full",
+ value: function (e) { return e.WIT + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Survival",
+ type: "full",
+ value: function (e) { return e.WIT + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Arcana",
+ type: "full",
+ value: function (e) { return e.INT + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Crafting",
+ type: "full",
+ value: function (e) { return e.INT + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Investigation",
+ type: "full",
+ value: function (e) { return e.INT + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Medicine",
+ type: "full",
+ value: function (e) { return e.INT + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Deception",
+ type: "full",
+ value: function (e) { return e.CHA + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Intimidation",
+ type: "full",
+ value: function (e) { return e.CHA + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Performance",
+ type: "full",
+ value: function (e) { return e.CHA + e.training + (e.mb * e.mastery); }
+ },
+ {
+ name: "Persuasion",
+ type: "full",
+ value: function (e) { return e.CHA + e.training + (e.mb * e.mastery); }
+ }
+ ]
+ }
+]
+
+export let features = [
+ {
+ name: "Core Species",
+ level: 1
+ },
+ {
+ name: "Species",
+ level: 1
+ },
+ {
+ name: "Cornerstone",
+ level: 1
+ },
+ {
+ name: "Cornerstone",
+ level: 1
+ },
+ {
+ name: "Novice",
+ level: 1
+ },
+ {
+ name: "Novice",
+ level: 2
+ },
+ {
+ name: "Novice",
+ level: 3
+ },
+ {
+ name: "Novice",
+ level: 4
+ },
+ {
+ name: "Apprentice",
+ level: 5
+ },
+ {
+ name: "Apprentice",
+ level: 6
+ },
+ {
+ name: "Apprentice",
+ level: 7
+ },
+ {
+ name: "Journeyman",
+ level: 9
+ },
+ {
+ name: "Journeyman",
+ level: 10
+ },
+ {
+ name: "Journeyman",
+ level: 11
+ },
+ {
+ name: "Expert",
+ level: 13
+ },
+ {
+ name: "Expert",
+ level: 14
+ },
+ {
+ name: "Expert",
+ level: 15
+ },
+ {
+ name: "Master",
+ level: 17
+ },
+ {
+ name: "Master",
+ level: 18
+ },
+ {
+ name: "Capstone",
+ level: 20
+ }
+
+]
+
+export let spellSlots = 20
\ No newline at end of file
diff --git a/songs.html b/songs.html
index 3481fea..76f49c5 100644
--- a/songs.html
+++ b/songs.html
@@ -7,7 +7,8 @@
-
+
+
diff --git a/songs.js b/songs.js
new file mode 100644
index 0000000..615d2ed
--- /dev/null
+++ b/songs.js
@@ -0,0 +1,129 @@
+import {serializeFormData, deserializeFormData, storeData, getData} from "./utils.js";
+import {combatModifiers, rpModifiers, features, spellSlots} from "./songs-meta.js"
+
+window.addEventListener("DOMContentLoaded", init);
+
+function init () {
+ buildModifiers("#combat-modifiers", combatModifiers);
+ buildModifiers("#rp-modifiers", rpModifiers);
+ buildFeatures("#features", features);
+ buildSpells("#spellcasting-spells", spellSlots);
+
+ let data = getData();
+ deserializeFormData("#character-data", data);
+
+ calculateModifiers(combatModifiers);
+ calculateModifiers(rpModifiers)
+ calculateSpellCasting();;
+
+ let inputs = document.querySelectorAll("input, select, textarea");
+ for (let i = 0; i < inputs.length; i++) {
+ inputs[i].addEventListener("input", refresh);
+ }
+}
+
+function refresh () {
+ calculateModifiers(combatModifiers);
+ calculateModifiers(rpModifiers);
+ calculateSpellCasting();
+
+ let data = serializeFormData("#character-data");
+ storeData(data);
+}
+
+function buildModifiers(container, data) {
+ let area = document.querySelector(container);
+ for (let i in data) {
+ let category = data[i];
+ let categoryDiv = document.createElement("div");
+ area.append(categoryDiv);
+ categoryDiv.style = "display: contents;";
+ categoryDiv.innerHTML = `${category.category}
`;
+ for (let j in data[i].items) {
+ let item = data[i].items[j];
+ if (item.type === "full") {
+ categoryDiv.innerHTML += `
+
+
${item.display ? item.display : item.name}
+
+
+
+
+ `;
+ }
+ else if (item.type === "training-only"){
+ categoryDiv.innerHTML += `
+
+
${item.display ? item.display : item.name}
+
+
+
+
+ `;
+ }
+ }
+ }
+}
+
+function buildFeatures (container) {
+ let area = document.querySelector(container);
+ for (let i in features) {
+ let feature = features[i];
+ area.innerHTML += `
+ ${feature.name}
+ ${feature.level}
+
+
+
+ `;
+ }
+}
+
+function buildSpells (container, numSpells) {
+ let area = document.querySelector(container);
+ for (let i = 0; i < numSpells; i++) {
+ area.innerHTML += `
+
+
+
+
+ `;
+ }
+}
+
+function calculateModifiers (data) {
+ for (let i in data) {
+ let category = data[i];
+ for (let j in data[i].items) {
+ let item = data[i].items[j];
+ setModifierVal(category.category, item.name, item.value);
+ }
+ }
+}
+
+function calculateSpellCasting () {
+ let attribute = document.querySelector("#spellcasting-attribute").value;
+ let baseVal = 0;
+ if (attribute === "int") { baseVal = Number(document.querySelector("#int").value); }
+ else if (attribute === "cha") { baseVal = Number(document.querySelector("#cha").value); }
+ let training = Number(document.querySelector("#spellcasting-training").value);
+ let mb = Number(document.querySelector("#spellcasting-mb").checked);
+ let mastery = Number(document.querySelector("#mastery").value);
+ let modifier = baseVal + training + (mb * mastery);
+ document.querySelector("#spellcasting-modifier").innerText = ` = ${modifier}`;
+ document.querySelector("#spellcasting-dc").innerText = ` = ${8 + modifier}`;
+}
+
+function setModifierVal (category, name, value) {
+ let e = {};
+ e.STR = Number(document.querySelector("#str").value);
+ e.END = Number(document.querySelector("#end").value);
+ e.AGI = Number(document.querySelector("#agi").value);
+ e.WIT = Number(document.querySelector("#wit").value);
+ e.INT = Number(document.querySelector("#int").value);
+ e.CHA = Number(document.querySelector("#cha").value);
+ e.training = Number(document.querySelector(`#${category}-${name}-training`).value);
+ e.mb = Number(document.querySelector(`#${category}-${name}-mb`).checked);
+ e.mastery = Number(document.querySelector("#mastery").value);
+ document.querySelector(`#${category}-${name}-result`).innerText = ` = ${value(e)}`;
+}
\ No newline at end of file