WFRPv1.04

This commit is contained in:
Nic Bradley
2021-02-20 12:54:28 -08:00
parent 39f7e43285
commit 7d20a358ea
28 changed files with 864 additions and 315 deletions
@@ -0,0 +1,3 @@
.DS_Store
node_modules
package-lock.json
@@ -0,0 +1,10 @@
# wfrp4e-official
The Working Repository for the official Warhammer Fantasy Roleplay 4th Edition Character Sheet
## File Structure
This sheet is developed using NPM and compiled languages (Pug and SCSS); understanding of these technologies is required.
Dependencies are outlined in the package.json. Just use `npm install` to download them.
Start the compiles for SCSS & PUG with `npm start`.
@@ -0,0 +1,30 @@
{
"name": "wfrp4e-official",
"version": "1.0.4",
"description": "The Official sheet development for Warhammer Fantasy Roleplay 4th Edititon",
"main": "index.js",
"dependencies": {
"npm-run-all": "^4.1.5",
"pug": "^3.0.0",
"sass": "^1.32.7"
},
"devDependencies": {},
"scripts": {
"start": "npm-run-all --parallel compile:sass compile:pug",
"compile:sass": "sass src/scss/wfrp4.scss wfrp4.css --no-source-map --watch",
"compile:pug": "pug src/pug/wfrp4.pug --out . -P -w"
},
"repository": {
"type": "git",
"url": "git+https://github.com/nmbradley/wfrp4e-official.git"
},
"keywords": [
"Roll20"
],
"author": "Nic Bradley",
"license": "ISC",
"bugs": {
"url": "https://github.com/nmbradley/wfrp4e-official/issues"
},
"homepage": "https://github.com/nmbradley/wfrp4e-official#readme"
}
@@ -182,8 +182,6 @@ const wfrpDragAndDrop = ( () => {
updateAttrs[`${characteristic.replace(/ /g,"_")}_bonus`] = Math.floor(characteristics[characteristic]/10);
}
console.log(updateAttrs);
const trait_map = new Map();
for (const trait of traits) {
@@ -495,8 +493,6 @@ const wfrpDragAndDrop = ( () => {
}
getAttrs(token_values, settings => {
console.log(settings)
const default_attr = {
width: 70,
@@ -511,8 +507,6 @@ const wfrpDragAndDrop = ( () => {
getAttrs(attrs, values => {
console.log(values)
for (const item in settings) {
if (settings[item] !== "") {
default_attr[item] = settings[item];
@@ -1,3 +1,5 @@
const helperFunctions = (() => {
const extractRepeatingId = (attribute, section) => {
@@ -3,7 +3,7 @@ const wfrpModule = ( () => {
// Global Variables
const wfrp = {
sheet_version: "1.0.3",
sheet_version: "1.0.4",
characteristics: [
"weapon_skill",
@@ -96,6 +96,7 @@ const wfrpModule = ( () => {
"explosives",
"sling",
"throwing",
"azyr",
"aqshy",
"chamon",
"dhar",
@@ -104,7 +105,8 @@ const wfrpModule = ( () => {
"hysh",
"shyish",
"ulgu",
"magick"
"magick",
"custom"
],
repeating_skills: [
@@ -137,7 +139,10 @@ const wfrpModule = ( () => {
const initSheet = () => {
wfrp.characteristics.forEach(char => calculateCharacteristic(char));
wfrp.characteristics.forEach(char => {
calculateCharacteristic(char)
recalculateAttribute(`${char}_modifier`, char);
});
wfrp.skills.forEach(skill => calculateSkill(skill));
@@ -188,7 +193,7 @@ const wfrpModule = ( () => {
let slbonus = "";
if (new_value === "1") {
query = "?{Bonus|0}";
query = "?{Target Bonus|0}";
slbonus = "{{sl_bonus=?{SL Bonus|0}}}"
}
@@ -217,10 +222,10 @@ const wfrpModule = ( () => {
}
const toggleInitOption = (new_value) => {
const init = (new_value === "1") ? `{{init=[[@{initiative} &{tracker}]]}}` :
(new_value === "2") ? `{{init=[[@{initiative}+1d10 &{tracker}]]}}` :
(new_value === "3") ? `{{init=[[@{agility_bonus}+@{initiative_bonus}+1d10 &{tracker}]]}}` :
`{{init=[[@{initiative}]]}}`;
const init = (new_value === "1") ? `{{init=[[@{initiative}+@{init_bonus} &{tracker}]]}}` :
(new_value === "2") ? `{{init=[[@{initiative}+1d10+@{init_bonus} &{tracker}]]}}` :
(new_value === "3") ? `{{init=[[@{agility_bonus}+@{initiatve_bonus}+1d10+@{init_bonus} &{tracker}]]}}` :
`{{init=[[@{initiative}+@{init_bonus}]]}}`;
setAttrs({roll_init:init});
}
@@ -266,7 +271,7 @@ const wfrpModule = ( () => {
}
const recalculateAttribute = (attribute, query) => {
const attrs = [...wfrp.characteristics, ...wfrp.characteristics.map(item => `${item}_bonus`)];
const attrs = [...wfrp.characteristics, ...wfrp.characteristics.map(item => `${item}_bonus`), ...wfrp.characteristics.map(item => `${item}_custom_mod`)];
let match_array = [query];
const parsed_query = query.replace(/ /g, "_");
@@ -346,6 +351,8 @@ const wfrpModule = ( () => {
}
});
if (wfrp.characteristics.includes(query)) mod_array.push(+values[`${parsed_query}_custom_mod`]);
const new_value = mod_array.reduce((a,b) => a+b, 0);
setAttrs({[attribute]:new_value});
@@ -367,6 +374,9 @@ const wfrpModule = ( () => {
size: 0
}
if (new_value === "") {
return;
}
if (new_value === "human") {
update["fate"] = 2;
update["resilience"] = 1;
@@ -397,6 +407,12 @@ const wfrpModule = ( () => {
update["movement"] = 5;
update["size"] = "average";
}
if (new_value === "gnome") {
update["fate"] = 2;
update["resilience"] = 0;
update["movement"] = 3;
update["size"] = "small";
}
if (new_value !== "custom") {
@@ -404,15 +420,14 @@ const wfrpModule = ( () => {
const skills = helperFunctions.parseJSON(page.data.Skills);
const talents = helperFunctions.parseJSON(page.data.Talents);
let skills_fixed = [];
let talents_fixed = [];
const skills_fixed = skills.Fixed.split(",").map(item=>item.trim()) || [];
const talents_fixed = talents.Fixed.split(",").map(item=>item.trim()) || [];
let talents_choices = [];
let skill_index = 1;
let talent_index = 1;
if (skills.Fixed) skills_fixed = skills.Fixed.split(",").map(item=>item.trim());
if (talents.Fixed) talents_fixed = talents.Fixed.split(",").map(item=>item.trim());
if (talents.Choices) talents.Choices.forEach(choice => talents_choices = [...talents_choices, ...choice]);
for (let index = 1; index <= 12; index++) {
@@ -442,8 +457,10 @@ const wfrpModule = ( () => {
update[`species_talent_${talent_index}_advances`] = "0";
talent_index++;
}
update["advances_changed"] = 1;
setAttrs(update, {silent:true}, callback => calculateTalentAdvances());
setAttrs(update, {silent:true});
});
} else {
@@ -497,7 +514,7 @@ const wfrpModule = ( () => {
const initial = parseInt(values[`${characteristic}_initial`]) || 0;
const advances = parseInt(values[`${characteristic}_advances`]) || 0;
const modifier = parseInt(values[`${characteristic}_modifier`]) || 0;
const custom_mod = parseInt(values[`${characteristic}_custom_mod`]) || 0;
// const custom_mod = parseInt(values[`${characteristic}_custom_mod`]) || 0;
const bonusmod = parseInt(values[`${characteristic}_bonusmod`]) || 0;
if (values["npc"] === "on") {
@@ -513,7 +530,7 @@ const wfrpModule = ( () => {
return;
} else {
const current = initial + advances + modifier + custom_mod;
const current = initial + advances + modifier;
const bonus = Math.floor(current / 10) + bonusmod;
@@ -1167,7 +1184,7 @@ const wfrpModule = ( () => {
});
}
const calculateSkillAdvances = (skill) => {
const calculateSkillAdvances = () => {
getSectionIDs("careers", id_array => {
getSectionIDs("noncareer-skills", id_array_2 => {
@@ -1346,7 +1363,7 @@ const wfrpModule = ( () => {
const key_array = Object.keys(values).filter(item => item !== "");
let page_name = key.split("(")[0].trim() || key;
let page_name = key.trim() || key;
if (value_array_test.includes(page_name.toLowerCase())) {
const index = value_array_test.indexOf(page_name.toLowerCase());
@@ -1389,7 +1406,7 @@ const wfrpModule = ( () => {
const calculateInitColumns = (source_attribute, new_value) => {
const attrs = [];
const source_type = (source_attribute.match(/talent/g)) ? "talent" :
(source_attribute.match(/skill/g)) ? "skill" :
(source_attribute.match(/career_skill/g)) ? "skill" :
false;
const source_id = helperFunctions.extractRepeatingId(source_attribute, "careers");
const is_init = source_attribute.match(/init/);
@@ -1410,6 +1427,7 @@ const wfrpModule = ( () => {
getAttrs(attrs, values => {
const spent = Object.values(values).filter(item => item !== "").map(item => parseInt(item));
if (spent.length === 0) return;
const total = spent.reduce((a,b) => a+b) || 0;
const maximum_allowed = (source_type === "skill") ? 40 : 1;
@@ -1423,6 +1441,14 @@ const wfrpModule = ( () => {
}
const updateAdvances = () => {
wfrp.characteristics.forEach(characteristic => calculateCharacteristicAdvances(characteristic));
calculateSkillAdvances();
calculateTalentAdvances();
setAttrs({advances_changed:0});
}
// Trappings, Weapons & Armor Functions
const calculateArmour = () => {
@@ -1548,9 +1574,9 @@ const wfrpModule = ( () => {
armour_array.forEach(id => {
const worn = values[`repeating_armour_${id}_armour_worn`] || false;
const enc = parseInt(values[`repeating_armour_${id}_armour_enc`])
const total = (worn === "on") ? enc - 1 : enc || 0
const total = (enc > 0 && worn === "on") ? enc - 1 : enc || 0
total_enc += total >= 0 ? total : 0;
total_enc += total;
});
weapons_array.forEach(id => {
@@ -1565,9 +1591,9 @@ const wfrpModule = ( () => {
const worn = values[`repeating_trappings_${id}_trappings_worn`] || false;
const inenc = values[`repeating_trappings_${id}_trappings_inenc`] || "0";
const total = (worn === "on") ? (enc - 1) * amount : enc * amount;
const total = (enc > 0 && worn === "on") ? (enc - 1) * amount : enc * amount;
if (inenc === "on") total_enc += total >= 0 ? total : 0;
if (inenc === "on") total_enc += total;
});
setAttrs({encumbrance:total_enc})
@@ -1845,6 +1871,11 @@ const wfrpModule = ( () => {
"intuition",
"perception",
"cool",
"npc_dodge",
"npc_endurance",
"npc_intuition",
"npc_perception",
"npc_cool",
...wfrp.characteristics
];
@@ -1852,11 +1883,31 @@ const wfrpModule = ( () => {
if (values[`NPC`] === "0") return;
const update = {};
if (!values[`dodge`]) update[`dodge`] = values[`agility`];
if (!values[`endurance`]) update[`endurance`] = values[`toughness`];
if (!values[`intuition`]) update[`intuition`] = values[`initiative`];
if (!values[`perception`]) update[`perception`] = values[`initiative`];
if (!values[`cool`]) update[`cool`] = values[`willpower`];
const dodge = (values["dodge"]) ? values["dodge"] :
(values["npc_dodge"]) ? values["npc_dodge"] :
values["agility"];
const endurance = (values["endurance"]) ? values["endurance"] :
(values["npc_endurance"]) ? values["npc_endurance"] :
values["toughness"];
const intuition = (values["intuition"]) ? values["intuition"] :
(values["npc_intuition"]) ? values["npc_intuition"] :
values["initiative"];
const perception = (values["perception"]) ? values["perception"] :
(values["npc_perception"]) ? values["npc_perception"] :
values["initiative"];
const cool = (values["cool"]) ? values["cool"] :
(values["npc_cool"]) ? values["npc_cool"] :
values["willpower"];
update[`npc_dodge`] = dodge;
update[`npc_endurance`] = endurance;
update[`npc_intuition`] = intuition;
update[`npc_perception`] = perception;
update[`npc_cool`] = cool;
setAttrs(update);
@@ -1877,6 +1928,7 @@ const wfrpModule = ( () => {
toggleRollCrits:toggleRollCrits,
toggleInitOption:toggleInitOption,
toggleWhisper:toggleWhisper,
recalculateAttribute:recalculateAttribute,
parseModField:parseModField,
// Class and Species Controls
@@ -1891,7 +1943,6 @@ const wfrpModule = ( () => {
// Skill Functions
calculateSkill: calculateSkill,
calculateSpecialisation: calculateSpecialisation,
//updateRepeatingSkillBase: updateRepeatingSkillBase,
recalculateRepeatingSkill: recalculateRepeatingSkill,
cascadeSkillChanges:cascadeSkillChanges,
@@ -1900,18 +1951,19 @@ const wfrpModule = ( () => {
updateCurrentCareer: updateCurrentCareer,
updateCurrentCareerLevel: updateCurrentCareerLevel,
updateCareerNames: updateCareerNames,
updateFirstCareer:updateFirstCareer,
updateFirstCareer: updateFirstCareer,
// Experience Functions
calculateTotalAdvances:calculateTotalAdvances,
recalculateEarnedXP:recalculateEarnedXP,
recalculateCurrentXP:recalculateCurrentXP,
recalculateSpentXP:recalculateSpentXP,
calculateCharacteristicAdvances:calculateCharacteristicAdvances,
calculateSkillAdvances:calculateSkillAdvances,
calculateTalentAdvances:calculateTalentAdvances,
calculateTotalAdvances:calculateTotalAdvances,
calculateInitColumns:calculateInitColumns,
consolidateXP:consolidateXP,
recalculateEarnedXP:recalculateEarnedXP,
recalculateCurrentXP:recalculateCurrentXP,
recalculateSpentXP:recalculateSpentXP,
updateAdvances: updateAdvances,
// Trappings, Weapons & Armor Functions
calculateArmour:calculateArmour,
@@ -1960,7 +2012,11 @@ on(`change:setting_whisper`, eventInfo => wfrpModule.toggleWhisper(eventInfo.new
"repeating_weapon:weapon_mods",
"repeating_armour:armour_mods",
].forEach(modifier => {
on(`change:${modifier}`, eventInfo => wfrpModule.parseModField(eventInfo.newValue, eventInfo.previousValue))
on(`change:${modifier}`, eventInfo => wfrpModule.parseModField(eventInfo.newValue, eventInfo.previousValue));
});
wfrpModule.wfrp.characteristics.forEach(characteristic => {
on(`change:${characteristic}_custom_mod`, eventInfo => wfrpModule.recalculateAttribute(`${characteristic}_modifier`, characteristic));
});
// CLASS AND SPECIES CONTROLS
@@ -2012,6 +2068,8 @@ wfrpModule.wfrp.repeating_skills.forEach(section => {
// CAREERS CHANGES
on(`clicked:update_advances`, eventInfo => wfrpModule.updateAdvances());
on(`change:repeating_careers change:_reporder:careers`, eventInfo => {
if (eventInfo.sourceType === "player" && !eventInfo.sourceAttribute.match(/reporder/g)) wfrpModule.calculateTotalAdvances(eventInfo.sourceAttribute);
wfrpModule.updateCareerPath();
@@ -2044,36 +2102,34 @@ on(`change:current_xp change:spent_xp change:total_xp remove:repeating_experienc
on(`change:repeating_experience change:repeating_experiencespent change:experience_mod remove:repeating_experiencespent remove:repeating_experience`, eventInfo => wfrpModule.recalculateSpentXP());
const advance_triggers = []
wfrpModule.wfrp.characteristics.forEach(characteristic => {
on(`change:repeating_careers:career_${characteristic}_advances change:repeating_careers:career_${characteristic}_init`, eventInfo => wfrpModule.calculateCharacteristicAdvances(characteristic))
advance_triggers.push(`change:repeating_careers:career_${characteristic}_advances change:repeating_careers:career_${characteristic}_init`)
});
[1,2,3,4].forEach(level => {
[1,2,3,4,5].forEach(talent => {
on(`change:repeating_careers:career_talent_${level}_${talent}_name
change:repeating_careers:career_talent_${level}_${talent}_init
change:repeating_careers:career_talent_${level}_${talent}_advances`,
eventInfo => wfrpModule.calculateTalentAdvances());
advance_triggers.push(`change:repeating_careers:career_talent_${level}_${talent}_name change:repeating_careers:career_talent_${level}_${talent}_init change:repeating_careers:career_talent_${level}_${talent}_advances`)
});
[1,2,3,4,5,6,7,8,9,10].forEach(skill => {
on(`change:repeating_careers:career_skill_${level}_${skill}_name
change:repeating_careers:career_skill_${level}_${skill}_init
change:repeating_careers:career_skill_${level}_${skill}_advances`,
eventInfo => wfrpModule.calculateSkillAdvances());
advance_triggers.push(`change:repeating_careers:career_skill_${level}_${skill}_name change:repeating_careers:career_skill_${level}_${skill}_init change:repeating_careers:career_skill_${level}_${skill}_advances`);
});
});
for (let index = 1; index <= 12; index++) {
on(`clicked:remove_skill_${index}`, eventInfo => setAttrs({[`species_skill_${index}_advances`]:"0"}));
advance_triggers.push(`clicked:remove_skill_${index}`);
on(`change:species_skill_${index}_advances`, eventInfo => wfrpModule.calculateSkillAdvances());
advance_triggers.push(`change:species_skill_${index}_advances`);
}
for (let index = 1; index <= 10; index++) {
on(`change:species_talent_${index}_advances`, eventInfo => wfrpModule.calculateTalentAdvances())
advance_triggers.push(`change:species_talent_${index}_advances`);
};
on(advance_triggers.join(" "), eventInfo => setAttrs({advances_changed:"1"}));
on(`clicked:combinexp`, eventInfo => wfrpModule.consolidateXP());
on(`clicked:advance`, eventInfo => wfrpModule.advanceXP());
@@ -2090,7 +2146,7 @@ on(`change:repeating_careers`, eventInfo => wfrpModule.calculateInitColumns(even
on(`change:repeating_armour remove:repeating_armour`, eventInfo => wfrpModule.calculateArmour());
on(`change:repeating_trappings change:repeating_armour:armour_enc change:repeating_weapons:weapon_enc`, eventInfo => wfrpModule.calculateCurrentEncumbrance());
on(`change:repeating_trappings change:repeating_armour:armour_enc change:repeating_armour:armour_worn change:repeating_weapons:weapon_enc`, eventInfo => wfrpModule.calculateCurrentEncumbrance());
on(`change:repeating_weapons:weapon_damage_flat change:repeating_weapons:weapon_damage_bonus`, eventInfo => wfrpModule.updateWeaponDamage(eventInfo.sourceAttribute));
@@ -2122,11 +2178,9 @@ on(`change:repeating_attacks:attack_name change:repeating_attacks:attack_type`,
on(`change:weapon_skill change:ballistic_skill`, eventInfo => wfrpModule.cascadeNPCAttacks());
wfrpModule.wfrp.characteristics.forEach(characteristic => {
[...wfrpModule.wfrp.characteristics, "initiative", "dodge", "endurance", "intuition", "perception", "cool"].forEach(characteristic => {
on(`change:${characteristic} change:${characteristic}_bonus`, eventInfo => wfrpModule.updateNPCButtons())
});
on(`change:npc sheet:opened`, eventInfo => wfrpModule.updateNPCButtons());
//# sourceURL=sheetworkers.js
@@ -8,11 +8,13 @@
"name":"Species",
"field":"select",
"options":[
"",
"Human",
"Halfling",
"Dwarf",
"High Elf",
"Wood Elf",
"Gnome",
]
},
{
@@ -202,7 +204,7 @@
"characteristic":"willpower",
"type":"advanced",
"grouped":true,
"specialisations":["Aqshy","Chamon","Dhar","Ghur","Ghyran","Hysh","Shyish","Ulgu"],
"specialisations":["Azyr","Aqshy","Chamon","Dhar","Ghur","Ghyran","Hysh","Shyish","Ulgu","Custom"],
},
{
"name":"Evaluate",
@@ -31,4 +31,5 @@ include npc-skill.pug
include repeating/npc-attack-row.pug
include repeating/npc-talent-row.pug
include repeating/npc-trait-row.pug
include repeating/npc-opttrait-row.pug
include repeating/npc-opttrait-row.pug
include repeating/npc-additional-skill.pug
@@ -1,7 +1,7 @@
mixin display-toggle(attr, checked=false)
mixin display-toggle(attr, checked=false, icon="y")
label.wfrp-displaytoggle
input.wfrp-displaytoggle__hide(checked=checked, name=`attr_${attr}`, type="checkbox", value="1")
span.wfrp-displaytoggle__span y
span.wfrp-displaytoggle__span=icon
mixin trait-toggle(attr, display, checked=false)
label.wfrp-traittoggle
@@ -0,0 +1,13 @@
mixin npc-additional-skill()
.wfrp-npcsettings__skill
input.wfrp-npcsettings__input(data-i18n-placeholder="Skill Name (Specialisation)", name=`attr_npc_skillname`, type="text")
input.wfrp-npcsettings__input(name=`attr_npc_skill`, type="number")
mixin npc-additional-skill-display()
button.wfrp-npcskill(type="roll", value=rolls.npc_repeating_skill)
input(name=`attr_npc_skill`, type="hidden")
input(name=`attr_npc_skillname`, type="hidden")
.wfrp-npcskill__title
span(name=`attr_npc_skillname`)
.wfrp-npcskill__value
span(name=`attr_npc_skill`)
@@ -36,12 +36,12 @@ mixin spell-row
.wfrp-settings__label(data-i18n=`Name`)
input.wfrp-settings__input(name=`attr_spell_name`, type="text")
input(name=`attr_spell_type`, type="hidden")
input(name=`attr_spell_type`, type="hidden", value="Spell")
.wfrp-settings__row
.wfrp-settings__label(data-i18n=`Type`)
select.wfrp-settings__input(name=`attr_spell_type`)
option(value="Spell",data-i18n="Spell")
option(value="Prayer",data-i18n="Prayer")
option(value="Spell", data-i18n="Spell")
option(value="Prayer", data-i18n="Prayer")
.wfrp-settings__row.control__hide--Spell
.wfrp-settings__label(data-i18n=`Lore`)
@@ -32,14 +32,23 @@ mixin skill-grouped(skill)
-const attr = specialisation.toLowerCase().replace(/ /g,"_");
input(name=`attr_${attr}_settings`, type="hidden")
input(name=`attr_${attr}_control`, type="hidden")
.wfrp-skilltable__row--specialisation(class=`control__hide--${attr}`)
input(name=`attr_${attr}_characteristic`, type="hidden", value=char_attr)
.wfrp-skilltable__cell--settingstoggle
+display-toggle(`${attr}_settings`)
.wfrp-skilltable__cell
button(data-i18n=specialisation, name=`roll_${attr}`, type="roll", value=rolls.skills[attr])
if (specialisation === "Custom")
.wfrp-skilltable__cell
button(name=`roll_${attr}`, type="roll", value=rolls.skills[attr])
span(name=`attr_${attr}_name`)
else
.wfrp-skilltable__cell
button(data-i18n=specialisation, name=`roll_${attr}`, type="roll", value=rolls.skills[attr])
.wfrp-skilltable__cell
+characteristic-select(characteristic,`${attr}_characteristic`, true)
@@ -58,6 +67,11 @@ mixin skill-grouped(skill)
span.display(name=`attr_${attr}`)
.wfrp-skilltable_row.wfrp-settings(class=`control__hide--${attr}_settings`)
if (specialisation === "Custom")
.wfrp-settings__row--span
.wfrp-settings__label(data-i18n=`Name`)
input.wfrp-settings__input(name=`attr_${attr}_name`, type="text")
.wfrp-settings__row
.wfrp-settings__label(data-i18n=`Modifier`)
@@ -54,6 +54,9 @@
.wfrp-npcsettings__label(data-i18n=`${skill.name} (${specialism})`)
input.wfrp-npcsettings__input(name=`attr_${specialism}`, type="number")
h2(data-i18n="Additional Skills")
.wfrp-npcsettings__skills--additional
+repeating-section("npc-skills","npc-additional-skill")
h2(data-i18n="Settings")
.wfrp-npcsettings__settings
@@ -105,6 +108,10 @@
option(value="2") 1d10+I
option(value="3") 1d10+IB+AgB
.wfrp-npcsettings__row
.wfrp-npcsettings__label(data-i18n="Initiative Roll Bonus")
input.wfrp-npcsettings__input(name=`attr_init_bonus`, type="number", value="0")
.wfrp-npcsettings__row
.wfrp-npcsettings__label(data-i18n="Maximum Advantage")
input.wfrp-npcsettings__input(name="attr_setting_max_advantage", type="number")
@@ -151,6 +158,10 @@
each skill in [...skills.basic, ...skills.advanced]
+npc-skill(skill)
.wfrp-npcskill__wrapper
+repeating-section("npc-skills","npc-additional-skill-display")
.wfrp-npccombat
h2.wfrp-npc__subtitle(data-i18n="Combat")
.wfrp-npcadvantage
@@ -160,15 +171,15 @@
.wfrp-npccontrols__button
button(data-i18n="Initiative", type="roll", value=`&{template:wfrp} {{name=@{character_name}}} {{roll_name=Initiative}} @{roll_init}`)
.wfrp-npccontrols__button
button(data-i18n="Dodge", type="roll", value=rolls.combat.dodge)
button(data-i18n="Dodge", type="roll", value=rolls.combat.npc_dodge)
.wfrp-npccontrols__button
button(data-i18n="Endurance", type="roll", value=rolls.combat.endurance)
button(data-i18n="Endurance", type="roll", value=rolls.combat.npc_endurance)
.wfrp-npccontrols__button
button(data-i18n="Intuition", type="roll", value=rolls.combat.intuition)
button(data-i18n="Intuition", type="roll", value=rolls.combat.npc_intuition)
.wfrp-npccontrols__button
button(data-i18n="Perception", type="roll", value=rolls.combat.perception)
button(data-i18n="Perception", type="roll", value=rolls.combat.npc_perception)
.wfrp-npccontrols__button
button(data-i18n="Cool", type="roll", value=rolls.combat.cool)
button(data-i18n="Cool", type="roll", value=rolls.combat.npc_cool)
.wfrp-npcattack
h2.wfrp-npc__subtitle(data-i18n="Attacks")
@@ -316,6 +316,12 @@ input(name="attr_setting_button_hide", type="hidden")
+species("spells","spell-row")
.wfrp-experience--alt.page__advances--flex
input(name="attr_advances_changed", type="hidden")
.wfrp-panel.wfrp-advancenotify
span.wfrp-advancenotify__message(data-i18n="This sheet has pending advance changes. Click below to save these changes.")
button.wfrp-advancenotify__button(data-i18n="Update", name="act_update_advances", type="action")
.wfrp-panel
h1.wfrp-panel__header(data-i18n="Experience")
each field in experience
@@ -32,10 +32,10 @@
input.wfrp-settingstable__select(name=`attr_encumbrance_mod`, type="number", value="0")
.wfrp-settingstable__row
.wfrp-settingstable__label(data-i18n="Hide Control Buttons")
.wfrp-settingstable__label(data-i18n="Control Buttons")
select.wfrp-settingstable__select(name="attr_setting_button_hide")
option(data-i18n="Off", value="1")
option(data-i18n="On", value="2")
option(data-i18n="Show", value="1")
option(data-i18n="Hide", value="2")
.wfrp-settingspanel.wfrp-panel.page__settings
h1.wfrp-panel__header(data-i18n="Roll Options")
@@ -68,6 +68,10 @@
option(value="2") 1d10+I
option(value="3") 1d10+IB+AgB
.wfrp-settingstable__row
.wfrp-settingstable__label(data-i18n="Initiative Roll Bonus")
input.wfrp-settingstable__select(name=`attr_init_bonus`, type="number", value="0")
.wfrp-settingstable__row
.wfrp-settingstable__label(data-i18n="Whisper to GM")
select.wfrp-settingstable__select(name="attr_setting_whisper")
@@ -34,8 +34,6 @@
}
Object.entries(roll).forEach(([key,val]) => roll_array.push(`{{${key}=${val}}}`));
roll_array.push(`{{name=@{character_name}}}`);
return roll_array.join(" ");
}
@@ -77,10 +75,13 @@
[skills.basic[18], skills.advanced[2], skills.advanced[5], skills.advanced[11]].forEach(skill => {
skill.specialisations.forEach(specialisation => {
const attr = specialisation.toLowerCase().replace(/ /g,"_");
const rollName = (specialisation === "Custom") ? "@{custom_name}" : specialisation;
const roll_values = {
roll_name: `${skill.name} - ${specialisation}`,
roll_name: `${skill.name} - ${rollName}`,
roll_type: `Specialisation`,
roll_notes: `@{${attr}_notes}`
}
@@ -100,6 +101,16 @@
}
rolls.repeating_skill = makeRoll(roll_values, attr);
}
{
const attr = "npc_skill";
const roll_values = {
roll_name: `@{npc_skillname}`,
roll_type: `Skill`
}
rolls.npc_repeating_skill = makeRoll(roll_values, attr);
}
rolls.repeating = {};
@@ -220,4 +231,20 @@
rolls.combat[attr] = makeRoll(roll_values, attr, true, "combat")
});
rolls.npc_combat = {};
["Dodge","Endurance","Intuition","Perception","Cool"].forEach(button => {
const attr = button.toLowerCase();
const roll_values = {
roll_name: button,
roll_type: `Skill`,
roll_notes: `@{${attr}_notes}`
}
rolls.combat[`npc_${attr}`] = makeRoll(roll_values, `npc_${attr}`, true, "combat");
});
@@ -18,34 +18,38 @@
{
label: "Bonus",
value: "bonus",
type: "number",
},
{
label: "Advantage",
value: "advantage",
value: "roll_advantage",
type: "number",
},
{
label: "SL Bonus",
value: "slbonus",
value: "sl_bonus",
type: "number",
},
{
label: "CN",
value: "cn",
value: "roll_cn",
type: "number",
},
{
label: "Range",
value: "range",
value: "roll_range",
},
{
label: "Damage",
value: "damage",
value: "roll_damage",
},
{
label: "Target",
value: "target",
value: "roll_target",
},
{
label: "Duration",
value: "duration",
value: "roll_duration",
}
];
@@ -265,10 +269,12 @@ rolltemplate.sheet-rolltemplate-wfrp
+success-fail()
each field in roll_fields
+tags([`roll_${field.value}`])
.wfrp-roll__row
- const className = (field.type) ? `sheet-wfrp-roll__row--${field.type}` : ``;
+tags([field.value])
.wfrp-roll__row(class=className)
.wfrp-roll__label(data-i18n=field.label)
.wfrp-roll__value {{roll_#{field.value}}}
.wfrp-roll__value {{#{field.value}}}
+tags(["roll_hit_location"])
.wfrp-roll__row
@@ -3,7 +3,7 @@ include rolls.pug
include components/_component-index.pug
input(name="attr_sheet_version", type="hidden", value="1.0.3")
input(name="attr_sheet_version", type="hidden", value="1.0.4")
input(name="attr_npc", type="hidden", value="0")
input(name="attr_nav", type="hidden", value="main")
input(name="attr_difficulty_query", type="hidden", value="?{Difficulty|Average (+20), 20|Very Easy (+60), 60|Easy (+40), 40|Average (+20), 20|Challenging (0), 0|Difficult (-10), -10|Hard (-20), -20|Very Hard (-30), -30}")
@@ -12,7 +12,7 @@ input(name="attr_roll_query", type="hidden", value="?{Bonus|0}")
input(name="attr_roll_slbonus", type="hidden", value="{{roll_slbonus=?{SL Bonus|0}}}")
input(name="attr_roll_cf", type="hidden", value="96")
input(name="attr_roll_cs", type="hidden", value="5")
input(name="attr_roll_init", type="hidden", value="{{init=[[@{initiative} &{tracker}]]}}")
input(name="attr_roll_init", type="hidden", value="{{init=[[@{initiative}+@{initiative_bonus} &{tracker}]]}}")
input(name="attr_roll_cs", type="hidden", value="5")
input(name="attr_roll_whisper", type="hidden", value="")
@@ -51,4 +51,6 @@ script(type="text/worker")
|
include ../js/dragndrop.js
|
include ../js/helperfunctions.js
include ../js/helperfunctions.js
|
| //# sourceURL=sheetworkers.js
@@ -93,6 +93,7 @@ $specialisations:
"explosives",
"sling",
"throwing",
"azyr",
"aqshy",
"chamon",
"dhar",
@@ -101,4 +102,5 @@ $specialisations:
"hysh",
"shyish",
"ulgu",
"magick";
"magick",
"custom";
@@ -121,6 +121,10 @@
grid-template-columns: .75fr 1fr;
gap: .25rem;
&--number {
grid-template-columns: 1fr 3rem;
}
&--full {
@extend .sheet-wfrp-roll__row;
grid-template-columns: 1fr;
@@ -264,6 +264,18 @@ input[name*="settings"] {
}
}
// Update Advances Control
.sheet-wfrp-advancenotify {
display: none;
}
input[name*="advances_changed"] {
&[value="1"] + .sheet-wfrp-advancenotify {
display: block;
}
}
// NPC Settings Control
.sheet-wfrp-npcsettings__wrapper {
@@ -102,11 +102,26 @@
grid-template-columns: 1fr 1fr 1fr;
gap: $margin-large $margin-large * 2;
margin: 0 $margin-large * 3;
&--additional {
.repcontainer {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: $margin-large $margin-large * 2;
margin: 0 $margin-large * 3;
}
.repcontrol {
margin-top: $margin-general;
}
}
}
&__skill {
display: grid;
grid-template-columns: 1fr 1.5em;
grid-template-columns: 1fr 3rem;
grid-gap: $margin-small;
}
&__settings {
@@ -177,8 +192,14 @@
&__skills {
input[type="hidden"][value="0"] + button.sheet-wfrp-npcskill {
display: none;
input[type="hidden"] {
&[value="0"],
&[value=""],
&:not([value]) {
& + button.sheet-wfrp-npcskill {
display: none;
}
}
}
}
@@ -197,6 +218,10 @@
display: flex;
flex-wrap: wrap;
margin: auto;
.repcontrol {
display: none;
}
}
&__title {
@@ -69,7 +69,7 @@
&-trappings {
grid-column: 1 / span 2;
grid-row: span 6;
grid-row: span 5;
display: flex;
flex-direction: column;
@@ -197,7 +197,7 @@
}
&-weapons {
grid-column: 3 / span 4;
grid-column: 1 / span 6;
}
&-spells {
@@ -53,4 +53,21 @@
text-shadow: none;
}
button.sheet-wfrp-advancenotify__button {
display: block;
margin: 2px;
padding: $margin-general;
border-radius: 5px;
background-color: #28a745;
color: #fff;
font-family: "Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
font-size: 8pt;
font-weight: bold;
text-align: center;
}
}
@@ -3,7 +3,7 @@
border: 3px solid transparent;
border-image: url('https://s3.amazonaws.com/files.d20.io/images/144604966/Zs6TlxfYvUa6o0tD1DmW2Q/max.png?1592590034') 4 round;
border-image: url("https://s3.amazonaws.com/files.d20.io/images/144604966/Zs6TlxfYvUa6o0tD1DmW2Q/max.png?1592590034") 8 / 2 / 0 repeat;
h1 {
border-bottom: $grid-border;
@@ -1,9 +1,11 @@
{
"":"",
"Name":"Name",
"Species":"Species",
"Human":"Human",
"Halfling":"Halfling",
"Dwarf":"Dwarf",
"Gnome":"Gnome",
"Class":"Class",
"Academic":"Academic",
"Burgher":"Burgher",
@@ -55,6 +57,7 @@
"Athletics":"Athletics",
"Bribery":"Bribery",
"Channelling":"Channelling",
"Azyr":"Azyr",
"Aqshy":"Aqshy",
"Chamon":"Chamon",
"Dhar":"Dhar",
@@ -171,6 +174,7 @@
"Adv.":"Adv.",
"Total":"Total",
"Custom":"Custom",
"Custom Name":"Custom Name",
"Char.":"Char.",
"Basic Skills":"Basic Skills",
"Advanced Skills":"Advanced Skills",
@@ -286,6 +290,7 @@
"Source":"Source",
"XP":"XP",
"Controls":"Controls",
"Control Buttons":"Control Buttons",
"Critical Hit":"Critical Hit",
"Advantage":"Advantage",
"General":"General",
@@ -350,7 +355,9 @@
"TB":"TB",
"Combat":"Combat",
"Channelling (Aqshy)":"Channelling (Aqshy)",
"Channelling (Azyr)":"Channelling (Azyr)",
"Channelling (Chamon)":"Channelling (Chamon)",
"Channelling (Custom)":"Channelling (Custom)",
"Channelling (Dhar)":"Channelling (Dhar)",
"Channelling (Ghur)":"Channelling (Ghur)",
"Channelling (Ghyran)":"Channelling (Ghyran)",
@@ -384,6 +391,13 @@
"Advance Career Tier":"Advance Career Tier",
"Change Career (Incomplete)":"Change Career (Incomplete)",
"Change Career (Complete)":"Change Career (Complete)",
"Skill Name (Specialisation)":"Skill Name (Specialisation)",
"Additional Skills":"Additional Skills",
"This sheet has pending advance changes. Click below to save these changes.":"This sheet has pending advance changes. Click below to save these changes.",
"Update":"Update",
"Show":"Show",
"Hide":"Hide",
"Initiative Roll Bonus":"Initiative Roll Bonus",
"settings_npc":"NPC",
"settings_npc_desc":"The NPC option sets new characters to default to the NPC card style sheet. Useful if the player characters have already been created and all new character sheets added to the game will likely represent non player characters.",
"setting_whisper":"Whisper Rolls to GM",
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long