+ {{/attack}}
+ {{^attack}}
+
+ {{/attack}}
+
+ DC
+ {{savedc}}
+
+ {{#savedesc}}
+
+ {{savedesc}}
+
+ {{/savedesc}}
+
+ {{saveattr}}
+ Save
+
+
+ {{/save}}
+ {{^attack}}
+ {{#desc}}
+
+
+ {{desc}}
+
+
+ {{/desc}}
+ {{/attack}}
+ {{#globaldamage}}
+ {{#^rollTotal() globaldamage 0}}
+
+ {{globaldamage}}{{#globaldamagecrit}}{{#^rollTotal() globaldamagecrit 0}} + {{globaldamagecrit}}{{/^rollTotal() globaldamagecrit 0}}{{/globaldamagecrit}}
+ {{globaldamagetype}}
+
+ {{/^rollTotal() globaldamage 0}}
+ {{/globaldamage}}
+ {{#globaldamage}}
+ {{#rollTotal() globaldamage 0}}
+ {{#globaldamagecrit}}
+ {{#^rollTotal() globaldamagecrit 0}}
+
+ {{globaldamagecrit}}
+ {{globaldamagetype}}
+
+ {{/^rollTotal() globaldamagecrit 0}}
+ {{/globaldamagecrit}}
+ {{/rollTotal() globaldamage 0}}
+ {{/globaldamage}}
+ {{^globaldamage}}
+ {{#globaldamagecrit}}
+ {{#^rollTotal() globaldamagecrit 0}}
+
+ {{globaldamagecrit}}
+ {{globaldamagetype}}
+
+ {{/^rollTotal() globaldamagecrit 0}}
+ {{/globaldamagecrit}}
+ {{/globaldamage}}
+ {{#hldmg}}
+ {{#^rollTotal() hldmg 0}}
+
+
{{hldmg}}{{#hldmgcrit}} + {{hldmgcrit}}{{/hldmgcrit}}
+
{{dmg1type}}
+
+ Higher Level Cast
+
+
+ {{/^rollTotal() hldmg 0}}
+ {{/hldmg}}
+
+
+ {{#dmg1flag}}
+ {{^dmg2flag}}
+
+ {{dmg1}}{{#crit}} + {{crit1}}{{/crit}}
+ {{dmg1type}}
+
+ {{/dmg2flag}}
+ {{/dmg1flag}}
+ {{#dmg2flag}}
+ {{^dmg1flag}}
+
+ {{dmg2}}{{#crit}} + {{crit2}}{{/crit}}
+ {{dmg2type}}
+
+ {{/dmg1flag}}
+ {{/dmg2flag}}
+ {{#dmg1flag}}
+ {{#dmg2flag}}
+
+ {{dmg1}}{{#crit}} + {{crit1}}{{/crit}}
+ {{dmg1type}}
+
+
+
+ {{dmg2}}{{#crit}} + {{crit2}}{{/crit}}
+ {{dmg2type}}
+
+ {{/dmg2flag}}
+ {{/dmg1flag}}
+
+ {{^attack}}
+ {{#range}}
+
+ {{range}}
+
+ {{/range}}
+
+ {{rname}}{{#innate}}, {{innate}}{{/innate}}
+
+ {{#charname}}
+
+ {{charname}}
+
+ {{/charname}}
+ {{#spelldesc_link}}
+
+ {{spelldesc_link}}
+
+ {{/spelldesc_link}}
+ {{/attack}}
+
+
\ No newline at end of file
diff --git a/Brancalonia Official/src/html/description.html b/Brancalonia Official/src/html/description.html
new file mode 100644
index 0000000000..e131e97739
--- /dev/null
+++ b/Brancalonia Official/src/html/description.html
@@ -0,0 +1,9 @@
+
+
+
+
+ {{desc}}
+
+
+
+
\ No newline at end of file
diff --git a/Brancalonia Official/src/html/dmgaction.html b/Brancalonia Official/src/html/dmgaction.html
new file mode 100644
index 0000000000..8f237b8c49
--- /dev/null
+++ b/Brancalonia Official/src/html/dmgaction.html
@@ -0,0 +1,28 @@
+
+
+
+ {{#name}}
+
+ {{/name}}
+
+
Damage:
+
+ {{#dmg1flag}}
+ {{dmg1}}{{#crit}} + {{crit1}}{{/crit}}{{dmg1type}}
+ {{/dmg1flag}}
+ {{#dmg1flag}}{{#dmg2flag}}+{{/dmg2flag}}{{/dmg1flag}}
+ {{#dmg2flag}}
+ {{dmg2}}{{#crit}} + {{crit2}}{{/crit}}{{dmg2type}}
+ {{/dmg2flag}}
+
+
+ {{#description}}
+
+ {{description}}
+
+ {{/description}}
+
\ No newline at end of file
diff --git a/Brancalonia Official/src/html/npc.html b/Brancalonia Official/src/html/npc.html
new file mode 100644
index 0000000000..bac64f55db
--- /dev/null
+++ b/Brancalonia Official/src/html/npc.html
@@ -0,0 +1,41 @@
+
+
+ {{#name}}
+
+ {{/name}}
+
+
+ {{#normal}}
+ {{type}}: {{r1}}
+ {{/normal}}
+ {{#always}}
+ {{type}}: {{r1}} | {{r2}}
+ {{/always}}
+ {{#advantage}}
+ {{#rollLess() r1 r2}}
+ {{type}}: {{r1}} | {{r2}}
+ {{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}
+ {{type}}: {{r1}} | {{r2}}
+ {{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}
+ {{type}}: {{r1}} | {{r2}}
+ {{/rollGreater() r1 r2}}
+ {{/advantage}}
+ {{#disadvantage}}
+ {{#rollLess() r1 r2}}
+ {{type}}: {{r1}} | {{r2}}
+ {{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}
+ {{type}}: {{r1}} | {{r2}}
+ {{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}
+ {{type}}: {{r1}} | {{r2}}
+ {{/rollGreater() r1 r2}}
+ {{/disadvantage}}
+
+
\ No newline at end of file
diff --git a/Brancalonia Official/src/html/npcaction.html b/Brancalonia Official/src/html/npcaction.html
new file mode 100644
index 0000000000..fbe5b83dd2
--- /dev/null
+++ b/Brancalonia Official/src/html/npcaction.html
@@ -0,0 +1,96 @@
+
+
+
+ {{#name}}
+
+ {{/name}}
+
+ {{#attack}}
+
+ {{#normal}}
+ Attack: {{r1}}
+ {{/normal}}
+ {{#always}}
+ Attack: {{r1}} | {{r2}}
+ {{/always}}
+ {{#advantage}}
+ {{#rollLess() r1 r2}}
+ Attack: {{r1}} | {{r2}}
+ {{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}
+ Attack: {{r1}} | {{r2}}
+ {{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}
+ Attack: {{r1}} | {{r2}}
+ {{/rollGreater() r1 r2}}
+ {{/advantage}}
+ {{#disadvantage}}
+ {{#rollLess() r1 r2}}
+ Attack: {{r1}} | {{r2}}
+ {{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}
+ Attack: {{r1}} | {{r2}}
+ {{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}
+ Attack: {{r1}} | {{r2}}
+ {{/rollGreater() r1 r2}}
+ {{/disadvantage}}
+
+ {{/attack}}
+ {{#description}}
+
{{description}}
+ {{/description}}
+
+ {{#damage}}
+
+ Damage:
+
+ {{#dmg1flag}}
+ {{dmg1}}
+ {{#normal}}
+ {{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}
+ {{/normal}}
+ {{#always}}
+ {{#rollLess() r1 r2}}{{#rollWasCrit() r2}} + {{crit1}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
+ {{/always}}
+ {{#advantage}}
+ {{#rollLess() r1 r2}}{{#rollWasCrit() r2}} + {{crit1}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
+ {{/advantage}}
+ {{#disadvantage}}
+ {{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
+ {{/disadvantage}}
+ {{dmg1type}}
+ {{/dmg1flag}}
+ {{#dmg1flag}}{{#dmg2flag}}+{{/dmg2flag}}{{/dmg1flag}}
+ {{#dmg2flag}}
+ {{dmg2}}
+ {{#normal}}
+ {{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}
+ {{/normal}}
+ {{#always}}
+ {{#rollLess() r1 r2}}{{#rollWasCrit() r2}} + {{crit2}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
+ {{/always}}
+ {{#advantage}}
+ {{#rollLess() r1 r2}}{{#rollWasCrit() r2}} + {{crit2}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
+ {{/advantage}}
+ {{#disadvantage}}
+ {{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
+ {{/disadvantage}}
+ {{dmg2type}}
+ {{/dmg2flag}}
+
+
+ {{/damage}}
+
\ No newline at end of file
diff --git a/Brancalonia Official/src/html/npcattack.html b/Brancalonia Official/src/html/npcattack.html
new file mode 100644
index 0000000000..a485bec7f3
--- /dev/null
+++ b/Brancalonia Official/src/html/npcattack.html
@@ -0,0 +1,93 @@
+
+
+ {{#name}}
+
+ {{/name}}
+
+
+ {{#normal}}
+ {{#rollWasCrit() r1}}{{typec}}: {{/rollWasCrit() r1}}
+ {{#^rollWasCrit() r1}}{{type}}: {{/^rollWasCrit() r1}}
+ {{/normal}}
+ {{#always}}
+ {{#rollLess() r1 r2}}{{#rollWasCrit() r2}}{{typec}}: {{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}{{typec}}: {{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}{{typec}}: {{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
+ {{#^rollWasCrit() r1}}{{#^rollWasCrit() r2}}{{type}}: {{/^rollWasCrit() r2}}{{/^rollWasCrit() r1}}
+ {{/always}}
+ {{#advantage}}
+ {{#rollLess() r1 r2}}{{#rollWasCrit() r2}}[{{typec}}: {{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}{{typec}}: {{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}{{typec}}: {{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
+ {{#^rollWasCrit() r1}}{{#^rollWasCrit() r2}}{{type}}: {{/^rollWasCrit() r2}}{{/^rollWasCrit() r1}}
+ {{/advantage}}
+ {{#disadvantage}}
+ {{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}{{typec}}: {{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
+ {{#rollTotal() r1 r2}}{{#^rollWasCrit() r1}}{{type}}: {{/^rollWasCrit() r1}}{{/rollTotal() r1 r2}}
+ {{#rollLess() r1 r2}}{{#rollWasCrit() r1}}{{typec}}: {{/rollWasCrit() r1}}{{/rollLess() r1 r2}}
+ {{#rollLess() r1 r2}}{{#^rollWasCrit() r1}}{{type}}: {{/^rollWasCrit() r1}}{{/rollLess() r1 r2}}
+ {{#rollGreater() r1 r2}}{{#rollWasCrit() r2}}{{typec}}: {{/rollWasCrit() r2}}{{/rollGreater() r1 r2}}
+ {{#rollGreater() r1 r2}}{{#^rollWasCrit() r2}}{{type}}: {{/^rollWasCrit() r2}}{{/rollGreater() r1 r2}}
+ {{/disadvantage}}
+ {{#normal}}
+ {{r1}}
+ {{/normal}}
+ {{#always}}
+ {{r1}} | {{r2}}
+ {{/always}}
+ {{#advantage}}
+ {{#rollLess() r1 r2}}
+ {{r1}} | {{r2}}
+ {{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}
+ {{r1}} | {{r2}}
+ {{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}
+ {{r1}} | {{r2}}
+ {{/rollGreater() r1 r2}}
+ {{/advantage}}
+ {{#disadvantage}}
+ {{#rollLess() r1 r2}}
+ {{r1}} | {{r2}}
+ {{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}
+ {{r1}} | {{r2}}
+ {{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}
+ {{r1}} | {{r2}}
+ {{/rollGreater() r1 r2}}
+ {{/disadvantage}}
+
+ {{#description}}
+
+ {{description}}
+
+ {{/description}}
+
\ No newline at end of file
diff --git a/Brancalonia Official/src/html/npcdmg.html b/Brancalonia Official/src/html/npcdmg.html
new file mode 100644
index 0000000000..b0be6ae490
--- /dev/null
+++ b/Brancalonia Official/src/html/npcdmg.html
@@ -0,0 +1,19 @@
+
+
+ Damage:
+
+ {{#dmg1flag}}
+ {{dmg1}}{{#crit}} + {{crit1}}{{/crit}}{{dmg1type}}
+ {{/dmg1flag}}
+ {{#dmg1flag}}{{#dmg2flag}}+{{/dmg2flag}}{{/dmg1flag}}
+ {{#dmg2flag}}
+ {{dmg2}}{{#crit}} + {{crit2}}{{/crit}}{{dmg2type}}
+ {{/dmg2flag}}
+
+
+ {{#description}}
+
+ {{description}}
+
+ {{/description}}
+
\ No newline at end of file
diff --git a/Brancalonia Official/src/html/npcfullatk.html b/Brancalonia Official/src/html/npcfullatk.html
new file mode 100644
index 0000000000..6c701f5d0d
--- /dev/null
+++ b/Brancalonia Official/src/html/npcfullatk.html
@@ -0,0 +1,98 @@
+
+
+
+ {{#name}}
+
+ {{/name}}
+
+ {{#attack}}
+
+ {{#normal}}
+ Attack: {{r1}}
+ {{/normal}}
+ {{#always}}
+ Attack: {{r1}} | {{r2}}
+ {{/always}}
+ {{#advantage}}
+ {{#rollLess() r1 r2}}
+ Attack: {{r1}} | {{r2}}
+ {{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}
+ Attack: {{r1}} | {{r2}}
+ {{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}
+ Attack: {{r1}} | {{r2}}
+ {{/rollGreater() r1 r2}}
+ {{/advantage}}
+ {{#disadvantage}}
+ {{#rollLess() r1 r2}}
+ Attack: {{r1}} | {{r2}}
+ {{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}
+ Attack: {{r1}} | {{r2}}
+ {{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}
+ Attack: {{r1}} | {{r2}}
+ {{/rollGreater() r1 r2}}
+ {{/disadvantage}}
+
+ {{/attack}}
+
+
+
Damage:
+ {{#damage}}
+
+ {{#dmg1flag}}
+ {{dmg1}}
+ {{#normal}}
+ {{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}
+ {{/normal}}
+ {{#always}}
+ {{#rollLess() r1 r2}}{{#rollWasCrit() r2}} + {{crit1}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
+ {{/always}}
+ {{#advantage}}
+ {{#rollLess() r1 r2}}{{#rollWasCrit() r2}} + {{crit1}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
+ {{/advantage}}
+ {{#disadvantage}}
+ {{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
+ {{/disadvantage}}
+ {{dmg1type}}
+ {{/dmg1flag}}
+ {{#dmg1flag}}{{#dmg2flag}}+{{/dmg2flag}}{{/dmg1flag}}
+ {{#dmg2flag}}
+ {{dmg2}}
+ {{#normal}}
+ {{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}
+ {{/normal}}
+ {{#always}}
+ {{#rollLess() r1 r2}}{{#rollWasCrit() r2}} + {{crit2}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
+ {{/always}}
+ {{#advantage}}
+ {{#rollLess() r1 r2}}{{#rollWasCrit() r2}} + {{crit2}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
+ {{/advantage}}
+ {{#disadvantage}}
+ {{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
+ {{/disadvantage}}
+ {{dmg2type}}
+ {{/dmg2flag}}
+
+ {{/damage}}
+ {{#description}}
+
+ {{description}}
+
+ {{/description}}
+
+
\ No newline at end of file
diff --git a/Brancalonia Official/src/html/simple.html b/Brancalonia Official/src/html/simple.html
new file mode 100644
index 0000000000..7f45206661
--- /dev/null
+++ b/Brancalonia Official/src/html/simple.html
@@ -0,0 +1,91 @@
+
+
+
+ {{#always}}
+
+ {{r1}}{{#global}} + {{global}}{{/global}}
+
+
+
+ {{r2}}{{#global}} + {{global}}{{/global}}
+
+ {{/always}}
+ {{#normal}}
+
+ {{r1}}{{#global}} + {{global}}{{/global}}
+
+ {{/normal}}
+ {{#advantage}}
+ {{#rollLess() r1 r2}}
+
+ {{r1}}{{#global}} + {{global}}{{/global}}
+
+
+
+ {{r2}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}
+
+ {{r1}}{{#global}} + {{global}}{{/global}}
+
+
+
+ {{r2}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}
+
+ {{r1}}{{#global}} + {{global}}{{/global}}
+
+
+
+ {{r2}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollGreater() r1 r2}}
+ {{/advantage}}
+ {{#disadvantage}}
+ {{#rollLess() r1 r2}}
+
+ {{r1}}{{#global}} + {{global}}{{/global}}
+
+
+
+ {{r2}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}
+
+ {{r1}}{{#global}} + {{global}}{{/global}}
+
+
+
+ {{r2}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}
+
+ {{r1}}{{#global}} + {{global}}{{/global}}
+
+
+
+ {{r2}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollGreater() r1 r2}}
+ {{#imposed}}
+
+ {{imposed}}
+
+ {{/imposed}}
+ {{/disadvantage}}
+
+
+ {{rname}}{{#mod}} ({{mod}}){{/mod}}
+
+ {{#charname}}
+
+ {{charname}}
+
+ {{/charname}}
+
+
diff --git a/Brancalonia Official/src/html/simple3d.html b/Brancalonia Official/src/html/simple3d.html
new file mode 100644
index 0000000000..964bc0c296
--- /dev/null
+++ b/Brancalonia Official/src/html/simple3d.html
@@ -0,0 +1,91 @@
+
+
+
+ {{#always}}
+
+ {{r1}}{{r3}}{{#global}} + {{global}}{{/global}}
+
+
+
+ {{r2}}{{r3}}{{#global}} + {{global}}{{/global}}
+
+ {{/always}}
+ {{#normal}}
+
+ {{r1}}{{r3}}{{#global}} + {{global}}{{/global}}
+
+ {{/normal}}
+ {{#advantage}}
+ {{#rollLess() r1 r2}}
+
+ {{r1}}{{r3}}{{#global}} + {{global}}{{/global}}
+
+
+
+ {{r2}}{{r3}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}
+
+ {{r1}}{{r3}}{{#global}} + {{global}}{{/global}}
+
+
+
+ {{r2}}{{r3}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}
+
+ {{r1}}{{r3}}{{#global}} + {{global}}{{/global}}
+
+
+
+ {{r2}}{{r3}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollGreater() r1 r2}}
+ {{/advantage}}
+ {{#disadvantage}}
+ {{#rollLess() r1 r2}}
+
+ {{r1}}{{r3}}{{#global}} + {{global}}{{/global}}
+
+
+
+ {{r2}}{{r3}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}
+
+ {{r1}}{{r3}}{{#global}} + {{global}}{{/global}}
+
+
+
+ {{r2}}{{r3}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}
+
+ {{r1}}{{r3}}{{#global}} + {{global}}{{/global}}
+
+
+
+ {{r2}}{{r3}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollGreater() r1 r2}}
+ {{#imposed}}
+
+ {{imposed}}
+
+ {{/imposed}}
+ {{/disadvantage}}
+
+
+ {{rname}}{{#mod}} ({{mod}}){{/mod}}
+
+ {{#charname}}
+
+ {{charname}}
+
+ {{/charname}}
+
+
\ No newline at end of file
diff --git a/Brancalonia Official/src/html/skill.html b/Brancalonia Official/src/html/skill.html
new file mode 100644
index 0000000000..022e28b8bb
--- /dev/null
+++ b/Brancalonia Official/src/html/skill.html
@@ -0,0 +1,125 @@
+
+
+
+ {{#always}}
+
+ {{r1}}{{#global}} + {{global}}{{/global}}
+
+
+ {{r2}}{{#global}} + {{global}}{{/global}}
+
+ {{#rollGreater() reliablecheck 0}}
+ {{#rollLess() r1 reliableroll}}
+ {{#rollLess() r2 reliableroll}}
+
+ {{reliableroll}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollLess() r2 reliableroll}}
+ {{/rollLess() r1 reliableroll}}
+ {{/rollGreater() reliablecheck 0}}
+ {{/always}}
+ {{#normal}}
+
+ {{r1}}{{#global}} + {{global}}{{/global}}
+
+ {{#rollGreater() reliablecheck 0}}
+ {{#rollLess() r1 reliableroll}}
+
+ {{reliableroll}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollLess() r1 reliableroll}}
+ {{/rollGreater() reliablecheck 0}}
+ {{/normal}}
+ {{#advantage}}
+ {{#rollLess() r1 r2}}
+
+ {{r1}}{{#global}} + {{global}}{{/global}}
+
+
+ {{r2}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}
+
+ {{r1}}{{#global}} + {{global}}{{/global}}
+
+
+ {{r2}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}
+
+ {{r1}}{{#global}} + {{global}}{{/global}}
+
+
+ {{r2}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollGreater() r1 r2}}
+ {{#rollGreater() reliablecheck 0}}
+ {{#rollLess() r1 reliableroll}}
+ {{#rollLess() r2 reliableroll}}
+
+ {{reliableroll}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollLess() r2 reliableroll}}
+ {{/rollLess() r1 reliableroll}}
+ {{/rollGreater() reliablecheck 0}}
+ {{/advantage}}
+ {{#disadvantage}}
+ {{#rollLess() r1 r2}}
+
+ {{r1}}{{#global}} + {{global}}{{/global}}
+
+
+ {{r2}}{{#global}} + {{global}}{{/global}}
+
+ {{#rollGreater() reliablecheck 0}}
+ {{#rollLess() r1 reliableroll}}
+
+ {{reliableroll}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollLess() r1 reliableroll}}
+ {{/rollGreater() reliablecheck 0}}
+ {{/rollLess() r1 r2}}
+ {{#rollTotal() r1 r2}}
+
+ {{r1}}{{#global}} + {{global}}{{/global}}
+
+
+ {{r2}}{{#global}} + {{global}}{{/global}}
+
+ {{#rollGreater() reliablecheck 0}}
+ {{#rollLess() r1 reliableroll}}
+
+ {{reliableroll}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollLess() r1 reliableroll}}
+ {{/rollGreater() reliablecheck 0}}
+ {{/rollTotal() r1 r2}}
+ {{#rollGreater() r1 r2}}
+
+ {{r1}}{{#global}} + {{global}}{{/global}}
+
+
+ {{r2}}{{#global}} + {{global}}{{/global}}
+
+ {{#rollGreater() reliablecheck 0}}
+ {{#rollLess() r2 reliableroll}}
+
+ {{reliableroll}}{{#global}} + {{global}}{{/global}}
+
+ {{/rollLess() r2 reliableroll}}
+ {{/rollGreater() reliablecheck 0}}
+ {{/rollGreater() r1 r2}}
+ {{/disadvantage}}
+
+
+ {{rname}}{{#mod}} ({{mod}}){{/mod}}
+
+ {{#charname}}
+
+ {{charname}}
+
+ {{/charname}}
+
+
\ No newline at end of file
diff --git a/Brancalonia Official/src/html/spell.html b/Brancalonia Official/src/html/spell.html
new file mode 100644
index 0000000000..ead7cac3fc
--- /dev/null
+++ b/Brancalonia Official/src/html/spell.html
@@ -0,0 +1,56 @@
+
+
+
+ {{name}}{{#innate}}, {{innate}}{{/innate}}
+
+
+ {{#level}}{{level}} {{/level}}
+ {{#ritual}} (){{/ritual}}
+
+
+ {{#castingtime}}
+
+ Casting Time: {{castingtime}}
+
+ {{/castingtime}}
+ {{#range}}
+
+ Range: {{range}}
+
+ {{/range}}
+ {{#target}}
+
+ Target: {{target}}
+
+ {{/target}}
+
+ Components:
+
+ {{#v}}V{{#s}}, {{/s}}{{^s}}{{#m}}, {{/m}}{{/s}}{{/v}}
+ {{#s}}S{{#m}}, {{/m}}{{/s}}
+ {{#m}}M {{#material}}({{material}}){{/material}}{{/m}}
+
+
+ {{#duration}}
+
+ Duration: {{#concentration}}Concentration {{/concentration}}{{duration}}
+
+ {{/duration}}
+
+ {{#description}}
+
+ {{description}}
+
+ {{/description}}
+ {{#athigherlevels}}
+
+ At Higher Levels. {{athigherlevels}}
+
+ {{/athigherlevels}}
+ {{#savedc}}
+
+ SPELL SAVE DC: {{savedc}}
+
+ {{/savedc}}
+
+
\ No newline at end of file
diff --git a/Brancalonia Official/src/html/spelloutput.html b/Brancalonia Official/src/html/spelloutput.html
new file mode 100644
index 0000000000..8aa795924f
--- /dev/null
+++ b/Brancalonia Official/src/html/spelloutput.html
@@ -0,0 +1,59 @@
+
+
+
+ For Description Only
+
+
+ {{name}}{{#innate}}, {{innate}}{{/innate}}
+
+
+ {{#level}}{{level}} {{/level}}
+ {{#ritual}} (){{/ritual}}
+
+
+ {{#castingtime}}
+
+ Casting Time: {{castingtime}}
+
+ {{/castingtime}}
+ {{#range}}
+
+ Range: {{range}}
+
+ {{/range}}
+ {{#target}}
+
+ Target: {{target}}
+
+ {{/target}}
+
+ Components:
+
+ {{#v}}V{{#s}}, {{/s}}{{^s}}{{#m}}, {{/m}}{{/s}}{{/v}}
+ {{#s}}S{{#m}}, {{/m}}{{/s}}
+ {{#m}}M {{#material}}({{material}}){{/material}}{{/m}}
+
+
+ {{#duration}}
+
+ Duration: {{#concentration}}Concentration {{/concentration}}{{duration}}
+
+ {{/duration}}
+
+ {{#description}}
+
+ {{description}}
+
+ {{/description}}
+ {{#athigherlevels}}
+
+ At Higher Levels. {{athigherlevels}}
+
+ {{/athigherlevels}}
+ {{#savedc}}
+
+ SPELL SAVE DC: {{savedc}}
+
+ {{/savedc}}
+
+
\ No newline at end of file
diff --git a/Brancalonia Official/src/html/traits.html b/Brancalonia Official/src/html/traits.html
new file mode 100644
index 0000000000..7ce0014f0a
--- /dev/null
+++ b/Brancalonia Official/src/html/traits.html
@@ -0,0 +1,15 @@
+
+
+ {{#source}}
+
+ {{/source}}
+ {{#description}}
+
+ {{description}}
+
+ {{/description}}
+
\ No newline at end of file
diff --git a/Brancalonia Official/src/js/Classes/DropClasses/DropClasses.js b/Brancalonia Official/src/js/Classes/DropClasses/DropClasses.js
new file mode 100644
index 0000000000..ee85dff91c
--- /dev/null
+++ b/Brancalonia Official/src/js/Classes/DropClasses/DropClasses.js
@@ -0,0 +1,488 @@
+class RepeatingFieldset {
+ constructor(groupname, id) {
+ this.groupname = groupname;
+ this.reprowid = id || generateRowID();
+ }
+
+ buildRowName() {
+ return `repeating_${this.groupname}_${this.reprowid}`
+ }
+
+ addAttribute(attributesibuteName) {
+ return `${this.buildRowName()}_${attributesibuteName}`
+ }
+}
+
+class Attack extends RepeatingFieldset {
+ constructor(name, id) {
+ super('attack', id)
+ this.attributes = {
+ atkname: name,
+ atkbonus: '', //Part of button display
+ atkdmgtype: '', //Part of button display
+ atkflag: '{{attack=1}}',
+ atkattr_base: '@{strength_mod}',
+ atkrange: '',
+ atkmagic: '',
+ atkcritrange: 20,
+ dmgflag: '{{damage=1}} {{dmg1flag=1}}',
+ dmgbase: '',
+ dmgattr: '@{strength_mod}',
+ dmgmod: '',
+ dmgtype: '',
+ dmgcustcrit: '',
+ dmg2flag: 0,
+ dmg2base: '',
+ dmg2attr: 0,
+ dmg2mod: '',
+ dmg2type: '',
+ dmg2custcrit: '',
+ saveflag: 0,
+ saveattr: 'Strength',
+ savedc: '(@{spell_save_dc})',
+ saveflat: '',
+ saveeffect: '',
+ atk_desc: '',
+ "options-flag": 0,
+ }
+ }
+
+ addSaveFlag() {
+ this.attributes.saveflag = '{{save=1}} {{saveattr=@{saveattr}}} {{savedesc=@{saveeffect}}} {{savedc=[[[[@{savedc}]][SAVE]]]}}'
+ }
+
+ checkFinesse(strenght, dexterity) {
+ const strengthGreaterThanDex = strenght > dexterity;
+ this.attributes.dmgattr = strengthGreaterThanDex ? '@{strength_mod}' : '@{dexterity_mod}'
+ this.attributes.atkattr_base = strengthGreaterThanDex ? '@{strength_mod}' : '@{dexterity_mod}'
+ }
+}
+
+class GlobalACMod extends RepeatingFieldset {
+ constructor(name, id) {
+ super('acmod', id)
+ name,
+ this.attributes = {
+ global_ac_name: name,
+ global_ac_val: '',
+ global_ac_active_flag: 0,
+ "options-flag": 0,
+ }
+ }
+}
+
+class GlobalDamage extends RepeatingFieldset {
+ constructor(name, id) {
+ super('damagemod', id)
+ name,
+ this.attributes = {
+ global_damage_name: name,
+ global_damage_damage: '',
+ global_damage_type: '',
+ global_damage_active_flag: 0,
+ "options-flag": 0
+ }
+ }
+}
+
+class GlobalSave extends RepeatingFieldset {
+ constructor(name, id) {
+ super('savemod', id)
+ name,
+ this.attributes = {
+ global_save_name: name,
+ global_save_roll: '',
+ global_save_active_flag: 0,
+ "options-flag": 0
+ }
+ }
+}
+
+class GlobalAttack extends RepeatingFieldset {
+ constructor(name, id) {
+ super('tohitmod', id)
+ name,
+ this.attributes = {
+ global_attack_name: name,
+ global_attack_roll: '',
+ global_attack_rollstring: '',
+ global_attack_active_flag: 0,
+ "options-flag": 0
+ }
+ }
+
+ addRoll(roll) {
+ this.attributes.global_attack_roll = roll;
+ }
+}
+
+class HPMod extends RepeatingFieldset {
+ constructor(name, id) {
+ super('hpmod', id)
+ name,
+ this.attributes = {
+ mod: '',
+ source: '',
+ levels: 'total'
+ }
+ }
+}
+
+class Item extends RepeatingFieldset {
+ constructor(name, id) {
+ super('inventory', id);
+ name,
+ this.attributes = {
+ itemname: name,
+ itemcount: 1,
+ itemproperties: '',
+ itemweight: 0,
+ itemcontent: '',
+ itemmodifiers: '',
+ hasattack: 0,
+ useasresource: 0
+ }
+ }
+}
+
+class Proficiency extends RepeatingFieldset {
+ constructor(name, id) {
+ super('proficiencies', id);
+ this.attributes = {
+ name,
+ prof_type: 'OTHER',
+ 'options-flag': 0
+ }
+ }
+}
+
+class Resource extends RepeatingFieldset {
+ constructor(name, id, side) {
+ super('resource', id);
+ this.side = side || 'left',
+ this.attributes = {
+ [`resource_${this.side}`]: '',
+ [`resource_${this.side}_name`]: name,
+ [`resource_${this.side}_max`]: '',
+ }
+ }
+}
+
+class Spell extends RepeatingFieldset {
+ constructor(name, section, id) {
+ super(section, id);
+ this.attributes = {
+ 'details-flag': 0,
+ 'options-flag': 0,
+ rollcontent: '',
+ spell_ability: 'spell',
+ innate: '',
+ spell_damage_progression: '',
+ spellathigherlevels: '',
+ spellattack: '',
+ spellcastingtime: '',
+ spellclass: '',
+ spellcomp_m: 0,
+ spellcomp_materials: '',
+ spellcomp_s: 0,
+ spellcomp_v: 0,
+ spellconcentration: '',
+ spelldamage2: '',
+ spelldamage: '',
+ spelldamagetype2: '',
+ spelldamagetype: '',
+ spelldescription: '',
+ spelldmgmod: '',
+ spellduration: '',
+ spellhealing: '',
+ spellhlbonus: '',
+ spellhldie: '',
+ spellhldietype: '',
+ spelllevel: 'cantrip',
+ spellname: name,
+ spelloutput: 'SPELLCARD',
+ spellrange: '',
+ spellritual: '',
+ spellsave: '',
+ spellsavesuccess: '',
+ spellschool: 'abjuration',
+ spellsource: '',
+ spelltarget: ''
+ }
+ }
+}
+
+class Trait extends RepeatingFieldset {
+ constructor(name, id) {
+ super('traits', id);
+ this.attributes = {
+ name,
+ description: '',
+ source_type: '',
+ source: '',
+ edit: "0",
+ display_flag: 'on'
+ };
+ }
+
+ determineSource(category) {
+ switch (category) {
+ case "Backgrounds":
+ case "Feats":
+ return category.slice(0, -1)
+ break;
+ case "Races":
+ case "Subraces":
+ return "Racial"
+ break;
+ case "Classes":
+ case "Subclasses":
+ return "Class"
+ break;
+ default:
+ return "Other"
+ }
+ }
+}
+
+class ToolProficiency extends RepeatingFieldset {
+ constructor(name, id) {
+ super('tool', id);
+ this.attributes = {
+ toolname: name,
+ toolbonus_base: '(@{pb})',
+ toolattr_base: '?{Attribute?|Strength,@{strength_mod}|Dexterity,@{dexterity_mod}|Constitution,@{constitution_mod}|Intelligence,@{intelligence_mod}|Wisdom,@{wisdom_mod}|Charisma,@{charisma_mod}}',
+ 'options-flag': 0
+ }
+ }
+}
+
+//========== Non-Repeating
+
+class Class {
+ constructor(name) {
+ name,
+ this.attributes = {
+ class: this.validateClassName(name) ? name : '',
+ base_level: 1,
+ hit_dice_max: 1,
+ hit_dice: 1,
+ hitdietype: 4,
+ spellcasting_ability: '0*'
+ }
+ }
+
+ validateClassName(name) {
+ return globalAttributesByCategory.classes.includes(name.toLowerCase()) ? true : false;
+ }
+
+ buildSpellcastingAbility(attributeName) {
+ return `@{${attributeName}_mod}+`
+ }
+}
+
+class CustomAC {
+ constructor(name) {
+ name,
+ this.attributes = {
+ custom_ac_flag: 1,
+ custom_ac_base: 10,
+ custom_ac_part1: 'none',
+ custom_ac_part2: 'none',
+ custom_ac_shield: 'yes'
+ }
+ }
+}
+
+class Race {
+ constructor(name) {
+ name,
+ this.attributes = {
+ race: name,
+ speed: 30,
+ size: 'Medium',
+ halflingluck_flag: this.checkHalfling(name) ? 1 : 0
+ }
+ }
+
+ checkHalfling(name) {
+ return name === 'Halfling' ? true : false
+ }
+}
+
+class Subrace {
+ constructor(name) {
+ name,
+ this.attributes = {
+ subrace: name
+ }
+ }
+}
+
+class SavingThrow {
+ constructor(name) {
+ name,
+ this.attributes = {
+ [`${this.attributesName(name)}_save_prof`]: `(@{pb})`
+ }
+ }
+
+ attributesName(name) {
+ return name.toLowerCase()
+ }
+}
+
+class Skill {
+ constructor(name) {
+ name,
+ this.attributes = {
+ [`${this.attributesName(name)}_prof`]: `(@{pb}*@{${this.attributesName(name)}_type})`
+ }
+ }
+
+ attributesName(name) {
+ return name.toLowerCase().replace(/ /g, '_')
+ }
+}
+
+class Subclass {
+ constructor(name) {
+ name,
+ this.attributes = {
+ subclass: name,
+ arcane_fighter: 0,
+ arcane_rogue: 0
+ }
+ }
+
+ checkArcane(className) {
+ return className === 'fighter' || className === 'rogue' ? true : false
+ }
+
+ buildSpellcastingAbility(attributeName) {
+ return `@{${attributeName}_mod}+`
+ }
+}
+
+//========== NPC AKA MONSTERS
+
+class Npc {
+ constructor(name) {
+ name,
+ this.attributes = {
+ npc_name: name,
+ strength_base: 10,
+ dexterity_base: 10,
+ constitution_base: 10,
+ intelligence_base: 10,
+ wisdom_base: 10,
+ charisma_base: 10,
+ npc_condition_immunities: '',
+ npc_immunities: '',
+ npc_resistances: '',
+ npc_languages: '',
+ npc_speed: '',
+ token_size: 1,
+ npc_vulnerabilities: '',
+ npc_challenge: '',
+ npc_senses: '',
+ npc_type: '',
+ npc_ac: '',
+ npc_actype: '',
+ hp_max: '',
+ npc_hpformula: '',
+ npc_xp: '',
+ npc_legendary_actions: 0,
+ npc_legendary_actions_desc: '',
+ npc_mythic_actions: 0,
+ npc_mythic_actions_desc: '',
+ npc: 1,
+ 'npc_options-flag': 0,
+ npcreactionsflag: 0,
+ npcspellcastingflag: 0,
+ spellcasting_ability: '0*',
+ globalmagicmod: 0,
+ caster_level: 0,
+ spell_dc_mod: 0
+ }
+ }
+
+ addSkills(list) {
+ list.forEach(value => this.attributes[`npc_${value.replace(/ /g, '_')}_base`] = "")
+ }
+
+ addSaves(list) {
+ list.forEach(value => this.attributes[`npc_${value.slice(0, 3)}_save_base`] = "")
+ }
+
+ addSpellcaster(ability, casterLevels) {
+ const spellcastrAttributes = {
+ npcspellcastingflag: 1,
+ base_level: casterLevels || 1,
+ caster_level: casterLevels || 1,
+ class: 'Wizard',
+ level: casterLevels || 1,
+ spellcasting_ability: ability
+ }
+
+ Object.assign(this.attributes, spellcastrAttributes);
+ }
+
+ addInnateCaster() {
+ this.attributes.npcspellcastingflag = 1
+ }
+}
+
+class NpcAction extends RepeatingFieldset {
+ constructor(name, section, id) {
+ super(section, id);
+ name,
+ this.attributes = {
+ name,
+ description: '',
+ edit: "0",
+ }
+ }
+
+ addAttack() {
+ const attackAttributes = {
+ attack_flag: 'on',
+ attack_display_flag: '{{attack=1}}',
+ attack_options: '{{attack=1}}',
+ attack_type: '',
+ attack_target: 'one target',
+ attack_range: '5 ft',
+ attack_tohit: '',
+ attack_damage: '',
+ attack_damagetype: '',
+ attack_damage2: '',
+ attack_damagetype2: ''
+ }
+
+ Object.assign(this.attributes, attackAttributes);
+ }
+}
+
+class NpcReaction extends RepeatingFieldset {
+ constructor(name, id) {
+ super('npcreaction', id)
+ name,
+ this.attributes = {
+ name,
+ edit: "0",
+ description: ''
+ }
+ }
+}
+
+class NpcTraits extends RepeatingFieldset {
+ constructor(name, id) {
+ super('npctrait', id)
+ name,
+ this.attributes = {
+ name,
+ edit_trait: "0",
+ description: ''
+ }
+ }
+}
diff --git a/Brancalonia Official/src/js/Classes/FlagManager/FlagManager.js b/Brancalonia Official/src/js/Classes/FlagManager/FlagManager.js
new file mode 100644
index 0000000000..7a5039b97b
--- /dev/null
+++ b/Brancalonia Official/src/js/Classes/FlagManager/FlagManager.js
@@ -0,0 +1,118 @@
+class RefereceSet extends Set {
+ constructor(...args) {
+ super(...args);
+ }
+ toggle(value) {
+ const toggleLookup = {
+ true: 'delete',
+ false: 'add'
+ };
+ const hasValue = this.has(value);
+ return this[toggleLookup[hasValue]](value);
+ }
+}
+class FlagManager {
+ constructor(reference) {
+ this._reference = reference;
+ this._delimiter = ' ';
+ this._delimiterSafe = '_';
+ }
+ async getFlags() {
+ const entries = await this._getReferenceSet();
+ return entries;
+ }
+ async hasFlag(flag) {
+ const entries = await this._getReferenceSet();
+ return entries.has(flag);
+ }
+ async addFlag(flag) {
+ const updatedReference = await this._updateReference(flag, 'add');
+ return updatedReference;
+ }
+ async deleteFlag(flag) {
+ const updatedReference = await this._updateReference(flag, 'delete');
+ return updatedReference;
+ }
+ async toggleFlag(flag) {
+ const updatedReference = await this._updateReference(flag, 'toggle');
+ return updatedReference;
+ }
+ async _updateReference(flag, method) {
+ const sanitizedFlag = this._sanitizeFlag(flag);
+ const updatedReference = await this._setReference(sanitizedFlag, method);
+ return updatedReference;
+ }
+ async syncFlagsWithRepeatingSection(section) {
+ const flags = await this._syncFlagsWithRepeatingSection(section);
+ return flags;
+ }
+ _syncFlagsWithRepeatingSection(section) {
+ return new Promise(resolve => {
+ SheetUtils.getSectionOrder(section, order => {
+ getAttrs([this._reference], attributes => {
+ let values = "";
+ Object.keys(attributes).some(() => {
+ values += attributes[this._reference];
+ return true;
+ });
+ const flags = (values) ? values.split(' ') : [];
+ const sectionName = `repeating_${section}`;
+ const filteredArray = Array.from(flags).filter(flag => flag.includes(sectionName)).filter(flag => order.includes(SheetUtils.getUID(flag).toLowerCase()));
+ filteredArray.forEach((flag, index) => {
+ const newIndex = order.indexOf(SheetUtils.getUID(flag).toLowerCase());
+ filteredArray[index] = flag.replace(this._getFlagIndex(flag), `_${newIndex}_`);
+ });
+ const updatedSet = Array.from(flags).filter(flag => !flag.includes(sectionName)).concat(filteredArray);
+ let update = {};
+ update[this._reference] = updatedSet.join(' ');
+ setAttrs(update, () => {
+ return resolve(new Set(updatedSet));
+ });
+ });
+ });
+ });
+ }
+ _getFlagIndex(flag) {
+ const regexp = /_[0-9]+_/g;
+ const valueAsString = String(flag);
+ const match = valueAsString.match(regexp);
+ return (match) ? match.join() : "";
+ }
+ _getReferenceSet() {
+ return new Promise(resolve => {
+ getAttrs([this._reference], attributes => {
+ let values = "";
+ Object.keys(attributes).some(() => {
+ values += attributes[this._reference];
+ return true;
+ });
+ const flags = values.split(this._delimiter).filter(e => {return e});
+ return resolve(new RefereceSet(flags));
+ });
+ });
+ }
+ _setReference(sanitizedFlag, method) {
+ return new Promise(resolve => {
+ getAttrs([this._reference], attributes => {
+ let values = "";
+ Object.keys(attributes).some(() => {
+ values += attributes[this._reference];
+ return true;
+ });
+ const flags = new RefereceSet(values.split(this._delimiter).filter(e => {return e}));
+ flags[method](sanitizedFlag);
+ const flagAsString = Array.from(flags).join(this._delimiter);
+ let update = {};
+ update[this._reference] = flagAsString;
+ setAttrs(update, () => {
+ return resolve(flags);
+ });
+ });
+ });
+ }
+ _sanitizeFlag(flag) {
+ const regex = new RegExp(`${this._delimiter}`, 'g');
+ const sanitizedFlag = flag.replace(regex, this._delimiterSafe);
+ return sanitizedFlag;
+ }
+}
diff --git a/Brancalonia Official/src/js/Classes/FlagManager/test/component.html b/Brancalonia Official/src/js/Classes/FlagManager/test/component.html
new file mode 100644
index 0000000000..18a1f0108c
--- /dev/null
+++ b/Brancalonia Official/src/js/Classes/FlagManager/test/component.html
@@ -0,0 +1,60 @@
+
+
+
+
+
+
FlagManager Component
+
+
+
+
+
+
+
+
+
+
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris hendrerit cursus ex. Pellentesque pulvinar nulla justo, finibus hendrerit magna aliquam vitae.
+
+
+
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris hendrerit cursus ex. Pellentesque pulvinar nulla justo, finibus hendrerit magna aliquam vitae.
+
+
+
+
diff --git a/Brancalonia Official/src/js/Classes/FlagManager/test/tests.html b/Brancalonia Official/src/js/Classes/FlagManager/test/tests.html
new file mode 100644
index 0000000000..5d2ad7ee66
--- /dev/null
+++ b/Brancalonia Official/src/js/Classes/FlagManager/test/tests.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+
FlagManager Tests
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Brancalonia Official/src/js/Classes/FlagManager/test/tests.js b/Brancalonia Official/src/js/Classes/FlagManager/test/tests.js
new file mode 100644
index 0000000000..ebe8f9efea
--- /dev/null
+++ b/Brancalonia Official/src/js/Classes/FlagManager/test/tests.js
@@ -0,0 +1,117 @@
+QUnit.module('Basic Tests', {
+ before: function() {
+ maxAsyncDelay = 100; //Sets the mock delay for getAttrs and setAttrs to a maximum of 1000ms.
+ },
+ beforeEach: function() {
+ //Resets attributes before each test
+ attributes = {};
+ sectionIDS = {};
+ this.flagManager = new FlagManager('ui_flags');
+ }
+});
+QUnit.test('Flag Manager was initiated with zero entries', function( assert ) {
+ var done = assert.async();
+ this.flagManager.getFlags().then(flags => {
+ assert.equal(flags.size, 0);
+ done();
+ });
+});
+
+QUnit.test('One flag added to Flag Manager', function( assert ) {
+ var done = assert.async();
+ this.flagManager.addFlag('show_traits').then(flags => {
+ assert.equal(flags.size, 1);
+ assert.equal(flags.has('show_traits'), true);
+ assert.strictEqual(attributes.ui_flags, 'show_traits');
+ done();
+ });
+});
+
+QUnit.test('Two flags added to Flag Manager', function( assert ) {
+ var done = assert.async();
+ this.flagManager.addFlag('show_traits').then(() => {
+ this.flagManager.addFlag('show_spells').then(flags => {
+ assert.equal(flags.size, 2);
+ assert.equal(flags.has('show_traits'), true);
+ assert.equal(flags.has('show_spells'), true);
+ assert.strictEqual(attributes.ui_flags, 'show_traits show_spells');
+ done();
+ });
+ });
+});
+
+QUnit.test('Flag Deleted from Flag Manager', function( assert ) {
+ //Faking some attributes
+ attributes['ui_flags'] = 'show_traits show_spells show_skills';
+
+ var done = assert.async();
+ this.flagManager.deleteFlag('show_spells').then(flags => {
+ assert.equal(flags.size, 2);
+ assert.equal(flags.has('show_traits'), true);
+ assert.equal(flags.has('show_spells'), false);
+ assert.equal(flags.has('show_skills'), true);
+ assert.strictEqual(attributes.ui_flags, 'show_traits show_skills');
+ done();
+ });
+});
+
+QUnit.test('Flags correctly detected in Flag Manager', function( assert ) {
+ //Faking some attributes
+ attributes['ui_flags'] = 'show_traits show_spells show_skills';
+
+ var done1 = assert.async();
+ var done2 = assert.async();
+ this.flagManager.hasFlag('show_spells').then(hasFlag => {
+ assert.equal(hasFlag, true);
+ done1();
+ });
+ this.flagManager.hasFlag('non_existing_flag').then(hasFlag => {
+ assert.equal(hasFlag, false);
+ done2();
+ });
+});
+
+QUnit.test('Flags cant be added more than once', function( assert ) {
+ //Faking some attributes
+ attributes['ui_flags'] = 'show_traits show_spells show_skills';
+
+ var done = assert.async();
+ this.flagManager.addFlag('show_skills').then(flags => {
+ assert.equal(flags.size, 3);
+ assert.strictEqual(attributes.ui_flags, 'show_traits show_spells show_skills');
+ done();
+ });
+});
+
+QUnit.test('Order of stored flags are synced with source repeating section', function(assert) {
+ attributes['ui_flags'] = 'a_flag another_flag repeating_traits_0_name_-LzbTrhcIwpDwRZxfvEn repeating_traits_1_name_-MzbTrhcIwpDwRZxfvEn';
+ attributes['_reporder_repeating_traits'] = '-MzbTrhcIwpDwRZxfvEn,-LzbTrhcIwpDwRZxfvEn';
+ sectionIDS['repeating_traits'] = ['-LzbTrhcIwpDwRZxfvEn', '-MzbTrhcIwpDwRZxfvEn'];
+ var done = assert.async();
+ this.flagManager.syncFlagsWithRepeatingSection('traits').then(flags => {
+ var expectedTags = new Set([
+ 'a_flag',
+ 'another_flag',
+ 'repeating_traits_1_name_-LzbTrhcIwpDwRZxfvEn',
+ 'repeating_traits_0_name_-MzbTrhcIwpDwRZxfvEn'
+ ]);
+ assert.equal(Array.from(flags).join(' '), Array.from(expectedTags).join(' '));
+ done();
+ });
+});
+
+QUnit.test('Deleted flags are synced with source repeating section', function(assert) {
+ attributes = {};
+ attributes['ui_flags'] = 'a_flag another_flag repeating_traits_1_name_-LzbTrhcIwpDwRZxfvEn repeating_traits_0_name_-MzbTrhcIwpDwRZxfvEn';
+ sectionIDS['repeating_traits'] = ['-MzbTrhcIwpDwRZxfvEn'];
+ var done = assert.async();
+ this.flagManager.syncFlagsWithRepeatingSection('traits').then(flags => {
+ var expectedTags = new Set([
+ 'a_flag',
+ 'another_flag',
+ 'repeating_traits_0_name_-MzbTrhcIwpDwRZxfvEn'
+ ]);
+ assert.equal(Array.from(flags).join(' '), Array.from(expectedTags).join(' '));
+ done();
+ });
+});
\ No newline at end of file
diff --git a/Brancalonia Official/src/js/Classes/SheetUtils/SheetUtils.js b/Brancalonia Official/src/js/Classes/SheetUtils/SheetUtils.js
new file mode 100644
index 0000000000..9d2ac50f6c
--- /dev/null
+++ b/Brancalonia Official/src/js/Classes/SheetUtils/SheetUtils.js
@@ -0,0 +1,82 @@
+class SheetUtils {
+ static getUID(value) {
+ const regexp = /-.{19}(?=_)|-.{19}$/g;
+ const valueAsString = String(value);
+ const match = valueAsString.match(regexp);
+ return (match) ? match.join() : "";
+ }
+ static aOrAn(value) {
+ if(['a','e','i','o','u'].indexOf(value.toLowerCase()[0]) > -1) return `an ${value}`;
+ return `a ${value}`;
+ }
+ static toLowerCase(value) {
+ if(Array.isArray(value)) {
+ const lowerCaseArray = value.map(item => { return item.toLowerCase(); });
+ return lowerCaseArray;
+ }
+ return String(value).toLowerCase();
+ }
+ static toCapitalCase(value) {
+ if(Array.isArray(value)) {
+ const capitalCaseArray = value.map(item => { return item[0].toUpperCase() + item.toLowerCase().slice(1); });
+ return capitalCaseArray;
+ }
+ return String(value)[0].toUpperCase() + String(value).toLowerCase().slice(1);
+ }
+ static getSectionOrder(section, callback) {
+ const sectionName = `repeating_${section}`;
+ const attributeName = `_reporder_${sectionName}`;
+ getAttrs([attributeName], attributes => {
+ let values = new Array();
+ Object.keys(attributes).some(() => {
+ let results = SheetUtils.toLowerCase(attributes[attributeName].replace(/ /g, '').split(','));
+ values = values.concat(results);
+ return true;
+ });
+ getSectionIDs(sectionName, ids => {
+ const filteredOrder = new Set();
+ const order = values.concat(SheetUtils.toLowerCase(ids)).filter(entry => { return SheetUtils.toLowerCase(ids).indexOf(entry) > -1; });
+ order.forEach(item => {
+ filteredOrder.add(item);
+ });
+ callback(Array.from(filteredOrder));
+ });
+ });
+ }
+ static deepReadAttribute(attr, callback, defaultValue) {
+ if(/^(@{).+}$/.test(String(attr)) === true) {
+ const regExp = /@\{([^@\{\}]+)\}/;
+ const reference = regExp.exec(attr)[1];
+ var self = this;
+ getAttrs([reference], function(v) {
+ if(!v[reference]) {
+ callback(defaultValue);
+ } else {
+ self.deepReadAttribute(v[reference], callback, defaultValue);
+ }
+ });
+ }
+ else {
+ callback(attr);
+ }
+ }
+ static sanitizeXP(value) {
+ const trimmedValue = value.trim();
+ if(!trimmedValue) return [];
+ const valueWithDecimalsRemoved = trimmedValue.replace(/,|\.| +/g, '');
+ const regex = /[0-9]+/g;
+ let xp = valueWithDecimalsRemoved.match(regex);
+ if(Array.isArray(xp)) xp = xp.map(entry => { return parseInt(entry) });
+ return xp;
+ }
+ static checkPath(obj, path, returnFalseOnEmpty = false) {
+ const sanitizedPath = path.replace(/\]\[|[\[,\]]/g, '.').replace(/\.+/g, '.').replace(/[",',]|\.$|^\./g, '');
+ const properties = sanitizedPath.split('.');
+ let level = obj;
+ for(let property = 0; property < properties.length; property++) {
+ if((returnFalseOnEmpty && !level[properties[property]]) || (!returnFalseOnEmpty && !(properties[property] in level))) return false;
+ level = level[properties[property]];
+ }
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/Brancalonia Official/src/js/Classes/SheetUtils/test/tests.html b/Brancalonia Official/src/js/Classes/SheetUtils/test/tests.html
new file mode 100644
index 0000000000..3ea3dfc38e
--- /dev/null
+++ b/Brancalonia Official/src/js/Classes/SheetUtils/test/tests.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
SheetUtils Tests
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Brancalonia Official/src/js/Classes/SheetUtils/test/tests.js b/Brancalonia Official/src/js/Classes/SheetUtils/test/tests.js
new file mode 100644
index 0000000000..93f20e49d9
--- /dev/null
+++ b/Brancalonia Official/src/js/Classes/SheetUtils/test/tests.js
@@ -0,0 +1,173 @@
+QUnit.module('Basic Tests', {
+ before: function() {
+ maxAsyncDelay = 100; //Sets the mock delay for getAttrs and setAttrs to a maximum of 1000ms.
+ },
+ beforeEach: function() {
+ //Resets attributes before each test
+ attributes = {};
+ sectionIDS = {};
+ }
+});
+QUnit.test('Sheet Utils returns correct UID', function( assert ) {
+ assert.equal(SheetUtils.getUID('repeating_npcreaction_-LzbTrhcIwpDwRZxfvEn_name'), '-LzbTrhcIwpDwRZxfvEn');
+ assert.equal(SheetUtils.getUID('attr_wisdom'), '');
+});
+
+QUnit.test('Sheet Utils returns a blank string when an invalid parameter is used', function( assert ) {
+ assert.equal(SheetUtils.getUID(12345), '');
+ assert.equal(SheetUtils.getUID(null), '');
+ assert.equal(SheetUtils.getUID(undefined), '');
+ assert.equal(SheetUtils.getUID({}), '');
+ assert.equal(SheetUtils.getUID(), '');
+ assert.equal(SheetUtils.getUID([]), '');
+});
+
+QUnit.test('Sheet Utils return the order a repeating section.', function(assert) {
+ attributes['_reporder_repeating_section'] = "-LzbTrhcIwpDwRZxfvEn,-MzbTrhcIwpDwRZxfvEn";
+ sectionIDS['repeating_section'] = ['-MzbTrhcIwpDwRZxfvEn', '-LzbTrhcIwpDwRZxfvEn'];
+ var done = assert.async();
+ SheetUtils.getSectionOrder('section', ids => {
+ assert.equal(ids.join(','), attributes['_reporder_repeating_section'].toLowerCase());
+ done();
+ });
+});
+
+QUnit.test('Sheet Utils section IDs when no ordering is found', function(assert) {
+ sectionIDS['repeating_section'] = ['-MzbTrhcIwpDwRZxfvEn', '-LzbTrhcIwpDwRZxfvEn'];
+ var done = assert.async();
+ SheetUtils.getSectionOrder('section', ids => {
+ assert.equal(ids.join(','), sectionIDS['repeating_section'].join(',').toLowerCase());
+ done();
+ });
+});
+
+QUnit.test('Sheet Utils returns correct lowered case array', function( assert ) {
+ assert.equal(SheetUtils.toLowerCase(['Something', 'SOMETHINGELSE']).join(' '), 'something somethingelse');
+});
+
+QUnit.test('Sheet Utils returns correct capitalized case array', function( assert ) {
+ assert.equal(SheetUtils.toCapitalCase(['something', 'SOMETHINGELSE']).join(' '), 'Something Somethingelse');
+});
+
+QUnit.test('Sheet Utils returns correct deep read attributes', function( assert ) {
+ attributes['hitdie_1'] = '6';
+ attributes['hitdie_2'] = '@{hitdie_2A}';
+ attributes['hitdie_2A'] = '8';
+ attributes['hitdie_3'] = 3;
+ attributes['hitdie_4'] = '["something"]';
+ attributes['hitdie_6'] = '6';
+ var done_1 = assert.async();
+ var done_2 = assert.async();
+ var done_3 = assert.async();
+ var done_4 = assert.async();
+ var done_5 = assert.async();
+ var done_6 = assert.async();
+ var done_7 = assert.async();
+ var done_8 = assert.async();
+ SheetUtils.deepReadAttribute('@{hitdie_1}', value => {
+ assert.equal(value, '6');
+ done_1();
+ }, '2');
+ SheetUtils.deepReadAttribute('@{hitdie_2}', value => {
+ assert.equal(value, '8');
+ done_2();
+ }, '2');
+ SheetUtils.deepReadAttribute('@{hitdie_3}', value => {
+ assert.equal(value, '3');
+ done_3();
+ }, '2');
+ SheetUtils.deepReadAttribute('@{hitdie_4}', value => {
+ assert.equal(value, '["something"]');
+ done_4();
+ }, '2');
+ SheetUtils.deepReadAttribute('@{hitdie_5}', value => {
+ assert.equal(value, '2');
+ done_5();
+ }, '2');
+ SheetUtils.deepReadAttribute('@{hitdie_5}', value => {
+ assert.equal(value, undefined);
+ done_6();
+ });
+ SheetUtils.deepReadAttribute('{hitdie_6}', value => {
+ assert.equal(value, '{hitdie_6}');
+ done_7();
+ });
+ SheetUtils.deepReadAttribute('something@{hitdie_6}', value => {
+ assert.equal(value, 'something@{hitdie_6}');
+ done_8();
+ });
+});
+
+QUnit.test('Invalid ordered itens are removed from result', function(assert) {
+ attributes['ui_flags'] = 'a_flag another_flag repeating_traits_0_name_-LzbTrhcIwpDwRZxfvEn repeating_traits_1_name_-MzbTrhcIwpDwRZxfvEn';
+ attributes['_reporder_repeating_traits'] = '-MzbTrhcIwpDwRZxfvEn,-LzbTrhcIwpDwRZxfvEn,-InvalidIwpDwRZxfvEn';
+ sectionIDS['repeating_traits'] = ['-FirsThcIwpDwRZxfvEn', '-LzbTrhcIwpDwRZxfvEn', '-MzbTrhcIwpDwRZxfvEn'];
+ var done = assert.async();
+ SheetUtils.getSectionOrder('traits', order => {
+ console.log(order);
+ var expected = '-MzbTrhcIwpDwRZxfvEn,-LzbTrhcIwpDwRZxfvEn,-FirsThcIwpDwRZxfvEn';
+ assert.equal(order.join(','), SheetUtils.toLowerCase(expected));
+ done();
+ });
+});
+
+QUnit.only('utils return valid experience points', function(assert) {
+ var xp_char_1 = '10000';
+ var xp_char_2 = '10,000';
+ var xp_char_3 = '10.000';
+ var xp_char_4 = '10000 / 30000';
+ var xp_char_5 = '10,000 /30.000';
+ var xp_char_6 = '10.000\\30.000';
+ var xp_char_7 = '10,000 |30.000';
+ var xp_char_8 = '10,000 : 30.000';
+ var xp_char_9 = '1.010,000-2.030.000';
+ var xp_char_10 = '1 010 000- 2.030.000';
+ var xp_char_11 = '1 010 000 2.030.000';
+ var xp_char_12 = 'abcde 10000 / 30000sdse';
+ var invalidXP = 'abcdef';
+ var blankXPField = '';
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_1)[0], 10000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_2)[0], 10000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_3)[0], 10000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_4)[0], 10000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_4)[1], 30000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_5)[0], 10000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_5)[1], 30000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_6)[0], 10000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_6)[1], 30000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_7)[0], 10000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_7)[1], 30000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_8)[0], 10000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_8)[1], 30000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_9)[0], 1010000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_9)[1], 2030000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_10)[0], 1010000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_10)[1], 2030000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_11)[0], 10100002030000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_12)[0], 10000);
+ assert.strictEqual(SheetUtils.sanitizeXP(xp_char_12)[1], 30000);
+ assert.strictEqual(SheetUtils.sanitizeXP(invalidXP), null);
+ assert.strictEqual(SheetUtils.sanitizeXP(blankXPField).length, 0);
+});
+
+QUnit.test('Sheet Utils checks object path', function( assert ) {
+ var my_obj = {
+ ["teste teste"]: {
+ another: {
+ empty: ""
+ }
+ }
+ };
+ var path_1 = "['teste teste']['another']['empty']";
+ var path_2 = "['teste teste'].another.empty";
+ var path_3 = "['teste teste'].another['empty']";
+ var path_4 = "['teste teste'].noexisting['empty']";
+ assert.equal(SheetUtils.checkPath(my_obj, path_1), true);
+ assert.equal(SheetUtils.checkPath(my_obj, path_1, true), false);
+ assert.equal(SheetUtils.checkPath(my_obj, path_2), true);
+ assert.equal(SheetUtils.checkPath(my_obj, path_2, true), false);
+ assert.equal(SheetUtils.checkPath(my_obj, path_3), true);
+ assert.equal(SheetUtils.checkPath(my_obj, path_3, true), false);
+ assert.equal(SheetUtils.checkPath(my_obj, path_4), false);
+ assert.equal(SheetUtils.checkPath(my_obj, path_4, true), false);
+});
diff --git a/Brancalonia Official/src/js/dragndrop/DragAndDrop.js b/Brancalonia Official/src/js/dragndrop/DragAndDrop.js
new file mode 100644
index 0000000000..c5cd6e7b6c
--- /dev/null
+++ b/Brancalonia Official/src/js/dragndrop/DragAndDrop.js
@@ -0,0 +1,1294 @@
+const filterBlobs = function(blobs, filters) {
+ var remove = filters.multiclass ? "no" : "yes";
+ var results = {};
+ delete filters.multiclass;
+ delete filters.slide;
+ _.each(blobs, function(blob, name) {
+ var match = true;
+ if(blob.Group && !filters.Group && !filters.name) match = false;
+ _.each(filters, function(v, k) {
+ if(k == "name") {
+ if(name != v) match = false;
+ } else if(v[0] === "<" && !isNaN(parseInt(v.substring(1)))) {
+ let blobval = isNaN(parseInt(blob[k])) ? 0 : parseInt(blob[k]);
+ if(blobval > parseInt(v.substring(1))) match = false;
+ } else {
+ if(blob[k] != v) match = false;
+ }
+ });
+ if(match && name.split("(")[0].toLowerCase() != "spell slots") results[name] = blob;
+ });
+ _.each(results, function(blob, name) {
+ if(blob.Multiclass == remove) {
+ delete results[name];
+ }
+ });
+ return results;
+};
+
+on("change:drop_name", function(eventinfo) {
+ if(eventinfo.newValue === "Monsters") {
+ getAttrs(["class","race","speed","hp"], function(v) {
+ if(v["class"] != "" || v["race"] != "" || v["speed"] != "" || v["hp"] != "") {
+ setAttrs({monster_confirm_flag: 1});
+ }
+ else {
+ handle_drop(eventinfo.newValue);
+ }
+ });
+ }
+ else {
+ handle_drop(eventinfo.newValue);
+ }
+});
+
+var handle_drop = function(category, eventinfo) {
+ getAttrs(["speed", "hp_max", "hp", "drop_name", "drop_data", "drop_content", "character_id", "npc_legendary_actions", "strength_mod", "dexterity_mod", "npc", "base_level", "strength_base", "dexterity_base", "constitution_base", "wisdom_base", "intelligence_base", "charisma_base", "class_resource_name", "other_resource_name", "multiclass1_lvl", "multiclass2_lvl", "multiclass3_lvl"], function(v) {
+ var pagedata = {};
+ try {
+ pagedata = JSON.parse(v.drop_data);
+ } catch(e) {
+ pagedata = v.drop_data;
+ }
+ var page = {
+ name: v.drop_name,
+ data: pagedata,
+ content: v.drop_content
+ };
+ var category = page.data["Category"];
+ get_repeating_data(function(repeating) {
+ var results = processDrop(page, v, repeating);
+ setAttrs(results.update, {silent: true}, function() {results.callbacks.forEach(function(callback) {callback(); })} );
+ });
+
+ });
+
+};
+
+var processDrop = function(page, currentData, repeating, looped) {
+ var numUses = function(uses_string) {
+ uses_string = parseValues(uses_string);
+
+ var terms = uses_string.split("+");
+ var total = 0;
+ _.each(terms, function(term) {
+ total += parseInt(term);
+ });
+ return uses_string === "" || uses_string === "-" ? uses_string : total;
+ };
+ var parseValues = function(uses_string) {
+ var attribs = ["strength", "dexterity", "constitution", "wisdom", "intelligence", "charisma"];
+ uses_string = uses_string ? uses_string.toLowerCase() : "";
+ _.each(attribs, function(attrib) {
+ var attribMod = Math.floor((parseInt(currentData[attrib + "_base"]) - 10) / 2);
+ if (attribMod < 0 || isNaN(attribMod)) attribMod = 0;
+ uses_string = uses_string.replace(attrib, attribMod);
+ });
+ uses_string = uses_string.replace(/half_level/g, Math.floor(classlevel/2));
+ return uses_string.replace(/level/g, classlevel);
+ };
+ const category = page.data["Category"];
+ let callbacks = [];
+ let update = {};
+ let blobs = {};
+ let classlevel = currentData.base_level ? parseInt(currentData.base_level) : 1;
+ repeating.traits = repeating.traits ? repeating.traits : [];
+ ["drop_category", "drop_name", "drop_data", "drop_content"].forEach(attr => update[attr] = "");
+
+ const coreDrops = ['Classes', 'Backgrounds', 'Feats', 'Items', 'Proficiencies', 'Races', 'Subraces', 'Other Options and Features'];
+ if (coreDrops.includes(category)) {
+ update["tab"] = "core";
+ }
+
+ const assignUpdate = newData => Object.assign(update, newData);
+
+ const processItems = () => {
+ try {
+ const itemType = page.data["Item Type"] ? page.data["Item Type"] : category;
+ const npc = currentData.npc === "0" ? false : true;
+
+ if (!npc) {
+ let newObject = new Item(page.name)
+
+ page.data["itemcount"] ? newObject.attributes.itemcount = page.data["itemcount"] : false;
+
+ ["Properties", "Weight"].forEach(attribute => {
+ const attributeLowercase = attribute.toLowerCase();
+ page.data[`${attribute}`] ? newObject.attributes[`item${attributeLowercase}`] = page.data[`${attribute}`] : false
+ });
+
+ page.content ? newObject.attributes.itemcontent = page.content : false;
+
+ newObject.attributes.itemmodifiers = dropFunctions.buildItemModString(page)
+
+ //ATTACK items such as Weapons
+ itemType.toLowerCase().includes('weapon') ? newObject.attributes.hasattack = 1 : false;
+
+ if (page.data.AC && !looped) {
+ callbacks.push(() => update_ac() );
+ }
+
+ if (page.data.Modifiers && page.data.Modifiers != "") {
+ callbacks.push(() => {
+ check_itemmodifiers(page.data.Modifiers);
+ });
+ };
+
+ //Create attacks for weapons. Create two attacks for versatile weapons such as Longsword.
+ if (newObject.attributes.hasattack === 1) {
+ callbacks.push(() => {
+ page.data["Alternate Damage"] && page.data["Alternate Damage"] !== "" ? create_attack_from_item(newObject.reprowid, {versatile: true}) : create_attack_from_item(newObject.reprowid);
+ });
+ }
+
+ if (itemType.toLowerCase() === "ammunition") {
+ newObject.attributes.useasresource = 1
+ callbacks.push(() => {
+ create_resource_from_item(newObject.reprowid);
+ });
+ }
+
+ if (!looped) {
+ callbacks.push(() => {
+ update_weight();
+ });
+ }
+
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+ } else if (npc && itemType.toLowerCase().includes("weapon")) {
+ const properties = page.data["Properties"] ? page.data["Properties"].toLowerCase() : "none";
+ let newObject = new NpcAction(page.name, 'npcaction')
+ newObject.addAttack()
+
+ page.data['Item Type'] ? newObject.attributes.attack_type = page.data['Item Type'] : false;
+ page.content ? newObject.attributes.description = page.content : false;
+
+ newObject.attributes.attack_tohit = dropFunctions.buildToHit(page, currentData)
+
+ const damageModifiers = dropFunctions.inferAbilityModifier(page.data["Item Type"], page.data["Properties"], currentData)
+ newObject.attributes.attack_damage = dropFunctions.buildDamage(page, damageModifiers)
+ page.data["Damage Type"] ? newObject.attributes.attack_damagetype = page.data["Damage Type"] : false;
+ page.data["Secondary Damage"] && !page.name.includes('+') ? newObject.attributes.attack_damage2 = page.data["Secondary Damage"] : false;
+ page.data["Secondary Damage Type"] && !page.name.includes('+') ? newObject.attributes.attack_damagetype2 = page.data["Secondary Damage Type"] : false;
+
+ properties.includes("versatile") ? newObject.attributes.name = `${newObject.attributes.name} (One-Handed)` : false
+
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+
+ //Versatile creates two attacks
+ if (properties.includes("versatile") && (page.data["Alternate Damage"] || page.data["Secondary Damage"])) {
+ let alternateAttack = new NpcAction(`${page.name} (Two-Handed)`, 'npcaction');
+ alternateAttack.addAttack()
+ alternateAttack.attributes.attack_type = newObject.attributes.attack_type;
+ alternateAttack.attributes.description = newObject.attributes.description;
+
+ if (page.data["Alternate Damage"]) {
+ alternateAttack.attributes.attack_damage = dropFunctions.buildDamage(page, damageModifiers, page.data["Alternate Damage"])
+ page.data["Alternate Damage Type"] ? alternateAttack.attributes.attack_damagetype = page.data["Alternate Damage Type"] : false;
+ page.data["Alternate Secondary Damage"] ? alternateAttack.attributes.attack_damage2 = page.data["Alternate Secondary Damage"] : false;
+ page.data["Alternate Secondary Damage Type"] ? alternateAttack.attributes.attack_damagetype2 = page.data["Alternate Secondary Damage Type"] : false;
+ } else {
+ alternateAttack.attributes.attack_damage = dropFunctions.buildDamage(page, damageModifiers, page.data["Secondary Damage"])
+ }
+
+ assignUpdate(dropFunctions.updateSheetAttributes(alternateAttack));
+ }
+
+ if (properties.includes("thrown")) {
+ let thrownAttack = new NpcAction(`${page.name} (Thrown)`, 'npcaction');
+ thrownAttack.addAttack()
+ page.data["Range"] ? thrownAttack.attributes.attack_range = page.data["Range"] : false;
+ thrownAttack.attributes.attack_type = "Range Weapon";
+
+ ['description', 'attack_tohit', 'attack_damage', 'attack_damagetype', 'attack_damage2', 'attack_damagetype2'].forEach(attr => {
+ thrownAttack.attributes[`${attr}`] = newObject.attributes[`${attr}`]
+ })
+
+ assignUpdate(dropFunctions.updateSheetAttributes(thrownAttack));
+ }
+
+ if (page.data.Modifiers) {
+ callbacks.push(() => { check_itemmodifiers(page.data.Modifiers); }, () => { update_npc_action("all"); });
+ } else {
+ callbacks.push(() => { update_npc_action("all"); });
+ };
+ } else {
+ warningMessage('processItems', `Only weapon drops are supported for npcs. For npcs, "Item Type" in the Compendium must include the word "weapon".`);
+ }
+ } catch (error) {
+ errorMessage(page.name, error);
+ }
+ }
+
+ const processSpells = () => {
+ try {
+ if(page.name) {
+ const spellLevel = page.data["Level"] && page.data["Level"] > 0 ? page.data["Level"] : "cantrip";
+ const section = `spell-${spellLevel}`
+ let existing = {id: false};
+
+ for (let [key, value] of Object.entries(repeating[`${section}`])) {
+ value.spellname === page.name ? existing.spellattackid = value.spellattackid : false;
+ value.spellname === page.name ? existing.id = key: false;
+ if(value.spellname === page.name) {
+ ['spellsource', 'innate'].forEach(attributeToKeep => {
+ if(repeating[`${section}`][key][attributeToKeep]) existing[attributeToKeep] = repeating[`${section}`][key][attributeToKeep];
+ });
+ }
+ }
+
+
+ let newObject = new Spell(page.name, section, existing.id);
+ newObject.attributes.spelllevel = spellLevel;
+
+ const dropSheetAssocitation = {
+ spelldescription: page.data['data-description'],
+ spellschool: page.data['School'].toLowerCase(),
+ spellclass: page.data['spellclass'],
+ spellsource: (existing.spellsource) ? existing.spellsource : page.data['spellsource'],
+ spellritual: page.data['Ritual'],
+ spelldmgmod: page.data['Add Casting Modifier'],
+ spellcomp_materials: page.data['Material'],
+ spelldamage2: page.data['Secondary Damage'],
+ spellcastingtime: page.data['Casting Time'],
+ spelldamagetype: page.data['Damage Type'],
+ spelldamage: page.data['Damage'],
+ spellduration: page.data['Duration'],
+ spellhealing: page.data['Healing'],
+ spellrange: page.data['Range'],
+ spellsave: page.data['Save'],
+ spellsavesuccess: page.data['Save Success'],
+ spelldamagetype2: page.data['Secondary Damage Type'],
+ spelltarget: page.data['Target'],
+ spellhlbonus: page.data['Higher Spell Slot Bonus'],
+ spellathigherlevels: page.data['Higher Spell Slot Desc'],
+ spellhldie: page.data['Higher Spell Slot Dice'],
+ spellhldietype: page.data['Higher Spell Slot Die'],
+ spellattack: page.data['Spell Attack']
+ }
+
+ for (let [key, value] of Object.entries(dropSheetAssocitation)) {
+ value ? newObject.attributes[`${key}`] = value : false;
+ }
+
+ page.data['Spellcasting Ability'] ? newObject.attributes.spell_ability = `@{${page.data['Spellcasting Ability'].toLowerCase()}_mod}+` : false;
+ page.data['Concentration'] ? newObject.attributes.spellconcentration = '{{concentration=1}}' : false;
+ if(existing.innate) {
+ newObject.attributes.innate = existing.innate;
+ } else {
+ page.data['Innate'] ? newObject.attributes.innate = page.data['Innate'] : false;
+ }
+
+ if (page.data['Components']) {
+ ['v', 's', 'm'].forEach(component => {
+ const componentCheck = dropFunctions.determineComponent(page.data['Components'], component)
+ newObject.attributes[`spellcomp_${component}`] = componentCheck ? componentCheck : 0;
+ })
+ }
+
+ if (page.data['Damage'] || page.data['Healing']) {
+ newObject.attributes.spelloutput = 'ATTACK'
+
+ callbacks.push(() => {
+ create_attack_from_spell(spellLevel, newObject.reprowid, currentData.character_id, existing.spellattackid);
+ });
+ }
+
+
+ if (newObject.attributes.spelloutput != 'ATTACK' && page.data['Higher Spell Slot Desc']) {
+ newObject.attributes.rollcontent = dropFunctions.buildSpellQuery(page.data['Level']);
+ }
+
+ //Character sheet accepts 'dice', 'beam', or none
+ if (page.data['data-Cantrip Scaling']) {
+ const validateCantripScaling = dropFunctions.validateCantripScaling(page.data['data-Cantrip Scaling'])
+ if (validateCantripScaling) {
+ newObject.attributes.spell_damage_progression = dropFunctions.buildCantripScaling(page.data['data-Cantrip Scaling'])
+ } else {
+ newObject.attributes.spell_damage_progression = ''
+ }
+ }
+ const assignedRowID = (newObject.reprowid) ? newObject.reprowid : generateRowID();
+ repeating[`${section}`][assignedRowID] = { spellname: page.name };
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+ }
+ } catch (error) {
+ errorMessage(page.name, error);
+ }
+ }
+
+ const processMonsters = () => {
+ try {
+ let newObject = new Npc(page.name);
+ newObject.addSkills(globalAttributesByCategory.skills.all())
+ newObject.addSaves(globalAttributesByCategory.abilities)
+
+ globalAttributesByCategory.abilities.forEach(ability => {
+ const abbreviation = ability.slice(0, 3).toUpperCase();
+ page.data[`${abbreviation}`] ? newObject.attributes[`${ability}_base`] = page.data[`${abbreviation}`] : false;
+ callbacks.push(() => {
+ update_attr(`${ability}`);
+ });
+ });
+
+ const dropSheetAssocitation = {
+ token_size: page.data["Token Size"],
+ npc_condition_immunities: page.data["Condition Immunities"],
+ npc_immunities: page.data["Immunities"],
+ npc_languages: page.data["Languages"],
+ npc_vulnerabilities: page.data["Vulnerabilities"],
+ npc_resistances: page.data["Resistances"],
+ npc_speed: page.data["Speed"],
+ npc_challenge: page.data["Challenge Rating"],
+ }
+
+ for (let [key, value] of Object.entries(dropSheetAssocitation)) {
+ value ? newObject.attributes[`${key}`] = value : false;
+ }
+
+ page.data["data-XP"] ? newObject.attributes.npc_xp = page.data["data-XP"].toString().replace(",","") : false
+
+ Object.assign(newObject.attributes, dropFunctions.inferSavingThrows(page.data['Saving Throws']))
+ Object.assign(newObject.attributes, dropFunctions.inferSkills(page.data['Skills']))
+
+ newObject.attributes.npc_type = dropFunctions.buildType(page.data["Size"], page.data["Type"], page.data["Alignment"])
+
+ newObject.attributes.npc_senses = dropFunctions.buildSenses(page.data['Senses'], page.data['Passive Perception'])
+
+ page.data['AC'] ? newObject.attributes.npc_ac = dropFunctions.inferBaseAttribute(page.data['AC']) : false;
+ page.data['AC'] ? newObject.attributes.npc_actype = dropFunctions.inferFormulaAttribute(page.data['AC']) : false;
+
+ page.data['HP'] ? newObject.attributes.hp_max = dropFunctions.inferBaseAttribute(page.data['HP']) : false;
+ page.data['HP'] ? newObject.attributes.npc_hpformula = dropFunctions.inferFormulaAttribute(page.data['HP']) : false;
+
+ const npcRepeating = ['npcaction-l', 'npcreaction', 'npcaction', 'npctrait'];
+ _.each(npcRepeating, section => {
+ getSectionIDs(`repeating_${section}`, idarray => {
+ _.each(idarray, (currentID, i) => {
+ removeRepeatingRow(`repeating_${section}_${currentID}`);
+ });
+ });
+ });
+
+ if (page.data["data-Legendary Actions"]) {
+ const actionCount = page.data["data-LANum"] ? page.data["data-LANum"] : 3;
+ newObject.attributes.npc_legendary_actions = actionCount
+
+ if (page.data["Legendary Actions Desc"]) {
+ newObject.attributes.npc_legendary_actions_desc = page.data["Legendary Actions Desc"];
+ } else {
+ newObject.attributes.npc_legendary_actions_desc = `The ${page.name} can take ${actionCount}, choosing from the options below. Only one legendary option can be used at a time and only at the end of another creature's turn. The ${page.name} regains spent legendary actions at the start of its turn.`
+ }
+ }
+
+ if (page.data["data-Mythic Actions"]) {
+ newObject.attributes.npc_mythic_actions = 1
+
+ if (page.data["data-MAdesc"]) {
+ newObject.attributes.npc_mythic_actions_desc = page.data["data-MAdesc"];
+ } else {
+ //TODO UC1098
+ newObject.attributes.npc_legendary_actions_desc = ``;
+ }
+ }
+
+ ["Actions", "Legendary Actions", "Mythic Actions"].forEach(attr => {
+ if (page.data[`data-${attr}`]) {
+ const fieldsetLookup = {
+ "Actions": "npcaction",
+ "Legendary Actions": "npcaction-l",
+ "Mythic Actions": "npcaction-m"
+ }
+ const repeatingFieldset = fieldsetLookup[attr];
+ const actions = dropFunctions.jsonParse(page.data[`data-${attr}`])
+ actions.forEach(action => {
+ let newAction = new NpcAction(action['Name'], repeatingFieldset);
+
+ action["Desc"] ? newAction.attributes.description = action["Desc"] : false;
+
+ if (action["Type Attack"]) {
+ newAction.addAttack()
+ const dropSheetAttackAssocitation = {
+ attack_damagetype: action['Damage Type'],
+ attack_damage: action['Damage'],
+ attack_tohit: action['Hit Bonus'],
+ attack_range: action['Reach'],
+ attack_target: action['Target'],
+ attack_type: action['Type'],
+ attack_damage2: action['Damage 2'],
+ attack_damagetype2: action['Damage 2 Type']
+ }
+
+ for (let [key, value] of Object.entries(dropSheetAttackAssocitation)) {
+ value ? newAction.attributes[`${key}`] = value : false;
+ }
+ }
+
+ assignUpdate(dropFunctions.updateSheetAttributes(newAction));
+ });
+ }
+ });
+
+
+ if (page.data["data-Reactions"]) {
+ newObject.attributes.npcreactionsflag = 1
+ const reactions = dropFunctions.jsonParse(page.data[`data-Reactions`])
+ reactions.forEach(reaction => {
+ let newReaction = new NpcReaction(reaction['Name']);
+ reaction["Desc"] ? newReaction.attributes.description = reaction["Desc"] : false;
+ assignUpdate(dropFunctions.updateSheetAttributes(newReaction));
+ })
+ }
+
+ if (page.data["data-Traits"]) {
+ const traits = dropFunctions.jsonParse(page.data[`data-Traits`])
+
+ traits.forEach(trait => {
+ let newTrait = new NpcTraits(trait['Name']);
+ trait["Desc"] ? newTrait.attributes.description = trait["Desc"] : false;
+
+ if (trait.Name.match(/(?!innate )(?:^.{0,6}|.{7})(spellcasting)/i)) {
+ let spellCastingAbility = page.data["Spellcasting Ability"];
+
+ if (spellCastingAbility) {
+ spellCastingAbility = `@{${spellCastingAbility.toLowerCase()}_mod}+`
+ } else {
+ spellCastingAbility = dropFunctions.inferSpellcastingAbility(newTrait.attributes.description)
+ }
+
+ const casterLevels = dropFunctions.inferCasterLevel(trait['Desc']);
+ newObject.addSpellcaster(spellCastingAbility, casterLevels)
+
+ callbacks.push(() => update_pb());
+ callbacks.push(() => update_spell_slots());
+ } else if (trait.Name.match(/innate spellcasting/i)) {
+ let spellCastingAbility = page.data["Spellcasting Ability"];
+ newObject.addInnateCaster()
+
+ spellCastingAbility ? newObject.attributes.spellcasting_ability = `@{${spellCastingAbility.toLowerCase()}_mod}+` : false;
+ }
+
+ assignUpdate(dropFunctions.updateSheetAttributes(newTrait));
+ })
+ }
+
+ if (page.data["data-Spells"]) {
+ const spellList = dropFunctions.buildSpellList(page.data["data-Spells"]);
+ getCompendiumPage(spellList, compendiumPages => {
+ compendiumPages = removeDuplicatedPageData(compendiumPages);
+ compendiumPages = Array.isArray(compendiumPages) ? compendiumPages : [compendiumPages];
+ const innateSpellLists = dropFunctions.jsonParse(page.data["data-Spells"])[`innate`] || false;
+ let spellUpdate = {}, spellCallbacks = [];
+
+ compendiumPages.forEach(spellPage => {
+ const processedSpell = processDrop(spellPage, currentData, repeating);
+ Object.assign(spellUpdate, processedSpell.update);
+ processedSpell.callbacks.forEach(callback => spellCallbacks.push(callback));
+ });
+
+ if (innateSpellLists) {
+ //Search each keys in INNATE to see if spell name === one of the Values
+ for (let [innateKey, innateValue] of Object.entries(innateSpellLists)) {
+ innateValue.forEach(spellName => {
+ for (let [key, value] of Object.entries(spellUpdate)) {
+ if (key.includes('_spellname') && (value === spellName || value.toLowerCase() === spellName)) {
+ const repeatingRow = key.split('_spellname')[0];
+ spellUpdate[`${repeatingRow}_innate`] = innateKey
+ }
+ }
+ });
+ };
+ };
+
+ setAttrs(spellUpdate, {silent: true}, () => {
+ spellCallbacks.forEach(callback => {
+ callback();
+ });
+ });
+ });
+ }
+
+ //Call backs
+ if (page.data["Saving Throws"]) {
+ callbacks.push(() => update_npc_saves() );
+ };
+
+ if (page.data["Skills"]) {
+ callbacks.push(() => update_npc_skills() );
+ };
+
+ if (page.data[`data-Actions`]) {
+ callbacks.push(() => update_npc_action("all"))
+ }
+
+ if (update["npc_challenge"]) {
+ callbacks.push(() => update_challenge() );
+ };
+
+ globalAttributesByCategory.abilities.forEach(ability => {
+ callbacks.push(() => update_attr(`${ability}`) );
+ });
+
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+ } catch (error) {
+ errorMessage(page.name, error);
+ }
+ }
+
+ const processFeats = () => {
+ try {
+ const match = {name: page.name};
+ let existing = _.findWhere(repeating.traits, match);
+ existing = existing ? existing : {};
+
+ let newObject = new Trait(page.name, existing.id || false);
+ newObject.attributes.description = page.data['data-Description'] || page.content
+ newObject.attributes.source = newObject.determineSource(category)
+ newObject.attributes.source_type = page.data["Properties"] || ""
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+
+ existing = dropHelpers.updateRepeatingTraits(newObject, existing)
+ existing ? false : repeating.traits.push(existing);
+ } catch (error) {
+ errorMessage(page.name, error);
+ }
+ }
+
+ const processProficiencies = () => {
+ try {
+ const proficiencies = globalAttributesByCategory.proficiencyTypes;
+ const tools = ["tool", "skillcustom"];
+ let type = page.data["Type"] || "";
+ type = proficiencies.includes(type.toUpperCase()) ? 'proficiencies' : tools.includes(type.toLowerCase()) ? 'tool' : type.toLowerCase() === 'skill' ? 'skill' : false;
+
+ if (type === 'proficiencies') {
+ if (repeating.prof_names.indexOf(page.name.toLowerCase()) == -1) {
+ let newObject = new Proficiency(page.name)
+ proficiencies.includes(page.data["Type"].toUpperCase()) ? newObject.attributes.prof_type = page.data["Type"].toUpperCase() : false;
+ repeating.prof_names.push(page.name.toLowerCase());
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+ }
+ } else if (type === 'tool') {
+ let existing = {id: false};
+ existing.id = dropHelpers.findToolId(repeating.tool, page.name)
+
+ let newObject = new ToolProficiency(page.name, existing.id)
+ page.data["toolbonus_base"] ? newObject.attributes.toolbonus_base = "(@{pb}*2)" : false;
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+
+ existing = dropHelpers.updateRepeatingTools(newObject, existing)
+ repeating.tool[newObject.reprowid] = existing
+ repeating.prof_names.push(page.name.toLowerCase());
+
+ //Updates the displays for the tool...
+ callbacks.push(() => {
+ update_tool(newObject.reprowid);
+ });
+ } else if (type === 'skill') {
+ let newObject = new Skill(page.name)
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+ } else {
+ warningMessage(`${page.data["Type"]}`, `No an approved type. Accepted types are skill, ${proficiencies.concat(tools).join(' ,')}. Update compendium "Type".`);
+ }
+ } catch (error) {
+ errorMessage(page.name, error);
+ }
+ }
+
+ const processClass = () => {
+ try {
+ if (page.data.multiclass) {
+ if(page.name && page.name !== "") { update[page.data.multiclass] = page.name; }
+ update[page.data.multiclass + "_flag"] = "1";
+ classlevel = parseInt(currentData[page.data.multiclass + "_lvl"]);
+ } else {
+ let newObject = new Class(page.name);
+
+ if (page.data["Hit Die"] && page.data["Hit Die"] !== "") {
+ currentData.base_level ? newObject.attributes.base_level = currentData.base_level : false;
+ newObject.attributes.hit_dice_max = newObject.attributes.base_level + page.data["Hit Die"];
+ newObject.attributes.hitdietype = page.data["Hit Die"].replace(/[^0-9]/g, '');
+ newObject.attributes.hit_dice = newObject.attributes.base_level;
+ }
+
+ const spellcastingAbility = page.data["Spellcasting Ability"] ? page.data["Spellcasting Ability"].toLowerCase() : false;
+ if (spellcastingAbility && globalAttributesByCategory.abilities.includes(spellcastingAbility)) {
+ newObject.attributes.spellcasting_ability = newObject.buildSpellcastingAbility(spellcastingAbility);
+ }
+
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+ }
+
+ if (page.data["data-Saving Throws"] && !page.data.multiclass) {
+ const saves = dropFunctions.jsonParse(page.data["data-Saving Throws"]);
+ saves.forEach(value => {
+ const save = new SavingThrow(value);
+ assignUpdate(dropFunctions.updateSheetAttributes(save));
+ });
+ }
+
+ if(!looped) {
+ callbacks.push(update_class);
+ }
+ } catch (error) {
+ errorMessage(page.name, error);
+ }
+ }
+
+ const processSubclasses = () => {
+ try {
+ const lowercaseClass = page.data.Class.toLowerCase();
+ if (page.data.multiclass) {
+ update[`${page.data.multiclass}_subclass`] = page.name;
+ classlevel = parseInt(currentData[`${page.data.multiclass}_lvl`]);
+ if (page.data["Spellcasting Ability"] && (lowercaseClass === 'fighter' || lowercaseClass === 'rogue')) {
+ update[`"arcane_${lowercaseClass}`] = "1";
+ }
+ } else {
+ let newObject = new Subclass(page.name);
+ const spellcastingAbility = page.data["Spellcasting Ability"] ? page.data["Spellcasting Ability"].toLowerCase() : false;
+ if (spellcastingAbility && globalAttributesByCategory.abilities.includes(spellcastingAbility)) {
+ newObject.attributes.spellcasting_ability = newObject.buildSpellcastingAbility(spellcastingAbility);
+ if(newObject.checkArcane(lowercaseClass)) newObject.attributes[`arcane_${lowercaseClass}`] = 1;
+ }
+
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+ }
+
+ if (!looped) {
+ callbacks.push(update_class);
+ };
+ } catch (error) {
+ errorMessage(page.name, error);
+ }
+ }
+
+ const processRaces = () => {
+ try {
+ let newObject = new Race(page.name)
+
+ page.data['Size'] && page.data['Size'] != 'Medium' ? newObject.attributes.size = page.data['Size'] : false
+ page.data['Speed'] && page.data['Speed'] != 30 ? newObject.attributes.speed = page.data['Speed'] : false
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+
+ if (!looped) {
+ callbacks.push(update_race_display);
+ }
+ } catch (error) {
+ errorMessage(page.name, error);
+ }
+ }
+
+ const processSubraces = () => {
+ try {
+ let newObject = new Subrace(page.name)
+ page.data['Size'] && page.data['Size'] ? newObject.attributes.size = page.data['Size'] : false
+ page.data['Speed'] && page.data['Speed'] ? newObject.attributes.speed = page.data['Speed'] : false
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+
+ if (!looped) {
+ callbacks.push(update_race_display);
+ }
+ } catch (error) {
+ errorMessage(page.name, error);
+ }
+ }
+
+ const processOtherOptionsAndFeatures = () => {
+ //Do nothing...
+ }
+
+ const processBackgrounds = () => {
+ try {
+ update["background"] = page.name;
+ } catch (errorMessage) {
+ errorMessage(page.name, error);
+ }
+ }
+
+ console.log(category)
+
+ switch(category) {
+ case "Backgrounds":
+ processBackgrounds();
+ break;
+ case "Classes":
+ processClass();
+ break;
+ case "Feats":
+ processFeats();
+ break;
+ case "Items":
+ processItems();
+ break;
+ case "Monsters":
+ processMonsters();
+ break;
+ case "Proficiencies":
+ processProficiencies();
+ break;
+ case "Spells":
+ processSpells();
+ break;
+ case "Subclasses":
+ processSubclasses();
+ break;
+ case "Races":
+ processRaces();
+ break
+ case "Subraces":
+ processSubraces();
+ break;
+ case "Other Options and Features":
+ processOtherOptionsAndFeatures();
+ break;
+ default:
+ errorMessage(category, `category does not match one of the drop functions conditions.`);
+ }
+
+ if (page.data.theseblobs) {
+ _.each(page.data.theseblobs, function(blobname) {
+ if(page.data.blobs[blobname]) blobs[blobname] = page.data.blobs[blobname];
+ });
+ } else {
+ if(category === "Other Options and Features") {
+ blobs = page.data.blobs;
+ } else {
+ blobs = filterBlobs(page.data.blobs, {"Level": "1"});
+ }
+ }
+
+ for (let [blobName, blob] of Object.entries(blobs)) {
+ if (blob["Traits"]) {
+ try {
+ const traitArray = dropFunctions.jsonParse(blob["Traits"]);
+ if (traitArray && traitArray.length) {
+ traitArray.forEach(trait => {
+ if (!trait.Input) {
+ let match = {name: trait["Name"], type: page.name};
+ if (trait["Replace"]) {
+ match = {name: trait["Replace"]};
+ }
+ let existing = _.findWhere(repeating.traits, match);
+ existing = existing ? existing : {};
+
+ let newObject = new Trait(trait["Name"].replace(/{{Input}}/g, ""), existing.id || false);
+ newObject.attributes.source = newObject.determineSource(category)
+ trait["Desc"] ? newObject.attributes.description = trait["Desc"].replace(/{{Input}}/g, "") : false
+ page.name ? newObject.attributes.source_type = removeExpansionInfo(page.name) : false
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+
+ existing = dropHelpers.updateRepeatingTraits(newObject, existing)
+ existing ? false : repeating.traits.push(existing);
+
+ if (trait["Name"] === "Reliable Talent") {
+ update["reliable_talent"] = "10";
+ }
+
+ else if (trait["Name"] === "Powerful Build") {
+ update["powerful_build"] = "1";
+ };
+ }
+ });
+ };
+ } catch (error) {
+ errorMessage(trait.Name, error)
+ }
+ }
+
+ ["Language Proficiency", "Weapon Proficiency", "Armor Proficiency"].forEach(proficiencyType => {
+ try {
+ const proficiencyArray = blob[`${proficiencyType}`] ? dropFunctions.jsonParse(blob[`${proficiencyType}`]) : false
+ if (proficiencyArray && proficiencyArray["Proficiencies"]) {
+ proficiencyArray["Proficiencies"].forEach(proficiency => {
+ if (repeating.prof_names.indexOf(proficiency.toLowerCase()) == -1) {
+ let newObject = new Proficiency(proficiency)
+ newObject.attributes.prof_type = proficiencyType.split(" Proficiency")[0].toUpperCase()
+ repeating.prof_names.push(proficiency.toLowerCase());
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+ }
+ })
+ }
+ } catch (error) {
+ errorMessage(proficiencyType, error)
+ }
+ })
+
+ if (blob["Tool Proficiency"]) {
+ try {
+ const toolArray = dropFunctions.jsonParse(blob["Tool Proficiency"]);
+ if(toolArray["Proficiencies"] && toolArray["Proficiencies"].length) {
+ toolArray["Proficiencies"].forEach(proficiency => {
+ let existing = {id: false}
+ existing.id = dropHelpers.findToolId(repeating.tool, proficiency)
+
+ let newObject = new ToolProficiency(proficiency, existing.id)
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+
+ existing = dropHelpers.updateRepeatingTools(newObject, existing)
+ repeating.tool[newObject.reprowid] = existing
+ repeating.prof_names.push(page.name.toLowerCase());
+
+ //Updates the displays for the tool...
+ callbacks.push(() => {
+ update_tool(newObject.reprowid);
+ });
+ })
+ }
+ } catch (error) {
+ errorMessage("Tool Proficiency", error)
+ }
+ }
+
+ if (blob["Skill Proficiency"]) {
+ try {
+ const skillArray = dropFunctions.jsonParse(blob["Skill Proficiency"]);
+ if (skillArray["Proficiencies"] && skillArray["Proficiencies"].length) {
+ skillArray["Proficiencies"].forEach(proficiency => {
+ let newObject = new Skill(proficiency);
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+ });
+ callbacks.push(() => {
+ update_skills(["athletics", "acrobatics", "sleight_of_hand", "stealth", "arcana", "history", "investigation", "nature", "religion", "animal_handling", "insight", "medicine", "perception", "survival","deception", "intimidation", "performance", "persuasion"]);
+ });
+ };
+ } catch (error) {
+ errorMessage("Skill Proficiency", error)
+ }
+ }
+
+ if (blob["Global Damage"]) {
+ try {
+ const dmgmod = dropFunctions.jsonParse(blob["Global Damage"])
+ let existing = {}
+
+ for (let [key, value] of Object.entries(repeating.damagemod)) {
+ value.toLowerCase() === dmgmod["Name"].toLowerCase() ? existing.id = key : false
+ }
+
+ let newObject = new GlobalDamage(dmgmod["Name"], existing.id || false)
+ newObject.attributes.global_damage_damage = `${parseValues(dmgmod["Damage"])}`
+ dmgmod["Active"] == "true" ? newObject.attributes.global_damage_active_flag = 1 : false
+ newObject.attributes.global_damage_type = dmgmod["Type"] ? dmgmod["Type"] : dmgmod["Name"];
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+
+ update["global_damage_mod_flag"] = "1";
+
+ repeating.damagemod[newObject.reprowid] = dmgmod["Name"];
+ } catch (error) {
+ errorMessage("Global Damage", error)
+ }
+ }
+
+ if (blob["Actions"]) {
+ try {
+ let actionsObject = {}
+ dropFunctions.jsonParse(blob["Actions"]).forEach(value => actionsObject[value.Name] = value)
+
+ for (let [actionName, action] of Object.entries(actionsObject)) {
+ let existing = {}
+
+ for (let [key, value] of Object.entries(repeating.attack)) {
+ value.atkname === actionName ? existing.id = key : false
+ }
+
+ let newObject = new Attack(actionName, existing.id || false)
+ action["Desc"] ? newObject.attributes.atk_desc = action["Desc"] : false
+
+ if (action["Type Attack"]) {
+ if (action["Type"] === "Spell") {
+ newObject.attributes.atkflag = 0
+ newObject.addSaveFlag()
+ }
+
+ action["Reach"] ? newObject.attributes.atkrange = action["Reach"] : false
+ action["Damage"] ? newObject.attributes.dmgbase = action["Damage"] : false
+ !action["Damage"] ? newObject.attributes.dmgflag = 0 : false;
+ action["Damage Type"] ? newObject.attributes.dmgtype = action["Damage Type"] : false
+
+ if (action["Modifier"]) {
+ if (action["Modifier"] === "FIN") {
+ newObject.checkFinesse(parseInt(currentData.strength_base), parseInt(currentData.dexterity_base))
+ } else {
+ const actionModifier = dropFunctions.convertAbbreviationToAttribute(action["Modifier"])
+ actionModifier && actionModifier != newObject.attributes.dmgattr ? newObject.attributes.dmgattr = actionModifier : false
+ actionModifier && actionModifier != newObject.attributes.atkattr_base ? newObject.attributes.atkattr_base = actionModifier : false
+ }
+ } else {
+ newObject.attributes.dmgattr = 0;
+ }
+
+ action["Save"] ? newObject.attributes.saveattr = action["Save"] : false
+ action["Save Effect"] ? newObject.attributes.saveeffect = action["Save Effect"] : false
+
+ if (action["Save DC"]) {
+ const saveDCModifier = dropFunctions.convertAbbreviationToAttribute(action["Save DC"])
+ newObject.attributes.savedc = `(@{saveflat})`;
+ newObject.attributes.saveflat = `(8+@{pb}+${saveDCModifier})`;
+ }
+
+ if (action["Damage 2"] && action["Damage 2 Type"]) {
+ newObject.attributes.dmg2flag = '{{damage=1}} {{dmg2flag=1}}'
+ newObject.attributes.atk_dmg2base = action["Damage 2"]
+ newObject.attributes.attack_damagetype2 = action["Damage 2 Type"]
+
+ if (action["Modifier 2"]) {
+ newObject.attributes.dmg2attr = dropFunctions.convertAbbreviationToAttribute(action["Modifier 2"])
+ } else {
+ newObject.attributes.dmgattr = 0
+ }
+ }
+ }
+
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+
+ repeating.attack[`${newObject.reprowid}`] = {atkname: newObject.attributes.atkname}
+
+ callbacks.push(() => {
+ do_update_attack([`${newObject.reprowid}`]);
+ });
+ }
+ } catch (error) {
+ errorMessage("Actions", error)
+ }
+ }
+
+ if (blob["Resources"]) {
+ try {
+ const resourcesArray = dropFunctions.jsonParse(blob["Resources"])
+ resourcesArray.forEach(resource => {
+ let section = undefined;
+
+ const findCurrentResource = resourceName => {
+ if (currentData["class_resource_name"] === resourceName) {
+ return "class_resource"
+ } else if (currentData["other_resource_name"] === resourceName) {
+ return "other_resource"
+ } else {
+ for (let [repeatingIDKey, repeatingValue] of Object.entries(repeating.resource)) {
+ return Object.values(repeatingValue).includes(resourceName) ? repeatingIDKey : false
+ }
+ }
+ }
+
+ //Testing this funtion to find an empty resource
+ const findEmptyResource = () => {
+ if (currentData["class_resource_name"].length === 0) {
+ return "class_resource"
+ } else if (currentData["other_resource_name"].length === 0) {
+ return "other_resource"
+ } else {
+ let foundEmptyString = false
+ for (let [repeatingIDKey, repeatingValue] of Object.entries(repeating.resource)) {
+ if (repeatingValue.left.length === 0) {
+ return `repeating_resource_${repeatingIDKey}_resource_left`
+ } else if (repeatingValue.right.length === 0) {
+ return `repeating_resource_${repeatingIDKey}_resource_right`
+ } else {
+ foundEmptyString = false
+ }
+ }
+
+ return foundEmptyString
+ }
+ }
+
+ let matchResource = findCurrentResource(resource.Name)
+
+ if (matchResource) {
+ if (matchResource === "class_resource" || matchResource === "other_resource") {
+ section = matchResource
+ } else {
+ const repeatingSide = repeating.resource[matchResource].left === resource.Name ? "left" : "right"
+ section = `repeating_resource_${matchResource}_resource_${repeatingSide}`
+ }
+ } else {
+ section = findEmptyResource()
+ }
+
+ //Section will be true if a repeating entry matches resource.Name or is has an empty side ||
+ //class/other_resource match the resource.Name or are empty
+ if (section) {
+ update[`${section}_name`] = resource.Name
+ if (resource.Uses) update[section] = numUses(resource.Uses)
+ update[`${section}_max`] = resource.Max ? numUses(resource.Max) : numUses(resource.Uses)
+
+ if (section === "class_resource" || section === "other_resource") {
+ currentData[`${section}_name`] = resource.Name
+ } else {
+ const sectionRepeatingId = section.split('_resource_')[1]
+ const sectionSide = section.includes('left') ? 'left' : 'right'
+ repeating.resource[`${sectionRepeatingId}`][sectionSide] = resource.Name
+ }
+ } else {
+ const newResource = new Resource(resource.Name)
+ newResource.attributes.resource_left = resource.Uses ? numUses(resource.Uses) : 0
+ newResource.attributes.resource_left_max = resource.Max ? numUses(resource.Max) : newResource.attributes.resource_left
+ assignUpdate(dropFunctions.updateSheetAttributes(newResource))
+
+ const addRepeating = {
+ [`${newResource.reprowid}`]: {
+ left: resource.Name,
+ right: ''
+ }
+ }
+ Object.assign(repeating.resource, addRepeating)
+ }
+ })
+ } catch (error) {
+ errorMessage("Resources", error)
+ }
+ }
+
+ if (blob["Custom AC"]) {
+ try {
+ const parsedKey = dropFunctions.jsonParse(blob["Custom AC"]);
+ update["custom_ac_flag"] = "1";
+ update["custom_ac_base"] = parsedKey.Base;
+ update["custom_ac_part1"] = parsedKey["Attribute 1"];
+ update["custom_ac_part2"] = parsedKey["Attribute 2"] ? parsedKey["Attribute 2"] : "";
+ update["custom_ac_shield"] = parsedKey.Shields;
+ if(!looped) {
+ callbacks.push( function() {update_ac();} )
+ }
+ } catch (error) {
+ errorMessage("Custom AC", error)
+ }
+ }
+
+ if (blob["Hit Points Per Level"]) {
+ try {
+ const parsedKey = dropFunctions.jsonParse(blob["Hit Points Per Level"])
+ let existing = {}
+ for (let [key, value] of Object.entries(repeating.hpmod)) {
+ value.source === blobName ? existing.id = key : false
+ }
+
+ let newObject = new HPMod(blobName, existing.id || false)
+ newObject.attributes.mod = blob["Hit Points Per Level"]
+ newObject.attributes.source = blobName
+ newObject.attributes.levels = category === "Races" || category === "Subraces" ? 'total' : 'base'
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject));
+ } catch (error) {
+ errorMessage("Hit Points Per Level", error)
+ }
+ }
+
+ if (blob["Hit Points Bonus"]) {
+ let prevHp = update["hp"] || currentData["hp"];
+ let prevHpMax = update["hp_max"] || currentData["hp_max"];
+ prevHp = prevHp && !isNaN(parseInt(prevHp)) ? parseInt(prevHp) : 0;
+ prevHpMax = prevHpMax && !isNaN(parseInt(prevHpMax)) ? parseInt(prevHpMax) : 0;
+ update["hp"] = prevHp + parseInt(blob["Hit Points Bonus"]);
+ update["hp_max"] = prevHpMax + parseInt(blob["Hit Points Bonus"]);
+ }
+
+ ["Global AC Mod", "Global Save", "Global Attack"].forEach(globalType => {
+ try {
+ if (blob[globalType]) {
+ const globalShortName = globalType.includes("Attack") ? "attack" : globalType.includes("Save") ? "save" : "ac";
+ const repeatingKey = globalShortName === "attack" ? "tohitmod" : globalShortName === "save" ? "savemod" : "acmod";
+
+ const parsedKey = dropFunctions.jsonParse(blob[`${globalType}`]);
+ let existing = {id: false}
+ for (let [key, value] of Object.entries(repeating[`${repeatingKey}`])) {
+ value.includes(blobName) ? existing.id = key : false
+ }
+
+ let newObject = {};
+ if (globalType === "Global AC Mod") {
+ newObject = new GlobalACMod(parsedKey.Name, existing.id)
+ newObject.attributes.global_ac_val = parsedKey.Bonus
+ } else if (globalType === "Global Save") {
+ newObject = new GlobalSave(parsedKey.Name, existing.id)
+ newObject.attributes.global_save_roll = parsedKey.Bonus
+ } else {
+ newObject = new GlobalAttack(parsedKey.Name, existing.id)
+ newObject.addRoll(parsedKey.Bonus)
+ }
+
+ parsedKey.Active !== "false" ? newObject.attributes[`global_${globalShortName}_active_flag`] = 1 : false
+ assignUpdate(dropFunctions.updateSheetAttributes(newObject))
+
+ update[`global_${globalShortName}_mod_flag`] = "1"
+ }
+ } catch (error) {
+ errorMessage(`${globalType}`, error)
+ }
+ })
+
+ if (blob["Initiative"]) {
+ if (blob["Initiative"].toLowerCase() === "advantage") {
+ update["initiative_style"] = "{@{d20},@{d20}}kh1";
+ } else if (blob["Initiative"].toLowerCase() === "disadvantage") {
+ update["initiative_style"] = "{@{d20},@{d20}}kl1";
+ } else {
+ update.initmod = numUses(blob["Initiative"]);
+ }
+ }
+
+ if (blob["Carry Multiplier"]) {
+ update["carrying_capacity_mod"] = `*${blob["Carry Multiplier"]}`
+ }
+
+ if (blob["Speed"]) {
+ try {
+ if (blob["Speed"][0] === "+") {
+ let prevspeed = update["speed"] || currentData["speed"];
+ prevspeed = prevspeed && !isNaN(parseInt(prevspeed)) ? parseInt(prevspeed) : 0;
+ update["speed"] = prevspeed + parseInt(blob["Speed"]);
+ } else {
+ update["speed"] = parseInt(blob["Speed"]);
+ }
+ } catch (error) {
+ errorMessage("Speed", error)
+ }
+ }
+
+ if (blob["Jack of All Trades"]) {
+ update["jack_of_all_trades"] = "@{jack}";
+ }
+
+ if (blob["Global Save Mod"]) {
+ update["globalsavemod"] = numUses(blob["Global Save Mod"]);
+ }
+
+ if (blob["Saving Throws"]) {
+ try {
+ const parsedArray = dropFunctions.jsonParse(blob["Saving Throws"])
+ parsedArray.forEach(value => {
+ const save = new SavingThrow(value);
+ assignUpdate(dropFunctions.updateSheetAttributes(save));
+ })
+ } catch (error) {
+ errorMessage("Saving Throws", error)
+ }
+ }
+
+ if (blob["Proficiency Bonus"]) {
+ try {
+ const parsedBonus = dropFunctions.jsonParse(blob["Proficiency Bonus"])
+ for (let [key, value] of Object.entries(parsedBonus)) {
+ update[`${key.replace(/ /g, "_").toLowerCase()}_flat`] = numUses(value);
+ }
+ update_skills(["athletics", "acrobatics", "sleight_of_hand", "stealth", "arcana", "history", "investigation", "nature", "religion", "animal_handling", "insight", "medicine", "perception", "survival","deception", "intimidation", "performance", "persuasion"]);
+ } catch (error) {
+ errorMessage("Proficiency Bonus", error)
+ }
+ }
+
+ if (blob["Spells"]) {
+ try {
+ let spells = dropFunctions.jsonParse(blob["Spells"]);
+ let spellUpdate = {}, spellCallbacks = [];
+ let spellPages = [];
+ spells.forEach(spell => {
+ if(spell.Name) spellPages.push(spell.Name);
+ if(spell.Known) spellPages = spellPages.concat(spell.Known);
+ });
+ spellPages = Array.from(new Set(spellPages));
+
+ getCompendiumPage(spellPages, spellData => {
+ var inSpellBook = function(name) {
+ let found = false;
+ const spellRepeating = ["cantrip", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
+ spellRepeating.forEach(spellLevel => {
+ if(found) return;
+ if(repeating[`spell-${spellLevel}`]) {
+ Object.keys(repeating[`spell-${spellLevel}`]).forEach(entry => {
+ if(repeating[`spell-${spellLevel}`][entry]['spellname'] === name) {
+ found = true;
+ return;
+ }
+ });
+ }
+ });
+ return found;
+ };
+ spellData = removeDuplicatedPageData(spellData);
+ spells.forEach(spellInformation => {
+ if(spellInformation.Known) {
+ spellInformation.Known.forEach(s => {
+ if(!inSpellBook(s)) {
+ const mockPage = {
+ name: s,
+ data: {
+ "Category": "Spells"
+ }
+ }
+ const pageData = (Array.isArray(spellData)) ? spellData.filter(entry => { return entry['name'] === s})[0] : spellData;
+ if(pageData) {
+ Object.assign(mockPage.data, pageData.data);
+ Object.assign(mockPage.data, spellInformation);
+ const processedSpell = processDrop(mockPage, currentData, repeating);
+ Object.assign(spellUpdate, processedSpell.update);
+ processedSpell.callbacks.forEach(callback => spellCallbacks.push(callback));
+ }
+ }
+ });
+ } else {
+ if(!inSpellBook(spellInformation.Name)) {
+ const mockPage = {
+ name: spellInformation.Name,
+ data: {
+ "Category": "Spells"
+ }
+ }
+ const pageData = (Array.isArray(spellData))? spellData.filter(entry => { return entry['name'] === spellInformation.Name})[0] : spellData;
+ Object.assign(mockPage.data, pageData.data);
+ Object.assign(mockPage.data, spellInformation);
+ const processedSpell = processDrop(mockPage, currentData, repeating);
+ Object.assign(spellUpdate, processedSpell.update);
+ processedSpell.callbacks.forEach(callback => spellCallbacks.push(callback));
+ }
+ }
+ });
+ if(Object.keys(spellUpdate).length > 0) {
+ setAttrs(spellUpdate, {silent: true}, () => {
+ spellCallbacks.forEach(callback => {
+ callback();
+ });
+ });
+ }
+ });
+ } catch (error) {
+ errorMessage("Spells", error)
+ }
+ }
+
+ if (blob["Custom Spells"]) {
+ try {
+ let customSpells = dropFunctions.jsonParse(blob["Custom Spells"]);
+ let spellUpdate = {}, spellCallbacks = [];
+ customSpells.forEach(spellInformation => {
+ const mockPage = {
+ name: spellInformation.Name,
+ data: {
+ "Category": "Spells"
+ }
+ }
+ Object.assign(mockPage.data, spellInformation);
+ const processedSpell = processDrop(mockPage, currentData, repeating);
+ Object.assign(spellUpdate, processedSpell.update);
+ processedSpell.callbacks.forEach(callback => spellCallbacks.push(callback));
+ });
+
+ setAttrs(spellUpdate, {silent: true}, () => {
+ spellCallbacks.forEach(callback => {
+ callback();
+ });
+ });
+ } catch (error) {
+ errorMessage("Custom Spells", error)
+ }
+ }
+ }
+
+ return {
+ update: update,
+ repeating: repeating,
+ callbacks: callbacks
+ };
+};
+
+
diff --git a/Brancalonia Official/src/js/dragndrop/dropFunctions.js b/Brancalonia Official/src/js/dragndrop/dropFunctions.js
new file mode 100644
index 0000000000..18716c09bd
--- /dev/null
+++ b/Brancalonia Official/src/js/dragndrop/dropFunctions.js
@@ -0,0 +1,268 @@
+const dropFunctions = {
+ validateCantripScaling: scaling => scaling === 'dice' || scaling === 'beam' ? true : false,
+ buildCantripScaling: scaling => `Cantrip ${scaling.charAt(0).toUpperCase()}${scaling.slice(1)}`,
+
+ buildDamage: (page, currentData, alternateDamage) => {
+ try {
+ const modifiers = dropFunctions.inferAbilityModifier(page.data["Item Type"], page.data["Properties"], currentData)
+ let damage = alternateDamage ? alternateDamage : page.data[`Damage`];
+ damage += modifiers && modifiers != 0 ? `+${modifiers}` : ""
+ damage += page.data["Modifiers"] ? dropFunctions.inferModifier(page.data["Modifiers"], 'damage') : ""
+
+ return damage
+ } catch (error) {
+ console.error(error)
+ return ''
+ }
+ },
+
+ buildItemModString: page => {
+ try {
+ let mods = `Item Type: ${page.data["Item Type"] || page.data["Category"]}`;
+
+ //Items with ac or attack related bonuses
+ ["AC", "Damage", "Damage Type", "Secondary Damage", "Secondary Damage Type", "Alternate Damage", "Alternate Damage Type", "Alternate Secondary Damage", "Alternate Secondary Damage Type", "Critical Range", "Range"].forEach(attr => {
+ mods += page.data[`${attr}`] && page.data[`${attr}`] != "" ? `, ${attr}: ${page.data[`${attr}`]}` : "";
+ });
+
+ //Items with modifiers such as Cloak of Protection
+ mods += page.data["Modifiers"] && page.data["Modifiers"] != "" ? `, ${page.data["Modifiers"]}` : "";
+
+ return mods
+ } catch (error) {
+ console.error(error)
+ return ''
+ }
+ },
+
+ buildSpellQuery: spellLevel => {
+ try {
+ let spellQuery = ""
+ for(i = 0; i < 10-spellLevel; i++) {
+ const sum = (parseInt(i, 10) + parseInt(spellLevel, 10))
+ spellQuery += `|Level ${sum},${sum}`
+ };
+
+ return `@{wtype}&{template:spell} {{level=@{spellschool} ?{Cast at what level?${spellQuery}}}} {{name=@{spellname}}} {{castingtime=@{spellcastingtime}}} {{range=@{spellrange}}} {{target=@{spelltarget}}} @{spellcomp_v} @{spellcomp_s} @{spellcomp_m} {{material=@{spellcomp_materials}}} {{duration=@{spellduration}}} {{description=@{spelldescription}}} {{athigherlevels=@{spellathigherlevels}}} @{spellritual} {{innate=@{innate}}} @{spellconcentration} @{charname_output}`
+ } catch (error) {
+ console.error(error)
+ }
+ },
+
+ buildToHit: (page, currentData) => {
+ try {
+ let hit = dropFunctions.inferAbilityModifier(page.data["Item Type"], page.data["Properties"], currentData);
+ hit += page.data["Modifiers"] ? dropFunctions.inferModifier(page.data["Modifiers"], 'attacks') : "";
+ return hit
+ } catch (error) {
+ console.error(error)
+ return ''
+ }
+ },
+
+ buildSenses: (senses, passivePerception) => {
+ try {
+ return senses ? `${senses}, passive Perception ${passivePerception}` : `passive Perception ${passivePerception}`;
+ } catch (error) {
+ console.log(error)
+ return ''
+ }
+ },
+
+ buildSpellList: spells => {
+ try {
+ let spellList = []
+ //Create an array of spells to get from the Comepndium
+ const spellTypes = ["spells", "innate"]
+ spellTypes.forEach(type => {
+ const spellObject = dropFunctions.jsonParse(spells)[type]
+ if (spellObject) {
+ for (let [key, value] of Object.entries(spellObject)) {
+ value.forEach(spell => spellList.push(spell))
+ }
+ }
+ })
+ return spellList
+ } catch (error) {
+ console.log(error)
+ }
+ },
+
+ buildType: (size, type, aligment) => {
+ let string = size || "";
+ type ? string += ` ${type}` : false;
+ aligment ? string += `, ${aligment}`: false;
+ return string
+ },
+
+ confirmFinesse: properties => properties.toLowerCase().includes("finesse") ? true : false,
+ confirmRanged: itemType => itemType.toLowerCase().includes("ranged") ? true : false,
+ confirmDexGreaterThanStr: (dex, str) => dex > str ? true : false,
+
+ convertAbbreviationToAttribute: threeLetterString => {
+ switch(threeLetterString.toLowerCase()) {
+ case "str":
+ return "@{strength_mod}";
+ break;
+ case "dex":
+ return "@{dexterity_mod}";
+ break;
+ case "con":
+ return "@{constitution_mod}";
+ break;
+ case "wis":
+ return "@{wisdom_mod}";
+ break;
+ case "int":
+ return "@{intelligence_mod}";
+ break;
+ case "cha":
+ return "@{charisma_mod}";
+ break;
+ default:
+ errorMessage("convertAbbreviationToAttribute", `${threeLetterString} did not match one of the expected types str, dex, con, wis, int, cha`)
+ return false
+ }
+ },
+
+ determineComponent: (componentList, component) => componentList.toLowerCase().includes(component) ? `{{${component}=1}}` : false,
+
+ inferAbilityModifier: (type, properties, currentData) => {
+ try {
+ const ranged = type ? dropFunctions.confirmRanged(type) : false;
+ const finesse = properties ? dropFunctions.confirmFinesse(properties) : false;
+ const dexGreaterThanStr = dropFunctions.confirmDexGreaterThanStr(currentData.dexterity_mod, currentData.strength_mod);
+
+ return ranged || (finesse && dexGreaterThanStr) ? currentData.dexterity_mod : currentData.strength_mod
+ } catch (error) {
+ console.log(error)
+ }
+ },
+
+ inferBaseAttribute: attribute => attribute.includes('(') ? attribute.split(" (")[0] : attribute,
+
+ inferCasterLevel: description => parseInt(description.substring(description.indexOf("-level")-4, description.indexOf("-level")-2).trim(), 10) || 1,
+
+ inferFormulaAttribute: attribute => attribute.includes('(') ? attribute.split(" (")[1].slice(0, -1) : "",
+
+ inferModifier: (modifiers, type) => {
+ try {
+ let modifier = "";
+ modifiers = modifiers.split(',');
+ modifiers.forEach(value => {
+ modifier += value.toLowerCase().includes(type) ? value.split(' ').pop() : ""
+ });
+ return modifier
+ } catch (error) {
+ console.log(error)
+ return ''
+ }
+ },
+
+ inferSpellcastingAbility: description => {
+ let ability = description.match(/casting ability is (.*?) /);
+ ability = ability && ability.length > 1 ? ability[1] : false;
+ ability = ability ? `@{${ability.toLowerCase()}_mod}+` : "0*";
+ return ability
+ },
+
+ inferSavingThrows: saves => {
+ try {
+ let object = {};
+ if (saves) {
+ saves = saves.includes(', ') ? saves.split(", ") : [saves]
+ saves.forEach(saveValue => {
+ const split = saveValue.includes(' ') ? saveValue.split(' ') : errorMessage(`inferSavingThrows`, `${saveValue} does no include a space`)
+ const abbreviation = split[0].toLowerCase();
+ object[`npc_${abbreviation}_save_base`] = split.pop();
+ });
+ }
+ return object
+ } catch (error) {
+ errorMessage('inferSavingThrows', error)
+ }
+ },
+
+ inferSkills: skills => {
+ try {
+ let object = {};
+ if (skills) {
+ skills = skills.includes(', ') ? skills.split(", ") : [skills]
+ skills.forEach(skillValue => {
+ const split = skillValue.includes(' ') ? skillValue.split(' ') : errorMessage(`inferSkills`, `${skillValue} does no include a space`)
+ const value = split.pop();
+ const name = split.length > 2 ? split.join("_").toLowerCase() : split.shift().toLowerCase();
+ object[`npc_${name}_base`] = value;
+ });
+ }
+ return object
+ } catch (error) {
+ errorMessage('inferSkills', error)
+ }
+ },
+
+ jsonParse: (data, defaultValue) => {
+ let result = null;
+ try {
+ result = JSON.parse(data);
+ } catch (error) {
+ switch(typeof defaultValue) {
+ case 'boolean':
+ case 'number':
+ case 'string':
+ case 'function':
+ result = (typeof data === typeof defaultValue) ? data : defaultValue;
+ break;
+ case 'object':
+ result = (typeof data === typeof defaultValue && data.constructor.name === defaultValue.constructor.name) ? data : defaultValue;
+ break;
+ default:
+ errorMessage('Invalid JSON', error);
+ }
+ }
+ return result;
+ },
+
+ updateSheetAttributes: newObjectForSheet => {
+ try {
+ let update = {};
+
+ for (let [key, value] of Object.entries(newObjectForSheet.attributes)) {
+ //If repeating section, update key needs the repeating information
+ const updateKey = newObjectForSheet.reprowid ? newObjectForSheet.addAttribute(key) : key;
+
+ //This 'update' will be handed to a setAttrs function
+ update[updateKey] = newObjectForSheet.attributes[key];
+ }
+
+ return update
+ } catch (error) {
+ errorMessage(`updateSheetAttributes`, error);
+ }
+ }
+}
+
+//These functions handle 'repeating' parameter of processDrop
+const dropHelpers = {
+ findToolId: (repeatingTools, toolName) => {
+ let id = false
+ for(let [key, value] of Object.entries(repeatingTools)) {
+ value.toolname === toolName.toLowerCase() ? id = key : false;
+ }
+ return id
+ },
+ updateRepeatingTools: (newTool, existingTool) => {
+ existingTool.id = newTool.reprowid
+ existingTool.toolname = newTool.attributes.toolname.toLowerCase()
+ existingTool.base = newTool.attributes.toolbonus_base
+ return existingTool
+ },
+ updateRepeatingTraits: (newTrait, existingTrait) => {
+ existingTrait.id = newTrait.reprowid;
+ existingTrait.name = newTrait.attributes.name;
+ existingTrait.source = newTrait.attributes.source;
+ existingTrait.type = newTrait.attributes.source_type;
+
+ return existingTrait
+ }
+}
diff --git a/Brancalonia Official/src/js/helperFunctions.js b/Brancalonia Official/src/js/helperFunctions.js
new file mode 100644
index 0000000000..2d65147f0d
--- /dev/null
+++ b/Brancalonia Official/src/js/helperFunctions.js
@@ -0,0 +1,23 @@
+
+const errorMessage = (name, error) => console.error(`%c ${name}: ${error}`, "color: orange; font-weight:14px;");
+const warningMessage = (name, error) => console.warn(`%c ${name}: ${error}`, "color: gold; font-weight:14px;");
+
+const checkSourceForSheetworker = eventinfo => eventinfo.sourceType && eventinfo.sourceType != "sheetworker" ? true : false
+
+// Example: -m2jzgfth07mvwp3hhng
+const getReprowid = sourceAttribute => sourceAttribute.split('_')[2]
+
+// Example: repeating_tool_-m2jzgfth07mvwp3hhng
+const getRepeatingSectionPrefix = sourceAttribute => {
+ const split = sourceAttribute.split('_');
+ return `${split[0]}_${split[1]}_${split[2]}`
+}
+
+// Example: repeating_tool_-m2jzgfth07mvwp3hhng_attkflag returns attkflag
+const getAttrNameAtEndRepeating = sourceAttribute => {
+ const repeatingSplit = sourceAttribute.split('_')
+ const repeatingSplice = repeatingSplit.splice(3)
+ const repeatingAttrName = repeatingSplice.length > 1 ? repeatingSplice.join('_') : repeatingSplice[0]
+ return repeatingAttrName
+}
+
diff --git a/Brancalonia Official/src/js/sheetworkers.js b/Brancalonia Official/src/js/sheetworkers.js
new file mode 100644
index 0000000000..34f5a20bcf
--- /dev/null
+++ b/Brancalonia Official/src/js/sheetworkers.js
@@ -0,0 +1,6398 @@
+// Create a collective list of attributs to reduce redundancy
+var abilityList = [
+ "Strength",
+ "Dexterity",
+ "Constitution",
+ "Intelligence",
+ "Wisdom",
+ "Charisma",
+];
+var abilityListEnabledOptionals = [];
+const globalAttributesByCategory = {
+ abilities: [
+ "strength",
+ "dexterity",
+ "constitution",
+ "intelligence",
+ "wisdom",
+ "charisma",
+ ],
+ abilitiesWithAllOptionals: [
+ "strength",
+ "dexterity",
+ "constitution",
+ "intelligence",
+ "wisdom",
+ "charisma",
+ "honor",
+ "sanity",
+ ],
+ classes: [
+ "artificer",
+ "barbarian",
+ "bard",
+ "cleric",
+ "druid",
+ "fighter",
+ "monk",
+ "paladin",
+ "ranger",
+ "rogue",
+ "sorcerer",
+ "warlock",
+ "wizard",
+ ],
+ hitDieTypes: ["d4", "d6", "d8", "d10", "d12"],
+ spellLevels: ["cantrip", "1", "2", "3"],
+ traitsTypes: ["Background", "Feats", "Racial", "Class", "Other"],
+ proficiencyTypes: ["LANGUAGE", "ARMOR", "WEAPON", "OTHER"],
+ skills: {
+ strength: ["athletics"],
+ constitution: [],
+ dexterity: ["acrobatics", "sleight_of_hand", "stealth"],
+ intelligence: ["arcana", "history", "investigation", "nature", "religion"],
+ wisdom: [
+ "animal_handling",
+ "insight",
+ "medicine",
+ "perception",
+ "survival",
+ ],
+ charisma: ["deception", "intimidation", "performance", "persuasion"],
+ honor: [],
+ sanity: [],
+ all: () => {
+ return [
+ ...globalAttributesByCategory.skills.strength,
+ ...globalAttributesByCategory.skills.dexterity,
+ ...globalAttributesByCategory.skills.intelligence,
+ ...globalAttributesByCategory.skills.wisdom,
+ ...globalAttributesByCategory.skills.charisma,
+ ];
+ },
+ getParentAbility: (skill) => {
+ let parent = "";
+ globalAttributesByCategory["abilities"].forEach((ability) => {
+ if (globalAttributesByCategory.skills[ability].indexOf(skill) > -1) {
+ parent = ability;
+ return;
+ }
+ });
+ return parent;
+ },
+ },
+};
+
+//Overwrites default defaultGetCharmancerData
+var defaultGetCharmancerData = getCharmancerData;
+var getCharmancerData = function () {
+ const data = defaultGetCharmancerData();
+ includeLPFeatsInCharmancerData(data);
+ return data;
+};
+var includeLPFeatsInCharmancerData = function (data) {
+ if (SheetUtils.checkPath(data, "['lp-asi']['values']")) {
+ var feats = {};
+ Object.keys(data["lp-asi"]["values"]).forEach((value) => {
+ if (
+ value.indexOf("asi-row_switch") &&
+ data["lp-asi"]["values"][value] === "feat"
+ ) {
+ const rowID = SheetUtils.getUID(value);
+ const rowName = `repeating_${rowID}_asi-row_feat`;
+ if (
+ SheetUtils.checkPath(data, `['lp-asi']['values']['${rowName}_data']`)
+ ) {
+ const featData = JSON.parse(
+ data["lp-asi"]["values"][`${rowName}_data`]
+ );
+ //delete data['lp-asi']['values'][`${rowName}_data`];
+ data["lp-asi"]["data"][rowName] = featData;
+ }
+ }
+ });
+ }
+};
+
+//Start of Compendium Drops
+on("sheet:compendium-drop", function () {
+ getAttrs(
+ [
+ "hp_max",
+ "npc_senses",
+ "token_size",
+ "cd_bar1_v",
+ "cd_bar1_m",
+ "cd_bar1_l",
+ "cd_bar2_v",
+ "cd_bar2_m",
+ "cd_bar2_l",
+ "cd_bar3_v",
+ "cd_bar3_m",
+ "cd_bar3_l",
+ ],
+ function (v) {
+ var default_attr = {};
+ default_attr["width"] = 70;
+ default_attr["height"] = 70;
+ if (
+ v["npc_senses"]
+ .toLowerCase()
+ .match(/(darkvision|blindsight|tremorsense|truesight)/)
+ ) {
+ const nightVisionRange = Math.max.apply(
+ Math,
+ v["npc_senses"].match(/\d+/g)
+ );
+ //LDL
+ default_attr["light_radius"] = nightVisionRange;
+ //UDL
+ default_attr["has_bright_light_vision"] = "on"; //Toggles Vision On
+ default_attr["has_low_light_vision"] = "on"; //Toggles Vision On
+ default_attr["has_night_vision"] = "on"; //Toggles Night Vision On
+ default_attr["night_vision_distance"] = nightVisionRange; //Set Night Vision Range
+ }
+ if (v["token_size"]) {
+ var squarelength = 70;
+ if (v["token_size"].toString().indexOf(",") > -1) {
+ var setwidth = !isNaN(v["token_size"].split(",")[0])
+ ? v["token_size"].split(",")[0]
+ : 1;
+ var setheight = !isNaN(v["token_size"].split(",")[1])
+ ? v["token_size"].split(",")[1]
+ : 1;
+ default_attr["width"] = setwidth * squarelength;
+ default_attr["height"] = setheight * squarelength;
+ } else {
+ default_attr["width"] = squarelength * v["token_size"];
+ default_attr["height"] = squarelength * v["token_size"];
+ }
+ }
+
+ var getList = {};
+ for (x = 1; x <= 3; x++) {
+ _.each(["v", "m"], function (letter) {
+ var keyname = "cd_bar" + x + "_" + letter;
+ if (v[keyname] != undefined && isNaN(v[keyname])) {
+ getList[keyname] = v[keyname];
+ }
+ });
+ }
+
+ getAttrs(_.values(getList), function (values) {
+ _.each(_.keys(getList), function (keyname) {
+ v[keyname] =
+ values[getList[keyname]] == undefined
+ ? ""
+ : values[getList[keyname]];
+ });
+
+ if (v["cd_bar1_l"]) {
+ default_attr["bar1_link"] = v["cd_bar1_l"];
+ } else if (v["cd_bar1_v"] || v["cd_bar1_m"]) {
+ if (v["cd_bar1_v"]) {
+ default_attr["bar1_value"] = v["cd_bar1_v"];
+ }
+ if (v["cd_bar1_m"]) {
+ default_attr["bar1_max"] = v["cd_bar1_m"];
+ }
+ } else {
+ default_attr["bar1_value"] = v["hp_max"];
+ default_attr["bar1_max"] = v["hp_max"];
+ }
+
+ if (v["cd_bar2_l"]) {
+ default_attr["bar2_link"] = v["cd_bar2_l"];
+ } else if (v["cd_bar2_v"] || v["cd_bar2_m"]) {
+ if (v["cd_bar2_v"]) {
+ default_attr["bar2_value"] = v["cd_bar2_v"];
+ }
+ if (v["cd_bar2_m"]) {
+ default_attr["bar2_max"] = v["cd_bar2_m"];
+ }
+ } else {
+ default_attr["bar2_link"] = "npc_ac";
+ }
+
+ if (v["cd_bar3_l"]) {
+ default_attr["bar3_link"] = v["cd_bar3_l"];
+ } else if (v["cd_bar3_v"] || v["cd_bar3_m"]) {
+ if (v["cd_bar3_v"]) {
+ default_attr["bar3_value"] = v["cd_bar3_v"];
+ }
+ if (v["cd_bar3_m"]) {
+ default_attr["bar3_max"] = v["cd_bar3_m"];
+ }
+ }
+
+ setDefaultToken(default_attr);
+ });
+ }
+ );
+});
+
+globalAttributesByCategory.abilitiesWithAllOptionals.forEach((attr) => {
+ on(`change:${attr}_base change:${attr}_bonus`, function () {
+ update_attr(`${attr}`);
+ });
+});
+
+globalAttributesByCategory.abilitiesWithAllOptionals.forEach((attr) => {
+ on(`change:${attr}`, function () {
+ update_mod(`${attr}`);
+
+ const cap = attr.charAt(0).toUpperCase() + attr.slice(1);
+ check_customac(cap);
+
+ attr === "strength" ? update_weight() : false;
+ attr === "dexterity" ? update_initiative() : false;
+ });
+});
+
+globalAttributesByCategory.abilitiesWithAllOptionals.forEach((attr) => {
+ on(`change:${attr}_mod`, function () {
+ update_save(`${attr}`);
+ update_attacks(`${attr}`);
+ update_tool(`${attr}`);
+ update_spell_info(`${attr}`);
+
+ switch (`${attr}`) {
+ case "strength":
+ update_skills(["athletics"]);
+ break;
+ case "dexterity":
+ update_skills(["acrobatics", "sleight_of_hand", "stealth"]);
+ update_ac();
+ update_initiative();
+ break;
+ case "intelligence":
+ update_skills([
+ "arcana",
+ "history",
+ "investigation",
+ "nature",
+ "religion",
+ ]);
+ break;
+ case "wisdom":
+ update_skills([
+ "animal_handling",
+ "insight",
+ "medicine",
+ "perception",
+ "survival",
+ ]);
+ break;
+ case "charisma":
+ update_skills([
+ "deception",
+ "intimidation",
+ "performance",
+ "persuasion",
+ ]);
+ break;
+ default:
+ false;
+ }
+ });
+});
+
+globalAttributesByCategory.abilitiesWithAllOptionals.forEach((attr) => {
+ on(`change:${attr}_save_prof change:${attr}_save_mod`, function (eventinfo) {
+ checkSourceForSheetworker(eventinfo) ? update_save(`${attr}`) : false;
+ });
+});
+
+on("change:globalsavemod", function (eventinfo) {
+ checkSourceForSheetworker(eventinfo) ? update_all_saves() : false;
+});
+
+on("change:death_save_mod", function (eventinfo) {
+ checkSourceForSheetworker(eventinfo) ? update_save("death") : false;
+});
+
+globalAttributesByCategory.skills.all().forEach((attr) => {
+ on(
+ `change:${attr}_prof change:${attr}_type change:${attr}_flat`,
+ function (eventinfo) {
+ checkSourceForSheetworker(eventinfo) ? update_skills([`${attr}`]) : false;
+ }
+ );
+});
+
+on(
+ "change:repeating_tool:toolname change:repeating_tool:toolbonus_base change:repeating_tool:toolattr_base change:repeating_tool:tool_mod",
+ function (eventinfo) {
+ const repeatingRowID = getReprowid(eventinfo.sourceAttribute);
+ checkSourceForSheetworker(eventinfo) ? update_tool(repeatingRowID) : false;
+ }
+);
+
+on(
+ "change:repeating_attack:atkname change:repeating_attack:atkflag change:repeating_attack:atkattr_base change:repeating_attack:atkmod change:repeating_attack:atkmagic change:repeating_attack:atkcritrange change:repeating_attack:atkprofflag change:repeating_attack:dmgflag change:repeating_attack:dmgbase change:repeating_attack:dmgattr change:repeating_attack:dmgmod change:repeating_attack:dmgtype change:repeating_attack:dmg2flag change:repeating_attack:dmg2base change:repeating_attack:dmg2attr change:repeating_attack:dmg2mod change:repeating_attack:dmg2type change:repeating_attack:saveflag change:repeating_attack:savedc change:repeating_attack:saveflat change:repeating_attack:dmgcustcrit change:repeating_attack:dmg2custcrit change:repeating_attack:ammo change:repeating_attack:saveattr change:repeating_attack:atkrange",
+ function (eventinfo) {
+ if (checkSourceForSheetworker(eventinfo)) {
+ var source = getAttrNameAtEndRepeating(eventinfo.sourceAttribute);
+ var attackid = getReprowid(eventinfo.sourceAttribute);
+
+ if (source == "atkattr_base" || source == "savedc") {
+ getAttrs(
+ ["repeating_attack_spellid", "repeating_attack_spelllevel"],
+ function (v) {
+ set = {};
+ if (
+ v.repeating_attack_spellid &&
+ v.repeating_attack_spellid != "" &&
+ v.repeating_attack_spelllevel &&
+ v.repeating_attack_spelllevel != ""
+ ) {
+ var newVal =
+ eventinfo.newValue == "spell"
+ ? "spell"
+ : _.last(eventinfo.newValue.split("_")[0].split("{"));
+ set["repeating_attack_atkattr_base"] =
+ newVal == "spell" ? "spell" : "@{" + newVal + "_mod}";
+ set["repeating_attack_savedc"] =
+ newVal == "spell" ? "spell" : "(@{" + newVal + "_mod}+8+@{pb})";
+ set[
+ "repeating_spell-" +
+ v.repeating_attack_spelllevel +
+ "_" +
+ v.repeating_attack_spellid +
+ "_spell_ability"
+ ] = newVal == "spell" ? "spell" : "@{" + newVal + "_mod}+";
+ }
+ setAttrs(set, function () {
+ update_attacks(attackid);
+ });
+ }
+ );
+ } else {
+ update_attacks(attackid);
+ }
+ }
+ }
+);
+
+on("change:default_critical_range", function (eventinfo) {
+ if (checkSourceForSheetworker(eventinfo)) {
+ update_attacks("all");
+ }
+});
+
+on(
+ "change:repeating_damagemod remove:repeating_damagemod",
+ function (eventinfo) {
+ update_globaldamage();
+ }
+);
+
+on("change:global_damage_mod_flag", function (eventinfo) {
+ getSectionIDs("damagemod", function (ids) {
+ var update = {};
+ if (eventinfo.newValue === "1") {
+ if (!ids || ids.length === 0) {
+ var rowid = generateRowID();
+ update[`repeating_damagemod_${rowid}_global_damage_active_flag`] = "1";
+ }
+ } else {
+ _.each(ids, function (rowid) {
+ update[`repeating_damagemod_${rowid}_global_damage_active_flag`] = "0";
+ });
+ }
+ setAttrs(update);
+ });
+});
+
+on("change:exhaustion_toggle", function (eventinfo) {
+ if (eventinfo.newValue !== "0") {
+ getAttrs(["exhaustion_level"], function (attrs) {
+ if (!attrs.exhaustion_level || attrs.exhaustion_level === "") {
+ var update = {};
+ update.exhaustion_level = "0";
+ setAttrs(update);
+ }
+ });
+ }
+});
+
+on("change:exhaustion_level", function (eventinfo) {
+ const newValue = parseInt(eventinfo.newValue) || 0,
+ previousValue = parseInt(eventinfo.previousValue) || 0;
+ let update = {};
+
+ if (newValue === 0) {
+ //If exhaustion is 0 the reset exhaustion_1 to "No Effect" and blank the other spans
+ for (let i = 2; i <= 6; i++) {
+ update[`exhaustion_${i}`] = "";
+ }
+ update[`exhaustion_1`] = "• " + getTranslationByKey(`exhaustion-0`);
+ } else if (newValue > previousValue) {
+ //If exhaustion increase then add text to the spans
+ for (let i = previousValue; i <= newValue; i++) {
+ update[`exhaustion_${i}`] = "• " + getTranslationByKey(`exhaustion-${i}`);
+ }
+ } else {
+ //If exhaustion decrease remove text from spans
+ for (let i = newValue + 1; i <= previousValue; i++) {
+ update[`exhaustion_${i}`] = "";
+ }
+ }
+
+ setAttrs(update, { silent: true });
+});
+
+on("change:race change:subrace", function (eventinfo) {
+ update_race_display();
+});
+
+on(`change:repeating_inventory:hasattack`, function (eventinfo) {
+ if (checkSourceForSheetworker(eventinfo)) {
+ const itemid = getReprowid(eventinfo.sourceAttribute);
+ getAttrs([`repeating_inventory_${itemid}_itemattackid`], function (v) {
+ const hasattack = eventinfo.newValue,
+ itemattackid = v[`repeating_inventory_${itemid}_itemattackid`];
+ hasattack == 1
+ ? create_attack_from_item(itemid)
+ : remove_attack(itemattackid);
+ });
+ }
+});
+
+on(`change:repeating_inventory:useasresource`, function (eventinfo) {
+ if (checkSourceForSheetworker(eventinfo)) {
+ const itemid = getReprowid(eventinfo.sourceAttribute);
+ getAttrs([`repeating_inventory_${itemid}_itemresourceid`], function (v) {
+ const useasresource = eventinfo.newValue,
+ itemresourceid = v[`repeating_inventory_${itemid}_itemresourceid`];
+ useasresource == 1
+ ? create_resource_from_item(itemid)
+ : remove_resource(itemresourceid);
+ });
+ }
+});
+
+on(
+ "change:repeating_inventory:itemname change:repeating_inventory:itemproperties change:repeating_inventory:itemmodifiers change:repeating_inventory:itemcount",
+ function (eventinfo) {
+ if (checkSourceForSheetworker(eventinfo)) {
+ var itemid = getReprowid(eventinfo.sourceAttribute);
+ getAttrs(
+ [
+ "repeating_inventory_" + itemid + "_itemattackid",
+ "repeating_inventory_" + itemid + "_itemresourceid",
+ ],
+ function (v) {
+ var attackid = v["repeating_inventory_" + itemid + "_itemattackid"];
+ var resourceid =
+ v["repeating_inventory_" + itemid + "_itemresourceid"];
+ if (attackid) {
+ update_attack_from_item(itemid, attackid);
+ }
+ if (resourceid) {
+ update_resource_from_item(itemid, resourceid);
+ }
+ }
+ );
+ }
+ }
+);
+
+[
+ "other_resource",
+ "repeating_resource:resource_left",
+ "repeating_resource:resource_right",
+].forEach((attr) => {
+ on(`change:${attr} change:${attr}_name`, (eventinfo) => {
+ if (checkSourceForSheetworker(eventinfo)) {
+ const resourceid = eventinfo.sourceAttribute.includes("_name")
+ ? eventinfo.sourceAttribute.slice(0, -5)
+ : eventinfo.sourceAttribute;
+ getAttrs([`${resourceid}_itemid`], (v) => {
+ const value = eventinfo.newValue;
+ //Update repeating_inventory if an itemid is associated with a resource
+ if (v[`${resourceid}_itemid`] && v[`${resourceid}_itemid`] != "") {
+ const itemid = v[`${resourceid}_itemid`];
+ let update = {};
+ if (eventinfo.sourceAttribute.includes("_name")) {
+ update[`repeating_inventory_${itemid}_itemname`] =
+ eventinfo.newValue;
+ } else {
+ update[`repeating_inventory_${itemid}_itemcount`] =
+ eventinfo.newValue;
+ }
+ setAttrs(update, { silent: true }, () => {
+ update_weight();
+ });
+ }
+ });
+ }
+ });
+});
+
+on(
+ "change:repeating_inventory:itemweight change:repeating_inventory:itemcount change:repeating_inventory:equipped change:cp change:sp change:ep change:gp change:pp change:encumbrance_setting change:size change:carrying_capacity_mod change:ingore_non_equipped_weight",
+ function () {
+ update_weight();
+ }
+);
+
+on(
+ "change:repeating_inventory:itemmodifiers change:repeating_inventory:equipped",
+ function (eventinfo) {
+ if (checkSourceForSheetworker(eventinfo)) {
+ var itemid = getReprowid(eventinfo.sourceAttribute);
+ getAttrs(
+ ["repeating_inventory_" + itemid + "_itemmodifiers"],
+ function (v) {
+ if (v["repeating_inventory_" + itemid + "_itemmodifiers"]) {
+ check_itemmodifiers(
+ v["repeating_inventory_" + itemid + "_itemmodifiers"],
+ eventinfo.previousValue
+ );
+ }
+ }
+ );
+ }
+ }
+);
+
+on(
+ "change:custom_ac_flag change:custom_ac_base change:custom_ac_part1 change:custom_ac_part2 change:custom_ac_shield",
+ function (eventinfo) {
+ checkSourceForSheetworker(eventinfo) ? update_ac() : false;
+ }
+);
+
+[
+ "spell-cantrip",
+ "spell-1",
+ "spell-2",
+ "spell-3",
+].forEach((attr) => {
+ on(
+ `change:repeating_${attr}:includedesc change:repeating_${attr}:innate change:repeating_${attr}:spell_ability change:repeating_${attr}:spell_updateflag change:repeating_${attr}:spellathigherlevels change:repeating_${attr}:spellattack change:repeating_${attr}:spelldamage change:repeating_${attr}:spelldamage2 change:repeating_${attr}:spelldamagetype change:repeating_${attr}:spelldamagetype2 change:repeating_${attr}:spelldescription change:repeating_${attr}:spelldmgmod change:repeating_${attr}:spellhealing change:repeating_${attr}:spellhlbonus change:repeating_${attr}:spellhldie change:repeating_${attr}:spellhldietype change:repeating_${attr}:spellname change:repeating_${attr}:spellprepared change:repeating_${attr}:spellrange change:repeating_${attr}:spellsave change:repeating_${attr}:spellsavesuccess change:repeating_${attr}:spelltarget change:repeating_${attr}:spell_damage_progression`,
+ (eventinfo) => {
+ if (checkSourceForSheetworker(eventinfo)) {
+ const spellid = eventinfo.sourceAttribute.split("_")[2],
+ repeating_source = `repeating_${attr}_${spellid}`;
+ getAttrs([`${repeating_source}_spellattackid`, "character_id"], (v) => {
+ var attackid = v[`${repeating_source}_spellattackid`];
+ var lvl = attr.split("spell-")[1];
+ if (attackid && lvl && spellid) {
+ update_attack_from_spell(
+ lvl,
+ spellid,
+ attackid,
+ false,
+ v["character_id"]
+ );
+ }
+ });
+ }
+ }
+ );
+});
+
+[
+ "spell-cantrip",
+ "spell-1",
+ "spell-2",
+ "spell-3",
+].forEach((attr) => {
+ on(`change:repeating_${attr}:spelloutput`, (eventinfo) => {
+ if (checkSourceForSheetworker(eventinfo)) {
+ const spellid = eventinfo.sourceAttribute.split("_")[2],
+ repeating_source = `repeating_${attr}_${spellid}`;
+ getAttrs(
+ [
+ `${repeating_source}_spellattackid`,
+ `${repeating_source}_spelllevel`,
+ `${repeating_source}_spellathigherlevels`,
+ "character_id",
+ ],
+ function (v) {
+ const attackid = v[repeating_source + "_spellattackid"];
+ const higherlevels = v[repeating_source + "_spellathigherlevels"];
+ const spelloutput = eventinfo.newValue;
+ let lvl = v[repeating_source + "_spelllevel"];
+
+ if (spelloutput && spelloutput === "ATTACK") {
+ create_attack_from_spell(lvl, spellid, v["character_id"]);
+ } else if (
+ spelloutput &&
+ spelloutput === "SPELLCARD" &&
+ attackid &&
+ attackid != ""
+ ) {
+ let lvl = parseInt(v[repeating_source + "_spelllevel"], 10);
+ remove_attack(attackid);
+ update_spelloutput(
+ higherlevels,
+ lvl,
+ repeating_source,
+ spelloutput
+ );
+ }
+ }
+ );
+ }
+ });
+});
+
+[
+ "spell-cantrip",
+ "spell-1",
+ "spell-2",
+ "spell-3",
+].forEach((attr) => {
+ on(`change:repeating_${attr}:spellathigherlevels`, (eventinfo) => {
+ if (checkSourceForSheetworker(eventinfo)) {
+ const spellid = eventinfo.sourceAttribute.split("_")[2],
+ repeating_source = `repeating_${attr}_${spellid}`;
+ getAttrs(
+ [`${repeating_source}_spelllevel`, `${repeating_source}_spelloutput`],
+ function (v) {
+ const higherlevels = eventinfo.newValue;
+ const lvl = parseInt(v[repeating_source + "_spelllevel"], 10);
+ const spelloutput = v[repeating_source + "_spelloutput"];
+
+ if (spelloutput && spelloutput === "SPELLCARD") {
+ update_spelloutput(
+ higherlevels,
+ lvl,
+ repeating_source,
+ spelloutput
+ );
+ }
+ }
+ );
+ }
+ });
+});
+
+const update_spelloutput = (
+ higherlevels,
+ lvl,
+ repeating_source,
+ spelloutput
+) => {
+ let spelllevel = "@{spelllevel}";
+ let update = {};
+
+ if (higherlevels) {
+ for (i = 0; i < 3 - lvl; i++) {
+ let tot = parseInt(i, 3) + parseInt(lvl, 3);
+ spelllevel = spelllevel + "|Level " + tot + "," + tot;
+ }
+ spelllevel = `?{Cast at what level? ${spelllevel}}`;
+ }
+ update[
+ repeating_source + "_rollcontent"
+ ] = `@{wtype}&{template:spell} {{level=@{spellschool} ${spelllevel}}} {{name=@{spellname}}} {{castingtime=@{spellcastingtime}}} {{range=@{spellrange}}} {{target=@{spelltarget}}} @{spellcomp_v} @{spellcomp_s} @{spellcomp_m} {{material=@{spellcomp_materials}}} {{duration=@{spellduration}}} {{description=@{spelldescription}}} {{athigherlevels=@{spellathigherlevels}}} @{spellritual} {{innate=@{innate}}} {{savedc=@{spell_save_dc}}} @{spellconcentration} @{charname_output}`;
+ setAttrs(update, { silent: true });
+};
+
+on(
+ "change:class change:custom_class change:cust_classname change:cust_hitdietype change:cust_spellcasting_ability change:cust_spellslots change:cust_strength_save_prof change:cust_dexterity_save_prof change:cust_constitution_save_prof change:cust_intelligence_save_prof change:cust_wisdom_save_prof change:cust_charisma_save_prof change:subclass change:multiclass1 change:multiclass1_subclass change:multiclass2 change:multiclass2_subclass change:multiclass3 change:multiclass3_subclass",
+ function (eventinfo) {
+ checkSourceForSheetworker(eventinfo) ? update_class() : false;
+ }
+);
+
+on(
+ "change:level change:arcane_fighter change:arcane_rogue",
+ function (eventinfo) {
+ checkSourceForSheetworker(eventinfo) ? set_level() : false;
+ }
+);
+
+on(
+ "sheet:open change:level_calculations change:level change:lvl1_slots_mod change:lvl2_slots_mod change:lvl3_slots_mod", (eventInfo) => {
+ update_spell_slots();
+ }
+);
+
+on("change:caster_level", function (eventinfo) {
+ getAttrs(["caster_level", "npc"], function (v) {
+ var casterlvl =
+ v["caster_level"] && !isNaN(parseInt(v["caster_level"], 10))
+ ? parseInt(v["caster_level"], 10)
+ : 0;
+ if (v["npc"] && v["npc"] == 1 && casterlvl > 0) {
+ setAttrs({ level: casterlvl });
+ }
+ });
+});
+
+on("change:pb_type change:pb_custom", function (eventinfo) {
+ checkSourceForSheetworker(eventinfo) ? update_pb() : false;
+});
+
+on("change:dtype", function (eventinfo) {
+ if (checkSourceForSheetworker(eventinfo)) {
+ update_attacks("all");
+ update_npc_action("all");
+ }
+});
+
+on("change:jack_of_all_trades", function (eventinfo) {
+ if (checkSourceForSheetworker(eventinfo)) {
+ update_jack_attr();
+ update_all_ability_checks();
+ }
+});
+
+on("change:initmod change:init_tiebreaker", function (eventinfo) {
+ checkSourceForSheetworker(eventinfo) ? update_initiative() : false;
+});
+
+on(
+ "change:spellcasting_ability change:spell_dc_mod change:globalmagicmod",
+ function (eventinfo) {
+ checkSourceForSheetworker(eventinfo) ? update_spell_info() : false;
+ }
+);
+
+on("change:npc_challenge", function () {
+ update_challenge();
+});
+
+on(
+ "change:npc_str_save_base change:npc_dex_save_base change:npc_con_save_base change:npc_int_save_base change:npc_wis_save_base change:npc_cha_save_base",
+ function (eventinfo) {
+ update_npc_saves();
+ }
+);
+
+on(
+ "change:npc_acrobatics_base change:npc_animal_handling_base change:npc_arcana_base change:npc_athletics_base change:npc_deception_base change:npc_history_base change:npc_insight_base change:npc_intimidation_base change:npc_investigation_base change:npc_medicine_base change:npc_nature_base change:npc_perception_base change:npc_performance_base change:npc_persuasion_base change:npc_religion_base change:npc_sleight_of_hand_base change:npc_stealth_base change:npc_survival_base",
+ function (eventinfo) {
+ update_npc_skills();
+ }
+);
+
+["npcaction", "npcbonusaction", "npcaction-l", "npcaction-m"].forEach(
+ (fieldset) => {
+ [
+ "attack_flag",
+ "attack_type",
+ "attack_range",
+ "attack_target",
+ "attack_tohit",
+ "attack_damage",
+ "attack_damagetype",
+ "attack_damage2",
+ "attack_damagetype2",
+ "show_desc",
+ "description",
+ ].forEach((property) => {
+ on(`change:repeating_${fieldset}:${property}`, (eventInfo) => {
+ const actionid = eventInfo.sourceAttribute.split("_")[2];
+ update_npc_action(actionid, fieldset);
+ });
+ });
+ }
+);
+
+on("change:core_die change:halflingluck_flag", function () {
+ getAttrs(["core_die", "halflingluck_flag"], function (v) {
+ core = v.core_die && v.core_die != "" ? v.core_die : "1d20";
+ luck = v.halflingluck_flag && v.halflingluck_flag === "1" ? "ro<1" : "";
+ update = {};
+ update["d20"] = core + luck;
+ if (!v.core_die || v.core_die === "") {
+ update["core_die"] = "1d20";
+ }
+ setAttrs(update);
+ });
+});
+
+on("change:powerful_build", function () {
+ update_weight();
+});
+
+[`ac`, `attack`, "save", "skill"].forEach((attr) => {
+ on(`change:global_${attr}_mod_flag`, (eventinfo) => {
+ const mod = attr === "attack" ? "tohitmod" : `${attr}mod`;
+ if (eventinfo.newValue === "1") {
+ const firstAttr = attr === "ac" ? "val" : "roll";
+ const firstAttrValue = attr === "ac" ? 1 : "1d4";
+ const secondAttrValue =
+ attr === "ac" ? "Defense" : attr === "skill" ? "GUIDANCE" : "BLESS";
+
+ getSectionIDs(mod, (ids) => {
+ if (!ids || ids.length === 0) {
+ var update = {};
+ var rowid = generateRowID();
+ update[
+ `repeating_${mod}_${rowid}_global_${attr}_${firstAttr}`
+ ] = `${firstAttrValue}`;
+ update[
+ `repeating_${mod}_${rowid}_global_${attr}_name`
+ ] = `${secondAttrValue}`;
+ update[`repeating_${mod}_${rowid}_global_${attr}_active_flag`] = "1";
+ setAttrs(update);
+ }
+ });
+ } else {
+ getSectionIDs(mod, function (ids) {
+ var update = {};
+ var rowid = generateRowID();
+ _.each(ids, function (rowid) {
+ update[`repeating_${mod}_${rowid}_global_${attr}_active_flag`] = "0";
+ });
+ setAttrs(update);
+ });
+ }
+ });
+});
+
+on("change:repeating_skillmod remove:repeating_skillmod", function (eventinfo) {
+ update_globalskills();
+});
+
+on("change:repeating_savemod remove:repeating_savemod", function (eventinfo) {
+ update_globalsaves();
+});
+
+on("change:repeating_tohitmod remove:repeating_tohitmod", function (eventinfo) {
+ update_globalattack();
+});
+
+on("change:repeating_acmod remove:repeating_acmod", function (eventinfo) {
+ update_ac();
+});
+
+on("clicked:confirm_npc", eventInfo => {
+ setAttrs({ monster_confirm_flag: "" });
+ getAttrs(["drop_category"], function (v) {
+ if (v["drop_category"]) {
+ handle_drop(v["drop_category"]);
+ }
+ });
+});
+
+on("clicked:reject_npc", function (eventinfo) {
+ setAttrs({ monster_confirm_flag: "" });
+ var update = {};
+ update["drop_category"] = "";
+ update["drop_name"] = "";
+ update["drop_data"] = "";
+ update["drop_content"] = "";
+ setAttrs(update, { silent: true });
+});
+
+on("change:mancer_confirm", function (eventinfo) {
+ setAttrs(
+ { mancer_confirm_flag: "", charactermancer_step: "l1-welcome" },
+ function () {
+ check_l1_mancer();
+ }
+ );
+});
+
+on("change:mancer_cancel", function (eventinfo) {
+ setAttrs(
+ { mancer_confirm_flag: "", l1mancer_status: "completed" },
+ function () {
+ check_l1_mancer();
+ }
+ );
+});
+
+on("change:mancer_npc", function (eventinfo) {
+ setAttrs(
+ { mancer_confirm_flag: "", l1mancer_status: "completed", npc: "1" },
+ function () {
+ check_l1_mancer();
+ }
+ );
+});
+
+on("change:passiveperceptionmod", function (eventinfo) {
+ update_passive_perception();
+});
+
+on("remove:repeating_inventory", function (eventinfo) {
+ var itemid = getReprowid(eventinfo.sourceAttribute);
+ var attackids =
+ eventinfo.removedInfo &&
+ eventinfo.removedInfo["repeating_inventory_" + itemid + "_itemattackid"]
+ ? eventinfo.removedInfo["repeating_inventory_" + itemid + "_itemattackid"]
+ : undefined;
+ var resourceid =
+ eventinfo.removedInfo &&
+ eventinfo.removedInfo["repeating_inventory_" + itemid + "_itemresourceid"]
+ ? eventinfo.removedInfo[
+ "repeating_inventory_" + itemid + "_itemresourceid"
+ ]
+ : undefined;
+
+ if (attackids) {
+ _.each(attackids.split(","), function (value) {
+ remove_attack(value);
+ });
+ }
+ if (resourceid) {
+ remove_resource(resourceid);
+ }
+
+ if (
+ eventinfo.removedInfo &&
+ eventinfo.removedInfo["repeating_inventory_" + itemid + "_itemmodifiers"]
+ ) {
+ check_itemmodifiers(
+ eventinfo.removedInfo["repeating_inventory_" + itemid + "_itemmodifiers"]
+ );
+ }
+
+ update_weight();
+});
+
+on("remove:repeating_attack", function (eventinfo) {
+ var attackid = getReprowid(eventinfo.sourceAttribute);
+ var itemid =
+ eventinfo.removedInfo["repeating_attack_" + attackid + "_itemid"];
+ var spellid =
+ eventinfo.removedInfo["repeating_attack_" + attackid + "_spellid"];
+ var spelllvl =
+ eventinfo.removedInfo["repeating_attack_" + attackid + "_spelllevel"];
+ if (itemid) {
+ getAttrs(["repeating_inventory_" + itemid + "_hasattack"], function (v) {
+ if (
+ v["repeating_inventory_" + itemid + "_hasattack"] &&
+ v["repeating_inventory_" + itemid + "_hasattack"] == 1
+ ) {
+ var update = {};
+ update["repeating_inventory_" + itemid + "_itemattackid"] = "";
+ update["repeating_inventory_" + itemid + "_hasattack"] = 0;
+ setAttrs(update, { silent: true });
+ }
+ });
+ }
+ if (spellid && spelllvl) {
+ getAttrs(
+ ["repeating_spell-" + spelllvl + "_" + spellid + "_spelloutput"],
+ function (v) {
+ if (
+ v["repeating_spell-" + spelllvl + "_" + spellid + "_spelloutput"] &&
+ v["repeating_spell-" + spelllvl + "_" + spellid + "_spelloutput"] ==
+ "ATTACK"
+ ) {
+ var update = {};
+ update[
+ "repeating_spell-" + spelllvl + "_" + spellid + "_spellattackid"
+ ] = "";
+ update[
+ "repeating_spell-" + spelllvl + "_" + spellid + "_spelloutput"
+ ] = "SPELLCARD";
+ setAttrs(update, { silent: true });
+ }
+ }
+ );
+ }
+});
+
+on("remove:repeating_resource", function (eventinfo) {
+ const resourceid = getReprowid(eventinfo.sourceAttribute);
+ let update = {};
+
+ _.each(["left", "right"], (side) => {
+ const itemid =
+ eventinfo.removedInfo[
+ `repeating_resource_${resourceid}_resource_${side}_itemid`
+ ];
+ if (itemid) {
+ update[`repeating_inventory_${itemid}_useasresource`] = 0;
+ update[`repeating_inventory_${itemid}_itemresourceid`] = "";
+ }
+ });
+
+ setAttrs(update, { silent: true });
+});
+
+on(
+ "remove:repeating_spell-cantrip remove:repeating_spell-1 remove:repeating_spell-2 remove:repeating_spell-3 remove:repeating_spell-4 remove:repeating_spell-5 remove:repeating_spell-6 remove:repeating_spell-7 remove:repeating_spell-8 remove:repeating_spell-9",
+ function (eventinfo) {
+ var attackid =
+ eventinfo.removedInfo[eventinfo.sourceAttribute + "_spellattackid"];
+ if (attackid) {
+ remove_attack(attackid);
+ }
+ }
+);
+
+on("clicked:relaunch_lvl1mancer", function (eventinfo) {
+ getAttrs(["l1mancer_status"], function (v) {
+ if (v["l1mancer_status"] === "completed") {
+ setAttrs({ l1mancer_status: "relaunch" });
+ }
+ check_l1_mancer();
+ });
+});
+
+on("clicked:launch_lvl+mancer", function (eventinfo) {
+ getAttrs(
+ [
+ "class",
+ "level",
+ "hp_max",
+ "custom_class",
+ "multiclass1_flag",
+ "multiclass2_flag",
+ "multiclass3_flag",
+ "multiclass1",
+ "multiclass2",
+ "multiclass3",
+ ],
+ function (v) {
+ var throw_warning = false;
+ var class_array = [v["class"]];
+ if (
+ !v["class"] ||
+ !v["hp_max"] ||
+ isNaN(parseInt(v["hp_max"], 10)) ||
+ !v["level"] ||
+ isNaN(parseInt(v["level"], 10)) ||
+ parseInt(v["level"], 10) < 1 ||
+ (v["multiclass2_flag"] == 1 && v["multiclass1_flag"] == 0) ||
+ (v["multiclass3_flag"] == 1 && v["multiclass2_flag"] == 0)
+ ) {
+ throw_warning = true;
+ }
+
+ if (v["multiclass1_flag"] == 1) {
+ class_array.push(v["multiclass1"]);
+ }
+ if (v["multiclass2_flag"] == 1) {
+ class_array.push(v["multiclass2"]);
+ }
+ if (v["multiclass3_flag"] == 1) {
+ class_array.push(v["multiclass3"]);
+ }
+ // Check to see if there are any duplicate multiclasses
+ if (new Set(class_array).size !== class_array.length) {
+ throw_warning = true;
+ }
+
+ if (throw_warning === true) {
+ setAttrs({ leveler_warningflag: "show" });
+ return;
+ }
+
+ setAttrs({ lpmancer_status: "active" }, function () {
+ startCharactermancer("lp-welcome");
+ });
+ }
+ );
+});
+
+on("change:experience", function (eventinfo) {
+ update_leveler_display();
+});
+
+var update_attr = function (attr) {
+ var update = {};
+ var attr_fields = [attr + "_base", attr + "_bonus"];
+ getSectionIDs("repeating_inventory", function (idarray) {
+ _.each(idarray, function (currentID, i) {
+ attr_fields.push("repeating_inventory_" + currentID + "_equipped");
+ attr_fields.push("repeating_inventory_" + currentID + "_itemmodifiers");
+ });
+ getAttrs(attr_fields, function (v) {
+ var base =
+ v[attr + "_base"] && !isNaN(parseInt(v[attr + "_base"], 10))
+ ? parseInt(v[attr + "_base"], 10)
+ : 10;
+ var bonus =
+ v[attr + "_bonus"] && !isNaN(parseInt(v[attr + "_bonus"], 10))
+ ? parseInt(v[attr + "_bonus"], 10)
+ : 0;
+ var item_base = 0;
+ var item_bonus = 0;
+ _.each(idarray, function (currentID) {
+ if (
+ (!v["repeating_inventory_" + currentID + "_equipped"] ||
+ v["repeating_inventory_" + currentID + "_equipped"] === "1") &&
+ v["repeating_inventory_" + currentID + "_itemmodifiers"] &&
+ v["repeating_inventory_" + currentID + "_itemmodifiers"]
+ .toLowerCase()
+ .indexOf(attr > -1)
+ ) {
+ var mods = v["repeating_inventory_" + currentID + "_itemmodifiers"]
+ .toLowerCase()
+ .split(",");
+ _.each(mods, function (mod) {
+ if (mod.indexOf(attr) > -1 && mod.indexOf("save") === -1) {
+ if (mod.indexOf(":") > -1) {
+ var new_base = !isNaN(parseInt(mod.replace(/[^0-9]/g, ""), 10))
+ ? parseInt(mod.replace(/[^0-9]/g, ""), 10)
+ : false;
+ item_base =
+ new_base && new_base > item_base ? new_base : item_base;
+ } else if (mod.indexOf("-") > -1) {
+ var new_mod = !isNaN(parseInt(mod.replace(/[^0-9]/g, ""), 10))
+ ? parseInt(mod.replace(/[^0-9]/g, ""), 10)
+ : false;
+ item_bonus = new_mod ? item_bonus - new_mod : item_bonus;
+ } else {
+ var new_mod = !isNaN(parseInt(mod.replace(/[^0-9]/g, ""), 10))
+ ? parseInt(mod.replace(/[^0-9]/g, ""), 10)
+ : false;
+ item_bonus = new_mod ? item_bonus + new_mod : item_bonus;
+ }
+ }
+ });
+ }
+ });
+
+ update[attr + "_flag"] =
+ bonus > 0 || item_bonus > 0 || item_base > base ? 1 : 0;
+ base = base > item_base ? base : item_base;
+ update[attr] = base + bonus + item_bonus;
+ setAttrs(update);
+ });
+ });
+};
+
+var update_mod = function (attr) {
+ getAttrs([attr], function (v) {
+ var attr_abr = attr.substring(0, 3);
+ var finalattr =
+ v[attr] && isNaN(v[attr]) === false
+ ? Math.floor((parseInt(v[attr], 10) - 10) / 2)
+ : 0;
+ var update = {};
+ update[attr + "_mod"] = finalattr;
+ update["npc_" + attr_abr + "_negative"] =
+ v[attr] && !isNaN(v[attr]) && parseInt(v[attr], 10) < 10 ? 1 : 0;
+ setAttrs(update);
+ });
+};
+
+var update_save = function (attr) {
+ var save_attrs = [
+ attr + "_mod",
+ attr + "_save_prof",
+ attr + "_save_mod",
+ "pb",
+ "globalsavemod",
+ "pb_type",
+ ];
+ getSectionIDs("repeating_inventory", function (idarray) {
+ _.each(idarray, function (currentID, i) {
+ save_attrs.push("repeating_inventory_" + currentID + "_equipped");
+ save_attrs.push("repeating_inventory_" + currentID + "_itemmodifiers");
+ });
+
+ getAttrs(save_attrs, function (v) {
+ var attr_mod = v[attr + "_mod"] ? parseInt(v[attr + "_mod"], 10) : 0;
+ var prof =
+ v[attr + "_save_prof"] && v[attr + "_save_prof"] != 0 && !isNaN(v["pb"])
+ ? parseInt(v["pb"], 10)
+ : 0;
+ var save_mod =
+ v[attr + "_save_mod"] && !isNaN(parseInt(v[attr + "_save_mod"], 10))
+ ? parseInt(v[attr + "_save_mod"], 10)
+ : 0;
+ var global =
+ v["globalsavemod"] && !isNaN(v["globalsavemod"])
+ ? parseInt(v["globalsavemod"], 10)
+ : 0;
+ var items = 0;
+ _.each(idarray, function (currentID) {
+ if (
+ v["repeating_inventory_" + currentID + "_equipped"] &&
+ v["repeating_inventory_" + currentID + "_equipped"] === "1" &&
+ v["repeating_inventory_" + currentID + "_itemmodifiers"] &&
+ (v["repeating_inventory_" + currentID + "_itemmodifiers"]
+ .toLowerCase()
+ .indexOf("saving throws") > -1 ||
+ v["repeating_inventory_" + currentID + "_itemmodifiers"]
+ .toLowerCase()
+ .indexOf(attr + " save") > -1)
+ ) {
+ var mods = v["repeating_inventory_" + currentID + "_itemmodifiers"]
+ .toLowerCase()
+ .split(",");
+ _.each(mods, function (mod) {
+ if (mod.indexOf(attr + " save") > -1) {
+ var substr = mod.slice(
+ mod.lastIndexOf(attr + " save") + attr.length + " save".length
+ );
+ var bonus =
+ substr && substr.length > 0 && !isNaN(parseInt(substr, 10))
+ ? parseInt(substr, 10)
+ : 0;
+ } else if (mod.indexOf("saving throws") > -1) {
+ var substr = mod.slice(
+ mod.lastIndexOf("saving throws") + "saving throws".length
+ );
+ var bonus =
+ substr && substr.length > 0 && !isNaN(parseInt(substr, 10))
+ ? parseInt(substr, 10)
+ : 0;
+ }
+ if (bonus && bonus != 0) {
+ items = items + bonus;
+ }
+ });
+ }
+ });
+ var total = attr_mod + prof + save_mod + global + items;
+ if (
+ v["pb_type"] &&
+ v["pb_type"] === "die" &&
+ v[attr + "_save_prof"] != 0 &&
+ attr != "death"
+ ) {
+ total = total + "+" + v["pb"];
+ }
+ var update = {};
+ update[attr + "_save_bonus"] = total;
+ setAttrs(update, { silent: true }, () => {
+ updateSavingRoll(attr);
+ });
+ });
+ });
+};
+
+var update_all_saves = function () {
+ update_save("strength");
+ update_save("dexterity");
+ update_save("constitution");
+ update_save("intelligence");
+ update_save("wisdom");
+ update_save("charisma");
+ update_save("honor");
+ update_save("sanity");
+ update_save("death");
+};
+
+var update_all_ability_checks = function () {
+ update_initiative();
+ update_skills([
+ "athletics",
+ "acrobatics",
+ "sleight_of_hand",
+ "stealth",
+ "arcana",
+ "history",
+ "investigation",
+ "nature",
+ "religion",
+ "animal_handling",
+ "insight",
+ "medicine",
+ "perception",
+ "survival",
+ "deception",
+ "intimidation",
+ "performance",
+ "persuasion",
+ ]);
+};
+
+var update_skills = function (skills_array) {
+ var skill_parent = {
+ athletics: "strength",
+ acrobatics: "dexterity",
+ sleight_of_hand: "dexterity",
+ stealth: "dexterity",
+ arcana: "intelligence",
+ history: "intelligence",
+ investigation: "intelligence",
+ nature: "intelligence",
+ religion: "intelligence",
+ animal_handling: "wisdom",
+ insight: "wisdom",
+ medicine: "wisdom",
+ perception: "wisdom",
+ survival: "wisdom",
+ deception: "charisma",
+ intimidation: "charisma",
+ performance: "charisma",
+ persuasion: "charisma",
+ };
+ var attrs_to_get = ["pb", "pb_type", "jack_of_all_trades", "jack"];
+ var update = {};
+ var callbacks = [];
+
+ if (skills_array.indexOf("perception") > -1) {
+ callbacks.push(function () {
+ update_passive_perception();
+ });
+ }
+
+ _.each(skills_array, function (s) {
+ if (skill_parent[s] && attrs_to_get.indexOf(skill_parent[s]) === -1) {
+ attrs_to_get.push(skill_parent[s] + "_mod");
+ }
+ attrs_to_get.push(s + "_prof");
+ attrs_to_get.push(s + "_type");
+ attrs_to_get.push(s + "_flat");
+ });
+
+ getSectionIDs("repeating_inventory", function (idarray) {
+ _.each(idarray, function (currentID, i) {
+ attrs_to_get.push("repeating_inventory_" + currentID + "_equipped");
+ attrs_to_get.push("repeating_inventory_" + currentID + "_itemmodifiers");
+ });
+
+ getAttrs(attrs_to_get, function (v) {
+ _.each(skills_array, function (s) {
+ var attr_mod = v[skill_parent[s] + "_mod"]
+ ? parseInt(v[skill_parent[s] + "_mod"], 10)
+ : 0;
+ var prof =
+ v[s + "_prof"] != 0 && !isNaN(v["pb"]) ? parseInt(v["pb"], 10) : 0;
+ var flat =
+ v[s + "_flat"] && !isNaN(parseInt(v[s + "_flat"], 10))
+ ? parseInt(v[s + "_flat"], 10)
+ : 0;
+ var type =
+ v[s + "_type"] && !isNaN(parseInt(v[s + "_type"], 10))
+ ? parseInt(v[s + "_type"], 10)
+ : 1;
+ var jack =
+ v["jack_of_all_trades"] && v["jack_of_all_trades"] != 0 && v["jack"]
+ ? v["jack"]
+ : 0;
+ var item_bonus = 0;
+
+ _.each(idarray, function (currentID) {
+ if (
+ v["repeating_inventory_" + currentID + "_equipped"] &&
+ v["repeating_inventory_" + currentID + "_equipped"] === "1" &&
+ v["repeating_inventory_" + currentID + "_itemmodifiers"] &&
+ (v["repeating_inventory_" + currentID + "_itemmodifiers"]
+ .toLowerCase()
+ .replace(/ /g, "_")
+ .indexOf(s) > -1 ||
+ v["repeating_inventory_" + currentID + "_itemmodifiers"]
+ .toLowerCase()
+ .indexOf("ability checks") > -1)
+ ) {
+ var mods = v["repeating_inventory_" + currentID + "_itemmodifiers"]
+ .toLowerCase()
+ .split(",");
+ _.each(mods, function (mod) {
+ if (
+ mod.replace(/ /g, "_").indexOf(s) > -1 ||
+ mod.indexOf("ability checks") > -1
+ ) {
+ if (mod.indexOf("-") > -1) {
+ var new_mod = !isNaN(parseInt(mod.replace(/[^0-9]/g, ""), 10))
+ ? parseInt(mod.replace(/[^0-9]/g, ""), 10)
+ : false;
+ item_bonus = new_mod ? item_bonus - new_mod : item_bonus;
+ } else {
+ var new_mod = !isNaN(parseInt(mod.replace(/[^0-9]/g, ""), 10))
+ ? parseInt(mod.replace(/[^0-9]/g, ""), 10)
+ : false;
+ item_bonus = new_mod ? item_bonus + new_mod : item_bonus;
+ }
+ }
+ });
+ }
+ });
+
+ var total = attr_mod + flat + item_bonus;
+
+ if (v["pb_type"] && v["pb_type"] === "die") {
+ if (v[s + "_prof"] != 0) {
+ type === 1 ? "" : "2";
+ total = total + "+" + type + v["pb"];
+ } else if (v[s + "_prof"] == 0 && jack != 0) {
+ total = total + "+" + jack;
+ }
+ } else {
+ if (v[s + "_prof"] != 0) {
+ total = total + prof * type;
+ } else if (v[s + "_prof"] == 0 && jack != 0) {
+ total = total + parseInt(jack, 10);
+ }
+ }
+ update[s + "_bonus"] = total;
+ });
+
+ setAttrs(update, { silent: true }, function () {
+ callbacks.forEach(function (callback) {
+ callback();
+ });
+ updateSkillRolls(skills_array);
+ });
+ });
+ });
+};
+
+var update_tool = function (tool_id) {
+ //D&D 5e Mancer: Land Vehicles proficiency does not drop with Marine background (UC748)
+ //Added a test to check for an undefined tool_id so to prevent similar errors.
+ //By Miguel Peres
+ if (typeof tool_id == "undefined") return;
+
+ if (tool_id.substring(0, 1) === "-" && tool_id.length === 20) {
+ do_update_tool([tool_id]);
+ } else if (tool_id === "all") {
+ getSectionIDs("repeating_tool", function (idarray) {
+ do_update_tool(idarray);
+ });
+ } else {
+ getSectionIDs("repeating_tool", function (idarray) {
+ var tool_attribs = [];
+ _.each(idarray, function (id) {
+ tool_attribs.push("repeating_tool_" + id + "_toolattr_base");
+ });
+ getAttrs(tool_attribs, function (v) {
+ var attr_tool_ids = [];
+ _.each(idarray, function (id) {
+ if (
+ v["repeating_tool_" + id + "_toolattr_base"] &&
+ v["repeating_tool_" + id + "_toolattr_base"].indexOf(tool_id) > -1
+ ) {
+ attr_tool_ids.push(id);
+ }
+ });
+ if (attr_tool_ids.length > 0) {
+ do_update_tool(attr_tool_ids);
+ }
+ });
+ });
+ }
+};
+
+var do_update_tool = function (tool_array) {
+ var tool_attribs = [
+ "pb",
+ "pb_type",
+ "jack",
+ "strength_mod",
+ "dexterity_mod",
+ "constitution_mod",
+ "intelligence_mod",
+ "wisdom_mod",
+ "charisma_mod",
+ ];
+ var update = {};
+ _.each(tool_array, function (tool_id) {
+ tool_attribs.push("repeating_tool_" + tool_id + "_toolbonus_base");
+ tool_attribs.push("repeating_tool_" + tool_id + "_tool_mod");
+ tool_attribs.push("repeating_tool_" + tool_id + "_toolattr_base");
+ });
+
+ getAttrs(tool_attribs, function (v) {
+ _.each(tool_array, function (tool_id) {
+ var query = false;
+ if (
+ v["repeating_tool_" + tool_id + "_toolattr_base"] &&
+ v["repeating_tool_" + tool_id + "_toolattr_base"].substring(0, 2) ===
+ "?{"
+ ) {
+ update["repeating_tool_" + tool_id + "_toolattr"] = "QUERY";
+ var mod =
+ "?{Attribute?|Strength,@{strength_mod}|Dexterity,@{dexterity_mod}|Constitution,@{constitution_mod}|Intelligence,@{intelligence_mod}|Wisdom,@{wisdom_mod}|Charisma,@{charisma_mod}}";
+ if (v["repeating_tool_" + tool_id + "_tool_mod"]) {
+ mod = mod + "+" + v["repeating_tool_" + tool_id + "_tool_mod"];
+ }
+ query = true;
+ } else {
+ var attr = v["repeating_tool_" + tool_id + "_toolattr_base"]
+ .substring(
+ 0,
+ v["repeating_tool_" + tool_id + "_toolattr_base"].length - 5
+ )
+ .substr(2);
+ var attr_mod = v[attr + "_mod"] ? parseInt(v[attr + "_mod"], 10) : 0;
+ var tool_mod =
+ v["repeating_tool_" + tool_id + "_tool_mod"] &&
+ !isNaN(parseInt(v["repeating_tool_" + tool_id + "_tool_mod"], 10))
+ ? parseInt(v["repeating_tool_" + tool_id + "_tool_mod"], 10)
+ : 0;
+ var mod = attr_mod + tool_mod;
+ update["repeating_tool_" + tool_id + "_toolattr"] = attr.toUpperCase();
+ if (
+ v["repeating_tool_" + tool_id + "_tool_mod"] &&
+ v["repeating_tool_" + tool_id + "_tool_mod"].indexOf("@{") > -1
+ ) {
+ update["repeating_tool_" + tool_id + "_toolbonus"] =
+ update["repeating_tool_" + tool_id + "_toolbonus"] +
+ "+" +
+ v["repeating_tool_" + tool_id + "_tool_mod"];
+ }
+ if (!v["repeating_tool_" + tool_id + "_tool_mod"]) {
+ update["repeating_tool_" + tool_id + "_tool_mod"] = 0;
+ }
+ }
+
+ if (v["pb_type"] && v["pb_type"] === "die") {
+ if (v["repeating_tool_" + tool_id + "_toolbonus_base"] === "(@{pb})") {
+ update["repeating_tool_" + tool_id + "_toolbonus"] = mod + "+" + v.pb;
+ } else if (
+ v["repeating_tool_" + tool_id + "_toolbonus_base"] === "(@{pb}*2)"
+ ) {
+ update["repeating_tool_" + tool_id + "_toolbonus"] =
+ mod + "+2" + v.pb;
+ } else if (
+ v["repeating_tool_" + tool_id + "_toolbonus_base"] ===
+ "(floor(@{pb}/2))"
+ ) {
+ update["repeating_tool_" + tool_id + "_toolbonus"] =
+ mod + "+" + v.jack;
+ }
+ } else if (
+ v["repeating_tool_" + tool_id + "_toolattr_base"] &&
+ v["repeating_tool_" + tool_id + "_toolattr_base"].substring(0, 2) ===
+ "?{"
+ ) {
+ if (v["repeating_tool_" + tool_id + "_toolbonus_base"] === "(@{pb})") {
+ update["repeating_tool_" + tool_id + "_toolbonus"] =
+ mod + "+" + parseInt(v.pb, 10);
+ } else if (
+ v["repeating_tool_" + tool_id + "_toolbonus_base"] === "(@{pb}*2)"
+ ) {
+ update["repeating_tool_" + tool_id + "_toolbonus"] =
+ mod + "+" + parseInt(v.pb, 10) * 2;
+ } else if (
+ v["repeating_tool_" + tool_id + "_toolbonus_base"] ===
+ "(floor(@{pb}/2))"
+ ) {
+ update["repeating_tool_" + tool_id + "_toolbonus"] =
+ mod + "+" + parseInt(v.jack, 10);
+ }
+ } else {
+ if (v["repeating_tool_" + tool_id + "_toolbonus_base"] === "(@{pb})") {
+ update["repeating_tool_" + tool_id + "_toolbonus"] =
+ mod + parseInt(v.pb, 10);
+ } else if (
+ v["repeating_tool_" + tool_id + "_toolbonus_base"] === "(@{pb}*2)"
+ ) {
+ update["repeating_tool_" + tool_id + "_toolbonus"] =
+ mod + parseInt(v.pb, 10) * 2;
+ } else if (
+ v["repeating_tool_" + tool_id + "_toolbonus_base"] ===
+ "(floor(@{pb}/2))"
+ ) {
+ update["repeating_tool_" + tool_id + "_toolbonus"] =
+ mod + parseInt(v.jack, 10);
+ }
+ }
+
+ if (query) {
+ update["repeating_tool_" + tool_id + "_toolbonus_display"] = "?";
+ } else {
+ update["repeating_tool_" + tool_id + "_toolbonus_display"] =
+ update["repeating_tool_" + tool_id + "_toolbonus"];
+ }
+ });
+
+ setAttrs(update, { silent: true }, () => {
+ updateToolRolls(tool_array);
+ });
+ });
+};
+
+var get_repeating_data = function (callback) {
+ var getallrepeating = function (getobj, thiscallback, attrlist) {
+ attrlist = attrlist || [];
+ var thisget = getobj.pop();
+ getSectionIDs(thisget.name, function (ids) {
+ _.each(ids, function (sectionId) {
+ _.each(thisget.list, function (attr) {
+ attrlist.push(
+ "repeating_" + thisget.name + "_" + sectionId + "_" + attr
+ );
+ });
+ });
+ if (getobj.length > 0) {
+ getallrepeating(getobj, thiscallback, attrlist);
+ } else {
+ getAttrs(attrlist, function (vals) {
+ thiscallback(vals);
+ });
+ }
+ });
+ };
+ var getList = [
+ { name: "proficiencies", list: ["name"] },
+ { name: "tool", list: ["toolname", "toolattr_base"] },
+ { name: "traits", list: ["name", "source", "source_type"] },
+ { name: "resource", list: ["resource_left_name", "resource_right_name"] },
+ {
+ name: "spell-cantrip",
+ list: [
+ "spellname",
+ "spellattackid",
+ "spellsource",
+ "innate",
+ "spellattackid",
+ ],
+ },
+ { name: "savemod", list: ["global_save_name"] },
+ { name: "tohitmod", list: ["global_attack_name"] },
+ { name: "damagemod", list: ["global_damage_name"] },
+ { name: "acmod", list: ["global_ac_name"] },
+ { name: "skillmod", list: ["global_skill_name"] },
+ { name: "attack", list: ["atkname", "spellid"] },
+ { name: "hpmod", list: ["levels", "source", "mod"] },
+ ];
+ for (var x = 1; x <= 9; x++) {
+ getList.push({
+ name: "spell-" + x,
+ list: [
+ "spellname",
+ "spellattackid",
+ "spellsource",
+ "innate",
+ "spellattackid",
+ ],
+ });
+ }
+ var repeating = { prof_names: [], traits: [] };
+ _.each(getList, function (section) {
+ if (!["proficiencies", "traits"].includes(section.name)) {
+ repeating[section.name] = {};
+ }
+ });
+ getallrepeating(getList, function (vals) {
+ var traitstemp = {};
+ _.each(vals, function (value, name) {
+ if (name.split("_")[1] == "proficiencies") {
+ repeating.prof_names.push(value.toLowerCase());
+ } else if (name.split("_")[1] == "tool") {
+ repeating.tool[name.split("_")[2]] =
+ repeating.tool[name.split("_")[2]] || {};
+ let attr = _.last(name.split("_"));
+ repeating.tool[name.split("_")[2]][attr] = value.toLowerCase();
+ if (attr == "toolname") repeating.prof_names.push(value.toLowerCase());
+ } else if (name.split("_")[1] == "traits") {
+ traitstemp[name.split("_")[2]] = traitstemp[name.split("_")[2]]
+ ? traitstemp[name.split("_")[2]]
+ : {};
+ traitstemp[name.split("_")[2]][_.last(name.split("_"))] = value;
+ } else if (name.split("_")[1] == "resource") {
+ repeating.resource[name.split("_")[2]] =
+ repeating.resource[name.split("_")[2]] || {};
+ repeating.resource[name.split("_")[2]][name.split("_")[4]] = value;
+ } else if (name.split("_")[1] == "hpmod") {
+ repeating.hpmod[name.split("_")[2]] =
+ repeating.hpmod[name.split("_")[2]] || {};
+ repeating.hpmod[name.split("_")[2]][name.split("_")[3]] = value;
+ } else if (name.split("_")[1].split("-")[0] == "spell") {
+ repeating[name.split("_")[1]][name.split("_")[2]] =
+ repeating[name.split("_")[1]][name.split("_")[2]] || {};
+ repeating[name.split("_")[1]][name.split("_")[2]][name.split("_")[3]] =
+ value;
+ } else if (name.split("_")[1] == "attack") {
+ repeating[name.split("_")[1]][name.split("_")[2]] =
+ repeating[name.split("_")[1]][name.split("_")[2]] || {};
+ repeating[name.split("_")[1]][name.split("_")[2]][name.split("_")[3]] =
+ value;
+ } else {
+ repeating[name.split("_")[1]][name.split("_")[2]] = value;
+ }
+ });
+ _.each(traitstemp, function (v, k) {
+ var trait = _.clone(v);
+ trait.id = k;
+ repeating.traits.push(trait);
+ });
+ callback(repeating);
+ });
+};
+
+var check_itemmodifiers = function (modifiers, previousValue) {
+ var mods = modifiers.toLowerCase().split(",");
+ if (previousValue) {
+ prevmods = previousValue.toLowerCase().split(",");
+ mods = _.union(mods, prevmods);
+ }
+ _.each(mods, function (mod) {
+ if (
+ mod.indexOf("ac:") > -1 ||
+ mod.indexOf("ac +") > -1 ||
+ mod.indexOf("ac -") > -1
+ ) {
+ update_ac();
+ }
+ if (mod.indexOf("spell") > -1) {
+ update_spell_info();
+ }
+ if (mod.indexOf("saving throws") > -1) {
+ update_all_saves();
+ }
+ if (mod.indexOf("strength save") > -1) {
+ update_save("strength");
+ } else if (mod.indexOf("strength") > -1) {
+ update_attr("strength");
+ }
+ if (mod.indexOf("dexterity save") > -1) {
+ update_save("dexterity");
+ } else if (mod.indexOf("dexterity") > -1) {
+ update_attr("dexterity");
+ }
+ if (mod.indexOf("constitution save") > -1) {
+ update_save("constitution");
+ } else if (mod.indexOf("constitution") > -1) {
+ update_attr("constitution");
+ }
+ if (mod.indexOf("intelligence save") > -1) {
+ update_save("intelligence");
+ } else if (mod.indexOf("intelligence") > -1) {
+ update_attr("intelligence");
+ }
+ if (mod.indexOf("wisdom save") > -1) {
+ update_save("wisdom");
+ } else if (mod.indexOf("wisdom") > -1) {
+ update_attr("wisdom");
+ }
+ if (mod.indexOf("charisma save") > -1) {
+ update_save("charisma");
+ } else if (mod.indexOf("charisma") > -1) {
+ update_attr("charisma");
+ }
+ if (mod.indexOf("honor save") > -1) {
+ update_save("honor");
+ } else if (mod.indexOf("honor") > -1) {
+ update_attr("honor");
+ }
+ if (mod.indexOf("sanity save") > -1) {
+ update_save("sanity");
+ } else if (mod.indexOf("sanity") > -1) {
+ update_attr("sanity");
+ }
+ if (mod.indexOf("ability checks") > -1) {
+ update_all_ability_checks();
+ }
+ if (mod.indexOf("acrobatics") > -1) {
+ update_skills(["acrobatics"]);
+ }
+ if (mod.indexOf("animal handling") > -1) {
+ update_skills(["animal_handling"]);
+ }
+ if (mod.indexOf("arcana") > -1) {
+ update_skills(["arcana"]);
+ }
+ if (mod.indexOf("athletics") > -1) {
+ update_skills(["athletics"]);
+ }
+ if (mod.indexOf("deception") > -1) {
+ update_skills(["deception"]);
+ }
+ if (mod.indexOf("history") > -1) {
+ update_skills(["history"]);
+ }
+ if (mod.indexOf("insight") > -1) {
+ update_skills(["insight"]);
+ }
+ if (mod.indexOf("intimidation") > -1) {
+ update_skills(["intimidation"]);
+ }
+ if (mod.indexOf("investigation") > -1) {
+ update_skills(["investigation"]);
+ }
+ if (mod.indexOf("medicine") > -1) {
+ update_skills(["medicine"]);
+ }
+ if (mod.indexOf("nature") > -1) {
+ update_skills(["nature"]);
+ }
+ if (mod.indexOf("perception") > -1) {
+ update_skills(["perception"]);
+ }
+ if (mod.indexOf("performance") > -1) {
+ update_skills(["performance"]);
+ }
+ if (mod.indexOf("persuasion") > -1) {
+ update_skills(["persuasion"]);
+ }
+ if (mod.indexOf("religion") > -1) {
+ update_skills(["religion"]);
+ }
+ if (mod.indexOf("sleight of hand") > -1) {
+ update_skills(["sleight_of_hand"]);
+ }
+ if (mod.indexOf("stealth") > -1) {
+ update_skills(["stealth"]);
+ }
+ if (mod.indexOf("survival") > -1) {
+ update_skills(["survival"]);
+ }
+ });
+};
+
+var create_attack_from_item = function (itemid, options) {
+ var update = {};
+ var newrowid = generateRowID();
+ update["repeating_inventory_" + itemid + "_itemattackid"] = newrowid;
+ if (options && options.versatile) {
+ var newrowid2 = generateRowID();
+ update["repeating_inventory_" + itemid + "_itemattackid"] +=
+ "," + newrowid2;
+ setAttrs(update, {}, function () {
+ update_attack_from_item(itemid, newrowid, {
+ newattack: true,
+ versatile: "primary",
+ });
+ update_attack_from_item(itemid, newrowid2, {
+ newattack: true,
+ versatile: "secondary",
+ });
+ });
+ } else {
+ setAttrs(
+ update,
+ {},
+ update_attack_from_item(itemid, newrowid, { newattack: true })
+ );
+ }
+};
+
+var update_attack_from_item = function (itemid, attackid, options) {
+ getAttrs(
+ [
+ "repeating_inventory_" + itemid + "_itemname",
+ "repeating_inventory_" + itemid + "_itemproperties",
+ "repeating_inventory_" + itemid + "_itemmodifiers",
+ "strength",
+ "dexterity",
+ "class",
+ "multiclass1",
+ "multiclass2",
+ "multiclass3",
+ ],
+ function (v) {
+ var update = {};
+ var itemtype;
+ var damage;
+ var damagetype;
+ var damage2;
+ var damagetype2;
+ var attackmod;
+ var damagemod;
+ var range;
+ var atkcritrange;
+ var alt = {};
+
+ if (options && options.newattack) {
+ update["repeating_attack_" + attackid + "_options-flag"] = "0";
+ update["repeating_attack_" + attackid + "_itemid"] = itemid;
+ }
+
+ const isMonk = () => {
+ let monk = false;
+ ["class", "multiclass1", "multiclass2", "multiclass3"].forEach(
+ (entry) => {
+ if (v[entry] && v[entry] === "Monk") monk = true;
+ }
+ );
+ return monk;
+ };
+
+ const isMonkWeapon = (weapon) => {
+ const monkWeapons = [
+ "club",
+ "dagger",
+ "dart",
+ "dorata",
+ "greatclub",
+ "handaxe",
+ "javelin",
+ "light crossbow",
+ "light hammer",
+ "mace",
+ "quarterstaff",
+ "shortbow",
+ "sickle",
+ "sling",
+ "spear",
+ "shortsword",
+ ];
+ return monkWeapons.indexOf(weapon.toLowerCase().trim()) > -1;
+ };
+
+ if (
+ v["repeating_inventory_" + itemid + "_itemmodifiers"] &&
+ v["repeating_inventory_" + itemid + "_itemmodifiers"] != ""
+ ) {
+ var mods =
+ v["repeating_inventory_" + itemid + "_itemmodifiers"].split(",");
+ _.each(mods, function (mod) {
+ if (mod.indexOf("Item Type:") > -1) {
+ itemtype = mod.split(":")[1].trim();
+ } else if (mod.indexOf("Alternate Secondary Damage Type:") > -1) {
+ alt.damagetype2 = mod.split(":")[1].trim();
+ } else if (mod.indexOf("Alternate Secondary Damage:") > -1) {
+ alt.damage2 = mod.split(":")[1].trim();
+ } else if (mod.indexOf("Alternate Damage Type:") > -1) {
+ alt.damagetype = mod.split(":")[1].trim();
+ } else if (mod.indexOf("Alternate Damage:") > -1) {
+ alt.damage = mod.split(":")[1].trim();
+ } else if (mod.indexOf("Secondary Damage Type:") > -1) {
+ damagetype2 = mod.split(":")[1].trim();
+ } else if (mod.indexOf("Secondary Damage:") > -1) {
+ damage2 = mod.split(":")[1].trim();
+ } else if (mod.indexOf("Damage Type:") > -1) {
+ damagetype = mod.split(":")[1].trim();
+ } else if (mod.indexOf("Damage:") > -1) {
+ damage = mod.split(":")[1].trim();
+ } else if (mod.indexOf("Critical Range:") > -1) {
+ atkcritrange = mod.split(":")[1].trim();
+ } else if (mod.indexOf("Range:") > -1) {
+ range = mod.split(":")[1].trim();
+ } else if (mod.indexOf(" Attacks ") > -1) {
+ attackmod = mod.split(" Attacks ")[1].trim();
+ } else if (mod.indexOf(" Damage ") > -1) {
+ damagemod = mod.split(" Damage ")[1].trim();
+ }
+ });
+ }
+
+ if (
+ v["repeating_inventory_" + itemid + "_itemname"] &&
+ v["repeating_inventory_" + itemid + "_itemname"] != ""
+ ) {
+ update["repeating_attack_" + attackid + "_atkname"] =
+ v["repeating_inventory_" + itemid + "_itemname"];
+ if (options && options.versatile === "primary") {
+ update["repeating_attack_" + attackid + "_atkname"] +=
+ " (One-Handed)";
+ } else if (options && options.versatile === "secondary") {
+ update["repeating_attack_" + attackid + "_atkname"] +=
+ " (Two-Handed)";
+ }
+ }
+ if (options && options.versatile === "secondary") {
+ if (alt.damage) {
+ update["repeating_attack_" + attackid + "_dmgbase"] = alt.damage;
+ }
+ if (alt.damagetype) {
+ update["repeating_attack_" + attackid + "_dmgtype"] = alt.damagetype;
+ }
+ if (alt.damage2) {
+ update["repeating_attack_" + attackid + "_dmg2base"] = alt.damage2;
+ update["repeating_attack_" + attackid + "_dmg2attr"] = 0;
+ update["repeating_attack_" + attackid + "_dmg2flag"] =
+ "{{damage=1}} {{dmg2flag=1}}";
+ }
+ if (alt.damagetype2) {
+ update["repeating_attack_" + attackid + "_dmg2type"] =
+ alt.damagetype2;
+ }
+ update["repeating_attack_" + attackid + "_versatile_alt"] = "1";
+ } else {
+ if (damage) {
+ update["repeating_attack_" + attackid + "_dmgbase"] = damage;
+ }
+ if (damagetype) {
+ update["repeating_attack_" + attackid + "_dmgtype"] = damagetype;
+ }
+ if (damage2) {
+ update["repeating_attack_" + attackid + "_dmg2base"] = damage2;
+ update["repeating_attack_" + attackid + "_dmg2attr"] = 0;
+ update["repeating_attack_" + attackid + "_dmg2flag"] =
+ "{{damage=1}} {{dmg2flag=1}}";
+ }
+ if (damagetype2) {
+ update["repeating_attack_" + attackid + "_dmg2type"] = damagetype2;
+ }
+ }
+ if (atkcritrange) {
+ update["repeating_attack_" + attackid + "_atkcritrange"] = atkcritrange;
+ }
+ if (range) {
+ update["repeating_attack_" + attackid + "_atkrange"] = range;
+ }
+ const monkWeapon =
+ isMonk() &&
+ isMonkWeapon(v["repeating_inventory_" + itemid + "_itemname"]);
+ var finesse =
+ v["repeating_inventory_" + itemid + "_itemproperties"] &&
+ /finesse/i.test(v["repeating_inventory_" + itemid + "_itemproperties"]);
+ if (
+ (itemtype && itemtype.indexOf("Ranged") > -1) ||
+ ((finesse || monkWeapon) && +v.dexterity > +v.strength)
+ ) {
+ update["repeating_attack_" + attackid + "_atkattr_base"] =
+ "@{dexterity_mod}";
+ update["repeating_attack_" + attackid + "_dmgattr"] =
+ "@{dexterity_mod}";
+ } else {
+ update["repeating_attack_" + attackid + "_atkattr_base"] =
+ "@{strength_mod}";
+ update["repeating_attack_" + attackid + "_dmgattr"] = "@{strength_mod}";
+ }
+ if (attackmod && damagemod && attackmod == damagemod) {
+ update["repeating_attack_" + attackid + "_atkmagic"] = parseInt(
+ attackmod,
+ 10
+ );
+ update["repeating_attack_" + attackid + "_atkmod"] = "";
+ update["repeating_attack_" + attackid + "_dmgmod"] = "";
+ } else {
+ if (attackmod) {
+ update["repeating_attack_" + attackid + "_atkmod"] = parseInt(
+ attackmod,
+ 10
+ );
+ }
+ if (damagemod) {
+ update["repeating_attack_" + attackid + "_dmgmod"] = parseInt(
+ damagemod,
+ 10
+ );
+ }
+ update["repeating_attack_" + attackid + "_atkmagic"] = "";
+ }
+ var callback = function () {
+ update_attacks(attackid, "item");
+ };
+ setAttrs(update, { silent: true }, callback);
+ }
+ );
+};
+
+const create_resource_from_item = (itemid) => {
+ const newrowid = generateRowID();
+ let update = {};
+
+ getAttrs(["other_resource_name"], (v) => {
+ //Use other_resource if it is empty
+ if (!v.other_resource_name || v.other_resource_name == "") {
+ update[`repeating_inventory_${itemid}_itemresourceid`] = "other_resource";
+ setAttrs(
+ update,
+ {},
+ update_resource_from_item(itemid, "other_resource", true)
+ );
+ //If other_resource is populated look through the repeating sections for an empty spot
+ } else {
+ getSectionIDs(`repeating_resource`, (idarray) => {
+ if (idarray.length == 0) {
+ update[
+ `repeating_inventory_${itemid}_itemresourceid`
+ ] = `${newrowid}_resource_left`;
+ setAttrs(
+ update,
+ {},
+ update_resource_from_item(itemid, `${newrowid}_resource_left`, true)
+ );
+ } else {
+ let array = [];
+ _.each(idarray, (currentID, i) => {
+ ["left", "right"].forEach((side) => {
+ array.push(`repeating_resource_${currentID}_resource_${side}`);
+ array.push(
+ `repeating_resource_${currentID}_resource_${side}_name`
+ );
+ array.push(
+ `repeating_resource_${currentID}_resource_${side}_max`
+ );
+ });
+ });
+ getAttrs(array, (y) => {
+ let existing = false;
+ _.each(idarray, (currentID, i) => {
+ ["left", "right"].forEach((side) => {
+ const Name =
+ y[`repeating_resource_${currentID}_resource_${side}_name`] ||
+ false;
+ const Value =
+ y[`repeating_resource_${currentID}_resource_${side}`] ||
+ false;
+ const Max =
+ y[`repeating_resource_${currentID}_resource_${side}_max`] ||
+ false;
+
+ //If Name, Value, & Max are empty and existing === false then populate a resource there
+ if (!Name && !Value && !Max && existing === false) {
+ update[
+ `repeating_inventory_${itemid}_itemresourceid`
+ ] = `${currentID}_resource_${side}`;
+ setAttrs(
+ update,
+ {},
+ update_resource_from_item(
+ itemid,
+ `${currentID}_resource_${side}`,
+ true
+ )
+ );
+ existing = true;
+ }
+ });
+ });
+ //If nothing is empty then generatae a new row
+ if (!existing) {
+ update[
+ `repeating_inventory_${itemid}_itemresourceid`
+ ] = `${newrowid}_resource_left`;
+ setAttrs(
+ update,
+ {},
+ update_resource_from_item(
+ itemid,
+ `${newrowid}_resource_left`,
+ true
+ )
+ );
+ }
+ });
+ }
+ });
+ }
+ });
+};
+
+var update_resource_from_item = function (itemid, resourceid, newresource) {
+ getAttrs(
+ [
+ "repeating_inventory_" + itemid + "_itemname",
+ "repeating_inventory_" + itemid + "_itemcount",
+ ],
+ function (v) {
+ var update = {};
+ var id;
+
+ if (resourceid && resourceid == "other_resource") {
+ id = resourceid;
+ } else {
+ id = "repeating_resource_" + resourceid;
+ }
+
+ if (newresource) {
+ update[id + "_itemid"] = itemid;
+ }
+
+ if (!v["repeating_inventory_" + itemid + "_itemname"]) {
+ update["repeating_inventory_" + itemid + "_useasresource"] = 0;
+ update["repeating_inventory_" + itemid + "_itemresourceid"] = "";
+ remove_resource(resourceid);
+ }
+ if (
+ v["repeating_inventory_" + itemid + "_itemname"] &&
+ v["repeating_inventory_" + itemid + "_itemname"] != ""
+ ) {
+ update[id + "_name"] = v["repeating_inventory_" + itemid + "_itemname"];
+ }
+ if (
+ v["repeating_inventory_" + itemid + "_itemcount"] &&
+ v["repeating_inventory_" + itemid + "_itemcount"] != ""
+ ) {
+ update[id] = v["repeating_inventory_" + itemid + "_itemcount"];
+ }
+
+ setAttrs(update, { silent: true });
+ }
+ );
+};
+
+const create_attack_from_spell = function (
+ lvl,
+ spellid,
+ character_id,
+ existing_id
+) {
+ let update = {};
+ const newrowid = existing_id ? existing_id : generateRowID();
+ update[`repeating_spell-${lvl}_${spellid}_spellattackid`] = newrowid;
+ update[
+ `repeating_spell-${lvl}_${spellid}_rollcontent`
+ ] = `%{${character_id}|repeating_attack_${newrowid}_attack}`;
+ setAttrs(
+ update,
+ {},
+ update_attack_from_spell(lvl, spellid, newrowid, true, character_id)
+ );
+};
+
+const update_attack_from_spell = (
+ lvl,
+ spellid,
+ attackid,
+ newattack,
+ character_id
+) => {
+ const repeating_spell = `repeating_spell-${lvl}_${spellid}`;
+ const repeating_attack = `repeating_attack_${attackid}`;
+ getAttrs(
+ [
+ `${repeating_spell}_spellname`,
+ `${repeating_spell}_spellrange`,
+ `${repeating_spell}_spelltarget`,
+ `${repeating_spell}_spellattack`,
+ `${repeating_spell}_spelldamage`,
+ `${repeating_spell}_spelldamage2`,
+ `${repeating_spell}_spelldamagetype`,
+ `${repeating_spell}_spelldamagetype2`,
+ `${repeating_spell}_spellhealing`,
+ `${repeating_spell}_spelldmgmod`,
+ `${repeating_spell}_spellsave`,
+ `${repeating_spell}_spellsavesuccess`,
+ `${repeating_spell}_spellhldie`,
+ `${repeating_spell}_spellhldietype`,
+ `${repeating_spell}_spellhlbonus`,
+ `${repeating_spell}_spelllevel`,
+ `${repeating_spell}_includedesc`,
+ `${repeating_spell}_spelldescription`,
+ `${repeating_spell}_spellathigherlevels`,
+ `${repeating_spell}_spell_damage_progression`,
+ `${repeating_spell}_innate`,
+ `${repeating_spell}_spell_ability`,
+ "spellcasting_ability",
+ ],
+ (v) => {
+ let update = {};
+ let description = "";
+ const spellAbility =
+ v[`${repeating_spell}_spell_ability`] != "spell"
+ ? v[`${repeating_spell}_spell_ability`].slice(0, -1)
+ : "spell";
+ update[`${repeating_attack}_atkattr_base`] = spellAbility;
+
+ if (newattack) {
+ update[`${repeating_attack}_options-flag`] = "0";
+ update[`${repeating_attack}_spellid`] = spellid;
+ update[`${repeating_attack}_spelllevel`] = lvl;
+ }
+
+ if (v[`${repeating_spell}_spell_ability`] == "spell") {
+ update[`${repeating_attack}_savedc`] = "(@{spell_save_dc})";
+ } else if (v[`${repeating_spell}_spell_ability`]) {
+ update[
+ `${repeating_attack}_savedc`
+ ] = `(${spellAbility}+8+@{spell_dc_mod}+@{pb})`;
+ }
+
+ if (
+ v[`${repeating_spell}_spellname`] &&
+ v[`${repeating_spell}_spellname`] != ""
+ ) {
+ update[`${repeating_attack}_atkname`] =
+ v[`${repeating_spell}_spellname`];
+ }
+
+ update[`${repeating_attack}_atkflag`] =
+ !v[`${repeating_spell}_spellattack`] ||
+ v[`${repeating_spell}_spellattack`] === "None"
+ ? "0"
+ : "{{attack=1}}";
+
+ if (
+ v[`${repeating_spell}_spellattack`] ||
+ !v[`${repeating_spell}_spellattack`] === "None"
+ ) {
+ description =
+ description + v[`${repeating_spell}_spellattack`] + " Spell Attack. ";
+ }
+
+ if (
+ v[`${repeating_spell}_spelldamage`] &&
+ v[`${repeating_spell}_spelldamage`] != ""
+ ) {
+ update[`${repeating_attack}_dmgbase`] =
+ v[`${repeating_spell}_spell_damage_progression`] &&
+ v[`${repeating_spell}_spell_damage_progression`] === "Cantrip Dice"
+ ? "[[round((@{level} + 1) / 6 + 0.5)]]" +
+ v[`${repeating_spell}_spelldamage`].substring(1)
+ : v[`${repeating_spell}_spelldamage`];
+ }
+
+ update[`${repeating_attack}_dmgflag`] =
+ v[`${repeating_spell}_spelldamage`] &&
+ v[`${repeating_spell}_spelldamage`] != ""
+ ? "{{damage=1}} {{dmg1flag=1}}"
+ : "0";
+ update[`${repeating_attack}_dmgattr`] =
+ v[`${repeating_spell}_spelldmgmod`] &&
+ v[`${repeating_spell}_spelldmgmod`] === "Yes"
+ ? spellAbility
+ : "0";
+ update[`${repeating_attack}_dmgtype`] = v[
+ `${repeating_spell}_spelldamagetype`
+ ]
+ ? v[`${repeating_spell}_spelldamagetype`]
+ : "";
+ update[`${repeating_attack}_dmg2base`] = v[
+ `${repeating_spell}_spelldamage2`
+ ]
+ ? v[`${repeating_spell}_spelldamage2`]
+ : "";
+ update[`${repeating_attack}_dmg2attr`] = "0";
+ update[`${repeating_attack}_dmg2flag`] = v[
+ `${repeating_spell}_spelldamage2`
+ ]
+ ? "{{damage=1}} {{dmg2flag=1}}"
+ : 0;
+ update[`${repeating_attack}_dmg2type`] = v[
+ `${repeating_spell}_spelldamagetype2`
+ ]
+ ? v[`${repeating_spell}_spelldamagetype2`]
+ : "";
+ update[`${repeating_attack}_atkrange`] = v[
+ `${repeating_spell}_spellrange`
+ ]
+ ? v[`${repeating_spell}_spellrange`]
+ : "";
+ update[`${repeating_attack}_saveflag`] = v[`${repeating_spell}_spellsave`]
+ ? "{{save=1}} {{saveattr=@{saveattr}}} {{savedesc=@{saveeffect}}} {{savedc=[[[[@{savedc}]][SAVE]]]}}"
+ : "0";
+ update[`${repeating_attack}_saveeffect`] = v[
+ `${repeating_spell}_spellsavesuccess`
+ ]
+ ? v[`${repeating_spell}_spellsavesuccess`]
+ : "";
+
+ if (v[`${repeating_spell}_spellsave`]) {
+ update[`${repeating_attack}_saveattr`] =
+ v[`${repeating_spell}_spellsave`];
+ }
+
+ if (
+ v[`${repeating_spell}_spellhldie`] &&
+ v[`${repeating_spell}_spellhldie`] != "" &&
+ v[`${repeating_spell}_spellhldietype`] &&
+ v[`${repeating_spell}_spellhldietype`] != ""
+ ) {
+ let bonus = "";
+ const spelllevel = v[`${repeating_spell}_spelllevel`];
+ let query = "?{Cast at what level?";
+ for (i = 0; i < 10 - spelllevel; i++) {
+ query =
+ query +
+ "|Level " +
+ (parseInt(i, 10) + parseInt(spelllevel, 10)) +
+ "," +
+ i;
+ }
+ query = query + "}";
+ if (
+ v[`${repeating_spell}_spellhlbonus`] &&
+ v[`${repeating_spell}_spellhlbonus`] != ""
+ ) {
+ bonus =
+ "+(" + v[`${repeating_spell}_spellhlbonus`] + "*" + query + ")";
+ }
+ update[`${repeating_attack}_hldmg`] = `{{hldmg=[[(${
+ v[`${repeating_spell}_spellhldie`]
+ }*${query})${v[`${repeating_spell}_spellhldietype`]}${bonus}]]}}`;
+ } else {
+ update[`${repeating_attack}_hldmg`] = "";
+ }
+
+ if (
+ v[`${repeating_spell}_spellhealing`] &&
+ v[`${repeating_spell}_spellhealing`] != ""
+ ) {
+ if (
+ !v[`${repeating_spell}_spelldamage`] ||
+ v[`${repeating_spell}_spelldamage`] === ""
+ ) {
+ update[`${repeating_attack}_dmgbase`] =
+ v[`${repeating_spell}_spellhealing`];
+ update[`${repeating_attack}_dmgflag`] = "{{damage=1}} {{dmg1flag=1}}";
+ update[`${repeating_attack}_dmgtype`] = "Healing";
+ } else if (
+ !v[`${repeating_spell}_spelldamage2`] ||
+ v[`${repeating_spell}_spelldamage2`] === ""
+ ) {
+ update[`${repeating_attack}_dmg2base`] =
+ v[`${repeating_spell}_spellhealing`];
+ update[`${repeating_attack}_dmg2flag`] =
+ "{{damage=1}} {{dmg2flag=1}}";
+ update[`${repeating_attack}_dmg2type`] = "Healing";
+ }
+ }
+
+ update[`${repeating_attack}_spell_innate`] = v[
+ `${repeating_spell}_innate`
+ ]
+ ? v[`${repeating_spell}_innate`]
+ : "";
+
+ if (v[`${repeating_spell}_spelltarget`]) {
+ description = description + v[`${repeating_spell}_spelltarget`] + ". ";
+ }
+ if (
+ v[`${repeating_spell}_includedesc`] &&
+ v[`${repeating_spell}_includedesc`] === "on"
+ ) {
+ description = v[`${repeating_spell}_spelldescription`];
+ if (
+ v[`${repeating_spell}_spellathigherlevels`] &&
+ v[`${repeating_spell}_spellathigherlevels`] != ""
+ ) {
+ description =
+ description +
+ "\n\nAt Higher Levels: " +
+ v[`${repeating_spell}_spellathigherlevels`];
+ }
+ } else if (
+ v[`${repeating_spell}_includedesc`] &&
+ v[`${repeating_spell}_includedesc`] === "off"
+ ) {
+ description = "";
+ }
+ update[`${repeating_attack}_atk_desc`] = description;
+
+ update[
+ `${repeating_attack}_spelldesc_link`
+ ] = `%{${character_id}|${repeating_spell}_output}`;
+
+ var callback = () => {
+ update_attacks(attackid, "spell");
+ };
+ setAttrs(update, { silent: true }, callback);
+ }
+ );
+};
+
+const update_attacks = (update_id, source) => {
+ if (update_id.substring(0, 1) === "-" && update_id.length === 20) {
+ do_update_attack([update_id], source);
+ } else if (
+ [
+ "strength",
+ "dexterity",
+ "constitution",
+ "intelligence",
+ "wisdom",
+ "charisma",
+ "spells",
+ "all",
+ ].indexOf(update_id) > -1
+ ) {
+ getSectionIDs("repeating_attack", (idarray) => {
+ if (update_id === "all") {
+ do_update_attack(idarray);
+ } else if (update_id === "spells") {
+ let attack_attribs = [];
+ _.each(idarray, (id) => {
+ attack_attribs.push(
+ `repeating_attack_${id}_spellid`,
+ `repeating_attack_${id}_spelllevel`
+ );
+ });
+ getAttrs([...attack_attribs, "character_id"], (v) => {
+ const filteredIds = _.filter(idarray, (id) => {
+ return (
+ v[`repeating_attack_${id}_spellid`] &&
+ v[`repeating_attack_${id}_spellid`] != ""
+ );
+ });
+ let spell_attacks = {};
+ _.each(filteredIds, (attack_id) => {
+ spell_attacks[attack_id] = {
+ spell_id: v[`repeating_attack_${attack_id}_spellid`],
+ spell_lvl: v[`repeating_attack_${attack_id}_spelllevel`],
+ };
+ });
+ _.each(spell_attacks, (data, attack_id) => {
+ update_attack_from_spell(
+ data.spell_lvl,
+ data.spell_id,
+ attack_id,
+ false,
+ v["character_id"]
+ );
+ });
+ });
+ } else {
+ let attack_attribs = ["spellcasting_ability"];
+ _.each(idarray, (id) => {
+ attack_attribs.push(`repeating_attack_${id}_atkattr_base`);
+ attack_attribs.push(`repeating_attack_${id}_dmgattr`);
+ attack_attribs.push(`repeating_attack_${id}_dmg2attr`);
+ attack_attribs.push(`repeating_attack_${id}_savedc`);
+ });
+ getAttrs(attack_attribs, (v) => {
+ let attr_attack_ids = [];
+ _.each(idarray, (id) => {
+ if (
+ (v[`repeating_attack_${id}_atkattr_base`] &&
+ v[`repeating_attack_${id}_atkattr_base`].indexOf(update_id) >
+ -1) ||
+ (v[`repeating_attack_${id}_dmgattr`] &&
+ v[`repeating_attack_${id}_dmgattr`].indexOf(update_id) > -1) ||
+ (v[`repeating_attack_${id}_dmg2attr`] &&
+ v[`repeating_attack_${id}_dmg2attr`].indexOf(update_id) > -1) ||
+ (v[`repeating_attack_${id}_savedc`] &&
+ v[`repeating_attack_${id}_savedc`].indexOf(update_id) > -1) ||
+ (v[`repeating_attack_${id}_savedc`] &&
+ v[`repeating_attack_${id}_savedc`] === "(@{spell_save_dc})" &&
+ v["spellcasting_ability"] &&
+ v["spellcasting_ability"].indexOf(update_id) > -1)
+ ) {
+ attr_attack_ids.push(id);
+ }
+ });
+ if (attr_attack_ids.length > 0) {
+ do_update_attack(attr_attack_ids);
+ }
+ });
+ }
+ });
+ }
+};
+
+const do_update_attack = (attack_array, source) => {
+ let attack_attribs = [
+ "level",
+ "d20",
+ "pb",
+ "pb_type",
+ "pbd_safe",
+ "dtype",
+ "globalmagicmod",
+ "strength_mod",
+ "dexterity_mod",
+ "constitution_mod",
+ "intelligence_mod",
+ "wisdom_mod",
+ "charisma_mod",
+ "spellcasting_ability",
+ "spell_save_dc",
+ "spell_attack_mod",
+ "spell_dc_mod",
+ "global_damage_mod_roll",
+ "global_damage_mod_crit",
+ "default_critical_range",
+ ];
+ _.each(attack_array, (attackid) => {
+ [
+ "atkflag",
+ "atkname",
+ "atkattr_base",
+ "atkmod",
+ "atkprofflag",
+ "atkmagic",
+ "atkcritrange",
+ "dmgflag",
+ "dmgbase",
+ "dmgattr",
+ "dmgmod",
+ "dmgtype",
+ "dmg2flag",
+ "dmg2base",
+ "dmg2attr",
+ "dmg2mod",
+ "dmg2type",
+ "dmgcustcrit",
+ "dmg2custcrit",
+ "saveflag",
+ "savedc",
+ "saveeffect",
+ "saveflat",
+ "hldmg",
+ "spellid",
+ "spelllevel",
+ "atkrange",
+ "itemid",
+ "ammo",
+ "spelldesc_link",
+ ].forEach((attr) => {
+ attack_attribs.push(`repeating_attack_${attackid}_${attr}`);
+ });
+ });
+
+ getAttrs(attack_attribs, (v) => {
+ _.each(attack_array, (attackid) => {
+ const repeating_attack = `repeating_attack_${attackid}`;
+ let callbacks = [];
+ let update = {};
+ let hbonus = "";
+ let hdmg1 = "";
+ let hdmg2 = "";
+ let dmg = "";
+ let dmg2 = "";
+ let rollbase = "";
+ let spellattack = false;
+ let magicattackmod = 0;
+ let magicsavemod = 0;
+ let atkattr_abrev = "";
+ let dmgattr_abrev = "";
+ let dmg2attr_abrev = "";
+ //PROFICIENCY BONUS select in Settings.
+ const pbd_safe = v["pbd_safe"] || "";
+
+ //HIGHER LVL CAST DMG found in Spells for spells like Fireball
+ const hldmgcrit =
+ v[`${repeating_attack}_hldmg`] && v[`${repeating_attack}_hldmg`] != ""
+ ? v[`${repeating_attack}_hldmg`].slice(0, 7) +
+ "crit" +
+ v[`${repeating_attack}_hldmg`].slice(7)
+ : "";
+
+ if (
+ v[`${repeating_attack}_spellid`] &&
+ v[`${repeating_attack}_spellid`] != ""
+ ) {
+ spellattack = true;
+ //GLOBAL MAGIC ATTACK MODIFIER in Settings
+ magicattackmod = parseInt(v["spell_attack_mod"], 10) || 0;
+ //SPELL SAVE DC MOD in Settings
+ magicsavemod = parseInt(v["spell_dc_mod"], 10) || 0;
+ }
+
+ //ATTACK select inside settings for the repeating attack
+ if (
+ !v[`${repeating_attack}_atkattr_base`] ||
+ v[`${repeating_attack}_atkattr_base`] === "0"
+ ) {
+ atkattr_base = 0;
+ } else if (
+ v[`${repeating_attack}_atkattr_base`] &&
+ v[`${repeating_attack}_atkattr_base`] === "spell"
+ ) {
+ atkattr_base = parseInt(
+ v[
+ v["spellcasting_ability"].substring(
+ 2,
+ v["spellcasting_ability"].length - 2
+ )
+ ],
+ 10
+ );
+ atkattr_abrev = v["spellcasting_ability"].substring(2, 5).toUpperCase();
+ } else {
+ atkattr_base = parseInt(
+ v[
+ v[`${repeating_attack}_atkattr_base`].substring(
+ 2,
+ v[`${repeating_attack}_atkattr_base`].length - 1
+ )
+ ],
+ 10
+ );
+ atkattr_abrev = v[`${repeating_attack}_atkattr_base`]
+ .substring(2, 5)
+ .toUpperCase();
+ }
+
+ //DAMAGE 1 ability select inside settings for the repeating attack
+ if (
+ !v[`${repeating_attack}_dmgattr`] ||
+ v[`${repeating_attack}_dmgattr`] === "0"
+ ) {
+ dmgattr = 0;
+ } else if (
+ v[`${repeating_attack}_dmgattr`] &&
+ v[`${repeating_attack}_dmgattr`] === "spell"
+ ) {
+ dmgattr = parseInt(
+ v[
+ v["spellcasting_ability"].substring(
+ 2,
+ v["spellcasting_ability"].length - 2
+ )
+ ],
+ 10
+ );
+ dmgattr_abrev = v["spellcasting_ability"].substring(2, 5).toUpperCase();
+ } else {
+ dmgattr = parseInt(
+ v[
+ v[`${repeating_attack}_dmgattr`].substring(
+ 2,
+ v[`${repeating_attack}_dmgattr`].length - 1
+ )
+ ],
+ 10
+ );
+ dmgattr_abrev = v[`${repeating_attack}_dmgattr`]
+ .substring(2, 5)
+ .toUpperCase();
+ }
+
+ //DAMAGE 2 ability select inside settings for the repeating attack
+ if (
+ !v[`${repeating_attack}_dmg2attr`] ||
+ v[`${repeating_attack}_dmg2attr`] === "0"
+ ) {
+ dmg2attr = 0;
+ } else if (
+ v[`${repeating_attack}_dmg2attr`] &&
+ v[`${repeating_attack}_dmg2attr`] === "spell"
+ ) {
+ dmg2attr = parseInt(
+ v[
+ v["spellcasting_ability"].substring(
+ 2,
+ v["spellcasting_ability"].length - 2
+ )
+ ],
+ 10
+ );
+ dmg2attr_abrev = v["spellcasting_ability"]
+ .substring(2, 5)
+ .toUpperCase();
+ } else {
+ dmg2attr = parseInt(
+ v[
+ v[`${repeating_attack}_dmg2attr`].substring(
+ 2,
+ v[`${repeating_attack}_dmg2attr`].length - 1
+ )
+ ],
+ 10
+ );
+ dmg2attr_abrev = v[`${repeating_attack}_dmg2attr`]
+ .substring(2, 5)
+ .toUpperCase();
+ }
+
+ //DAMAGE first input inside settings for the repeating attack
+ const dmgbase = v[`${repeating_attack}_dmgbase`] || 0;
+ const dmg2base = v[`${repeating_attack}_dmg2base`] || 0;
+ //DAMAGE 1 second input inside settings for the repeating attack
+ const dmgmod = parseInt(v[`${repeating_attack}_dmgmod`], 10) || 0;
+ //DAMAGE 2 second input inside settings for the repeating attack
+ const dmg2mod = parseInt(v[`${repeating_attack}_dmg2mod`], 10) || 0;
+ //DAMAGE 1 TYPE input inside settings for the repeating attack
+ const dmgtype = v[`${repeating_attack}_dmgtype`] || "";
+ //DAMAGE 2 TYPE input inside settings for the repeating attack
+ const dmg2type = v[`${repeating_attack}_dmg2type`] || "";
+
+ //PROFICIENT flag inside settings for the repeating attack && PROFICIENCY BONUS from Settings
+ const atkprofflag = v[`${repeating_attack}_atkprofflag`] || 0;
+ const pb = atkprofflag != 0 && v.pb ? v.pb : 0;
+
+ //ATTACK input inside settings for the repeating attack
+ const atkmod = parseInt(v[`${repeating_attack}_atkmod`], 10) || 0;
+ //MAGIC BONUS input inside settings for the repeating attack
+ const atkmag = parseInt(v[`${repeating_attack}_atkmagic`], 10) || 0;
+
+ //used in _atkdmgtype display
+ const dmgmag =
+ isNaN(atkmag) === false &&
+ atkmag != 0 &&
+ ((v[`${repeating_attack}_dmgflag`] &&
+ v[`${repeating_attack}_dmgflag`] != 0) ||
+ (v[`${repeating_attack}_dmg2flag`] &&
+ v[`${repeating_attack}_dmg2flag`] != 0))
+ ? `+ ${atkmag} Magic Bonus`
+ : "";
+
+ //Spell description link
+ const spelldesc_link = v[`${repeating_attack}_spelldesc_link`]
+ ? `{{spelldesc_link=[Show Spell Description](~repeating_attack_spelldesc_link)}} `
+ : "";
+
+ //ATTACK checkbox inside settings for the repeating attack
+ const atkflag = v[`${repeating_attack}_atkflag`] || 0;
+ if (atkflag != 0) {
+ bonus_mod = atkattr_base + atkmod + atkmag + magicattackmod;
+ plus_minus = bonus_mod > -1 ? "+" : "";
+ //pb_type is PROFICIENCY BONUS select in Settings
+ if (v["pb_type"] && v["pb_type"] === "die") {
+ bonus = `${bonus_mod}+${pb}`;
+ } else {
+ bonus_mod = bonus_mod + parseInt(pb, 10);
+ bonus = plus_minus + bonus_mod;
+ }
+ //SAVING THROW checkbox inside settings for the repeating attack
+ } else if (
+ v[`${repeating_attack}_saveflag`] &&
+ v[`${repeating_attack}_saveflag`] != 0
+ ) {
+ const saveDC = v[`${repeating_attack}_savedc`] || "";
+ //SAVING THROW VS DC select "Spell" inside settings for the repeating attack
+ if (!saveDC || saveDC === "(@{spell_save_dc})") {
+ const tempdc = v["spell_save_dc"];
+ bonus = "DC" + tempdc;
+ //SAVING THROW VS DC select "FLAT" inside settings for the repeating attack
+ } else if (saveDC === "(@{saveflat})") {
+ const tempdc = parseInt(v[`${repeating_attack}_saveflat`]) || 0;
+ bonus = "DC" + tempdc;
+ //SAVING THROW VS DC select ability score inside settings for the repeating attack
+ } else {
+ const savedcattr = v[`${repeating_attack}_savedc`]
+ .split("_mod")[0]
+ .slice(3);
+ const safe_pb =
+ v["pb_type"] && v["pb_type"] === "die"
+ ? parseInt(pb.substring(1), 10) / 2
+ : parseInt(pb, 10);
+ const safe_attr = v[`${savedcattr}_mod`]
+ ? parseInt(v[`${savedcattr}_mod`], 10)
+ : 0;
+ const tempdc = 8 + safe_attr + safe_pb + magicsavemod;
+ bonus = "DC" + tempdc;
+ }
+ } else {
+ bonus = "-";
+ }
+
+ //DAMAGE checkbox inside settings for the repeating attack
+ const dmgflag1 = v[`${repeating_attack}_dmgflag`] || 0;
+ const dmgflag2 = v[`${repeating_attack}_dmg2flag`] || 0;
+ if (dmgflag1 != 0) {
+ if (
+ spellattack === true &&
+ dmgbase.indexOf("[[round((@{level} + 1) / 6 + 0.5)]]") > -1
+ ) {
+ // SPECIAL CANTRIP DAMAGE
+ dmgdiestring = Math.round(
+ (parseInt(v["level"], 10) + 1) / 6 + 0.5
+ ).toString();
+ dmg = dmgdiestring + dmgbase.substring(dmgbase.lastIndexOf("d"));
+ //select & input to the right of damage
+ if (dmgattr + dmgmod != 0) {
+ dmg += `+${dmgattr + dmgmod}`;
+ }
+ dmg += ` ${dmgtype}`;
+ } else {
+ if (dmgbase === 0 && dmgattr + dmgmod === 0) {
+ dmg = 0;
+ }
+ if (dmgbase != 0) {
+ dmg = dmgbase;
+ }
+ if (dmgbase != 0 && dmgattr + dmgmod != 0) {
+ dmg = dmgattr + dmgmod > 0 ? dmg + "+" : dmg;
+ }
+ if (dmgattr + dmgmod != 0) {
+ dmg = dmg + (dmgattr + dmgmod);
+ }
+ dmg = dmg + " " + dmgtype;
+ }
+ }
+ if (dmgflag2 != 0) {
+ if (dmg2base === 0 && dmg2attr + dmg2mod === 0) {
+ dmg2 = 0;
+ }
+ if (dmg2base != 0) {
+ dmg2 = dmg2base;
+ }
+ if (dmg2base != 0 && dmg2attr + dmg2mod != 0) {
+ dmg2 = dmg2attr + dmg2mod > 0 ? dmg2 + "+" : dmg2;
+ }
+ if (dmg2attr + dmg2mod != 0) {
+ dmg2 = dmg2 + (dmg2attr + dmg2mod);
+ }
+ dmg2 = dmg2 + " " + dmg2type;
+ }
+ update[`${repeating_attack}_atkdmgtype`] =
+ dmgflag1 != 0 && dmgflag2 != 0
+ ? `${dmg} + ${dmg2}${dmgmag} `
+ : `${dmg}${dmg2}${dmgmag} `;
+
+ //Build ROLL TEMPLATE with below variables
+ //ATTACK checkbox inside settings for the repeating attack
+ if (atkflag != 0) {
+ if (atkattr_base != 0) {
+ hbonus += ` + ${atkattr_base}[${atkattr_abrev}]`;
+ }
+ if (atkmod != 0) {
+ hbonus += ` + ${atkmod}[MOD]`;
+ }
+ if (pb != 0) {
+ hbonus += ` + ${pb}${pbd_safe}[PROF]`;
+ }
+ if (atkmag != 0) {
+ hbonus += ` + ${atkmag}[MAGIC]`;
+ }
+ if (magicattackmod != 0) {
+ hbonus += ` + ${magicattackmod}[SPELLATK]`;
+ }
+ }
+ //DAMAGE 1 checkbox inside settings for the repeating attack
+ if (dmgflag1 != 0) {
+ hdmg1 += dmgbase;
+ if (dmgattr != 0) {
+ hdmg1 += ` + ${dmgattr}[${dmgattr_abrev}]`;
+ }
+ if (dmgmod != 0) {
+ hdmg1 += ` + ${dmgmod}[MOD]`;
+ }
+ if (atkmag != 0) {
+ hdmg1 += ` + ${atkmag}[MAGIC]`;
+ }
+ } else {
+ hdmg1 += "0";
+ }
+ //DAMAGE 2 checkbox inside settings for the repeating attack
+ if (dmgflag2 != 0) {
+ hdmg2 += dmg2base;
+ if (dmg2attr != 0) {
+ hdmg2 += ` + ${dmg2attr}[${dmg2attr_abrev}]`;
+ }
+ if (dmg2mod != 0) {
+ hdmg2 += ` + ${dmg2mod}[MOD]`;
+ }
+ } else {
+ hdmg2 += "0";
+ }
+ //CRIT input inside settings for the repeating attack
+ let crit1 = v[`${repeating_attack}_dmgcustcrit`] || 0;
+ let crit2 = v[`${repeating_attack}_dmg2custcrit`] || 0;
+ crit1 = crit1 != 0 ? v[`${repeating_attack}_dmgcustcrit`] : dmgbase;
+ crit2 = crit2 != 0 ? v[`${repeating_attack}_dmg2custcrit`] : dmg2base;
+ r1 = atkflag != 0 ? "@{d20}" : "0d20";
+ r2 = atkflag != 0 ? "@{rtype}" : "{{r2=[[0d20";
+ //set in the GLOBAL DAMAGE MODIFIER section
+ let globaldamage = `[[${v.global_damage_mod_roll || 0}]]`;
+ let globaldamagecrit = `[[${v.global_damage_mod_crit || 0}]]`;
+
+ //Assamble Roll Templates
+ const criticalrange =
+ v[`${repeating_attack}_atkcritrange`] &&
+ v["default_critical_range"] &&
+ parseInt(v["default_critical_range"]) <
+ parseInt(v[`${repeating_attack}_atkcritrange`])
+ ? "@{default_critical_range}"
+ : "@{atkcritrange}";
+ if (v.dtype === "full") {
+ rollbase = `@{wtype}&{template:atkdmg} {{mod=@{atkbonus}}} {{rname=@{atkname}}} {{r1=[[${r1}cs>${criticalrange}${hbonus}]]}} ${r2}cs>${criticalrange}${hbonus}]]}} @{atkflag} {{range=@{atkrange}}} @{dmgflag} {{dmg1=[[${hdmg1}]]}} {{dmg1type=${dmgtype}}} @{dmg2flag} {{dmg2=[[${hdmg2}]]}} {{dmg2type=${dmg2type}}} {{crit1=[[${crit1}[CRIT]]]}} {{crit2=[[${crit2}[CRIT]]]}} @{saveflag} {{desc=@{atk_desc}}} @{hldmg} ${hldmgcrit} {{spelllevel=@{spelllevel}}} {{innate=@{spell_innate}}} {{globalattack=@{global_attack_mod}}} {{globaldamage=${globaldamage}}} {{globaldamagecrit=${globaldamagecrit}}} {{globaldamagetype=@{global_damage_mod_type}}} ammo=@{ammo} ${spelldesc_link}@{charname_output}`;
+ } else if (atkflag != 0) {
+ rollbase = `@{wtype}&{template:atk} {{mod=@{atkbonus}}} {{rname=[@{atkname}](~repeating_attack_attack_dmg)}} {{rnamec=[@{atkname}](~repeating_attack_attack_crit)}} {{r1=[[${r1}cs>${criticalrange}${hbonus}]]}} ${r2}cs>${criticalrange}${hbonus}]]}} {{range=@{atkrange}}} {{desc=@{atk_desc}}} {{spelllevel=@{spelllevel}}} {{innate=@{spell_innate}}} {{globalattack=@{global_attack_mod}}} ammo=@{ammo} ${spelldesc_link}@{charname_output}`;
+ } else if (dmgflag1 != 0) {
+ rollbase = `@{wtype}&{template:dmg} {{rname=@{atkname}}} @{atkflag} {{range=@{atkrange}}} @{dmgflag} {{dmg1=[[${hdmg1}]]}} {{dmg1type=${dmgtype}}} @{dmg2flag} {{dmg2=[[${hdmg2}]]}} {{dmg2type=${dmg2type}}} @{saveflag} {{desc=@{atk_desc}}} @{hldmg} {{spelllevel=@{spelllevel}}} {{innate=@{spell_innate}}} {{globaldamage=${globaldamage}}} {{globaldamagetype=@{global_damage_mod_type}}} ammo=@{ammo} ${spelldesc_link}@{charname_output}`;
+ } else {
+ rollbase = `@{wtype}&{template:dmg} {{rname=@{atkname}}} @{atkflag} {{range=@{atkrange}}} @{saveflag} {{desc=@{atk_desc}}} {{spelllevel=@{spelllevel}}} {{innate=@{spell_innate}}} ammo=@{ammo} ${spelldesc_link}@{charname_output}`;
+ }
+
+ update[
+ `${repeating_attack}_rollbase_dmg`
+ ] = `@{wtype}&{template:dmg} {{rname=@{atkname}}} @{atkflag} {{range=@{atkrange}}} @{dmgflag} {{dmg1=[[${hdmg1}]]}} {{dmg1type=${dmgtype}}} @{dmg2flag} {{dmg2=[[${hdmg2}]]}} {{dmg2type=${dmg2type}}} @{saveflag} {{desc=@{atk_desc}}} @{hldmg} {{spelllevel=@{spelllevel}}} {{innate=@{spell_innate}}} {{globaldamage=${globaldamage}}} {{globaldamagetype=@{global_damage_mod_type}}} ${spelldesc_link}@{charname_output}`;
+ update[
+ `${repeating_attack}_rollbase_crit`
+ ] = `@{wtype}&{template:dmg} {{crit=1}} {{rname=@{atkname}}} @{atkflag} {{range=@{atkrange}}} @{dmgflag} {{dmg1=[[${hdmg1}]]}} {{dmg1type=${dmgtype}}} @{dmg2flag} {{dmg2=[[${hdmg2}]]}} {{dmg2type=${dmg2type}}} {{crit1=[[${crit1}]]}} {{crit2=[[${crit2}]]}} @{saveflag} {{desc=@{atk_desc}}} @{hldmg} ${hldmgcrit} {{spelllevel=@{spelllevel}}} {{innate=@{spell_innate}}} {{globaldamage=${globaldamage}}} {{globaldamagecrit=${globaldamagecrit}}} {{globaldamagetype=@{global_damage_mod_type}}} ${spelldesc_link}@{charname_output}`;
+ update[`${repeating_attack}_atkbonus`] = bonus;
+ update[`${repeating_attack}_rollbase`] = rollbase;
+
+ if (
+ v[`${repeating_attack}_spellid`] &&
+ v[`${repeating_attack}_spellid`] != "" &&
+ (!source || (source && source != "spell")) &&
+ v[`${repeating_attack}_spellid`].length == 20
+ ) {
+ const spellid = v[`${repeating_attack}_spellid`];
+ const lvl = v[`${repeating_attack}_spelllevel`];
+ callbacks.push(() => {
+ update_spell_from_attack(lvl, spellid, attackid);
+ });
+ }
+ if (
+ v[`${repeating_attack}_itemid`] &&
+ v[`${repeating_attack}_itemid`] != "" &&
+ (!source || (source && source != "item"))
+ ) {
+ const itemid = v[`${repeating_attack}_itemid`];
+ callbacks.push(() => {
+ update_item_from_attack(itemid, attackid);
+ });
+ }
+ setAttrs(update, { silent: true }, () => {
+ callbacks.forEach((callback) => {
+ callback();
+ });
+ });
+ });
+ });
+};
+
+//Update spells in the attack section
+const update_spell_from_attack = (lvl, spellid, attackid) => {
+ const repeating_attack = `repeating_attack_${attackid}`;
+ const repeating_spell = `repeating_spell-${lvl}_${spellid}`;
+ let update = {};
+ getAttrs(
+ [
+ `${repeating_attack}_atkname`,
+ `${repeating_attack}_atkrange`,
+ `${repeating_attack}_atkflag`,
+ `${repeating_attack}_atkattr_base`,
+ `${repeating_attack}_dmgbase`,
+ `${repeating_attack}_dmgtype`,
+ `${repeating_attack}_dmg2base`,
+ `${repeating_attack}_dmg2type`,
+ `${repeating_attack}_saveflag`,
+ `${repeating_attack}_saveattr`,
+ `${repeating_attack}_saveeffect`,
+ ],
+ (v) => {
+ update[`${repeating_spell}_spellname`] = v[`${repeating_attack}_atkname`];
+ update[`${repeating_spell}_spellrange`] =
+ v[`${repeating_attack}_atkrange`] || "";
+ update[`${repeating_spell}_spellsavesuccess`] =
+ v[`${repeating_attack}_saveeffect`] || "";
+
+ if (
+ v[`${repeating_attack}_dmgtype`] &&
+ v[`${repeating_attack}_dmgtype`].toLowerCase() == "healing"
+ ) {
+ if (
+ v[`${repeating_attack}_dmgbase`] &&
+ v[`${repeating_attack}_dmgbase`] != ""
+ ) {
+ update[`${repeating_spell}_spellhealing`] =
+ v[`${repeating_attack}_dmgbase`];
+ }
+ } else {
+ if (
+ v[`${repeating_attack}_dmgbase`] &&
+ v[`${repeating_attack}_dmgbase`] != "" &&
+ v[`${repeating_attack}_dmgbase`].indexOf(
+ "[[round((@{level} + 1) / 6 + 0.5)]]"
+ ) === -1
+ ) {
+ update[`${repeating_spell}_spelldamage`] =
+ v[`${repeating_attack}_dmgbase`];
+ } else if (
+ !v[`${repeating_attack}_dmgbase`] ||
+ v[`${repeating_attack}_dmgbase`] === ""
+ ) {
+ update[`${repeating_spell}_spelldamage`] = "";
+ }
+
+ update[`${repeating_spell}_spelldamagetype`] =
+ v[`${repeating_attack}_dmgtype`] || "";
+ }
+ if (
+ v[`${repeating_attack}_dmg2type`] &&
+ v[`${repeating_attack}_dmg2type`].toLowerCase() === "healing"
+ ) {
+ if (
+ v[`${repeating_attack}_dmgbase`] &&
+ v[`${repeating_attack}_dmgbase`] != ""
+ ) {
+ update[`${repeating_spell}_spellhealing`] =
+ v[`${repeating_attack}_dmgbase`];
+ }
+ } else {
+ update[`${repeating_spell}_spelldamage2`] =
+ v[`${repeating_attack}_dmg2base`] || "";
+ update[`${repeating_spell}_spelldamagetype2`] =
+ v[`${repeating_attack}_dmg2type`] || "";
+ }
+
+ //SAVING THROW checkbox inside settings for the repeating attack
+ update[`${repeating_spell}_spellsave`] =
+ v[`${repeating_attack}_saveflag`] &&
+ v[`${repeating_attack}_saveflag`] != "0"
+ ? v[`${repeating_attack}_saveattr`]
+ : "";
+ setAttrs(update, { silent: true });
+ }
+ );
+};
+
+var update_item_from_attack = function (itemid, attackid) {
+ getAttrs(
+ [
+ "repeating_attack_" + attackid + "_atkname",
+ "repeating_attack_" + attackid + "_dmgbase",
+ "repeating_attack_" + attackid + "_dmg2base",
+ "repeating_attack_" + attackid + "_dmgtype",
+ "repeating_attack_" + attackid + "_dmg2type",
+ "repeating_attack_" + attackid + "_atkrange",
+ "repeating_attack_" + attackid + "_atkmod",
+ "repeating_attack_" + attackid + "_dmgmod",
+ "repeating_inventory_" + itemid + "_itemmodifiers",
+ "repeating_attack_" + attackid + "_versatile_alt",
+ "repeating_inventory_" + itemid + "_itemproperties",
+ "repeating_attack_" + attackid + "_atkmagic",
+ ],
+ function (v) {
+ var update = {};
+ var mods = v["repeating_inventory_" + itemid + "_itemmodifiers"];
+ var damage = v["repeating_attack_" + attackid + "_dmgbase"]
+ ? v["repeating_attack_" + attackid + "_dmgbase"]
+ : 0;
+ var damage2 = v["repeating_attack_" + attackid + "_dmg2base"]
+ ? v["repeating_attack_" + attackid + "_dmg2base"]
+ : 0;
+ var damagetype = v["repeating_attack_" + attackid + "_dmgtype"]
+ ? v["repeating_attack_" + attackid + "_dmgtype"]
+ : 0;
+ var damagetype2 = v["repeating_attack_" + attackid + "_dmg2type"]
+ ? v["repeating_attack_" + attackid + "_dmg2type"]
+ : 0;
+ var atkcritrange = v["repeating_attack_" + attackid + "_atkcritrange"]
+ ? v["repeating_attack_" + attackid + "_atkcritrange"]
+ : 20;
+ var range = v["repeating_attack_" + attackid + "_atkrange"]
+ ? v["repeating_attack_" + attackid + "_atkrange"]
+ : 0;
+ var attackmod = v["repeating_attack_" + attackid + "_atkmod"]
+ ? v["repeating_attack_" + attackid + "_atkmod"]
+ : 0;
+ var damagemod = v["repeating_attack_" + attackid + "_dmgmod"]
+ ? v["repeating_attack_" + attackid + "_dmgmod"]
+ : 0;
+ var magicmod = v["repeating_attack_" + attackid + "_atkmagic"]
+ ? v["repeating_attack_" + attackid + "_atkmagic"]
+ : 0;
+ var atktype = "";
+ var altprefix =
+ v["repeating_attack_" + attackid + "_versatile_alt"] === "1"
+ ? "Alternate "
+ : "";
+
+ if (
+ /Alternate Damage:/i.test(
+ v["repeating_inventory_" + itemid + "_itemmodifiers"]
+ )
+ ) {
+ update["repeating_inventory_" + itemid + "_itemname"] = v[
+ "repeating_attack_" + attackid + "_atkname"
+ ].replace(/\s*(?:\(One-Handed\)|\(Two-Handed\))/, "");
+ } else {
+ update["repeating_inventory_" + itemid + "_itemname"] =
+ v["repeating_attack_" + attackid + "_atkname"];
+ }
+
+ var attack_type_regex =
+ /(?:^|,)\s*Item Type: (Melee|Ranged) Weapon(?:,|$)/i;
+ var attack_type_results = attack_type_regex.exec(
+ v["repeating_inventory_" + itemid + "_itemmodifiers"]
+ );
+ atktype = attack_type_results ? attack_type_results[1] : "";
+ if (mods) {
+ mods = mods.split(",");
+ } else {
+ mods = [];
+ }
+
+ var damage_regex = new RegExp(
+ "^\\s*" + altprefix + "Damage:\\s*(.+)$",
+ "i"
+ );
+ var damage_found = false;
+ for (var i = 0; i < mods.length; i++) {
+ if ((damage_found = damage_regex.exec(mods[i]))) {
+ if (damage !== 0) {
+ mods[i] = mods[i].replace(damage_found[1], damage);
+ } else {
+ mods.splice(i, 1);
+ }
+ break;
+ }
+ }
+ if (!damage_found && damage !== 0) {
+ mods.push(altprefix + "Damage: " + damage);
+ }
+
+ var damage2_regex = new RegExp(
+ "^\\s*" + altprefix + "Secondary Damage:\\s*(.+)$",
+ "i"
+ );
+ var damage2_found = false;
+ for (var i = 0; i < mods.length; i++) {
+ if ((damage2_found = damage2_regex.exec(mods[i]))) {
+ if (damage2 !== 0) {
+ mods[i] = mods[i].replace(damage2_found[1], damage2);
+ } else {
+ mods.splice(i, 1);
+ }
+ break;
+ }
+ }
+ if (!damage2_found && damage2 !== 0) {
+ mods.push(altprefix + "Secondary Damage: " + damage2);
+ }
+
+ var dmgtype_regex = new RegExp(
+ "^\\s*" + altprefix + "Damage Type:\\s*(.+)$",
+ "i"
+ );
+ var dmgtype_found = false;
+ for (var i = 0; i < mods.length; i++) {
+ if ((dmgtype_found = dmgtype_regex.exec(mods[i]))) {
+ if (damagetype !== 0) {
+ mods[i] = mods[i].replace(dmgtype_found[1], damagetype);
+ } else {
+ mods.splice(i, 1);
+ }
+ break;
+ }
+ }
+ if (!dmgtype_found && damagetype !== 0) {
+ mods.push(altprefix + "Damage Type: " + damagetype);
+ }
+
+ var dmgtype2_regex = new RegExp(
+ "^\\s*" + altprefix + "Secondary Damage Type:\\s*(.+)$",
+ "i"
+ );
+ var dmgtype2_found = false;
+ for (var i = 0; i < mods.length; i++) {
+ if ((dmgtype2_found = dmgtype2_regex.exec(mods[i]))) {
+ if (damagetype2 !== 0) {
+ mods[i] = mods[i].replace(dmgtype_found[1], damagetype);
+ } else {
+ mods.splice(i, 1);
+ }
+ break;
+ }
+ }
+ if (!dmgtype2_found && damagetype2 !== 0) {
+ mods.push(altprefix + "Secondary Damage Type: " + damagetype2);
+ }
+
+ var atkcritrange_found = false;
+ for (var i = 0; i < mods.length; i++) {
+ if (
+ (atkcritrange_found = /^\s*Critical Range:\s*(.+)$/i.exec(mods[i]))
+ ) {
+ if (atkcritrange !== 0) {
+ mods[i] = mods[i].replace(atkcritrange_found[1], atkcritrange);
+ } else {
+ mods.splice(i, 1);
+ }
+ break;
+ }
+ }
+ if (!range_found && range !== 0) {
+ mods.push("Critical Range: " + atkcritrange);
+ }
+
+ var range_found = false;
+ for (var i = 0; i < mods.length; i++) {
+ if ((range_found = /^\s*Range:\s*(.+)$/i.exec(mods[i]))) {
+ if (range !== 0) {
+ mods[i] = mods[i].replace(range_found[1], range);
+ } else {
+ mods.splice(i, 1);
+ }
+ break;
+ }
+ }
+ if (!range_found && range !== 0) {
+ mods.push("Range: " + range);
+ }
+
+ var attackmod_regex = new RegExp(
+ "^\\s*(?:" +
+ (atktype !== "" ? atktype + "|" : "") +
+ "Weapon) Attacks \\+?(.+)$",
+ "i"
+ );
+ var attackmod_found = false;
+ for (var i = 0; i < mods.length; i++) {
+ if ((attackmod_found = attackmod_regex.exec(mods[i]))) {
+ if (magicmod !== 0 || attackmod !== 0) {
+ mods[i] = mods[i].replace(
+ attackmod_found[1],
+ magicmod !== 0 ? magicmod : attackmod
+ );
+ } else {
+ mods.splice(i, 1);
+ }
+ break;
+ }
+ }
+ if (!attackmod_found && (magicmod !== 0 || attackmod !== 0)) {
+ var properties = v["repeating_inventory_" + itemid + "_itemproperties"];
+ if (properties && /Thrown/i.test(properties)) {
+ mods.push(
+ "Weapon Attacks: " + (magicmod !== 0 ? magicmod : attackmod)
+ );
+ } else {
+ mods.push(
+ atktype + " Attacks: " + (magicmod !== 0 ? magicmod : attackmod)
+ );
+ }
+ }
+
+ var damagemod_regex = new RegExp(
+ "^\\s*(?:" +
+ (atktype !== "" ? atktype + "|" : "") +
+ "Weapon) Damage \\+?(.+)$",
+ "i"
+ );
+ var damagemod_found = false;
+ for (var i = 0; i < mods.length; i++) {
+ if ((damagemod_found = damagemod_regex.exec(mods[i]))) {
+ if (magicmod !== 0 || damagemod !== 0) {
+ mods[i] = mods[i].replace(
+ damagemod_found[1],
+ magicmod !== 0 ? magicmod : attackmod
+ );
+ } else {
+ mods.splice(i, 1);
+ }
+ break;
+ }
+ }
+ if (!damagemod_found && (magicmod !== 0 || damagemod !== 0)) {
+ var properties = v["repeating_inventory_" + itemid + "_itemproperties"];
+ if (properties && /Thrown/i.test(properties)) {
+ mods.push(
+ "Weapon Damage: " + (magicmod !== 0 ? magicmod : damagemod)
+ );
+ } else {
+ mods.push(
+ atktype + " Damage: " + (magicmod !== 0 ? magicmod : damagemod)
+ );
+ }
+ }
+
+ update["repeating_inventory_" + itemid + "_itemmodifiers"] =
+ mods.join(",");
+
+ setAttrs(update, { silent: true });
+ }
+ );
+};
+
+var remove_attack = function (attackid) {
+ removeRepeatingRow("repeating_attack_" + attackid);
+};
+
+const createResource = (name, max, current) => {
+ const updateResource = (name, max, current, side, id) => {
+ const newrowid = id || generateRowID();
+ let update = {};
+ update[`repeating_resource_${newrowid}_resource_${side}_name`] = name;
+ update[`repeating_resource_${newrowid}_resource_${side}_max`] = max;
+ update[`repeating_resource_${newrowid}_resource_${side}`] = current;
+ setAttrs(update);
+ };
+
+ getAttrs(["other_resource_name"], (v) => {
+ //Use other_resource if it is empty or same name:
+ if (
+ !v.other_resource_name ||
+ v.other_resource_name == "" ||
+ v.other_resource_name == name
+ ) {
+ let update = {};
+ update[`other_resource_name`] = name;
+ update[`other_resource_max`] = max;
+ update[`other_resource`] = current;
+ setAttrs(update);
+ //If other_resource is populated look through the repeating sections:
+ } else {
+ getSectionIDs(`repeating_resource`, (idarray) => {
+ //No resources founds, create one:
+ if (idarray.length == 0) {
+ updateResource(name, max, current);
+ } else {
+ const namesAttributes = idarray
+ .map((id) => {
+ return `repeating_resource_${id}_resource_left_name`;
+ })
+ .concat(
+ idarray.map((id) => {
+ return `repeating_resource_${id}_resource_right_name`;
+ })
+ );
+ getAttrs(namesAttributes, (v) => {
+ let existingID = false;
+ let side = "left";
+ for (const [key, value] of Object.entries(v)) {
+ if (value == name || value == "") {
+ existingID = SheetUtils.getUID(key);
+ if (key.includes("_right_")) side = "right";
+ break;
+ }
+ }
+ //Existing resource found, updated it:
+ if (existingID) {
+ updateResource(name, max, current, side, existingID);
+ //No matching resource found, create one:
+ } else {
+ updateResource(name, max, current, side);
+ }
+ });
+ }
+ });
+ }
+ });
+};
+
+const deleteResource = (name) => {
+ const updateResource = (name, max, current, side, id) => {
+ const newrowid = id || generateRowID();
+ let update = {};
+ update[`repeating_resource_${newrowid}_resource_${side}_name`] = name;
+ update[`repeating_resource_${newrowid}_resource_${side}_max`] = max;
+ update[`repeating_resource_${newrowid}_resource_${side}`] = current;
+ setAttrs(update);
+ };
+ getAttrs(["other_resource_name"], (v) => {
+ if (v.other_resource_name && v.other_resource_name == name) {
+ let update = {};
+ update[`other_resource_name`] = "";
+ update[`other_resource_max`] = "";
+ update[`other_resource`] = "";
+ setAttrs(update);
+ //If other_resource is populated look through the repeating sections:
+ } else {
+ getSectionIDs(`repeating_resource`, (idarray) => {
+ //No resources founds, create one:
+ if (idarray.length > 0) {
+ const namesAttributes = idarray
+ .map((id) => {
+ return `repeating_resource_${id}_resource_left_name`;
+ })
+ .concat(
+ idarray.map((id) => {
+ return `repeating_resource_${id}_resource_right_name`;
+ })
+ );
+ getAttrs(namesAttributes, (v) => {
+ let existingID = false;
+ let side = "left";
+ for (const [key, value] of Object.entries(v)) {
+ if (value == name) existingID = SheetUtils.getUID(key);
+ if (key.includes("_right_")) side = "right";
+ break;
+ }
+ if (existingID) {
+ if (
+ side == "right" &&
+ !v[`repeating_resource_${existingID}_resource_left_name`]
+ ) {
+ removeRepeatingRow(`repeating_resource_${existingID}`);
+ } else if (
+ side == "left" &&
+ !v[`repeating_resource_${existingID}_resource_right_name`]
+ ) {
+ removeRepeatingRow(`repeating_resource_${existingID}`);
+ } else {
+ let update = {};
+ update[
+ `repeating_resource_${existingID}_resource_${side}_name`
+ ] = "";
+ update[
+ `repeating_resource_${existingID}_resource_${side}_max`
+ ] = "";
+ update[`repeating_resource_${existingID}_resource_${side}`] =
+ "";
+ update[
+ `repeating_resource_${existingID}_resource_${side}_itemid`
+ ] = "";
+ setAttrs(update);
+ }
+ }
+ });
+ }
+ });
+ }
+ });
+};
+
+const remove_resource = (id) => {
+ const attr = id === "other_resource" ? id : `repeating_resource_${id}_itemid`;
+ let update = {};
+ getAttrs([`${attr}`], (v) => {
+ const itemid = v[`${attr}`];
+ if (id == "other_resource") {
+ update["other_resource"] = "";
+ update["other_resource_name"] = "";
+ update["other_resource_itemid"] = "";
+ setAttrs(update, { silent: true });
+ } else {
+ const currentID = id.replace("repeating_resource_", "").substring(0, 20);
+ const side = id.includes("left") ? `right` : `left`;
+ //Get the inputs for the opposite side to see if they are empty.
+ //If they are empty delete the entire row. Otherwise set the side that was the source of this event to empty strings
+ getAttrs(
+ [
+ `repeating_resource_${currentID}_resource_${side}`,
+ `repeating_resource_${currentID}_resource_${side}_name`,
+ `repeating_resource_${currentID}_resource_${side}_max`,
+ ],
+ (v) => {
+ const Name =
+ v[`repeating_resource_${currentID}_resource_${side}_name`] || false;
+ const Value =
+ v[`repeating_resource_${currentID}_resource_${side}`] || false;
+ const Max =
+ v[`repeating_resource_${currentID}_resource_${side}_max`] || false;
+ if (!Name && !Value && !Max) {
+ if (currentID)
+ removeRepeatingRow(`repeating_resource_${currentID}`);
+ } else {
+ update[`repeating_resource_${id}`] = "";
+ update[`repeating_resource_${id}_name`] = "";
+ update[`repeating_resource_${id}_max`] = "";
+ update[`repeating_resource_${id}_itemid`] = "";
+ }
+ setAttrs(update, { silent: true });
+ }
+ );
+ }
+ });
+};
+
+const update_weight = function () {
+ let update = {};
+ let wtotal = 0;
+ let weight_attrs = [
+ "cp",
+ "sp",
+ "ep",
+ "gp",
+ "pp",
+ "encumbrance_setting",
+ "strength",
+ "size",
+ "carrying_capacity_mod",
+ "powerful_build",
+ "ingore_non_equipped_weight",
+ ];
+ getSectionIDs("repeating_inventory", (idarray) => {
+ _.each(idarray, (currentID, i) => {
+ weight_attrs.push(`repeating_inventory_${currentID}_itemweight`);
+ weight_attrs.push(`repeating_inventory_${currentID}_itemcount`);
+ weight_attrs.push(`repeating_inventory_${currentID}_equipped`);
+ });
+ getAttrs(weight_attrs, (v) => {
+ let coinWeight = 0;
+ ["cp", "sp", "ep", "gp", "pp"].forEach((type) => {
+ coinWeight +=
+ isNaN(parseInt(v[`${type}`], 10)) === false
+ ? parseInt(v[`${type}`], 10)
+ : 0;
+ });
+ wtotal = wtotal + coinWeight / 50;
+
+ _.each(idarray, (currentID, i) => {
+ if (
+ v["ingore_non_equipped_weight"] &&
+ v["ingore_non_equipped_weight"] == 1 &&
+ (!v[`repeating_inventory_${currentID}_equipped`] ||
+ v[`repeating_inventory_${currentID}_equipped`] != 1)
+ )
+ return;
+ if (
+ v[`repeating_inventory_${currentID}_itemweight`] &&
+ isNaN(
+ parseInt(v[`repeating_inventory_${currentID}_itemweight`], 10)
+ ) === false
+ ) {
+ count =
+ v[`repeating_inventory_${currentID}_itemcount`] &&
+ isNaN(
+ parseFloat(v[`repeating_inventory_${currentID}_itemcount`])
+ ) === false
+ ? parseFloat(v[`repeating_inventory_${currentID}_itemcount`])
+ : 1;
+ wtotal =
+ wtotal +
+ parseFloat(v[`repeating_inventory_${currentID}_itemweight`]) *
+ count;
+ }
+ });
+
+ update["weighttotal"] =
+ wtotal % 1 === 0 ? wtotal : parseFloat(wtotal.toFixed(2));
+
+ const str_base = parseInt(v.strength, 10);
+ let size_multiplier = 1;
+ if (v["size"]) {
+ const size = v["size"].toLowerCase().trim();
+ const sizeLookup = {
+ tiny: 0.5,
+ medium: 1,
+ large: 2,
+ huge: 4,
+ gargantuan: 8,
+ };
+ const sizeIndex = Object.keys(sizeLookup).indexOf(size);
+ size_multiplier = sizeIndex > -1 ? sizeLookup[size] : size_multiplier;
+ if (v["powerful_build"] && v["powerful_build"] == 1 && sizeIndex > -1) {
+ size_multiplier *= 2;
+ }
+ }
+ let str = str_base * size_multiplier;
+ // Parse the carrying capacitiy modificator if any
+ if (v.carrying_capacity_mod) {
+ const operator = v.carrying_capacity_mod.substring(0, 1);
+ const value = v.carrying_capacity_mod.substring(1);
+ if (
+ ["*", "x", "+", "-"].indexOf(operator) > -1 &&
+ isNaN(parseFloat(value, 10)) === false
+ ) {
+ str =
+ operator === "*" || operator == "x"
+ ? str * parseFloat(value, 10)
+ : operator === "+"
+ ? str + parseFloat(value, 10)
+ : operator === "-"
+ ? str - parseFloat(value, 10)
+ : str;
+ }
+ }
+
+ if (!v.encumbrance_setting || v.encumbrance_setting === "off") {
+ update["encumbrance"] =
+ wtotal > str * 15 ? "OVER CARRYING CAPACITY" : " ";
+ } else if (v.encumbrance_setting === "on") {
+ update["encumbrance"] =
+ wtotal > str * 15
+ ? "IMMOBILE"
+ : wtotal > str * 10
+ ? "HEAVILY ENCUMBERED"
+ : wtotal > str * 5
+ ? "ENCUMBERED"
+ : " ";
+ } else {
+ update["encumbrance"] = " ";
+ }
+
+ setAttrs(update, { silent: true });
+ });
+ });
+};
+
+var update_ac = function () {
+ getAttrs(["custom_ac_flag"], function (v) {
+ if (v.custom_ac_flag === "2") {
+ return;
+ } else {
+ var update = {};
+ var ac_attrs = [
+ "simpleinventory",
+ "custom_ac_base",
+ "custom_ac_part1",
+ "custom_ac_part2",
+ "strength_mod",
+ "dexterity_mod",
+ "constitution_mod",
+ "intelligence_mod",
+ "wisdom_mod",
+ "charisma_mod",
+ "custom_ac_shield",
+ ];
+ getSectionIDs("repeating_acmod", function (acidarray) {
+ _.each(acidarray, function (currentID, i) {
+ ac_attrs.push("repeating_acmod_" + currentID + "_global_ac_val");
+ ac_attrs.push(
+ "repeating_acmod_" + currentID + "_global_ac_active_flag"
+ );
+ });
+ getSectionIDs("repeating_inventory", function (idarray) {
+ _.each(idarray, function (currentID, i) {
+ ac_attrs.push("repeating_inventory_" + currentID + "_equipped");
+ ac_attrs.push(
+ "repeating_inventory_" + currentID + "_itemmodifiers"
+ );
+ });
+ getAttrs(ac_attrs, function (b) {
+ var custom_total = 0;
+ if (v.custom_ac_flag === "1") {
+ var base =
+ isNaN(parseInt(b.custom_ac_base, 10)) === false
+ ? parseInt(b.custom_ac_base, 10)
+ : 10;
+ var part1attr = b.custom_ac_part1.toLowerCase();
+ var part2attr = b.custom_ac_part2.toLowerCase();
+ var part1 =
+ part1attr === "none" ? 0 : parseInt(b[part1attr + "_mod"], 10);
+ var part2 =
+ part2attr === "none" ? 0 : parseInt(b[part2attr + "_mod"], 10);
+ custom_total = base + part1 + part2;
+ }
+ var globalacmod = 0;
+ _.each(acidarray, function (currentID, i) {
+ if (
+ b["repeating_acmod_" + currentID + "_global_ac_active_flag"] ==
+ "1"
+ ) {
+ globalacmod += parseInt(
+ b["repeating_acmod_" + currentID + "_global_ac_val"],
+ 10
+ );
+ }
+ });
+ var dexmod = +b["dexterity_mod"];
+ var total = 10 + dexmod;
+ var armorcount = 0;
+ var shieldcount = 0;
+ var armoritems = [];
+ if (b.simpleinventory === "complex") {
+ _.each(idarray, function (currentID, i) {
+ if (
+ b["repeating_inventory_" + currentID + "_equipped"] &&
+ b["repeating_inventory_" + currentID + "_equipped"] === "1" &&
+ b["repeating_inventory_" + currentID + "_itemmodifiers"] &&
+ b["repeating_inventory_" + currentID + "_itemmodifiers"]
+ .toLowerCase()
+ .indexOf("ac") > -1
+ ) {
+ var mods =
+ b[
+ "repeating_inventory_" + currentID + "_itemmodifiers"
+ ].split(",");
+ var ac = 0;
+ var type = "mod";
+ _.each(mods, function (mod) {
+ if (mod.substring(0, 10) === "Item Type:") {
+ type = mod.substring(11, mod.length).trim().toLowerCase();
+ }
+ if (
+ mod.toLowerCase().indexOf("ac:") > -1 ||
+ mod.toLowerCase().indexOf("ac +") > -1 ||
+ mod.toLowerCase().indexOf("ac+") > -1
+ ) {
+ var regex = mod.replace(/[^0-9]/g, "");
+ var bonus =
+ regex &&
+ regex.length > 0 &&
+ isNaN(parseInt(regex, 10)) === false
+ ? parseInt(regex, 10)
+ : 0;
+ ac = ac + bonus;
+ }
+ if (
+ mod.toLowerCase().indexOf("ac -") > -1 ||
+ mod.toLowerCase().indexOf("ac-") > -1
+ ) {
+ var regex = mod.replace(/[^0-9]/g, "");
+ var bonus =
+ regex &&
+ regex.length > 0 &&
+ isNaN(parseInt(regex, 10)) === false
+ ? parseInt(regex, 10)
+ : 0;
+ ac = ac - bonus;
+ }
+ });
+ armoritems.push({ type: type, ac: ac });
+ }
+ });
+ armorcount = armoritems.filter(function (item) {
+ return item["type"].indexOf("armor") > -1;
+ }).length;
+ shieldcount = armoritems.filter(function (item) {
+ return item["type"].indexOf("shield") > -1;
+ }).length;
+ var base = dexmod;
+ var armorac = 10;
+ var shieldac = 0;
+ var modac = 0;
+
+ _.each(armoritems, function (item) {
+ if (item["type"].indexOf("light armor") > -1) {
+ armorac = item["ac"];
+ base = dexmod;
+ } else if (item["type"].indexOf("medium armor") > -1) {
+ armorac = item["ac"];
+ base = Math.min(dexmod, 2);
+ } else if (item["type"].indexOf("heavy armor") > -1) {
+ armorac = item["ac"];
+ base = 0;
+ } else if (item["type"].indexOf("shield") > -1) {
+ shieldac = item["ac"];
+ } else {
+ modac = modac + item["ac"];
+ }
+ });
+
+ total = base + armorac + shieldac + modac;
+ }
+ update["armorwarningflag"] = "hide";
+ update["customacwarningflag"] = "hide";
+ if (armorcount > 1 || shieldcount > 1) {
+ update["armorwarningflag"] = "show";
+ }
+ update["ac"] = total + globalacmod;
+ if (custom_total > 0) {
+ if (
+ armorcount > 0 ||
+ (shieldcount > 0 && b.custom_ac_shield != "yes")
+ ) {
+ update["customacwarningflag"] = "show";
+ } else {
+ update["ac"] =
+ b.custom_ac_shield == "yes"
+ ? custom_total + shieldac + globalacmod + modac
+ : custom_total + globalacmod + modac;
+ }
+ }
+ setAttrs(update, { silent: true });
+ });
+ });
+ });
+ }
+ });
+};
+
+var check_customac = function (attr) {
+ getAttrs(
+ ["custom_ac_flag", "custom_ac_part1", "custom_ac_part2"],
+ function (v) {
+ if (
+ v["custom_ac_flag"] &&
+ v["custom_ac_flag"] === "1" &&
+ ((v["custom_ac_part1"] && v["custom_ac_part1"] === attr) ||
+ (v["custom_ac_part2"] && v["custom_ac_part2"] === attr))
+ ) {
+ update_ac();
+ }
+ }
+ );
+};
+
+const update_initiative = () => {
+ const attrs_to_get = [
+ "dexterity",
+ "dexterity_mod",
+ "initmod",
+ "jack_of_all_trades",
+ "jack",
+ "init_tiebreaker",
+ "pb_type",
+ ];
+ getSectionIDs("repeating_inventory", (idarray) => {
+ _.each(idarray, (currentID) => {
+ attrs_to_get.push(`repeating_inventory_${currentID}_equipped`);
+ attrs_to_get.push(`repeating_inventory_${currentID}_itemmodifiers`);
+ });
+ getAttrs(attrs_to_get, (v) => {
+ let update = {};
+ let final_init = parseInt(v["dexterity_mod"], 10);
+ if (v["initmod"] && !isNaN(parseInt(v["initmod"], 10))) {
+ final_init = final_init + parseInt(v["initmod"], 10);
+ }
+ if (v["init_tiebreaker"] && v["init_tiebreaker"] != 0) {
+ final_init = final_init + parseInt(v["dexterity"], 10) / 100;
+ }
+ if (v["jack_of_all_trades"] && v["jack_of_all_trades"] != 0) {
+ if (v["pb_type"] && v["pb_type"] === "die" && v["jack"]) {
+ final_init = final_init + "+" + v["jack"];
+ } else if (v["jack"] && !isNaN(parseInt(v["jack"], 10))) {
+ final_init = final_init + parseInt(v["jack"], 10);
+ }
+ }
+ _.each(idarray, (currentID) => {
+ if (
+ v[`repeating_inventory_${currentID}_equipped`] &&
+ v[`repeating_inventory_${currentID}_equipped`] === "1" &&
+ v[`repeating_inventory_${currentID}_itemmodifiers`] &&
+ v[`repeating_inventory_${currentID}_itemmodifiers`]
+ .toLowerCase()
+ .indexOf("ability checks") > -1
+ ) {
+ const mods = v[`repeating_inventory_${currentID}_itemmodifiers`]
+ .toLowerCase()
+ .split(",");
+ _.each(mods, (mod) => {
+ if (mod.indexOf("ability checks") > -1) {
+ const new_mod = !isNaN(parseInt(mod.replace(/[^0-9]/g, ""), 10))
+ ? parseInt(mod.replace(/[^0-9]/g, ""), 10)
+ : false;
+ final_init =
+ mod.indexOf("-") > -1 && new_mod
+ ? final_init - new_mod
+ : new_mod
+ ? final_init + new_mod
+ : final_init;
+ }
+ });
+ }
+ });
+ if (final_init % 1 != 0) {
+ final_init = parseFloat(final_init.toPrecision(12)); // ROUNDING ERROR BUGFIX
+ }
+ update["initiative_bonus"] = final_init;
+ setAttrs(update, { silent: true });
+ });
+ });
+};
+
+const update_class = () => {
+ getAttrs(
+ [
+ "class",
+ "base_level",
+ "custom_class",
+ "cust_hitdietype",
+ "cust_spellcasting_ability",
+ "cust_strength_save_prof",
+ "cust_dexterity_save_prof",
+ "cust_constitution_save_prof",
+ "cust_intelligence_save_prof",
+ "cust_wisdom_save_prof",
+ "cust_charisma_save_prof",
+ "npc",
+ ],
+ (v) => {
+ if (v.npc && v.npc == "1") {
+ return;
+ }
+ const abilites = [
+ "Strength",
+ "Dexterity",
+ "Constitution",
+ "Intelligence",
+ "Wisdom",
+ "Charisma",
+ ];
+ //Custom Classes
+ if (v.custom_class && v.custom_class != "0") {
+ update = {};
+ update["hitdietype"] = v.cust_hitdietype;
+ update["hitdieroll"] = v.cust_hitdietype;
+ update["spellcasting_ability"] = v.cust_spellcasting_ability;
+ abilites.forEach((save) => {
+ const ability = save.toLowerCase();
+ update[`${ability}_save_prof`] = v[`cust_${ability}_save_prof`];
+ });
+ setAttrs(update, { silent: true });
+ //If "Choose" has been selected in the select
+ } else if (v.class === "") {
+ update = {};
+ update["hitdietype"] = 4;
+ update["hitdieroll"] = 4;
+ update["spellcasting_ability"] = "0*";
+ abilites.forEach((save) => {
+ const ability = save.toLowerCase();
+ update[`${ability}_save_prof`] = 0;
+ });
+ setAttrs(update, { silent: true });
+ //Standard classes can pull their data from the Comependium
+ } else {
+ getCompendiumPage(v.class, (pages) => {
+ pages = removeDuplicatedPageData(pages);
+ update = {};
+ const classPages = Array.isArray(pages) ? pages : [pages];
+ classPages.forEach((classData) => {
+ if (
+ classData.data &&
+ "Category" in classData.data &&
+ classData.data[`Category`] === "Classes"
+ ) {
+ update["hitdietype"] = classData.data["Hit Die"].slice(1);
+ update["hitdieroll"] = classData.data["Hit Die"].slice(1);
+ update["spellcasting_ability"] = classData.data[
+ "Spellcasting Ability"
+ ]
+ ? `@{${classData.data[
+ "Spellcasting Ability"
+ ].toLowerCase()}_mod}+`
+ : "0*";
+ abilites.forEach((save) => {
+ const ability = save.toLowerCase();
+ update[`${ability}_save_prof`] =
+ classData.data["data-Saving Throws"].indexOf(`${save}`) > -1
+ ? "(@{pb})"
+ : 0;
+ update_save(ability);
+ });
+ }
+
+ setAttrs(update, { silent: true });
+ //Update Spell info to change or remove casting attributes in Spells
+ update_spell_info();
+ });
+ });
+ }
+ }
+ );
+ set_level();
+};
+
+const update_hds = (source) => {
+ var newPool = {};
+ Object.keys(source).forEach((dieType) => {
+ newPool[`d${dieType}`] = {
+ size: source[dieType],
+ };
+ });
+ getHitDicePool((allPool) => {
+ let hd = 0;
+ let hdMax = 0;
+ const existingPool = Object.keys(allPool).filter((die) => {
+ return Object.keys(newPool).indexOf(die) > -1;
+ });
+ Object.keys(newPool).forEach((die) => {
+ if (existingPool.indexOf(die) > -1) {
+ const pool = allPool[die];
+ const poolUpdate = newPool[die];
+ const previousValue = pool.size;
+ const newValue = poolUpdate.size;
+ const gained =
+ poolUpdate.size < pool.available
+ ? poolUpdate.size - pool.available
+ : Math.max(newValue - previousValue, 0);
+ const available = pool.available + gained;
+ newPool[die]["available"] = available;
+ } else {
+ newPool[die]["available"] = newPool[die]["size"];
+ }
+ hd += newPool[die]["available"];
+ hdMax += newPool[die]["size"];
+ });
+ setAttrs({ hit_dice: hd, hit_dice_max: hdMax }, { silent: true }, () => {
+ updateHitDicePool(newPool, true);
+ });
+ });
+};
+
+const set_level = function () {
+ getAttrs(
+ [
+ "level",
+ "class",
+ "arcane_fighter",
+ "arcane_rogue",
+ "cust_classname",
+ "level_calculations",
+ "class",
+ "subclass",
+ "hitdietype",
+ "use_per_class_hit_dice",
+ ],
+ (v) => {
+ let update = {};
+ let callbacks = [];
+ const finalclass = v["class"];
+ let finallevel = v["level"];
+ const charclass = v[`class`];
+ let hitdie_final = "@{hitdietype}";
+ const subclass = v[`subclass`] ? v[`subclass`] + " " : "";
+ const casterlevel = finallevel;
+ let hitDicePool = {};
+ hitDicePool[v["hitdietype"]] = finallevel;
+
+ // This nested array is used to determine the overall spellcasting level for the character.
+ var classes = [[finalclass.toLowerCase(), v[`level`]]];
+
+ update["hitdice"] = finallevel;
+ update["caster_level"] = casterlevel;
+ update["hitdice_max"] = finallevel;
+
+ callbacks.push(() => {
+ update_spell_slots();
+ });
+ callbacks.push(() => {
+ update_pb();
+ });
+ // callbacks.push(() => {
+ // update_leveler_display();
+ // });
+
+ setAttrs(update, { silent: true }, () => {
+ callbacks.forEach((callback) => {
+ callback();
+ });
+ });
+ }
+ );
+};
+
+var isMultiCaster = function (classes, arcane_fighter, arcane_rogue) {
+ var singlecaster = false;
+ var multicaster = false;
+ _.each(classes, function (multiclass) {
+ var caster =
+ getCasterType(
+ multiclass[0],
+ multiclass[1],
+ arcane_fighter,
+ arcane_rogue
+ ) > 0;
+ if (caster && singlecaster) {
+ multicaster = true;
+ } else if (caster) {
+ singlecaster = true;
+ }
+ });
+ return multicaster;
+};
+
+var getCasterType = function (
+ class_string,
+ levels,
+ arcane_fighter,
+ arcane_rogue
+) {
+ var full = ["bard", "cleric", "druid", "sorcerer", "wizard", "full"];
+ var half = ["artificer", "paladin", "ranger", "half"];
+ class_string = class_string.toLowerCase();
+ if (full.indexOf(class_string) != -1) {
+ return 1;
+ } else if (half.indexOf(class_string) != -1) {
+ if (class_string === "artificer" && levels == 1) return 1;
+ return levels == 1 ? 0 : 1 / 2;
+ } else if (
+ class_string === "third" ||
+ (class_string === "fighter" && arcane_fighter == 1) ||
+ (class_string === "rogue" && arcane_rogue == 1)
+ ) {
+ return levels == 1 || levels == 2 ? 0 : 1 / 3;
+ } else {
+ return 0;
+ }
+};
+
+var checkCasterLevel = function (classes, arcane_fighter, arcane_rogue) {
+ var multicaster = isMultiCaster(classes, arcane_fighter, arcane_rogue);
+ var totalcasterlevel = 0;
+ _.each(classes, function (multiclass) {
+ var casterlevel =
+ parseInt(multiclass[1], 10) *
+ getCasterType(multiclass[0], multiclass[1], arcane_fighter, arcane_rogue);
+ // Characters with multiple spellcasting classes round down the casting level for that class
+ // Character with a single spellcasting class round up the casting level
+ totalcasterlevel =
+ totalcasterlevel +
+ (multicaster ? Math.floor(casterlevel) : Math.ceil(casterlevel));
+ });
+ return totalcasterlevel;
+};
+
+var checkHitDie = function (class_string) {
+ var d10class = ["fighter", "paladin", "ranger"];
+ var d8class = [
+ "artificer",
+ "bard",
+ "cleric",
+ "druid",
+ "monk",
+ "rogue",
+ "warlock",
+ ];
+ var d6class = ["sorcerer", "wizard"];
+ class_string = class_string.toLowerCase();
+ if (class_string === "barbarian") {
+ return "12";
+ } else if (d10class.indexOf(class_string) != -1) {
+ return "10";
+ } else if (d8class.indexOf(class_string) != -1) {
+ return "8";
+ } else if (d6class.indexOf(class_string) != -1) {
+ return "6";
+ } else {
+ return "0";
+ }
+};
+
+var update_leveler_display = function () {
+ getAttrs(["experience", "level"], function (v) {
+ let lvl = 0;
+ let exp = 0;
+ let update = {};
+ const xpLookup = [
+ 0, 300, 900, 2700, 6500, 14000, 23000, 34000, 48000, 64000, 85000, 100000,
+ 120000, 140000, 165000, 195000, 225000, 265000, 305000, 355000,
+ ];
+ update["showleveler"] = 0;
+ update["invalidXP"] = 0;
+ if (
+ v["level"] &&
+ !isNaN(parseInt(v["level"], 10)) &&
+ parseInt(v["level"], 10) > 0
+ ) {
+ lvl = parseInt(v["level"], 10);
+ }
+ if (v["experience"]) {
+ let sanitizedXP = SheetUtils.sanitizeXP(v["experience"]);
+ if (!sanitizedXP) {
+ update["invalidXP"] = 1;
+ } else if (Array.isArray(sanitizedXP) && sanitizedXP.length > 0) {
+ exp = sanitizedXP[0];
+ }
+ }
+ if (lvl > 0 && lvl < xpLookup.length && exp > 0) {
+ if (exp >= xpLookup[lvl]) update["showleveler"] = 1;
+ }
+ setAttrs(update, { silent: true });
+ });
+};
+
+const get_spells_slots = (casterLvl, pactMagicLvl) => {
+ const casterSlots = [
+ [0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [2, 0, 0, 0, 0, 0, 0, 0, 0],
+ [3, 0, 0, 0, 0, 0, 0, 0, 0],
+ [4, 2, 0, 0, 0, 0, 0, 0, 0],
+ [4, 3, 0, 0, 0, 0, 0, 0, 0],
+ [4, 3, 2, 0, 0, 0, 0, 0, 0],
+ [4, 3, 3, 0, 0, 0, 0, 0, 0],
+ [4, 3, 3, 1, 0, 0, 0, 0, 0],
+ [4, 3, 3, 2, 0, 0, 0, 0, 0],
+ [4, 3, 3, 3, 1, 0, 0, 0, 0],
+ [4, 3, 3, 3, 2, 0, 0, 0, 0],
+ [4, 3, 3, 3, 2, 1, 0, 0, 0],
+ [4, 3, 3, 3, 2, 1, 0, 0, 0],
+ [4, 3, 3, 3, 2, 1, 1, 0, 0],
+ [4, 3, 3, 3, 2, 1, 1, 0, 0],
+ [4, 3, 3, 3, 2, 1, 1, 1, 0],
+ [4, 3, 3, 3, 2, 1, 1, 1, 0],
+ [4, 3, 3, 3, 2, 1, 1, 1, 1],
+ [4, 3, 3, 3, 3, 1, 1, 1, 1],
+ [4, 3, 3, 3, 3, 2, 1, 1, 1],
+ [4, 3, 3, 3, 3, 2, 2, 1, 1],
+ ];
+ const pactMagicSlots = [
+ [0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [1, 0, 0, 0, 0, 0, 0, 0, 0],
+ [2, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 2, 0, 0, 0, 0, 0, 0, 0],
+ [0, 2, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 2, 0, 0, 0, 0, 0, 0],
+ [0, 0, 2, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 2, 0, 0, 0, 0, 0],
+ [0, 0, 0, 2, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 2, 0, 0, 0, 0],
+ [0, 0, 0, 0, 2, 0, 0, 0, 0],
+ [0, 0, 0, 0, 3, 0, 0, 0, 0],
+ [0, 0, 0, 0, 3, 0, 0, 0, 0],
+ [0, 0, 0, 0, 3, 0, 0, 0, 0],
+ [0, 0, 0, 0, 3, 0, 0, 0, 0],
+ [0, 0, 0, 0, 3, 0, 0, 0, 0],
+ [0, 0, 0, 0, 3, 0, 0, 0, 0],
+ [0, 0, 0, 0, 4, 0, 0, 0, 0],
+ [0, 0, 0, 0, 4, 0, 0, 0, 0],
+ [0, 0, 0, 0, 4, 0, 0, 0, 0],
+ [0, 0, 0, 0, 4, 0, 0, 0, 0],
+ ];
+ const slots = casterSlots[casterLvl].map((slots, level) => {
+ return slots + pactMagicSlots[pactMagicLvl][level];
+ });
+ return slots
+};
+const update_spell_slots = () => {
+ const request = [
+ "level",
+ "lvl1_slots_mod",
+ "lvl2_slots_mod",
+ "lvl3_slots_mod",
+ "caster_level",
+ "class"
+ ];
+ getAttrs(request, (response) => {
+ const level = response.level;
+ const moveslots = (level == 1) ? 2 :
+ (level == 2) ? 2 :
+ (level == 3) ? 3 :
+ (level == 4) ? 3 :
+ (level == 5) ? 4 :
+ (level == 6) ? 4 :
+ 0;
+ const totalSlots = get_spells_slots(+response.caster_level, 0);
+ const update = {};
+ update["moves_total"] = moveslots;
+ if (response.caster_level == 0) {
+ for (let i = 1; i <= 3; i++) {
+ update[`lvl${i}_slots_total`] = 0;
+ }
+ } else {
+ for (let i = 1; i <= 3; i++) {
+ update[`lvl${i}_slots_total`] = totalSlots[i - 1];
+ }
+ }
+ setAttrs(update, {silent:true})
+ })
+};
+
+var update_pb = function () {
+ callbacks = [];
+ getAttrs(["level", "pb_type", "pb_custom"], function (v) {
+ var update = {};
+ var pb = 2;
+ var lvl = parseInt(v["level"], 10);
+ if (lvl < 5) {
+ pb = "2";
+ } else if (lvl < 9) {
+ pb = "3";
+ } else if (lvl < 13) {
+ pb = "4";
+ } else if (lvl < 17) {
+ pb = "5";
+ } else {
+ pb = "6";
+ }
+ var jack = Math.floor(pb / 2);
+ if (v["pb_type"] === "die") {
+ update["jack"] = "d" + pb;
+ update["pb"] = "d" + pb * 2;
+ update["pbd_safe"] = "cs0cf0";
+ } else if (
+ v["pb_type"] === "custom" &&
+ v["pb_custom"] &&
+ v["pb_custom"] != ""
+ ) {
+ update["pb"] = v["pb_custom"];
+ update["jack"] = !isNaN(parseInt(v["pb_custom"], 10))
+ ? Math.floor(parseInt(v["pb_custom"], 10) / 2)
+ : jack;
+ update["pbd_safe"] = "";
+ } else {
+ update["pb"] = pb;
+ update["jack"] = jack;
+ update["pbd_safe"] = "";
+ }
+ callbacks.push(function () {
+ update_attacks("all");
+ });
+ callbacks.push(function () {
+ update_spell_info();
+ });
+ callbacks.push(function () {
+ update_jack_attr();
+ });
+ callbacks.push(function () {
+ update_initiative();
+ });
+ callbacks.push(function () {
+ update_tool("all");
+ });
+ callbacks.push(function () {
+ update_all_saves();
+ });
+ callbacks.push(function () {
+ update_skills([
+ "athletics",
+ "acrobatics",
+ "sleight_of_hand",
+ "stealth",
+ "arcana",
+ "history",
+ "investigation",
+ "nature",
+ "religion",
+ "animal_handling",
+ "insight",
+ "medicine",
+ "perception",
+ "survival",
+ "deception",
+ "intimidation",
+ "performance",
+ "persuasion",
+ ]);
+ });
+
+ setAttrs(update, { silent: true }, function () {
+ callbacks.forEach(function (callback) {
+ callback();
+ });
+ });
+ });
+};
+
+var update_jack_attr = function () {
+ var update = {};
+ getAttrs(["jack_of_all_trades", "jack"], function (v) {
+ if (v["jack_of_all_trades"] && v["jack_of_all_trades"] != 0) {
+ update["jack_bonus"] = "+" + v["jack"];
+ update["jack_attr"] = "+" + v["jack"] + "@{pbd_safe}";
+ } else {
+ update["jack_bonus"] = "";
+ update["jack_attr"] = "";
+ }
+ setAttrs(update, { silent: true });
+ });
+};
+
+var update_spell_info = function (attr) {
+ var update = {};
+ getAttrs(
+ [
+ "spellcasting_ability",
+ "spell_dc_mod",
+ "globalmagicmod",
+ "strength_mod",
+ "dexterity_mod",
+ "constitution_mod",
+ "intelligence_mod",
+ "wisdom_mod",
+ "charisma_mod",
+ ],
+ function (v) {
+ if (
+ attr &&
+ v["spellcasting_ability"] &&
+ v["spellcasting_ability"].indexOf(attr) === -1
+ ) {
+ return;
+ }
+ if (
+ !v["spellcasting_ability"] ||
+ (v["spellcasting_ability"] && v["spellcasting_ability"] === "0*")
+ ) {
+ update["spell_attack_bonus"] = "0";
+ update["spell_save_dc"] = "0";
+ var callback = function () {
+ update_attacks("spells");
+ };
+ setAttrs(update, { silent: true }, callback);
+ return;
+ }
+ var attr = attr ? attr : "";
+
+ var ability = parseInt(
+ v[
+ v["spellcasting_ability"].substring(
+ 2,
+ v["spellcasting_ability"].length - 2
+ )
+ ],
+ 10
+ );
+ var spell_mod =
+ v["globalmagicmod"] && !isNaN(parseInt(v["globalmagicmod"], 10))
+ ? parseInt(v["globalmagicmod"], 10)
+ : 0;
+ var atk =
+ v["globalmagicmod"] && !isNaN(parseInt(v["globalmagicmod"], 10))
+ ? ability + parseInt(v["globalmagicmod"], 10)
+ : ability;
+ var dc =
+ v["spell_dc_mod"] && !isNaN(parseInt(v["spell_dc_mod"], 10))
+ ? 8 + ability + parseInt(v["spell_dc_mod"], 10)
+ : 8 + ability;
+ var itemfields = ["pb_type", "pb"];
+
+ getSectionIDs("repeating_inventory", function (idarray) {
+ _.each(idarray, function (currentID, i) {
+ itemfields.push("repeating_inventory_" + currentID + "_equipped");
+ itemfields.push(
+ "repeating_inventory_" + currentID + "_itemmodifiers"
+ );
+ });
+ getAttrs(itemfields, function (v) {
+ _.each(idarray, function (currentID) {
+ if (
+ (!v["repeating_inventory_" + currentID + "_equipped"] ||
+ v["repeating_inventory_" + currentID + "_equipped"] === "1") &&
+ v["repeating_inventory_" + currentID + "_itemmodifiers"] &&
+ v["repeating_inventory_" + currentID + "_itemmodifiers"]
+ .toLowerCase()
+ .indexOf("spell" > -1)
+ ) {
+ var mods = v[
+ "repeating_inventory_" + currentID + "_itemmodifiers"
+ ]
+ .toLowerCase()
+ .split(",");
+ _.each(mods, function (mod) {
+ if (mod.indexOf("spell attack") > -1) {
+ var substr = mod.slice(
+ mod.lastIndexOf("spell attack") + "spell attack".length
+ );
+ atk =
+ substr && substr.length > 0 && !isNaN(parseInt(substr, 10))
+ ? atk + parseInt(substr, 10)
+ : atk;
+ spell_mod =
+ substr && substr.length > 0 && !isNaN(parseInt(substr, 10))
+ ? spell_mod + parseInt(substr, 10)
+ : spell_mod;
+ }
+ if (mod.indexOf("spell dc") > -1) {
+ var substr = mod.slice(
+ mod.lastIndexOf("spell dc") + "spell dc".length
+ );
+ dc =
+ substr && substr.length > 0 && !isNaN(parseInt(substr, 10))
+ ? dc + parseInt(substr, 10)
+ : dc;
+ }
+ });
+ }
+ });
+
+ if (v["pb_type"] && v["pb_type"] === "die") {
+ atk = atk + "+" + v["pb"];
+ //Fixing Spell DC when using type Die
+ //By Miguel
+ //Used to be equals to: dc + parseInt(v["pb"].substring(1), 10) / 2
+ dc = dc + "+" + v["pb"];
+ } else {
+ atk = parseInt(atk, 10) + parseInt(v["pb"], 10);
+ dc = parseInt(dc, 10) + parseInt(v["pb"], 10);
+ }
+ update["spell_attack_mod"] = spell_mod;
+ update["spell_attack_bonus"] = atk;
+ update["spell_save_dc"] = dc;
+ var callback = function () {
+ update_attacks("spells");
+ };
+ setAttrs(update, { silent: true }, callback);
+ });
+ });
+ }
+ );
+};
+
+var update_passive_perception = function () {
+ getAttrs(
+ ["pb_type", "passiveperceptionmod", "perception_bonus"],
+ function (v) {
+ var passive_perception = 10;
+ var mod = !isNaN(parseInt(v["passiveperceptionmod"], 10))
+ ? parseInt(v["passiveperceptionmod"], 10)
+ : 0;
+ var bonus = !isNaN(parseInt(v["perception_bonus"], 10))
+ ? parseInt(v["perception_bonus"], 10)
+ : 0;
+ if (
+ v["pb_type"] &&
+ v["pb_type"] === "die" &&
+ v["perception_bonus"] &&
+ isNaN(v["perception_bonus"]) &&
+ v["perception_bonus"].indexOf("+") > -1
+ ) {
+ var pieces = v["perception_bonus"].split(/\+|d/);
+ var base = !isNaN(parseInt(pieces[0], 10))
+ ? parseInt(pieces[0], 10)
+ : 0;
+ var num_dice = !isNaN(parseInt(pieces[1], 10))
+ ? parseInt(pieces[1], 10)
+ : 1;
+ var half_pb_die = !isNaN(parseInt(pieces[2], 10))
+ ? parseInt(pieces[2], 10) / 2
+ : 2;
+ bonus = base + num_dice * half_pb_die;
+ }
+ passive_perception = passive_perception + bonus + mod;
+ setAttrs({ passive_wisdom: passive_perception });
+ }
+ );
+};
+
+var update_race_display = function () {
+ getAttrs(["race", "subrace"], function (v) {
+ var final_race = "";
+ final_race = v.subrace ? v.subrace : v.race;
+ if (v.race.toLowerCase() === "dragonborn") {
+ final_race = v.race;
+ }
+ setAttrs({ race_display: final_race });
+ });
+};
+
+var organize_section_proficiencies = function () {
+ getSectionIDs("proficiencies", function (ids) {
+ var attribs = ["_reporder_repeating_proficiencies"];
+ _.each(ids, function (id) {
+ attribs.push("repeating_proficiencies_" + id + "_prof_type");
+ attribs.push("repeating_proficiencies_" + id + "_name");
+ });
+
+ getAttrs(attribs, function (v) {
+ var final_array = _(ids)
+ .chain()
+ .sortBy(function (id) {
+ return v["repeating_proficiencies_" + id + "_name"];
+ })
+ .sortBy(function (id) {
+ return v["repeating_proficiencies_" + id + "_prof_type"];
+ })
+ .value();
+ _.each(final_array, function (id) {});
+ if (final_array && final_array.length > 0) {
+ setSectionOrder("proficiencies", final_array);
+ }
+ });
+ });
+};
+
+const update_challenge = () => {
+ getAttrs(["npc_challenge"], (v) => {
+ let update = {};
+ const challengeRatingsXP = {
+ 0: "10",
+ "1/8": "25",
+ "1/4": "50",
+ "1/2": "100",
+ 1: "200",
+ 2: "450",
+ 3: "700",
+ 4: "1100",
+ 5: "1800",
+ 6: "2300",
+ 7: "2900",
+ 8: "3900",
+ 9: "5000",
+ 10: "5900",
+ 11: "7200",
+ 12: "8400",
+ 13: "10000",
+ 14: "11500",
+ 15: "13000",
+ 16: "15000",
+ 17: "18000",
+ 18: "20000",
+ 19: "22000",
+ 20: "25000",
+ 21: "33000",
+ 22: "41000",
+ 23: "50000",
+ 24: "62000",
+ 25: "75000",
+ 26: "90000",
+ 27: "105000",
+ 28: "120000",
+ 29: "135000",
+ 30: "155000",
+ };
+
+ const xp = parseInt(challengeRatingsXP[v.npc_challenge]) || 0;
+ const pb =
+ xp <= 1100
+ ? 2
+ : xp <= 3900
+ ? 3
+ : xp <= 8400
+ ? 4
+ : xp <= 15000
+ ? 5
+ : xp <= 25000
+ ? 6
+ : xp <= 62000
+ ? 7
+ : xp <= 120000
+ ? 8
+ : xp <= 155000
+ ? 9
+ : 0;
+
+ update["npc_xp"] = xp;
+ update["pb_custom"] = pb;
+ update["pb_type"] = "custom";
+ setAttrs(update, { silent: true }, function () {
+ update_pb();
+ });
+ });
+};
+
+const update_npc_saves = () => {
+ const list = [
+ "npc_str_save_base",
+ "npc_dex_save_base",
+ "npc_con_save_base",
+ "npc_int_save_base",
+ "npc_wis_save_base",
+ "npc_cha_save_base",
+ ];
+ const type = "save";
+ update_npc_lists(list, type);
+};
+
+const update_npc_skills = () => {
+ const list = [
+ "npc_acrobatics_base",
+ "npc_animal_handling_base",
+ "npc_arcana_base",
+ "npc_athletics_base",
+ "npc_deception_base",
+ "npc_history_base",
+ "npc_insight_base",
+ "npc_intimidation_base",
+ "npc_investigation_base",
+ "npc_medicine_base",
+ "npc_nature_base",
+ "npc_perception_base",
+ "npc_performance_base",
+ "npc_persuasion_base",
+ "npc_religion_base",
+ "npc_sleight_of_hand_base",
+ "npc_stealth_base",
+ "npc_survival_base",
+ ];
+ const type = "skills";
+ update_npc_lists(list, type);
+};
+
+const update_npc_lists = (list, type) => {
+ getAttrs(list, function (v) {
+ let update = {};
+ let last_save = 0;
+ let npc_flag = 0;
+
+ _.each(list.reverse(), (base) => {
+ const attr = base.slice(4, -5); //Remove npc_ and _base
+ let item = parseInt(v[`${base}`], 10);
+
+ // CSS will add comma :after 2 & 4 and +/- :before
+ // 1 = Positive Number, 2 = Last Number, 3 = Negative Number, 4 = Last Negative Number
+ if ((v[`${base}`] && !isNaN(item)) || v[`${base}`] === 0) {
+ if (last_save === 0) {
+ last_save = 1;
+ item_flag = item < 0 ? 4 : 2;
+ } else {
+ item_flag = item < 0 ? 3 : 1;
+ }
+ } else {
+ item_flag = 0;
+ item = "";
+ }
+
+ update[`npc_${attr}_flag`] = item_flag;
+ update[`npc_${attr}`] = item;
+
+ npc_flag += item_flag;
+ });
+
+ const flagAttr = type === "save" ? "saving" : type;
+ update[`npc_${flagAttr}_flag`] = npc_flag === 0 ? "" : npc_flag;
+
+ setAttrs(update, { silent: true });
+ });
+};
+
+var update_npc_action = function (update_id, fieldset) {
+ if (update_id.substring(0, 1) === "-" && update_id.length === 20) {
+ do_update_npc_action([update_id], fieldset);
+ } else if (update_id === "all") {
+ var mythic_array = [];
+ var legendary_array = [];
+ var bonus_array = [];
+ var actions_array = [];
+ getSectionIDs("repeating_npcaction-l", function (idarray) {
+ legendary_array = idarray;
+ if (legendary_array.length > 0) {
+ do_update_npc_action(legendary_array, "npcaction-l");
+ }
+ getSectionIDs("repeating_npcaction-m", function (idarray) {
+ mythic_array = idarray;
+ if (mythic_array.length > 0) {
+ do_update_npc_action(mythic_array, "npcaction-m");
+ }
+ getSectionIDs("repeating_npcbonusaction", function (idarray) {
+ bonus_array = idarray;
+ if (bonus_array.length > 0) {
+ do_update_npc_action(actions_array, "npcaction");
+ }
+ getSectionIDs("repeating_npcaction", function (idarray) {
+ actions_array = idarray.filter(function (i) {
+ return (
+ legendary_array.indexOf(i) < 0 &&
+ mythic_array.indexOf(i) < 0 &&
+ bonus_array.indexOf(i) < 0
+ );
+ });
+ if (actions_array.length > 0) {
+ do_update_npc_action(actions_array, "npcaction");
+ }
+ });
+ });
+ });
+ });
+ }
+};
+
+var do_update_npc_action = function (action_array, fieldset) {
+ var repvar = `repeating_${fieldset}_`;
+ var action_attribs = ["dtype"];
+ _.each(action_array, function (actionid) {
+ action_attribs.push(repvar + actionid + "_attack_flag");
+ action_attribs.push(repvar + actionid + "_attack_type");
+ action_attribs.push(repvar + actionid + "_attack_range");
+ action_attribs.push(repvar + actionid + "_attack_target");
+ action_attribs.push(repvar + actionid + "_attack_tohit");
+ action_attribs.push(repvar + actionid + "_attack_damage");
+ action_attribs.push(repvar + actionid + "_attack_damagetype");
+ action_attribs.push(repvar + actionid + "_attack_damage2");
+ action_attribs.push(repvar + actionid + "_attack_damagetype2");
+ });
+
+ getAttrs(action_attribs, function (v) {
+ _.each(action_array, function (actionid) {
+ var callbacks = [];
+ var update = {};
+ var onhit = "";
+ var damage_flag = "";
+ var range = "";
+ var attack_flag =
+ v[repvar + actionid + "_attack_flag"] &&
+ v[repvar + actionid + "_attack_flag"] != "0"
+ ? "{{attack=1}}"
+ : "";
+ var tohit =
+ v[repvar + actionid + "_attack_tohit"] &&
+ isNaN(parseInt(v[repvar + actionid + "_attack_tohit"], 10)) === false
+ ? parseInt(v[repvar + actionid + "_attack_tohit"], 10)
+ : 0;
+ if (
+ v[repvar + actionid + "_attack_type"] &&
+ v[repvar + actionid + "_attack_range"]
+ ) {
+ if (v[repvar + actionid + "_attack_type"] === "Melee") {
+ var rangetype = "Reach";
+ } else {
+ var rangetype = "Range";
+ }
+ range = ", " + rangetype + " " + v[repvar + actionid + "_attack_range"];
+ }
+ var target =
+ v[repvar + actionid + "_attack_target"] &&
+ v[repvar + actionid + "_attack_target"] != ""
+ ? ", " + v[repvar + actionid + "_attack_target"]
+ : "";
+ var attack_tohitrange = "+" + tohit + range + target;
+ var dmg1 =
+ v[repvar + actionid + "_attack_damage"] &&
+ v[repvar + actionid + "_attack_damage"] != ""
+ ? v[repvar + actionid + "_attack_damage"]
+ : "";
+ var dmg1type =
+ v[repvar + actionid + "_attack_damagetype"] &&
+ v[repvar + actionid + "_attack_damagetype"] != ""
+ ? " " + v[repvar + actionid + "_attack_damagetype"]
+ : "";
+ var dmg2 =
+ v[repvar + actionid + "_attack_damage2"] &&
+ v[repvar + actionid + "_attack_damage2"] != ""
+ ? v[repvar + actionid + "_attack_damage2"]
+ : "";
+ var dmg2type =
+ v[repvar + actionid + "_attack_damagetype2"] &&
+ v[repvar + actionid + "_attack_damagetype2"] != ""
+ ? " " + v[repvar + actionid + "_attack_damagetype2"]
+ : "";
+ var dmgspacer = dmg1 != "" && dmg2 != "" ? " plus " : "";
+
+ var parsed_dmg1 = parse_roll_string(dmg1);
+ var parsed_dmg2 = parse_roll_string(dmg2);
+
+ if (dmg1 != "") {
+ onhit =
+ onhit + parsed_dmg1.avg + " (" + dmg1 + ")" + dmg1type + " damage";
+ }
+ dmgspacer = dmg1 != "" && dmg2 != "" ? " plus " : "";
+ onhit = onhit + dmgspacer;
+ if (dmg2 != "") {
+ onhit =
+ onhit + parsed_dmg2.avg + " (" + dmg2 + ")" + dmg2type + " damage";
+ }
+ if (dmg1 != "" || dmg2 != "") {
+ damage_flag = damage_flag + "{{damage=1}} ";
+ }
+ if (dmg1 != "") {
+ damage_flag = damage_flag + "{{dmg1flag=1}} ";
+ }
+ if (dmg2 != "") {
+ damage_flag = damage_flag + "{{dmg2flag=1}} ";
+ }
+
+ var crit1 = "";
+ if (parsed_dmg1.rolls.length > 0) {
+ parsed_dmg1.rolls.forEach(function (value) {
+ crit1 += parsed_dmg1.array[value] + "+";
+ });
+ crit1 = crit1.substring(0, crit1.length - 1);
+ }
+
+ var crit2 = "";
+ if (parsed_dmg2.rolls.length > 0) {
+ parsed_dmg2.rolls.forEach(function (value) {
+ crit2 += parsed_dmg2.array[value] + "+";
+ });
+ crit2 = crit2.substring(0, crit2.length - 1);
+ }
+
+ var rollbase = "";
+ if (v.dtype === "full") {
+ if (attack_flag) {
+ rollbase =
+ "@{wtype}&{template:npcfullatk} " +
+ attack_flag +
+ " @{damage_flag} @{npc_name_flag} {{rname=@{name}}} {{r1=[[@{d20}+(@{attack_tohit}+0)]]}} @{rtype}+(@{attack_tohit}+0)]]}} {{dmg1=[[@{attack_damage}+0]]}} {{dmg1type=@{attack_damagetype}}} {{dmg2=[[@{attack_damage2}+0]]}} {{dmg2type=@{attack_damagetype2}}} {{crit1=[[@{attack_crit}+0]]}} {{crit2=[[@{attack_crit2}+0]]}} {{description=@{show_desc}}} @{charname_output}";
+ } else {
+ if (dmg1) {
+ rollbase =
+ "@{wtype}&{template:dmgaction} @{damage_flag} @{npc_name_flag} {{rname=@{name}}} {{dmg1=[[@{attack_damage}+0]]}} {{dmg1type=@{attack_damagetype}}} {{dmg2=[[@{attack_damage2}+0]]}} {{dmg2type=@{attack_damagetype2}}} {{crit1=[[@{attack_crit}+0]]}} {{crit2=[[@{attack_crit2}+0]]}} {{description=@{show_desc}}} @{charname_output}";
+ } else {
+ rollbase =
+ "@{wtype}&{template:npcaction} @{npc_name_flag} {{rname=@{name}}} {{description=@{show_desc}}} @{charname_output}";
+ }
+ }
+ } else if (
+ v[repvar + actionid + "_attack_flag"] &&
+ v[repvar + actionid + "_attack_flag"] != "0"
+ ) {
+ rollbase = `@{wtype}&{template:npcatk} ${attack_flag} @{damage_flag} @{npc_name_flag} {{rname=[@{name}](~repeating_${fieldset}_npc_dmg)}} {{rnamec=[@{name}](~repeating_${fieldset}_npc_crit)}} {{type=[^{attack-u}](~repeating_${fieldset}_npc_dmg)}} {{typec=[^{attack-u}](~repeating_${fieldset}_npc_crit)}} {{r1=[[@{d20}+(@{attack_tohit}+0)]]}} @{rtype}+(@{attack_tohit}+0)]]}} @{charname_output}`;
+ } else if (dmg1 || dmg2) {
+ if (attack_flag) {
+ rollbase =
+ "@{wtype}&{template:npcdmg} @{damage_flag} {{dmg1=[[@{attack_damage}+0]]}} {{dmg1type=@{attack_damagetype}}} {{dmg2=[[@{attack_damage2}+0]]}} {{dmg2type=@{attack_damagetype2}}} {{crit1=[[@{attack_crit}+0]]}} {{crit2=[[@{attack_crit2}+0]]}} {{description=@{show_desc}}} @{charname_output}";
+ } else {
+ rollbase =
+ "@{wtype}&{template:dmgaction} @{damage_flag} @{npc_name_flag} {{rname=@{name}}} {{dmg1=[[@{attack_damage}+0]]}} {{dmg1type=@{attack_damagetype}}} {{dmg2=[[@{attack_damage2}+0]]}} {{dmg2type=@{attack_damagetype2}}} {{crit1=[[@{attack_crit}+0]]}} {{crit2=[[@{attack_crit2}+0]]}} {{description=@{show_desc}}} @{charname_output}";
+ }
+ } else {
+ rollbase =
+ "@{wtype}&{template:npcaction} @{npc_name_flag} {{rname=@{name}}} {{description=@{show_desc}}} @{charname_output}";
+ }
+
+ update[repvar + actionid + "_attack_tohitrange"] = attack_tohitrange;
+ update[repvar + actionid + "_attack_onhit"] = onhit;
+ update[repvar + actionid + "_damage_flag"] = damage_flag;
+ update[repvar + actionid + "_attack_crit"] = crit1;
+ update[repvar + actionid + "_attack_crit2"] = crit2;
+ update[repvar + actionid + "_rollbase"] = rollbase;
+ setAttrs(update, { silent: true });
+ });
+ });
+};
+
+var parse_roll_string = function (rollstring) {
+ var out = { array: [], avg: 0, rolls: [] };
+
+ if (!rollstring || rollstring === "") {
+ return out;
+ }
+
+ var rs_regex_initial = /(\-?\d+(?:d\d+)?)/gi;
+ var rs_regex_repeating = /([\+\-])(\-?\d+(?:d\d+)?)/gi;
+ var rs_nospace = rollstring.replace(/\s/g, "");
+ var rs_initial = rs_regex_initial.exec(rs_nospace);
+
+ if (rs_initial) {
+ out.array.push(rs_initial[1]);
+ rs_regex_repeating.lastIndex = rs_regex_initial.lastIndex;
+ var rs_repeating;
+ while ((rs_repeating = rs_regex_repeating.exec(rs_nospace))) {
+ out.array.push(rs_repeating[1], rs_repeating[2]);
+ }
+ }
+
+ var add = true;
+ var dice_regex = /(\d+)d(\d+)/i;
+ var dice;
+
+ out.array.forEach(function (value, index, array) {
+ if (value === "+") {
+ add = true;
+ } else if (value === "-") {
+ add = false;
+ } else if ((dice = dice_regex.exec(value))) {
+ // this value is a die roll
+ var dice_avg = Math.floor(+dice[1] * (+dice[2] / 2 + 0.5));
+ out.avg += add ? dice_avg : -dice_avg;
+ out.rolls.push(index);
+ } else {
+ // this value is a number
+ out.avg += add ? +value : -+value;
+ }
+ });
+
+ return out;
+};
+
+var get_class_level = function (class_name, callback) {
+ getAttrs(
+ [
+ "class",
+ "base_level",
+ "multiclass1_flag",
+ "multiclass1",
+ "multiclass1_lvl",
+ "multiclass2_flag",
+ "multiclass2",
+ "multiclass2_lvl",
+ "multiclass3_flag",
+ "multiclass3",
+ "multiclass3_lvl",
+ ],
+ function (attrs) {
+ var regex = new RegExp(class_name, "i");
+ if (regex.test(attrs["class"])) {
+ callback(attrs.base_level);
+ } else if (
+ attrs.multiclass1_flag &&
+ attrs.multiclass1_flag !== "0" &&
+ regex.test(attrs.multiclass1)
+ ) {
+ callback(attrs.multiclass1_lvl);
+ } else if (
+ attrs.multiclass2_flag &&
+ attrs.multiclass2_flag !== "0" &&
+ regex.test(attrs.multiclass2)
+ ) {
+ callback(attrs.multiclass2_lvl);
+ } else if (
+ attrs.multiclass3_flag &&
+ attrs.multiclass3_flag !== "0" &&
+ regex.test(attrs.multiclass3)
+ ) {
+ callback(attrs.multiclass3_lvl);
+ } else {
+ callback("0");
+ }
+ }
+ );
+};
+
+var update_globaldamage = function (callback) {
+ getSectionIDs("damagemod", function (ids) {
+ if (ids) {
+ var fields = {};
+ var attr_name_list = [];
+ ids.forEach(function (id) {
+ fields[id] = {};
+ attr_name_list.push(
+ `repeating_damagemod_${id}_global_damage_active_flag`,
+ `repeating_damagemod_${id}_global_damage_name`,
+ `repeating_damagemod_${id}_global_damage_damage`,
+ `repeating_damagemod_${id}_global_damage_critical_damage`,
+ `repeating_damagemod_${id}_global_damage_type`
+ );
+ });
+
+ getAttrs(attr_name_list, function (attrs) {
+ var regex =
+ /^repeating_damagemod_(.+)_global_damage_(active_flag|name|critical_damage|damage|type)$/;
+ _.each(attrs, function (obj, name) {
+ var r = regex.exec(name);
+ if (r) {
+ fields[r[1]][r[2]] = obj;
+ }
+ });
+
+ var update = {
+ global_damage_mod_roll: "",
+ global_damage_mod_crit: "",
+ global_damage_mod_type: "",
+ };
+ const simpleDamageRegex = new RegExp(
+ /([0-9]*d[0-9]+)|(\[.+?\])|\+|\-|\/|\*| /gi
+ );
+ _.each(fields, function (element) {
+ if (element.active_flag != "0") {
+ if (element.name && element.damage) {
+ update["global_damage_mod_roll"] +=
+ element.damage + "[" + element.name + "]" + "+";
+ }
+ if (element.name && element.critical_damage) {
+ const criticalDamage = element.critical_damage;
+ const criticalSource = element.name;
+ update["global_damage_mod_crit"] = update[
+ "global_damage_mod_crit"
+ ]
+ ? `${update["global_damage_mod_crit"]} + ${criticalDamage}[${criticalSource}]`
+ : `${criticalDamage}[${criticalSource}]`;
+ update["global_damage_mod_crit"] = update[
+ "global_damage_mod_crit"
+ ]
+ .replace(/\+$/gi, "")
+ .trim();
+ } else if (element.name && element.damage) {
+ const criticalDamage = element.damage;
+ const criticalSource = element.name;
+ const simpleDamage =
+ element.damage.replace(simpleDamageRegex, "").length == 0;
+ if (simpleDamage) {
+ update["global_damage_mod_crit"] = update[
+ "global_damage_mod_crit"
+ ]
+ ? `${update["global_damage_mod_crit"]} + ${criticalDamage}[${criticalSource}]`
+ : `${criticalDamage}[${criticalSource}]`;
+ update["global_damage_mod_crit"] = update[
+ "global_damage_mod_crit"
+ ]
+ .replace(/\+$/gi, "")
+ .trim();
+ }
+ //removing this regex
+ // Remove any non-roll damage modifiers from the global damage modifier for the crit rolls
+ // Will also remove any labels attached to these non-roll damage modifiers
+ //.replace(/(?:[+\-*\/%]|\*\*|^)\s*\d+(?:\[.*?])?(?!\d?d\d+)/gi, '')
+ // If what was just replace removed the first damage modifier, remove any now precending plus signs
+ //.replace(/(?:^\+)/i, '');
+ }
+ if (element.type) {
+ update["global_damage_mod_type"] += element.type + "/";
+ }
+ }
+ });
+
+ update["global_damage_mod_roll"] = update[
+ "global_damage_mod_roll"
+ ].replace(/\+(?=$)/, "");
+ update["global_damage_mod_type"] = update[
+ "global_damage_mod_type"
+ ].replace(/\/(?=$)/, "");
+
+ setAttrs(update, { silent: true }, function () {
+ update_attacks("all");
+ if (typeof callback == "function") callback();
+ });
+ });
+ }
+ });
+};
+
+var update_globalattack = function (callback) {
+ getSectionIDs("tohitmod", function (ids) {
+ if (ids) {
+ var fields = {};
+ var attr_name_list = [];
+ ids.forEach(function (id) {
+ fields[id] = {};
+ attr_name_list.push(
+ `repeating_tohitmod_${id}_global_attack_active_flag`,
+ `repeating_tohitmod_${id}_global_attack_roll`,
+ `repeating_tohitmod_${id}_global_attack_name`
+ );
+ });
+ getAttrs(attr_name_list, function (attrs) {
+ var regex =
+ /^repeating_tohitmod_(.+)_global_attack_(active_flag|roll|name)$/;
+ _.each(attrs, function (obj, name) {
+ var r = regex.exec(name);
+ if (r) {
+ fields[r[1]][r[2]] = obj;
+ }
+ });
+
+ var update = { global_attack_mod: "" };
+ _.each(fields, function (element) {
+ if (element.active_flag != "0") {
+ if (element.roll && element.roll !== "") {
+ update["global_attack_mod"] +=
+ element.roll + "[" + element.name + "]" + "+";
+ }
+ }
+ });
+ if (update["global_attack_mod"] !== "") {
+ update["global_attack_mod"] =
+ "[[" + update["global_attack_mod"].replace(/\+(?=$)/, "") + "]]";
+ }
+ setAttrs(update, { silent: true }, function () {
+ if (typeof callback == "function") callback();
+ });
+ });
+ }
+ });
+};
+
+var update_globalsaves = function (callback) {
+ getSectionIDs("savemod", function (ids) {
+ if (ids) {
+ var fields = {};
+ var attr_name_list = [];
+ ids.forEach(function (id) {
+ fields[id] = {};
+ attr_name_list.push(
+ `repeating_savemod_${id}_global_save_active_flag`,
+ `repeating_savemod_${id}_global_save_roll`,
+ `repeating_savemod_${id}_global_save_name`
+ );
+ });
+ getAttrs(attr_name_list, function (attrs) {
+ var regex =
+ /^repeating_savemod_(.+)_global_save_(active_flag|roll|name)$/;
+ _.each(attrs, function (obj, name) {
+ var r = regex.exec(name);
+ if (r) {
+ fields[r[1]][r[2]] = obj;
+ }
+ });
+
+ var update = { global_save_mod: "" };
+ _.each(fields, function (element) {
+ if (element.active_flag != "0") {
+ if (element.roll && element.roll !== "") {
+ update["global_save_mod"] +=
+ element.roll + "[" + element.name + "]" + "+";
+ }
+ }
+ });
+ if (update["global_save_mod"] !== "") {
+ update["global_save_mod"] =
+ "[[" + update["global_save_mod"].replace(/\+(?=$)/, "") + "]]";
+ }
+ setAttrs(update, { silent: true }, function () {
+ if (typeof callback == "function") callback();
+ });
+ });
+ }
+ });
+};
+
+var update_globalskills = function (callback) {
+ getSectionIDs("skillmod", function (ids) {
+ if (ids) {
+ var fields = {};
+ var attr_name_list = [];
+ ids.forEach(function (id) {
+ fields[id] = {};
+ attr_name_list.push(
+ `repeating_skillmod_${id}_global_skill_active_flag`,
+ `repeating_skillmod_${id}_global_skill_roll`,
+ `repeating_skillmod_${id}_global_skill_name`
+ );
+ });
+ getAttrs(attr_name_list, function (attrs) {
+ var regex =
+ /^repeating_skillmod_(.+)_global_skill_(active_flag|roll|name)$/;
+ _.each(attrs, function (obj, name) {
+ var r = regex.exec(name);
+ if (r) {
+ fields[r[1]][r[2]] = obj;
+ }
+ });
+
+ var update = { global_skill_mod: "" };
+ _.each(fields, function (element) {
+ if (element.active_flag != "0") {
+ if (element.roll && element.roll !== "") {
+ update["global_skill_mod"] +=
+ element.roll + "[" + element.name + "]" + "+";
+ }
+ }
+ });
+ if (update["global_skill_mod"] !== "") {
+ update["global_skill_mod"] =
+ "[[" + update["global_skill_mod"].replace(/\+(?=$)/, "") + "]]";
+ }
+ setAttrs(update, { silent: true }, function () {
+ if (typeof callback == "function") callback();
+ });
+ });
+ }
+ });
+};
+
+var check_l1_mancer = function () {
+ getAttrs(
+ [
+ "class",
+ "base_level",
+ "strength_base",
+ "dexterity_base",
+ "constitution_base",
+ "intelligence_base",
+ "wisdom_base",
+ "charisma_base",
+ "l1mancer_status",
+ "version",
+ "charactermancer_step",
+ ],
+ function (v) {
+ if (!v["version"] || parseFloat(v["version"]) < 2.2) {
+ return;
+ }
+ if (v["l1mancer_status"] && v["l1mancer_status"] === "completed") {
+ return;
+ }
+
+ if (
+ v["charactermancer_step"] &&
+ v["charactermancer_step"].split("-")[0] == "l1"
+ ) {
+ startCharactermancer(v["charactermancer_step"]);
+ } else {
+ if (v["l1mancer_status"] && v["l1mancer_status"] === "relaunch") {
+ startCharactermancer("l1-welcome");
+ } else {
+ setAttrs({ mancer_confirm_flag: 1 });
+ }
+ }
+ }
+ );
+};
+
+var check_lp_mancer = function () {
+ getAttrs(
+ [
+ "class",
+ "base_level",
+ "strength_base",
+ "dexterity_base",
+ "constitution_base",
+ "intelligence_base",
+ "wisdom_base",
+ "charisma_base",
+ "l1mancer_status",
+ "lpmancer_status",
+ "version",
+ "charactermancer_step",
+ ],
+ function (v) {
+ if (
+ v["lpmancer_status"] === "active" &&
+ v["charactermancer_step"] &&
+ v["charactermancer_step"].split("-")[0] == "lp"
+ ) {
+ startCharactermancer(v["charactermancer_step"]);
+ }
+ }
+ );
+};
+
+on("mancer:cancel", function (eventinfo) {
+ if (!eventinfo["value"]) {
+ return;
+ }
+ var update = {};
+
+ if (
+ eventinfo["value"] === "l1-welcome" ||
+ eventinfo["value"] === "l1-cancel"
+ ) {
+ update["l1mancer_status"] = "completed";
+ update["charactermancer_step"] = "l1-welcome";
+ deleteCharmancerData([
+ "l1-welcome",
+ "l1-race",
+ "l1-class",
+ "l1-abilities",
+ "l1-background",
+ "l1-equipment",
+ "l1-spells",
+ "l1-summary",
+ ]);
+ } else if (eventinfo["value"].substring(0, 3) === "l1-") {
+ update["l1mancer_status"] = eventinfo["value"];
+ } else if (
+ eventinfo["value"] === "lp-welcome" ||
+ eventinfo["value"] === "lp-cancel"
+ ) {
+ update["lpmancer_status"] = "";
+ update["charactermancer_step"] = "";
+ deleteCharmancerData([
+ "lp-welcome",
+ "lp-levels",
+ "lp-choices",
+ "lp-asi",
+ "lp-spells",
+ "lp-summary",
+ ]);
+ } else if (eventinfo["value"].substring(0, 3) === "lp-") {
+ update["charactermancer_step"] = "";
+ update["lpmancer_status"] = "";
+ }
+ setAttrs(update);
+});
+
+on("change:hitdie_final", function (eventinfo) {
+ setHitdieroll();
+});
+
+on("sheet:opened", function (eventinfo) {
+ setHitdieroll();
+ update_leveler_display();
+});
+
+var setHitdieroll = function () {
+ getAttrs(["npc", "hitdietype"], function (v) {
+ if ((v["npc"] && v["npc"] == 1) || !v["hitdietype"]) return;
+ v["hitdietype"] =
+ globalAttributesByCategory.hitDieTypes.indexOf(`d${v["hitdietype"]}`) > -1
+ ? v["hitdietype"]
+ : "4";
+ setAttrs({ hitdieroll: v["hitdietype"] });
+ });
+};
+
+var flagManager = new FlagManager("ui_flags");
+[
+ { section: "npcaction", button: "edit" },
+ { section: "npcbonusaction", button: "edit" },
+ { section: "npctrait", button: "edit" },
+ { section: "npcreaction", button: "edit" },
+ { section: "npcaction-l", button: "edit" },
+ { section: "npcaction-m", button: "edit" },
+].forEach((flag) => {
+ on(`clicked:repeating_${flag.section}:${flag.button}`, function (eventInfo) {
+ SheetUtils.getSectionOrder(flag.section, (ids) => {
+ const uid = SheetUtils.getUID(eventInfo.sourceAttribute).toLowerCase();
+ const index = ids.indexOf(uid);
+ const flagName = `repeating_${flag.section}_${flag.button}_${index}_${uid}`;
+ flagManager.toggleFlag(flagName);
+ });
+ });
+ on(`remove:repeating_${flag.section}`, function (eventInfo) {
+ flagManager.syncFlagsWithRepeatingSection(flag.section);
+ });
+ on(`change:_reporder:${flag.section}`, function (eventInfo) {
+ flagManager.syncFlagsWithRepeatingSection(flag.section);
+ });
+ on(`change:repeating_${flag.section}`, function (eventInfo) {
+ if (
+ !eventInfo.sourceType ||
+ eventInfo.sourceType !== "player" ||
+ (eventInfo.sourceAttribute &&
+ eventInfo.sourceAttribute.indexOf("_rollbase") > -1)
+ )
+ return;
+ SheetUtils.getSectionOrder(flag.section, (ids) => {
+ const uid = SheetUtils.getUID(eventInfo.sourceAttribute.toLowerCase());
+ const index = ids.indexOf(uid);
+ if (index === ids.length - 1) {
+ const flagName = `repeating_${flag.section}_${flag.button}_${index}_${uid}`;
+ flagManager.addFlag(flagName);
+ }
+ });
+ });
+});
+
+var showOptionalAttributeFields = function () {
+ const optionalAttributesClasses = SheetUtils.toLowerCase(
+ abilityListEnabledOptionals
+ ).map((key) => `sheet-${key}_toggle`);
+ optionalAttributesClasses.forEach((attribute) => {
+ showChoices([attribute]);
+ });
+};
+
+var getAllSpellsIDS = function (callback) {
+ const levels = ["cantrip", "1", "2", "3", "4", "5", "6", "6", "8", "9"];
+ let currentLevel = 0;
+ let spells = [];
+ getSectionIDs(`spell-${levels[currentLevel]}`, (ids) => {
+ ids.forEach((id) => {
+ spells.push(`repeating_spell-${levels[currentLevel]}_${id}`);
+ });
+ currentLevel = 1;
+ getSectionIDs(`spell-${levels[currentLevel]}`, (ids) => {
+ ids.forEach((id) => {
+ spells.push(`repeating_spell-${levels[currentLevel]}_${id}`);
+ });
+ currentLevel = 2;
+ getSectionIDs(`spell-${levels[currentLevel]}`, (ids) => {
+ ids.forEach((id) => {
+ spells.push(`repeating_spell-${levels[currentLevel]}_${id}`);
+ });
+ currentLevel = 3;
+ getSectionIDs(`spell-${levels[currentLevel]}`, (ids) => {
+ ids.forEach((id) => {
+ spells.push(`repeating_spell-${levels[currentLevel]}_${id}`);
+ });
+ currentLevel = 4;
+ getSectionIDs(`spell-${levels[currentLevel]}`, (ids) => {
+ ids.forEach((id) => {
+ spells.push(`repeating_spell-${levels[currentLevel]}_${id}`);
+ });
+ currentLevel = 5;
+ getSectionIDs(`spell-${levels[currentLevel]}`, (ids) => {
+ ids.forEach((id) => {
+ spells.push(`repeating_spell-${levels[currentLevel]}_${id}`);
+ });
+ currentLevel = 6;
+ getSectionIDs(`spell-${levels[currentLevel]}`, (ids) => {
+ ids.forEach((id) => {
+ spells.push(`repeating_spell-${levels[currentLevel]}_${id}`);
+ });
+ currentLevel = 7;
+ getSectionIDs(`spell-${levels[currentLevel]}`, (ids) => {
+ ids.forEach((id) => {
+ spells.push(
+ `repeating_spell-${levels[currentLevel]}_${id}`
+ );
+ });
+ currentLevel = 8;
+ getSectionIDs(`spell-${levels[currentLevel]}`, (ids) => {
+ ids.forEach((id) => {
+ spells.push(
+ `repeating_spell-${levels[currentLevel]}_${id}`
+ );
+ });
+ currentLevel = 9;
+ getSectionIDs(`spell-${levels[currentLevel]}`, (ids) => {
+ ids.forEach((id) => {
+ spells.push(
+ `repeating_spell-${levels[currentLevel]}_${id}`
+ );
+ });
+ callback(spells);
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+};
+
+on("sheet:opened change:honor_toggle change:sanity_toggle", (eventInfo) => {
+ getAttrs(["honor_toggle", "sanity_toggle"], (values) => {
+ abilityListEnabledOptionals = SheetUtils.toCapitalCase(
+ Object.keys(values)
+ .filter((key) => {
+ return values[key] === "1";
+ })
+ .map((key) => key.replace("_toggle", ""))
+ );
+ abilityList = SheetUtils.toCapitalCase(
+ globalAttributesByCategory.abilities
+ ).concat(abilityListEnabledOptionals);
+ });
+});
+
+globalAttributesByCategory.skills.all().forEach((skill) => {
+ on(`change:${skill}_bonus`, () => {
+ updateSkillRoll(skill);
+ });
+});
+
+globalAttributesByCategory.abilitiesWithAllOptionals.forEach((ability) => {
+ on(`change:${ability}_save_bonus`, () => {
+ updateSavingRoll(ability);
+ });
+});
+
+on("change:rtype change:reliable_talent change:pb", (eventInfo) => {
+ getSectionIDs("repeating_tool", (idarray) => {
+ updateSavingRolls(globalAttributesByCategory.abilitiesWithAllOptionals);
+ updateSkillRolls(globalAttributesByCategory.skills.all());
+ do_update_tool(idarray);
+ });
+});
+
+var updateSkillRoll = function (skill, callback) {
+ updateSkillRolls([skill], callback);
+};
+
+var updateSavingRoll = function (saving, callback) {
+ updateSavingRolls([saving], callback);
+};
+
+const checkProficiency = function (values, prof) {
+ return values[prof] && values[prof].indexOf("@{pb}") > -1;
+};
+
+var updateSavingRolls = function (savings, callback) {
+ const attrs_prof = savings.map((saving) => {
+ return `${saving}_save_prof`;
+ });
+ const attrs_bonus = savings.map((saving) => {
+ return `${saving}_save_bonus`;
+ });
+ getAttrs(
+ [
+ ...attrs_prof,
+ ...attrs_bonus,
+ "reliable_talent",
+ "rtype",
+ "advantagetoggle",
+ "queryadvantage",
+ "pb",
+ ],
+ (values) => {
+ const usingProficiencyDie =
+ values.pb && String(values.pb).includes("d") ? true : false;
+ let rtype = values["rtype"].includes("@{advantagetoggle}")
+ ? values["advantagetoggle"]
+ : values["rtype"];
+ rtype = values["rtype"].includes("@{queryadvantage}")
+ ? values["queryadvantage"]
+ : values["rtype"];
+ let update = {};
+ savings.forEach((saving) => {
+ let roll;
+ const isProficient = checkProficiency(values, `${saving}_save_prof`);
+ if (usingProficiencyDie && isProficient) {
+ const proficiencyDie = values.pb.match(/^[0-9]/)
+ ? values.pb
+ : `${values.pb}`;
+ const savingBonus = String(values[`${saving}_save_bonus`])
+ .replace(proficiencyDie, "")
+ .replace(/\+{2,}|-{2,}|^[\+-]|[\+-]$/, "");
+ const rtypeString = rtype.includes("{{normal=1}}")
+ ? "{{normal=1}} "
+ : `${rtype}+${savingBonus}]]}} `;
+ const r3 = ` + [[${proficiencyDie}@{pbd_safe}[Proficiency]]]`;
+ roll = `@{wtype}&{template:simple3D} {{rname=^{${saving}-save-u}}} {{mod=${
+ values[`${saving}_save_bonus`]
+ }}} {{r1=[[@{d20}+${savingBonus}]]}} {{r3=${r3}}} ${rtypeString}{{global=@{global_save_mod}}} @{charname_output}`;
+ } else {
+ const rtypeString = rtype.includes("{{normal=1}}")
+ ? "{{normal=1}} "
+ : `${rtype}+@{${saving}_save_bonus}@{pbd_safe}]]}} `;
+ roll = `@{wtype}&{template:simple} {{rname=^{${saving}-save-u}}} {{mod=@{${saving}_save_bonus}}} {{r1=[[@{d20}+@{${saving}_save_bonus}@{pbd_safe}]]}} ${rtypeString}{{global=@{global_save_mod}}} @{charname_output}`;
+ }
+ update[`${saving}_save_roll`] = roll;
+ });
+ setAttrs(update, () => {
+ if (callback) callback();
+ });
+ }
+ );
+};
+
+var updateSkillRolls = function (skills, callback) {
+ const attrs_prof = skills.map((skill) => {
+ return `${skill}_prof`;
+ });
+ const attrs_bonus = skills.map((skill) => {
+ return `${skill}_bonus`;
+ });
+ const attrs_type = skills.map((skill) => {
+ return `${skill}_type`;
+ });
+ const ability_mods = globalAttributesByCategory.abilities.map((ability) => {
+ return `${ability}_mod`;
+ });
+ getAttrs(
+ [
+ ...attrs_prof,
+ ...attrs_bonus,
+ ...attrs_type,
+ ...ability_mods,
+ "reliable_talent",
+ "jack_of_all_trades",
+ "jack",
+ "rtype",
+ "advantagetoggle",
+ "queryadvantage",
+ "pb",
+ ],
+ (values) => {
+ const usingProficiencyDie =
+ values.pb && String(values.pb).includes("d") ? true : false;
+ let rtype = values["rtype"].includes("@{advantagetoggle}")
+ ? values["advantagetoggle"]
+ : values["rtype"];
+ rtype = values["rtype"].includes("@{queryadvantage}")
+ ? values["queryadvantage"]
+ : values["rtype"];
+ const query = rtype.indexOf("queryadvantage") > -1;
+ const isJack =
+ values["jack_of_all_trades"] &&
+ values["jack_of_all_trades"] == "@{jack}";
+ let update = {};
+ skills.forEach((skill) => {
+ let roll;
+ const isProficient = checkProficiency(values, `${skill}_prof`);
+ if (
+ (usingProficiencyDie && isProficient) ||
+ (usingProficiencyDie && isJack)
+ ) {
+ const die =
+ !isProficient && isJack
+ ? `${values["jack"]}`
+ : `${values[`${skill}_type`]}${values.pb}`;
+ const proficiencyDie = die;
+ const jackSafeDie =
+ !isProficient && isJack ? `round(${values.pb}/2)` : proficiencyDie;
+ const skillBonus = String(values[`${skill}_bonus`])
+ .replace(proficiencyDie, "")
+ .replace(/\+{2,}|-{2,}|^[\+-]|[\+-]$/, "");
+ const rtypeString = rtype.includes("{{normal=1}}")
+ ? "{{normal=1}} "
+ : `${rtype}+${skillBonus}]]}} `;
+ const r3 = ` + [[${jackSafeDie}@{pbd_safe}[Proficiency]]]`;
+ roll = `@{wtype}&{template:simple3D} {{rname=^{${skill}-u}}} {{mod=${
+ values[`${skill}_bonus`]
+ }}} {{r1=[[@{d20}+${skillBonus}[Mods]]]}} {{r3=${r3}}} ${rtypeString}{{global=@{global_skill_mod}}} @{charname_output}`;
+ } else {
+ let profBonus =
+ values["pb"] && isProficient ? parseInt(values["pb"]) : 0;
+ profBonus =
+ !isProficient && isJack && values["pb"]
+ ? Math.round(parseInt(values["pb"]) / 2)
+ : profBonus;
+ let rollBonuses = `@{${skill}_bonus}[Mods]`;
+ if (
+ values[`${skill}_bonus`] &&
+ values[`${skill}_bonus`].toString().toLowerCase().indexOf("d") ===
+ -1
+ ) {
+ const parentAbility =
+ globalAttributesByCategory.skills.getParentAbility(skill);
+ const parentMod = parseInt(values[`${parentAbility}_mod`]);
+ const otherBonuses = parseInt(values[`${skill}_bonus`]) - profBonus;
+ const label = otherBonuses > parentMod ? "Mods" : parentAbility;
+ if (profBonus != 0 && otherBonuses != 0) {
+ rollBonuses =
+ `${profBonus}[Proficiency]+${otherBonuses}[${label}]`.replace(
+ /\+-/g,
+ "-"
+ );
+ } else if (profBonus == 0 && otherBonuses != 0) {
+ rollBonuses = `${otherBonuses}[${label}]`.replace(/\+-/g, "-");
+ } else if (profBonus != 0 && otherBonuses == 0) {
+ rollBonuses = `${profBonus}[Proficiency]`.replace(/\+-/g, "-");
+ } else {
+ let rollBonuses = `@{${skill}_bonus}[Mods]`;
+ }
+ }
+ const rtypeString = rtype.includes("{{normal=1}}")
+ ? "{{normal=1}} "
+ : `${rtype}+${rollBonuses}@{pbd_safe}]]}} `;
+ roll = `@{wtype}&{template:simple} {{rname=^{${skill}-u}}} {{mod=@{${skill}_bonus}}} {{r1=[[@{d20}+${rollBonuses}@{pbd_safe}]]}} ${rtypeString}{{global=@{global_skill_mod}}} @{charname_output}`;
+ }
+ if (
+ values["reliable_talent"] &&
+ values["reliable_talent"] == 10 &&
+ values[`${skill}_prof`] &&
+ values[`${skill}_prof`] != 0
+ ) {
+ if (query) {
+ const queryReplace = "r2=[[{1d20,0d20+10}k1"
+ .replace("{", "{")
+ .replace("}", "}")
+ .replace(",", ",");
+ roll = roll.replace(/r2=\[\[@{d20}/g, queryReplace);
+ roll = roll.replace(/@{d20}/g, "{@{d20},0d20+10}k1");
+ } else {
+ roll = roll.replace(/@{d20}/g, "{@{d20},0d20+10}k1");
+ }
+ }
+ update[`${skill}_roll`] = roll;
+ });
+ setAttrs(update, () => {
+ if (callback) callback();
+ });
+ }
+ );
+};
+
+var updateToolRolls = function (toolsIDs, callback) {
+ const attrs_prof = toolsIDs.map((id) => {
+ return `repeating_tool_${id}_toolbonus_base`;
+ });
+ const attrs_bonus = toolsIDs.map((id) => {
+ return `repeating_tool_${id}_toolbonus`;
+ });
+ const attrs_bonus_base = toolsIDs.map((id) => {
+ return `repeating_tool_${id}_toolbonus_base`;
+ });
+ getAttrs(
+ [
+ ...attrs_prof,
+ ...attrs_bonus,
+ ...attrs_bonus_base,
+ "reliable_talent",
+ "jack_of_all_trades",
+ "jack",
+ "rtype",
+ "advantagetoggle",
+ "queryadvantage",
+ "pb",
+ ],
+ (values) => {
+ const usingProficiencyDie =
+ values.pb && String(values.pb).includes("d") ? true : false;
+ let rtype = values["rtype"].includes("@{advantagetoggle}")
+ ? values["advantagetoggle"]
+ : values["rtype"];
+ rtype = values["rtype"].includes("@{queryadvantage}")
+ ? values["queryadvantage"]
+ : values["rtype"];
+ const query = rtype.indexOf("queryadvantage") > -1;
+ let update = {};
+ const isJack =
+ values["jack_of_all_trades"] &&
+ values["jack_of_all_trades"] == "@{jack}";
+ toolsIDs.forEach((id) => {
+ let roll;
+ if (usingProficiencyDie) {
+ const isProficient =
+ values[`repeating_tool_${id}_toolbonus_base`] !==
+ "(floor(@{pb}/2))";
+ const proficiencyType =
+ values[`repeating_tool_${id}_toolbonus_base`] &&
+ values[`repeating_tool_${id}_toolbonus_base`] === "(@{pb}*2)"
+ ? "2"
+ : "";
+ const die =
+ isJack && !isProficient
+ ? `${proficiencyType}${values["jack"]}`
+ : `${proficiencyType}${values.pb}`;
+ const proficiencyDie = die;
+ const jackSafeDie =
+ !isProficient && isJack ? `round(${values.pb}/2)` : proficiencyDie;
+ const skillBonus = String(values[`repeating_tool_${id}_toolbonus`])
+ .replace(proficiencyDie, "")
+ .replace(/\+{2,}|-{2,}|^[\+-]|[\+-]$/, "")
+ .replace(/\+0|-0/, "");
+ const rtypeString = rtype.includes("{{normal=1}}")
+ ? "{{normal=1}} "
+ : `${rtype}+${skillBonus}]]}} `;
+ const r3 = ` + [[${jackSafeDie}@{pbd_safe}[Proficiency]]]`;
+ roll = `@{wtype}&{template:simple3D} {{rname=@{toolname}}} {{mod=${
+ values[`repeating_tool_${id}_toolbonus`]
+ }}} {{r1=[[@{d20}+${skillBonus}[Mods]]]}} {{r3=${r3}}} ${rtypeString}{{global=@{global_skill_mod}}} @{charname_output}`;
+ } else {
+ const rtypeString = rtype.includes("{{normal=1}}")
+ ? "{{normal=1}} "
+ : `${rtype}+@{toolbonus}[Mods]@{pbd_safe}]]}} `;
+ roll = `@{wtype}&{template:simple} {{rname=@{toolname}}} {{mod=@{toolbonus}}} {{r1=[[@{d20}+@{toolbonus}[Mods]@{pbd_safe}]]}} ${rtypeString}{{global=@{global_skill_mod}}} @{charname_output}`;
+ }
+ if (
+ values["reliable_talent"] &&
+ values["reliable_talent"] == 10 &&
+ values[`repeating_tool_${id}_toolbonus_base`] &&
+ values[`repeating_tool_${id}_toolbonus_base`] != "(floor(@{pb}/2))"
+ ) {
+ if (query) {
+ const queryReplace = "r2=[[{1d20,0d20+10}k1"
+ .replace("{", "{")
+ .replace("}", "}")
+ .replace(",", ",");
+ roll = roll.replace(/r2=\[\[@{d20}/g, queryReplace);
+ roll = roll.replace(/@{d20}/g, "{@{d20},0d20+10}k1");
+ } else {
+ roll = roll.replace(/@{d20}/g, "{@{d20},0d20+10}k1");
+ }
+ }
+ update[`repeating_tool_${id}_toolroll`] = roll;
+ });
+ setAttrs(update, () => {
+ if (callback) callback();
+ });
+ }
+ );
+};
+
+var updateCharnameOutput = function (npcCallback, pcCallback) {
+ getAttrs(["npc", "npc_name", "npc_name_flag"], (values) => {
+ if (
+ values["npc"] &&
+ values["npc"] == "1" &&
+ values["npc_name"] &&
+ values["npc_name_flag"]
+ ) {
+ const charname = values["npc_name_flag"].replace("name", "charname");
+ setAttrs({ charname_output: charname }, () => {
+ if (npcCallback) npcCallback();
+ });
+ } else {
+ if (pcCallback) pcCallback();
+ else if (npcCallback) npcCallback();
+ }
+ });
+};
+
+on("change:npc_name change:npc_name_flag", (eventInfo) => {
+ updateCharnameOutput();
+});
+
+var getHitDiceAttributeSet = function (id) {
+ let attributes = [];
+ attributes.push(`repeating_hd_${id}_type`);
+ attributes.push(`repeating_hd_${id}_size`);
+ attributes.push(`repeating_hd_${id}_available`);
+ return attributes;
+};
+var getHitDicePool = function (callback, single) {
+ getSectionIDs("repeating_hd", (ids) => {
+ if (single) ids = [single];
+ let attributes = [];
+ ids.forEach((id) => {
+ attributes = attributes.concat(getHitDiceAttributeSet(id));
+ });
+ getAttrs(attributes, (values) => {
+ let pool = {};
+ if (single) {
+ (pool["id"] = ids[0]),
+ (pool["size"] = parseInt(values[`repeating_hd_${ids[0]}_size`] || 0)),
+ (pool["available"] =
+ parseInt(values[`repeating_hd_${ids[0]}_available`]) || 0);
+ pool["type"] = parseInt(values[`repeating_hd_${ids[0]}_type`]) || 0;
+ } else {
+ ids.forEach((id) => {
+ pool[`d${values[`repeating_hd_${id}_type`]}`] = {
+ id: id,
+ size: parseInt(values[`repeating_hd_${id}_size`] || 0),
+ available: parseInt(values[`repeating_hd_${id}_available`]) || 0,
+ };
+ });
+ }
+ if (typeof callback === "function") callback(pool);
+ });
+ });
+};
+var isValidEvent = function (eventInfo, blockWorker) {
+ if (
+ blockWorker &&
+ (!eventInfo.sourceType || eventInfo.sourceType != "player")
+ )
+ return false;
+ if (
+ eventInfo.newValue &&
+ eventInfo.previousValue &&
+ eventInfo.newValue != eventInfo.previousValue
+ )
+ return true;
+ if (eventInfo.newValue && !eventInfo.previousValue) return true;
+ return false;
+};
+var updateHitDicePool = function (newPool, silent) {
+ if (Object.keys(newPool).length === 0) return;
+ silent = silent || false;
+ getHitDicePool((availablePool) => {
+ let update = {};
+ Object.keys(newPool).forEach((die) => {
+ if (availablePool[die]) {
+ const id = availablePool[die].id;
+ Object.keys(newPool[die]).forEach((property) => {
+ update[`repeating_hd_${id}_${property}`] = newPool[die][property];
+ });
+ } else {
+ const id = generateRowID();
+ update[`repeating_hd_${id}_type`] = die.replace(/[^0-9]/g, "");
+ Object.keys(newPool[die]).forEach((property) => {
+ update[`repeating_hd_${id}_${property}`] = newPool[die][property];
+ });
+ }
+ });
+ if (silent) {
+ setAttrs(update, { silent: true });
+ } else {
+ setAttrs(update);
+ }
+ });
+};
+on("change:repeating_hd:size", (eventInfo) => {
+ if (isValidEvent(eventInfo, true)) {
+ const id = SheetUtils.getUID(eventInfo.sourceAttribute);
+ const newValue = eventInfo.newValue || 0;
+ const previousValue = eventInfo.previousValue || 0;
+ let hitDiceMax = 0;
+ getHitDicePool((allPool) => {
+ const selectedPoolKey = Object.keys(allPool).filter((die) => {
+ return allPool[die]["id"] == id;
+ });
+ const pool = allPool[selectedPoolKey];
+ const gained =
+ pool.size < pool.available
+ ? pool.size - pool.available
+ : Math.max(newValue - previousValue, 0);
+ const available = pool.available + gained;
+ const update = {
+ [`repeating_hd_${pool.id}_available`]: available,
+ };
+ Object.keys(allPool).forEach((die) => {
+ hitDiceMax += allPool[die]["size"];
+ });
+ setAttrs(update, () => {
+ setAttrs({ hit_dice_max: hitDiceMax }, { silent: true });
+ });
+ });
+ }
+});
+on("change:repeating_hd:available", (eventInfo) => {
+ if (isValidEvent(eventInfo, true)) {
+ getHitDicePool((pool) => {
+ let dicePoolSize = 0;
+ Object.keys(pool).forEach((die) => {
+ dicePoolSize += pool[die]["available"];
+ });
+ let update = { hit_dice: dicePoolSize };
+ setAttrs(update, { silent: true });
+ });
+ }
+});
+on("change:repeating_hd:consumed", (eventInfo) => {
+ const id = SheetUtils.getUID(eventInfo.sourceAttribute);
+ const poolAttribute = `repeating_hd_${id}_available`;
+ getAttrs([poolAttribute], (values) => {
+ const update = {
+ [poolAttribute]: Math.max(parseInt(values[poolAttribute]) - 1, 0),
+ };
+ setAttrs(update, { silent: true }, () => {
+ getHitDicePool((pool) => {
+ let dicePoolSize = 0;
+ Object.keys(pool).forEach((die) => {
+ dicePoolSize += pool[die]["available"];
+ });
+ let update = { hit_dice: dicePoolSize };
+ setAttrs(update, { silent: true });
+ });
+ });
+ });
+});
+on("change:use_per_class_hit_dice", (eventInfo) => {
+ set_level();
+});
+on("change:hit_dice", (eventInfo) => {
+ //For compatibility with rest script
+ getAttrs(["use_per_class_hit_dice", "hit_dice"], (values) => {
+ if (
+ values["use_per_class_hit_dice"] &&
+ values["use_per_class_hit_dice"] == 1
+ ) {
+ let increaseLeft = 0;
+ let updatePool = {};
+ getHitDicePool((pool) => {
+ let dicePoolSize = 0;
+ Object.keys(pool).forEach((die) => {
+ dicePoolSize += pool[die]["available"];
+ });
+ increaseLeft = parseInt(values["hit_dice"]) - dicePoolSize;
+ ["d12", "d10", "d8", "d6", "d4"].forEach((die) => {
+ if (pool[die] && pool[die]["available"] < pool[die]["size"]) {
+ const diff = Math.min(
+ pool[die]["size"] - pool[die]["available"],
+ increaseLeft
+ );
+ updatePool[die] = { available: pool[die]["available"] + diff };
+ increaseLeft -= diff;
+ return;
+ }
+ });
+ updateHitDicePool(updatePool, true);
+ });
+ }
+ });
+});
+on("clicked:show_hit_dice", (eventInfo) => {
+ getSectionIDs("repeating_hd", (ids) => {
+ let attributes = [];
+ ids.forEach((id) => {
+ attributes.push(`repeating_hd_${id}_type`);
+ attributes.push(`repeating_hd_${id}_size`);
+ attributes.push(`repeating_hd_${id}_available`);
+ });
+ getAttrs(attributes, (values) => {
+ const types = Object.keys(values).filter((entry) => {
+ return entry.indexOf("_type") > -1;
+ });
+ let dice = [];
+ let update = {
+ current_d4: 0,
+ current_d6: 0,
+ current_d8: 0,
+ current_d10: 0,
+ current_d12: 0,
+ current_d4_max: 0,
+ current_d6_max: 0,
+ current_d8_max: 0,
+ current_d10_max: 0,
+ current_d12_max: 0,
+ show_hit_dice_roll: "[[0]]",
+ };
+ types.forEach((type) => {
+ dice.push(values[type]);
+ const id = SheetUtils.getUID(type);
+ update[`current_d${values[type]}_max`] =
+ values[`repeating_hd_${id}_available`];
+ });
+ update["show_hit_dice"] = dice.join(" ");
+ setAttrs(update);
+ });
+ });
+});
+on(
+ "change:current_d4 change:current_d6 change:current_d4 change:current_d8 change:current_d10 change:current_d12",
+ (eventInfo) => {
+ if (eventInfo.newValue || eventInfo.previousValue) {
+ getAttrs(
+ [
+ "current_d4",
+ "current_d6",
+ "current_d8",
+ "current_d10",
+ "current_d12",
+ "constitution_mod",
+ ],
+ (values) => {
+ let query = [];
+ let totalDice = 0;
+ Object.keys(values)
+ .filter((entry) => {
+ return entry.includes("current_");
+ })
+ .forEach((entry) => {
+ if (parseInt(values[entry]) > 0) {
+ const splited = entry.split("_");
+ const dice = splited[splited.length - 1];
+ query.push(`${values[entry]}${dice}`);
+ totalDice += parseInt(values[entry]);
+ }
+ });
+ if (
+ totalDice > 0 &&
+ values["constitution_mod"] &&
+ values["constitution_mod"] != 0
+ )
+ query.push(parseInt(values["constitution_mod"]) * totalDice);
+ setAttrs({ show_hit_dice_roll: query.join(" + ") });
+ }
+ );
+ }
+ }
+);
+on("change:hit_dice_rolled", (eventInfo) => {
+ getSectionIDs("repeating_hd", (ids) => {
+ let attributes = [];
+ ids.forEach((id) => {
+ attributes.push(`repeating_hd_${id}_type`);
+ attributes.push(`repeating_hd_${id}_size`);
+ attributes.push(`repeating_hd_${id}_available`);
+ });
+
+ getAttrs(
+ [
+ ...attributes,
+ "current_d4",
+ "current_d6",
+ "current_d8",
+ "current_d10",
+ "current_d12",
+ ],
+ (values) => {
+ const types = Object.keys(values).filter((entry) => {
+ return entry.indexOf("_type") > -1;
+ });
+ let update = {
+ current_d4: 0,
+ current_d6: 0,
+ current_d8: 0,
+ current_d10: 0,
+ current_d12: 0,
+ current_d4_max: 0,
+ current_d6_max: 0,
+ current_d8_max: 0,
+ current_d10_max: 0,
+ current_d12_max: 0,
+ show_hit_dice: "",
+ show_hit_dice_roll: "[[0]]",
+ };
+ types.forEach((type) => {
+ const die = values[type];
+ if (
+ values[`current_d${die}`] &&
+ parseInt(values[`current_d${die}`]) > 0
+ ) {
+ const id = SheetUtils.getUID(type);
+ const result = parseInt(
+ values[`repeating_hd_${id}_available`] - values[`current_d${die}`]
+ );
+ update[`repeating_hd_${id}_available`] = Math.max(result, 0);
+ }
+ });
+ setAttrs(update);
+ }
+ );
+ });
+});
+on("clicked:hide_hit_dice", (eventInfo) => {
+ let update = {
+ current_d4: 0,
+ current_d6: 0,
+ current_d8: 0,
+ current_d10: 0,
+ current_d12: 0,
+ current_d4_max: 0,
+ current_d6_max: 0,
+ current_d8_max: 0,
+ current_d10_max: 0,
+ current_d12_max: 0,
+ show_hit_dice: "",
+ show_hit_dice_roll: "[[0]]",
+ };
+ setAttrs(update);
+});
+on("change:consumed_hero_points", (eventInfo) => {
+ getAttrs(["hero_points"], (values) => {
+ const hero_points = values["hero_points"]
+ ? parseInt(values["hero_points"])
+ : 0;
+ const update = { hero_points: Math.max(hero_points - 1, 0) };
+ setAttrs(update, { silent: true }, () => {});
+ });
+});
+on("change:hero_points", (eventInfo) => {
+ const hero_points = eventInfo.newValue ? Math.max(eventInfo.newValue, 0) : 0;
+ const update = { hero_points: hero_points };
+ setAttrs(update, { silent: true }, () => {});
+});
+on("change:level", (eventInfo) => {
+ updateHeroPoints(eventInfo.newValue);
+});
+on("change:use_hero_points", (eventInfo) => {
+ if (eventInfo.newValue && eventInfo.newValue == 1) updateHeroPoints();
+});
+var updateHeroPoints = function (level) {
+ if (level) {
+ const hero_points = level ? Math.floor(parseInt(level) / 2) + 5 : 0;
+ const update = { hero_points: hero_points };
+ setAttrs(update, { silent: true }, () => {});
+ } else {
+ getAttrs(["level"], (values) => {
+ const level = values.level ? values.level : 0;
+ updateHeroPoints(level);
+ });
+ }
+};
+
+const classRelatedAttrs = [
+ "class",
+ "subclass",
+ "base_level",
+ "multiclass1_flag",
+ "multiclass1",
+ "multiclass1_subclass",
+ "multiclass1_lvl",
+ "multiclass2_flag",
+ "multiclass2",
+ "multiclass2_subclass",
+ "multiclass2_lvl",
+ "multiclass3_flag",
+ "multiclass3",
+ "multiclass3_subclass",
+ "multiclass3_lvl",
+];
+const getSpellPoints = (callback) => {
+ getAttrs(classRelatedAttrs, (values) => {
+ let level = 0;
+ let characterClassAttributes = {
+ mainclass: {
+ class: "class",
+ subclass: "subclass",
+ level: "base_level",
+ },
+ };
+ for (let i = 1; i <= 3; i++) {
+ characterClassAttributes[`multiclass_${i}`] = {
+ enabled: `multiclass${i}_flag`,
+ class: `multiclass${i}`,
+ subclass: `multiclass${i}_subclass`,
+ level: `multiclass${i}_lvl`,
+ };
+ }
+ const pointsPerLevel = [
+ "",
+ 4,
+ 6,
+ 14,
+ 17,
+ 27,
+ 32,
+ 38,
+ 44,
+ 57,
+ 64,
+ 73,
+ 78,
+ 83,
+ 88,
+ 94,
+ 100,
+ 107,
+ 114,
+ 123,
+ 133,
+ ];
+ const getLevelInfo = (charClass, values) => {
+ let charLevel = 0;
+ if (!characterClassAttributes[charClass]) return charLevel;
+ if (
+ !characterClassAttributes[charClass]["enabled"] ||
+ (values[characterClassAttributes[charClass]["enabled"]] &&
+ values[characterClassAttributes[charClass]["enabled"]] == 1)
+ ) {
+ const subclass =
+ values[characterClassAttributes[charClass]["subclass"]] || "";
+ const level = values[characterClassAttributes[charClass]["level"]]
+ ? parseInt(values[characterClassAttributes[charClass]["level"]])
+ : 0;
+ charClass =
+ subclass.toLowerCase().includes("arcane trickster") ||
+ subclass.toLowerCase().includes("eldritch knight")
+ ? "third"
+ : values[characterClassAttributes[charClass]["class"]];
+ const casterType = getCasterType(charClass.toLowerCase());
+ if (casterType > 0) {
+ charLevel = Math.floor(level * casterType);
+ }
+ }
+ return charLevel;
+ };
+ Object.keys(characterClassAttributes).forEach((charClass) => {
+ const levelInfo = getLevelInfo(charClass, values);
+ level += levelInfo;
+ });
+ callback(pointsPerLevel[level]);
+ });
+};
+
+const setSpellPoints = () => {
+ getSpellPoints((spellPoints) => {
+ if (spellPoints > 0)
+ createResource("Spell Points", spellPoints, spellPoints);
+ });
+};
+
+classRelatedAttrs.forEach((attr) => {
+ on(`change:${attr}`, (evenInfo) => {
+ getAttrs(["use_spell_points"], (v) => {
+ if (v["use_spell_points"] && v["use_spell_points"] == 1) {
+ setSpellPoints();
+ }
+ });
+ });
+});
+
+on("change:use_spell_points", (eventInfo) => {
+ if (eventInfo.newValue && eventInfo.newValue == 1) {
+ setSpellPoints();
+ } else {
+ deleteResource("Spell Points");
+ }
+ update_spell_slots();
+});
+
+var updateSpellOutputDC = function (eventinfo) {
+ if (!eventinfo.newValue) return;
+ getAttrs(
+ [
+ "strength_mod",
+ "dexterity_mod",
+ "constitution_mod",
+ "intelligence_mod",
+ "wisdom_mod",
+ "charisma_mod",
+ "spell_save_dc",
+ "pb",
+ ],
+ (values) => {
+ let dc = 0;
+ const spellLevel = eventinfo.sourceAttribute
+ .split("_")[1]
+ .replace("spell-", "");
+ const pb = values.pb ? parseInt(values.pb) : 0;
+ if (eventinfo.newValue === "spell") {
+ const spellSaveDc = values["spell_save_dc"]
+ ? parseInt(values["spell_save_dc"])
+ : 8 + pb;
+ dc = spellSaveDc;
+ } else if (eventinfo.newValue === "0*") {
+ dc = 0;
+ } else {
+ const attr = eventinfo.newValue.replace(/@{|}\+/g, "");
+ const mod = values[attr] ? 8 + pb + parseInt(values[attr]) : 8 + pb;
+ dc = mod;
+ }
+ const id = SheetUtils.getUID(eventinfo.sourceAttribute);
+ const update = {};
+ update[`repeating_spell-${spellLevel}_${id}_roll_output_dc`] = dc;
+ setAttrs(update);
+ }
+ );
+};
+globalAttributesByCategory.spellLevels.forEach((level) => {
+ on(`change:repeating_spell-${level}:spell_ability`, (eventinfo) => {
+ updateSpellOutputDC(eventinfo);
+ });
+});
+
+
+on(`change:level`, (eventInfo) => {
+ const level = +eventInfo.newValue;
+ const profBonus = Math.floor(2 + (level - 1) / 4 );
+ setAttrs({ pb: profBonus });
+});
+
+
+on("clicked:move-reset", () => {
+ getAttrs(["moves_total"], v => {
+ setAttrs({moves_expended: v.moves_total || 0})
+ });
+});
+
+on("clicked:move-use", () => {
+ getAttrs(["moves_expended"], v => {
+ setAttrs({moves_expended: parseInt(v.moves_expended) - 1 || 0})
+ });
+});
+
+[1,2,3].forEach(level => {
+ on(`clicked:spell-reset-${level}`, () => {
+ getAttrs([`lvl${level}_slots_total`], v => setAttrs({[`lvl${level}_slots_expended`]: v[`lvl${level}_slots_total`] || 0}));
+ })
+ on(`clicked:spell-use-${level}`, () => {
+ getAttrs([`lvl${level}_slots_expended`], v => setAttrs({[`lvl${level}_slots_expended`]: parseInt(v[`lvl${level}_slots_expended`]) - 1|| 0}));
+ })
+})
diff --git a/Brancalonia Official/src/pug/abstracts/hiddenvariables.pug b/Brancalonia Official/src/pug/abstracts/hiddenvariables.pug
new file mode 100644
index 0000000000..1fa2b47b66
--- /dev/null
+++ b/Brancalonia Official/src/pug/abstracts/hiddenvariables.pug
@@ -0,0 +1,92 @@
+-
+ const hiddenvariables = [
+ { name:"version", value:"4.2" },
+ { name:"appliedUpdates", value: "", },
+ { name:"monster_confirm_flag", value: "", },
+ { name:"mancer_confirm_flag", value: "", },
+ { name:"d20", value: "1d20" },
+ { name:"level", value: "1" },
+ { name:"pb", value: "2" },
+ { name:"pbd_safe", value: "" },
+ { name:"jack", value: "1" },
+ { name:"jack_attr", value: "" },
+ { name:"jack_bonus", value: "" },
+ { name:"passive_wisdom", value: "10" },
+ { name:"hitdie_final", value: "" },
+ { name:"globalsavingthrowbonus", value: "" },
+ { name:"death_save_bonus", value: "0" },
+ { name:"initiative_bonus", value: "0" },
+ { name:"spell_save_dc", value: "0" },
+ { name:"spell_attack_bonus", value: "0" },
+ { name:"spell_attack_mod", value: "0" },
+ { name:"npc_legendary_actions_desc", value:"The creature can take 3 legendary actions, choosing from the options below. Only one legendary option can be used at a time and only at the end of another creature's turn. The creature regains spent legendary actions at the start of its turn." },
+ { name:"global_damage_mod_crit", value: "0" },
+ { name:"global_damage_mod_roll", value: "0" },
+ { name:"global_damage_mod_type", value: "" },
+ { name:"global_attack_mod", value: "" },
+ { name:"global_save_mod", value: "" },
+ { name:"global_skill_mod", value: "" },
+ { name:"exhaustion_1", value: "" },
+ { name:"exhaustion_2", value: "" },
+ { name:"exhaustion_3", value: "" },
+ { name:"exhaustion_4", value: "" },
+ { name:"exhaustion_5", value: "" },
+ { name:"exhaustion_6", value: "" },
+ { name:"strength_mod", value: "0" },
+ { name:"dexterity_mod", value: "0" },
+ { name:"constitution_mod", value: "0" },
+ { name:"intelligence_mod", value: "0" },
+ { name:"wisdom_mod", value: "0" },
+ { name:"charisma_mod", value: "0" },
+ { name:"honor_mod", value: "0" },
+ { name:"sanity_mod", value: "0" },
+ { name:"strength_save_bonus", value: "0" },
+ { name:"dexterity_save_bonus", value: "0" },
+ { name:"constitution_save_bonus", value: "0" },
+ { name:"intelligence_save_bonus", value: "0" },
+ { name:"wisdom_save_bonus", value: "0" },
+ { name:"charisma_save_bonus", value: "0" },
+ { name:"honor_save_bonus", value: "0" },
+ { name:"sanity_save_bonus", value: "0" },
+ { name:"strength_maximum", value: "20" },
+ { name:"dexterity_maximum", value: "20" },
+ { name:"constitution_maximum", value: "20" },
+ { name:"intelligence_maximum", value: "20" },
+ { name:"wisdom_maximum", value: "20" },
+ { name:"charisma_maximum", value: "20" },
+ { name:"honor_maximum", value: "20" },
+ { name:"sanity_maximum", value: "20" },
+ { name:"acrobatics_bonus", value: "0" },
+ { name:"animal_handling_bonus", value: "0" },
+ { name:"arcana_bonus", value: "0" },
+ { name:"athletics_bonus", value: "0" },
+ { name:"deception_bonus", value: "0" },
+ { name:"history_bonus", value: "0" },
+ { name:"insight_bonus", value: "0" },
+ { name:"intimidation_bonus", value: "0" },
+ { name:"investigation_bonus", value: "0" },
+ { name:"medicine_bonus", value: "0" },
+ { name:"nature_bonus", value: "0" },
+ { name:"perception_bonus", value: "0" },
+ { name:"performance_bonus", value: "0" },
+ { name:"persuasion_bonus", value: "0" },
+ { name:"religion_bonus", value: "0" },
+ { name:"sleight_of_hand_bonus", value: "0" },
+ { name:"stealth_bonus", value: "0" },
+ { name:"survival_bonus", value: "0" },
+ { name:"lvl1_slots_total", value: "0" },
+ { name:"lvl2_slots_total", value: "0" },
+ { name:"lvl3_slots_total", value: "0" },
+ { name:"lvl4_slots_total", value: "0" },
+ { name:"lvl5_slots_total", value: "0" },
+ { name:"lvl6_slots_total", value: "0" },
+ { name:"lvl7_slots_total", value: "0" },
+ { name:"lvl8_slots_total", value: "0" },
+ { name:"lvl9_slots_total", value: "0" },
+ { name:"l1mancer_status", value: "" },
+ { name:"lpmancer_status", value: "" },
+ { name:"queryadvantage", value: "" },
+ ];
+
+each field in hiddenvariables
+ input(name=`attr_${field.name}`, type="hidden", value=field.value)
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/abstracts/variables.pug b/Brancalonia Official/src/pug/abstracts/variables.pug
new file mode 100644
index 0000000000..e104669c93
--- /dev/null
+++ b/Brancalonia Official/src/pug/abstracts/variables.pug
@@ -0,0 +1,84 @@
+-
+ const globalAttributesByCategory = {
+ abilities: ['strength', 'dexterity', 'constitution', 'intelligence', 'wisdom', 'charisma'],
+ optionalAbilites: ['honor', 'sanity'],
+ alignments: ['Lawful Good', 'Neutral Good', 'Chaotic Good', 'Lawful Neutral', 'Neutral', 'Chaotic Neutral', 'Lawful Evil', 'Neutral Evil', 'Chaotic Evil'],
+ classes: ['artificer', 'bard', 'cleric', 'druid', 'paladin', 'ranger', 'sorcerer', 'warlock', 'wizard'],
+ sizes: ['Tiny', 'Small', 'Medium', 'Large', 'Huge', 'Gargantuan'],
+ diceSizes: ['d4', 'd6', 'd8', 'd10', 'd12'],
+ skills: [
+ {
+ name: "Acrobatics",
+ ability: "Dexterity"
+ },
+ {
+ name: "Animal Handling",
+ ability: "Wisdom"
+ },
+ {
+ name: "Arcana",
+ ability: "Intelligence"
+ },
+ {
+ name: "Athletics",
+ ability: "Strength"
+ },
+ {
+ name: "Deception",
+ ability: "Charisma"
+ },
+ {
+ name: "History",
+ ability: "Intelligence"
+ },
+ {
+ name: "Insight",
+ ability: "Wisdom"
+ },
+ {
+ name: "Intimidation",
+ ability: "Charisma"
+ },
+ {
+ name: "Investigation",
+ ability: "Intelligence"
+ },
+ {
+ name: "Medicine",
+ ability: "Wisdom"
+ },
+ {
+ name: "Nature",
+ ability: "Intelligence"
+ },
+ {
+ name: "Perception",
+ ability: "Wisdom"
+ },
+ {
+ name: "Performance",
+ ability: "Charisma"
+ },
+ {
+ name: "Persuasion",
+ ability: "Charisma"
+ },
+ {
+ name: "Religion",
+ ability: "Intelligence"
+ },
+ {
+ name: "Sleight of Hand",
+ ability: "Dexterity"
+ },
+ {
+ name: "Stealth",
+ ability: "Dexterity"
+ },
+ {
+ name: "Survival",
+ ability: "Wisdom"
+ },
+ ],
+ personalityTraits: ["Personality Traits", "Ideals", "Bonds", "Flaws"]
+ }
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/components/components.pug b/Brancalonia Official/src/pug/components/components.pug
new file mode 100644
index 0000000000..9a2c650516
--- /dev/null
+++ b/Brancalonia Official/src/pug/components/components.pug
@@ -0,0 +1,11 @@
+// PC
+include pc/AbilityScore
+include pc/InsProf
+include pc/PersonalityTrait
+include pc/SavingThrow
+include pc/Skills
+include pc/SpellContainer
+include pc/SpellLabel
+include pc/SpellSection
+include utility/SelectClass
+include utility/SelectHitDice
diff --git a/Brancalonia Official/src/pug/components/pc/AbilityScore.pug b/Brancalonia Official/src/pug/components/pc/AbilityScore.pug
new file mode 100644
index 0000000000..41764b6409
--- /dev/null
+++ b/Brancalonia Official/src/pug/components/pc/AbilityScore.pug
@@ -0,0 +1,16 @@
+mixin AbilityScore(attr, componentSettings = {})
+ - const { optional = false } = componentSettings;
+ - const shortName = attr.slice(0,3).toUpperCase();
+ - const className = (optional) ? ` toggleVisibilityBy-${attr}` : "";
+
+ if (optional)
+ input.toggleVisibility(type=`hidden` name=`attr_${attr}_toggle`)
+
+ .abilityscore(class=`abilityscore--${shortName} ${className}`)
+ button.abilityscore__rollbutton(type=`roll` name=`roll_${attr}` value=`@{wtype}&{template:simple} {{rname=^{${attr}-u}}} {{mod=@{${attr}_mod}@{jack_bonus}}} {{r1=[[@{d20}+@{${attr}_mod}@{jack_attr}[${shortName}]]]}} @{rtype}+@{${attr}_mod}@{jack_attr}[${shortName}]]]}} @{charname_output}` data-i18n=`${attr}-u`)
+ span.abilityscore__value(name=`attr_${attr}_mod` title=`@{${attr}_mod}`)
+ .abilityscore__mod
+ input.abilityscore__base(type=`text` name=`attr_${attr}_base` title=`@{${attr}}` value=`10`)
+ input(type=`hidden` name=`attr_${attr}` value=`10`)
+ input.abilityscore__flag(type=`hidden` name=`attr_${attr}_flag` value=`0`)
+ span.abilityscore__final(name=`attr_${attr}`)
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/components/pc/InsProf.pug b/Brancalonia Official/src/pug/components/pc/InsProf.pug
new file mode 100644
index 0000000000..0112c9851b
--- /dev/null
+++ b/Brancalonia Official/src/pug/components/pc/InsProf.pug
@@ -0,0 +1,12 @@
+mixin InsProf(name)
+ -
+ const typebox = (name.toLowerCase() === "inspiration") ? "inspprof--inspiration" :
+ (name.toLowerCase() === "pass-wis") ? "inspprof--passive"
+ : "";
+
+ .inspprof(class=typebox)
+ .inspprof__value
+ if (block)
+ block
+ .inspprof__label
+ span(data-i18n=name)
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/components/pc/PersonalityTrait.pug b/Brancalonia Official/src/pug/components/pc/PersonalityTrait.pug
new file mode 100644
index 0000000000..786793d7c6
--- /dev/null
+++ b/Brancalonia Official/src/pug/components/pc/PersonalityTrait.pug
@@ -0,0 +1,7 @@
+mixin PersonalityTrait(name)
+ - const attr = name.replace(/ /g, '_').replace(/[^a-zA-Z_]/g, "").replace(/__/g, "_").toLowerCase();
+ - const i18n = `${attr}-s`;
+ - const flag = attr.split(attr.indexOf('_'))[0];
+ .personalitytrait
+ .personalitytrait__label(data-i18n=name)
+ textarea(name=`attr_${attr}`)
diff --git a/Brancalonia Official/src/pug/components/pc/SavingThrow.pug b/Brancalonia Official/src/pug/components/pc/SavingThrow.pug
new file mode 100644
index 0000000000..1c0bc12047
--- /dev/null
+++ b/Brancalonia Official/src/pug/components/pc/SavingThrow.pug
@@ -0,0 +1,15 @@
+mixin SavingThrow (name, componentSettings = {})
+ - const { optional } = componentSettings;
+ - const attr = name.toLowerCase();
+ - const className = (optional) ? `toggleVisibilityBy-${attr}` : ``;
+
+ if (optional)
+ input.toggle(type=`hidden` name=`attr_${attr}_toggle`)
+
+ .savingthrow(class=className)
+ input(type=`hidden` name=`attr_${attr}_save_roll`)
+ .savingthrow__checkbox
+ input(type=`checkbox` name=`attr_${attr}_save_prof` title=`@{${attr}_save_prof}` value=`(@{pb})`)
+ span
+ span.savingthrow__value(name=`attr_${attr}_save_bonus` title=`@{${attr}_save_bonus}`)
+ button.savingthrow__button(type=`roll` name=`roll_${attr}_save` value=`@{${attr}_save_roll}` data-i18n=attr)
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/components/pc/Skills.pug b/Brancalonia Official/src/pug/components/pc/Skills.pug
new file mode 100644
index 0000000000..90c09f795f
--- /dev/null
+++ b/Brancalonia Official/src/pug/components/pc/Skills.pug
@@ -0,0 +1,13 @@
+mixin Skill(name, ability)
+ - const attr = name.toLowerCase().replace(/ /g, "_");
+ - const shortName = ability.split(0,3)[0].toUpperCase();
+
+ .skill(data-i18n-list-item=`${attr}`)
+ input(type=`hidden` name=`attr_${attr}_roll`)
+ .skill__checkbox
+ input(type=`checkbox` name=`attr_${attr}_prof` title=`@{${attr}_prof}` value=`(@{pb}*@{${attr}_type})`)
+ span
+ span.skill__value(name=`attr_${attr}_bonus` title=`@{${attr}_bonus}`) 0
+ button.skill__button(type=`roll` name=`roll_${attr}` value=`@{${attr}_roll}` data-i18n=`${attr}-core`)
+ | #{name}
+ span #{shortName}
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/components/pc/SpellContainer.pug b/Brancalonia Official/src/pug/components/pc/SpellContainer.pug
new file mode 100644
index 0000000000..d5bdbf627c
--- /dev/null
+++ b/Brancalonia Official/src/pug/components/pc/SpellContainer.pug
@@ -0,0 +1,208 @@
+mixin SpellContainer(level, isCantrip=false)
+ fieldset(class=`repeating_spell-${level}`)
+ .spell
+ //input.spell__flag--details(type="hidden" name="attr_details-flag" checked="checked")
+ input.spell__flag--options(type="hidden" name="attr_options-flag" checked="checked")
+
+ .spell__display
+ input(type="hidden" name="attr_rollcontent" value="@{wtype}&{template:spell} {{level=@{spellschool} @{spelllevel}}} {{name=@{spellname}}} {{castingtime=@{spellcastingtime}}} {{range=@{spellrange}}} {{target=@{spelltarget}}} @{spellcomp_v} @{spellcomp_s} @{spellcomp_m} {{material=@{spellcomp_materials}}} {{duration=@{spellduration}}} {{description=@{spelldescription}}} {{athigherlevels=@{spellathigherlevels}}} @{spellritual} {{innate=@{innate}}} {{savedc=@{spell_save_dc}}} @{spellconcentration} @{charname_output}")
+
+ if !isCantrip
+ .spell__prepped
+ input.spell__prepped-input(type="checkbox" name="attr_spellprepared" value="1")
+ span.spell__prepped-mark
+
+ button.spell__card-button(type="roll" name="roll_spell" value="@{rollcontent}")
+ span.spell__name(name="attr_spellname")
+ span.spell__innate(name="attr_innate")
+
+ .spell__indicators
+
+ input.spell__flag--innate(type="hidden" name="attr_innate" value="")
+ input.spell__flag--ritual(type="hidden" name="attr_spellritual" value="0")
+ input.spell__flag--concentration(type="hidden" name="attr_spellconcentration" value="0")
+ .spell__casting-details
+ span.spell__ritual(data-i18n="spell-ritual") R
+ span.spell__concentration(data-i18n="spell-concentration") C
+
+ input.spell__flag--v(type="hidden" name="attr_spellcomp_v" value="{{v=1}}")
+ input.spell__flag--s(type="hidden" name="attr_spellcomp_s" value="{{s=1}}")
+ input.spell__flag--m(type="hidden" name="attr_spellcomp_m" value="{{m=1}}")
+ .spell__components
+ span.spell__component--v(data-i18n="spell-component-verbal") V
+ span.spell__component--s(data-i18n="spell-component-somatic") S
+ span.spell__component--m(data-i18n="spell-component-material") M
+
+ input.spell__flag--spellsave(type="hidden" name="attr_roll_output_dc" value="@{spell_save_dc}")
+ button.spell__chat-button.output.btn.ui-draggable(type="roll" name="roll_output" value="@{wtype}&{template:spelloutput} {{level=@{spellschool} @{spelllevel}}} {{name=@{spellname}}} {{castingtime=@{spellcastingtime}}} {{range=@{spellrange}}} {{target=@{spelltarget}}} @{spellcomp_v} @{spellcomp_s} @{spellcomp_m} {{material=@{spellcomp_materials}}} {{duration=@{spellduration}}} {{description=@{spelldescription}}} {{athigherlevels=@{spellathigherlevels}}} @{spellritual} {{innate=@{innate}}} {{savedc=@{roll_output_dc}}} @{spellconcentration} @{charname_output}") w
+
+ //.spell__details-container
+ input.spell__flag--details(type="checkbox" name="attr_details-flag" checked="checked")
+ span i
+
+ .spell__options-container
+ input.spell__flag--options(type="checkbox" name="attr_options-flag" checked="checked")
+ span y
+
+ .spell__options.options
+ .options__row
+ span.options__label(data-i18n="name:-u") NAME:
+ input.options__flex(type="text" name="attr_spellname")
+
+ .options__row.options__row--noborder
+ span.options__label(data-i18n="school:-u") SCHOOL:
+ select.options__flex(name="attr_spellschool")
+ option(value="abjuration" data-i18n="abjuration") Abjuration
+ option(value="conjuration" data-i18n="conjuration") Conjuration
+ option(value="divination" data-i18n="divination") Divination
+ option(value="enchantment" data-i18n="enchantment") Enchantment
+ option(value="evocation" data-i18n="evocation") Evocation
+ option(value="illusion" data-i18n="illusion") Illusion
+ option(value="necromancy" data-i18n="necromancy") Necromancy
+ option(value="transmutation" data-i18n="transmutation") Transmutation
+ input.options__flex(type="checkbox" name="attr_spellritual" value="{{ritual=1}}")
+ span.options__label(data-i18n="ritual-u") RITUAL
+ .options__row.options__row--noborder
+ span.options__label(data-i18n="casting-time:-u") CASTING TIME:
+ input.options__flex(type="text" name="attr_spellcastingtime")
+ .options__row.options__row--noborder
+ span.options__label(data-i18n="range:-u") RANGE:
+ input.options__flex(type="text" name="attr_spellrange")
+ .options__row
+ span.options__label(data-i18n="target:-u") TARGET:
+ input.options__flex(type="text" name="attr_spelltarget")
+
+ input(type="hidden" name="attr_spellcomp")
+ .options__row.options__row--noborder
+ span.options__label(data-i18n="components:-u") COMPONENTS:
+ input.options__flex(type="checkbox" name="attr_spellcomp_v" value="{{v=1}}" checked="checked")
+ span.options__label(data-i18n="spell-component-verbal") V
+ input.options__flex(type="checkbox" name="attr_spellcomp_s" value="{{s=1}}" checked="checked")
+ span.options__label(data-i18n="spell-component-somatic") S
+ input.options__flex(type="checkbox" name="attr_spellcomp_m" value="{{m=1}}" checked="checked")
+ span.options__label(data-i18n="spell-component-material") M
+ .options__row
+ input.options__flex(type="text" name="attr_spellcomp_materials" placeholder="ruby dust worth 50gp" data-i18n-placeholder="ruby-dust-place")
+
+ .options__row
+ input.options__flex--1(type="checkbox" name="attr_spellconcentration" value="{{concentration=1}}")
+ span.options__label.options__flex--9(data-i18n="concentration-u") CONCENTRATION
+
+ .options__row
+ span.options__label(data-i18n="duration:-u") DURATION:
+ input.options__flex(type="text" name="attr_spellduration")
+
+ .options__row
+ span.options__label(data-i18n="spell-ability-u") SPELLCASTING ABILITY
+ select.options__flex(name="attr_spell_ability")
+ option(value="0*" data-i18n="none-u") NONE
+ option(value="spell" data-i18n="spell-u") SPELL
+ option(value="@{strength_mod}+" data-i18n="strength-u") STRENGTH
+ option(value="@{dexterity_mod}+" data-i18n="dexterity-u") DEXTERITY
+ option(value="@{constitution_mod}+" data-i18n="constitution-u") CONSTITUTION
+ option(value="@{intelligence_mod}+" data-i18n="intelligence-u") INTELLIGENCE
+ option(value="@{wisdom_mod}+" data-i18n="wisdom-u") WISDOM
+ option(value="@{charisma_mod}+" data-i18n="charisma-u") CHARISMA
+
+ .options__row
+ span.options__label(data-i18n="innate:-u") INNATE:
+ input.options__flex(type="text" name="attr_innate" placeholder="1/day" value="")
+
+ .options__row
+ span.options__label(data-i18n="output:-u") OUTPUT:
+ select.options__flex(name="attr_spelloutput")
+ option(value="SPELLCARD" data-i18n="spellcard-u") SPELLCARD
+ option(value="ATTACK" data-i18n="attack-u") ATTACK
+
+ input.spell__flag--output(type="hidden" name="attr_spelloutput")
+ .spell__options--attack
+
+ .options__row--noborder
+ span.options__label(data-i18n="spell-atk:-u") SPELL ATTACK:
+ select.options__flex(name="attr_spellattack")
+ option(value="None" data-i18n="none") None
+ option(value="Melee" data-i18n="melee") Melee
+ option(value="Ranged" data-i18n="ranged") Ranged
+ .options__row.options__row--noborder
+ span.options__label(data-i18n="damage:-u") DAMAGE:
+ input.options__flex(type="text" name="attr_spelldamage" )
+ span.options__label(data-i18n="type:-u") TYPE:
+ input.options__flex(type="text" name="attr_spelldamagetype" )
+ .options__row.options__row--noborder
+ span.options__label(data-i18n="damage2:-u") DAMAGE2:
+ input.options__flex(type="text" name="attr_spelldamage2" )
+ span.options__label(data-i18n="type:-u") TYPE:
+ input.options__flex(type="text" name="attr_spelldamagetype2" )
+ .options__row.options__row--noborder
+ span.options__label(data-i18n="healing:-u") HEALING:
+ input(type="text" name="attr_spellhealing" )
+ .options__row
+ input.options__flex--1(type="checkbox" name="attr_spelldmgmod" value="Yes")
+ span.options__label.options__flex--9(data-i18n="add-ability-mod-u") ADD ABILITY MOD TO DAMAGE OR HEALING
+
+ if isCantrip
+ .options__row
+ span.options__label(data-i18n="cantrip-progression:-u") CANTRIP PROGRESSION
+ select.options__flex(name="attr_spell_damage_progression")
+ option(value="" selected="selected" data-i18n="none-u") NONE
+ option(value="Cantrip Dice" data-i18n="cantrip-dice-u") CANTRIP DICE
+ option(value="Cantrip Beam" data-i18n="cantrip-beam-u") CANTRIP BEAM
+
+ .options__row
+ span.options__label(data-i18n="saving-throw:-u") SAVING THROW:
+ select(name="attr_spellsave")
+ option(value="" selected="selected" data-i18n="none-u") NONE
+ option(value="Strength" data-i18n="str-u") STR
+ option(value="Dexterity" data-i18n="dex-u") DEX
+ option(value="Constitution" data-i18n="con-u") CON
+ option(value="Intelligence" data-i18n="int-u") INT
+ option(value="Wisdom" data-i18n="wis-u") WIS
+ option(value="Charisma" data-i18n="cha-u") CHA
+
+ .options__row
+ span.options__label(data-i18n="effect:-u") EFFECT:
+ input(type="text" name="attr_spellsavesuccess" placeholder="Half damage" data-i18n-placeholder="half-dmg-place")
+
+ .options__row.options__row--noborder
+ span.options__label(data-i18n="at-higher-lvl-dmg:-u") HIGHER LVL CAST DMG:
+ .options__row
+ input.options__flex--3(type="text" name="attr_`spellhldie" placeholder="1" )
+ select.options__flex--3(name="attr_spellhldietype")
+ option(value="" selected="selected" data-i18n="none-u") NONE
+ option(value="d4") d4
+ option(value="d6") d6
+ option(value="d8") d8
+ option(value="d10") d10
+ option(value="d12") d12
+ option(value="d20") d20
+ span.options__flex--1 +
+ input.options__flex--3(type="text" name="attr_spellhlbonus" placeholder="0" )
+
+ .options__row
+ span.options__label.options__flex--7(data-i18n="include_spell_desc:-u") INCLUDE SPELL DESCRIPTION IN ATTACK:
+ select.options__flex--3(name="attr_includedesc")
+ option(value="off" selected="selected" data-i18n="off") Off
+ option(value="partial" data-i18n="partial") Partial
+ option(value="on" data-i18n="on") On
+
+ .options__row.options__row--topborder
+ span.options__label(data-i18n="description:-u") DESCRIPTION:
+ .options__row
+ textarea(name="attr_spelldescription")
+
+ if !isCantrip
+ .options__row.options__row--noborder
+ span.options__label(data-i18n="at-higher-lvl:-u") AT HIGHER LEVELS:
+ .options__row
+ textarea(name="attr_spellathigherlevels")
+
+ .options__row
+ span.options__label(data-i18n="class:-u") CLASS:
+ input(type="text" name="attr_spellclass" )
+
+ .options__row
+ span.options__label(data-i18n="type:-u") TYPE:
+ input(type="text" name="attr_spellsource" )
+
+ input(type="hidden" name="attr_spellattackid")
+ input(type="hidden" name="attr_spelllevel" value=`${level}`)
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/components/pc/SpellLabel.pug b/Brancalonia Official/src/pug/components/pc/SpellLabel.pug
new file mode 100644
index 0000000000..4c2fb1e1d7
--- /dev/null
+++ b/Brancalonia Official/src/pug/components/pc/SpellLabel.pug
@@ -0,0 +1,20 @@
+mixin SpellLabel(level)
+ - const label = (level === 0) ? "Cantrips" : level;
+ - var spellPointCostPerLevel = [0, 2, 3, 5, 6, 7, 9, 10, 11, 13];
+ - var spellPoinstCost = spellPointCostPerLevel[level];
+ .spell-label(class=`spell-label--${level}`)
+ .spell-label__numeral
+ .spell-label__label
+ if level !== 0
+ span(data-i18n="Level")
+ span #{ label }
+ if level !== 0
+ button.pictos(name=`act_spell-reset-${level}`, type="action") 1
+ button.pictos(name=`act_spell-use-${level}`, type="action") }
+ if level !== 0
+ .spell-label__total
+ .spell-label__title(data-i18n="total")
+ span(name=`attr_lvl${level}_slots_total`)
+ .spell-label__expended
+ .spell-label__title(data-i18n="current")
+ input(type="number", name=`attr_lvl${level}_slots_expended`, value!="0")
diff --git a/Brancalonia Official/src/pug/components/pc/SpellSection.pug b/Brancalonia Official/src/pug/components/pc/SpellSection.pug
new file mode 100644
index 0000000000..bfa5b96ef6
--- /dev/null
+++ b/Brancalonia Official/src/pug/components/pc/SpellSection.pug
@@ -0,0 +1,5 @@
+mixin SpellSection(level, isCantrip=false)
+ - const label = (level === 0) ? "cantrip" : level;
+ .spells__container
+ +SpellLabel(level, isCantrip)
+ +SpellContainer(label, isCantrip)
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/components/utility/selectClass.pug b/Brancalonia Official/src/pug/components/utility/selectClass.pug
new file mode 100644
index 0000000000..350b8df159
--- /dev/null
+++ b/Brancalonia Official/src/pug/components/utility/selectClass.pug
@@ -0,0 +1,12 @@
+mixin selectClass(attr = "class", defaultOption, mixinSettings )
+ - const { chooseOption = true, classNames = [] } = mixinSettings;
+ - const className = classNames.join(" ");
+ select.hiding.class(name=`attr_${attr}`, class=className)
+
+ if (chooseOption)
+ option(value=`` data-i18n=`choose`) Choose
+
+ for classAttr in globalAttributesByCategory.classes
+ - const name = classAttr.charAt(0).toUpperCase() + classAttr.slice(1);
+ - const selected = (classAttr === defaultOption) ? "selected" : "";
+ option(value=name data-i18n=classAttr) #{name}
diff --git a/Brancalonia Official/src/pug/components/utility/selectHitDice.pug b/Brancalonia Official/src/pug/components/utility/selectHitDice.pug
new file mode 100644
index 0000000000..2d6298eb96
--- /dev/null
+++ b/Brancalonia Official/src/pug/components/utility/selectHitDice.pug
@@ -0,0 +1,8 @@
+mixin selectHitDice(attr = "hitdiceroll", defaultOption, mixinSettings={} )
+ - const { chooseOption = true, classNames = []} = mixinSettings;
+ - const className = classNames.join(" ");
+
+ select(name=`attr_${attr}`, class=className)
+ each dieSize in globalAttributesByCategory.diceSizes
+ - const value = dieSize.split(1);
+ option(value=value) #{dieSize}
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/l1.pug b/Brancalonia Official/src/pug/l1.pug
new file mode 100644
index 0000000000..4c84ddf89b
--- /dev/null
+++ b/Brancalonia Official/src/pug/l1.pug
@@ -0,0 +1,600 @@
+mixin bottomBar(firstTab, lastTab)
+ .bottombar
+ button.prev(data-i18n='back' type='back' value=`l1-${firstTab}`)
+ button.jump(data-i18n='back-to-top' data-scroll='#top' type='button')
+ button.next(data-i18n='next' type='back' value=`l1-${lastTab}`)
+
+mixin cancelPrompt(slide)
+ .choice.cancel-prompt
+ p.label(data-i18n='charmancer-cancel-heading')
+ button.warning(data-i18n='cancel_charactermancer' type='cancel' value='l1-cancel')
+ button(data-i18n='save_progress_and_exit' type='cancel' value=`l1-${slide}`)
+ button(data-i18n='continue-charmancer' name='act_continue' type='action')
+ p.warning
+ span(data-i18n='charmancer-discard-warning')
+
+mixin buttonMancerInfo(name)
+ button.mancer_info(name=`act_info_${name}` type='action' required) i
+
+mixin infoDiv(className, acceptString)
+ .info
+ .sheet-compendium-page(accept=acceptString class=`sheet-${className}-info`)
+
+mixin abilitiesOptions()
+ option(data-i18n='choose' value='')
+ each val in globalAttributesByCategory.abilities
+ option(data-i18n=val value=val)
+
+mixin classOptions()
+ option(data-i18n='choose' value='')
+ each val in globalAttributesByCategory.classes
+ option(data-i18n=val value=val)
+
+mixin diceOptions()
+ option(data-i18n='choose' value='')
+ each val in globalAttributesByCategory.diceSizes
+ - const value = val.slice(-1)
+ option(data-i18n=val value=value)
+
+charmancer.sheet-charmancer-l1-welcome
+ .charmancer.container
+ input(type='hidden' name='comp_has_tasha' value='0')
+ ol.steps
+ .logos
+ span.charmancer-logo
+ span.compendium-logo
+ p.label(data-i18n='charmancer-welcome')
+ p(data-i18n='charmancer-what-is')
+ p.label(data-i18n='charmancer-compendium')
+ p(data-i18n='charmancer-compendium-detail')
+ p.label(data-i18n='get-started')
+ .bottombar
+ button.prev(data-i18n='opt-out-u' type='cancel' value='l1-cancel')
+ button.jump(data-i18n='back-to-top' data-scroll='#top' type='button')
+ button.next(data-i18n='next' type='back' value='l1-race')
+ +cancelPrompt('welcome')
+
+charmancer.sheet-charmancer-l1-race
+ .charmancer.container
+ ol.steps
+ .topbar-holder
+ .choices
+ .row
+ input(type='hidden' name='comp_has_tasha')
+ .customize-origin
+ label
+ span(data-i18n='customize-your-origin')
+ span(data-i18n='customize-your-origin-info')
+ .toggle
+ input(type='checkbox' name='comp_customize_origin' value='1')
+ .knob
+ .row
+ label.hilite
+ span(data-i18n='charmancer-choose-race')
+ select(accept='Category:Races' name='comp_race' required)
+ option(data-i18n='choose' value='')
+ option.custom(data-i18n='custom' value='Rules:Races')
+ +buttonMancerInfo('race')
+ .choice.custom_race
+ label.hilite(data-i18n='charmancer-custom-race-name')
+ input(name='comp_race_name' placeholder='Custom Race' type='text' required)
+ .row.choice.race_possible.custom_race.race_abilities
+ label
+ .choice.tasha_race_enabled
+ input(type='hidden' name='comp_tasha_race_ability_choice1_increase')
+ span.choice.tasha_race_ability_choice1.tasha(data-i18n='ability-score-increase-tasha')
+ select.choice.race_possible.tasha_race_ability_choice1(name='comp_tasha_race_ability_choice1')
+ +abilitiesOptions()
+ input(type='hidden' name='comp_tasha_race_ability_choice2_increase')
+ span.choice.tasha_race_ability_choice2.tasha(data-i18n='ability-score-increase-tasha')
+ select.choice.race_possible.tasha_race_ability_choice2(name='comp_tasha_race_ability_choice2')
+ +abilitiesOptions()
+ input(type='hidden' name='comp_tasha_race_ability_choice3_increase')
+ span.choice.tasha_race_ability_choice3.tasha(data-i18n='ability-score-increase-tasha')
+ select.choice.race_possible.tasha_race_ability_choice3(name='comp_tasha_race_ability_choice3')
+ +abilitiesOptions()
+ input(type='hidden' name='comp_tasha_race_ability_choice4_increase')
+ span.choice.tasha_race_ability_choice4.tasha(data-i18n='ability-score-increase-tasha')
+ select.choice.race_possible.tasha_race_ability_choice4(name='comp_tasha_race_ability_choice4')
+ +abilitiesOptions()
+ input(type='hidden' name='comp_tasha_race_ability_choice5_increase')
+ span.choice.tasha_race_ability_choice5.tasha(data-i18n='ability-score-increase-tasha')
+ select.choice.race_possible.tasha_race_ability_choice5(name='comp_tasha_race_ability_choice5')
+ +abilitiesOptions()
+ input(type='hidden' name='comp_tasha_race_ability_choice6_increase')
+ span.choice.tasha_race_ability_choice6.tasha(data-i18n='ability-score-increase-tasha')
+ select.choice.race_possible.tasha_race_ability_choice6(name='comp_tasha_race_ability_choice6')
+ +abilitiesOptions()
+ .choice.tasha_race_disabled
+ span(data-i18n='ability-score-increase')
+ p.race_ability_score.race_text
+ p.race_ability_choice_rule.race_text
+ select.choice.race_possible.race_ability_choice1(name='comp_race_ability_choice1')
+ +abilitiesOptions()
+ select.choice.race_possible.race_ability_choice2(name='comp_race_ability_choice2')
+ +abilitiesOptions()
+ select.choice.race_possible.race_ability_choice3(name='comp_race_ability_choice3')
+ +abilitiesOptions()
+ each val in globalAttributesByCategory.abilities
+ label.choice.custom_race
+ span(data-i18n=val)
+ input.choice.custom_race(max='5' min='-5' name=`comp_race_custom_${val}` type='number' value='0')
+ .row.choice.race_always.custom_race
+ label
+ span(data-i18n='alignment')
+ select(name='comp_alignment')
+ option(data-i18n='choose' value='')
+ each val in globalAttributesByCategory.alignments
+ - const datai18n = val.toLowerCase().replace(' ', '-')
+ option(data-i18n=datai18n value=val)
+ .row.choice.race_always.custom_race
+ label
+ span(data-i18n='size')
+ p.race_size.race_text
+ select.choice.custom_race(name='comp_size')
+ option(data-i18n='choose' value='')
+ each val in globalAttributesByCategory.sizes
+ - const datai18n = val.toLowerCase();
+ option(data-i18n=datai18n value=val)
+ .row.choice.race_always.custom_race
+ label
+ span(data-i18n='speed')
+ p.race_speed.race_text
+ input.choice.custom_race(min='0' name='comp_speed' type='number')
+ .race_holder.holder
+ .choice.subrace
+ .row
+ label.hilite
+ span(data-i18n='subrace')
+ select.choose_subrace(name='comp_subrace' required)
+ option(data-i18n='choose' value='')
+ option.custom(data-i18n='custom' value='Rules:Races')
+ +buttonMancerInfo('subrace')
+ .choice.custom_subrace
+ label.hilite
+ span(data-i18n='charmancer-custom-subrace-name')
+ input(name='comp_subrace_name' placeholder='Custom Subrace' type='text' required)
+ .choice.subrace_options
+ .row.choice.subrace_possible.subrace_abilities.custom_subrace
+ label
+ .choice.tasha_subrace_enabled
+ input(type='hidden' name='comp_tasha_subrace_ability_choice1_increase')
+ span.choice.tasha_subrace_ability_choice1.tasha(data-i18n='ability-score-increase-tasha')
+ select.choice.subrace_possible.tasha_subrace_ability_choice1(name='comp_tasha_subrace_ability_choice1')
+ +abilitiesOptions()
+ input(type='hidden' name='comp_tasha_subrace_ability_choice2_increase')
+ span.choice.tasha_subrace_ability_choice2.tasha(data-i18n='ability-score-increase-tasha')
+ select.choice.subrace_possible.tasha_subrace_ability_choice2(name='comp_tasha_subrace_ability_choice2')
+ +abilitiesOptions()
+ input(type='hidden' name='comp_tasha_subrace_ability_choice3_increase')
+ span.choice.tasha_subrace_ability_choice3.tasha(data-i18n='ability-score-increase-tasha')
+ select.choice.subrace_possible.tasha_subrace_ability_choice3(name='comp_tasha_subrace_ability_choice3')
+ +abilitiesOptions()
+ input(type='hidden' name='comp_tasha_subrace_ability_choice4_increase')
+ span.choice.tasha_subrace_ability_choice4.tasha(data-i18n='ability-score-increase-tasha')
+ select.choice.subrace_possible.tasha_subrace_ability_choice4(name='comp_tasha_subrace_ability_choice4')
+ +abilitiesOptions()
+ input(type='hidden' name='comp_tasha_subrace_ability_choice5_increase')
+ span.choice.tasha_subrace_ability_choice5.tasha(data-i18n='ability-score-increase-tasha')
+ select.choice.subrace_possible.tasha_subrace_ability_choice5(name='comp_tasha_subrace_ability_choice5')
+ +abilitiesOptions()
+ input(type='hidden' name='comp_tasha_subrace_ability_choice6_increase')
+ span.choice.tasha_subrace_ability_choice6.tasha(data-i18n='ability-score-increase-tasha')
+ select.choice.subrace_possible.tasha_subrace_ability_choice6(name='comp_tasha_subrace_ability_choice6')
+ +abilitiesOptions()
+ .choice.tasha_subrace_disabled
+ span(data-i18n='subrace-ability-increase')
+ p.subrace_ability_score.subrace_text
+ - let subraceChoiceInt = 1;
+ while subraceChoiceInt <= 3
+ select(class=`choice subrace_possible subrace_ability_choice${subraceChoiceInt}` name=`comp_subrace_ability_choice${subraceChoiceInt}`)
+ +abilitiesOptions()
+ - subraceChoiceInt++
+ each val in globalAttributesByCategory.abilities
+ label.choice.custom_subrace
+ span(data-i18n=val)
+ input.choice.custom_subrace(max='5' min='-5' name=`comp_subrace_custom_${val}` type='number' value='0')
+ .row.choice.subrace_possible.subrace_speed_row.custom_subrace
+ label
+ span(data-i18n='speed')
+ p.subrace_speed.subrace_text
+ input.choice.custom_subrace(name='comp_speed' min='0' type='number')
+ .subrace_holder.holder
+ .row.choice.race_possible.custom_race.custom_subrace
+ label
+ span(data-i18n='innate-spellcasting:')
+ label
+ span(data-i18n='spellcasting-ability')
+ select(name='comp_custom_race_spell_ability')
+ +abilitiesOptions()
+ label.hilite.choice.custom_spellcasting
+ span(data-i18n='number-of-cantrips')
+ input(min='1' name='comp_custom_race_spell_number' type='number' value='1' required)
+ label.hilite.choice.custom_spellcasting
+ span(data-i18n='spell-list')
+ select(name='comp_custom_race_spell_list')
+ +classOptions()
+ +infoDiv('race','Rules:Races')
+ +bottomBar('welcome', 'class')
+ +cancelPrompt('race')
+ input(name='comp_has_subrace' type='hidden')
+
+//- Class slide is throwing an error when converted to pug
+include ../html/charactermancer/class.html
+
+charmancer.sheet-charmancer-l1-abilities
+ .charmancer.container
+ ol.steps
+ .topbar-holder
+ input(name='comp_pointbuy_points' type='hidden' value='27')
+ input(name='comp_roll_results' type='hidden' value='0')
+ .choices
+ .row
+ label.hilite
+ span(data-i18n='ability-score-method')
+ select(name='comp_abilities' required)
+ option(data-i18n='choose' value='')
+ option.custom(data-i18n='custom' value='custom')
+ .row.choice.abilities_possible.abilities_stdarray
+ p(data-i18n='select-your-choices')
+ button(data-i18n='clear-abilities' name='act_clearstats' type='action')
+ .row.choice.abilities_possible.abilities_rollstats
+ p(data-i18n='select-your-choices')
+ p
+ .rollstats-button
+ button(data-i18n='standard-roll' type="roll" name="roll_rollstats" value="@{wtype}&{template:mancerroll} {{title=Roll for Stats}} {{r1=[[4d6dl1]]}} {{r2=[[4d6dl1]]}} {{r3=[[4d6dl1]]}} {{r4=[[4d6dl1]]}} {{r5=[[4d6dl1]]}} {{r6=[[4d6dl1]]}}")
+ button(data-i18n='clear-abilities' name='act_clearstats' type='action')
+ .row.choice.abilities_possible.abilities_rollstats_rolled
+ p
+ span(data-i18n='stats-rolled-hint')
+ .row.choice.abilities_possible.abilities_pointbuy
+ p(data-i18n='select-your-choices')
+ p
+ span(data-i18n='available-points:')
+ strong
+ span(class='points_available_display')
+ button(data-i18n='clear-abilities' name='act_clearstats' type='action')
+ .choice.abilities_possible.abilities_selects
+ .row
+ .hilite
+ each val in globalAttributesByCategory.abilities
+ div
+ span.label(data-i18n=val)
+ span(class=`abilities_radio_${val}` name=`comp_${val}` required)
+ each val in globalAttributesByCategory.optionalAbilites
+ .sheet-choice(class=`${val}_toggle`)
+ span.label(data-i18n=val)
+ span(class=`abilities_radio_${val}` name=`comp_${val}` required)
+ .row.choice.abilities_possible.abilities_custom
+ p(data-i18n='input-your-scores')
+ .abilities_possible.abilities_selects
+ .hilite
+ each val in globalAttributesByCategory.abilities
+ div
+ span.label(data-i18n=val)
+ input(max='20' min='0' name=`comp_${val}` type='number' required)
+ each val in globalAttributesByCategory.optionalAbilites
+ .sheet-choice(class=`${val}_toggle`)
+ span.label(data-i18n=val)
+ input(min="0" max="20" name=`comp_${val}` type="number" required)
+ +infoDiv('abilscores','Rules:Ability%20Scores')
+ +bottomBar('class', 'background')
+ +cancelPrompt('abilities')
+
+mixin backgroundOptions(type)
+ label
+ span(data-i18n=type)
+ br
+ select.choice.background_possible.background_ideal_choice(name=`comp_background_${type}_choice`)
+ option(data-i18n='choose' value='')
+ button.choice.standardbg.bg_roll(data-i18n='roll' name=`roll_background_${type}_choice_roll` type='roll' value='')
+ input.choice.custom_background(name=`comp_background_${type}_choice` type='text')
+
+charmancer.sheet-charmancer-l1-background
+ .charmancer.container
+ ol.steps
+ .topbar-holder
+ .choices
+ .row
+ label.hilite
+ span(data-i18n='choose-background')
+ select(accept='Category:Backgrounds' name='comp_background' required)
+ option(data-i18n='choose' value='')
+ option.custom(data-i18n='custom' value='Rules:Backgrounds')
+ .choice.custom_background
+ label.hilite
+ span(data-i18n='name-background')
+ input(name='comp_background_name' placeholder='Artisan' type='text' required)
+ .choice.backgrounds_options
+ .holder.background_holder
+ .row.choice.background_possible.background_detail_choice_row
+ label
+ span.label
+ span.background_detail_choice_name(data-i18n='option' name='comp_background_detail_choice_name')
+ br
+ select.choice.background_possible.background_detail_choice(name='comp_background_detail_choice')
+ option(data-i18n='choose' value='')
+ button.choice.standardbg.bg_roll(data-i18n='roll' name='roll_background_detail_choice_roll' type='roll' value='')
+ .row.choice.background_possible.background_personality_row.custom_background
+ label
+ span(data-i18n='personality-traits')
+ br
+ - let backgroundChoiceInt = 1;
+ while backgroundChoiceInt <= 2
+ select.choice.background_possible.background_personality_choice1(name=`comp_background_personality_choice${backgroundChoiceInt}`)
+ option(data-i18n='choose' value='')
+ button.choice.standardbg.bg_roll(data-i18n='roll' name=`roll_background_personality_choice${backgroundChoiceInt}_roll` type='roll' value='')
+ input.choice.custom_background(name=`comp_background_personality_choice${backgroundChoiceInt}` type='text')
+ - backgroundChoiceInt++
+ each val in ['ideal', 'bond', 'flaw']
+ +backgroundOptions(val)
+ .row.choice.background_possible.background_equipment_row
+ p
+ span.label(data-i18n='equipment')
+ span.background_standard_equipment
+ +infoDiv('background','Rules:Backgrounds')
+ +bottomBar('abilities', 'equipment')
+ +cancelPrompt('background')
+
+ each val in ['detail_choice', 'personality_choice1', 'personality_choice2', 'ideal_choice', 'bond_choice', 'flaw_choice']
+ input(name=`comp_background_${val}_array` type='hidden')
+
+charmancer.sheet-charmancer-l1-equipment
+ .charmancer.container
+ ol.steps
+ .topbar-holder
+ .choices
+ each val in ['equipment_class', 'equipment_background', 'starting_gold_roll', 'background_starting_gold']
+ input(name=`comp_${val}` type='hidden')
+ .row
+ p.choice.no_class
+ span.label(data-i18n='you-havent-selected-class')
+ p.choice.eqp_custom_class
+ span.label(data-i18n='you-have-created-custom-class')
+ p.choice.no_gold_option
+ span.label(data-i18n='pick-your-equipment')
+ span :
+ span.class_label
+ .choice.has_class.equipment_type.hilite
+ p
+ span.label(data-i18n='equipment-choice-text')
+ span(data-i18n='class')
+ span :
+ span.class_label
+ select.equipment_type(name='comp_equipment_type' required)
+ option(data-i18n='choose' value='')
+ option(data-i18n='class-equipment' value='class')
+ option(data-i18n='starting-wealth' value='gold')
+ .row.choice.gold_option
+ p.choice.custom_class_gold
+ span.label(data-i18n='equipment-from-class')
+ span (
+ span.class_label
+ span )
+ p
+ span.label(data-i18n='starting-gold:')
+ p
+ .choice.random_gold_option
+ button(name='roll_starting_gold' type='roll' value='')
+ span.starting_gold_btn_label
+ input(name='comp_starting_gold' type='number' value='0')
+ .row.choice.class_option
+ p
+ span.class_equipment
+ - let equipmentChoiceInt = 1;
+ while equipmentChoiceInt <= 4
+ p.equipment_choice_title
+ span.choice.class_possible(class=`class_equipment_choice${equipmentChoiceInt} class_equipment_choice${equipmentChoiceInt}_title`)
+ select.choice.class_possible(class=`class_equipment_choice${equipmentChoiceInt}` name=`comp_class_equipment_choice${equipmentChoiceInt}`)
+ option(data-i18n='choose' value='')
+ select.choice.class_possible(class=`class_equipment_choice${equipmentChoiceInt}_double` name=`comp_class_equipment_choice${equipmentChoiceInt+4}`)
+ option(data-i18n='choose' value='')
+ - equipmentChoiceInt++
+ .row.choice.no_class_warning
+ span.warning(data-i18n='no_class_warning-u')
+ .row
+ p.choice.no_background
+ span.label(data-i18n='you-havent-chosen-background')
+ p.choice.has_background.class_option
+ span.label(data-i18n='equipment-from-background')
+ span (
+ span.background_label
+ span )
+ p.choice.background_chose_starting_gold.background_gold_option
+ span.label(data-i18n='you-have-chosen-starting-gold')
+ p.choice.has_background.class_option
+ span.background_equipment
+ .choice.class_option
+ - let backEquipInt = 1;
+ while backEquipInt <= 4
+ p.equipment_choice_title
+ span.choice.background_possible(class=`background_equipment_choice${backEquipInt} background_equipment_choice${backEquipInt}_title`)
+ select.choice.background_possible(class=`background_equipment_choice${backEquipInt}` name=`comp_background_equipment_choice${backEquipInt}`)
+ option(data-i18n='choose' value='')
+ - backEquipInt++
+ +infoDiv('background','Rules:Equipment')
+ +bottomBar('background', 'spells')
+ +cancelPrompt('equipment')
+
+charmancer.sheet-charmancer-l1-spells
+ .charmancer.container
+ ol.steps
+ .topbar-holder
+ .choice.no_spells
+ p.label(data-i18n='arcane-is-mystery')
+ p(data-i18n='your-character-dont-have-spells-this-lvl')
+ .choices.spell_holder
+ .info.choice.spell-info-container
+ .sheet-compendium-page.sheet-spell-info(accept='Rules:Spells' class=`sheet-spells-info`)
+ +bottomBar('equipment', 'feat')
+ +cancelPrompt('spells')
+ each val in ['race_spells', 'class_spells', 'race_number', 'class_number']
+ input(name=`comp_${val}` type='hidden')
+
+mixin featChoices(type, acceptString)
+ .row.choice.feat_possible(class=`feat_${type}_row`)
+ label
+ span(data-i18n=`${type}-proficiencies`)
+ - const typePlural = `${type}s`
+ p.feat_text(class=`feat_${typePlural}`)
+ - let choiceInt = 1;
+ while choiceInt <= 4
+ if acceptString
+ select.choice.feat_possible(class=`feat_${type}_choice${choiceInt}` name=`comp_feat_${type}_choice${choiceInt}` accept=acceptString)
+ option(data-i18n='choose' value='')
+ else
+ select.choice.feat_possible(class=`feat_${type}_choice${choiceInt}` name=`comp_feat_${type}_choice${choiceInt}`)
+ option(data-i18n='choose' value='')
+ - choiceInt++
+
+charmancer.sheet-charmancer-l1-feat
+ .charmancer.container
+ ol.steps
+ .topbar-holder
+ .choice.no_feat
+ p.label(data-i18n='charmancer-a-feat-represents')
+ p(data-i18n='you-really-havent-done')
+ .choices.choice.yes_feat
+ .row
+ label
+ span(data-i18n='choose-a-feat:')
+ select(accept='Category:Feats' name='comp_feat')
+ option(data-i18n='choose' value='')
+ .choice.feat_options
+ .row.choice.feat_prereq.feat_possible
+ label.warning
+ span(data-i18n='prerequisite:')
+ p.feat_prerequisite.feat_text
+ p.feat_text(data-i18n='feat-pre-check')
+ .row.choice.feat_ability.feat_possible
+ label
+ span(data-i18n='ability-score-increase:')
+ p.feat_ability_score.feat_text
+ select.choice.feat_possible.feat_ability_choice(name='comp_feat_ability_choice')
+ option(data-i18n='choose' value='')
+ +featChoices('language')
+ +featChoices('skill', 'Category:Proficiencies Type:Skill')
+ +featChoices('weapon')
+ +featChoices('armor')
+ +featChoices('tool')
+ .sheet-row.sheet-choice.sheet-feat_possible.sheet-feat_spell_row
+ label
+ span(data-i18n='spell-list') Spell List:
+ span(style='color: red;')
+ p.sheet-feat_text.sheet-feat_spells
+ select.sheet-choice.sheet-feat_possible.sheet-feat_spell_choice1(name='comp_feat_spell_choice1')
+ option(data-i18n='choose' value='') Choose
+ select.sheet-choice.sheet-feat_possible.sheet-feat_spell_choice2(name='comp_feat_spell_choice2')
+ option(data-i18n='choose' value='') Choose
+ select.sheet-choice.sheet-feat_possible.sheet-feat_spell_choice3(name='comp_feat_spell_choice3')
+ option(data-i18n='choose' value='') Choose
+ select.sheet-choice.sheet-feat_possible.sheet-feat_spell_choice4(name='comp_feat_spell_choice4')
+ option(data-i18n='choose' value='') Choose
+ .row.choice.feat_possible.feat_expertise_row
+ label
+ span(data-i18n='expertise')
+ each val in [1, 2]
+ select(class=`choice feat_possible feat_expertise_choice${val}` name=`comp_feat_expertise_choice_${val}`)
+ option(data-i18n='choose' value='')
+ .row.choice.feat_possible.feat_feature_row_1
+ h4.feat_feature_name_1
+ span(class='feat_feature_1')
+ select.feat_possible.feat_feature_choice_1(name='comp_feat_feature_choice_1')
+ option(data-i18n='choose' value='')
+ option.custom(data-i18n='custom')
+ p.description.feat_feature_description_1
+ .row.choice.feat_possible.feat_feature_row_1_double
+ h4.feat_feature_name_1_double
+ span.feat_feature_1_double
+ select.feat_possible.feat_feature_choice_1_double(name='comp_feat_feature_choice_3')
+ option(data-i18n='choose' value='')
+ option.custom(data-i18n='custom')
+ p.description.feat_feature_description_1_double
+ .row.choice.feat_possible.feat_feature_row_2
+ h4.feat_feature_name_2
+ span.feat_feature_2
+ select.feat_possible.feat_feature_choice_2(name='comp_feat_feature_choice_2')
+ option(data-i18n='choose' value='')
+ option.custom(data-i18n='custom')
+ p.description.feat_feature_description_2
+ .choice.row.feat_possible.other_options_and_features1
+ label
+ span.other_options_and_features_title1
+ select.feat_possible.other_options_and_features_choice1(name='comp_other_options_and_features_choice1')
+ option(data-i18n='choose' value='')
+ .choice.row.feat_possible.other_options_and_features2
+ label
+ span.other_options_and_features_title2
+ select.feat_possible.other_options_and_features_choice1(name='comp_other_options_and_features_choice2')
+ option(data-i18n='choose' value='')
+ .info.feat-info-container.choice.yes_feat
+ .sheet-compendium-page.sheet-feat-info(accept='Rules:Feats')
+ +bottomBar('spells', 'bio')
+ +cancelPrompt('feat')
+
+
+charmancer.sheet-charmancer-l1-bio
+ .charmancer.container
+ ol.steps
+ .topbar-holder
+ .choices
+ input(name='comp_previous_race' type='hidden' value='')
+ each val in ['Name', 'Age', 'Height', 'Weight', 'Eyes', 'Hair', 'Skin']
+ - const attributeName = val === 'Name' ? 'character_name' : val.toLowerCase();
+ - const datai18n = val === 'Name' ? 'char-name-u' : val === 'Eyes' ? `eye-u` : `${val.toLowerCase()}-u`;
+ .row
+ label
+ div(data-i18n=datai18n)
+ input(name=`comp_${attributeName}` type='text')
+ +infoDiv('race','Rules:Races')
+ +bottomBar('feat', 'summary')
+ +cancelPrompt('bio')
+
+
+mixin summaryBlocks(type)
+ .summary
+ p.label(data-i18n=type)
+ div(class=`${type}_info`)
+ .choice.returnblock(class=`${type}_button`)
+ span(data-i18n='return-to:')
+ button.step(data-i18n=`${type}-u` type='back' value=`l1-${type}`)
+
+charmancer.sheet-charmancer-l1-summary
+ .charmancer
+ ol.steps
+ .topbar-holder
+ p.choice.ready_text(data-i18n='charmancer-only-choice-left-is-on-or')
+ p.label.ready_message
+ p.label(data-i18n='review-your-choices')
+ .summary-container
+ +summaryBlocks('race')
+ +summaryBlocks('class')
+ +summaryBlocks('abilities')
+ +summaryBlocks('background')
+ +summaryBlocks('equipment')
+ +summaryBlocks('spells')
+ .summary
+ p.label(data-i18n='feats')
+ .feat_info
+ .summary
+ p.label(data-i18n='bio')
+ .race_warning
+ .bio_info
+ .bottombar
+ button.prev(data-i18n='back' type='back' value='l1-bio')
+ button.jump(data-i18n='back-to-top' data-scroll='#top' type='button')
+ button.next.apply_changes(data-i18n='apply-changes' type='finish' value=`l1-mancer`)
+ +cancelPrompt('summary')
+
+
+charmancer.sheet-charmancer-final
+ .charmancer
+ div
+ h1(data-i18n='building-your-character')
+ .mancer_progress
+ div(style='width: 0%')
+ input(name='attr_mancer_category' type='hidden')
+ input(name='attr_mancer_progress' type='hidden')
+
+
+
diff --git a/Brancalonia Official/src/pug/layouts/headers/core.pug b/Brancalonia Official/src/pug/layouts/headers/core.pug
new file mode 100644
index 0000000000..31e51c73a0
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/headers/core.pug
@@ -0,0 +1,61 @@
+.header
+ .name-container
+ img(src='https://app.roll20.net/images/dndstyling/srd5_360.png' style='padding-bottom: 5px;' alt='SRD5 by Roll20')
+ input(type='text' name='attr_character_name' style='width: 100%;')
+ span.label(data-i18n='char-name-u') CHARACTER NAME
+ input.options-flag(type='checkbox' name='attr_options-class-selection' checked='checked')
+ span y
+ .header-info.options
+ .row(style='border-top: 2px dashed gold;')
+ span(data-i18n='class:-u') CLASS:
+ input.flag(type='hidden' name='attr_custom_class')
+ select.hiding.class(name='attr_class')
+ option(value='' data-i18n='choose') Choose
+ option(value='Artificer' data-i18n='artificer') Artificer
+ option(value='Barbarian' data-i18n='barbarian') Barbarian
+ option(value='Bard' data-i18n='bard') Bard
+ option(value='Cleric' data-i18n='cleric') Cleric
+ option(value='Druid' data-i18n='druid') Druid
+ option(value='Fighter' data-i18n='fighter') Fighter
+ option(value='Monk' data-i18n='monk') Monk
+ option(value='Paladin' data-i18n='paladin') Paladin
+ option(value='Ranger' data-i18n='ranger') Ranger
+ option(value='Rogue' data-i18n='rogue') Rogue
+ option(value='Sorcerer' data-i18n='sorcerer') Sorcerer
+ option(value='Warlock' data-i18n='warlock') Warlock
+ option(value='Wizard' data-i18n='wizard') Wizard
+ input.showing(type='text' name='attr_cust_classname' style='width: 90px;')
+ span(data-i18n='subclass:-u') SUBCLASS:
+ input(type='text' name='attr_subclass')
+ span(data-i18n='lvl:-u') LEVEL:
+ input.class-level(type='number' style='width: 40px' name='attr_base_level' value='1')
+ .row
+ span(data-i18n='race:-u') RACE:
+ input(type='text' name='attr_race')
+ span(data-i18n='subrace:-u') SUBRACE:
+ input(type='text' name='attr_subrace')
+ .header-info.display
+ .top
+ .hlabel-container
+ input.class-display.no_events(type='text' name='attr_class_display')
+ span.label(data-i18n='class-level-u') CLASS & LEVEL
+ .hlabel-container
+ input(type='text' name='attr_background' style='width: 182px;')
+ span.label(data-i18n='background-u') BACKGROUND
+ .bottom
+ .hlabel-container
+ input.no_events(type='text' name='attr_race_display')
+ span.label(data-i18n='race-u') RACE
+ .hlabel-container
+ input(type='text' name='attr_alignment')
+ span.label(data-i18n='alignment-u') ALIGNMENT
+ .hlabel-container(style='position: relative;')
+ input(type='hidden' name='attr_invalidXP')
+ input(type='text' name='attr_experience')
+ span.label(data-i18n='exp-pts-u') EXPERIENCE POINTS
+ input.showleveler(type='hidden' name='attr_showleveler' value='0')
+ button.levelerbutton(type='action' name='act_launch_lvl+mancer' style='padding: 0px; position: absolute; top: -10px; right: 0px;' title='Charactermancer Level Up')
+ img(src='https://s3.amazonaws.com/files.d20.io/images/175804938/qmVmtNHONHhHcd9cxCxm7w/med.png?1604618286' style='height: 18px; width: 18px; max-width: inherit;' alt='Wand & Hammer logo of Charactermancer')
+ .invalidXP
+ span.icon !
+ span.message(data-i18n='invalidxp') Enter a number for Level Up reminder
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/headers/header.pug b/Brancalonia Official/src/pug/layouts/headers/header.pug
new file mode 100644
index 0000000000..b772204f46
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/headers/header.pug
@@ -0,0 +1,24 @@
+.header
+ .alignment
+ input.alignment__value(name="attr_alignment", type="text")
+ .alignment__label(data-i18n="Alignment") Alignment
+ .playername
+ input.playername__value(name="attr_playername", type="text")
+ .playername__label(data-i18n="Player Name") Player Name
+ .logo
+ .classlevel
+ .class
+ input.class__value(type="text", name="attr_class", title="@{class}")
+ .class__label(data-i18n="Class") Class
+ .level
+ input.level__value(type="text", name="attr_level", title="@{level}")
+ .level__label(data-i18n="Level") Level
+ .background
+ input.background__value(name="attr_background", type="text")
+ .background__label(data-i18n="Background") Background
+ .name
+ input.name__value(name="attr_character_name", type="text")
+ .name__label(data-i18n="Character Name") Character Name
+ .race
+ input.race__value(name="attr_race", type="text")
+ .race__label(data-i18n="Race") Race
diff --git a/Brancalonia Official/src/pug/layouts/panels/AttacksSpellcasting.pug b/Brancalonia Official/src/pug/layouts/panels/AttacksSpellcasting.pug
new file mode 100644
index 0000000000..119d744f97
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/AttacksSpellcasting.pug
@@ -0,0 +1,181 @@
+input.ammoflag(type='hidden' name='attr_ammotracking')
+.attacks()
+ .attacks__header
+ span(data-i18n='name-u') NAME
+ span(data-i18n='atk-u') ATK
+ span(data-i18n='dmg-type-u') DAMAGE/TYPE
+ fieldset.repeating_attack
+ .attack
+ input.options__flag(name='attr_options-flag', type="hidden", value='on')
+ .attack__display
+ button.attack__button(type='roll' name='roll_attack' value='@{rollbase}')
+ span.attack__name(name='attr_atkname')
+ input.attack__bonus(type='text' name='attr_atkbonus' value='')
+ input.attack__type(type='text' name='attr_atkdmgtype' value='')
+ .options__cog
+ input(type='checkbox' name='attr_options-flag' checked='checked')
+ span y
+ .attack__options.options
+ .options__row
+ span.options__label(data-i18n='name:-u') NAME:
+ input(type='text' name='attr_atkname')
+ .options__row.options__row--noborder
+ input(type='checkbox' name='attr_atkflag' value='{{attack=1}}' checked='checked')
+ span.options__label(data-i18n='attack:-u') ATTACK:
+ select(name='attr_atkattr_base')
+ option(value='@{strength_mod}' selected='selected' data-i18n='str-u') STR
+ option(value='@{dexterity_mod}' data-i18n='dex-u') DEX
+ option(value='@{constitution_mod}' data-i18n='con-u') CON
+ option(value='@{intelligence_mod}' data-i18n='int-u') INT
+ option(value='@{wisdom_mod}' data-i18n='wis-u') WIS
+ option(value='@{charisma_mod}' data-i18n='cha-u') CHA
+ option(value='spell' data-i18n='spell-u') SPELL
+ option(value='0') -
+ span +
+ input(type='text' name='attr_atkmod' placeholder='0')
+ span +
+ input(type='checkbox' name='attr_atkprofflag' value='(@{pb})' checked='checked' )
+ span(data-i18n='proficient-u') PROFICIENT
+ .options__row.options__row--noborder
+ span.options__label(data-i18n='range:-u') RANGE:
+ input(type='text' name='attr_atkrange' placeholder='Self (60-foot cone)' data-i18n-placeholder='range-place')
+ .options__row
+ span.options__label(data-i18n='magic-bonus:-u') MAGIC BONUS:
+ input.options__flex--2(type='text' name='attr_atkmagic' placeholder='0')
+ span.options__label(data-i18n='crit-range-u') CRIT RANGE:
+ input.options__flex--2(type='text' name='attr_atkcritrange' value='20' placeholder='20')
+ .options__row.options__row--noborder
+ input(type='checkbox' name='attr_dmgflag' value='{{damage=1}} {{dmg1flag=1}}' checked='checked')
+ span.options__label(data-i18n='damage:-u') DAMAGE:
+ input(type='text' name='attr_dmgbase' placeholder='1d6' )
+ span.options__label +
+ select(name='attr_dmgattr')
+ option(value='@{strength_mod}' selected='selected' data-i18n='str-u') STR
+ option(value='@{dexterity_mod}' data-i18n='dex-u') DEX
+ option(value='@{constitution_mod}' data-i18n='con-u') CON
+ option(value='@{intelligence_mod}' data-i18n='int-u') INT
+ option(value='@{wisdom_mod}' data-i18n='wis-u') WIS
+ option(value='@{charisma_mod}' data-i18n='cha-u') CHA
+ option(value='spell' data-i18n='spell-u') SPELL
+ option(value='0') -
+ span.options__label +
+ input(type='text' name='attr_dmgmod' placeholder='0')
+ .options__row
+ span.options__label(data-i18n='type:-u') TYPE:
+ input(type='text' name='attr_dmgtype' placeholder='Slashing' data-i18n-placeholder='dmg-type-place')
+ span.options__label(data-i18n='crit:-u') CRIT:
+ input(type='text' name='attr_dmgcustcrit' placeholder='1d6' )
+ .options__row.options__row--noborder
+ input(type='checkbox' name='attr_dmg2flag' value='{{damage=1}} {{dmg2flag=1}}')
+ span.options__label(data-i18n='damage2:-u') DAMAGE2:
+ input(type='text' name='attr_dmg2base' placeholder='1d6' )
+ span.options__label +
+ select(name='attr_dmg2attr')
+ option(value='@{strength_mod}' data-i18n='str-u') STR
+ option(value='@{dexterity_mod}' data-i18n='dex-u') DEX
+ option(value='@{constitution_mod}' data-i18n='con-u') CON
+ option(value='@{intelligence_mod}' data-i18n='int-u') INT
+ option(value='@{wisdom_mod}' data-i18n='wis-u') WIS
+ option(value='@{charisma_mod}' data-i18n='cha-u') CHA
+ option(value='spell' data-i18n='spell-u') SPELL
+ option(value='0' selected='selected') -
+ span.options__label +
+ input(type='text' name='attr_dmg2mod' placeholder='0')
+ .options__row
+ span(data-i18n='type:-u') TYPE:
+ input(type='text' name='attr_dmg2type' placeholder='Slashing' data-i18n-placeholder='dmg-type-place')
+ span(data-i18n='crit:-u') CRIT:
+ input(type='text' name='attr_dmg2custcrit' placeholder='1d6' )
+ .options__row.options__row--noborder
+ input(type='checkbox' name='attr_saveflag' value='{{save=1}} {{saveattr=@{saveattr}}} {{savedesc=@{saveeffect}}} {{savedc=[[[[@{savedc}]][SAVE]]]}}')
+ span.options__label(data-i18n='saving-throw:-u') SAVING THROW:
+ select.options__flex(name='attr_saveattr')
+ option(value='Strength' selected='selected' data-i18n='str-u') STR
+ option(value='Dexterity' data-i18n='dex-u') DEX
+ option(value='Constitution' data-i18n='con-u') CON
+ option(value='Intelligence' data-i18n='int-u') INT
+ option(value='Wisdom' data-i18n='wis-u') WIS
+ option(value='Charisma' data-i18n='cha-u') CHA
+ .options__row.options__row--noborder
+ span.options__label.options__flex--4(data-i18n='vs-dc:-u') VS DC:
+ select.options__flex(name='attr_savedc')
+ option(value='(@{spell_save_dc})' selected='selected' data-i18n='spell-u') SPELL
+ option(value='(@{strength_mod}+8+@{spell_dc_mod}+@{pb})' data-i18n='str-u') STR
+ option(value='(@{dexterity_mod}+8+@{spell_dc_mod}+@{pb})' data-i18n='dex-u') DEX
+ option(value='(@{constitution_mod}+8+@{spell_dc_mod}+@{pb})' data-i18n='con-u') CON
+ option(value='(@{intelligence_mod}+8+@{spell_dc_mod}+@{pb})' data-i18n='int-u') INT
+ option(value='(@{wisdom_mod}+8+@{spell_dc_mod}+@{pb})' data-i18n='wis-u') WIS
+ option(value='(@{charisma_mod}+8+@{spell_dc_mod}+@{pb})' data-i18n='cha-u') CHA
+ option(value='(@{saveflat})' data-i18n='flat-u') FLAT
+ input.flatflag(type='hidden' name='attr_savedc')
+ input.flat(type='text' name='attr_saveflat' placeholder='10' value='10')
+ .options__row
+ span.options__label.options__flex--4(data-i18n='save-effect:-u') SAVE EFFECT:
+ input(type='text' name='attr_saveeffect' placeholder='half damage' data-i18n-placeholder='save-effect-place')
+ .options__row
+ span.options__label(data-i18n='ammunition:-u') AMMUNITION:
+ input(type='text' name='attr_ammo' placeholder='Arrows' data-i18n-placeholder='ammunition-place')
+ .options__row
+ span.options__label(data-i18n='description:-u') DESCRIPTION:
+ textarea(name='attr_atk_desc' placeholder='Up to 2 creatures within 5 feet' data-i18n-placeholder='description-place')
+
+ input(type='hidden' name='attr_rollbase')
+ input(type='hidden' name='attr_rollbase_dmg')
+ input(type='hidden' name='attr_rollbase_crit')
+ input(type='hidden' name='attr_hldmg')
+ input(type='hidden' name='attr_spelllevel')
+ input(type='hidden' name='attr_itemid')
+ input(type='hidden' name='attr_spellid')
+ input(type='hidden' name='attr_spell_innate')
+ input(type='hidden' name='attr_versatile_alt')
+ button.hidden(type='roll' name='roll_attack_dmg' value='@{rollbase_dmg}')
+ button.hidden(type='roll' name='roll_attack_crit' value='@{rollbase_crit}')
+ input.toggleflag(type='hidden' name='attr_global_attack_mod_flag')
+ .hidden.textbox.globalattack
+ span(data-i18n='global-attack-u') GLOBAL ATTACK MODIFIER
+ fieldset.repeating_tohitmod
+ .global-mod
+ input.options-flag(type='checkbox' name='attr_options-flag' checked='checked' )
+ span y
+ input.active-flag(type='checkbox' name='attr_global_attack_active_flag' value='1')
+ .options
+ .row
+ span(data-i18n='name:-u') NAME:
+ input(type='text' name='attr_global_attack_name' value='' placeholder='Bless')
+ .row
+ span(data-i18n='roll:-u') ROLL:
+ input(type='text' name='attr_global_attack_roll' value='' placeholder='1d4')
+ .globaldisplay
+ button.ellipsis(type='roll' name='roll_global_save' value='@{wtype}&{template:simple} {{rname=@{global_attack_name}}} {{r1=[[@{global_attack_roll}]]}} {{normal=1}} @{charname_output}')
+ span(name='attr_global_attack_roll')
+ span(name='attr_global_attack_name')
+ input.toggleflag(type='hidden' name='attr_global_damage_mod_flag')
+ .hidden.globalattack.global-dmg
+ span(data-i18n='global-damage-u') GLOBAL DAMAGE MODIFIER
+ fieldset.repeating_damagemod
+ .global-mod
+ input.options-flag(type='checkbox' name='attr_options-flag' checked='checked' )
+ span y
+ input.active-flag(type='checkbox' name='attr_global_damage_active_flag' value='1')
+ .options
+ .row
+ span(data-i18n='name:-u') NAME:
+ input(type='text' name='attr_global_damage_name' value='' placeholder='Sneak Attack')
+ .row
+ span(data-i18n='dmg:-u') DAMAGE:
+ input(type='text' name='attr_global_damage_damage' value='' placeholder='1d6')
+ .row
+ span(data-i18n='critical-dmg:-u') CRITICAL DAMAGE:
+ input(type='text' name='attr_global_damage_critical_damage' value='' placeholder='1d6')
+ .row
+ span(data-i18n='type:-u') TYPE:
+ input(type='text' name='attr_global_damage_type' value='' placeholder='Sneak')
+ .display
+ span.title(name='attr_global_damage_name')
+ span.subheader
+ button.ellipsis(type='roll' name='roll_global_save' value='@{wtype}&{template:simple} {{rname=@{global_damage_type}}} {{r1=[[@{global_damage_damage}]]}} {{normal=1}} @{charname_output}')
+ span(name='attr_global_damage_damage')
+ span(name='attr_global_damage_critical_damage')
+ span(name='attr_global_damage_type')
+
+ .attacks__label(data-i18n="Attacks & Spellcasting") Attacks & Spellcasting
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/panels/Coins.pug b/Brancalonia Official/src/pug/layouts/panels/Coins.pug
new file mode 100644
index 0000000000..aa65d78403
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/Coins.pug
@@ -0,0 +1,13 @@
+.money
+ .coin
+ span.coin__label(data-i18n="L")
+ input(type="number", name="attr_l", placeholder="0")
+ .coin
+ span.coin__label(data-i18n="P")
+ input(type="number", name="attr_p", placeholder="0")
+ .coin
+ span.coin__label(data-i18n="S")
+ input(type="number", name="attr_s", placeholder="0")
+ .coin
+ span.coin__label(data-i18n="G")
+ input(type="number", name="attr_g", placeholder="0")
diff --git a/Brancalonia Official/src/pug/layouts/panels/DeathSaves.pug b/Brancalonia Official/src/pug/layouts/panels/DeathSaves.pug
new file mode 100644
index 0000000000..6d9c0dae77
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/DeathSaves.pug
@@ -0,0 +1,31 @@
+.deathsaves
+ .deathsaves__container
+ .deathsaves__label
+ button(
+ type="roll",
+ name="roll_death_save",
+ value="@{wtype}&{template:simple} {{rname=^{death-save-u}}} {{mod=@{death_save_bonus}}} {{r1=[[@{d20}+@{death_save_bonus}[MOD]@{globalsavingthrowbonus}]]}} {{normal=1}} {{global=@{global_save_mod}}} @{charname_output}",
+ data-i18n="death-saves-u"
+ ) DEATH SAVES
+ .deathsaves__successes
+ span.deathsaves__text(data-i18n="successes-u") SUCCESSES
+ .deathsaves__check
+ input(type="checkbox", name="attr_deathsave_succ1")
+ span
+ .deathsaves__check
+ input(type="checkbox", name="attr_deathsave_succ2")
+ span
+ .deathsaves__check
+ input(type="checkbox", name="attr_deathsave_succ3")
+ span
+ .deathsaves__failures
+ span.deathsaves__text(data-i18n="failures-u") FAILURES
+ .deathsaves__check
+ input(type="checkbox", name="attr_deathsave_fail1")
+ span
+ .deathsaves__check
+ input(type="checkbox", name="attr_deathsave_fail2")
+ span
+ .deathsaves__check
+ input(type="checkbox", name="attr_deathsave_fail3")
+ span
diff --git a/Brancalonia Official/src/pug/layouts/panels/Equipment.pug b/Brancalonia Official/src/pug/layouts/panels/Equipment.pug
new file mode 100644
index 0000000000..5635b7a8bc
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/Equipment.pug
@@ -0,0 +1,65 @@
+.equipment
+ .equipment__header
+ span.equipment__count.pictos *
+ span.equipment__title(data-i18n="item-name-u") ITEM NAME
+ span.equipment__weighti
+ img(
+ src="https://app.roll20.net/images/dndstyling/weight_lbs.png",
+ alt="Weight symbol"
+ )
+
+ fieldset.repeating_inventory
+ .item
+ input.item__optionsflag(type="hidden", name="attr_inventory_options")
+ .item__titlerow
+ input.item__equipped(
+ type="checkbox",
+ name="attr_equipped",
+ value="1",
+ checked="checked"
+ )
+ input.item__count(type="text", name="attr_itemcount", value="1")
+ input.item__name(type="text", name="attr_itemname")
+ input.item__weight(type="text", name="attr_itemweight")
+ .item__optionsflag
+ input.item__optionscheck(
+ type="checkbox",
+ name="attr_inventory_options"
+ )
+ span.pictos y
+ .item__options.options
+ .options__row.options__row--checkbox
+ input.equipped(
+ type="checkbox",
+ name="attr_equipped",
+ value="1",
+ checked="checked"
+ )
+ span.equippedlabel(data-i18n="equipped-u") EQUIPPED
+ .options__row.options__row--checkbox
+ input.equipped(type="checkbox", name="attr_useasresource", value="1")
+ span.equippedlabel(data-i18n="use-as-resource-u") USE AS A RESOURCE
+ .options__row.options__row--checkbox
+ input.equipped(type="checkbox", name="attr_hasattack", value="1")
+ span.equippedlabel(data-i18n="has-attack-u") HAS AN ATTACK
+ .options__row
+ span(data-i18n="prop:-u") PROP:
+ input(type="text", name="attr_itemproperties")
+ .options__row
+ span(data-i18n="mods:-u") MODS:
+ input(type="text", name="attr_itemmodifiers")
+ .options__row
+ textarea.subtextarea(name="attr_itemcontent")
+ input(type="hidden", name="attr_itemattackid")
+ input(type="hidden", name="attr_itemresourceid")
+
+ .equipment__weighttotal
+ span.equipment__encumbrancetitle(data-i18n="total-weight-u") TOTAL WEIGHT
+ input.equipment__encumbrance(
+ type="number",
+ name="attr_weighttotal",
+ value="0"
+ )
+ input(type="hidden", name="attr_encumbrance")
+
+ .equipment__label(data-i18n="Equipment") Equipment
diff --git a/Brancalonia Official/src/pug/layouts/panels/Exhaustion.pug b/Brancalonia Official/src/pug/layouts/panels/Exhaustion.pug
new file mode 100644
index 0000000000..7652b0ff7d
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/Exhaustion.pug
@@ -0,0 +1,12 @@
+.exhaustions
+ input(type="hidden", name="attr_exhaustion", value="0")
+ .exhaustions__checks
+ each i in [0, 1, 2, 3, 4, 5, 6]
+ .exhaustion
+ input.exhaustion__radio(type="radio", name="attr_exhaustion", value=i)
+ span.exhaustion__text= i
+ .exhaustions__tracker
+ each url, i in ["https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/exhaustion-0_wulpge.png", "https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/exhaustion-1_fzmarb.png", "https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/exhaustion-2_prwgr3.png", "https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/exhaustion-3_hvsfbn.png", "https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/exhaustion-4_bnucar.png", "https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/exhaustion-5_ncgzva.png", "https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/exhaustion-6_zles7f.png"]
+ - const className = `exhaustions__level--${i}`;
+ img.exhaustions__level(class=className, src=url)
+ span.exhaustions__label(data-i18n="Exhaustion") Exhaustion
diff --git a/Brancalonia Official/src/pug/layouts/panels/Features.pug b/Brancalonia Official/src/pug/layouts/panels/Features.pug
new file mode 100644
index 0000000000..5b47b72f0d
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/Features.pug
@@ -0,0 +1,32 @@
+.features
+ .features__label(data-i18n="feats-traits-u") FEATURES & TRAITS
+ fieldset.repeating_traits
+ .feature
+ input.feature__flag--options(type="hidden" name="attr_options-flag" value="on")
+ .feature__display
+ span.feature__title(name="attr_name")
+ span.feature__subheader
+ span(name="attr_source")
+ span :
+ span(name="attr_source_type")
+ button.feature__chat-button(type="roll" name="roll_output" value="@{wtype}&{template:traits} @{charname_output} {{name=@{name}}} {{source=@{source}: @{source_type}}} {{description=@{description}}}") w
+ .feature__options-container
+ input.feature__flag--options(type="checkbox" name="attr_options-flag" checked="checked")
+ span y
+ .feature__options.options
+ .options__row
+ span(data-i18n="name:-u") NAME:
+ input(type="text" name="attr_name")
+ .options__row
+ span(data-i18n="source:-u") SOURCE:
+ select(name="attr_source")
+ option(selected="selected" data-i18n="racial") Racial
+ option(data-i18n="class") Class
+ option(data-i18n="feat") Feat
+ option(data-i18n="background") Background
+ option(data-i18n="other") Other
+ .options__row
+ span(data-i18n="source-type:-u") SOURCE TYPE:
+ input(type="text" name="attr_source_type" placeholder="Dwarf/Fighter/4th Level")
+ .options__row
+ textarea(name="attr_description")
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/panels/GlobalACMod.pug b/Brancalonia Official/src/pug/layouts/panels/GlobalACMod.pug
new file mode 100644
index 0000000000..fcf9439f00
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/GlobalACMod.pug
@@ -0,0 +1,22 @@
+input.toggleflag(type='hidden' name='attr_global_ac_mod_flag')
+.equipment.hidden
+ .textarea.globalattack.acmod
+ fieldset.repeating_acmod
+ .global-mod
+ input.options-flag(type='checkbox' name='attr_options-flag' checked='checked' style='top: -15px;')
+ span y
+ input.active-flag(type='checkbox' name='attr_global_ac_active_flag' value='1')
+ .options
+ label
+ | Value:
+ input(type='number' name='attr_global_ac_val' placeholder='1')
+ label
+ | Name:
+ input(type='text' name='attr_global_ac_name' placeholder='Defense')
+ .display
+ span.title.ellipsis
+ span(name='attr_global_ac_val')
+ | [
+ span(name='attr_global_ac_name')
+ | ]
+ span.label(data-i18n='global-ac-u') GLOBAL AC MODIFIER
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/panels/GlobalSaveRepeating.pug b/Brancalonia Official/src/pug/layouts/panels/GlobalSaveRepeating.pug
new file mode 100644
index 0000000000..342eab87d8
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/GlobalSaveRepeating.pug
@@ -0,0 +1,19 @@
+input.toggleflag(type='hidden' name='attr_global_save_mod_flag')
+.hidden.textarea.globalattack
+ span.label(data-i18n='global-save-u' style='position: relative; padding-bottom: 5px;') GLOBAL SAVE MODIFIER
+ fieldset.repeating_savemod
+ .global-mod
+ input.options-flag(type='checkbox' name='attr_options-flag' checked='checked' style='top: -15px;')
+ span y
+ input.active-flag(type='checkbox' name='attr_global_save_active_flag' value='1')
+ .options
+ .row
+ span(data-i18n='name:-u') NAME:
+ input(type='text' name='attr_global_save_name' value='' placeholder='Bless' style='width:75px')
+ .row
+ span(data-i18n='roll:-u') ROLL:
+ input(type='text' name='attr_global_save_roll' value='' placeholder='1d4' style='width:75px')
+ .globaldisplay(style='width: 75%')
+ button.ellipsis(type='roll' name='roll_global_save' value='@{wtype}&{template:simple} {{rname=@{global_save_name}}} {{r1=[[@{global_save_roll}]]}} {{normal=1}} @{charname_output}')
+ span(name='attr_global_save_roll')
+ span(name='attr_global_save_name')
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/panels/HeroPoints.pug b/Brancalonia Official/src/pug/layouts/panels/HeroPoints.pug
new file mode 100644
index 0000000000..0e14be22cc
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/HeroPoints.pug
@@ -0,0 +1,12 @@
+input(type='hidden' name='attr_use_hero_points')
+.hero-points
+ input(type='hidden' name='attr_hero_points')
+ .value
+ input(type='text' name='attr_hero_points' value='0')
+ .label
+ button.roll-hd.btn.ui-draggable(type='roll' name='roll_hero_points' value='@{wtype}&{template:simple} {{rname=^{hero-points-u}}} {{r1=[[d6]]}} {{normal=1}} {{r2=[[0d20]]}} @{charname_output}' title='Roll Hero Points')
+ span
+ span(data-i18n='hero-points-u') HERO POINTS
+ | (1D6)
+ span(data-i18n='none-left-u') NONE LEFT
+ input(type='checkbox' name='attr_consumed_hero_points' value='1')
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/panels/Knock.pug b/Brancalonia Official/src/pug/layouts/panels/Knock.pug
new file mode 100644
index 0000000000..7748647200
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/Knock.pug
@@ -0,0 +1,12 @@
+.knocks
+ input(type="hidden", name="attr_knock", value="0")
+ .knocks__tracker
+ each url, i in ["https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/knocks-0_vjhzm1.png","https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/knocks-1_jw2f7g.png","https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/knocks-2_vjnn6l.png","https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/knocks-3_k5vfqe.png","https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/knocks-4_qgcbum.png","https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558384/knocks-5_tdonfo.png","https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558384/knocks-6_ta9dgm.png"]
+ - const className = `knocks__level--${i}`;
+ img.knocks__level(class=className, src=url)
+ .knocks__checks
+ each i in [0, 1, 2, 3, 4, 5, 6]
+ .knock
+ input.knock__radio(type="radio", name="attr_knock", value=i)
+ span.knock__text= i
+ span.knocks__label(data-i18n="Knocks") Knocks
diff --git a/Brancalonia Official/src/pug/layouts/panels/MissingInfo.pug b/Brancalonia Official/src/pug/layouts/panels/MissingInfo.pug
new file mode 100644
index 0000000000..989b9c7d96
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/MissingInfo.pug
@@ -0,0 +1,7 @@
+input.missing-info-flag(type='hidden' name='attr_missing_info')
+.missing-info
+ span
+ span.info-popup.pictos i
+ | Looking for missing data?
+ span.missing-info-desc
+ | Your data is in the simple version that can be re-enabled from the Settings(gear) tab of the character sheet. Under GENERAL OPTIONS and then FEATS & TRAITS. Set the section to be 'Simple'.
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/panels/Moves.pug b/Brancalonia Official/src/pug/layouts/panels/Moves.pug
new file mode 100644
index 0000000000..afb4e8cdad
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/Moves.pug
@@ -0,0 +1,30 @@
+.moves
+ .move-label(class=`move-label--${level}`)
+ .move-label__numeral
+ .move-label__label
+ span(data-i18n="moves-u") Moves
+ button.pictos(name="act_move-reset", type="action") 1
+ button.pictos(name="act_move-use", type="action") }
+ .move-label__total
+ .move-label__title(data-i18n="total")
+ span(name=`attr_moves_total`)
+ input(name=`attr_moves_total`, type="hidden", value="0")
+ .move-label__expended
+ .move-label__title(data-i18n="current")
+ input(type="number", name=`attr_moves_expended`, value="0")
+ fieldset.repeating_moves
+ .move
+ input.move__flag--options(type="hidden" name="attr_options-flag" value="on")
+ span.move__title(name="attr_name")
+ button.move__chat-button(type="roll" name="roll_output" value="@{wtype}&{template:traits} @{charname_output} {{name=@{name}}} {{source=@{source}: @{source_type}}} {{description=@{description}}}") w
+ .move__options-container
+ input.move__flag--options(type="checkbox" name="attr_options-flag" checked="checked")
+ span y
+ .move__options.options
+ .options__row
+ span(data-i18n="name:-u") NAME:
+ input(type="text" name="attr_name")
+ .options__row--noborder
+ span(data-i18n="description:-u") DESCRIPTION:
+ .options__row
+ textarea(name="attr_description")
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/panels/OtherProficiencies.pug b/Brancalonia Official/src/pug/layouts/panels/OtherProficiencies.pug
new file mode 100644
index 0000000000..3d0dae9fc2
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/OtherProficiencies.pug
@@ -0,0 +1,30 @@
+.otherprofs
+ input.hiddenflag__flag(type='hidden' name='attr_simpleproficencies' value='complex')
+ textarea.hiddenflag__simple(name='attr_other_proficiencies_and_languages' style='min-height: 91px; height: 91px;')
+ .hiddenflag__complex
+ .otherprofs__header
+ span.label(data-i18n='type-u') TYPE
+ span.label(data-i18n='proficency-u') PROFICIENCY
+ fieldset.repeating_proficiencies
+ .otherprof
+ input.options__flag(name='attr_options-flag', type="hidden", value='on')
+ .toolprof__options.options
+ .options__row
+ span.options__label.options__flex(data-i18n='type:-u') TYPE:
+ select.options__flex(name='attr_prof_type')
+ option(selected='selected' data-i18n='lang-u') LANGUAGE
+ option(data-i18n='weapon-u') WEAPON
+ option(data-i18n='armor-u') ARMOR
+ option(data-i18n='other-u') OTHER
+ .options__row
+ span.options__label.options__flex(data-i18n='proficency-u') PROFICIENCY
+ input.options__flex(type='text' name='attr_name' placeholder='Elven, Dwarven, and Common')
+ .otherprof__display
+ button.otherprof__button(type='roll' name='roll_output' value='@{wtype}&{template:traits} @{charname_output} {{name=@{prof_type} PROFICIENCY}} {{description=@{name}}}')
+ span.otherprof__type(name='attr_prof_type')
+ span.otherprof__name(name='attr_name')
+ .options__cog
+ input(type='checkbox' name='attr_options-flag' checked='checked')
+ span y
+ .otherprofs__label
+ span(data-i18n='other-prof-langs-u') OTHER PROFICIENCIES & LANGUAGES
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/panels/Piety.pug b/Brancalonia Official/src/pug/layouts/panels/Piety.pug
new file mode 100644
index 0000000000..93eb9a9f16
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/Piety.pug
@@ -0,0 +1,76 @@
+input(type='hidden' name='attr_use_piety')
+.piety
+ input.details-flag(type='checkbox' name='attr_piety_details-flag' checked='checked')
+ span i
+ .container
+ .header
+ .score
+ input(type='number' name='attr_piety' value='1')
+ span Piety
+ label.deity
+ span Deity:
+ input(type='text' placeholder="Deity's name..." name='attr_piety_deity')
+ .earning
+ span.title Earning Piety
+ fieldset.repeating_earning
+ .desc
+ input(type='hidden' name='attr_desc' value='')
+ textarea(name='attr_desc' placeholder='Enter description...')
+ span(name='attr_desc')
+ .losing
+ span.title Losing Piety
+ fieldset.repeating_losing
+ .desc
+ input(type='hidden' name='attr_desc' value='')
+ textarea(name='attr_desc' placeholder='Enter description...')
+ span(name='attr_desc')
+ input.toggle(type='hidden' name='attr_piety' value='1')
+ .none
+ span
+ | You haven't aquired enough piety. Keep true to you deity and good things will come.
+ .devotee
+ span.rank
+ span(name='attr_piety_deity')
+ span Devotee
+ span.subheader
+ | Piety 3+
+ span(name='attr_piety_deity')
+ | trait
+ .desc
+ input(type='hidden' name='attr_piety_devotee' value='')
+ textarea(name='attr_piety_devotee' placeholder='Enter description...')
+ span(name='attr_piety_devotee')
+ .votary
+ span.rank
+ span(name='attr_piety_deity')
+ span Votary
+ span.subheader
+ | Piety 10+
+ span(name='attr_piety_deity')
+ | trait
+ .desc
+ input(type='hidden' name='attr_piety_votary' value='')
+ textarea(name='attr_piety_votary' placeholder='Enter description...')
+ span(name='attr_piety_votary')
+ .disciple
+ span.rank
+ span(name='attr_piety_deity')
+ span Disciple
+ span.subheader
+ | Piety 25+
+ span(name='attr_piety_deity')
+ | trait
+ .desc
+ input(type='hidden' name='attr_piety_disciple' value='')
+ textarea(name='attr_piety_disciple' placeholder='Enter description...')
+ span(name='attr_piety_disciple')
+ .champion
+ input.rank(type='text' name='attr_piety_champion_title' value='Champion of')
+ span.subheader
+ | Piety 50+
+ span(name='attr_piety_deity')
+ | trait
+ .desc
+ input(type='hidden' name='attr_piety_champion' value='')
+ textarea(name='attr_piety_champion' placeholder='Enter description...')
+ span(name='attr_piety_champion')
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/panels/Resources.pug b/Brancalonia Official/src/pug/layouts/panels/Resources.pug
new file mode 100644
index 0000000000..982c25915a
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/Resources.pug
@@ -0,0 +1,31 @@
+.resources
+ .hdice-dsaves-container(style='width: 246px; margin-top: 10px;')
+ .subcontainer(style='height: 64px; width: 119px;')
+ .top
+ span(data-i18n='total') Total
+ input(type='text' name='attr_class_resource_max' title='@{class_resource_max}')
+ input(type='number' name='attr_class_resource' title='@{class_resource}' style='margin-bottom: -6px;')
+ input.label(type='text' name='attr_class_resource_name' title='@{class_resource_name}' placeholder='CLASS RESOURCE' data-i18n-placeholder='class-resource-u')
+ .subcontainer(style='height: 64px; width: 119px; float: right;')
+ .top
+ span(data-i18n='total') Total
+ input(type='text' name='attr_other_resource_max' title='@{other_resource_max}')
+ input(type='number' name='attr_other_resource' title='@{other_resource}' style='margin-bottom: -6px;')
+ input.label(type='text' name='attr_other_resource_name' title='@{other_resource_name}' placeholder='OTHER RESOURCE' data-i18n-placeholder='other-resource-u')
+ input(type='hidden' name='attr_other_resource_itemid')
+ fieldset.repeating_resource
+ .hdice-dsaves-container(style='width: 246px;')
+ .subcontainer(style='height: 64px; width: 119px;')
+ .top
+ span(data-i18n='total') Total
+ input(type='text' name='attr_resource_left_max' title='@{repeating_resource_left_max}')
+ input(type='number' name='attr_resource_left' title='@{repeating_resource_left}' style='margin-bottom: -6px;')
+ input.label(type='text' name='attr_resource_left_name' title='@{repeating_resource_left_name}' placeholder='OTHER RESOURCE' data-i18n-placeholder='other-resource-u')
+ input(type='hidden' name='attr_resource_left_itemid')
+ .subcontainer(style='height: 64px; width: 119px;')
+ .top
+ span(data-i18n='total') Total
+ input(type='text' name='attr_resource_right_max' title='@{repeating_resource_right_max}')
+ input(type='number' name='attr_resource_right' title='@{repeating_resource_right}' style='margin-bottom: -6px;')
+ input.label(type='text' name='attr_resource_right_name' title='@{repeating_resource_right_name}' placeholder='OTHER RESOURCE' data-i18n-placeholder='other-resource-u')
+ input(type='hidden' name='attr_resource_right_itemid')
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/panels/SpellStats.pug b/Brancalonia Official/src/pug/layouts/panels/SpellStats.pug
new file mode 100644
index 0000000000..51fc762c72
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/SpellStats.pug
@@ -0,0 +1,17 @@
+.spellstats
+ .spellstats__ability
+ select(name="attr_spellcasting_ability")
+ option(value!="0*", data-i18n="None") None
+ option(value!="@{strength_mod}+", data-i18n="Strength") Strength
+ option(value!="@{dexterity_mod}+", data-i18n="Dexterity") Dexterity
+ option(value!="@{constitution_mod}+", data-i18n="Constitution") Constitution
+ option(value!="@{intelligence_mod}+", data-i18n="Intelligence") Intelligence
+ option(value!="@{wisdom_mod}+", data-i18n="Wisdom") Wisdom
+ option(value!="@{charisma_mod}+", data-i18n="Charisma") Charisma
+ span.spellstats__label(data-i18n="Spellcasting Ability") Spellcasting Ability
+ .spellstats__dc
+ span.spellstats__display(name="attr_spell_save_dc")
+ span.spellstats__label(data-i18n="Spell Save DC") Spell Save DC
+ .spellstats__attackbonus
+ span.spellstats__display(name="attr_spell_attack_bonus")
+ span.spellstats__label(data-i18n="Spell Attack Bonus") Spell Attack Bonus
diff --git a/Brancalonia Official/src/pug/layouts/panels/ToolsProficiencies.pug b/Brancalonia Official/src/pug/layouts/panels/ToolsProficiencies.pug
new file mode 100644
index 0000000000..3338d27dd2
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/ToolsProficiencies.pug
@@ -0,0 +1,64 @@
+.toolprofs
+ .toolprofs__header
+ span.label(data-i18n='tool-u') TOOL
+ span.label(data-i18n='pro-u') PRO
+ span.label(data-i18n='attr-u') ATTRIBUTE
+ fieldset.repeating_tool
+ .toolprof
+ input.options__flag(name='attr_options-flag', type="hidden", value='on')
+ .toolprof__options.options
+ .options__row
+ .options__label.options__flex(data-i18n='name:-u') NAME:
+ input.options__flex(type='text' name='attr_toolname')
+ .options__row
+ span.options__label.options__flex(data-i18n='prof-bonus:-u') PROFICIENCY BONUS:
+ select.options__flex--5(name='attr_toolbonus_base')
+ option(value='(@{pb})' selected='selected' data-i18n='prof-u') PROFICIENT
+ option(value='(@{pb}*2)' data-i18n='expertise-u') EXPERTISE
+ option(value='(floor(@{pb}/2))' data-i18n='jack-of-all-u') JACK OF ALL TRADES
+ .options__row
+ span.options__label.options__flex(data-i18n='attr:-u') ATTRIBUTE:
+ select.options__flex(name='attr_toolattr_base')
+ option(value='@{strength_mod}' selected='selected' data-i18n='strength-u') STRENGTH
+ option(value='@{dexterity_mod}' data-i18n='dexterity-u') DEXTERITY
+ option(value='@{constitution_mod}' data-i18n='constitution-u') CONSTITUTION
+ option(value='@{intelligence_mod}' data-i18n='intelligence-u') INTELLIGENCE
+ option(value='@{wisdom_mod}' data-i18n='wisdom-u') WISDOM
+ option(value='@{charisma_mod}' data-i18n='charisma-u') CHARISMA
+ option(value='?{Attribute?|Strength,@{strength_mod}|Dexterity,@{dexterity_mod}|Constitution,@{constitution_mod}|Intelligence,@{intelligence_mod}|Wisdom,@{wisdom_mod}|Charisma,@{charisma_mod}}' data-i18n='query-attr-u') QUERY ATTRIBUTE
+ span.options__label.options__flex(data-i18n='mods:-u') MODS:
+ input.options__flex--2(type='text' name='attr_tool_mod' title='@{tool_mod}' value='0')
+ .toolprof__display
+ input(type='hidden' name='attr_toolroll')
+ //
+ button.toolprof__button(type='roll' name='roll_tool' value='@{toolroll}')
+ span.toolprof__name(name='attr_toolname')
+ input.toolprof__value(type='text' name='attr_toolbonus_display')
+ input(type='hidden' name='attr_toolbonus')
+ input.toolprof__attribute(type='text' name='attr_toolattr')
+ .options__cog
+ input(type='checkbox' name='attr_options-flag' checked='checked')
+ span y
+ input.toggleflag(type='hidden' name='attr_global_skill_mod_flag')
+ .hidden.textarea.globalattack
+ span.label(data-i18n='global-skill-u') GLOBAL SKILL MODIFIER
+ fieldset.repeating_skillmod
+ .global-mod
+ input.options-flag(type='checkbox' name='attr_options-flag' checked='checked' style='top: -15px;')
+ span y
+ input.active-flag(type='checkbox' name='attr_global_skill_active_flag' value='1')
+ .options
+ .row
+ span(data-i18n='name:-u') NAME:
+ input(type='text' name='attr_global_skill_name' value='' placeholder='Guidance')
+ .row
+ span(data-i18n='roll:-u') ROLL:
+ input(type='text' name='attr_global_skill_roll' value='' placeholder='1d4')
+ .globaldisplay
+ button.ellipsis(type='roll' name='roll_global_save' value='@{wtype}&{template:simple} {{rname=@{global_skill_name}}} {{r1=[[@{global_skill_roll}]]}} {{normal=1}} @{charname_output}')
+ span(name='attr_global_skill_roll')
+ span(name='attr_global_skill_name')
+ .toolprofs__label
+ span(data-i18n='tool-prof-u') TOOL PROFICIENCIES
+ span &
+ span(data-i18n='custom-skills-u') CUSTOM SKILLS
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/panels/Traits.pug b/Brancalonia Official/src/pug/layouts/panels/Traits.pug
new file mode 100644
index 0000000000..794de0bcd8
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/Traits.pug
@@ -0,0 +1,35 @@
+.textbox.traits(style='min-height: 480px;')
+ input.inventoryflag(type='hidden' name='attr_simpletraits' value='complex')
+ textarea.simple(name='attr_features_and_traits' style='min-height: 461px; height: 461px;')
+ .complex
+ fieldset.repeating_traits
+ .trait
+ button.output(type='roll' name='roll_output' value='@{wtype}&{template:traits} @{charname_output} {{name=@{name}}} {{source=@{source}: @{source_type}}} {{description=@{description}}}') w
+ input.options-flag(type='checkbox' name='attr_options-flag' checked='checked')
+ span y
+ input.display-flag(type='checkbox' name='attr_display_flag')
+ .options
+ .row
+ span(data-i18n='name:-u') NAME:
+ input(type='text' name='attr_name' style='width: 120px;')
+ .row
+ span(data-i18n='source:-u') SOURCE:
+ select(name='attr_source')
+ option(selected='selected' data-i18n='racial') Racial
+ option(data-i18n='class') Class
+ option(data-i18n='feat') Feat
+ option(data-i18n='background') Background
+ option(data-i18n='other') Other
+ .row
+ span(data-i18n='source-type:-u') SOURCE TYPE:
+ input(type='text' name='attr_source_type' style='width: 160px;' placeholder='Dwarf/Fighter/4th Level')
+ .row
+ textarea(name='attr_description' style='min-height: 200px; height: 200px;')
+ .display(style='margin-bottom: 2px;')
+ span.title(name='attr_name')
+ span.subheader
+ span(name='attr_source')
+ span :
+ span(name='attr_source_type')
+ span.desc(name='attr_description')
+ span.label(data-i18n='feats-traits-u' style='margin-top: 0px; position: absolute; bottom: 0px;') FEATURES & TRAITS
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/panels/Vitals.pug b/Brancalonia Official/src/pug/layouts/panels/Vitals.pug
new file mode 100644
index 0000000000..643dfec85b
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/Vitals.pug
@@ -0,0 +1,14 @@
+.vitals
+ .vitals__hp
+ input(type="number", name="attr_hitpoints", value="0")
+ input(type="number", name="attr_hitpoints_max", value="0")
+ span.vitals__label(data-i18n="Hitpoints")
+ .vitals__temphp
+ input(type="number", name="attr_temp_hitpoints")
+ span.vitals__label(data-i18n="Temporary HP")
+ .vitals__hitdice
+ input(type="number", name="attr_hitdice")
+ span /
+ input(name="attr_hitdice_max", type="hidden", value="1")
+ span(name="attr_hitdice_max")
+ span.vitals__label(data-i18n="Hit Dice")
diff --git a/Brancalonia Official/src/pug/layouts/panels/npc/Actions.pug b/Brancalonia Official/src/pug/layouts/panels/npc/Actions.pug
new file mode 100644
index 0000000000..404279ccfb
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/npc/Actions.pug
@@ -0,0 +1,64 @@
+.npc__actions
+ span.npc__section-header(data-i18n="actions") Actions
+ fieldset.repeating_npcaction
+ .action
+ +toggleButton('edit', 'npc__toggle', true)
+ .action__options.toggle__options.options
+ .options__row
+ span(data-i18n="name:-u") NAME:
+ input(type="text" name="attr_name")
+ .options__row.options__row--center
+ input.options__flex-1(type="checkbox" name="attr_attack_flag")
+ span.options__flex-4(data-i18n="attack-u") ATTACK
+ input.flag__toggle--attack(type="hidden" name="attr_attack_flag" value!="0")
+ .options__row.flag__display--attack
+ span(data-i18n="type:-u") TYPE:
+ select(name="attr_attack_type")
+ option(value!="Melee" data-i18n="melee") Melee
+ option(value!="Ranged" data-i18n="ranged") Ranged
+ span( data-i18n="range-reach:-u") RANGE/REACH:
+ input(type="text" name="attr_attack_range" placeholder="5 ft." data-i18n-placeholder="range-reach-place")
+ .options__row.flag__display--attack
+ span(data-i18n="to-hit:-u") TO HIT:
+ input(type="text" name="attr_attack_tohit" value!="0" placeholder="5")
+ span( data-i18n="target:-u") TARGET:
+ input(type="text" name="attr_attack_target" placeholder="One target" data-i18n-placeholder="to-hit-place")
+ input(type="hidden" name="attr_damage_flag")
+ .options__row.flag__display--attack
+ span(data-i18n="on-hit:-u") ON HIT:
+ input(type="text" name="attr_attack_damage" placeholder="1d10")
+ input(type="text" name="attr_attack_damagetype" placeholder="slashing" data-i18n-placeholder="on-hit-place")
+ input(type="hidden" name="attr_attack_crit")
+ .options__row.flag__display--attack
+ span(data-i18n="on-hit2:-u") ON HIT 2:
+ input(type="text" name="attr_attack_damage2" placeholder="2d6+5")
+ input(type="text" name="attr_attack_damagetype2" placeholder="fire" data-i18n-placeholder="on-hit-2-place")
+ input(type="hidden" name="attr_attack_crit2")
+ .options__row.flag__display--attack
+ span(data-i18n="desc:-u") DESCRIPTION:
+ select(name="attr_show_desc")
+ option(value!="@{description}" data-i18n="show") Show
+ option(value!=" " data-i18n="hide") Hide
+ .options__row
+ textarea(name="attr_description")
+ .options__row.flag__display--attack.flag__hide--attack
+ span(data-i18n="damage:-u") DAMAGE:
+ input(type="text" name="attr_attack_damage" placeholder="1d10")
+ input(type="text" name="attr_attack_damagetype" placeholder="slashing" data-i18n-placeholder="on-hit-place")
+ input(type="hidden" name="attr_attack_crit")
+ .action__display.toggle__display
+ .npc__row
+ button.action__name(type="roll" name="roll_npc_action" value!="@{rollbase}")
+ span(name="attr_name")
+ input.flag__toggle--attack(type="hidden" name="attr_attack_flag")
+ .npc__row.flag__display--attack
+ span(name="attr_attack_type")
+ span Weapon Attack:
+ span(name="attr_attack_tohitrange")
+ .npc__row.flag__display--attack
+ span( data-i18n="hit:") Hit:
+ span(name="attr_attack_onhit")
+ span.action__description(name="attr_description")
+ input(type="hidden" name="attr_rollbase")
+ button(type="roll" name="roll_npc_dmg" value!="@{wtype}&{template:npcdmg} @{damage_flag} {{dmg1=[[@{attack_damage}+0]]}} {{dmg1type=@{attack_damagetype}}} {{dmg2=[[@{attack_damage2}+0]]}} {{dmg2type=@{attack_damagetype2}}} {{description=@{show_desc}}}")
+ button(type="roll" name="roll_npc_crit" value!="@{wtype}&{template:npcdmg} @{damage_flag} {{crit=1}} {{dmg1=[[@{attack_damage}+0]]}} {{dmg1type=@{attack_damagetype}}} {{dmg2=[[@{attack_damage2}+0]]}} {{dmg2type=@{attack_damagetype2}}} {{crit1=[[@{attack_crit}+0]]}} {{crit2=[[@{attack_crit2}+0]]}} {{description=@{show_desc}}}")
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/panels/npc/BonusActions.pug b/Brancalonia Official/src/pug/layouts/panels/npc/BonusActions.pug
new file mode 100644
index 0000000000..ba17c9642a
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/npc/BonusActions.pug
@@ -0,0 +1,67 @@
+//BONUS ACTIONS
+input.bonusaction_flag(type="hidden" name="attr_npcbonusactionsflag")
+.npc__bonus-actions
+ hr.npc__rule--thin
+ span.npc__section-header(data-i18n="bonus-actions") Bonus Actions
+ fieldset.repeating_npcbonusaction
+ .action
+ +toggleButton('edit', 'npc__toggle', true)
+ .action__options.toggle__options.options
+ .options__row
+ span(data-i18n="name:-u") NAME:
+ input(type="text" name="attr_name")
+ .options__row.options__row--center
+ input.options__flex--1(type="checkbox" name="attr_attack_flag" value!="on")
+ span.options__flex--4(data-i18n="attack-u") ATTACK
+ input.flag__toggle--attack(type="hidden" name="attr_attack_flag" value!="0")
+ .options__row.flag__display--attack
+ span(data-i18n="type:-u") TYPE:
+ select(name="attr_attack_type")
+ option(value!="Melee" data-i18n="melee") Melee
+ option(value!="Ranged" data-i18n="ranged") Ranged
+ span( data-i18n="range-reach:-u") RANGE/REACH:
+ input(type="text" name="attr_attack_range" placeholder="5 ft." data-i18n-placeholder="range-reach-place")
+ .options__row.flag__display--attack
+ span(data-i18n="to-hit:-u") TO HIT:
+ input(type="text" name="attr_attack_tohit" value!="0" placeholder="5")
+ span( data-i18n="target:-u") TARGET:
+ input(type="text" name="attr_attack_target" placeholder="One target" data-i18n-placeholder="to-hit-place")
+ input(type="hidden" name="attr_damage_flag")
+ .options__row.flag__display--attack
+ span(data-i18n="on-hit:-u") ON HIT:
+ input(type="text" name="attr_attack_damage" placeholder="1d10")
+ input(type="text" name="attr_attack_damagetype" placeholder="slashing" data-i18n-placeholder="on-hit-place")
+ input(type="hidden" name="attr_attack_crit")
+ .options__row.flag__display--attack
+ span(data-i18n="on-hit2:-u") ON HIT 2:
+ input(type="text" name="attr_attack_damage2" placeholder="2d6+5")
+ input(type="text" name="attr_attack_damagetype2" placeholder="fire" data-i18n-placeholder="on-hit-2-place")
+ input(type="hidden" name="attr_attack_crit2")
+ .options__row.flag__display--attack
+ span(data-i18n="desc:-u") DESCRIPTION:
+ select(name="attr_show_desc")
+ option(value!="@{description}" data-i18n="show") Show
+ option(value!=" " data-i18n="hide") Hide
+ .options__row
+ textarea(name="attr_description")
+ .options__row.flag__display--attack.flag__hide--attack
+ span(data-i18n="damage:-u") DAMAGE:
+ input(type="text" name="attr_attack_damage" placeholder="1d10")
+ input(type="text" name="attr_attack_damagetype" placeholder="slashing" data-i18n-placeholder="on-hit-place")
+ input(type="hidden" name="attr_attack_crit")
+ .action__display.toggle__display
+ .npc__row
+ button.action__name(type="roll" name="roll_npc_action" value!="@{rollbase}")
+ span(name="attr_name")
+ input.flag__toggle--attack(type="hidden" name="attr_attack_flag")
+ .npc__row.attack.flag__display--attack
+ span(name="attr_attack_type")
+ span Weapon Attack:
+ span(name="attr_attack_tohitrange")
+ .npc__row.attack.flag__display--attack
+ span( data-i18n="hit:") Hit:
+ span(name="attr_attack_onhit")
+ span.action__description(name="attr_description")
+ input(type="hidden" name="attr_rollbase")
+ button(type="roll" name="roll_npc_dmg" value!="@{wtype}&{template:npcdmg} @{damage_flag} {{dmg1=[[@{attack_damage}+0]]}} {{dmg1type=@{attack_damagetype}}} {{dmg2=[[@{attack_damage2}+0]]}} {{dmg2type=@{attack_damagetype2}}} {{description=@{show_desc}}}")
+ button(type="roll" name="roll_npc_crit" value!="@{wtype}&{template:npcdmg} @{damage_flag} {{crit=1}} {{dmg1=[[@{attack_damage}+0]]}} {{dmg1type=@{attack_damagetype}}} {{dmg2=[[@{attack_damage2}+0]]}} {{dmg2type=@{attack_damagetype2}}} {{crit1=[[@{attack_crit}+0]]}} {{crit2=[[@{attack_crit2}+0]]}} {{description=@{show_desc}}}")
diff --git a/Brancalonia Official/src/pug/layouts/panels/npc/LegendaryActions.pug b/Brancalonia Official/src/pug/layouts/panels/npc/LegendaryActions.pug
new file mode 100644
index 0000000000..53f7fe3c21
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/npc/LegendaryActions.pug
@@ -0,0 +1,62 @@
+input.legendary_flag(type="hidden" name="attr_npc_legendary_actions" value="0")
+.npc_legactions
+ hr.npc__rule--thin
+ span.npc__section-header(data-i18n="leg-actions") Legendary Actions
+ .npc_description
+ span(name="attr_npc_legendary_actions_desc")
+ fieldset.repeating_npcaction-l
+ .legaction
+ +toggleButton('edit', 'npc__toggle', true)
+ .legaction__options.toggle__options.options
+ .options__row
+ span(data-i18n="name:-u") NAME:
+ input(type="text" name="attr_name")
+ .options__row
+ input(type="checkbox" name="attr_attack_flag" value!="on")
+ span(data-i18n="attack-u") ATTACK
+ input.flag__toggle--attack(type="hidden" name="attr_attack_flag" value!="0")
+ .options__row.flag__display--attack
+ span(data-i18n="type:-u") TYPE:
+ select(name="attr_attack_type")
+ option(value!="Melee" data-i18n="melee") Melee
+ option(value!="Ranged" data-i18n="ranged") Ranged
+ span( data-i18n="range-reach:-u") RANGE/REACH:
+ input(type="text" name="attr_attack_range" placeholder="5 ft." data-i18n-placeholder="range-reach-place")
+ .options__row.flag__display--attack
+ span(data-i18n="to-hit:-u") TO HIT:
+ input(type="text" name="attr_attack_tohit" value!="0" placeholder="5")
+ span( data-i18n="target:-u") TARGET:
+ input(type="text" name="attr_attack_target" placeholder="One target" data-i18n-placeholder="to-hit-place")
+ input(type="hidden" name="attr_damage_flag")
+ .options__row.flag__display--attack
+ span(data-i18n="on-hit:-u") ON HIT:
+ input(type="text" name="attr_attack_damage" placeholder="1d10")
+ input(type="text" name="attr_attack_damagetype" placeholder="slashing" data-i18n-placeholder="on-hit-place")
+ input(type="hidden" name="attr_attack_crit")
+ .options__row.flag__display--attack
+ span(data-i18n="on-hit2:-u") ON HIT 2:
+ input(type="text" name="attr_attack_damage2" placeholder="2d6+5")
+ input(type="text" name="attr_attack_damagetype2" placeholder="fire" data-i18n-placeholder="on-hit-2-place")
+ input(type="hidden" name="attr_attack_crit2")
+ .options__row.flag__display--attack
+ span(data-i18n="desc:-u") DESCRIPTION:
+ select(name="attr_show_desc")
+ option(value!="@{description}" data-i18n="show") Show
+ option(value!=" " data-i18n="hide") Hide
+ .options__row
+ textarea(name="attr_description")
+ .legaction__display.toggle__display
+ button.legaction__name.pick(type="roll" name="roll_npc_action" value!="@{rollbase}")
+ span(name="attr_name")
+ input.flag__toggle--attack(type="hidden" name="attr_attack_flag")
+ .npc__row.flag__display--attack
+ span(name="attr_attack_type")
+ span Weapon Attack:
+ span(name="attr_attack_tohitrange")
+ .npc__row.flag__display--attack
+ span( data-i18n="hit:") Hit:
+ span(name="attr_attack_onhit")
+ span.legaction__description(name="attr_description")
+ input(type="hidden" name="attr_rollbase")
+ button(type="roll" name="roll_npc_dmg" value!="@{wtype}&{template:npcdmg} @{damage_flag} {{dmg1=[[@{attack_damage}+0]]}} {{dmg1type=@{attack_damagetype}}} {{dmg2=[[@{attack_damage2}+0]]}} {{dmg2type=@{attack_damagetype2}}}")
+ button(type="roll" name="roll_npc_crit" value!="@{wtype}&{template:npcdmg} @{damage_flag} {{crit=1}} {{dmg1=[[@{attack_damage}+0]]}} {{dmg1type=@{attack_damagetype}}} {{dmg2=[[@{attack_damage2}+0]]}} {{dmg2type=@{attack_damagetype2}}} {{crit1=[[@{attack_crit}+0]]}} {{crit2=[[@{attack_crit2}+0]]}}")
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/panels/npc/Reactions.pug b/Brancalonia Official/src/pug/layouts/panels/npc/Reactions.pug
new file mode 100644
index 0000000000..a8890db56a
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/npc/Reactions.pug
@@ -0,0 +1,18 @@
+input.reaction_flag(type="hidden" name="attr_npcreactionsflag")
+.npc__reactions
+ hr.npc__rule--thin
+ span.npc__section-header(data-i18n="reactions") Reactions
+ fieldset.repeating_npcreaction
+ .reaction
+ +toggleButton('edit', 'npc__toggle', true)
+ .reaction__options.toggle__options.options
+ .options__row
+ span(data-i18n="name:-u") NAME:
+ input(type="text" name="attr_name" placeholder="Parry." data-i18n-placeholder="npc-repeating-name-place")
+ .options__row
+ textarea(name="attr_description" placeholder="The creature adds 2 to its AC against..." data-i18n-placeholder="npc-repeating-desc-place")
+ .reaction__display.toggle__display
+ .reaction__row
+ button.reaction__name(type="roll" name="npc_roll_output" value="@{wtype}&{template:traits} @{charname_output} {{name=@{name}}} {{description=@{description}}}")
+ span(name="attr_name")
+ span.reaction__description(name="attr_description")
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/panels/npc/Settings.pug b/Brancalonia Official/src/pug/layouts/panels/npc/Settings.pug
new file mode 100644
index 0000000000..6f4a181762
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/npc/Settings.pug
@@ -0,0 +1,137 @@
+input.npc__flag--options(type="hidden" name="attr_npc_options-flag" value="on")
+input.npc_ui_flags(type="hidden" name="attr_ui_flags" value="")
+.options.npc__options
+ .options__row--title
+ span(data-i18n="npc-options-u") NPC OPTIONS
+ .options__row
+ span(data-i18n="name-u") NAME
+ input(type="text" name="attr_npc_name")
+ .options__row
+ span(data-i18n="npc-type-u") NPC TYPE
+ input(type="text" name="attr_npc_type" placeholder="Medium fiend, any evil alignment" data-i18n-placeholder="npc-type-place")
+ .options__row
+ span(data-i18n="armor-class-u") ARMOR CLASS
+ input(type="text" name="attr_npc_ac" placeholder="10")
+ span(data-i18n="type-u") TYPE
+ input(type="text" name="attr_npc_actype" placeholder="scale mail" data-i18n-placeholder="npc-armor-place" value!="")
+ .options__row
+ span(data-i18n="hit-points-u") HIT POINTS
+ input(type="text" name="attr_hp_max" placeholder="82")
+ span(data-i18n="formula-u") FORMULA
+ input(type="text" name="attr_npc_hpformula" placeholder="11d8 + 33")
+ .options__row
+ span(data-i18n="speed-u") SPEED
+ input(type="text" name="attr_npc_speed" placeholder="30 ft., fly 60ft." data-i18n-placeholder="npc-speed-place")
+ .spacer
+ .options__row--title
+ span(data-i18n="attributes-u") ATTRIBUTES
+ .options__row
+ each attr in ['strength', 'dexterity', 'constitution', 'intelligence', 'wisdom', 'charisma']
+ +npcAttribute(attr)
+ .spacer
+ .options__row--title
+ span(data-i18n="saves-u") SAVES
+ .options__row
+ each attr in ['strength', 'dexterity', 'constitution', 'intelligence', 'wisdom', 'charisma']
+ +npcSave(attr)
+ .spacer
+ .options__row--title
+ span(data-i18n="skills-u") SKILLS
+ .options__row.skills-list(data-i18n-list="skills-list")
+ .col
+ each skill in ['acrobatics:dexterity', 'animal handling:wisdom', 'arcana:intelligence', 'athletics:strength', 'deception:charisma', 'history:intelligence']
+ +npcSkill(skill)
+ .col(data-i18n-list-sublist="")
+ each skill in ['insight:wisdom', 'intimidation:charisma', 'investigation:intelligence', 'medicine:wisdom', 'nature:intelligence', 'perception:wisdom']
+ +npcSkill(skill)
+ .col(data-i18n-list-sublist="")
+ each skill in ['performance:charisma', 'persuasion:charisma', 'religion:intelligence', 'sleight_of_hand:dexterity', 'stealth:dexterity', 'survival:wisdom']
+ +npcSkill(skill)
+ .options__row.options__row--noborder
+ span(data-i18n="damage-vuln-u") DAMAGE VULNERABILITIES
+ input(type="text" name="attr_npc_vulnerabilities" placeholder="fire" data-i18n-placeholder="npc-dmg-vuln-place")
+ .options__row.options__row--noborder
+ span(data-i18n="damage-res-u") DAMAGE RESISTANCES
+ input(type="text" name="attr_npc_resistances" placeholder="cold" data-i18n-placeholder="npc-dmg-res-place")
+ .options__row.options__row--noborder
+ span(data-i18n="damage-imm-u") DAMAGE IMMUNITIES
+ input(type="text" name="attr_npc_immunities" placeholder="lighting, thunder" data-i18n-placeholder="npc-dmg-imm-place")
+ .options__row.options__row--noborder
+ span(data-i18n="cond-imm-u") CONDITION IMMUNITIES
+ input(type="text" name="attr_npc_condition_immunities" placeholder="charmed" data-i18n-placeholder="npc-cond-imm-place")
+ .options__row
+ span(data-i18n="senses-u") SENSES
+ input(type="text" name="attr_npc_senses" placeholder="darkvision 120ft., passive Perception 16" data-i18n-placeholder="npc-senses-place")
+ .options__row
+ span(data-i18n="langs-u") LANGUAGES
+ input(type="text" name="attr_npc_languages" placeholder="Abyssal, Common, Infernal" value!="—" data-i18n-placeholder="npc-langs-place")
+ .options__row
+ span(data-i18n="challenge-u") CHALLENGE
+ input(type="text" name="attr_npc_challenge" placeholder="1")
+ span(data-i18n="xp-u") XP
+ input(type="text" name="attr_npc_xp" placeholder="250")
+ .options__row
+ span(data-i18n="token_size-u") TOKEN SIZE
+ input(name="attr_token_size" value!="1" placeholder="1")
+ input.npc__flag--spellcasting(type="hidden" name="attr_npcspellcastingflag" value!="1")
+ .options__row
+ input.options__flex--1(type="checkbox" name="attr_npcspellcastingflag" value!="1")
+ span.options__flex--9(data-i18n="spellcast-npc-u") SPELLCASTING NPC
+ span(data-i18n="spell-ability-u") SPELLCASTING ABILITY
+ select(name="attr_spellcasting_ability")
+ option(value!="0*" data-i18n="none-u") NONE
+ option(value!="@{strength_mod}+" data-i18n="strength-u") STRENGTH
+ option(value!="@{dexterity_mod}+" data-i18n="dexterity-u") DEXTERITY
+ option(value!="@{constitution_mod}+" data-i18n="constitution-u") CONSTITUTION
+ option(value!="@{intelligence_mod}+" data-i18n="intelligence-u") INTELLIGENCE
+ option(value!="@{wisdom_mod}+" data-i18n="wisdom-u") WISDOM
+ option(value!="@{charisma_mod}+" data-i18n="charisma-u") CHARISMA
+ .options__row.npc__hidden--spellcasting
+ span(data-i18n="glob-atk-mod:-u") GLOBAL MAGIC ATTACK MODIFIER:
+ input(type="text" name="attr_globalmagicmod" placeholder="0" value!="0")
+ span(data-i18n="magic-caster-lvl:-u") MAGIC CASTER LEVEL:
+ input(type="text" name="attr_caster_level")
+ span(data-i18n="spell_dc_mod:-u") SPELL SAVE DC MOD:
+ input(type="text" name="attr_spell_dc_mod" placeholder="0" value!="0")
+ .options__row
+ input.options__flex--1(type="checkbox" name="attr_npcbonusactionsflag" value!="1")
+ span.options__flex--4(data-i18n="has-bonusaction-u") HAS BONUS ACTIONS
+ input.options__flex--1(type="checkbox" name="attr_npcreactionsflag" value!="1")
+ span.options__flex--4(data-i18n="has-reaction-u") HAS REACTIONS
+ .options__row
+ span(data-i18n="leg-actions:-u") LEGENDARY ACTIONS:
+ input(type="text" name="attr_npc_legendary_actions" value!="0" placeholder="0")
+ .options__row
+ input(type="checkbox" name="attr_npc_mythic_actions" value!="1")
+ span(data-i18n="myt-actions:-u") MYTHIC ACTIONS:
+ textarea.mythic-rules(name="attr_npc_mythic_actions_desc" placeholder="Mythic Action Rules. This creature can use the options below...")
+ .options__row--title
+ span(data-i18n="gen-opts-u") GENERAL OPTIONS
+ .options__row.options__row--center
+ input.options__flex--1(type="checkbox" name="attr_npc" value!="1")
+ span.options__flex--1(data-i18n="npc-u") NPC
+ .options__row
+ span(data-i18n="roll-queries:-u") ROLL QUERIES:
+ select(name="attr_rtype")
+ option(value!="{{always=1}} {{r2=[[@{d20}" data-i18n="always-adv") Always Roll Advantage
+ option(value!="@{advantagetoggle}" data-i18n="adv-toggle") Advantage Toggle
+ option(value!="@{queryadvantage}" data-i18n="query-adv") Query Advantage
+ option(value!="{{normal=1}} {{r2=[[0d20" data-i18n="never-adv") Never Roll Advantage
+ span(data-i18n="whisp-rolls-gm:-u") WHISPER ROLLS TO GM:
+ select(name="attr_wtype")
+ option(value!="" data-i18n="never-whisper-roll") Never Whisper Rolls
+ option(value!="@{whispertoggle}" data-i18n="toggle-roll-whisper") Whisper Toggle
+ option(value!="?{Whisper?|Public Roll,|Whisper Roll,/w gm }" data-i18n="query-whisper-roll") Query Whisper
+ option(value!="/w gm " data-i18n="always-whisper-roll") Always Whisper Rolls
+ .options__row
+ span(data-i18n="auto-dmg-roll:-u") AUTO DAMAGE ROLL:
+ select.dtype(name="attr_dtype")
+ option(value!="pick" data-i18n="never-dmg") Don't Auto Roll Damage
+ option(value!="full" data-i18n="always-dmg") Auto Roll Damage & Crit
+ span(data-i18n="npc-name-in-rolls:-u") NPC NAME IN ROLLS:
+ select(name="attr_npc_name_flag")
+ option(value!="{{name=@{npc_name}}}" data-i18n="show") Show
+ option(value!="0" data-i18n="hide") Hide
+ .options__row.options__row--center
+ input.options__flex--1(type="checkbox" name="attr_init_tiebreaker" value!="@{dexterity}/100")
+ span.options__flex--4(data-i18n="add-dex-tiebreaker-u") ADD DEX TIEBREAKER TO INITIATIVE
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/panels/npc/Stats.pug b/Brancalonia Official/src/pug/layouts/panels/npc/Stats.pug
new file mode 100644
index 0000000000..3e324dbadb
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/npc/Stats.pug
@@ -0,0 +1,65 @@
+.display.npc__statblock
+ .npc__settings
+ input.npc__flag--options(type="checkbox" name="attr_npc_options-flag" checked="checked")
+ span y
+ .npc__row.options__title
+ button(type="roll" name="roll_npc_init" value!="@{wtype}&{template:npc} @{npc_name_flag} {{rname=^{init}}} {{mod=[[[[@{initiative_bonus}]][DEX]]]}} {{r1=[[@{d20}+[[@{initiative_bonus}]][DEX] &{tracker}]]}} {{normal=1}} {{type=Initiative}}")
+ span.npc__title(name="attr_npc_name")
+ .npc__row
+ span.npc__subtitle(name="attr_npc_type")
+ hr.npc__rule--thin
+ .npc__row
+ span.npc__label(data-i18n="ac") Armor Class
+ span(name="attr_npc_ac")
+ input.npc__flag--actype(type="hidden" name="attr_npc_actype" value!="")
+ span.npc__ac-type(name="attr_npc_actype")
+ .npc__row
+ span.npc__label(data-i18n="hp") Hit Points
+ span(name="attr_hp_max")
+ button(type="roll" name="roll_npc_hpformula" value!="@{wtype}&{template:npc} {{type=Hit Points}} {{normal=1}} @{npc_name_flag} {{rname=^{hp}}} {{mod=@{npc_hpformula}}} {{r1=[[@{npc_hpformula}]]}} charname=@{character_name}")
+ span.npc__hitpoints-formula(name="attr_npc_hpformula")
+ .npc__row
+ span.npc__label(data-i18n="speed") Speed
+ span(name="attr_npc_speed")
+ hr.npc__rule--thick-top
+ .npc__row.npc__row--space-between
+ each attr in ['strength', 'dexterity', 'constitution', 'intelligence', 'wisdom', 'charisma']
+ +npcAttributeRoll(attr)
+ hr.npc__rule--thick-bottom
+ input.npc__flag--next(type="hidden" name="attr_npc_saving_flag" value!="")
+ .npc__row
+ span.npc__label(data-i18n="saving-throw") Saving Throws
+ each attr in ['strength', 'dexterity', 'constitution', 'intelligence', 'wisdom', 'charisma']
+ +npcSaveRoll(attr)
+ input.npc__flag--next(type="hidden" name="attr_npc_skills_flag" value!="")
+ .npc__row.skills.skills-list(data-i18n-list="skills-list")
+ span.npc__label(data-i18n="skills") Skills
+ each skill in ['acrobatics', 'animal handling', 'arcana', 'athletics', 'deception', 'history', 'insight', 'intimidation', 'investigation', 'medicine', 'nature', 'perception', 'performance', 'persuasion', 'religion', 'sleight_of_hand', 'stealth', 'survival']
+ +npcSkillRoll(skill)
+ input.npc__flag--next(type="hidden" name="attr_npc_vulnerabilities")
+ .npc__row.npc__hidden.vulnerabilities
+ span.npc__label(data-i18n="dmg-vuln") Damage Vulnerabilities
+ span(name="attr_npc_vulnerabilities")
+ input.npc__flag--next(type="hidden" name="attr_npc_resistances")
+ .npc__row.npc__hidden.resistances
+ span.npc__label(data-i18n="dmg-res") Damage Resistances
+ span(name="attr_npc_resistances")
+ input.npc__flag--next(type="hidden" name="attr_npc_immunities")
+ .npc__row.npc__hidden.immunities
+ span.npc__label(data-i18n="dmg-imm") Damage Immunities
+ span(name="attr_npc_immunities")
+ input.npc__flag--next(type="hidden" name="attr_npc_condition_immunities")
+ .npc__row.npc__hidden.condition_immunities
+ span.npc__label(data-i18n="cond-imm") Condition Immunities
+ span(name="attr_npc_condition_immunities")
+ .npc__row.senses
+ span.npc__label(data-i18n="senses") Senses
+ span(name="attr_npc_senses")
+ .npc__row.languages
+ span.npc__label(data-i18n="langs") Languages
+ span.languages(name="attr_npc_languages" value!="—")
+ .npc__row
+ span.npc__label(data-i18n="challenge") Challenge
+ span(name="attr_npc_challenge")
+ span.npc__challenge--brackets(name="attr_npc_xp")
+ hr.npc__rule--thin
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/panels/npc/Traits.pug b/Brancalonia Official/src/pug/layouts/panels/npc/Traits.pug
new file mode 100644
index 0000000000..cc3fc673c1
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/panels/npc/Traits.pug
@@ -0,0 +1,14 @@
+.npc__traits
+ fieldset.repeating_npctrait
+ .trait
+ +toggleButton('edit_trait', 'npc__toggle', true)
+ .trait__options.options.toggle__options
+ .options__row
+ span(data-i18n="name:-u") NAME:
+ input(type="text" name="attr_name" placeholder="False Appearance." data-i18n-placeholder="npc-trait-name-place")
+ .options__row
+ textarea(name="attr_description" placeholder="If the dragon fails..." data-i18n-placeholder="npc-trait-desc-place")
+ .trait__display.toggle__display
+ button.trait__name.btn.ui-draggable(type="roll" name="roll_npc_roll_output" value="@{wtype}&{template:traits} @{charname_output} {{name=@{name}}} {{description=@{description}}}")
+ span(name="attr_name")
+ span.trait__description(name="attr_description")
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/tabs/bio.pug b/Brancalonia Official/src/pug/layouts/tabs/bio.pug
new file mode 100644
index 0000000000..7ec904f098
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/tabs/bio.pug
@@ -0,0 +1,20 @@
+.bio-body
+ .appearance
+ span.appearance__label(data-i18n="Appearance") Appearance
+ .appearance__row
+ .appearance__title(data-i18n="Build")
+ input.appearance__input(name="attr_build", type="text")
+ .appearance__row
+ .appearance__title(data-i18n="Eyes")
+ input.appearance__input(name="attr_eyes", type="text")
+ .appearance__row
+ .appearance__title(data-i18n="Hair")
+ input.appearance__input(name="attr_hair", type="text")
+ .appearance__row
+ .appearance__title(data-i18n="Skin")
+ input.appearance__input(name="attr_skin", type="text")
+ +PersonalityTrait("Misdeeds")
+ +PersonalityTrait("Allies & Organizations")
+ +PersonalityTrait("Backstory")
+ +PersonalityTrait("Backpack")
+ +PersonalityTrait("Notes")
diff --git a/Brancalonia Official/src/pug/layouts/tabs/core.pug b/Brancalonia Official/src/pug/layouts/tabs/core.pug
new file mode 100644
index 0000000000..4bd72c33b0
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/tabs/core.pug
@@ -0,0 +1,72 @@
+.core-body
+ .core-col
+ .shields
+ .ac
+ input.ac__value(name="attr_ac", title="@{ac}", type="number")
+ .ac__label(data-i18n="AC") AC
+ .speed
+ input.speed__value(name="attr_speed", title="@{speed}", type="number")
+ .speed__label(data-i18n="Speed") Speed
+
+ .inspprof.inspprof--initiative
+ .inspprof__value
+ span(name="attr_initiative_bonus", title="@{initiative_bonus}")
+
+ .inspprof__label
+ button.inspprof__button(
+ type="roll",
+ name="roll_initiative",
+ value="@{wtype}&{template:simple} {{rname=^{init-u}}} {{mod=@{initiative_bonus}}} {{r1=[[@{initiative_style}+@{initiative_bonus}@{pbd_safe}[INIT] &{tracker}]]}} {{normal=1}} @{charname_output}",
+ data-i18n="Initiative"
+ ) initative
+
+ each personalityTrait in globalAttributesByCategory.personalityTraits
+ +PersonalityTrait(personalityTrait)
+
+ .bounty
+ .bounty__image
+ .bounty__bounty
+ .bounty__label(data-i18n="Bounty")
+ input(name="attr_bounty", type="number")
+
+ .core-col.core-col--middle
+ include ../panels/Vitals
+
+ .trackers
+ include ../panels/Exhaustion
+ include ../panels/Knock
+
+ .deathsaves
+ include ../panels/DeathSaves
+
+ include ../panels/Equipment
+
+ include ../panels/AttacksSpellcasting
+
+ .core-col.core-col__split
+ .abilityscores
+ each abilityScore in globalAttributesByCategory.abilities
+ +AbilityScore(abilityScore)
+
+ .skillwrap
+ +InsProf('Proficiency Bonus')
+ span(name="attr_pb", title="@{pb}")
+
+ .savingthrows
+ each save in globalAttributesByCategory.abilities
+ +SavingThrow(save)
+
+ +InsProf('Inspiration')
+ input(type="checkbox", name="attr_inspiration")
+ span
+
+ .skills
+ div(data-i18n-list="skills-list")
+ each skill in globalAttributesByCategory.skills
+ +Skill(skill.name, skill.ability)
+
+ +InsProf("Passive Perception")
+ span(name="attr_passive_wisdom")
+
+ .coins
+ include ../panels/Coins
diff --git a/Brancalonia Official/src/pug/layouts/tabs/settings.pug b/Brancalonia Official/src/pug/layouts/tabs/settings.pug
new file mode 100644
index 0000000000..a432920449
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/tabs/settings.pug
@@ -0,0 +1,262 @@
+.settings-body
+ .settings__col
+ .options
+ .options__row
+ span(data-i18n="hit-die:-u") HIT DIE:
+ select(name="attr_hitdietype")
+ option(value="4") D4
+ option(value="6") D6
+ option(value="8") D8
+ option(value="10") D10
+ option(value="12") D12
+ .options__row
+ span(data-i18n="carrying-capacity-mod:-u") CARRYING CAPACITY MODIFIER:
+ input(type="text" name="attr_carrying_capacity_mod" placeholder="*2")
+ .options__row
+ span(data-i18n="glob-atk-mod:-u") GLOBAL MAGIC ATTACK MODIFIER:
+ input(type="text" name="attr_globalmagicmod" placeholder="0" value="0")
+ .options__row
+ span(data-i18n="magic-use-lvl:-u") MAGIC CASTER LEVEL:
+ input(type="text" name="attr_caster_level")
+ .options__row
+ span(data-i18n="spell_dc_mod:-u") SPELL SAVE DC MOD:
+ input(type="text" name="attr_spell_dc_mod" placeholder="0" value="0")
+ .options__row--title
+ span(data-i18n="class-options-u") CLASS OPTIONS
+ | (
+ span(name="attr_class")
+ | )
+ .options
+ input(type="hidden" name="attr_custom_class" value="1")
+ .options__row
+ span(data-i18n="class-name:-u") CLASS NAME:
+ input(type="text" name="attr_cust_classname")
+ .options__row
+ span(data-i18n="hit-die:-u") HIT DIE:
+ select(name="attr_cust_hitdietype")
+ option(value="4") D4
+ option(value="6") D6
+ option(value="8") D8
+ option(value="10") D10
+ option(value="12") D12
+ .options__row
+ span(data-i18n="spellcasting-ability:-u") SPELLCASTING ABILITY:
+ select(name="attr_cust_spellcasting_ability")
+ option(value="0*" data-i18n="none-u") NONE
+ option(value="@{strength_mod}+" data-i18n="strength-u") STRENGTH
+ option(value="@{dexterity_mod}+" data-i18n="dexterity-u") DEXTERITY
+ option(value="@{constitution_mod}+" data-i18n="constitution-u") CONSTITUTION
+ option(value="@{intelligence_mod}+" data-i18n="intelligence-u") INTELLIGENCE
+ option(value="@{wisdom_mod}+" data-i18n="wisdom-u") WISDOM
+ option(value="@{charisma_mod}+" data-i18n="charisma-u") CHARISMA
+ .options__row
+ span(data-i18n="spell-slots:-u") SPELL SLOTS:
+ select(name="attr_cust_spellslots")
+ option(value="none" data-i18n="none-u") NONE
+ option(value="full" data-i18n="spell-full-u") FULL (Cleric, Druid, Wizard)
+ option(value="half" data-i18n="spell-half-u") HALF (Artificer, Paladin, Ranger)
+ option(value="third" data-i18n="spell-third-u") THIRD (Arcane Fighter/Rogue)
+ .options__row--title
+ span(data-i18n="saves-u") SAVES
+ .options__row.options__row--noborder
+ input.options__flex--1(type="checkbox" name="attr_cust_strength_save_prof" value="(@{pb})")
+ span(data-i18n="strength") Strength
+ input.options__flex--1(type="checkbox" name="attr_cust_dexterity_save_prof" value="(@{pb})")
+ span(data-i18n="dexterity") Dexterity
+ .options__row.options__row--noborder
+ input.options__flex--1(type="checkbox" name="attr_cust_constitution_save_prof" value="(@{pb})")
+ span(data-i18n="constitution") Constitution
+ input.options__flex--1(type="checkbox" name="attr_cust_intelligence_save_prof" value="(@{pb})")
+ span(data-i18n="intelligence") Intelligence
+ .options__row
+ input.options__flex--1(type="checkbox" name="attr_cust_wisdom_save_prof" value="(@{pb})")
+ span(data-i18n="wisdom") Wisdom
+ input.options__flex--1(type="checkbox" name="attr_cust_charisma_save_prof" value="(@{pb})")
+ span(data-i18n="charisma") Charisma
+ .options__row--title
+ span(data-i18n="cust-class-opts") CUSTOM CLASS OPTIONS
+ .options.spell_slot_mods
+ .options__row
+ each level in [1,2,3]
+ .options__flex--2
+ span(data-i18n="lvl-u") LEVEL
+ span.options__flex=level
+ span.options__flex--1 +
+ input.options__flex--1(type="text" name=`attr_lvl${level}_slots_mod` value="0" placeholder="0" title=`@{lvl${level}_slots_mod}`)
+ .options__row--title
+ span(data-i18n="spell_slot_modifiers-u") SPELL SLOT MODIFIERS
+ .settings__col
+ .options
+ .options__row
+ span.options__flex--3(data-i18n="strength-u") STRENGTH
+ span.options__flex--1 +
+ input.options__flex--1(type="text" name="attr_strength_bonus" value="0" placeholder="0" title="@{strength_bonus}")
+ span.options__flex--3(data-i18n="dexterity-u") DEXTERITY
+ span.options__flex--1 +
+ input.options__flex--1(type="text" name="attr_dexterity_bonus" value="0" placeholder="0" title="@{dexterity_bonus}")
+ .options__row
+ span.options__flex--3(data-i18n="constitution-u") CONSTITUTION
+ span.options__flex--1 +
+ input.options__flex--1(type="text" name="attr_constitution_bonus" value="0" placeholder="0" title="@{constitution_bonus}")
+ span.options__flex--3(data-i18n="intelligence-u") INTELLIGENCE
+ span.options__flex--1 +
+ input.options__flex--1(type="text" name="attr_intelligence_bonus" value="0" placeholder="0" title="@{intelligence_bonus}")
+ .options__row
+ span.options__flex--3(data-i18n="wisdom-u") WISDOM
+ span.options__flex--1 +
+ input.options__flex--1(type="text" name="attr_wisdom_bonus" value="0" placeholder="0" title="@{wisdom_bonus}")
+ span.options__flex--3(data-i18n="charisma-u") CHARISMA
+ span.options__flex--1 +
+ input.options__flex--1(type="text" name="attr_charisma_bonus" value="0" placeholder="0" title="@{charisma_bonus}")
+ .options__row.options__row--noborder
+ span(data-i18n="initiative-mod:-u") INITIATIVE MODIFIER:
+ input(type="text" name="attr_initmod" placeholder="0" value="0")
+ .options__row.options__row--noborder
+ span(data-i18n="initiative-style:-u") INITIATIVE STYLE:
+ select(name="attr_initiative_style")
+ option(value="@{d20}" selected="selected" data-i18n="norm") Normal
+ option(value="{@{d20},@{d20}}kh1" data-i18n="adv") Advantage
+ option(value="{@{d20},@{d20}}kl1" data-i18n="disadv") Disadvantage
+ .options__row
+ input(type="checkbox" name="attr_init_tiebreaker" value="@{dexterity}/100")
+ span(data-i18n="add-dex-tiebreaker-u") ADD DEX TIEBREAKER TO INITIATIVE
+ //- .options__row.options__row--noborder
+ //- span(data-i18n="hpmods:-u") HP MODIFIERS:
+ //- fieldset.repeating_hpmod
+ //- div
+ //- span(data-i18n="levels:-u") LEVELS:
+ //- select(name="attr_levels")
+ //- option(value="total" selected="selected" data-i18n="total-level-u") TOTAL LEVEL
+ //- option(value="base" data-i18n="main-class-level-u") MAIN CLASS LEVEL
+ //- option(value="multiclass1" data-i18n="class-2-level-u") CLASS 2 LEVEL
+ //- option(value="multiclass2" data-i18n="class-3-level-u") CLASS 3 LEVEL
+ //- option(value="multiclass3" data-i18n="class-4-level-u") CLASS 4 LEVEL
+ //- br
+ //- span(data-i18n="source:-u") SOURCE:
+ //- input(type="text" name="attr_source")
+ //- span(data-i18n="mod:-u") MOD:
+ //- input(type="text" name="attr_mod")
+ .options__row--title
+ span(data-i18n="attribute-opts-u") ATTRIBUTE OPTIONS
+ .options
+ .options__row.options__row--noborder
+ span.options__flex--4(data-i18n="strength-save-u") STRENGTH SAVE
+ span.options__flex +
+ input.options__flex--1(type="text" name="attr_strength_save_mod" value="0" placeholder="0" title="@{strength_save_mod}")
+ span.options__flex--4(data-i18n="dexterity-save-u") DEXTERITY SAVE
+ span.options__flex +
+ input.options__flex--1(type="text" name="attr_dexterity_save_mod" value="0" placeholder="0" title="@{dexterity_save_mod}")
+ .options__row.options__row--noborder
+ span.options__flex--4(data-i18n="constitution-save-u") CONSTITUTION SAVE
+ span.options__flex +
+ input.options__flex--1(type="text" name="attr_constitution_save_mod" value="0" placeholder="0" title="@{constitution_save_mod}")
+ span.options__flex--4(data-i18n="intelligence-save-u") INTELLIGENCE SAVE
+ span.options__flex +
+ input.options__flex--1(type="text" name="attr_intelligence_save_mod" value="0" placeholder="0" title="@{intelligence_save_mod}")
+ .options__row
+ span.options__flex--4(data-i18n="wisdom-save-u") WISDOM SAVE
+ span.options__flex +
+ input.options__flex--1(type="text" name="attr_wisdom_save_mod" value="0" placeholder="0" title="@{wisdom_save_mod}")
+ span.options__flex--4(data-i18n="charisma-save-u") CHARISMA SAVE
+ span.options__flex +
+ input.options__flex--1(type="text" name="attr_charisma_save_mod" value="0" placeholder="0" title="@{charisma_save_mod}")
+ .options__row
+ span(data-i18n="death-save-mod:-u") DEATH SAVE MODIFIER:
+ input(type="text" name="attr_death_save_mod" placeholder="0" value="0")
+ .options__row
+ span(data-i18n="glob-saving-mod:-u") GLOBAL SAVING THROW MODIFIER:
+ input(type="text" name="attr_globalsavemod" placeholder="0" value="0")
+ .options__row--title
+ span(data-i18n="save-opts-u") SAVE OPTIONS
+ .options
+ div(data-i18n-list="skills-list")
+ for skill in globalAttributesByCategory.skills
+ - const { name, ability } = skill;
+ - const name_undercase = name.toLowerCase().replace(/ /g,"_");
+ - const ability_short = ability.substring(0,3);
+ .options__row(data-i18n-list-item=`${name_undercase}`)
+ select.options__flex--4(name=`attr_${name_undercase}_type`)
+ option(value="1" selected="selected" data-i18n="normal") Normal
+ option(value="2" data-i18n="expertise") Expertise
+ span.options__flex--5(data-i18n=`${name_undercase}-core`)
+ | #{name}
+ span (#{ability_short})
+ span.options__flex +
+ input.options__flex--1(type="text" name=`attr_${name_undercase}_flat` value="0" placeholder="0" title=`@{${name_undercase}_flat}`)
+ //- .options__row
+ //- input(type="checkbox" name="attr_jack_of_all_trades" value="@{jack}")
+ //- span(data-i18n="jack-of-all-u") JACK OF ALL TRADES
+ //- .options__row
+ //- span(data-i18n="reliable-talent-u") RELIABLE TALENT:
+ //- select.dtype(name="attr_reliable_talent")
+ //- option(value="10" data-i18n="on") On
+ //- option(value="0" selected="selected" data-i18n="off") Off
+ .options__row
+ span(data-i18n="pass-perc-mod:-u") PASSIVE PERCEPTION MODIFIER:
+ input(type="text" name="attr_passiveperceptionmod" placeholder="0" value="0")
+ .options__row--title
+ span(data-i18n="skill-opts-u") SKILL OPTIONS
+ .settings__col
+ .options
+ .options__row
+ input(type="checkbox" name="attr_npc" value="1")
+ span(data-i18n="npc-u") NPC
+ .options__row
+ span(data-i18n="roll-queries:-u") ROLL QUERIES:
+ select(name="attr_rtype")
+ option(value="{{always=1}} {{r2=[[@{d20}" data-i18n="always-roll-adv") Always Roll Advantage
+ option(value="@{advantagetoggle}" data-i18n="toggle-roll-adv") Advantage Toggle
+ option(value="@{queryadvantage}" data-i18n="query-roll-adv") Query Advantage
+ option(value="{{normal=1}} {{r2=[[0d20" data-i18n="never-roll-adv") Never Roll Advantage
+ .options__row
+ span(data-i18n="whisp-rolls-gm:-u") WHISPER ROLLS TO GM:
+ select(name="attr_wtype")
+ option(value="" data-i18n="never-whisper-roll") Never Whisper Rolls
+ option(value="@{whispertoggle}" data-i18n="toggle-roll-whisper") Whisper Toggle
+ option(value="?{Whisper?|Public Roll,|Whisper Roll,/w gm }" data-i18n="query-whisper-roll") Query Whisper
+ option(value="/w gm " data-i18n="always-whisper-roll") Always Whisper Rolls
+ .options__row
+ span(data-i18n="auto-dmg-roll:-u") AUTO DAMAGE ROLL:
+ select.dtype(name="attr_dtype")
+ option(value="pick" data-i18n="never-roll-dmg") Don't Auto Roll Damage
+ option(value="full" data-i18n="always-roll-dmg") Auto Roll Damage & Crit
+ .options__row
+ span(data-i18n="core-die-roll:-u") CORE DIE ROLL:
+ input(type="text" name="attr_core_die" value="1d20" placeholder="1d20" title="@{core_die}")
+ .options__row
+ span(data-i18n="default-critical-range:-u") CRITICAL RANGE:
+ input(type="number" name="attr_default_critical_range" value="20" placeholder="20")
+ .options__row
+ span(data-i18n="prof-bonus:-u") PROFICIENCY BONUS:
+ select.dtype(name="attr_pb_type")
+ option(value="level" data-i18n="by-level") By Level (Default)
+ option(value="die" data-i18n="prof-die") Proficency Die (DMG)
+ option(value="custom" data-i18n="custom") Custom
+ input(type="hidden" name="attr_pb_type")
+ input.pb_custom(type="text" name="attr_pb_custom" placeholder="2d10")
+ .options__row
+ span(data-i18n="add-char-to-templates:-u") ADD CHARACTER NAME TO TEMPLATES:
+ select.dtype(name="attr_charname_output")
+ option(value="{{charname=@{character_name}}}" data-i18n="on") On
+ option(value="charname=@{character_name}" selected="selected" data-i18n="off") Off
+ .options__row
+ span(data-i18n="level-calculations:-u") LEVEL CALCULATIONS:
+ select.dtype(name="attr_level_calculations")
+ option(value="on" selected="selected" data-i18n="on") On
+ option(value="off" data-i18n="off") Off
+ .options__row.options__row--noborder
+ span(data-i18n="encumbrance:-u") ENCUMBRANCE:
+ select(name="attr_encumbrance_setting")
+ option(value="off" data-i18n="simple") Simple
+ option(value="on" data-i18n="variant-phb") Variant (PHB p176)
+ option(value="disabled" data-i18n="off") Off
+ .options__row
+ input(type="checkbox" name="attr_ingore_non_equipped_weight" value="1")
+ span(data-i18n="ingore-non-equipped-weight") IGNORE NON-EQUIPPED ITEMS WEIGHT
+ .options__row
+ span(data-i18n="inventory:-u") INVENTORY:
+ select(name="attr_simpleinventory")
+ option(value="complex" data-i18n="compendium-compatible") Compendium Compatible
+ option(value="simple" data-i18n="simple") Simple
+ .options__row--title
+ span(data-i18n="general-opts-u") GENERAL OPTIONS
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/tabs/spells.pug b/Brancalonia Official/src/pug/layouts/tabs/spells.pug
new file mode 100644
index 0000000000..d6a750d75c
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/tabs/spells.pug
@@ -0,0 +1,14 @@
+input.spellicon_flag(type="hidden", name="attr_spellicon_flag", value!="all")
+.spells-body
+ .spells
+ .spells__features
+ include ../panels/Features
+ include ../panels/Moves
+ .spells__stats
+ include ../panels/SpellStats
+ .spells__section
+ +SpellSection(0, true)
+ +SpellSection(1)
+ .spells__section
+ +SpellSection(2)
+ +SpellSection(3)
diff --git a/Brancalonia Official/src/pug/layouts/utility/advantagetoggle.pug b/Brancalonia Official/src/pug/layouts/utility/advantagetoggle.pug
new file mode 100644
index 0000000000..6aded444c9
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/utility/advantagetoggle.pug
@@ -0,0 +1,11 @@
+input.toggleflag(name='attr_rtype' type='hidden')
+.navigation__toggle-group
+ .navigation__toggle
+ input(type='radio' name='attr_advantagetoggle' value='{{query=1}} {{advantage=1}} {{r2=[[@{d20}')
+ span(data-i18n='ADVANTAGE')
+ .navigation__toggle
+ input.toggle-center(type='radio' name='attr_advantagetoggle' value='{{query=1}} {{normal=1}} {{r2=[[0d20' checked='checked')
+ span(data-i18n='NORMAL')
+ .navigation__toggle
+ input.toggle-right(type='radio' name='attr_advantagetoggle' value='{{query=1}} {{disadvantage=1}} {{r2=[[@{d20}')
+ span(data-i18n='DISADVANTAGE')
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/layouts/utility/dialogs.pug b/Brancalonia Official/src/pug/layouts/utility/dialogs.pug
new file mode 100644
index 0000000000..900c542c57
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/utility/dialogs.pug
@@ -0,0 +1,23 @@
+.monster_confirm
+ span(data-i18n='are_you_sure') Are you sure you want to turn this character into a
+ span(name='attr_drop_name')
+ span ?
+ div(style='margin-top: 20px;')
+ div(style='position: relative; display: inline-block; margin-right: 25px;')
+ input.yes(type='checkbox' name='attr_confirm')
+ span.yes(data-i18n='yes') Yes
+ div(style='position: relative; display: inline-block;')
+ input.cancel(type='checkbox' name='attr_cancel')
+ span.cancel(data-i18n='cancel') Cancel
+.mancer_confirm
+ span(style='line-height: 25px' data-i18n='do_you_want_mancer') How do you want to create this character?
+ div(style='margin-top: 20px;')
+ div(style='position: relative; display: inline-block; width:130px;')
+ input.yes(type='checkbox' style='width:130px;' name='attr_mancer_confirm')
+ span.yes(style='width:130px;' data-i18n='mancer-confirm-yes') Use the Charactermancer
+ div(style='position: relative; display: inline-block; width:80px;')
+ input.yes(style='width:80px;' type='checkbox' name='attr_mancer_npc')
+ span.yes(style='width:80px;' data-i18n='npc-new') Create an NPC
+ div(style='position: relative; display: inline-block; width:90px;')
+ input.yes(type='checkbox' style='width:90px;' name='attr_mancer_cancel')
+ span.yes(style='width:90px;' data-i18n='manual') Edit sheet direclty
diff --git a/Brancalonia Official/src/pug/layouts/utility/navigation.pug b/Brancalonia Official/src/pug/layouts/utility/navigation.pug
new file mode 100644
index 0000000000..06b1136600
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/utility/navigation.pug
@@ -0,0 +1,18 @@
+.navigation
+ .navigation__toggles
+ include advantagetoggle
+ include whispertoggle
+
+ .navigation__pages
+ .navigation__toggle
+ input(name="attr_tab", type="radio", value="core", checked)
+ span(data-i18n="CORE")
+ .navigation__toggle
+ input(name="attr_tab", type="radio", value="spells")
+ span(data-i18n="SPELLS & MOVES")
+ .navigation__toggle
+ input(name="attr_tab", type="radio", value="bio")
+ span(data-i18n="BIO")
+ .navigation__toggle.navigation__toggle--settings
+ input(name="attr_tab", type="radio", value="settings")
+ span.pictos y
diff --git a/Brancalonia Official/src/pug/layouts/utility/whispertoggle.pug b/Brancalonia Official/src/pug/layouts/utility/whispertoggle.pug
new file mode 100644
index 0000000000..f6f3daa842
--- /dev/null
+++ b/Brancalonia Official/src/pug/layouts/utility/whispertoggle.pug
@@ -0,0 +1,7 @@
+input.toggleflag(name='attr_wtype' type='hidden')
+.navigation__toggle.navigation__toggle--whisperleft
+ input.toggle-left(name='attr_whispertoggle' type='radio' value='' checked)
+ span(data-i18n='public') PUBLIC
+.navigation__toggle
+ input.toggle-right(name='attr_whispertoggle' type='radio' value='/w gm ')
+ span(data-i18n='WHISPER') WHISPER
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/lp.pug b/Brancalonia Official/src/pug/lp.pug
new file mode 100644
index 0000000000..167dd05799
--- /dev/null
+++ b/Brancalonia Official/src/pug/lp.pug
@@ -0,0 +1,230 @@
+mixin hiddenInput(name)
+ input(type='hidden' name=`comp_${name}`)
+
+mixin lpSteps(showCancel=true)
+ ol.steps.lp-steps
+ if showCancel
+ li
+ button.exit(type='action' name='act_cancel' data-i18n='cancel-u') CANCEL
+ if showCancel
+ .topbar-holder
+
+mixin cancelPrompt()
+ .choice.cancel-prompt
+ p.label(data-i18n='charmancer-cancel-heading') Where would you like to go, Traveler?
+ button.warning(type='cancel' value='lp-cancel' data-i18n='cancel_charactermancer') Discard and exit
+ button(type='action' name='act_continue')
+ span(data-i18n='continue-charmancer') Continue Charactermancer
+ p.warning
+ span(data-i18n='charmancer-discard-warning')
+ | Discard and Exit will discard all choices you’ve made in Charactermancer and let you edit your character sheet directly.
+
+mixin bottomBar(nav={}, dialog=false, firstTab=false, lastTab=false)
+ .bottombar
+ if firstTab
+ button.prev(type='cancel' value='lp-cancel' data-i18n='opt-out-u') OPT OUT
+ else if !dialog
+ if(nav.back.action)
+ button.prev(type='action' name=`${nav.back.name}` data-i18n='back') Back
+ else
+ button.prev(type=`${nav.back.type}` value=`${nav.back.value}` data-i18n='back') Back
+ button.jump(type='button' data-scroll='#top' data-i18n='back-to-top') Back to Top
+ if dialog
+ button.next(type='action' name='act_lp-spellchoice_back' data-i18n='accept') Accept
+ else if lastTab
+ button.next.choice.apply_changes(type='finish' value='lp-mancer' data-i18n='apply-changes') Apply Changes
+ else
+ if(nav.next.action)
+ button.next(type='action' name=`${nav.next.name}` data-i18n='next') Next
+ else
+ button.next(type=`${nav.next.type}` value=`${nav.next.value}` data-i18n='next') Next
+
+mixin multiclass(level)
+ .row
+ div(style='display: inline;')
+ div(class=`class${level}_selector`)
+ select.multiclass_select(name=`comp_class${level}` style='width: 85%;' value='')
+ option(value='' data-i18n='choose') Choose
+ .levels-message
+ span(class=`class${level}_update`)
+ input.addinglevel(type='number' name=`comp_class${level}_addlevel` min='0' max='19')
+ span(class=`class${level}_tot`)
+ .levels-hp-row
+ h2(data-i18n='hp-u') HP
+ input(type='number' name=`comp_class${level}_addhp`)
+ input.hp-flag(type='hidden' name=`comp_class${level}_hp_flag` value='average')
+ div(class=`class${level}_rollhp` style='display: inline;')
+ button(type='roll' name=`roll_class${level}_rollhp` value='' title='You must input a level increase to this class' data-i18n='roll') Roll
+ div(class=`class${level}_averagehp` style='display: inline;')
+ button(type='roll' name=`roll_class${level}_averagehp` value='' title='' data-i18n='average') Average
+ input.hpbylevel-toggle(type='checkbox' name='comp_hpbyLevel')
+ span.collapse 9
+ div(class=`class${level}_by-levels`)
+ div
+ h3(class=`class${level}_features_title choice` style='display: inline;' data-i18n='charmancer-class-features:') Class Features:
+ button.mancer_info(type='action' name=`act_class${level}`) i
+ div(class=`class${level}_features`)
+ div(class=`subclass${level}_name`)
+ div(class=`subclass${level}_warning`)
+ div(class=`subclass${level}_selector`)
+ select(class=`choice subclass${level}` name=`comp_class${level}_subclass`)
+ option(value='' data-i18n='choose') Choose
+ div
+ h3(class=`subclass${level}_features_title choice` style='display: inline;' data-i18n='charmancer-subclass-features:') Subclass Features:
+ button.mancer_info(type='action' name=`act_class${level}_subclass`) i
+ div(class=`subclass${level}_features`)
+
+charmancer.sheet-charmancer-lp-welcome
+ .charmancer.container
+ +lpSteps(false)
+ .logos
+ span.charmancer-logo
+ span.compendium-logo
+ p.label(data-i18n='charmancer-welcome-lp') Welcome to the Charactermancer Level Up!
+ p(data-i18n='charmancer-leveler-what-is-lp')
+ | Look at you, with all that experience. Now it's time to claim your reward. You'll walk through the step-by-step process to make a few decisions, and your character will be at the next level in no time. Changes are saved as you move through the process, but if you change your mind, you'll need to revisit the steps and choices that come after.
+ p.label(data-i18n='charmancer-compendium') Your Compendium Awaits.
+ p(data-i18n='charmancer-compendium-detail-lp')
+ | The Charactermancer currently supports Dungeons & Dragons 5th Edition SRD, Player's Handbook, and Guildmasters' Guide to Ravnica. Xanathar's Guide to everything will be supported in the coming weeks. You can add the Player's Handbook and Guildmasters' Guide to Ravnica to your compendium in the Marketplace, or the game owner can share their compendium with everyone in the game.
+ p.label(data-i18n='get-started') Get started by clicking "Next".
+ +bottomBar({next: {type:'back', value: 'lp-levels'}}, false, true)
+ +cancelPrompt()
+ each name in ['spellinfo', 'previous_abilities', 'previous_attributes', 'previous_proficiencies', 'previous_repeating', 'lp-race', 'lp-subrace', 'lp-background']
+ +hiddenInput(name)
+
+charmancer.sheet-charmancer-lp-levels
+ .charmancer.container
+ +lpSteps()
+ div(style='width: 100%;')
+ p(data-i18n='charmancer-leveler-level-info1')
+ | Your existing class levels have been pre-populated for you. By default your primary class has been set to be increased by one level. You can change how many levels to increase below, as well as adding a new multiclass.
+ p(data-i18n='charmancer-leveler-level-info2')
+ | In each class section you'll have the option to take the average number of hit points or to roll randomly, choose class features for the levels you're advancing, and choose your subclass if appropriate.
+ div(style='width: 100%; font-weight: bold;')
+ .levels_message
+ .choices.levels-multiclass
+ input.lock-custom-class(type='hidden' name='comp_lockcustomclass')
+ input.hide-multiclass(type='hidden' name='comp_multiclass' min='0' max='3')
+ input(type='hidden' name='comp_multiclass_initial' min='0' max='3')
+ .row.class1_container
+ .custom_warning
+ span(data-i18n='charmancer-leveler-custom-class-warning') The Level Up tool does not support custom classes at this time.
+ div
+ .class1_selector
+ select(name='comp_class1' value='')
+ .levels-message
+ span.class1_update
+ input.addinglevel(type='number' name='comp_class1_addlevel' min='0' max='19' value='1')
+ span.class1_tot
+ .levels-hp-row
+ h2(data-i18n='hp-u') HP
+ input(type='number' name='comp_class1_addhp')
+ input.hp-flag(type='hidden' name='comp_class1_hp_flag' value='average')
+ .class1_rollhp(style='display: inline;')
+ button(type='roll' name='roll_class1_rollhp' value='' title='' data-i18n='roll') Roll
+ .class1_averagehp(style='display: inline;')
+ button(type='roll' name='roll_class1_averagehp' value='' title='' data-i18n='average') Average
+ input.hpbylevel-toggle(type='checkbox' name='comp_hpbyLevel')
+ span.collapse 9
+ .class1_by-levels
+ .class_features_container
+ h3.class1_features_title.choice(style='display: inline;' data-i18n='charmancer-class-features:') Class Features:
+ button.mancer_info(type='action' name='act_class1') i
+ .class1_features
+ .subclass1_name
+ .subclass1_warning
+ .subclass1_selector
+ select.choice.subclass1(name='comp_class1_subclass')
+ option(value='' data-i18n='choose') Choose
+ .subclass_features_container
+ h3.subclass1_features_title.choice(style='display: inline;' data-i18n='charmancer-subclass-features:') Subclass Features:
+ button.mancer_info(type='action' name='act_class1_subclass') i
+ .subclass1_features
+ +multiclass(2)
+ +multiclass(3)
+ +multiclass(4)
+ div
+ .multiclass_message
+ button(type='action' name='act_multiclass_add') +
+ button(type='action' name='act_multiclass_remove') -
+ .info
+ .sheet-compendium-page.sheet-levels-info(accept='Rules:Classes')
+ +bottomBar({back: {type:'back', value: 'lp-welcome'}, next: {type:'back', value: 'lp-choices'}})
+ +cancelPrompt()
+ each name in ['characterlevel', 'class1', 'class1_subclass', 'class1_currentlevel', 'class1_classlevel', 'class1_hitdie', 'class2', 'class2_subclass', 'class2_currentlevel', 'class2_classlevel', 'class2_hitdie', 'class3', 'class3_subclass', 'class3_currentlevel', 'class3_classlevel', 'class3_hitdie', 'class4', 'class4_subclass', 'class4_currentlevel', 'class4_classlevel', 'class4_hitdie', 'asi', 'spells']
+ +hiddenInput(name)
+
+charmancer.sheet-charmancer-lp-choices
+ .charmancer.container
+ +lpSteps()
+ .choices
+ .info
+ .sheet-compendium-page.sheet-class-info(accept='Rules:Classes')
+ +bottomBar({back: {type:'back', value: 'lp-levels'}, next: {action: true, name: 'act_lp-choices_next'}})
+ +cancelPrompt()
+
+charmancer.sheet-charmancer-lp-asi
+ .charmancer.container
+ +lpSteps()
+ span.spinner-toggle
+ .spinnerloader
+ .choices
+ .info
+ .sheet-compendium-page.sheet-class-info(accept='Rules:Ability Scores')
+ +bottomBar({back: {type:'back', value: 'lp-choices'}, next: {action: true, name: 'act_lp-asi_next'}})
+ +cancelPrompt()
+
+charmancer.sheet-charmancer-lp-spells
+ .charmancer.container
+ +lpSteps()
+ span.pagelock(style='display: none')
+ .choices.spellslide
+ p.instructions(data-i18n='charmancer-leveler-spells-info')
+ | Listed here are the current spells your character already knows. If you gained access to more spells during your advancement you will be able to select them below. Check next to the spells you wish to learn. The Charactermancer will help you pick the right number of spells and from the correct list. If your class has the option to swap out spells, you can do so by unselecting currently known spells which will allow you to select new ones in their place.
+ p.spells-summary
+ .cantripinfo
+ .info.spellslide
+ .sheet-compendium-page.sheet-spells-info(accept='Rules:Spells')
+ +bottomBar({back: {action: true, name: 'act_lp-spells_back'}, next: {type: 'back', value: 'lp-summary'}})
+ +cancelPrompt()
+ each name in ['knowncantrips', 'knownspells', 'newcantrips', 'newspells', 'replace']
+ +hiddenInput(name)
+
+charmancer.sheet-charmancer-lp-summary
+ .charmancer.container
+ +lpSteps()
+ .lp-summary.summary-container
+ .before
+ h2(data-i18n='before-leveling') Before Leveling
+ div
+ .after
+ h2(data-i18n='after-leveling') After Leveling
+ div
+ .summary-container
+ .summary
+ p.label(data-i18n='features') Features
+ .feature_info
+ .summary
+ p.label(data-i18n='feats')
+ .feat_info
+ .summary
+ p.label(data-i18n='spells') Spells
+ .spell_info
+ .choice.returnblock.spells_button
+ span(data-i18n='return-to:') Return to:
+ button.step(type='back' value='l1-spells' data-i18n='spells-u') SPELLS
+ +bottomBar({back: {action: true, name: 'act_lp-summary_back'}}, false, false, true)
+ +cancelPrompt()
+
+charmancer.sheet-charmancer-lp-spellchoice
+ .charmancer.container
+ +lpSteps()
+ span.pagelock(style='display: none')
+ .choices.spellslide
+ p.instructions
+ .info.spellslide
+ .sheet-compendium-page.sheet-spells-info(accept='Rules:Spells')
+ +bottomBar({}, true)
+ +cancelPrompt()
+ each name in ['source', 'valid', 'newcantrips', 'newspells']
+ +hiddenInput(name)
\ No newline at end of file
diff --git a/Brancalonia Official/src/pug/npc.pug b/Brancalonia Official/src/pug/npc.pug
new file mode 100644
index 0000000000..2ea2bb4cf1
--- /dev/null
+++ b/Brancalonia Official/src/pug/npc.pug
@@ -0,0 +1,74 @@
+mixin npcAttribute(name)
+ span(data-i18n=`${name.substring(0,3)}-u`) #{name.substring(0,3).toUpperCase()}
+ input(type="text" name=`attr_${name}_base` value!="10")
+
+mixin npcAttributeRoll(name)
+ - var short = name.substring(0,3);
+ - var value = `@{wtype}&{template:npc} @{npc_name_flag} {{rname=^{${name}}}} {{mod=[[[[@{${name}_mod}]][${short.toUpperCase()}]]]}} {{r1=[[@{d20}+[[@{${name}_mod}]][${short.toUpperCase()}]]]}} @{rtype}+[[@{${name}_mod}]][${short.toUpperCase()}]]]}} {{type=Ability}}`;
+ .npc__attribute-container
+ button.npc__attribute-button(type="roll" name=`roll_npc_${short}` value!=value)
+ span.npc__attribute-title(data-i18n=`${short}-u`) #{short.toUpperCase()}
+ span.npc__attribute-score(name=`attr_${name}`)
+ span (
+ span.npc__attribute-mod(name=`attr_${name}_mod`)
+ span )
+
+mixin npcSave(name)
+ - var short = name.substring(0,3);
+ span(data-i18n=`${short}-u`) #{short.toUpperCase()}
+ input(type="text" name=`attr_npc_${short}_save_base` placeholder="0")
+ input(type="hidden" name=`attr_npc_${short}_save` value!=`@{${name}_mod}`)
+
+mixin npcSaveRoll(name)
+ - const short = name.substring(0,3);
+ - const capitalized = short.charAt(0).toUpperCase() + short.slice(1);
+ - const value = `@{wtype}&{template:npc} @{npc_name_flag} {{rname=^{${name}-save}}} {{mod=[[[[@{npc_${short}_save}]][${short.toUpperCase()} SAVE]]]}} {{r1=[[@{d20}+[[@{npc_${short}_save}]][${short.toUpperCase()} SAVE]]]}} @{rtype}+[[@{npc_${short}_save}]][${short.toUpperCase()} SAVE]]]}} {{type=Save}}`
+ input.npc__flag--mod(type="hidden" name=`attr_npc_${short}_save`)
+ button.npc__save(type="roll" name=`roll_npc_${short}_save` value!=value)
+ span(data-i18n=short) #{capitalized}
+ span.stat(name=`attr_npc_${short}_save`)
+
+mixin npcSkill(skill)
+ - var name = skill.split(':')[0];
+ - var sanitized = name.replace(/ /g,'_');
+ - var modifier = skill.split(':')[1];
+ .options__row.options__row--noborder(data-i18n-list-item=sanitized)
+ span.options__flex(data-i18n=`${sanitized}-u`) #{name.toUpperCase()}
+ input.options__flex--2(type="text" name=`attr_npc_${sanitized}_base` placeholder="0")
+ input(type="hidden" name=`attr_npc_${sanitized}` value!=`@{${modifier}_mod}`)
+
+mixin npcSkillRoll(skill)
+ - var sanitized = skill.replace(/ /g,'_');
+ - var capitalized = skill.charAt(0).toUpperCase() + skill.slice(1);
+ - var value = `@{wtype}&{template:npc} @{npc_name_flag} {{rname=^{${sanitized}}}} {{mod=@{npc_${sanitized}}}} {{r1=[[@{d20}+@{npc_${sanitized}}]]}} @{rtype}+@{npc_${sanitized}}]]}} {{type=Skill}}`
+ input.npc__flag--mod(type="hidden" name=`attr_npc_${sanitized}`)
+ span(data-i18n-list-item=sanitized)
+ button.npc__skill(type="roll" name=`roll_npc_${sanitized}` value!=value)
+ span(data-i18n=sanitized) #{capitalized}
+ span.stat(name=`attr_npc_${sanitized}`)
+
+mixin toggleButton(attribute, cssClass="npc__toggle", showIcon=false, label="")
+ input.toggle__input(name=`attr_${attribute}`, type="hidden", value="on")
+ .toggle(class=`${cssClass}`)
+ input(name=`attr_${attribute}`, type="checkbox", checked)
+ span y
+
+include layouts/panels/npc/Settings
+
+.npc__grid
+
+ .npc__column
+
+ include layouts/panels/npc/Stats
+
+ include layouts/panels/npc/Traits
+
+ include layouts/panels/npc/BonusActions
+
+ .npc__column--right
+
+ include layouts/panels/npc/Actions
+
+ include layouts/panels/npc/Reactions
+
+ include layouts/panels/npc/LegendaryActions
\ No newline at end of file
diff --git a/Brancalonia Official/src/scss/abstracts/_placeholders.scss b/Brancalonia Official/src/scss/abstracts/_placeholders.scss
new file mode 100644
index 0000000000..25a292c967
--- /dev/null
+++ b/Brancalonia Official/src/scss/abstracts/_placeholders.scss
@@ -0,0 +1,59 @@
+%SaveSkillBox {
+ text-align: center;
+
+ .label {
+ font-weight: bold;
+ text-align: center;
+ }
+}
+
+%TextBox {
+ width: auto;
+ margin-top: 0.5rem;
+
+ border: {
+ width: 0.5rem;
+ style: solid;
+ color: transparent;
+ image-slice: 10% 5% 10% 5%;
+ image-width: 0.75rem 1rem 0.75rem 1rem;
+ image-outset: 0px 0px 0px 0px;
+ image-repeat: round round;
+ image-source: url("https://s3.amazonaws.com/files.d20.io/images/229248387/s-7U3vgLH9-s9S_jTdpHBw/max.png?1624041526");
+ }
+}
+
+%MagicLabel {
+ margin: auto;
+ height: 3rem;
+ width: 100%;
+ margin-bottom: -2rem;
+ text-align: center;
+ padding-top: 0.75rem;
+
+ background: {
+ image: url("https://s3.amazonaws.com/files.d20.io/images/229570991/7amxLms4s6lpmFthaaBpcQ/med.png?1624162130");
+ position: center center;
+ size: 100% 100%;
+ repeat: no-repeat;
+ }
+
+ font-size: 1.25rem;
+}
+
+%BoxLabel {
+ position: relative;
+ height: 2.5rem;
+ border: {
+ image-slice: 10 190 33 146 fill;
+ image-width: 0.5rem 4rem 2rem 4rem;
+ image-outset: 0.5rem 3rem 2rem 3.5rem;
+ image-repeat: round stretch;
+ image-source: url("https://res.cloudinary.com/dmrhbjudf/image/upload/v1626586904/box-header-2_qo5bye.png");
+ style: solid;
+ }
+
+ background-color: white;
+
+ text-align: center;
+}
diff --git a/Brancalonia Official/src/scss/external/sanitization-fixes.scss b/Brancalonia Official/src/scss/external/sanitization-fixes.scss
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Brancalonia Official/src/scss/generic.scss b/Brancalonia Official/src/scss/generic.scss
new file mode 100644
index 0000000000..10194c549a
--- /dev/null
+++ b/Brancalonia Official/src/scss/generic.scss
@@ -0,0 +1,117 @@
+
+ .ellipsis {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+/* GRID
+ ============================= */
+ div.grid {
+ display: inline-grid;
+ grid-column-gap: 1%;
+ grid-row-gap: 0.5%;
+ }
+
+ %gridRowCol {
+ display: inline-grid;
+ overflow: hidden;
+ grid-auto-rows: min-content;
+ grid-column-gap: 1%;
+ }
+
+ .bold {
+ font-weight: bold;
+ }
+
+ .italics {
+ font-style: italic;
+ }
+
+ .text-right {
+ text-align: right;
+ }
+
+ .text-uppercase {
+ text-transform: uppercase;
+ }
+
+ .text-capitalize {
+ text-transform: capitalize;
+ }
+
+ // div.2column {
+ // grid-template-columns: 1fr 1fr;
+ // }
+
+ div.auto2column {
+ grid-template-columns: auto 1fr;
+ }
+
+
+// dialogs
+
+.dialog {
+ display: none;
+
+ position: absolute;
+ z-index: 999;
+ width: 100%;
+ height: 100%;
+
+ background-color: rgba(white, 0.5);
+
+ &__wrapper {
+ position: fixed;
+ top: 45%;
+ left: calc(50% - 20rem);
+ width: 40rem;
+ margin: auto;
+ padding: 2rem;
+ padding-bottom: 0;
+
+ border: 1px solid black;
+
+ background-color: white;
+
+ text-align: center;
+ }
+
+ &__newname {
+ display: block;
+ margin-top: 1rem;
+
+ font-weight: bold;
+ }
+
+ &__buttonrow {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ width: 100%;
+ margin: auto;
+ margin-top: 2rem;
+ padding: 1rem 1rem;
+
+ border-top: 1px solid rgba(black, 0.5);
+ }
+
+ &__button {
+ padding: 0.5rem 1rem;
+
+ border: 1px solid black;
+ border-radius: 0.5rem;
+ }
+ }
+
+input[name*="npc_confirmation_flag"][value="1"] + .dialog {
+ display: block;
+}
+
+.active-drop-target.dropping {
+ border: none;
+ background: transparent;
+
+ .dialog--warning {
+ display: block !important;
+ }
+}
\ No newline at end of file
diff --git a/Brancalonia Official/src/scss/generics/_RollButton.scss b/Brancalonia Official/src/scss/generics/_RollButton.scss
new file mode 100644
index 0000000000..10b23f8e3a
--- /dev/null
+++ b/Brancalonia Official/src/scss/generics/_RollButton.scss
@@ -0,0 +1,25 @@
+%RollButton {
+ width: 100%;
+ padding: 0;
+ margin: 0;
+
+ border: none;
+
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ color: black;
+ text-shadow: none;
+
+ font-size: 0.8rem;
+ font-weight: bold;
+ line-height: 1.2rem;
+
+ &:before {
+ content: "";
+ }
+
+ &:hover {
+ color: #ec2127;
+ }
+}
diff --git a/Brancalonia Official/src/scss/generics/_StandardInput.scss b/Brancalonia Official/src/scss/generics/_StandardInput.scss
new file mode 100644
index 0000000000..414159321f
--- /dev/null
+++ b/Brancalonia Official/src/scss/generics/_StandardInput.scss
@@ -0,0 +1,15 @@
+%StandardInput {
+ width: 100%;
+ padding: 0;
+
+ background: none;
+ box-shadow: none;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ -webkit-border-radius: 0px;
+
+ border: none;
+ border-radius: 0px;
+
+ color: #c00;
+}
diff --git a/Brancalonia Official/src/scss/generics/_gridsystem.scss b/Brancalonia Official/src/scss/generics/_gridsystem.scss
new file mode 100644
index 0000000000..addbcda598
--- /dev/null
+++ b/Brancalonia Official/src/scss/generics/_gridsystem.scss
@@ -0,0 +1,99 @@
+.core-body {
+ display: grid;
+ grid-template-columns: 0.8fr 1fr 1fr;
+ align-items: flex-start;
+ align-items: start;
+ grid-gap: 0.5rem;
+ margin-top: 1rem;
+
+ .core-col {
+ &__split {
+ display: grid;
+ grid-template-columns: 10rem 1fr;
+ grid-gap: 1rem;
+ align-items: flex-start;
+ align-items: start;
+ }
+
+ &--middle {
+ padding-left: 2rem;
+ }
+ }
+}
+
+.bio-body {
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr;
+ align-items: stretch;
+ grid-gap: 1rem 3rem;
+
+ > * {
+ min-height: 20rem;
+ }
+}
+
+.spells {
+ display: grid;
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ grid-template-rows: 10rem 1fr;
+ align-items: stretch;
+ grid-gap: 1rem 3rem;
+
+ @media only screen and (max-width: 600px) {
+ grid-template-columns: 1fr;
+ }
+
+
+ * {
+ margin: 0;
+ }
+
+ > * {
+ max-width: 100%;
+ }
+
+ &__stats {
+ grid-column-end: span 2;
+
+ @media only screen and (max-width: 600px) {
+ grid-column-end: unset;
+ }
+ }
+
+ &__features {
+ grid-row-end: span 2;
+
+ @media only screen and (max-width: 600px) {
+ grid-column-end: unset;
+ }
+ }
+}
+
+.settings-body {
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr;
+ align-items: stretch;
+ grid-gap: 1rem;
+ margin-top: 1rem;
+
+ .options {
+ display: block;
+ padding: 1rem;
+ margin-bottom: 1rem;
+
+ border: 1px solid rgba(red, 0.5);
+ border-radius: 1.5rem;
+
+ &__row {
+
+ &--title {
+ text-align: center;
+ font-weight: bold;
+ }
+ }
+
+ &__flex--1 {
+ text-align: center;
+ }
+ }
+}
diff --git a/Brancalonia Official/src/scss/generics/_hiddenflag.scss b/Brancalonia Official/src/scss/generics/_hiddenflag.scss
new file mode 100644
index 0000000000..85185d7a5f
--- /dev/null
+++ b/Brancalonia Official/src/scss/generics/_hiddenflag.scss
@@ -0,0 +1,21 @@
+.hiddenflag {
+ &__simple {
+ display: none;
+ }
+
+ &__complex {
+ display: block;
+ }
+
+ &__flag {
+ &[value="on"] {
+ ~ .hiddenflag__simple {
+ display: block;
+ }
+
+ ~ .hiddenflag__complex {
+ display: none;
+ }
+ }
+ }
+}
diff --git a/Brancalonia Official/src/scss/generics/_options.scss b/Brancalonia Official/src/scss/generics/_options.scss
new file mode 100644
index 0000000000..316a28b97c
--- /dev/null
+++ b/Brancalonia Official/src/scss/generics/_options.scss
@@ -0,0 +1,197 @@
+.options {
+ display: none;
+ box-sizing: border-box;
+ max-width: 100%;
+ padding: 0 0.5rem;
+
+ border: 0.2rem dashed #c00;
+ border-width: 0.2rem 0;
+
+ font-family: "Verdana", "Tahoma", sans-serif !important;
+ font-size: 0.9rem;
+
+ background: rgba(#c00, 0.1);
+
+ * {
+ font-family: inherit;
+ font-size: inherit;
+ }
+
+ &__flag {
+ &[value="on"] {
+ ~ .options {
+ display: block;
+ }
+ }
+ }
+
+ &__cog {
+ width: 1rem;
+ display: grid;
+ grid-template-areas: "checkmark";
+
+ > * {
+ grid-area: checkmark;
+ width: 100%;
+ height: 100%;
+ }
+
+ span {
+ font-family: pictos;
+ text-align: center;
+ }
+
+ input {
+ opacity: 0;
+
+ &:checked + span {
+ color: #c00;
+ }
+ }
+ }
+
+ &__row {
+ display: flex;
+ flex-wrap: nowrap;
+ align-items: center;
+ justify-content: space-between;
+
+ margin-bottom: 0.25rem;
+ padding-bottom: 0.25rem;
+
+ &--checkbox {
+ display: grid;
+ grid-template-columns: 3rem 1fr;
+ }
+
+ &:not(:last-child) {
+ border-bottom: 1px solid rgba(#c00, 0.5);
+ }
+
+ > * {
+ flex: auto 1 1;
+ }
+
+ &--wrap {
+ flex-wrap: wrap;
+ }
+
+ &--noborder {
+ border-bottom: 0 !important;
+ }
+
+ &--topborder {
+ border-top: 1px solid rgba(#c00, 0.5);
+ border-bottom: 0 !important;
+ }
+
+ &--title {
+ text-align: center;
+ font-weight: bold;
+ }
+
+ &--center {
+ justify-content: center;
+ }
+ }
+
+ &__flex {
+ flex: auto 1 1;
+
+ @for $i from 1 through 10 {
+ &--#{$i} {
+ flex: $i * 10% 0 1 !important;
+ max-width: $i * 10%;
+ }
+ }
+ }
+
+ span,
+ &__label {
+ flex: auto 0 0;
+ max-width: 100%;
+
+ padding: 0;
+ margin: 0;
+ margin-right: 0.25rem;
+
+ line-height: 1rem;
+ text-align: left;
+ }
+
+ select,
+ input[type="checkbox"],
+ input[type="text"],
+ input[type="number"] {
+ + .options__label {
+ margin-left: 0.25rem;
+ }
+ }
+
+ select,
+ input[type="text"],
+ input[type="number"] {
+ margin: 0;
+ margin-right: 0.25rem;
+ padding: 0;
+ height: 2rem;
+ width: 100%;
+
+ border: 1px solid rgba(#c00, 0.25) !important;
+ border-radius: 0.3rem;
+
+ font-size: 1rem !important;
+ font-family: sans-serif;
+ line-height: 1;
+ text-indent: 0;
+ text-align: left;
+
+ color: black;
+
+ background: white;
+ background-image: none !important;
+ }
+
+ input[type="text"] {
+ text-align: left;
+ }
+
+ textarea {
+ margin: 0;
+ padding: 0.25rem;
+ height: 10rem;
+ width: 100%;
+
+ border: 1px solid rgba(#c00, 0.25) !important;
+ border-radius: 0.3rem;
+
+ font-size: 1rem !important;
+ line-height: 2rem;
+ text-indent: 0;
+ text-align: left;
+
+ color: black;
+
+ background: white;
+ background-image: none !important;
+ }
+
+ input[type="text"],
+ input[type="number"] {
+ padding-left: 0.5rem;
+ }
+
+ .pb_custom {
+ display: none;
+ }
+
+ input[name*="pb_type"][value*="custom"] ~ .pb_custom {
+ display: block;
+ }
+
+ .repcontrol {
+ button {
+ font-size: 0;
+ }
+ }
+}
diff --git a/Brancalonia Official/src/scss/npc/_grid.scss b/Brancalonia Official/src/scss/npc/_grid.scss
new file mode 100644
index 0000000000..114b27cc0c
--- /dev/null
+++ b/Brancalonia Official/src/scss/npc/_grid.scss
@@ -0,0 +1,66 @@
+.npc {
+ &__grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ grid-gap: 5rem;
+ }
+
+ &__column {
+
+ }
+
+ &__row {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: baseline;
+
+ > * {
+ display: inline;
+ margin-right: 0.25rem;
+
+ font-family: sans-serif;
+ }
+
+ &--center {
+ justify-content: center;
+ }
+
+ &--space-between {
+ justify-content: space-between;
+ }
+
+ button[type="roll"] {
+ padding: 0;
+ margin: 0;
+ line-height: 1;
+ }
+ }
+
+ &__rule {
+
+ &--thin {
+ margin: 1rem 0;
+ border: 0.5px solid #900;
+ }
+
+ &--thick-top {
+ margin: 1rem 0;
+ border: 0.5px solid #900;
+
+ &:after {
+ display: block;
+ content: "";
+ margin-top: 3px;
+ width: 100%;
+ height: 3px;
+ background-color: #900;
+ }
+ }
+
+ &--thick-bottom {
+ @extend .npc__rule--thick-top;
+ transform: rotate(180deg)
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Brancalonia Official/src/scss/npc/_npc.scss b/Brancalonia Official/src/scss/npc/_npc.scss
new file mode 100644
index 0000000000..128d38594c
--- /dev/null
+++ b/Brancalonia Official/src/scss/npc/_npc.scss
@@ -0,0 +1,174 @@
+input[type="text"],
+input[type="number"],
+select,
+textarea {
+ font-family: sans-serif !important;
+}
+
+button[type="roll"][type="roll"] {
+ border: 0;
+
+ background: none;
+ box-shadow: none;
+
+ * {
+ font-family: sans-serif;
+ }
+
+ &:hover {
+ color: red;
+ }
+}
+
+@import "placeholders";
+
+@import "options";
+@import "grid";
+@import "statblock";
+
+.npc {
+ &__section-header {
+ font-family: "Playfair Display", serif !important;
+ font-size: 9pt;
+ font-weight: 800;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ color: #900;
+ }
+
+ &__toggle {
+ float: right;
+
+ border: 0;
+ background: none;
+ box-shadow: none;
+
+ span {
+ font-family: "Pictos";
+ }
+ }
+
+ &__challenge {
+ &--brackets {
+ @extend %brackets;
+ }
+ }
+}
+
+.toggle {
+ display: grid;
+ grid-template-areas: "checkbox";
+
+ > * {
+ grid-area: checkbox;
+ width: 100%;
+ height: 100%;
+ }
+
+ > input {
+ opacity: 0;
+
+ &:checked + span {
+ color: red;
+ }
+ }
+
+ > span {
+ font-family: "Pictos";
+ }
+}
+
+.action,
+.bonusaction,
+.reaction,
+.legaction,
+.trait {
+ margin-bottom: 0.33rem;
+
+ input.toggle__input[value="on"] {
+ & ~ .toggle__options {
+ display: block;
+ }
+
+ & ~ .toggle__display {
+ display: none;
+ }
+ }
+
+ &__name[type="roll"] {
+ display: inline-block;
+ margin: 0;
+ padding: 0;
+ vertical-align: baseline;
+
+ line-height: inherit;
+ font-weight: bold;
+ font-size: inherit;
+ font-style: italic;
+
+ &:after {
+ display: inline;
+ content: ".";
+ margin-right: 0.5rem;
+ }
+ }
+
+ &__description {
+ font-family: sans-serif;
+ white-space: pre-wrap;
+ }
+}
+
+.repcontrol {
+ .repcontrol_edit,
+ .repcontrol_add {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+}
+
+.flag__display--attack {
+ display: none;
+}
+
+input.flag__toggle--attack[value="on"] {
+ & ~ .flag__display--attack {
+ display: flex;
+ }
+}
+
+input.npc__flag--options[value="on"] {
+ & ~ .npc__options {
+ display: block;
+ }
+}
+
+input.npc__flag--next[value] {
+ & + * {
+ display: flex;
+ }
+}
+
+input.npc__flag--mod:not([value]),
+input.npc__flag--mod[value*="mod"] {
+ & + * {
+ display: none;
+ }
+}
+
+.npc__bonus-actions,
+.npc__reactions {
+ display: none;
+}
+
+input[name*="npcbonusactionsflag"],
+input[name*="npcreactionsflag"] {
+ &[value="1"] + div {
+ display: block;
+ }
+}
+
+input[name*="npc_legendary_actions"][value="0"] + div {
+ display: none;
+}
diff --git a/Brancalonia Official/src/scss/npc/_options.scss b/Brancalonia Official/src/scss/npc/_options.scss
new file mode 100644
index 0000000000..edf76b2600
--- /dev/null
+++ b/Brancalonia Official/src/scss/npc/_options.scss
@@ -0,0 +1,33 @@
+.npc {
+ &__options {
+ max-width: 500px;
+ margin-bottom: 2rem;
+ }
+
+ &__settings {
+ float:right;
+
+ display: grid;
+ grid-template-areas: "checkbox";
+
+ > * {
+ grid-area: checkbox;
+ width: 100%;
+ height: 100%;
+ }
+
+ > input {
+ opacity: 0;
+
+ &:checked ~ span {
+ color: red;
+ }
+ }
+
+ > span {
+ font-family: Pictos;
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/Brancalonia Official/src/scss/npc/_placeholders.scss b/Brancalonia Official/src/scss/npc/_placeholders.scss
new file mode 100644
index 0000000000..008f06131d
--- /dev/null
+++ b/Brancalonia Official/src/scss/npc/_placeholders.scss
@@ -0,0 +1,12 @@
+%brackets {
+ &:before,
+ &:after {
+ display: inline;
+ }
+ &:before {
+ content: "(";
+ }
+ &:after {
+ content: ")";
+ }
+}
\ No newline at end of file
diff --git a/Brancalonia Official/src/scss/npc/_statblock.scss b/Brancalonia Official/src/scss/npc/_statblock.scss
new file mode 100644
index 0000000000..8dcf159a8c
--- /dev/null
+++ b/Brancalonia Official/src/scss/npc/_statblock.scss
@@ -0,0 +1,81 @@
+.npc {
+
+
+
+ &__title {
+ display: block;
+ font-family: "Playfair Display SC", serif !important;
+ font-size: 16pt;
+ text-align: center;
+ color: #900;
+ }
+
+ &__subtitle {
+ display: block;
+ font-family: "Playfair Display", serif;
+ }
+
+ &__attribute-container {
+ margin-right: 1rem;
+ }
+
+ &__attribute-mod {
+ font-weight: bold;
+
+ &:not([value^="-"]):before {
+ display: inline;
+ content: "+";
+ }
+ }
+
+ &__attribute-title {
+ display: block;
+
+ font-weight: bold;
+ text-align: center;
+
+ color: #900;
+ }
+
+ &__attribute-score {
+ margin-right: .25rem;
+ }
+
+ &__label {
+ margin-right: .5rem;
+
+ color: #900;
+
+ font-size: 1.2rem;
+ font-weight: bold;
+ text-transform: uppercase;
+ }
+
+ &__hidden {
+ display: none;
+ }
+
+ &__ac-type {
+ @extend %brackets;
+ }
+
+ &__hitpoints {
+
+ &-formula {
+ @extend %brackets;
+ }
+ }
+
+ &__skill,
+ &__save {
+
+ > span {
+ margin-right: .5rem;
+
+ &:last-child:after {
+ display: inline;
+ content: ","
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Brancalonia Official/src/scss/pc/_AbilityScore.scss b/Brancalonia Official/src/scss/pc/_AbilityScore.scss
new file mode 100644
index 0000000000..733b90b839
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_AbilityScore.scss
@@ -0,0 +1,106 @@
+.abilityscores {
+ display: grid;
+ grid-template-rows: repeat(6, 12rem);
+ padding: 0.25rem;
+ padding-top: 1rem;
+ margin: 0;
+}
+
+.abilityscore {
+ box-sizing: border-box;
+ display: grid;
+ grid-template-rows: 1.25rem 3.75rem 3rem;
+ align-items: center;
+ padding: 1rem 0;
+ margin-top: 1rem;
+
+ text-align: center;
+
+ background: {
+ image: url("https://s3.amazonaws.com/files.d20.io/images/229250145/sGV8WHAseUSfkSS6wyP14w/max.png?1624042176");
+ repeat: no-repeat;
+ size: 100% 100%;
+ position: center top;
+ }
+
+ input[type="text"],
+ input[type="number"] {
+ @extend %StandardInput;
+ }
+
+ &__value {
+ font-family: "Dancing Script", serif;
+ font-size: 2.75rem;
+ font-weight: bold;
+ text-align: center;
+ }
+
+ &__base {
+ opacity: 0;
+
+ &:focus,
+ &:active {
+ opacity: 1;
+
+ & ~ .abilityscore__final {
+ display: none;
+ }
+ }
+ }
+
+ &__base,
+ &__final {
+ font-family: "Dancing Script", serif;
+ text-align: center;
+
+ color: #c00;
+ }
+
+ &__mod {
+ display: grid;
+ grid-template-areas: "mod";
+ margin-top: 1rem;
+
+ text-align: center;
+
+ pointer-events: auto;
+
+ > * {
+ grid-area: mod;
+ font-size: 2rem;
+ width: 100%;
+ height: 100%;
+ }
+
+ &:hover {
+ .abilityscore__final {
+ display: none;
+ }
+
+ .abilityscore__base {
+ opacity: 1;
+ pointer-events: auto;
+ }
+ }
+ }
+
+ &__flag {
+ &[value="1"] + .abilityscore__final {
+ color: #3e99e8;
+
+ &:after {
+ content: "*";
+ font-size: 15px;
+ }
+ }
+ }
+
+ &__rollbutton[type="roll"] {
+ @extend %RollButton;
+ padding: 0;
+ margin: 0;
+ margin-top: 1rem;
+
+ font-size: 0.75rem;
+ }
+}
diff --git a/Brancalonia Official/src/scss/pc/_AttacksSpellcasting.scss b/Brancalonia Official/src/scss/pc/_AttacksSpellcasting.scss
new file mode 100644
index 0000000000..bd5e1a6d1a
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_AttacksSpellcasting.scss
@@ -0,0 +1,95 @@
+.attacks {
+ @extend %TextBox;
+ margin: 0 0.5rem;
+
+ &__header {
+ @extend %TextBox;
+ display: grid;
+ grid-template-columns: 1fr 0.5fr 1fr 1.25rem;
+ grid-gap: 0.25rem;
+ padding: 0 0.5rem;
+ margin: 0.5rem -1rem;
+
+ text-align: center;
+ }
+
+ textarea {
+ width: auto;
+ }
+
+ &__label {
+ @extend %MagicLabel;
+ height: 4rem;
+ margin-bottom: -1.5rem;
+
+ background-size: 90% 100%;
+
+ text-align: center;
+ }
+}
+
+.attack {
+ width: 100%;
+ margin: 0.5rem 0;
+
+ &__display {
+ display: grid;
+ grid-template-columns: 1fr 1.5rem;
+ grid-gap: 0.25rem;
+ align-items: center;
+ margin: 0.5rem;
+
+ button[type="roll"] {
+ @extend %RollButton;
+
+ display: grid;
+ grid-template-columns: 1fr 3rem 0.7fr;
+ grid-gap: 0.25rem;
+ align-items: center;
+ }
+ }
+
+ &__name,
+ &__type,
+ &__bonus {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ height: 2.5rem;
+ overflow: hidden;
+ text-overflow: ellipsis;
+
+ border: {
+ width: 0 0 0.5rem 0;
+ style: solid;
+ color: transparent;
+ image-slice: 15% 5% 10% 5%;
+ image-width: 0rem 0rem 0.75rem 0rem;
+ image-outset: 0px 0px 0px 0px;
+ image-source: url("https://s3.amazonaws.com/files.d20.io/images/229248387/s-7U3vgLH9-s9S_jTdpHBw/max.png?1624041526");
+ image-repeat: repeat;
+ }
+
+ font-size: 1.3rem;
+ font-weight: normal;
+ line-height: 1;
+ }
+
+ &__name {
+ text-align: left;
+ }
+
+ &__type,
+ &__bonus {
+ text-align: center;
+ }
+
+ &__type {
+ font-size: 1.2em;
+ }
+
+ &__value[type="text"] {
+ text-align: center;
+ }
+}
diff --git a/Brancalonia Official/src/scss/pc/_Bio.scss b/Brancalonia Official/src/scss/pc/_Bio.scss
new file mode 100644
index 0000000000..fb5001754a
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_Bio.scss
@@ -0,0 +1,78 @@
+.appearance,
+.backstory,
+.allies,
+.adfeatures,
+.personalitytrait,
+.treasure {
+ @extend %TextBox;
+ display: grid;
+ grid-template-columns: 1fr;
+ grid-template-rows: 3.5rem 1fr;
+ justify-content: center;
+ align-items: stretch;
+ padding: 1rem;
+
+ &__label {
+ @extend %BoxLabel;
+ }
+
+ textarea {
+ width: 100%;
+ min-height: 5rem;
+ height: auto;
+ margin: 0;
+ padding: 0;
+ resize: vertical;
+ border: 0;
+ }
+
+ input[type="text"] {
+ padding: 0;
+
+ border: 0;
+ border-bottom: 1px solid black;
+ border-radius: 0;
+ }
+}
+
+.bounty {
+ @extend %TextBox;
+ display: grid;
+ min-height: 15rem;
+ grid-template-columns: 1fr;
+ grid-template-rows: 1fr 1rem;
+ justify-content: center;
+ align-items: stretch;
+ padding: 1rem;
+
+ &__image {
+ display: block;
+ min-height: 3.5rem;
+ }
+
+ &__bounty {
+ @extend %TextBox;
+ display: grid;
+ grid-template-columns: 1fr 7rem;
+ grid-gap: 1rem;
+ align-items: center;
+ height: 3rem;
+ margin: 0 -2rem;
+ padding: 0 1rem;
+
+ background-color: white;
+
+ input[type="number"] {
+ margin-top: -1rem;
+ margin-bottom: -1rem;
+ border: 0;
+ padding: 0;
+ width: 100%;
+ height: 4rem;
+ background-image: url("https://s3.amazonaws.com/files.d20.io/images/229570955/6sQSflLpvCODi8jUmDLwkg/med.png?1624162114");
+ background-size: 100% 100%;
+ background-color: transparent;
+ text-align: center;
+ }
+ }
+}
diff --git a/Brancalonia Official/src/scss/pc/_Coins.scss b/Brancalonia Official/src/scss/pc/_Coins.scss
new file mode 100644
index 0000000000..ce56191729
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_Coins.scss
@@ -0,0 +1,39 @@
+.coins {
+ width: 100%;
+ height: 15rem;
+ margin-top: -2rem;
+ padding: 18% 7% 0 43%;
+ grid-column: span 2;
+
+ background: {
+ image: url("https://res.cloudinary.com/dmrhbjudf/image/upload/v1626578001/Pouch-Money_pagkje.png");
+ size: contain;
+ position: center;
+ repeat: no-repeat;
+ }
+}
+
+.money {
+ grid-column: 1 / -1;
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ grid-gap: 0.5rem;
+ align-items: center;
+ justify-items: center;
+
+ > * {
+ text-align: center;
+ }
+
+ input[type="number"] {
+ width: 100%;
+ border: 0;
+ background: transparent;
+
+ text-align: center;
+ }
+}
+
+.coin {
+ color: black !important;
+}
diff --git a/Brancalonia Official/src/scss/pc/_DeathSaves.scss b/Brancalonia Official/src/scss/pc/_DeathSaves.scss
new file mode 100644
index 0000000000..75599fb3f5
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_DeathSaves.scss
@@ -0,0 +1,87 @@
+.deathsaves {
+ margin: 2rem 0;
+
+ &__label {
+ @extend %MagicLabel;
+ margin: auto;
+ margin-bottom: 1rem;
+ height: 4rem;
+ width: 80%;
+
+ button[type="roll"] {
+ @extend %RollButton;
+
+ font-size: 1.2rem;
+ }
+ }
+
+ &__failures,
+ &__successes {
+ width: 80%;
+ margin: auto;
+ display: grid;
+ grid-template-columns: 1fr 5rem 5rem 5rem;
+ align-items: center;
+ height: 3rem;
+
+ input[type="checkbox"] {
+ &:checked ~ span {
+ background: {
+ image: url("");
+ }
+ }
+ }
+ }
+
+ &__failures {
+ .deathsaves__check {
+ span {
+ background: {
+ image: url("https://res.cloudinary.com/dmrhbjudf/image/upload/v1626577399/ds-fail-white_e65mmc.png");
+ size: contain;
+ position: center;
+ repeat: no-repeat;
+ }
+ }
+
+ input[type="checkbox"]:checked + span {
+ background-image: url("https://res.cloudinary.com/dmrhbjudf/image/upload/v1626577399/ds-fail-red_qydhmr.png");
+ }
+ }
+ }
+
+ &__successes {
+ .deathsaves__check {
+ span {
+ background: {
+ image: url("https://res.cloudinary.com/dmrhbjudf/image/upload/v1626577399/ds-succeed-white_l9svuh.png");
+ size: contain;
+ position: center;
+ repeat: no-repeat;
+ }
+ }
+
+ input[type="checkbox"]:checked + span {
+ background-image: url("https://res.cloudinary.com/dmrhbjudf/image/upload/v1626577399/ds-succeed-red_rogomh.png");
+ }
+ }
+ }
+
+ &__check {
+ display: grid;
+ grid-template-areas: "check";
+ height: 3rem;
+
+ > * {
+ grid-area: check;
+ height: 100%;
+ width: 100%;
+ }
+
+ input[type="checkbox"] {
+ opacity: 0;
+ position: relative;
+ z-index: 1000;
+ }
+ }
+}
diff --git a/Brancalonia Official/src/scss/pc/_Equipment.scss b/Brancalonia Official/src/scss/pc/_Equipment.scss
new file mode 100644
index 0000000000..4925413df5
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_Equipment.scss
@@ -0,0 +1,128 @@
+.equipment {
+ @extend %TextBox;
+ margin: 0 0.5rem;
+ margin-bottom: 2rem;
+
+ &__header {
+ @extend %TextBox;
+ display: grid;
+ grid-template-columns: 1.5rem 3rem 1fr 3rem 1.5rem;
+ grid-gap: 0.25rem;
+ align-items: center;
+ padding: 0 0.5rem;
+ margin: 0.5rem -1rem;
+ }
+
+ &__count {
+ grid-column: 2;
+ }
+
+ &__title {
+ }
+
+ &__weighti {
+ width: 1.5rem;
+ height: 1.5rem;
+ vertical-align: top;
+ justify-self: center;
+
+ img {
+ vertical-align: top;
+ }
+ }
+
+ &__weighttotal {
+ display: grid;
+ grid-template-columns: 1fr 3rem;
+ align-items: center;
+ padding: 0 4rem;
+
+ font-weight: bold;
+ }
+
+ &__encumbrance[type="number"] {
+ width: 3rem;
+ height: 3rem;
+ margin: 0.5rem 0;
+
+ border-radius: 50%;
+ border: 1px solid black;
+
+ text-align: center;
+ }
+
+ &__encumbrancetotal {
+ font-weight: bold;
+ }
+
+ &__label {
+ @extend %MagicLabel;
+ height: 4rem;
+ margin-bottom: -1.5rem;
+
+ background-size: 90% 100%;
+
+ text-align: center;
+ }
+}
+
+.item {
+ input.item__optionsflag[value="on"] {
+ ~ .options {
+ display: block;
+ }
+ }
+
+ input[type="text"] {
+ text-align: center;
+ }
+
+ input[type="text"],
+ input[type="number"] {
+ width: 100%;
+ height: 16pt;
+
+ border: {
+ width: 0 0 0.5rem 0;
+ style: solid;
+ color: transparent;
+ image-slice: 15% 5% 10% 5%;
+ image-width: 0rem 0rem 0.75rem 0rem;
+ image-outset: 0px 0px 0px 0px;
+ image-source: url("https://s3.amazonaws.com/files.d20.io/images/229248387/s-7U3vgLH9-s9S_jTdpHBw/max.png?1624041526");
+ image-repeat: repeat;
+ }
+
+ font-size: 12pt;
+ line-height: 1;
+ }
+
+ &__titlerow {
+ display: grid;
+ grid-template-columns: 1.5rem 3rem 1fr 3rem 1.5rem;
+ grid-gap: 0.5rem;
+ }
+
+ &__optionsflag {
+ display: grid;
+ grid-template-areas: "check";
+
+ > * {
+ grid-area: check;
+ width: 100%;
+ height: 100%;
+ }
+ }
+
+ &__optionscheck {
+ position: relative;
+ z-index: 1000;
+ opacity: 0;
+
+ &:checked {
+ ~ span.pictos {
+ color: #c00;
+ }
+ }
+ }
+}
diff --git a/Brancalonia Official/src/scss/pc/_Exhaustion.scss b/Brancalonia Official/src/scss/pc/_Exhaustion.scss
new file mode 100644
index 0000000000..7ea29518ff
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_Exhaustion.scss
@@ -0,0 +1,77 @@
+.exhaustions {
+ grid-template-columns: 2rem 1fr;
+}
+
+.knocks {
+ grid-template-columns: 1fr 2rem;
+}
+
+.exhaustions,
+.knocks {
+ display: grid;
+ align-items: center;
+
+ &__level {
+ display: none;
+ }
+
+ > input[type="hidden"] {
+ @for $i from 0 through 6 {
+ &[value="#{$i}"] ~ * {
+ .knocks__level--#{$i},
+ .exhaustions__level--#{$i} {
+ display: block;
+ margin: auto;
+ height: 100%;
+ max-height: 14rem;
+ width: auto;
+ }
+ }
+ }
+ }
+
+ &__checks {
+ display: grid;
+ grid-template-rows: repeat(6, 1fr) 2rem;
+ }
+
+ &__label {
+ grid-column: 1 / -1;
+
+ font-size: 12pt;
+ text-align: center;
+ }
+}
+
+.exhaustion,
+.knock {
+ display: grid;
+ grid-template-areas: "checkbox";
+
+ &__radio {
+ grid-area: checkbox;
+ width: 100%;
+ height: 100%;
+ opacity: 0;
+
+ &:checked {
+ opacity: 1;
+
+ + span {
+ background-color: black;
+ color: white;
+ font-weight: bold;
+ }
+ }
+ }
+
+ &__text {
+ display: block;
+ grid-area: checkbox;
+ width: 100%;
+ height: 100%;
+ text-align: center;
+ font-size: 1rem;
+ font-family: "Libre Baskerville", sans-serif;
+ }
+}
diff --git a/Brancalonia Official/src/scss/pc/_Features.scss b/Brancalonia Official/src/scss/pc/_Features.scss
new file mode 100644
index 0000000000..a87b95a093
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_Features.scss
@@ -0,0 +1,101 @@
+.features {
+ @extend %TextBox;
+ padding: 1rem 0.5rem;
+
+ &__label {
+ @extend %BoxLabel;
+ margin-bottom: 1rem;
+ }
+}
+
+.feature {
+ $this: ".feature";
+
+ display: grid;
+ grid-template-columns: 1fr 1.5rem 1.5rem;
+ grid-gap: 0.5rem;
+ align-items: start;
+
+ margin: 0 0.25rem;
+ padding: 0 0.25rem;
+
+ border: {
+ width: 0 0 0.5rem 0;
+ style: solid;
+ color: transparent;
+ image-slice: 15% 5% 10% 5%;
+ image-width: 0rem 0rem 0.75rem 0rem;
+ image-outset: 0px 0px 0px 0px;
+ image-source: url("https://s3.amazonaws.com/files.d20.io/images/229248387/s-7U3vgLH9-s9S_jTdpHBw/max.png?1624041526");
+ image-repeat: repeat;
+ }
+
+ &__title,
+ &__subheader {
+ display: block;
+
+ text-align: left;
+ }
+
+ &__subheader {
+ color: #666;
+
+ > * {
+ font-size: 8pt;
+ }
+ }
+
+ &__options {
+ grid-column: 1 / -1;
+ }
+
+ &__chat-button[type="roll"] {
+ padding: 0;
+ margin: 0;
+
+ border: 0;
+ box-shadow: none;
+
+ background: transparent;
+
+ font-family: Pictos;
+ font-size: 12pt;
+ text-align: center;
+ }
+
+ &__options-container {
+ display: grid;
+ grid-template-areas: "checkbox";
+ align-items: center;
+
+ > * {
+ grid-area: checkbox;
+ width: 100%;
+ height: 100%;
+ }
+
+ input[class*="flag"][type="checkbox"] {
+ opacity: 0;
+ width: 100%;
+ height: 100%;
+
+ &:checked ~ span {
+ color: red;
+ }
+ }
+
+ span {
+ font-family: Pictos;
+ font-size: 12pt;
+ text-align: center;
+ }
+ }
+
+ // Display Controls
+
+ input#{$this}__flag--options {
+ &[value="on"] ~ #{$this}__options {
+ display: block !important;
+ }
+ }
+}
diff --git a/Brancalonia Official/src/scss/pc/_Header.scss b/Brancalonia Official/src/scss/pc/_Header.scss
new file mode 100644
index 0000000000..0de16e1f2e
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_Header.scss
@@ -0,0 +1,153 @@
+.header {
+ @extend %TextBox;
+ display: grid;
+ grid-template-columns: 0.5fr 1fr 2fr 1fr 0.5fr;
+ grid-gap: 1rem;
+ width: 100%;
+ padding: 0 1rem;
+ margin-bottom: 0.5rem;
+
+ .logo {
+ height: 14rem;
+ margin-top: -7.5rem;
+ margin-bottom: -2rem;
+ background: {
+ image: url("https://res.cloudinary.com/dmrhbjudf/image/upload/v1626655012/logo2_aaue57.png");
+ position: center;
+ repeat: no-repeat;
+ size: contain;
+ }
+ }
+
+ .classlevel,
+ .race,
+ .background {
+ grid-column: span 2;
+ }
+
+ .initspeed {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ grid-gap: 0.5rem;
+ }
+
+ .classlevel {
+ display: grid;
+ grid-template-columns: 1fr 4rem;
+ grid-gap: 0.5rem;
+ }
+
+ .alignment,
+ .initiative,
+ .speed,
+ .class,
+ .level,
+ .ac,
+ .playername,
+ .background,
+ .name,
+ .race {
+ display: grid;
+ grid-template-rows: 1fr 1.5rem;
+
+ &__label {
+ font-size: 1.2rem;
+ font-weight: bold;
+ text-align: center;
+ }
+
+ button[type="roll"],
+ input[type="number"],
+ input[type="text"] {
+ width: 100%;
+ margin: 0;
+ padding: 0;
+
+ border: 0;
+ border-radius: 0;
+
+ text-align: center;
+
+ background: none;
+ box-shadow: none;
+ text-shadow: none;
+ }
+
+ input[type="number"],
+ input[type="text"] {
+ border: {
+ width: 0 0 0.5rem 0;
+ style: solid;
+ color: transparent;
+ image-slice: 15% 5% 10% 5%;
+ image-width: 0rem 0rem 0.75rem 0rem;
+ image-outset: 0px 0px 0px 0px;
+ image-source: url("https://s3.amazonaws.com/files.d20.io/images/229248387/s-7U3vgLH9-s9S_jTdpHBw/max.png?1624041526");
+ image-repeat: repeat;
+ }
+
+ font-size: 1.45rem;
+ text-align: center;
+ }
+
+ &__value,
+ button[type="roll"] {
+ padding: 0;
+ margin: 0;
+
+ line-height: 1.4;
+ }
+ }
+
+ .initiative__value {
+ border: {
+ width: 0 0 0.5rem 0;
+ style: solid;
+ color: transparent;
+ image-slice: 10% 5% 10% 5%;
+ image-width: 0rem 0rem 0.75rem 0rem;
+ image-outset: 0px 0px 0px 0px;
+ image-source: url("https://s3.amazonaws.com/files.d20.io/images/229248387/s-7U3vgLH9-s9S_jTdpHBw/max.png?1624041526");
+ }
+
+ color: #c00;
+
+ font-size: 1.45rem;
+ text-align: center;
+ }
+
+ .name {
+ position: relative;
+ margin-top: 0rem;
+ z-index: 10;
+ grid-template-rows: 3rem 1.5rem;
+ padding-top: 0.5rem;
+
+ &:before {
+ @extend %MagicLabel;
+ position: absolute;
+ display: block;
+ content: "";
+ top: 0;
+ bottom: 0;
+ right: -2rem;
+ left: -2rem;
+ z-index: -1;
+ height: 6rem;
+ margin-top: 0;
+
+ background-image: url("https://s3.amazonaws.com/files.d20.io/images/229580853/RzAvglXLNQ9vfDdM0qm-nA/med.png?1624168102");
+ }
+
+ input[type="text"] {
+ width: 80%;
+ margin: auto;
+ height: auto;
+
+ font-size: 1.5rem;
+ font-weight: bold;
+
+ border-image: none;
+ }
+ }
+}
diff --git a/Brancalonia Official/src/scss/pc/_InsProf.scss b/Brancalonia Official/src/scss/pc/_InsProf.scss
new file mode 100644
index 0000000000..011bea8fb0
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_InsProf.scss
@@ -0,0 +1,77 @@
+.inspprof {
+ @extend %TextBox;
+ display: grid;
+ grid-template-columns: 7rem 1fr;
+ align-items: center;
+ margin: 1rem 0;
+
+ &:after {
+ width: 100%;
+ height: 100%;
+ }
+
+ &__value {
+ display: grid;
+ grid-template-areas: "checkbox";
+ align-items: center;
+ margin-top: -1rem;
+ margin-bottom: -1rem;
+ margin-left: 1rem;
+ height: 4rem;
+
+ background: {
+ image: url("https://s3.amazonaws.com/files.d20.io/images/229570955/6sQSflLpvCODi8jUmDLwkg/med.png?1624162114");
+ size: 100% 100%;
+ }
+
+ font-family: "Dancing Script", serif;
+ font-size: 4rem;
+ font-weight: bold;
+ text-align: center;
+
+ > * {
+ grid-area: checkbox;
+ height: 100%;
+ width: 100%;
+
+ font-family: "Dancing Script", serif;
+ font-size: 3rem;
+ }
+
+ input[type="checkbox"] {
+ opacity: 0;
+ height: 100%;
+
+ &:checked ~ span {
+ align-self: center;
+ justify-self: center;
+ height: 130%;
+ background: {
+ image: url("https://res.cloudinary.com/dmrhbjudf/image/upload/v1626670086/inspiration-3_qfwtry.png");
+ position: center center;
+ size: contain;
+ repeat: no-repeat;
+ }
+ }
+ }
+ }
+
+ &__label {
+ font-size: 0.9rem;
+ text-align: center;
+ }
+
+ &__button[type="roll"] {
+ width: 100%;
+
+ border: 0;
+
+ background: transparent;
+
+ font-size: 1.65rem;
+
+ &:hover {
+ color: #c00;
+ }
+ }
+}
diff --git a/Brancalonia Official/src/scss/pc/_Moves.scss b/Brancalonia Official/src/scss/pc/_Moves.scss
new file mode 100644
index 0000000000..eec1923522
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_Moves.scss
@@ -0,0 +1,158 @@
+.moves {
+ @extend %TextBox;
+ margin-top: 1rem;
+ padding: 0;
+
+ &__label {
+ @extend %BoxLabel;
+ margin-bottom: 1rem;
+ }
+}
+
+.move-label {
+ @extend %BoxLabel;
+ display: grid;
+ grid-template-columns: 1fr 5rem 5rem;
+ align-items: center;
+ margin: 1rem 0.5rem;
+ height: auto;
+
+ font-size: 1.25rem;
+ font-weight: bold;
+
+ &__numeral {
+ display: grid;
+ grid-template-columns: 1fr min-content min-content;
+
+ button[type="action"] {
+ border: none;
+ background: none;
+ }
+ }
+
+ &__label {
+ font-size: 2rem;
+ text-transform: uppercase;
+ }
+
+ &__total span {
+ font-family: "Dancing Script", serif;
+ }
+
+ &__title {
+ font-family: "Quintessential", "Baskerville", serif;
+ font-size: 6pt;
+ text-transform: uppercase;
+
+ color: #666;
+ }
+
+ input[type="number"] {
+ @extend %StandardInput;
+ width: 100%;
+ height: auto;
+ border: 0;
+
+ background-color: transparent;
+
+ font-weight: bold;
+ text-align: center;
+
+ -moz-appearance: textfield;
+ &::-webkit-outer-spin-button,
+ &::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ }
+ }
+}
+
+.move {
+ $this: ".move";
+
+ display: grid;
+ grid-template-columns: 1fr 1.5rem 1.5rem;
+ grid-gap: 0.5rem;
+
+ margin: 0 0.25rem;
+ padding: 0 0.25rem;
+
+ border: {
+ width: 0 0 0.5rem 0;
+ style: solid;
+ color: transparent;
+ image-slice: 15% 5% 10% 5%;
+ image-width: 0rem 0rem 0.75rem 0rem;
+ image-outset: 0px 0px 0px 0px;
+ image-source: url("https://s3.amazonaws.com/files.d20.io/images/229248387/s-7U3vgLH9-s9S_jTdpHBw/max.png?1624041526");
+ image-repeat: repeat;
+ }
+
+ &__title,
+ &__subheader {
+ display: block;
+
+ text-align: left;
+ }
+
+ &__subheader {
+ color: #666;
+
+ > * {
+ font-size: 8pt;
+ }
+ }
+
+ &__options {
+ grid-column: 1 / -1;
+ }
+
+ &__chat-button[type="roll"] {
+ padding: 0;
+ margin: 0;
+
+ border: 0;
+ box-shadow: none;
+
+ background: transparent;
+
+ font-family: Pictos;
+ font-size: 12pt;
+ text-align: center;
+ }
+
+ &__options-container {
+ display: grid;
+ grid-template-areas: "checkbox";
+ align-items: center;
+
+ > * {
+ grid-area: checkbox;
+ width: 100%;
+ height: 100%;
+ }
+
+ input[class*="flag"][type="checkbox"] {
+ opacity: 0;
+ width: 100%;
+ height: 100%;
+
+ &:checked ~ span {
+ color: red;
+ }
+ }
+
+ span {
+ font-family: Pictos;
+ font-size: 12pt;
+ text-align: center;
+ }
+ }
+
+ // Display Controls
+
+ input#{$this}__flag--options {
+ &[value="on"] ~ #{$this}__options {
+ display: block !important;
+ }
+ }
+}
diff --git a/Brancalonia Official/src/scss/pc/_Navigation.scss b/Brancalonia Official/src/scss/pc/_Navigation.scss
new file mode 100644
index 0000000000..85c715722b
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_Navigation.scss
@@ -0,0 +1,79 @@
+.navigation {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ margin-top: 1rem;
+
+ &__pages {
+ justify-self: end;
+ display: grid;
+ grid-template-columns: auto auto auto 2rem;
+ justify-content: end;
+ }
+
+ &__toggles {
+ grid-column: 1;
+ justify-self: left start;
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr;
+ }
+
+ &__toggle {
+ display: grid;
+ grid-template-columns: 1fr;
+ grid-template-areas: "checkbox";
+ margin-right: 1rem;
+
+ > * {
+ grid-area: checkbox;
+ width: 100%;
+ height: 100%;
+ }
+
+ &--settings {
+ font-family: Pictos;
+ }
+
+ &--whisperleft {
+ border-left: 1px solid black;
+ padding-left: 1rem;
+ }
+
+ input[type="radio"] {
+ opacity: 0;
+
+ &:checked + span {
+ border: 1px solid #c00;
+ background-color: #c00;
+ color: white;
+ }
+ }
+
+ span.pictos,
+ span[data-i18n] {
+ display: block;
+ padding: 0.1rem 0.2rem;
+
+ border: 1px solid black;
+ border-radius: 0.3rem;
+
+ font-size: 1.2rem;
+ font-weight: bold;
+ text-align: center;
+ }
+ }
+}
+
+.deathsaves {
+ grid-column: 1 / -1;
+}
+
+.navigation__toggle-group {
+ display: none;
+}
+
+.toggleflag[value="@{advantagetoggle}"] {
+ + .navigation__toggle-group {
+ display: flex;
+ align-items: space-between;
+ }
+}
diff --git a/Brancalonia Official/src/scss/pc/_OtherProficiencies.scss b/Brancalonia Official/src/scss/pc/_OtherProficiencies.scss
new file mode 100644
index 0000000000..c1e8679f45
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_OtherProficiencies.scss
@@ -0,0 +1,79 @@
+.otherprofs {
+ width: auto;
+ margin-top: 0.5rem;
+
+ border: {
+ width: 0.5rem;
+ style: solid;
+ color: transparent;
+ image-source: url("#{$externalImgsPath}5eBorder.svg#{$imgParameters}");
+ image-slice: 4% 8% 12% 8%;
+ image-width: 1.5rem 2rem 3rem 2rem;
+ image-repeat: stretch;
+ }
+
+ &__header {
+ display: grid;
+ grid-template-columns: 0.8fr 1fr 1.25rem;
+ grid-gap: 0.25rem;
+ margin: 0.5rem;
+
+ text-align: center;
+
+ color: #666;
+ }
+
+ &__label {
+ font-size: 1rem;
+ font-weight: bold;
+ text-align: center;
+ }
+
+ textarea {
+ width: auto;
+ }
+}
+
+.otherprof {
+ width: 100%;
+ margin: 0.5rem 0;
+
+ &__display {
+ display: grid;
+ grid-template-columns: 1fr 1.5rem;
+ grid-gap: 0.25rem;
+ align-items: center;
+ margin: 0.5rem;
+
+ button[type="roll"] {
+ @extend %RollButton;
+
+ display: grid;
+ grid-template-columns: 0.8fr 1fr;
+ grid-gap: 0.25rem;
+ align-items: center;
+ }
+ }
+
+ &__name,
+ &__type {
+ box-sizing: border-box;
+ margin: 0 0.25rem;
+ padding: 0.5rem;
+ width: 100%;
+ height: 2rem;
+
+ border-radius: 5px 0 5px 0;
+ border: 0;
+
+ font-size: 1rem;
+ font-weight: bold;
+ text-align: left;
+
+ background-color: #efefef;
+ }
+
+ &__value[type="text"] {
+ text-align: center;
+ }
+}
diff --git a/Brancalonia Official/src/scss/pc/_SavingThrows.scss b/Brancalonia Official/src/scss/pc/_SavingThrows.scss
new file mode 100644
index 0000000000..e9bdebe9a6
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_SavingThrows.scss
@@ -0,0 +1,68 @@
+.savingthrows {
+ @extend %TextBox;
+ display: grid;
+ grid-gap: 0.25rem;
+ padding: 1rem;
+ margin-bottom: 1rem;
+}
+
+.savingthrow {
+ display: grid;
+ grid-template-columns: 1rem 2rem 1fr;
+ grid-gap: 0.5rem;
+ width: auto;
+
+ &__button[type="roll"] {
+ @extend %RollButton;
+
+ font-size: 1.2rem;
+ font-weight: normal;
+ text-align: left;
+ }
+
+ &__value {
+ text-align: center;
+ }
+
+ &__checkbox {
+ display: grid;
+ grid-template-areas: "checkbox";
+ align-items: center;
+
+ > * {
+ grid-area: checkbox;
+ width: 100%;
+ height: 100%;
+ }
+
+ input[type="checkbox"] {
+ opacity: 0;
+
+ &:checked ~ span {
+ &:before {
+ background-color: #c00;
+ }
+ }
+ }
+
+ span {
+ &:before {
+ display: block;
+ content: " ";
+ width: 1rem;
+ height: 1rem;
+
+ border: 1px solid black;
+ border-radius: 50%;
+
+ font-family: Pictos;
+ font-size: 1rem;
+ line-height: 1rem;
+ }
+ }
+ }
+}
+
+.toggle:not([value="1"]) + [class*="toggleVisibilityBy"] {
+ display: none;
+}
diff --git a/Brancalonia Official/src/scss/pc/_Shields.scss b/Brancalonia Official/src/scss/pc/_Shields.scss
new file mode 100644
index 0000000000..8e58ed454c
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_Shields.scss
@@ -0,0 +1,44 @@
+.shields {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ grid-gap: 4rem;
+ padding: 30% 10% 20% 10%;
+ height: 18rem;
+
+ background: {
+ image: url("https://res.cloudinary.com/dmrhbjudf/image/upload/v1626658997/shields_m7snh3.png");
+ position: center;
+ repeat: no-repeat;
+ size: contain;
+ }
+
+ .speed,
+ .ac {
+ input[type="number"] {
+ width: 100%;
+ padding: 0;
+ margin: 0;
+
+ border: {
+ width: 0 0 0.5rem 0;
+ style: solid;
+ color: transparent;
+ image-slice: 15% 5% 10% 5%;
+ image-width: 0rem 0rem 0.75rem 0rem;
+ image-outset: 0px 0px 0px 0px;
+ image-source: url("https://s3.amazonaws.com/files.d20.io/images/229248387/s-7U3vgLH9-s9S_jTdpHBw/max.png?1624041526");
+ image-repeat: repeat;
+ }
+
+ background: transparent;
+
+ font-size: 3rem;
+ text-align: center;
+ }
+
+ &__label {
+ text-align: center;
+ font-size: 1.65rem;
+ }
+ }
+}
diff --git a/Brancalonia Official/src/scss/pc/_Skills.scss b/Brancalonia Official/src/scss/pc/_Skills.scss
new file mode 100644
index 0000000000..351e0648e2
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_Skills.scss
@@ -0,0 +1,63 @@
+.skills {
+ @extend %TextBox;
+ display: grid;
+ grid-gap: 0.25rem;
+ padding: 1rem;
+}
+
+.skill {
+ display: grid;
+ grid-template-columns: 1rem 2rem 1fr;
+ grid-gap: 0.5rem;
+ width: auto;
+
+ &__button[type="roll"] {
+ @extend %RollButton;
+
+ font-size: 1.2rem;
+ font-weight: normal;
+ text-align: left;
+ }
+
+ &__value {
+ text-align: center;
+ }
+
+ &__checkbox {
+ display: grid;
+ grid-template-areas: "checkbox";
+ align-items: center;
+
+ > * {
+ grid-area: checkbox;
+ width: 100%;
+ height: 100%;
+ }
+
+ input[type="checkbox"] {
+ opacity: 0;
+
+ &:checked ~ span {
+ &:before {
+ background-color: #c00;
+ }
+ }
+ }
+
+ span {
+ &:before {
+ display: block;
+ content: " ";
+ width: 1rem;
+ height: 1rem;
+
+ border: 1px solid black;
+ border-radius: 50%;
+
+ font-family: Pictos;
+ font-size: 1rem;
+ line-height: 1rem;
+ }
+ }
+ }
+}
diff --git a/Brancalonia Official/src/scss/pc/_SpellStats.scss b/Brancalonia Official/src/scss/pc/_SpellStats.scss
new file mode 100644
index 0000000000..2f2ca8c653
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_SpellStats.scss
@@ -0,0 +1,54 @@
+.spellstats {
+ @extend %TextBox;
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+ padding: 1rem;
+ height: 100%;
+
+ &__ability select {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+
+ max-width: 10.5rem;
+ height: 4rem;
+ margin: 0;
+ padding: 0;
+
+ border: none;
+
+ background: {
+ image: url("https://s3.amazonaws.com/files.d20.io/images/229570955/6sQSflLpvCODi8jUmDLwkg/med.png?1624162114");
+ size: 100% 100%;
+ }
+
+ text-align: center;
+ font-size: 1.6rem;
+
+ }
+
+ &__display {
+ display: block;
+ margin: auto;
+ max-width: 7.5rem;
+ height: 4rem;
+
+ background: {
+ image: url("https://s3.amazonaws.com/files.d20.io/images/229570955/6sQSflLpvCODi8jUmDLwkg/med.png?1624162114");
+ size: 100% 100%;
+ }
+
+ font-family: "Dancing Script", serif;
+ font-size: 2.45rem;
+ line-height: 4rem;
+ text-align: center;
+
+ color: #c00;
+ }
+
+ &__label {
+ display: block;
+
+ font-weight: bold;
+ }
+}
\ No newline at end of file
diff --git a/Brancalonia Official/src/scss/pc/_Spells.scss b/Brancalonia Official/src/scss/pc/_Spells.scss
new file mode 100644
index 0000000000..b21a31ac87
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_Spells.scss
@@ -0,0 +1,274 @@
+.spells {
+ margin-top: 1rem;
+
+ &__cantrips,
+ &__section {
+ margin: 0;
+ }
+
+ &__stats {
+ }
+
+ &__section {
+ display: grid;
+ grid-gap: 1rem;
+ }
+
+ &__container {
+ @extend %TextBox;
+ min-height: 100%;
+ }
+}
+
+.spell-label {
+ @extend %BoxLabel;
+ display: grid;
+ grid-template-columns: 1fr 5rem 5rem;
+ align-items: center;
+ margin: 1rem .5rem;
+ height: auto;
+
+ border-image: {
+ width: 0.5rem 3rem 2rem 2.5em;
+ outset: 0.5rem 2.50rem 2rem 3rem;
+ }
+
+ font-size: 1.25rem;
+ font-weight: bold;
+
+ &__numeral {
+ display: grid;
+ grid-template-columns: 1fr min-content min-content;
+
+ button[type="action"] {
+ border: none;
+ background: none;
+ }
+ }
+
+ &--0 {
+ grid-template-columns: 1fr;
+ }
+
+ &__label {
+ font-size: 2rem;
+ text-transform: uppercase;
+ }
+
+ &__total span {
+ font-family: "Dancing Script", serif;
+ }
+
+ &__title {
+ font-family: "Quintessential", "Baskerville", serif;
+ font-size: 6pt;
+ text-transform: uppercase;
+
+ color: #666;
+ }
+
+ input[type="number"] {
+ @extend %StandardInput;
+ width: 100%;
+ height: auto;
+ border: 0;
+
+ background-color: transparent;
+
+ font-weight: bold;
+ text-align: center;
+
+ -moz-appearance: textfield;
+ &::-webkit-outer-spin-button,
+ &::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ }
+ }
+}
+
+.spell {
+ $this: ".spell";
+ margin: 0 .25rem;
+ padding: 0 .25rem;
+
+ border: {
+ width: 0 0 0.5rem 0;
+ style: solid;
+ color: transparent;
+ image-slice: 15% 5% 10% 5%;
+ image-width: 0rem 0rem 0.75rem 0rem;
+ image-outset: 0px 0px 0px 0px;
+ image-source: url("https://s3.amazonaws.com/files.d20.io/images/229248387/s-7U3vgLH9-s9S_jTdpHBw/max.png?1624041526");
+ image-repeat: repeat;
+ }
+
+ &__display {
+ display: grid;
+ grid-template-columns: 1.5rem 1fr 3.5rem 1.5rem 1.5rem; // 1.5rem;
+ grid-gap: .5rem;
+ align-items: center;
+ justify-content: center;
+ }
+
+ &__card-button[type="roll"] {
+ grid-column: span 2;
+ }
+
+ &__prepped {
+ display: grid;
+ align-items: center;
+ justify-content: center;
+ grid-template-areas: "checkbox";
+
+ text-align: center;
+
+ > * {
+ grid-area: checkbox;
+ width: 100%;
+ height: 100%;
+ }
+
+ &-mark {
+ $mark-size: 1rem;
+ display: block;
+ width: $mark-size;
+ height: $mark-size;
+
+ border: 1px solid black;
+ border-radius: $mark-size;
+ }
+
+ input#{$this}__prepped-input[type="checkbox"] {
+ opacity: 0;
+ }
+
+ + .spell__card-button[type="roll"] {
+ grid-column: 2;
+ }
+
+ }
+
+ &__card-button[type="roll"] {
+ padding: 0;
+ margin: 0;
+ overflow: hidden;
+
+ border: 0;
+ box-shadow: none;
+
+ background: transparent;
+
+ text-align: left;
+ text-overflow: ellipsis;
+ }
+
+ &__indicators {
+ }
+
+ &__components,
+ &__casting-details {
+ display: flex;
+ justify-content: space-between;
+ }
+
+ &__ritual,
+ &__concentration {
+ display: block;
+ width: 1.25rem;
+ height: 1.25rem;
+
+ background-color: black;
+ color: white;
+
+ font-size: 6pt;
+ font-family: "Verdana", "Tahoma", sans-serif;
+ text-align: center;
+ }
+
+ &__component {
+ font-size: 6pt;
+ font-family: "Verdana", "Tahoma", sans-serif;
+ text-align: center;
+
+ &--v,
+ &--s,
+ &--m {
+ @extend #{$this}__component;
+ }
+ }
+
+ &__chat-button[type="roll"] {
+ padding: 0;
+ margin: 0;
+
+ border: 0;
+ box-shadow: none;
+
+ background: transparent;
+
+ font-family: Pictos;
+ font-size: 12pt;
+ text-align: center;
+ }
+
+ &__details-container,
+ &__options-container {
+ display: grid;
+ grid-template-areas: "checkbox";
+
+ > * {
+ grid-area: checkbox;
+ width: 100%;
+ height: 100%;
+ }
+
+ input[class*="flag"][type="checkbox"] {
+ opacity: 0;
+
+ &:checked ~ span {
+ color: red;
+ }
+ }
+
+ span {
+ font-family: Pictos;
+ font-size: 12pt;
+ text-align: center;
+ }
+ }
+
+ &__details {
+ display: none;
+ }
+
+ &__options--attack {
+ display: none;
+ }
+
+ // Display Controls
+
+ input.spell__flag--details {
+ &[value="on"] ~ .spell__details {
+ display: block !important;
+ }
+ }
+
+ input.spell__flag--options {
+ &[value="on"] ~ .spell__options {
+ display: block !important;
+ }
+ }
+
+ input.spell__flag--output {
+ &[value="ATTACK"] ~ .spell__options--attack {
+ display: block !important;
+ }
+ }
+}
+
+.details {
+ &__row {
+
+ }
+
+}
\ No newline at end of file
diff --git a/Brancalonia Official/src/scss/pc/_ToolsProficiencies.scss b/Brancalonia Official/src/scss/pc/_ToolsProficiencies.scss
new file mode 100644
index 0000000000..ce49a02b29
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_ToolsProficiencies.scss
@@ -0,0 +1,74 @@
+.toolprofs {
+ width: auto;
+ margin-top: 0.25rem;
+
+ border: {
+ width: 0.5rem;
+ style: solid;
+ color: transparent;
+ image-source: url("#{$externalImgsPath}proficiency-block.svg#{$imgParameters}");
+ image-slice: 6% 8% 6% 8%;
+ image-width: 1.5rem 2rem;
+ image-repeat: stretch;
+ }
+
+ &__header {
+ display: grid;
+ grid-template-columns: 1fr 0.75fr 1fr 1.25rem;
+ grid-gap: 0.25rem;
+ margin: 0.5rem;
+
+ text-align: center;
+
+ color: #666;
+ }
+
+ &__label {
+ font-size: 1rem;
+ font-weight: bold;
+ text-align: center;
+ }
+}
+
+.toolprof {
+ width: auto;
+
+ &__display {
+ display: grid;
+ grid-template-columns: 1fr 1.25rem;
+ align-items: center;
+ margin: 0.5rem;
+
+ button[type="roll"] {
+ @extend %RollButton;
+
+ display: grid;
+ grid-template-columns: 1fr 0.75fr 1fr;
+ grid-gap: 0.25rem;
+ align-items: center;
+ }
+ }
+
+ &__name,
+ &__value,
+ &__attribute {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0.5rem;
+ width: 100%;
+ height: 2rem;
+
+ border-radius: 5px 0 5px 0;
+ border: 0;
+
+ font-size: 1rem;
+ font-weight: bold;
+ text-align: left;
+
+ background-color: #efefef;
+ }
+
+ &__value[type="text"] {
+ text-align: center;
+ }
+}
diff --git a/Brancalonia Official/src/scss/pc/_Vitals.scss b/Brancalonia Official/src/scss/pc/_Vitals.scss
new file mode 100644
index 0000000000..26be3a3238
--- /dev/null
+++ b/Brancalonia Official/src/scss/pc/_Vitals.scss
@@ -0,0 +1,160 @@
+.vitals {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ grid-template-rows: 1fr 0.8fr;
+ grid-gap: 1rem 0;
+ padding: 0 8%;
+
+ input[type="number"] {
+ -moz-appearance: textfield;
+ &::-webkit-outer-spin-button,
+ ::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+ }
+ }
+
+ > div {
+ span {
+ display: block;
+ text-align: center;
+ font-size: 10pt;
+ }
+ }
+
+ &__hp {
+ grid-row: span 2;
+ min-height: 22.5rem;
+ padding: 0 25%;
+
+ background: {
+ image: url("https://res.cloudinary.com/dmrhbjudf/image/upload/v1626560576/bottlehp_xgdwjn.png");
+ size: auto 100%;
+ position: top center;
+ repeat: no-repeat;
+ }
+
+ > input[type="number"]:first-child {
+ margin-top: 10rem;
+
+ border: {
+ width: 0 0 0.5rem 0;
+ style: solid;
+ color: transparent;
+ image-slice: 15% 5% 10% 5%;
+ image-width: 0rem 0rem 0.75rem 0rem;
+ image-outset: 0px 0px 0px 0px;
+ image-source: url("https://s3.amazonaws.com/files.d20.io/images/229248387/s-7U3vgLH9-s9S_jTdpHBw/max.png?1624041526");
+ image-repeat: repeat;
+ }
+ }
+
+ > input[type="number"] {
+ font-size: 15pt;
+ text-align: center;
+ }
+ }
+
+ &__temphp {
+ padding: 0 27%;
+ padding-left: 20%;
+
+ background: {
+ image: url("https://res.cloudinary.com/dmrhbjudf/image/upload/v1626557916/Pitcher-TempHP_mieznd.png");
+ size: auto 100%;
+ position: top center;
+ repeat: no-repeat;
+ }
+
+ > input[type="number"]:first-child {
+ margin-top: 57.5%;
+
+ border: {
+ width: 0 0 0.5rem 0;
+ style: solid;
+ color: transparent;
+ image-slice: 15% 5% 10% 5%;
+ image-width: 0rem 0rem 0.75rem 0rem;
+ image-outset: 0px 0px 0px 0px;
+ image-source: url("https://s3.amazonaws.com/files.d20.io/images/229248387/s-7U3vgLH9-s9S_jTdpHBw/max.png?1624041526");
+ image-repeat: repeat;
+ }
+ }
+
+ > input[type="number"] {
+ font-size: 14pt;
+ text-align: center;
+ }
+ }
+
+ &__hitdice {
+ padding: 0 27.5%;
+ padding-top: 2.5rem;
+ padding-bottom: 1rem;
+ display: grid;
+ grid-template-columns: 1fr 1rem 1fr;
+ align-items: center;
+
+ background: {
+ image: url("https://res.cloudinary.com/dmrhbjudf/image/upload/v1626557915/Cup-HD_t2gkum.png");
+ size: auto 100%;
+ position: top center;
+ repeat: no-repeat;
+ }
+
+ > input[type="number"]:first-child {
+
+ border: {
+ width: 0 0 0.5rem 0;
+ style: solid;
+ color: transparent;
+ image-slice: 15% 5% 10% 5%;
+ image-width: 0rem 0rem 0.75rem 0rem;
+ image-outset: 0px 0px 0px 0px;
+ image-source: url("https://s3.amazonaws.com/files.d20.io/images/229248387/s-7U3vgLH9-s9S_jTdpHBw/max.png?1624041526");
+ image-repeat: repeat;
+ }
+ }
+
+ > input[type="number"] {
+ font-size: 14pt;
+ text-align: center;
+ }
+
+ > span[name*="max"] {
+ font-size: 16pt;
+
+ border: {
+ width: 0 0 0.5rem 0;
+ style: solid;
+ color: transparent;
+ image-slice: 15% 5% 10% 5%;
+ image-width: 0rem 0rem 0.75rem 0rem;
+ image-outset: 0px 0px 0px 0px;
+ image-source: url("https://s3.amazonaws.com/files.d20.io/images/229248387/s-7U3vgLH9-s9S_jTdpHBw/max.png?1624041526");
+ image-repeat: repeat;
+ }
+ }
+
+ > span.vitals__label {
+ grid-column: span 3;
+ }
+ }
+
+ button[type="roll"] {
+ @extend %RollButton;
+ }
+
+ input[type="number"],
+ input[type="text"] {
+ @extend %StandardInput;
+ }
+}
+
+.trackers {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ grid-gap: 1rem;
+ margin-top: 1rem;
+ padding: 1rem;
+}
diff --git a/Brancalonia Official/src/scss/repcontrol.scss b/Brancalonia Official/src/scss/repcontrol.scss
new file mode 100644
index 0000000000..6426b60b73
--- /dev/null
+++ b/Brancalonia Official/src/scss/repcontrol.scss
@@ -0,0 +1,83 @@
+
+.repcontrol {
+ min-height: 27px;
+}
+
+.repcontrol .btn {
+ /*visibility: hidden;*/
+ border: medium none;
+ color: white !important;
+ background: none;
+ box-shadow: none;
+}
+
+.repcontrol .btn:focus {
+ outline: 0;
+}
+.saving-throw-container .repcontrol .repcontrol_edit,
+.saving-throw-container .repcontrol .repcontrol_add {
+ padding-left: 4px;
+ padding-right: 4px;
+}
+
+.repcontrol .repcontrol_edit:after {
+ content: '(';
+ visibility: visible;
+ font-family: pictos;
+ background-color: #fff;
+ border: 1px solid black;
+ border-radius: 2px;
+ font-size: 12px;
+ height: 12px;
+ width: 12px;
+ padding: 2px 4px 2px 4px;
+ color: black;
+}
+
+.editmode ~ .repcontrol .repcontrol_edit:after {
+ content: ')';
+}
+
+.repcontrol .repcontrol_add:before {
+ content: '&';
+ visibility: visible;
+ font-family: pictos;
+ background-color: #fff;
+ border: 1px solid black;
+ border-radius: 2px;
+ font-size: 12px;
+ height: 12px;
+ width: 12px;
+ padding: 2px 4px 2px 4px;
+ color: black;
+}
+
+.repcontrol .repcontrol_edit:hover:after,
+.repcontrol .repcontrol_add:hover:before
+{
+ background-color: #EFEFEF;
+}
+
+.resources .repcontrol {
+ margin-top: -10px;
+}
+
+.itemcontrol {
+ z-index: 10;
+}
+
+.itemcontrol .repcontrol_del {
+ font-size: 10px;
+ margin-top: 3px;
+ padding: 0px;
+ height: 18px;
+ width: 18px;
+}
+
+.itemcontrol .repcontrol_move {
+ font-size: 10px;
+ margin-top: 3px;
+ padding: 0px;
+ height: 18px;
+ width: 18px;
+}
diff --git a/Brancalonia Official/src/scss/rolltemplate.scss b/Brancalonia Official/src/scss/rolltemplate.scss
new file mode 100644
index 0000000000..b4bac40341
--- /dev/null
+++ b/Brancalonia Official/src/scss/rolltemplate.scss
@@ -0,0 +1,1103 @@
+// Variables
+
+$font-l: 2rem;
+
+$title-face: "Quintessential", serif;
+$info-face: "Dancing Script", serif;
+$dense-face: 'Times New Roman', Times, serif;
+
+// Placeholders
+
+%RollTemplate {
+}
+
+%InlineRollResult {
+}
+
+// Default Styling
+
+// Attack
+
+.sheet-rolltemplate-atk {
+
+}
+
+// Simple
+
+.sheet-rolltemplate-atkdmg,
+.sheet-rolltemplate-dmg,
+.sheet-rolltemplate-atk,
+.sheet-rolltemplate-simple {
+ width: 80%;
+ margin: auto;
+
+ border: {
+ width: 0.5rem;
+ style: solid;
+ color: transparent;
+ image-slice: 11% 5% 10% 5% fill;
+ image-width: 0.75rem 1rem 0.75rem 1rem;
+ image-outset: 0px 0px 0px 0px;
+ image-repeat: round round;
+ image-source: url("https://s3.amazonaws.com/files.d20.io/images/229248387/s-7U3vgLH9-s9S_jTdpHBw/max.png?1624041526");
+ }
+
+ font-family: $info-face;
+
+ * {
+ box-sizing: border-box;
+ }
+
+ .sheet-result {
+ display: flex;
+ align-content: center;
+ justify-content: space-around;
+
+ width: 80%;
+ margin: auto;
+ padding: .5rem 1rem;
+ }
+
+ .sheet-adv,
+ .sheet-solo {
+ display: grid;
+ align-items: center;
+ justify-content: center;
+
+ height: auto;
+
+ line-height: 1.125;
+
+ > * {
+ display: block;
+
+ text-align: center;
+ }
+ }
+
+ .inlinerollresult {
+ padding: 0;
+
+ border: 0;
+
+ background-color: transparent;
+
+ font-size: $font-l;
+
+ &.fullcrit {
+ color: #3fb315;
+ border: 0;
+ }
+
+ &.fullfail {
+ color: #b31515;
+ border: 0;
+ }
+
+ &.importantroll {
+ color: #4a57ed;
+ border: 0;
+ }
+ }
+
+ .sheet-advspacer {
+ align-self: stretch;
+
+ min-width: .1rem;
+ max-width: .1rem;
+ min-height: 3.5rem;
+ height: 100%;
+
+ background-color: black;
+ }
+
+ .sheet-grey {
+ color: #ccc;
+ }
+
+ .sheet-label {
+ margin: 0.5rem 0;
+
+ color: black;
+
+ font-family: $title-face;
+ font-weight: bold;
+ text-align: center;
+
+ a {
+ background: transparent;
+
+ border: 0px solid;
+
+ text-decoration: none;
+
+ color: #c00;
+ }
+
+ span span {
+ font-family: $info-face;
+ }
+ }
+
+ .sheet-sublabel {
+ display: flex;
+ justify-content: space-around;
+
+ margin: 0 1rem;
+
+ color: #000;
+ background-color: #eee;
+ }
+
+ .sheet-charname {
+ font-family: $dense-face;
+ font-size: 1rem;
+ text-align: center;
+ text-transform: uppercase;
+ }
+
+ .sheet-desc {
+ margin: .25rem 1rem;
+ padding: .5rem;
+
+ border-top: 1px solid black;
+
+ font-family: $dense-face;
+ font-size: 1.2rem;
+ line-height: 1.5;
+ }
+
+ .sheet-savedc {
+ font-family: $dense-face;
+ font-size: 1.2rem;
+ text-align: center;
+ text-transform: uppercase;
+
+ .inlinerollresult {
+ font-family: $dense-face;
+ font-size: 1.2rem;
+ font-weight: normal;
+ }
+ }
+
+ .sheet-damagetype {
+ font-size: 1.5rem;
+ font-weight: bold;
+ }
+
+ .sheet-spelldesc-link {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ margin: .5rem 0;
+
+ a {
+ background: transparent;
+
+ border: 1px solid black;
+
+ text-decoration: none;
+
+ color: #c00;
+ }
+ }
+
+ .sheet-atk.sheet-save {
+ margin: .5rem 1rem;
+
+ border-bottom: 1px solid black;
+
+ .sheet-label {
+ margin: 0;
+ }
+ }
+
+ .sheet-hldmg {
+ display: block;
+ margin: 1rem;
+
+ border-bottom: 1px solid black;
+
+ text-align: center;
+ }
+}
+
+.sheet-rolltemplate-traits,
+.sheet-rolltemplate-spell,
+.sheet-rolltemplate-spelloutput {
+
+ border: {
+ width: 0.5rem;
+ style: solid;
+ color: transparent;
+ image-slice: 11% 5% 10% 5% fill;
+ image-width: 0.75rem 1rem 0.75rem 1rem;
+ image-outset: 0px 0px 0px 0px;
+ image-repeat: round round;
+ image-source: url("https://s3.amazonaws.com/files.d20.io/images/229248387/s-7U3vgLH9-s9S_jTdpHBw/max.png?1624041526");
+ }
+
+ font-family: $dense-face;
+
+ .sheet-header,
+ .sheet-title {
+ margin: .5rem 0;
+
+ font-weight: bold;
+ font-family: $title-face;
+ font-size: 2rem;
+ text-align: center;
+ text-transform: uppercase;
+
+ &.sheet-desconly {
+ margin: 0;
+
+ color: #c00;
+
+ font-size: 1.2rem
+ }
+ }
+
+ .sheet-subheader,
+ .sheet-level {
+ display: block;
+
+ font-weight: bold;
+ text-align: center;
+ text-transform: capitalize;
+ }
+
+ .sheet-row {
+ margin: .5rem .75rem;
+ }
+
+ .sheet-bold {
+ font-weight: bold;
+ text-transform: uppercase;
+ }
+
+ .sheet-spellsavedc {
+ margin-top: 1rem;
+
+ font-weight: bold;
+ font-size: 1.5rem;
+ text-align: center;
+ }
+}
+
+.sheet-rolltemplate-npc,
+.sheet-rolltemplate-npcfullatk,
+.sheet-rolltemplate-npcdmg,
+.sheet-rolltemplate-npcaction,
+.sheet-rolltemplate-npcatk {
+ position: relative;
+ width: 80%;
+ margin: auto;
+ padding: 1rem 1rem;
+
+ &:before {
+ display: block;
+ content: " ";
+ box-sizing: border-box;
+
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 1;
+
+ border: {
+ width: 0.5rem;
+ style: solid;
+ color: transparent;
+ image-slice: 11% 5% 10% 5% fill;
+ image-width: 0.75rem 1rem 0.75rem 1rem;
+ image-outset: 0px 0px 0px 0px;
+ image-repeat: round round;
+ image-source: url("https://s3.amazonaws.com/files.d20.io/images/229248387/s-7U3vgLH9-s9S_jTdpHBw/max.png?1624041526");
+ }
+
+ filter: grayscale(100%) brightness(30%) sepia(100%) hue-rotate(-50deg) saturate(600%) contrast(0.8);
+ }
+
+ > * {
+ position: relative;
+ z-index: 10;
+
+ color: white;
+
+ font-family: $dense-face;
+ }
+
+ a {
+ padding: 0;
+ border: 0;
+ font-weight: bold;
+ background: transparent;
+ }
+
+ .inlinerollresult {
+ padding: 0 .33rem;
+
+ background: none;
+ border: none;
+
+ font-family: $dense-face;
+ font-size: 1.5rem;
+ font-weight: normal;
+ line-height: 1;
+
+ &.fullcrit {
+ border: 1px solid black;
+ background-color: green;
+ color: white;
+ font-weight: bold;
+ }
+
+ &.fullfail {
+ border: 1px solid black;
+ background-color: red;
+ color: white;
+ font-weight: bold;
+ }
+
+ &.importantroll {
+ border: 1px solid black;
+ background-color: blue;
+ color: white;
+ font-weight: bold;
+ }
+ }
+
+ .sheet-row,
+ .sheet-header {
+ color: white;
+
+ a {
+ padding: 0;
+ border: 0;
+ font-weight: bold;
+ background: transparent;
+ color: white;
+ }
+ }
+
+ .sheet-row {
+ margin: 0.5rem 0;
+ }
+
+ .sheet-header {
+ padding-bottom: .25rem;
+ margin-bottom: .5rem;
+
+ border-bottom: 2px solid white;
+
+ font-family: $title-face;
+ font-weight: bold;
+ }
+
+ .sheet-subheader {
+ text-align: center;
+ text-transform: uppercase;
+ }
+
+ .sheet-italics {
+ margin-right: .33rem;
+ font-weight: bold;
+ }
+}
+
+
+
+// .sheet-rolltemplate-dmg,
+// .sheet-rolltemplate-atk,
+// .sheet-rolltemplate-simple,
+// .sheet-rolltemplate-simple3D,
+// .sheet-rolltemplate-skill,
+// .sheet-rolltemplate-atkdmg {
+// width: 100%;
+
+// .sheet-container {
+// background-color: white;
+// border: 1px solid black;
+// color: black;
+// width: 100%;
+// }
+
+// .sheet-adv {
+// display: inline-block;
+// margin-top: 1rem;
+// text-align: center;
+// vertical-align: top;
+// width: 45%;
+// }
+
+// .sheet-adv:first-child {
+// margin-left: 0.2em;
+// }
+
+// .sheet-adv:nth-child(3) {
+// margin-right: 8px;
+// margin-left: -3px;
+// }
+
+// .sheet-adv span,
+// .sheet-solo span {
+// background-color: transparent;
+// border: 0px;
+// font-size: 1.2em;
+// padding: 0px;
+// }
+
+// .sheet-advspacer {
+// border: 1px solid black;
+// display: inline-block;
+// height: 35px;
+// width: 0px;
+// }
+
+// .sheet-solo {
+// height: auto;
+// padding-bottom: 0.5em;
+// padding-top: 1em;
+// text-align: center;
+// width: 100%;
+// }
+
+// span {
+// font-size: 12px;
+// font-weight: bold;
+// line-height: 12px;
+// text-align: center;
+// }
+
+// span.sheet-plus {
+// display: inline;
+// font-size: 20px;
+// font-weight: bold;
+// }
+
+// .sheet-label span span {
+// padding: 0px;
+// border: 0px;
+// background-color: transparent;
+// font-size: 12px;
+// }
+
+// .sheet-grey,
+// .sheet-grey .inlinerollresult.fullcrit,
+// .sheet-grey .inlinerollresult.fullfail,
+// .sheet-grey .inlinerollresult.importantroll,
+// .sheet-label span span {
+// color: #a0a0a0;
+// border: 0px;
+// font-weight: normal;
+// }
+
+// .sheet-label {
+// margin-top: -3px;
+// padding: 0.25em;
+// text-align: center;
+// }
+
+// .inlinerollresult.fullcrit {
+// color: #3fb315;
+// border: 0px;
+// }
+
+// .inlinerollresult.fullfail {
+// color: #b31515;
+// border: 0px;
+// }
+
+// .inlinerollresult.importantroll {
+// color: #4a57ed;
+// border: 0px;
+// }
+
+// .sheet-save {
+// .sheet-savedc {
+// padding-bottom: 5px;
+// padding-top: 15px;
+// text-align: center;
+// }
+
+// span {
+// font-size: 15px;
+// font-weight: bold;
+// }
+
+// .sheet-label span {
+// font-weight: bold;
+// }
+
+// .inlinerollresult {
+// background-color: transparent;
+// border: 0px;
+// display: inline-block;
+// font-weight: bold;
+// }
+
+// .inlinerollresult {
+// padding: 0px;
+// }
+// }
+
+// .inlinerollresult {
+// font-size: 20px;
+// padding-bottom: 6px;
+// padding-top: 10px;
+// }
+
+// .sheet-desc .sheet-label span {
+// font-weight: bold;
+// }
+
+// span.sheet-bold {
+// font-weight: bold;
+// display: inline-block;
+// }
+
+// .sheet-sublabel {
+// text-align: center;
+// font-style: italic;
+// margin-top: -2px;
+// min-height: 17px;
+// }
+
+// .sheet-desc {
+// background-color: white;
+// border: 1px solid black;
+// color: black;
+// padding-bottom: 5px;
+// padding-top: 5px;
+// text-align: center;
+// width: 81%;
+// }
+
+// .sheet-desc {
+// width: 100%;
+// }
+
+// .sheet-desc span {
+// font-weight: normal;
+// line-height: 12px;
+// display: block;
+// }
+
+// .sheet-info span {
+// text-align: left;
+// padding: 0px 5px 0px 5px;
+// }
+
+// .sheet-info .inlinerollresult {
+// font-size: inherit;
+// padding: 0px;
+// }
+
+// .sheet-desc .sheet-sublabel {
+// color: #a0a0a0;
+// display: block;
+// font-size: 10px;
+// font-weight: normal;
+// margin-top: -5px;
+// }
+
+// .sheet-sublabel span {
+// font-weight: normal;
+// color: black;
+// }
+
+// .sheet-spacer {
+// height: 10px;
+// }
+
+// a[href^="~"] {
+// background-color: transparent;
+// padding: 0px;
+// color: black;
+// border: 0px;
+// }
+
+// a:hover {
+// color: #ec2127;
+// }
+
+// a[href^="~"]:visited {
+// pointer-events: none;
+// }
+
+// .sheet-header {
+// color: rgb(126, 45, 64);
+// font-size: 18px;
+// text-align: left;
+// font-family: "Times New Roman", Times, serif;
+// font-variant: small-caps;
+// }
+
+// .sheet-italics {
+// font-style: italic;
+// }
+// }
+
+// .sheet-rolltemplate-atkdmg .sheet-damagetemplate .sheet-result,
+// .sheet-rolltemplate-dmg .sheet-damagetemplate .sheet-result {
+// min-height: 4.5rem;
+// }
+
+// .sheet-rolltemplate-skill {
+
+// .sheet-result {
+// display: flex;
+// margin: 0 10px 0 7px;
+// overflow: hidden;
+// }
+
+// .sheet-roll {
+// display: inline-block;
+// margin-top: 1em;
+// margin-bottom: 1em;
+// text-align: center;
+// vertical-align: top;
+// width: 45%;
+// flex-basis: 50%;
+// flex-grow: 1;
+// flex-shrink: 1;
+// min-width: 33.33333%;
+// position: relative;
+// }
+
+// .sheet-reliableroll span .inlinerollresult {
+// color: #4a57ed;
+// }
+
+// .sheet-roll + .sheet-roll:before {
+// content: "";
+// display: block;
+// position: absolute;
+// width: 2px;
+// height: calc(100% + 1em);
+// min-height: 35px;
+// background: black;
+// position: absolute;
+// top: -1em;
+// left: -1px;
+// }
+// }
+
+// .sheet-rolltemplate-spell .sheet-container,
+// .sheet-rolltemplate-spelloutput .sheet-container {
+// background-repeat: repeat;
+// background-size: auto;
+// border: 1px solid black;
+// color: black;
+// font-family: "Times New Roman", Times, serif;
+// margin-left: -3em;
+// padding: 0.5em;
+// width: 19em;
+// }
+
+// .withoutavatars .sheet-rolltemplate-spell .sheet-container,
+// .withoutavatars .sheet-rolltemplate-spelloutput .sheet-container {
+// margin-left: -15px;
+// }
+
+// .sheet-rolltemplate-spell,
+// .sheet-rolltemplate-spelloutput {
+
+// .sheet-row {
+// display: block;
+// }
+
+// .sheet-title {
+// color: rgb(126, 45, 64);
+// font-size: 1.2em;
+// }
+
+// .sheet-italics {
+// font-style: italic;
+// }
+
+// .sheet-bold {
+// font-weight: bold;
+// }
+
+// .sheet-spacer {
+// height: 5px;
+// }
+// }
+
+// .sheet-rolltemplate-traits .sheet-header {
+// font-family: "Times New Roman", Times, serif;
+// font-size: 16px;
+// text-transform: capitalize;
+// font-variant: small-caps;
+// font-weight: bold;
+// color: rgb(126, 45, 64);
+// }
+
+// .sheet-rolltemplate-npc .sheet-italics,
+// .sheet-rolltemplate-npcaction .sheet-italics,
+// .sheet-rolltemplate-npcfullatk .sheet-italics,
+// .sheet-rolltemplate-npcatk .sheet-italics,
+// .sheet-rolltemplate-npcdmg .sheet-italics,
+// .sheet-rolltemplate-dmgaction .sheet-italics,
+// .sheet-rolltemplate-traits
+
+// .sheet-rolltemplate-npc .sheet-subheader,
+// .sheet-rolltemplate-npcaction .sheet-subheader,
+// .sheet-rolltemplate-npcfullatk .sheet-subheader,
+// .sheet-rolltemplate-npcatk .sheet-subheader,
+// .sheet-rolltemplate-npcdmg .sheet-subheader,
+// .sheet-rolltemplate-dmgaction .sheet-subheader {
+// line-height: 13px;
+// margin-top: -3px;
+// }
+
+// .sheet-rolltemplate-traits .sheet-subheader {
+// font-style: italic;
+// color: #a0a0a0;
+// margin-top: -5px;
+// }
+
+// .sheet-rolltemplate-npc .sheet-subheader span,
+// .sheet-rolltemplate-npcaction .sheet-subheader span,
+// .sheet-rolltemplate-npcfullatk .sheet-subheader span,
+// .sheet-rolltemplate-npcatk .sheet-subheader span,
+// .sheet-rolltemplate-npcdmg .sheet-subheader span,
+// .sheet-rolltemplate-dmgaction .sheet-subheader span {
+// font-size: 11px;
+// line-height: 11px;
+// }
+
+// .sheet-rolltemplate-traits .sheet-subheader span {
+// font-weight: normal;
+// font-size: 10px;
+// text-align: left;
+// line-height: 16px;
+// }
+
+// .sheet-rolltemplate-traits .sheet-desc {
+// font-weight: normal;
+// font-size: 12px;
+// text-align: left;
+// line-height: 16px;
+// }
+
+// .sheet-rolltemplate-npc .sheet-arrow-rightold,
+// .sheet-rolltemplate-npcaction .sheet-arrow-rightold,
+// .sheet-rolltemplate-npcfullatk .sheet-arrow-rightold,
+// .sheet-rolltemplate-npcatk .sheet-arrow-rightold,
+// .sheet-rolltemplate-npcdmg .sheet-arrow-rightold,
+// .sheet-rolltemplate-dmgaction .sheet-arrow-rightold {
+// border-top: 3px solid transparent;
+// border-bottom: 3px solid transparent;
+// border-left: 195px solid rgb(126, 45, 64);
+// }
+
+// .sheet-rolltemplate-npc .sheet-arrow-right,
+// .sheet-rolltemplate-npcaction .sheet-arrow-right,
+// .sheet-rolltemplate-npcfullatk .sheet-arrow-right,
+// .sheet-rolltemplate-npcatk .sheet-arrow-right,
+// .sheet-rolltemplate-npcdmg .sheet-arrow-right,
+// .sheet-rolltemplate-dmgaction .sheet-arrow-right {
+// border: 1px solid rgb(126, 45, 64);
+// margin-bottom: 2px;
+// margin-top: 2px;
+// }
+
+// .sheet-rolltemplate-npc .inlinerollresult,
+// .sheet-rolltemplate-npcaction .inlinerollresult,
+// .sheet-rolltemplate-npcfullatk .inlinerollresult,
+// .sheet-rolltemplate-npcatk .inlinerollresult,
+// .sheet-rolltemplate-npcdmg .inlinerollresult,
+// .sheet-rolltemplate-dmgaction .inlinerollresult,
+// .sheet-rolltemplate-traits .inlinerollresult {
+// background-color: #ffffff;
+// border: none;
+// }
+
+// .sheet-rolltemplate-npc .inlinerollresult.fullcrit,
+// .sheet-rolltemplate-npcaction .inlinerollresult.fullcrit,
+// .sheet-rolltemplate-npcfullatk .inlinerollresult.fullcrit,
+// .sheet-rolltemplate-npcatk .inlinerollresult.fullcrit,
+// .sheet-rolltemplate-npcdmg .inlinerollresult.fullcrit,
+// .sheet-rolltemplate-dmgaction .inlinerollresult.fullcrit {
+// color: #3fb315;
+// border: none;
+// }
+
+// .sheet-rolltemplate-npc .inlinerollresult.fullfail,
+// .sheet-rolltemplate-npcaction .inlinerollresult.fullfail,
+// .sheet-rolltemplate-npcfullatk .inlinerollresult.fullfail,
+// .sheet-rolltemplate-npcatk .inlinerollresult.fullfail,
+// .sheet-rolltemplate-npcdmg .inlinerollresult.fullfail,
+// .sheet-rolltemplate-dmgaction .inlinerollresult.fullfail {
+// color: #b31515;
+// border: none;
+// }
+
+// .sheet-rolltemplate-npc .inlinerollresult.importantroll,
+// .sheet-rolltemplate-npcaction .inlinerollresult.importantroll,
+// .sheet-rolltemplate-npcfullatk .inlinerollresult.importantroll,
+// .sheet-rolltemplate-npcatk .inlinerollresult.importantroll,
+// .sheet-rolltemplate-npcdmg .inlinerollresult.importantroll,
+// .sheet-rolltemplate-dmgaction .inlinerollresult.importantroll {
+// color: #4a57ed;
+// border: none;
+// }
+
+// .sheet-rolltemplate-npcatk a[href^="~"] {
+// background-color: transparent;
+// padding: 0px;
+// color: black;
+// border: 0px;
+// }
+
+// .sheet-rolltemplate-npcatk .sheet-header a[href^="~"] {
+// color: rgb(126, 45, 64);
+// }
+
+// .sheet-rolltemplate-npcatk a[href^="~"]:hover {
+// color: #ec2127;
+// }
+
+// .sheet-rolltemplate-simple .sheet-charname,
+// .sheet-rolltemplate-simple3D .sheet-charname,
+// .sheet-rolltemplate-skill .sheet-charname,
+// .sheet-rolltemplate-atk .sheet-charname,
+// .sheet-rolltemplate-dmg .sheet-charname,
+// .sheet-rolltemplate-atkdmg .sheet-charname {
+// text-align: center;
+// margin-top: -10px;
+// }
+
+// .sheet-rolltemplate-simple .sheet-charname span,
+// .sheet-rolltemplate-simple3D .sheet-charname span,
+// .sheet-rolltemplate-skill .sheet-charname span,
+// .sheet-rolltemplate-atk .sheet-charname span,
+// .sheet-rolltemplate-dmg .sheet-charname span,
+// .sheet-rolltemplate-atkdmg .sheet-charname span {
+// font-size: 11px;
+// font-weight: normal;
+// color: #a0a0a0;
+// }
+
+// .sheet-rolltemplate-dmg .sheet-label .sheet-rolltemplate-inline,
+// .sheet-rolltemplate-dmg .sheet-savedc .sheet-rolltemplate-inline,
+// .sheet-rolltemplate-atkdmg .sheet-savedc .sheet-rolltemplate-inline,
+// .sheet-rolltemplate-atkdmg .sheet-label .sheet-rolltemplate-inline {
+// display: inline-block;
+// }
+
+// /* ROLL TEMPLATE */
+// .sheet-rolltemplate-simple,
+// .sheet-rolltemplate-simple3D,
+// .sheet-rolltemplate-skill,
+// .sheet-rolltemplate-atk,
+// .sheet-rolltemplate-atkdmg,
+// .sheet-rolltemplate-dmg,
+// .sheet-rolltemplate-desc {
+// image-rendering: -webkit-optimize-contrast;
+// }
+
+// .sheet-rolltemplate-simple div.sheet-container,
+// .sheet-rolltemplate-simple3D div.sheet-container,
+// .sheet-rolltemplate-skill div.sheet-container {
+// background: url("#{$externalImgsPath}D&D-Rolltemplate-Simple.png") top left;
+// }
+
+// .sheet-rolltemplate-atk div.sheet-container,
+// .sheet-rolltemplate-atkdmg div.sheet-container.sheet-atk,
+// .sheet-rolltemplate-dmg div.sheet-atk {
+// background: url("#{$externalImgsPath}D&D-Rolltemplate-Attack.png") top left;
+// background-color: inherit;
+// }
+
+// .sheet-rolltemplate-dmg div.sheet-container,
+// .sheet-rolltemplate-atkdmg div.sheet-container.sheet-damagetemplate {
+// background: url("#{$externalImgsPath}D&D-Rolltemplate-Damage.png") top left;
+// background-color: inherit;
+// }
+
+// .sheet-rolltemplate-atk div.sheet-desc,
+// .sheet-rolltemplate-atkdmg div.sheet-desc,
+// .sheet-rolltemplate-dmg div.sheet-desc,
+// .sheet-rolltemplate-desc div.sheet-desc {
+// background: url("#{$externalImgsPath}D&D-Rolltemplate-Desc.png") top left;
+// background-color: inherit;
+// padding-bottom: 0.35em;
+// padding-top: 0.35em;
+// }
+
+// .sheet-rolltemplate-simple div.sheet-container,
+// .sheet-rolltemplate-simple3D div.sheet-container,
+// .sheet-rolltemplate-skill div.sheet-container,
+// .sheet-rolltemplate-atk div.sheet-container,
+// .sheet-rolltemplate-atkdmg div.sheet-container.sheet-atk,
+// .sheet-rolltemplate-dmg div.sheet-atk,
+// .sheet-rolltemplate-dmg div.sheet-container,
+// .sheet-rolltemplate-atkdmg div.sheet-container.sheet-damagetemplate,
+// .sheet-rolltemplate-atk div.sheet-desc,
+// .sheet-rolltemplate-atkdmg div.sheet-desc,
+// .sheet-rolltemplate-dmg div.sheet-desc,
+// .sheet-rolltemplate-desc div.sheet-desc {
+// background-repeat: no-repeat;
+// background-size: 13.8em 100%;
+// border: none;
+// width: 100%;
+// }
+
+// .sheet-rolltemplate-atk div.sheet-desc.sheet-info,
+// .sheet-rolltemplate-atkdmg div.sheet-desc.sheet-info,
+// .sheet-rolltemplate-dmg div.sheet-desc.sheet-info,
+// .sheet-rolltemplate-desc div.sheet-desc.sheet-info {
+// background: none;
+// width: 100%;
+// }
+
+// .sheet-rolltemplate-atk div.sheet-desc.sheet-info > span,
+// .sheet-rolltemplate-atkdmg div.sheet-desc.sheet-info > span,
+// .sheet-rolltemplate-dmg div.sheet-desc.sheet-info > span,
+// .sheet-rolltemplate-desc div.sheet-desc.sheet-info > span {
+// padding: 0px;
+// }
+
+// .sheet-rolltemplate-atk div.sheet-desc.sheet-info .sheet-bottom,
+// .sheet-rolltemplate-atkdmg div.sheet-desc.sheet-info .sheet-bottom,
+// .sheet-rolltemplate-dmg div.sheet-desc.sheet-info .sheet-bottom,
+// .sheet-rolltemplate-desc div.sheet-desc.sheet-info .sheet-bottom {
+// background: url("#{$externalImgsPath}D&D-Rolltemplate-Info-Bottom.png") top
+// left;
+// height: 1.1em;
+// background-size: 100% 100%;
+// margin-bottom: -0.3em;
+// }
+
+// .sheet-rolltemplate-atk div.sheet-desc.sheet-info .sheet-top,
+// .sheet-rolltemplate-atkdmg div.sheet-desc.sheet-info .sheet-top,
+// .sheet-rolltemplate-dmg div.sheet-desc.sheet-info .sheet-top,
+// .sheet-rolltemplate-desc div.sheet-desc.sheet-info .sheet-top {
+// background: url("#{$externalImgsPath}D&D-Rolltemplate-Info-Top.png") top left;
+// height: 1.1em;
+// background-size: 100% 100%;
+// margin-top: -0.3em;
+// }
+
+// .sheet-rolltemplate-atk div.sheet-desc.sheet-info .sheet-middle,
+// .sheet-rolltemplate-atkdmg div.sheet-desc.sheet-info .sheet-middle,
+// .sheet-rolltemplate-dmg div.sheet-desc.sheet-info .sheet-middle,
+// .sheet-rolltemplate-desc div.sheet-desc.sheet-info .sheet-middle {
+// background: url("#{$externalImgsPath}D&D-Rolltemplate-Info-Middle.png") top
+// left;
+// background-size: 100% 100%;
+// }
+
+// .sheet-rolltemplate-npc div.sheet-arrow-right,
+// .sheet-rolltemplate-npcaction div.sheet-arrow-right,
+// .sheet-rolltemplate-npcfullatk div.sheet-arrow-right,
+// .sheet-rolltemplate-npcatk div.sheet-arrow-right,
+// .sheet-rolltemplate-npcdmg div.sheet-arrow-right,
+// .sheet-rolltemplate-dmgaction div.sheet-arrow-right {
+// border: none;
+// border-top: 0.25em solid transparent;
+// border-bottom: 0.25em solid transparent;
+// border-left: 14em solid rgb(126, 45, 64);
+// }
+
+// .sheet-rolltemplate-atk div.sheet-advspacer,
+// .sheet-rolltemplate-dmg div.sheet-advspacer,
+// .sheet-rolltemplate-atkdmg div.sheet-advspacer {
+// margin-top: 1px;
+// }
+
+// .sheet-rolltemplate-npc .sheet-translated,
+// .sheet-rolltemplate-npcaction .sheet-translated,
+// .sheet-rolltemplate-npcfullatk .sheet-translated,
+// .sheet-rolltemplate-npcatk .sheet-translated,
+// .sheet-rolltemplate-npcdmg .sheet-translated,
+// .sheet-rolltemplate-dmgaction .sheet-translated,
+// .sheet-rolltemplate-npc .sheet-translated a,
+// .sheet-rolltemplate-npcaction .sheet-translated a,
+// .sheet-rolltemplate-npcfullatk .sheet-translated a,
+// .sheet-rolltemplate-npcatk .sheet-translated a,
+// .sheet-rolltemplate-npcdmg .sheet-translated a,
+// .sheet-rolltemplate-dmgaction .sheet-translated a {
+// text-transform: lowercase;
+// display: inline-block;
+// }
+
+// .sheet-rolltemplate-npc .sheet-translated:first-letter,
+// .sheet-rolltemplate-npcaction .sheet-translated:first-letter,
+// .sheet-rolltemplate-npcfullatk .sheet-translated:first-letter,
+// .sheet-rolltemplate-npcatk .sheet-translated:first-letter,
+// .sheet-rolltemplate-npcdmg .sheet-translated:first-letter,
+// .sheet-rolltemplate-dmgaction .sheet-translated:first-letter,
+// .sheet-rolltemplate-npc .sheet-translated a:first-letter,
+// .sheet-rolltemplate-npcaction .sheet-translated a:first-letter,
+// .sheet-rolltemplate-npcfullatk .sheet-translated a:first-letter,
+// .sheet-rolltemplate-npcatk .sheet-translated a:first-letter,
+// .sheet-rolltemplate-npcdmg .sheet-translated a:first-letter,
+// .sheet-rolltemplate-dmgaction .sheet-translated a:first-letter {
+// text-transform: capitalize;
+// }
+
+// .sheet-rolltemplate-spelloutput .sheet-container {
+// border: 1px dashed black;
+// background: #fffef2;
+// .sheet-desconly {
+// span {
+// width: 100%;
+// text-transform: uppercase;
+// text-align: center;
+// display: inline-block;
+// background: #c43c35;
+// padding: 5px;
+// box-sizing: border-box;
+// margin-bottom: 5px;
+// color: white;
+// font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+// font-size: 10px;
+// line-height: normal;
+// font-weight: 600;
+// }
+// }
+// }
+
+// .sheet-rolltemplate-spelloutput .sheet-level,
+// .sheet-rolltemplate-spell .sheet-level {
+// text-transform: capitalize;
+// }
+
+// .sheet-rolltemplate-spelloutput,
+// .sheet-rolltemplate-spell {
+// .sheet-spellsavedc {
+// text-align: center;
+// text-align: center;
+// padding-top: 5px;
+// border-top: 1px dotted black;
+// margin-top: 10px;
+// }
+// }
+
+// .sheet-rolltemplate-atk .sheet-spelldesc-link,
+// .sheet-rolltemplate-dmg .sheet-spelldesc-link,
+// .sheet-rolltemplate-atkdmg .sheet-spelldesc-link {
+// text-align: center;
+// padding-bottom: 7px;
+// span {
+// a {
+// background-color: transparent;
+// padding: 0;
+// color: #a0a0a0;
+// border: 0;
+// &:hover {
+// color: #ec2127;
+// }
+// }
+// }
+// }
diff --git a/Brancalonia Official/src/scss/spell.scss b/Brancalonia Official/src/scss/spell.scss
new file mode 100644
index 0000000000..8a521d6101
--- /dev/null
+++ b/Brancalonia Official/src/scss/spell.scss
@@ -0,0 +1,608 @@
+
+ .cantrips {
+ display: inline-block;
+ border: 1px solid black;
+ height: 25px;
+ border-radius: 5px;
+ width: 238px;
+ text-align: center;
+ margin-left: -20px;
+ }
+
+ .cantrips span {
+ display: block;
+ font-size: 9px;
+ line-height: 12px;
+ width: 100%;
+ text-align: center;
+ font-weight: bold;
+ margin-top: 8px;
+ }
+
+ .spell-labels {
+ color: #a0a0a0;
+ }
+
+ .spell-labels span {
+ display: inline;
+ font-weight: normal;
+ font-size: 8px;
+ }
+
+ .spell-level input {
+ width: 100%;
+ text-align: center;
+ font-size: 20px;
+ border: none;
+ background: none;
+ box-shadow: none;
+ -webkit-appearance: none;
+ -moz-appearance: textfield;
+ -webkit-border-radius: 0px;
+ border-radius: 0px;
+ color: black;
+ padding: 0px;
+ margin: 2px;
+ height: 100%;
+ }
+
+ .spell-level .total,
+ .spell-level .expended {
+ display: inline-block;
+ border: 1px solid black;
+ height: 25px;
+ border-radius: 5px;
+ text-align: center;
+ margin-left: -20px;
+ background-color: white;
+ }
+
+ .spell-level .total {
+ width: 114px;
+ vertical-align: bottom;
+ }
+
+ .spell-level .total span {
+ font-size: 20px;
+ font-weight: normal;
+ position: relative;
+ top: 3px;
+ }
+
+ .spell-level .expended {
+ width: 139px;
+ border-top-left-radius: 0px;
+ border-bottom-left-radius: 0px;
+ }
+
+ .spell {
+ margin-bottom: 5px;
+ width: 245px;
+ }
+
+ .spell .wrapper button.spell_link::before {
+ content: "|";
+ }
+
+ .spell .wrapper button.spell_link {
+ position: absolute;
+ top: 0;
+ right: 5px;
+ border: none;
+ background: none;
+ color: #a0a0a0;
+ margin: 0;
+ padding: 0;
+ }
+
+ .spell .wrapper button.spell_link:hover {
+ color: #000000;
+ }
+
+ .spell .wrapper {
+ position: relative;
+ }
+
+ .charsheet .spells .details span {
+ font-size: 12px;
+ }
+
+ .charsheet .spells .details span[name="attr_spelldescription"] {
+ white-space: pre-line;
+ }
+
+ .repcontainer .spell .details-flag:not(:checked) ~ .wrapper {
+ display: none;
+ }
+
+ .spell .wrapper .options-flag,
+ .spell .wrapper .options-flag + span {
+ display: inherit;
+ }
+
+ .repcontainer
+ .spell
+ .details-flag:not(:checked)
+ ~ .wrapper
+ input.spell_desc
+ + .options-flag,
+ .repcontainer
+ .spell
+ .details-flag:not(:checked)
+ ~ .wrapper
+ input.spell_desc
+ + .options-flag
+ + span {
+ display: none;
+ }
+
+ .repcontainer .spell .wrapper .options .options-flag + span {
+ right: 23.5px;
+ width: 18px;
+ height: 18px;
+ }
+
+ .repcontainer
+ .spell
+ .wrapper
+ input.spell_desc[value]
+ + .options-flag:not(:checked)
+ ~ .options {
+ display: none;
+ }
+
+ .repcontainer .spell .wrapper .options-flag:not(:checked) ~ .options {
+ display: none;
+ }
+
+ .spell .wrapper .options-flag:checked ~ .details {
+ display: none;
+ }
+
+ .spell .wrapper .options-flag:checked ~ .options {
+ display: inherit;
+ }
+
+ .spell .wrapper .options-flag {
+ z-index: 10;
+ }
+
+ .spell .wrapper .options-flag,
+ .spell .wrapper .options-flag + span {
+ right: 23.5px;
+ }
+
+ div.spell {
+ div.details {
+ overflow: hidden;
+ margin: 15px 10px;
+ }
+ }
+
+ .spell .details span:not(.innate) {
+ display: inline;
+ font-weight: normal;
+ }
+
+ .spell .details span.bold {
+ font-weight: bold;
+ }
+
+ .spell .details .italics {
+ font-style: italic;
+ }
+
+ .spell .details input[type="checkbox"] {
+ display: none;
+ }
+
+ .spell .details input[type="checkbox"] + span {
+ display: none;
+ }
+
+ .spell .details input[type="checkbox"]:checked + span {
+ display: inline;
+ }
+
+ .spell
+ .details
+ input[type="checkbox"]:checked
+ ~ input[type="checkbox"]:checked
+ + span::before {
+ content: ", ";
+ }
+
+ .spell .details span[name="attr_spellname"] {
+ font-family: "Times New Roman", Times, serif;
+ font-size: 16px;
+ text-transform: capitalize;
+ font-variant: small-caps;
+ color: rgb(126, 45, 64);
+ }
+
+ .spell .details input[name="attr_spellcomp_materials"][value=""] + span,
+ .spell .details input[name="attr_spellathigherlevels"][value=""] + div {
+ display: none;
+ }
+
+ .spell .options {
+ border-top: none;
+ border-bottom: 2px dashed gold;
+ padding-bottom: 40px;
+ }
+
+ .spell .options-done {
+ display: inline-block;
+ margin-top: 5px;
+ padding: 3px 10px;
+ width: auto;
+ border-radius: 1em;
+ color: #ffffff;
+ background-color: #000000;
+ font-size: 1em;
+ float: right;
+ cursor: pointer;
+ }
+
+ .spell .options-done:hover {
+ opacity: 0.6;
+ }
+
+ .spell .options-done::before {
+ content: "3";
+ font-family: pictos;
+ }
+
+ .spell .options-done input[type="checkbox"] {
+ display: none;
+ }
+
+ .spell .options-done span.label {
+ margin-top: 0;
+ }
+
+ .spell .display {
+ position: relative;
+ }
+
+ .spell .display button[type="roll"] {
+ background-color: transparent;
+ color: black;
+ border-top: none;
+ border-left: none;
+ border-right: none;
+ border-bottom: 1px solid #d3d3d3;
+ background-image: none;
+ text-shadow: none;
+ box-shadow: none;
+ padding: 0px;
+ margin: 0px;
+ width: 100%;
+ font-weight: bold;
+ text-align: left;
+ }
+
+ .spell .display button[type="roll"]::before {
+ content: "" !important;
+ }
+
+ span.spellritual,
+ span.spellconcentration {
+ display: none;
+ font-size: 8px;
+ font-weight: normal;
+ margin-top: 0px;
+ color: white;
+ background-color: black;
+ position: absolute;
+ width: 10px;
+ height: 10px;
+ top: 0px;
+ line-height: 10px;
+ }
+
+ .spellicon_flag:not([value="none"])
+ + .body
+ .spell
+ .display
+ .spellritual:not([value="0"])
+ ~ span.spellritual {
+ display: inline-block;
+ right: 11px;
+ }
+
+ .spellicon_flag:not([value="none"])
+ + .body
+ .spell
+ .display
+ .spellconcentration:not([value="0"])
+ ~ span.spellconcentration {
+ border-radius: 100%;
+ display: inline-block;
+ right: 0;
+ }
+
+ .spell .display .componentscontainer {
+ position: absolute;
+ top: 3px;
+ right: 0;
+ width: auto;
+ }
+
+ .spell .display .v,
+ .spell .display .s,
+ .spell .display .m {
+ display: none;
+ }
+
+ .spellicon_flag[value="all"]
+ + .body
+ .spell
+ .display
+ input.v:not([value="0"])
+ ~ .componentscontainer
+ span.v,
+ .spellicon_flag[value="all"]
+ + .body
+ .spell
+ .display
+ input.s:not([value="0"])
+ ~ .componentscontainer
+ span.s,
+ .spellicon_flag[value="all"]
+ + .body
+ .spell
+ .display
+ input.m:not([value="0"])
+ ~ .componentscontainer
+ span.m {
+ display: inline;
+ width: initial;
+ font-size: 8px;
+ }
+
+ .spell .display input[type="text"] {
+ font-size: 12px;
+ line-height: 12px;
+ cursor: pointer;
+ text-align: left;
+ padding: none;
+ margin: none;
+ background-color: transparent;
+ color: black;
+ border: none;
+ background-image: none;
+ text-shadow: none;
+ box-shadow: none;
+ padding: 0px;
+ margin: 0px;
+ width: 100%;
+ }
+
+ .spell .display span.spellname {
+ font-size: 12px;
+ text-align: left;
+ font-weight: normal;
+ margin-right: -4px;
+ margin-left: 4px;
+ display: inline;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ max-width: 220px;
+ }
+
+ .spell .display .prep ~ span.spellname {
+ margin-left: 14px;
+ }
+
+ .spell .details-flag,
+ .spell .details-flag + span {
+ position: absolute;
+ top: 0px;
+ right: 23px;
+ width: 18px;
+ height: 18px;
+ }
+ .spell .details-flag {
+ opacity: 0;
+ z-index: 2;
+ }
+
+ .spell .details-flag + span {
+ white-space: nowrap;
+ font-size: 20px;
+ font-family: pictos;
+ color: #a0a0a0;
+ cursor: pointer;
+ margin-top: 0px;
+ display: none;
+ line-height: 18px;
+ }
+
+ .spell .options-flag,
+ .spell .options-flag + span {
+ position: absolute;
+ top: 0px;
+ right: 23px;
+ width: 18px;
+ height: 18px;
+ }
+ .spell .options-flag {
+ opacity: 0;
+ z-index: 2;
+ }
+
+ .spell .options-flag + span {
+ white-space: nowrap;
+ font-size: 20px;
+ font-family: pictos;
+ color: #a0a0a0;
+ cursor: pointer;
+ margin-top: 0px;
+ }
+
+ .spell .details button.spell_link::before {
+ content: "|";
+ }
+
+ .spell .details button.spell_link {
+ float: right;
+ border: none;
+ background: none;
+ color: #a0a0a0;
+ }
+
+ .spell .details button.spell_link:hover {
+ color: #000000;
+ }
+
+ .spell .details-flag:checked + span {
+ display: block;
+ color: #000000;
+ }
+
+ .spell:hover .details-flag + span {
+ display: block;
+ }
+
+ .spell .details-flag ~ .details {
+ display: none;
+ }
+
+ .spell .details-flag:checked ~ .details {
+ display: block;
+ }
+
+ .spell .options {
+ margin: 15px 10px;
+ padding: 0;
+ overflow-x: hidden;
+ text-overflow: ellipsis;
+ }
+
+ .spell .details span.bold {
+ font-weight: bold;
+ }
+
+ .spell .details .italics {
+ font-style: italic;
+ }
+
+ .spell .details input[type="checkbox"] {
+ display: none;
+ }
+
+ .spell .details input[type="checkbox"] + span {
+ display: none;
+ }
+
+ .spell .details input[type="checkbox"]:checked + span {
+ display: inline;
+ }
+
+ .spell
+ .details
+ input[type="checkbox"]:checked
+ ~ input[type="checkbox"]:checked
+ + span::before {
+ content: ", ";
+ }
+
+ .spell .details span[name="attr_spellname"] {
+ font-family: "Times New Roman", Times, serif;
+ font-size: 16px;
+ text-transform: capitalize;
+ font-variant: small-caps;
+ color: rgb(126, 45, 64);
+ }
+
+ .spell .details input[name="attr_spellcomp_materials"][value=""] + span,
+ .spell .details input[name="attr_spellathigherlevels"][value=""] + div {
+ display: none;
+ }
+
+ .spell .display {
+ position: relative;
+ }
+
+ .spell .prep {
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+ position: absolute;
+ top: 0px;
+ border: 1px solid black;
+ }
+
+ .spell input[type="checkbox"]:checked ~ span.prep {
+ background-color: #ec2127;
+ }
+
+ .spell .prep-box {
+ -webkit-appearance: checkbox;
+ -moz-appearance: checkbox;
+ opacity: 0;
+ z-index: 2;
+ position: relative;
+ width: 12px;
+ }
+
+ .charsheet .spell .display button[type="roll"].spellcard {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ width: calc(93% - 18px);
+ }
+
+ .spell-level .spell-points {
+ span {
+ font-size: 20px;
+ font-weight: normal;
+ }
+ }
+ .spellpoints_flag:not([value="1"]) ~ .body .spell-points {
+ display: none;
+ }
+ .spellpoints_flag[value="1"] ~ .body .spell-labels {
+ display: grid;
+ grid-template-columns: 70px 1fr 1fr;
+ margin-left: 25px;
+ width: calc(100% - 25px);
+ span {
+ width: 100%;
+ margin: 0;
+ text-align: center;
+ }
+ }
+ .spellpoints_flag[value="1"] ~ .body {
+ .spell-point-hide {
+ display: none;
+ }
+ .spell-level {
+ display: grid;
+ grid-template-columns: 25px 70px 1fr 1fr;
+ .spell-points {
+ display: flex;
+ align-items: center;
+ span {
+ margin-top: 0;
+ }
+ }
+ .total:after {
+ content: "";
+ position: absolute;
+ width: 1px;
+ height: 20px;
+ left: 76px;
+ top: 4px;
+ background: black;
+ }
+ .total,
+ .expended {
+ margin: 0;
+ width: 100%;
+ text-align: center;
+ box-sizing: border-box;
+ }
+ }
+ }
\ No newline at end of file
diff --git a/Brancalonia Official/translation.json b/Brancalonia Official/translation.json
new file mode 100644
index 0000000000..d3c6dab3b4
--- /dev/null
+++ b/Brancalonia Official/translation.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with":"Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/af.json b/Brancalonia Official/translations/af.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/af.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/ca.json b/Brancalonia Official/translations/ca.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/ca.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/cs.json b/Brancalonia Official/translations/cs.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/cs.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/da.json b/Brancalonia Official/translations/da.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/da.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/de.json b/Brancalonia Official/translations/de.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/de.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/el.json b/Brancalonia Official/translations/el.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/el.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/en.json b/Brancalonia Official/translations/en.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/en.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/es.json b/Brancalonia Official/translations/es.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/es.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/fi.json b/Brancalonia Official/translations/fi.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/fi.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/fr.json b/Brancalonia Official/translations/fr.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/fr.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/he.json b/Brancalonia Official/translations/he.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/he.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/hu.json b/Brancalonia Official/translations/hu.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/hu.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/it.json b/Brancalonia Official/translations/it.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/it.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/ja.json b/Brancalonia Official/translations/ja.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/ja.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/ko.json b/Brancalonia Official/translations/ko.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/ko.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/nl.json b/Brancalonia Official/translations/nl.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/nl.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/pb.json b/Brancalonia Official/translations/pb.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/pb.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/pl.json b/Brancalonia Official/translations/pl.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/pl.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/pt.json b/Brancalonia Official/translations/pt.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/pt.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/ru.json b/Brancalonia Official/translations/ru.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/ru.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/sl.json b/Brancalonia Official/translations/sl.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/sl.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/sv.json b/Brancalonia Official/translations/sv.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/sv.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/tr.json b/Brancalonia Official/translations/tr.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/tr.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/uk.json b/Brancalonia Official/translations/uk.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/uk.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/Brancalonia Official/translations/zh.json b/Brancalonia Official/translations/zh.json
new file mode 100644
index 0000000000..84c2484542
--- /dev/null
+++ b/Brancalonia Official/translations/zh.json
@@ -0,0 +1,387 @@
+{
+ "npc-options-u": "NPC OPTIONS",
+ "name-u": "NAME",
+ "npc-type-u": "NPC TYPE",
+ "armor-class-u": "ARMOR CLASS",
+ "type-u": "TYPE",
+ "hit-points-u": "HIT POINTS",
+ "formula-u": "FORMULA",
+ "speed-u": "SPEED",
+ "attributes-u": "ATTRIBUTES",
+ "str-u": "STR",
+ "dex-u": "DEX",
+ "con-u": "CON",
+ "int-u": "INT",
+ "wis-u": "WIS",
+ "cha-u": "CHA",
+ "saves-u": "SAVES",
+ "skills-u": "SKILLS",
+ "acrobatics-u": "ACROBATICS",
+ "animal_handling-u": "ANIMAL HANDLING",
+ "arcana-u": "ARCANA",
+ "athletics-u": "ATHLETICS",
+ "deception-u": "DECEPTION",
+ "history-u": "HISTORY",
+ "insight-u": "INSIGHT",
+ "intimidation-u": "INTIMIDATION",
+ "investigation-u": "INVESTIGATION",
+ "medicine-u": "MEDICINE",
+ "nature-u": "NATURE",
+ "perception-u": "PERCEPTION",
+ "performance-u": "PERFORMANCE",
+ "persuasion-u": "PERSUASION",
+ "religion-u": "RELIGION",
+ "sleight_of_hand-u": "SLEIGHT_OF_HAND",
+ "stealth-u": "STEALTH",
+ "survival-u": "SURVIVAL",
+ "damage-vuln-u": "DAMAGE VULNERABILITIES",
+ "damage-res-u": "DAMAGE RESISTANCES",
+ "damage-imm-u": "DAMAGE IMMUNITIES",
+ "cond-imm-u": "CONDITION IMMUNITIES",
+ "senses-u": "SENSES",
+ "langs-u": "LANGUAGES",
+ "challenge-u": "CHALLENGE",
+ "xp-u": "XP",
+ "token_size-u": "TOKEN SIZE",
+ "spellcast-npc-u": "SPELLCASTING NPCSPELLCASTING ABILITY\n \n NONE\n STRENGTH\n DEXTERITY\n CONSTITUTION\n INTELLIGENCE\n WISDOM\n CHARISMA",
+ "spell-ability-u": "SPELLCASTING ABILITY",
+ "none-u": "NONE",
+ "strength-u": "STRENGTH",
+ "dexterity-u": "DEXTERITY",
+ "constitution-u": "CONSTITUTION",
+ "intelligence-u": "INTELLIGENCE",
+ "wisdom-u": "WISDOM",
+ "charisma-u": "CHARISMA",
+ "glob-atk-mod:-u": "GLOBAL MAGIC ATTACK MODIFIER:",
+ "magic-caster-lvl:-u": "MAGIC CASTER LEVEL:",
+ "spell_dc_mod:-u": "SPELL SAVE DC MOD:",
+ "has-bonusaction-u": "HAS BONUS ACTIONS",
+ "has-reaction-u": "HAS REACTIONS",
+ "leg-actions:-u": "LEGENDARY ACTIONS:",
+ "myt-actions:-u": "MYTHIC ACTIONS:",
+ "gen-opts-u": "GENERAL OPTIONS",
+ "npc-u": "NPC",
+ "roll-queries:-u": "ROLL QUERIES:",
+ "always-adv": "Always Roll Advantage",
+ "adv-toggle": "Advantage Toggle",
+ "query-adv": "Query Advantage",
+ "never-adv": "Never Roll Advantage",
+ "whisp-rolls-gm:-u": "WHISPER ROLLS TO GM:",
+ "never-whisper-roll": "Never Whisper Rolls",
+ "toggle-roll-whisper": "Whisper Toggle",
+ "query-whisper-roll": "Query Whisper",
+ "always-whisper-roll": "Always Whisper Rolls",
+ "auto-dmg-roll:-u": "AUTO DAMAGE ROLL:",
+ "never-dmg": "Don't Auto Roll Damage",
+ "always-dmg": "Auto Roll Damage & Crit",
+ "npc-name-in-rolls:-u": "NPC NAME IN ROLLS:",
+ "show": "Show",
+ "hide": "Hide",
+ "add-dex-tiebreaker-u": "ADD DEX TIEBREAKER TO INITIATIVE",
+ "ac": "Armor Class",
+ "init-u": "INITIATIVE",
+ "hp": "Hit Points",
+ "speed": "Speed",
+ "saving-throw": "Saving Throws",
+ "str": "Str",
+ "dex": "Dex",
+ "con": "Con",
+ "int": "Int",
+ "wis": "Wis",
+ "cha": "Cha",
+ "skills": "Skills",
+ "acrobatics": "Acrobatics",
+ "animal_handling": "Animal handling",
+ "arcana": "Arcana",
+ "athletics": "Athletics",
+ "deception": "Deception",
+ "history": "History",
+ "insight": "Insight",
+ "intimidation": "Intimidation",
+ "investigation": "Investigation",
+ "medicine": "Medicine",
+ "nature": "Nature",
+ "perception": "Perception",
+ "performance": "Performance",
+ "persuasion": "Persuasion",
+ "religion": "Religion",
+ "sleight_of_hand": "Sleight_of_hand",
+ "stealth": "Stealth",
+ "survival": "Survival",
+ "dmg-vuln": "Damage Vulnerabilities",
+ "dmg-res": "Damage Resistances",
+ "dmg-imm": "Damage Immunities",
+ "cond-imm": "Condition Immunities",
+ "senses": "Senses",
+ "langs": "Languages",
+ "challenge": "Challenge",
+ "name:-u": "NAME:",
+ "bonus-actions": "Bonus Actions",
+ "attack-u": "ATTACK",
+ "type:-u": "TYPE:",
+ "melee": "Melee",
+ "ranged": "Ranged",
+ "range-reach:-u": "RANGE/REACH:",
+ "to-hit:-u": "TO HIT:",
+ "target:-u": "TARGET:",
+ "on-hit:-u": "ON HIT:",
+ "on-hit2:-u": "ON HIT 2:",
+ "desc:-u": "DESCRIPTION:",
+ "damage:-u": "DAMAGE:",
+ "hit:": "Hit:",
+ "actions": "Actions",
+ "reactions": "Reactions",
+ "leg-actions": "Legendary Actions",
+ "Alignment": "Alignment",
+ "Player Name": "Player Name",
+ "Class": "Class",
+ "Level": "Level",
+ "Background": "Background",
+ "Character Name": "Character Name",
+ "Race": "Race",
+ "ADVANTAGE": "ADVANTAGE",
+ "NORMAL": "NORMAL",
+ "DISADVANTAGE": "DISADVANTAGE",
+ "public": "PUBLIC",
+ "WHISPER": "WHISPER",
+ "CORE": "CORE",
+ "SPELLS & MOVES": "SPELLS & MOVES",
+ "BIO": "BIO",
+ "AC": "AC",
+ "Speed": "Speed",
+ "Initiative": "initative",
+ "Personality Traits": "Personality Traits",
+ "Ideals": "Ideals",
+ "Bonds": "Bonds",
+ "Flaws": "Flaws",
+ "Bounty": "Bounty",
+ "Hitpoints": "Hitpoints",
+ "Temporary HP": "Temporary HP",
+ "Hit Dice": "Hit Dice",
+ "Exhaustion": "Exhaustion",
+ "Knocks": "Knocks",
+ "death-saves-u": "DEATH SAVES",
+ "successes-u": "SUCCESSES",
+ "failures-u": "FAILURES",
+ "item-name-u": "ITEM NAME",
+ "equipped-u": "EQUIPPED",
+ "use-as-resource-u": "USE AS A RESOURCE",
+ "has-attack-u": "HAS AN ATTACK",
+ "prop:-u": "PROP:",
+ "mods:-u": "MODS:",
+ "total-weight-u": "TOTAL WEIGHT",
+ "Equipment": "Equipment",
+ "atk-u": "ATK",
+ "dmg-type-u": "DAMAGE/TYPE",
+ "attack:-u": "Attack:",
+ "spell-u": "SPELL",
+ "proficient-u": "PROFICIENT",
+ "range:-u": "RANGE:",
+ "magic-bonus:-u": "MAGIC BONUS:",
+ "crit-range-u": "CRIT RANGE:",
+ "crit:-u": "CRIT:",
+ "damage2:-u": "DAMAGE2:",
+ "saving-throw:-u": "SAVING THROW:",
+ "vs-dc:-u": "VS DC:",
+ "flat-u": "FLAT",
+ "save-effect:-u": "SAVE EFFECT:",
+ "ammunition:-u": "AMMUNITION:",
+ "description:-u": "DESCRIPTION:",
+ "global-attack-u": "GLOBAL ATTACK MODIFIER",
+ "roll:-u": "ROLL:",
+ "global-damage-u": "GLOBAL DAMAGE MODIFIER",
+ "dmg:-u": "Damage:",
+ "critical-dmg:-u": "CRITICAL DAMAGE:",
+ "Attacks & Spellcasting": "Attacks & Spellcasting",
+ "Proficiency Bonus": "Proficiency Bonus",
+ "strength": "Strength",
+ "dexterity": "Dexterity",
+ "constitution": "Constitution",
+ "intelligence": "Intelligence",
+ "wisdom": "Wisdom",
+ "charisma": "Charisma",
+ "Inspiration": "Inspiration",
+ "acrobatics-core": "Acrobatics (Dex)",
+ "animal_handling-core": "Animal Handling (Wis)",
+ "arcana-core": "Arcana (Int)",
+ "athletics-core": "Athletics (Str)",
+ "deception-core": "Deception (Cha)",
+ "history-core": "History (Int)",
+ "insight-core": "Insight (Wis)",
+ "intimidation-core": "Intimidation (Cha)",
+ "investigation-core": "Investigation (Int)",
+ "medicine-core": "Medicine (Wis)",
+ "nature-core": "Nature (Int)",
+ "perception-core": "Perception (Wis)",
+ "performance-core": "Performance (Cha)",
+ "persuasion-core": "Persuasion (Cha)",
+ "religion-core": "Religion (Int)",
+ "sleight_of_hand-core": "Sleight of Hand (Dex)",
+ "stealth-core": "Stealth (Dex)",
+ "survival-core": "Survival (Wis)",
+ "Passive Perception": "Passive Perception",
+ "L": "L",
+ "P": "P",
+ "S": "S",
+ "G": "G",
+ "feats-traits-u": "FEATURES & TRAITS",
+ "source:-u": "SOURCE:",
+ "racial": "Racial",
+ "class": "Class",
+ "feat": "Feat",
+ "background": "Background",
+ "other": "Other",
+ "source-type:-u": "SOURCE TYPE:",
+ "moves-u": "Moves",
+ "total": "total",
+ "current": "current",
+ "None": "None",
+ "Strength": "Strength",
+ "Dexterity": "Dexterity",
+ "Constitution": "Constitution",
+ "Intelligence": "Intelligence",
+ "Wisdom": "Wisdom",
+ "Charisma": "Charisma",
+ "Spellcasting Ability": "Spellcasting Ability",
+ "Spell Save DC": "Spell Save DC",
+ "Spell Attack Bonus": "Spell Attack Bonus",
+ "spell-ritual": "R",
+ "spell-concentration": "C",
+ "spell-component-verbal": "V",
+ "spell-component-somatic": "S",
+ "spell-component-material": "M",
+ "school:-u": "SCHOOL:",
+ "abjuration": "Abjuration",
+ "conjuration": "Conjuration",
+ "divination": "Divination",
+ "enchantment": "Enchantment",
+ "evocation": "Evocation",
+ "illusion": "Illusion",
+ "necromancy": "Necromancy",
+ "transmutation": "Transmutation",
+ "ritual-u": "RITUAL",
+ "casting-time:-u": "CASTING TIME:",
+ "components:-u": "COMPONENTS:",
+ "concentration-u": "CONCENTRATION",
+ "duration:-u": "DURATION:",
+ "innate:-u": "INNATE:",
+ "output:-u": "OUTPUT:",
+ "spellcard-u": "SPELLCARD",
+ "spell-atk:-u": "SPELL ATTACK:",
+ "none": "None",
+ "healing:-u": "HEALING:",
+ "add-ability-mod-u": "ADD ABILITY MOD TO DAMAGE OR HEALING",
+ "cantrip-progression:-u": "CANTRIP PROGRESSION",
+ "cantrip-dice-u": "CANTRIP DICE",
+ "cantrip-beam-u": "CANTRIP BEAM",
+ "effect:-u": "EFFECT:",
+ "at-higher-lvl-dmg:-u": "HIGHER LVL CAST DMG:",
+ "include_spell_desc:-u": "INCLUDE SPELL DESCRIPTION IN ATTACK:",
+ "off": "Off",
+ "partial": "Partial",
+ "on": "On",
+ "class:-u": "CLASS:",
+ "at-higher-lvl:-u": "AT HIGHER LEVELS:",
+ "Appearance": "Appearance",
+ "Build": "Build",
+ "Eyes": "Eyes",
+ "Hair": "Hair",
+ "Skin": "Skin",
+ "Misdeeds": "Misdeeds",
+ "Allies & Organizations": "Allies & Organizations",
+ "Backstory": "Backstory",
+ "Backpack": "Backpack",
+ "Notes": "Notes",
+ "hit-die:-u": "HIT DIE:",
+ "carrying-capacity-mod:-u": "CARRYING CAPACITY MODIFIER:",
+ "magic-use-lvl:-u": "MAGIC CASTER LEVEL:",
+ "class-options-u": "CLASS OPTIONS",
+ "class-name:-u": "CLASS NAME:",
+ "spellcasting-ability:-u": "SPELLCASTING ABILITY:",
+ "spell-slots:-u": "SPELL SLOTS:",
+ "spell-full-u": "FULL (Cleric, Druid, Wizard)",
+ "spell-half-u": "HALF (Artificer, Paladin, Ranger)",
+ "spell-third-u": "THIRD (Arcane Fighter/Rogue)",
+ "cust-class-opts": "CUSTOM CLASS OPTIONS",
+ "lvl-u": "LEVEL",
+ "spell_slot_modifiers-u": "SPELL SLOT MODIFIERS",
+ "initiative-mod:-u": "INITIATIVE MODIFIER:",
+ "initiative-style:-u": "INITIATIVE STYLE:",
+ "norm": "Normal",
+ "adv": "Advantage",
+ "disadv": "Disadvantage",
+ "attribute-opts-u": "ATTRIBUTE OPTIONS",
+ "strength-save-u": "STRENGTH SAVE",
+ "dexterity-save-u": "DEXTERITY SAVE",
+ "constitution-save-u": "CONSTITUTION SAVE",
+ "intelligence-save-u": "INTELLIGENCE SAVE",
+ "wisdom-save-u": "WISDOM SAVE",
+ "charisma-save-u": "CHARISMA SAVE",
+ "death-save-mod:-u": "DEATH SAVE MODIFIER:",
+ "glob-saving-mod:-u": "GLOBAL SAVING THROW MODIFIER:",
+ "save-opts-u": "SAVE OPTIONS",
+ "normal": "Normal",
+ "expertise": "Expertise",
+ "pass-perc-mod:-u": "PASSIVE PERCEPTION MODIFIER:",
+ "skill-opts-u": "SKILL OPTIONS",
+ "always-roll-adv": "Always Roll Advantage",
+ "toggle-roll-adv": "Advantage Toggle",
+ "query-roll-adv": "Query Advantage",
+ "never-roll-adv": "Never Roll Advantage",
+ "never-roll-dmg": "Don't Auto Roll Damage",
+ "always-roll-dmg": "Auto Roll Damage & Crit",
+ "core-die-roll:-u": "CORE DIE ROLL:",
+ "default-critical-range:-u": "CRITICAL RANGE:",
+ "prof-bonus:-u": "PROFICIENCY BONUS:",
+ "by-level": "By Level (Default)",
+ "prof-die": "Proficency Die (DMG)",
+ "custom": "Custom",
+ "add-char-to-templates:-u": "ADD CHARACTER NAME TO TEMPLATES:",
+ "level-calculations:-u": "LEVEL CALCULATIONS:",
+ "encumbrance:-u": "ENCUMBRANCE:",
+ "simple": "Simple",
+ "variant-phb": "Variant (PHB p176)",
+ "ingore-non-equipped-weight": "IGNORE NON-EQUIPPED ITEMS WEIGHT",
+ "inventory:-u": "INVENTORY:",
+ "compendium-compatible": "Compendium Compatible",
+ "general-opts-u": "GENERAL OPTIONS",
+ "difficulty-class-abv": "DC",
+ "save": "Save",
+ "higher-lvl-cast": "Higher Level Cast",
+ "ritual-l": "ritual-l",
+ "casting-time:": "Casting Time:",
+ "range:": "Range:",
+ "target:": "Target:",
+ "components:": "Components:",
+ "duration:": "Duration:",
+ "concentration": "Concentration",
+ "at-higher-lvl": "At Higher Levels",
+ "spell-save-dc-u": "SPELL SAVE DC",
+ "desconly": "For Description Only",
+ "npc-type-place": "Medium fiend, any evil alignment",
+ "npc-armor-place": "scale mail",
+ "npc-speed-place": "30 ft., fly 60ft.",
+ "npc-dmg-vuln-place": "fire",
+ "npc-dmg-res-place": "cold",
+ "npc-dmg-imm-place": "lighting, thunder",
+ "npc-cond-imm-place": "charmed",
+ "npc-senses-place": "darkvision 120ft., passive Perception 16",
+ "npc-langs-place": "Abyssal, Common, Infernal",
+ "npc-trait-name-place": "False Appearance.",
+ "npc-trait-desc-place": "If the dragon fails...",
+ "range-reach-place": "5 ft.",
+ "to-hit-place": "One target",
+ "on-hit-place": "slashing",
+ "on-hit-2-place": "fire",
+ "npc-repeating-name-place": "Parry.",
+ "npc-repeating-desc-place": "The creature adds 2 to its AC against...",
+ "range-place": "Self (60-foot cone)",
+ "dmg-type-place": "Slashing",
+ "save-effect-place": "half damage",
+ "ammunition-place": "Arrows",
+ "description-place": "Up to 2 creatures within 5 feet",
+ "ruby-dust-place": "ruby dust worth 50gp",
+ "half-dmg-place": "Half damage",
+ "accept-compendium-drop": "Accepting Compendium Drop",
+ "replace-sheet-with": "Do you want to replace this sheet with"
+}
\ No newline at end of file
diff --git a/COPS/COPS.css b/COPS/COPS.css
index c29cb88809..94f8899ee6 100644
--- a/COPS/COPS.css
+++ b/COPS/COPS.css
@@ -162,6 +162,7 @@ div.sheet-options > label > span
font-family:inherit;
font-size:12px;
align-items:center;
+ color:black;
}
div.sheet-options > label > select
@@ -203,6 +204,12 @@ div.sheet-options > label > select
.sheet-topHeader > div:nth-child(even) > label > span
{
font-weight:normal;
+ color:black;
+}
+
+.sheet-topHeader > div:nth-child(odd) > label > span
+{
+ color:white;
}
.sheet-topHeader > div > label
@@ -457,6 +464,7 @@ input[type="hidden"].sheet-page[value="5"] ~ div.sheet-page5
padding-left:2px;
align-items:center;
font-weight:normal;
+ color:black;
}
.sheet-ficheIdentite > label > input,
@@ -534,6 +542,7 @@ input[type="hidden"].sheet-page[value="5"] ~ div.sheet-page5
padding-left:2px;
align-items:center;
font-weight:normal;
+ color:black;
}
.sheet-ficheParcours > label > input,
@@ -746,6 +755,7 @@ input[type="hidden"].sheet-page[value="5"] ~ div.sheet-page5
.sheet-comp > div > div > div.repcontainer > div.repitem > div > label > input[type="checkbox"] ~ span
{
width:100%;
+ color:black;
}
.sheet-comp > div > div > div > label > input[type="checkbox"] ~ span::before,
@@ -1212,6 +1222,7 @@ div.sheet-armeEBonus > label > input[type="checkbox"]:checked ~ span::before
.sheet-buttonSC > label > span
{
width:100%;
+ color:black;
}
@@ -1281,6 +1292,7 @@ div.sheet-armeEBonus > label > input[type="checkbox"]:checked ~ span::before
width:100%;
justify-content:center;
align-items:center;
+ color:black;
}
.sheet-stage > div > div > div > div:nth-child(2) > label:first-of-type > input[type="text"]
@@ -1318,6 +1330,7 @@ div.sheet-armeEBonus > label > input[type="checkbox"]:checked ~ span::before
font-size:12px;
font-weight:bold;
font-family:inherit;
+ color:black;
}
.sheet-stage > div > div > div > div:not(:nth-child(2)) > label > span
@@ -1349,6 +1362,7 @@ div.sheet-armeEBonus > label > input[type="checkbox"]:checked ~ span::before
{
width:100%;
height:22px;
+ color:black;
}
.sheet-stage > div > div > div > div > label > label > span::before
@@ -1496,6 +1510,7 @@ div.sheet-armeEBonus > label > input[type="checkbox"]:checked ~ span::before
font-weight:bold;
font-family:inherit;
padding-left:2px;
+ color:black;
}
.sheet-mods > label > input[type="number"]
@@ -1563,6 +1578,7 @@ div.sheet-armeEBonus > label > input[type="checkbox"]:checked ~ span::before
{
width:100%;
height:22px;
+ color:black;
}
.sheet-initAtt > div > label > input[type="radio"],
@@ -1643,6 +1659,7 @@ div.sheet-armeEBonus > label > input[type="checkbox"]:checked ~ span::before
font-weight:bold;
font-family:inherit;
padding-left:2px;
+ color:black;
}
.sheet-bottomRight > label > input[type="number"]
@@ -1722,6 +1739,7 @@ div.sheet-armeEBonus > label > input[type="checkbox"]:checked ~ span::before
align-items:center;
font-size:12px;
padding-left:2px;
+ color:black;
}
.sheet-poursuite > label > input[type="number"]
@@ -1823,7 +1841,6 @@ div.sheet-armeEBonus > label > input[type="checkbox"]:checked ~ span::before
padding-right:2px;
}
-,
.sheet-rolltemplate-armement > div > div.sheet-spe > span:last-of-type
{
width:50%;
diff --git a/CP-Unofficial-Persona-TTRPG/crimsonparcelsupttrpg.html b/CP-Unofficial-Persona-TTRPG/crimsonparcelsupttrpg.html
index b5235898ab..ba933d008a 100644
--- a/CP-Unofficial-Persona-TTRPG/crimsonparcelsupttrpg.html
+++ b/CP-Unofficial-Persona-TTRPG/crimsonparcelsupttrpg.html
@@ -53,7 +53,7 @@
@@ -156,7 +156,7 @@
Current
Total
-
Temp.
+