diff --git a/rapidfire_system/Assets/115658654-abstract-black-texture-background-hexagon-sci-fi-concept-black-and-white-3d-rendering-illustration.png b/rapidfire_system/Assets/115658654-abstract-black-texture-background-hexagon-sci-fi-concept-black-and-white-3d-rendering-illustration.png new file mode 100644 index 0000000000..515353e0b5 Binary files /dev/null and b/rapidfire_system/Assets/115658654-abstract-black-texture-background-hexagon-sci-fi-concept-black-and-white-3d-rendering-illustration.png differ diff --git a/rapidfire_system/Assets/115658654_m.jpg b/rapidfire_system/Assets/115658654_m.jpg new file mode 100644 index 0000000000..57efccfd61 Binary files /dev/null and b/rapidfire_system/Assets/115658654_m.jpg differ diff --git a/rapidfire_system/Assets/115658654_xl.jpg b/rapidfire_system/Assets/115658654_xl.jpg new file mode 100644 index 0000000000..1b1703aa32 Binary files /dev/null and b/rapidfire_system/Assets/115658654_xl.jpg differ diff --git a/rapidfire_system/Assets/Eye Corner Footer Top.png b/rapidfire_system/Assets/Eye Corner Footer Top.png new file mode 100644 index 0000000000..f76613ce15 Binary files /dev/null and b/rapidfire_system/Assets/Eye Corner Footer Top.png differ diff --git a/rapidfire_system/Assets/Eye Corner Footer.png b/rapidfire_system/Assets/Eye Corner Footer.png new file mode 100644 index 0000000000..c1ef4d58d6 Binary files /dev/null and b/rapidfire_system/Assets/Eye Corner Footer.png differ diff --git a/rapidfire_system/Assets/Eye Corner Head Bottom.png b/rapidfire_system/Assets/Eye Corner Head Bottom.png new file mode 100644 index 0000000000..799061e90c Binary files /dev/null and b/rapidfire_system/Assets/Eye Corner Head Bottom.png differ diff --git a/rapidfire_system/Assets/Eye Corner Head.png b/rapidfire_system/Assets/Eye Corner Head.png new file mode 100644 index 0000000000..448448c8ad Binary files /dev/null and b/rapidfire_system/Assets/Eye Corner Head.png differ diff --git a/rapidfire_system/Assets/Eye Corner Head.psd b/rapidfire_system/Assets/Eye Corner Head.psd new file mode 100644 index 0000000000..e44a32649d Binary files /dev/null and b/rapidfire_system/Assets/Eye Corner Head.psd differ diff --git a/rapidfire_system/Assets/Eye_Corner_Footer BR keithed.png b/rapidfire_system/Assets/Eye_Corner_Footer BR keithed.png new file mode 100644 index 0000000000..de24f04108 Binary files /dev/null and b/rapidfire_system/Assets/Eye_Corner_Footer BR keithed.png differ diff --git a/rapidfire_system/Assets/Eye_Corner_Footer keithed.png b/rapidfire_system/Assets/Eye_Corner_Footer keithed.png new file mode 100644 index 0000000000..56af7c485b Binary files /dev/null and b/rapidfire_system/Assets/Eye_Corner_Footer keithed.png differ diff --git a/rapidfire_system/Assets/Eye_Corner_header UL keithed.png b/rapidfire_system/Assets/Eye_Corner_header UL keithed.png new file mode 100644 index 0000000000..5758208fbb Binary files /dev/null and b/rapidfire_system/Assets/Eye_Corner_header UL keithed.png differ diff --git a/rapidfire_system/Assets/Eyecorner.png b/rapidfire_system/Assets/Eyecorner.png new file mode 100644 index 0000000000..405834d820 Binary files /dev/null and b/rapidfire_system/Assets/Eyecorner.png differ diff --git a/rapidfire_system/Assets/faded hex.png b/rapidfire_system/Assets/faded hex.png new file mode 100644 index 0000000000..f1a433a863 Binary files /dev/null and b/rapidfire_system/Assets/faded hex.png differ diff --git a/rapidfire_system/Assets/remnanttitle.png b/rapidfire_system/Assets/remnanttitle.png new file mode 100644 index 0000000000..09c786ff61 Binary files /dev/null and b/rapidfire_system/Assets/remnanttitle.png differ diff --git a/rapidfire_system/Assets/silhouettes.png b/rapidfire_system/Assets/silhouettes.png new file mode 100644 index 0000000000..20a5a0e12e Binary files /dev/null and b/rapidfire_system/Assets/silhouettes.png differ diff --git a/rapidfire_system/Assets/tab header.png b/rapidfire_system/Assets/tab header.png new file mode 100644 index 0000000000..e0bf5ee344 Binary files /dev/null and b/rapidfire_system/Assets/tab header.png differ diff --git a/rapidfire_system/Javascript/calculators.js b/rapidfire_system/Javascript/calculators.js new file mode 100644 index 0000000000..947d5ee5f6 --- /dev/null +++ b/rapidfire_system/Javascript/calculators.js @@ -0,0 +1,69 @@ +/*jshint esversion: 11, laxcomma:true, eqeqeq:true*/ +/*jshint -W014,-W084,-W030,-W033*/ +//Calculation Functions + +const calcInitiative = function(trigger,attributes,sections){ + debug('calculating initiative'); + let awarenessID = sections.repeating_skill.find((id)=>attributes[`repeating_skill_${id}_name`] === 'awareness'); + let awareness = attributes[`repeating_skill_${awarenessID}_level`]; + return awareness + attributes.mind + attributes.initiative_mod; +}; + +const calcDefence = function(trigger,attributes,sections){ + debug('calculating defense'); + let dodgeID = sections.repeating_skill.find((id)=>attributes[`repeating_skill_${id}_name`] === 'dodge'); + let dodge = attributes[`repeating_skill_${dodgeID}_level`]; + let damagePenalty = determinePenalty('health',attributes,sections); + let total = 3 + attributes.body + dodge + attributes.shield_bonus + damagePenalty + attributes.defence_mod; + return Math.max(total,0); +}; + +const totalHealth = function(trigger,attributes,sections){ + const type = trigger.name.replace(/_max/,''); + debug(`calculating total ${type}`); + return sections[`repeating_${type}`].reduce((total,id)=>{ + total -= attributes[`repeating_${type}_${id}_damaged`] + attributes[`repeating_${type}_${id}_fill`]; + return total; + },attributes[`${type}_max`]); +}; + +const calcResist = function(trigger,attributes,sections){ + debug('calculating resist'); + return Math.max(attributes.spirit + attributes.armour_bonus + attributes.resist_mod,0); +}; + +const calcSA = function(trigger,attributes,sections){ + debug('calculating situational awareness'); + return ['body','mind','spirit'].reduce((m,attr)=>{ + return m + attributes[attr]; + },0); +}; + +const calcRemnantInitiative = function(trigger,attributes,sections){ + debug('calculating remnant initiative'); + let awarenessID = sections.repeating_skill.find((id)=>attributes[`repeating_skill_${id}_name`] === 'awareness'); + let awareness = attributes[`repeating_skill_${awarenessID}_level`]; + let penalty = determinePenalty('structure',attributes,sections); + return attributes.situational_awareness + awareness + penalty; +}; + +const calcRemnantDefence = function(trigger,attributes,sections){ + debug('calculating remnant defence'); + let damagePenalty = determinePenalty('structure',attributes,sections); + debug({damagePenalty}); + return Math.max(attributes.speed + attributes.situational_awareness + attributes.motion_level + damagePenalty,0); +}; + +const calcStrikeRange = function(trigger,attributes,sections){ + debug('calculating strike range'); + const [section,rowID,field] = parseTriggerName(trigger.name); + let strike = section ? `${section}_${rowID}_strike` : 'strike_level'; + return attributes[strike] * 100; +}; + +const calcRemnantDamage = function(trigger,attributes,sections){ + debug('calculating remnant damage'); + let [section,rowID,field] = parseTriggerName(trigger.name); + let skill = attributes[`${section}_${rowID}_skill`]; + return attributes[`${skill}_damage`] + attributes[`${section}_${rowID}_damage_bonus`]; +}; \ No newline at end of file diff --git a/rapidfire_system/Javascript/clickfunctions.js b/rapidfire_system/Javascript/clickfunctions.js new file mode 100644 index 0000000000..5ebd4eadaa --- /dev/null +++ b/rapidfire_system/Javascript/clickfunctions.js @@ -0,0 +1,92 @@ +/*jshint esversion: 11, laxcomma:true, eqeqeq:true*/ +/*jshint -W014,-W084,-W030,-W033*/ +//Expands/collapses the sections +const expandHeader = function(jEvent){ + debug('entering expandHeader'); + const name = jEvent.htmlAttributes.name.replace(/act_/,''); + const target = `.${name}.expandable-header`; + _getAttrs(['collapsed'],(attributes)=>{ + attributes.collapsed = attributes.collapsed.split(/\s*,\s*/).filter(b => b!==name && !/^\s*$/.test(b) ); + if(!/collapse/.test(jEvent.htmlAttributes.class)){ + attributes.collapsed.push(name); + } + attributes.collapsed = attributes.collapsed.join(','); + $20(target).toggleClass('collapse'); + attributes.set(); + }); +}; + +const imageInput = function(trigger,attributes,sections){ + debug('entering imageInput'); + let [section,rowID,field] = parseTriggerName(trigger.name); + if(!field) return; + if(!attributes[field]){ + attributes[field] = 'https://s3.amazonaws.com/files.d20.io/images/259054779/OzN3yQwg7MbfXNtMYs-iOg/original.png'; + } + $20(`.${field.replace(/_/g,'-')} .image-container__input`).removeClass('active'); +}; + +const toggleImageInput = function(jEvent){ + let field = parseHTMLName(jEvent.htmlAttributes.name); + $20(`.${field.replace(/_/g,'-')} .image-container__input`).toggleClass('active'); +}; + +//Calls the appropriate dynamic query function for the event +const dynamicSelect = function(event){ + let[section,rowID,field] = parseClickTrigger(event.triggerName); + field = field.replace(/-action$/,''); + getAllAttrs({callback:async (attributes,sections)=>{ + let selection = await dynamicQueries[field]({section,rowID,field},attributes,sections); + attributes[`${section}_${rowID}_${field}`] = selection; + attributes[`${section}_${rowID}_translate_${field}`] = getTranslationByKey(selection) ? 1 : 0; + attributes.set(); + }}); +}; + +const skillQuery = function(click,attributes,sections){ + let query = sections.repeating_skill.reduce((prompt,id)=>{ + if(attributes[`repeating_skill_${id}_raw`]){ + prompt.push(`${capitalize(getTranslationByKey(attributes[`repeating_skill_${id}_name`]))},${attributes[`repeating_skill_${id}_name`]}`); + }else{ + prompt.push(capitalize(attributes[`repeating_skill_${id}_name`])); + } + return prompt; + },[`${getTranslationByKey('skill query')}`]).join('|'); + query = `${query}` + return extractQueryResult(query); +}; +//Click Functions +//These functions are fired in response to an action button being clicked. +//Clears a tracker of all damage +const clearTracker = function(event){ + debug('clearing tracker'); + let [section,rowID,field] = parseClickTrigger(event.triggerName); + getAllAttrs({callback:(attributes,sections,casc)=>{ + sections[section].forEach((id)=>{ + attributes[`${section}_${id}_damaged`] = 0; + attributes[`${section}_${id}_fill`] = 0; + }); + let attr = section.replace(/repeating_/,''); + attributes[attr] = attributes[`${attr}_max`]; + let trigger = casc[attr]; + processSheet(trigger,attributes,sections,casc); + }}); +}; + +const addItem = function(event){ + debug(`adding repeating item from ${event.triggerName}`); + let [,,section] = parseClickTrigger(event.triggerName); + section = section.replace(/add-/,''); + let rowID = generateRowID(); + const setObj = {}; + setObj[`repeating_${section}_${rowID}_name`] = ''; + set(setObj); +}; + +const editSection = function(event){ + debug(`editing repeating section from ${event.triggerName}`); + let [,,section] = parseClickTrigger(event.triggerName); + section = section.replace(/edit-/,''); + let target = `fieldset.repeating_${section} + .repcontainer`; + $20(target).toggleClass('editmode'); +}; \ No newline at end of file diff --git a/rapidfire_system/Javascript/initialchangefunctions.js b/rapidfire_system/Javascript/initialchangefunctions.js new file mode 100644 index 0000000000..b1827e3eef --- /dev/null +++ b/rapidfire_system/Javascript/initialchangefunctions.js @@ -0,0 +1,16 @@ +/*jshint esversion: 11, laxcomma:true, eqeqeq:true*/ +/*jshint -W014,-W084,-W030,-W033*/ +//Initial change functions +const syncHealth = function(trigger,attributes,sections){ + debug('syncing token and character health'); + const type = trigger.name.replace(/_max/,''); + let damage = attributes[`${type}_max`] - attributes[type]; + let damageIndex = damage - 1; + sections[`repeating_${type}`].forEach((id,index)=>{ + attributes[`repeating_${type}_${id}_damaged`] = index === damageIndex ? 1 : 0; + attributes[`repeating_${type}_${id}_fill`] = index < damageIndex ? 1 : 0; + }); + if(attributes[type] > attributes[`${type}_max`]){ + attributes[type] = attributes[`${type}_max`]; + } +}; \ No newline at end of file diff --git a/rapidfire_system/Javascript/listeners.js b/rapidfire_system/Javascript/listeners.js new file mode 100644 index 0000000000..74f31a94a5 --- /dev/null +++ b/rapidfire_system/Javascript/listeners.js @@ -0,0 +1,59 @@ +/*jshint esversion: 11, laxcomma:true, eqeqeq:true*/ +/*jshint -W014,-W084,-W030,-W033*/ +//accesses the sheet and iterates through all changes necessary before calling setAttrs +const accessSheet = function(event){ + debug({event}); + getAllAttrs({callback:(attributes,sections,casc)=>{ + let trigger = casc[event.sourceAttribute]; + processSheet(trigger,attributes,sections,casc); + }}); +}; + +const processSheet = function(trigger,attributes,sections,casc){ + debug({trigger}); + if(!trigger){ + return; + } + initialFunction(trigger,attributes,sections);//functions that should only be run if the attribute was the thing changed + triggerFunctions(trigger,attributes,sections);//functions that cause complex changes to the character + let queue = [...trigger.affects]; + while(queue.length){ + let name = queue.shift(); + debug(`processing ${name}`); + let obj = casc[name]; + triggerFunctions(obj,attributes,sections); + if(obj.calculation){ + attributes[name] = obj.calculation(obj,attributes,sections);//Basic calculation of an attribute value + } + queue = [...queue,...obj.affects]; + } + debug('sheet accessed, setting attributes'); + attributes.set(); +}; +const registerEventHandlers = function(){ + on('sheet:opened',updateSheet); + toMonitor.forEach((m)=>{ + on(`change:${m}`,accessSheet); + }); + + //Click Listeners + navButtons.forEach((button)=>{ + on(`clicked:nav-${button}`,navigateSheet); + }); + trackerMonitors.forEach((button)=>{ + on(`clicked:${button}`,clearTracker); + }); + queryButtons.forEach((button)=>{ + on(`clicked:${button}`,dynamicSelect); + }); + rollMonitor.forEach((button)=>{ + on(`clicked:${button}`,initiateRoll); + }); + repeatAddMonitors.forEach((button)=>{ + on(`clicked:add-${button}`,addItem); + on(`clicked:edit-${button}`,editSection); + }) + //jQuery listeners + $20('.expandable-header').on('click',expandHeader); + $20('.image-container__button').on('click',toggleImageInput); +}; \ No newline at end of file diff --git a/rapidfire_system/Javascript/rollfunctions.js b/rapidfire_system/Javascript/rollfunctions.js new file mode 100644 index 0000000000..b71c0caf41 --- /dev/null +++ b/rapidfire_system/Javascript/rollfunctions.js @@ -0,0 +1,178 @@ +/*jshint esversion: 11, laxcomma:true, eqeqeq:true*/ +/*jshint -W014,-W084,-W030,-W033*/ +//Roll Functions +//Begins the parsing of a roll +const skillRollDetails = function({section,rowID,sections,attributes,rollObj,actionPenalty}){ + rollObj.header = attributes[`${section}_${rowID}_name`]; + rollObj.header = attributes[`${section}_${rowID}_raw`] ? `^{${rollObj.header}}` : rollObj.header; + let skill = attributes[`${section}_${rowID}_level`]; + let stat = attributes[`${section}_${rowID}_stat`]; + let penalty = determinePenalty('health',attributes,sections); + if(stat === 'query'){ + stat = `?{${getTranslationByKey('stat query')}|${['body','mind','spirit'].map((s)=>`${getTranslationByKey(s)},@{${s}}[${s}]`).join('|')}}`; + }else{ + stat = `[[0@{${stat}}]][${stat}]`; + } + rollObj.roll = `[[1d6 + ${stat} + [[0${skill}]][${rollObj.header}] + ${penalty}[Damage Penalty]${actionPenalty}]]`; +}; + +const weaponRollDetails = function({section,rowID,field,sections,attributes,rollObj,actionPenalty}){ + rollObj.header = attributes[`${section}_${rowID}_name`]; + let skill; + let stat; + let healthType = determineHealthType(section,field); + let penalty = determinePenalty(healthType,attributes,sections); + debug({healthType,penalty}); + if(section === 'repeating_weapon'){ + let skillID = sections.repeating_skill.find((id)=>attributes[`repeating_skill_${id}_name`] === attributes[`${section}_${rowID}_skill`]); + let skillRef = `repeating_skill_${skillID}`; + skill = attributes[`${skillRef}_level`]; + stat = attributes[`${skillRef}_stat`]; + if(stat === 'query'){ + stat = `?{${getTranslationByKey('stat query')}|${['body','mind','spirit'].map((s)=>`${getTranslationByKey(s)},@{${s}}[${s}]`).join('|')}}`; + }else{ + stat = `@{${stat}}[${stat}]`; + } + rollObj.roll = `[[1d6 + ${stat} + ${skill}[${attributes[`${skillRef}_name`]}] + ${penalty}[Damage Penalty]${actionPenalty}]]`; + rollObj.damage = `[[${attributes[`${section}_${rowID}_damage`]} + Lead]]`; + }else if(section === 'repeating_remnant-weapon'){ + let skillName = attributes[`${section}_${rowID}_skill`]; + skill = attributes[`${skillName}_level`]; + stat = attributes.situational_awareness; + rollObj.roll = `[[1d6 + [[0${stat}]][SA] + [[0${skill}]][${skillName}] + [[0${attributes[`${section}_${rowID}_bonus`]}]] + ${penalty}[Damage Penalty]${actionPenalty} ]]`; + rollObj.damage = `[[${attributes[`${section}_${rowID}_damage`]+ attributes[`${section}_${rowID}_damage_bonus`]} + Lead]]`; + } + debug({roll:rollObj.roll}); + rollObj.description = `@{${section}_${rowID}_notes}`; +}; + +const droneRollDetails = async function({section,rowID,field,attributes,rollObj,actionPenalty}){ + rollObj.header = attributes[`${section}_${rowID}_name`]; + let numQuery = _.range(attributes[`${section}_${rowID}_active`]).map((num)=>{ + return num +1; + }); + let attackNum; + debug({numQuery}); + if(numQuery.length <= 1){ + attackNum = await pseudoQuery(1); + }else{ + attackNum = await extractQueryResult(`${getTranslationByKey('drone query')}|${numQuery.join('|')}`); + } + debug({attackNum}); + attackNum = +attackNum; + let bonus = Math.floor(attackNum / 2); + _.range(attackNum).forEach((n)=>{ + let num = n+1; + rollObj[`roll${num}`] = `[[1d6 + [[0@{${section}_${rowID}_${field}}]][${field}] + ${bonus}[multiple attack]${actionPenalty}]]`; + rollObj[`status${num}`] = `[[0[computed value]]]`; + }); + rollObj.damage = `[[${attributes[`${section}_${rowID}_${field}_dam`]} + Lead]]`; + rollObj.description = `@{${section}_${rowID}_description}`; + if(field === 'strike'){ + rollObj.description = `^{strike range}: @{${section}_${rowID}_strikerange}\n@{${section}_${rowID}_description}`; + } +}; + +const initiateRoll = function(event){ + let [section,rowID,field] = parseClickTrigger(event.triggerName); + field = field.replace(/-action/,''); + const rollSwitch = { + repeating_weapon:weaponRollDetails, + repeating_skill:skillRollDetails, + 'repeating_remnant-weapon':weaponRollDetails, + repeating_drone:droneRollDetails + }; + getAllAttrs({props:['difficulty','action_penalty_automation',...baseGet],callback:async (attributes,sections)=>{ + let rollObj = {status:'[[0[computed value]]]'}; + let actionPenalty = determineActionPenalty(attributes); + if(/^(?:assault|strike|motion)-roll$/.test(field)){ + let penalty = determinePenalty('structure',attributes,sections); + field = field.replace(/-roll/,''); + rollObj.header = `^{${field}}`; + rollObj.roll = `[[1d6 + [[0@{${field}_level}]][${field}] + [[0@{situational_awareness}]][SA] + ${penalty}[Damage Penalty]${actionPenalty}]]`; + rollObj.damage = /assault|strike/.test(field) ? `[[[[0@{${field}_damage}]] + Lead]]` : undefined; + }else if(!section){ + //Base rolling for simple stats + let healthType = determineHealthType(section,field); + let penalty = determinePenalty(healthType,attributes,sections); + rollObj.header = `^{${field.replace(/-/g,' ')}}`;//output translation of name + rollObj.roll = `[[1d6 + [[0@{${field.replace(/-/g,'_')}}]][${field.replace(/-/g,' ')}] + ${penalty}[Damage Penalty]${actionPenalty}${/initiative/.test(field) ? '&{tracker}' : ''}]]`; + }else{ + //rolling for more complex fields. These are typically repeating sections + if(section === 'repeating_drone'){ + await rollSwitch[section]({section,rowID,field,sections,attributes,rollObj,actionPenalty}); + }else{ + rollSwitch[section]({section,rowID,field,sections,attributes,rollObj,actionPenalty}); + } + } + if(attributes.difficulty && !/initiative/.test(field)){ + rollObj.difficulty = `[[?{${getTranslationByKey('difficulty query')}|0}]]`; + rollObj.damage_label = rollObj.damage ? undefined : '[[0[computed value]]]'; + rollObj.damage = rollObj.damage || `[[0[computed value]]]`; + } + if(!rollObj.damage && !rollObj.difficulty){ + rollObj.singleroll = 'true'; + } + executeRoll(rollObj); + }}); +}; + +const determineActionPenalty = function(attributes){ + const stateSwitch = { + disabled:'', + ask:`+ [[abs(0?{${getTranslationByKey('action penalty query')}|0}) * -1]][Action Penalty]`, + 'use input':`+ ${attributes.action_penalty}[Action Penalty]` + }; + return stateSwitch[attributes.action_penalty_automation]; +}; + +const executeRoll = async function(rollObj){ + let rollText = Object.entries(rollObj).reduce((text,[field,content])=>{ + if(content){ + text += `{{${field}=${content}}}`; + } + return text; + },'@{template_start}'); + let roll = await startRoll(rollText); + const computeObj = {}; + if(roll.results.roll1){ + computeMultipleRolls(roll.results,computeObj,rollObj); + }else{ + computeSingleRoll(roll.results,computeObj,rollObj); + } + finishRoll(roll.rollId,computeObj); +}; + +const computeMultipleRolls = function(results,computeObj,rollObj){ + let rollNums = [6,5,4,3,2,1].find((num)=>results.hasOwnProperty(`roll${num}`)); + computeObj[`damage`] = rollObj[`damage`] && rollObj.difficulty ? 0 : undefined; + _.range(rollNums).forEach((n)=>{ + let num = n + 1; + if(rollObj[`damage`] && rollObj.difficulty){ + let damage = results[`damage`].result + (results[`roll${num}`].result - results.difficulty.result); + if(damage < results[`damage`].result){ + damage = 0; + } + computeObj.damage += damage; + } + if(rollObj.difficulty){ + computeObj[`status`] = checkResult(results[`roll${num}`],results.difficulty); + } + }); +}; + +const computeSingleRoll = function(results,computeObj,rollObj){ + if(rollObj.damage && rollObj.difficulty){ + computeObj.damage = results.damage.result + (results.roll.result - results.difficulty.result); + } + if(results.damage_label){ + computeObj.damage_label = getTranslationByKey(computeObj.damage < 0 ? 'trail' : 'lead'); + } + if(rollObj.difficulty){ + computeObj[`status`] = checkResult(results[`roll`],results.difficulty); + } +}; + +const checkResult = function(roll,difficulty){ + return roll.result - difficulty.result; +}; \ No newline at end of file diff --git a/rapidfire_system/Javascript/setupfunctions.js b/rapidfire_system/Javascript/setupfunctions.js new file mode 100644 index 0000000000..bbbbaf79b9 --- /dev/null +++ b/rapidfire_system/Javascript/setupfunctions.js @@ -0,0 +1,65 @@ +/*jshint esversion: 11, laxcomma:true, eqeqeq:true*/ +/*jshint -W014,-W084,-W030,-W033*/ +/* + Sheet Styling +*/ +const navigateSheet = function(event){ + debug('navigating sheet'); + const setObj = {}; + let [,,page] = parseClickTrigger(event.triggerName); + page = page.replace(/nav-|-action/g,''); + debug({page}); + navButtons.forEach((button)=>{ + let element = button.replace(/-action/,''); + let action = element === page ? 'addClass' : 'removeClass'; + $20(`.${element}`)[action]('active'); + }); + setObj.sheet_state = page; + debug({setObj}); + set(setObj); +}; +const setupSystem = function(trigger,attributes,sections){ + setupAttributes(attributes,sections); + setupSkills(attributes,sections); + setupHealth(attributes,sections); +}; + +const setupAttributes = function(attributes,sections){ + const attrDetails = systemDefaults[attributes.system].attributes; + Object.entries(attrDetails).forEach(([attr,value])=>{ + attributes[attr] = value; + }); +}; + +const setupSkills = function(attributes,sections){ + let skillDetails = systemDefaults[attributes.system].repeating_skill.values; + let missingSkills = Object.keys(skillDetails).filter((skill)=>sections.repeating_skill.every((id)=>attributes[`repeating_skill_${id}_name`]===skill)); + missingSkills.forEach((skill)=>{ + let newID = generateRowID(); + attributes[`repeating_skill_${newID}_name`] = skill; + attributes[`repeating_skill_${newID}_stat`] = /\//.test(skillDetails[skill]) ? 'query' : skillDetails[skill]; + attributes[`repeating_skill_${newID}_raw`] = 1; + }); +}; + +const setupHealth = function(attributes,sections){ + let healthDetails = systemDefaults[attributes.system].repeating_health.values; + if(healthDetails && !sections.repeating_health.length){ + healthDetails.forEach((penalty)=>{ + let newID = generateRowID(); + attributes[`repeating_health_${newID}_penalty`] = penalty; + }); + attributes.health = healthDetails.length; + attributes.health_max = attributes.health; + } + let structureDetails = systemDefaults[attributes.system].repeating_structure.values; + if(structureDetails && !sections.repeating_structure.length){ + structureDetails.forEach((penalty)=>{ + let newID = generateRowID(); + attributes[`repeating_structure_${newID}_penalty`] = penalty; + }); + attributes.structure = structureDetails.length; + attributes.structure_max = attributes.structure; + attributes.structure_base = attributes.structure; + } +}; \ No newline at end of file diff --git a/rapidfire_system/Javascript/triggeredfunctions.js b/rapidfire_system/Javascript/triggeredfunctions.js new file mode 100644 index 0000000000..430110d3d4 --- /dev/null +++ b/rapidfire_system/Javascript/triggeredfunctions.js @@ -0,0 +1,95 @@ +/*jshint esversion: 11, laxcomma:true, eqeqeq:true*/ +/*jshint -W014,-W084,-W030,-W033*/ +// Triggered Functions +const setActionCalls = function(trigger,attributes,sections){ + debug('setting action calls'); + actionAttributes.forEach((base)=>{ + let [section,,field] = parseTriggerName(base); + let fieldAction = field.replace(/_/g,'-'); + if(section){ + sections[section].forEach((id)=>{ + attributes[`${section}_${id}_${field}`] = `%{${attributes.character_name}|${section}_${id}_${fieldAction}}`; + }); + }else{ + attributes[`${field}`] = `%{${attributes.character_name}|${fieldAction}}`; + } + }); + debug({updates:attributes.updates}); +}; + +const checkHealth = function(trigger,attributes,sections){ + debug('checking current health trackers') + let [section,rowID] = parseRepeatName(trigger.name); + let currDamage = sections[section].indexOf(rowID); + sections[section].forEach((id,index)=>{ + if(index !== currDamage){ + attributes[`${section}_${id}_damaged`] = 0; + } + attributes[`${section}_${id}_fill`] = index < currDamage ? 1 : 0; + }); +}; + +const updateTrack = function(section,attributes,sections){ + let newTracks = attributes[`${section}_max`] - sections[`repeating_${section}`].length; + if(newTracks > 0){ + _.range(newTracks).forEach((n)=>{ + let newID = generateRowID(); + let priorPenalties = sections[`repeating_${section}`].slice(Math.max(0,sections[`repeating_${section}`].length - 2)) + .map((id)=>{ + return attributes[`repeating_${section}_${id}_penalty`]; + }); + let newPenalty; + if(priorPenalties[0] !== priorPenalties[1]){ + newPenalty = priorPenalties[1] || priorPenalties[0]; + }else{ + let penStart = priorPenalties[1] || priorPenalties[0]; + newPenalty = Math.max(Math.min(-3,penStart),penStart - 1); + } + attributes[`repeating_${section}_${newID}_damaged`] = 0; + attributes[`repeating_${section}_${newID}_penalty`] = newPenalty; + sections[`repeating_${section}`].push(newID); + }); + }else if(newTracks < 0){ + let slicePoint = Math.max(0,sections[`repeating_${section}`].length + newTracks); + let extraTracks = sections[`repeating_${section}`].slice(slicePoint); + extraTracks.forEach((id)=>{ + _removeRepeatingRow(`repeating_${section}_${id}`,attributes,sections); + }); + } +}; + +const maxHealth = function(type,attributes){ + const typeSwitch = { + structure:()=> attributes.structure_base, + health:()=> 3 + attributes.body + attributes.spirit + attributes.health_mod + } + return Math.max(typeSwitch[type](),1); +}; + +const calcHealth = function(trigger,attributes,sections){ + const type = trigger.name.replace(/_max/,''); + debug(`calculating ${type}`); + attributes[`${type}_max`] = maxHealth(type,attributes); + let healthDiff = attributes[`${type}_max`] - value(attributes.attributes[`${type}_max`]); + updateTrack(type,attributes,sections); + attributes[type] = attributes[type] + healthDiff; + syncHealth(trigger,attributes,sections); +}; + +const skillEffects = function(trigger,attributes,sections){ + let [section,rowID,field] = parseRepeatName(trigger.name); + let skillName = attributes[`${section}_${rowID}_name`]; + const skillSwitch = { + dodge:['defence'], + awareness:['initiative'] + }; + if(skillSwitch[skillName]){ + trigger.affects = [...trigger.affects,...skillSwitch[skillName]]; + } +}; + +const validateActionPenalty = function(trigger,attributes,sections){ + if(attributes.action_penalty > 0){ + attributes.action_penalty = attributes.action_penalty * -1; + } +}; \ No newline at end of file diff --git a/rapidfire_system/Javascript/utility.js b/rapidfire_system/Javascript/utility.js new file mode 100644 index 0000000000..39dae7609f --- /dev/null +++ b/rapidfire_system/Javascript/utility.js @@ -0,0 +1,354 @@ +/*jshint esversion: 11, laxcomma:true, eqeqeq:true*/ +/*jshint -W014,-W084,-W030,-W033*/ +//# Attribute Obj Proxy handler +const createAttrProxy = function(attributes){ + //creates a proxy for the attributes object so that values can be worked with more easily. + const attrTarget = { + updates:{}, + attributes:{...attributes}, + repOrders:{} + }; + const attrHandler = { + get:function(obj,prop){//gets the most value of the attribute. + //If it is a repeating order, returns the array, otherwise returns the update value or the original value + if(prop === 'set'){ + return function(){ + set(obj.updates,...arguments); + } + }else if(Object.keys(obj).some(key=>key===prop)){ + return Reflect.get(...arguments) + }else{ + let retValue; + switch(true){ + case obj.repOrders.hasOwnProperty(prop): + retValue = obj.repOrders[prop]; + break; + case obj.updates.hasOwnProperty(prop): + retValue = obj.updates[prop]; + break; + default: + retValue = obj.attributes[prop]; + break; + } + let cascRef = prop.replace(/(repeating_[^_]+_)[^_]+/,'$1\$x'); + let numRetVal = +retValue; + if(!Number.isNaN(numRetVal)){ + retValue = numRetVal; + }else if(cascades[cascRef] && cascades[cascRef].type === 'number'){ + retValue = cascades[cascRef].defaultValue || 0; + } + return retValue; + } + }, + set:function(obj,prop,value){ + //Sets the value. Also verifies that the value is a valid attribute value + //e.g. not undefined, null, or NaN + if(value || value===0 || value===''){ + if(/reporder|^repeating_[^_]+$/.test(prop)){ + let section = prop.replace(/_reporder_/,''); + obj.repOrders[section] = value; + }else{ + obj.updates[prop] = value; + } + }else{ + debug(`!!!Warning: Attempted to set ${prop} to an invalid value:${value}; value not stored!!!`); + } + return true; + }, + deleteProperty(obj,prop){ + //removes the property from the original attributes, updates, and the reporders + Object.keys(obj).forEach((key)=>{ + delete obj[key][prop.toLowerCase()]; + }); + } + }; + return new Proxy(attrTarget,attrHandler); +}; + +const _setSectionOrder = function(section,order){ + let trueSection = section.replace(/repeating_/,''); + setSectionOrder(trueSection,order); +}; +const _removeRepeatingRow = function(row,attributes,sections){ + debug(`removing ${row}`); + Object.keys(attributes.attributes).forEach((key)=>{ + if(key.startsWith(row)){ + delete attributes[key]; + } + }); + let [,section,rowID] = row.match(/(repeating_[^_]+)_(.+)/,''); + sections[section] = sections[section].filter((id)=>id!==rowID); + removeRepeatingRow(row); +}; +const _getAttrs = function(props=baseGet,callback){ + getAttrs(props,(values)=>{ + const attributes = createAttrProxy(values); + callback(attributes); + }); +}; +const getAllAttrs = function({callback,props=baseGet,sectionDetails=repeatingSectionDetails}){ + getSections(sectionDetails,(repeats,sections)=>{ + getAttrs([...props,...repeats],(values)=>{ + const attributes = createAttrProxy(values); + orderSections(attributes,sections); + const casc = expandCascade(cascades,sections,attributes); + callback(attributes,sections,casc); + }) + }); +}; +const getSections = function(section_details,callback){ + let queueClone = _.clone(section_details); + const worker = (queue,repeatAttrs=[],sections={})=>{ + let detail = queue.shift(); + getSectionIDs(detail.section,(IDs)=>{ + sections[detail.section] = IDs; + IDs.forEach((id)=>{ + detail.fields.forEach((f)=>{ + repeatAttrs.push(`${detail.section}_${id}_${f}`); + }); + }); + repeatAttrs.push(`_reporder_${detail.section}`); + if(queue.length){ + worker(queue,repeatAttrs,sections); + }else{ + callback(repeatAttrs,sections); + } + }); + }; + if(!queueClone[0]){ + callback([],{}); + } + worker(queueClone); +}; +// Sets the attributes while always calling with {silent:true} +// Can be awaited to get the values returned from _setAttrs +const set = function(obj,vocal=false){ + setAttrs(obj,{silent:!vocal}); +}; +//sanitizes text for use as a regex +sanitizeForRegex = function(text){ + return text.replace(/\.|\||\(|\)|\[|\]|\-|\+|\?|\/|\{|\}|\^|\$|\*/g,'\\$&'); +}; +//converts a value to a number, it's default value, or 0 +const value = function(val,def){ + return (+val||def||0); +}; +//extracts the section, rowID, and field name from a repeating attribute name +/* +e.g. repeating_equipment_-09Jhu89z_bulk would give: +section: equipment +rowID: -09Jhu89z +field: bulk +*/ +const parseRepeatName = function(string){ + let match = string.match(/(repeating_[^_]+)_([^_]+)(?:_(.+))?/); + match.shift(); + return match; +}; + +const parseTriggerName = function(string){ + let match = string.match(/(?:(repeating_[^_]+)_([^_]+)_)?(.+)/); + match.shift(); + return match; +}; + +const parseClickTrigger = function(string){ + let match = string.match(/clicked:(?:(repeating_[^_]+)_([^_]+)_)?(.+)/); + match.shift(); + return match; +}; + +const parseHTMLName = function(string){ + let match = string.match(/(?:attr|act|roll)_(.+)/); + match.shift(); + return match[0]; +}; + +const capitalize = function(string){ + return string.replace(/(?:^|\s+|\/)[a-z]/ig,(letter)=>letter.toUpperCase()); +}; + +const extractQueryResult = async function(query){ + debug('entering extractQueryResult'); + let queryRoll = await startRoll(`!{{query=[[0[response=?{${query}}]]]}}`); + finishRoll(queryRoll.rollId); + return queryRoll.results.query.expression.replace(/^.+?response=|\]$/g,''); +}; + +const pseudoQuery = async function(value){ + debug('entering pseudoQuery'); + let queryRoll = await startRoll(`!{{query=[[0[response=${value}]]]}}`); + finishRoll(queryRoll.rollId); + return queryRoll.results.query.expression.replace(/^.+?response=|\]$/g,''); +}; + +//Determines which penalty to apply (if any) +const determinePenalty = function(type,attributes,sections){ + let damageID = sections[`repeating_${type}`].find((id)=> attributes[`repeating_${type}_${id}_damaged`] === 1); + return damageID ? attributes[`repeating_${type}_${damageID}_penalty`] : 0; +}; + +//determines which health track's penalties should affect an attribute +const determineHealthType = function(section,field){ + const attrCharacterLookup = { + 'situational-awareness':'structure', + 'remnant-initiative':'structure', + 'assault-roll':'structure', + 'strike-roll':'structure', + 'motion-roll':'structure', + repeating_drone:'structure', + 'repeating_remnant-weapon':'structure' + }; + return attrCharacterLookup[section] || attrCharacterLookup[field] || 'health'; +}; + +//# Utility Functions # +const log = function(msg){ + if(typeof msg === 'string'){ + console.log(`%c${sheetName} log| ${msg}`,"background-color:#159ccf"); + }else if(typeof msg === 'object'){ + Object.keys(msg).forEach((m)=>{ + if(typeof msg[m] === 'string'){ + console.log(`%c${sheetName} log| ${m}: ${msg[m]}`,"background-color:#159ccf"); + }else{ + console.log(`%c${sheetName} log| ${typeof msg[m]} ${m}`,"background-color:#159ccf"); + console.table(msg[m]); + } + }); + } +}; +const debug = function(msg,force){ + if(!debugMode && !force && version > 0) return; + if(typeof msg === 'string'){ + console.log(`%c${sheetName} DEBUG| ${msg}`,"background-color:tan;color:red;"); + }else if(typeof msg === 'object'){ + Object.keys(msg).forEach((m)=>{ + if(typeof msg[m] === 'string'){ + console.log(`%c${sheetName} DEBUG| ${m}: ${msg[m]}`,"background-color:tan;color:red;"); + }else{ + console.log(`%c${sheetName} DEBUG| ${typeof msg[m]} ${m}`,"background-color:tan;color:red;font-weight:bold;"); + console.table(msg[m]); + } + }); + } +}; +//Section ordering +//orders the section id arrays to match the repOrder attribute +const orderSections = function(attributes,sections){ + Object.keys(sections).forEach((section)=>{ + attributes.attributes[`_reporder_${section}`] = commaArray(attributes[`_reporder_${section}`]); + orderSection(attributes.attributes[`_reporder_${section}`],sections[section]); + }); +}; +//orders a single ID array +const orderSection = function(repOrder,IDs=[]){ + IDs.sort((a,b)=>{ + return repOrder.indexOf(a.toLowerCase()) - repOrder.indexOf(b.toLowerCase()); + }); +}; +//splits a comma delimited string into an array +const commaArray = function(string=''){ + return string.toLowerCase().split(/\s*,\s*/); +}; +//Creates a row ID specific for an add section for pseudo nested repeating sections +const generateCustomID = function(string,rowID){ + rowID = rowID || generateRowID(); + let re = new RegExp(`^.{${string.length}}`); + return `${string}${rowID.replace(re,'')}`; +}; + +//Sheet Updaters and styling functions +const updateSheet = function(){ + debug('updating sheet'); + getAllAttrs({props:['sheet_version','debug_mode','collapsed',...baseGet],callback:(attributes,sections,casc)=>{ + debugMode = !!attributes.debug_mode; + attributes.sheet_version = version; + if(!attributes.sheet_version){ + initialSetup(attributes,sections); + } + log(`Sheet Update applied. Current Sheet Version ${version}`); + styleOnOpen(attributes,sections); + setActionCalls({},attributes,sections); + attributes.set(); + log('Sheet ready for use'); + }}) +}; +const initialSetup = function(attributes,sections){ + debug('Initial sheet setup'); +}; +const styleOnOpen = function(attributes,sections){ + navigateSheet({triggerName:`clicked:${attributes.sheet_state}`}); + setupSystem({},attributes,sections); +}; + +/* +Cascade Expansion functions +*/ +//Expands the repeating section templates in cascades to reflect the rows actually available +const expandCascade = function(cascade,sections,attributes){ + return _.keys(cascade).reduce((memo,key)=>{//iterate through cascades and replace references to repeating attributes with correct row ids. + if(/^repeating/.test(key)){//If the attribute is a repeating attribute, do special logic + expandRepeating(memo,key,cascade,sections,attributes); + }else{//for non repeating attributes do this logic + expandNormal(memo,key,cascade,sections); + } + return memo; + },{}); +}; + +const expandRepeating = function(memo,key,cascade,sections,attributes){ + key.replace(/(repeating_[^_]+)_[^_]+?_(.+)/,(match,section,field)=>{ + (sections[section]||[]).forEach((id)=>{ + memo[`${section}_${id}_${field}`]=_.clone(cascade[key]);//clone the details so that each row's attributes have correct ids + memo[`${section}_${id}_${field}`].name = `${section}_${id}_${field}`; + memo[`${section}_${id}_${field}`].affects = memo[`${section}_${id}_${field}`].affects.reduce((m,affected)=>{ + if(section === affected){//otherwise if the affected attribute is in the same section, simply set the affected attribute to have the same row id. + m.push(applyID(affected,id)); + }else if(/repeating/.test(affected)){//If the affected attribute isn't in the same repeating section but is still a repeating attribute, add all the rows of that section + addAllRows(affected,m,sections); + }else{//otherwise the affected attribute is a non repeating attribute. Simply add it to the computed affected array + m.push(affected); + } + return m; + },[]); + }); + }); +}; + +const applyID = function(affected,id){ + return affected.replace(/(repeating_[^_]+_)[^_]+(.+)/,`$1${id}$2`); +}; + +const expandNormal = function(memo,key,cascade,sections){ + memo[key] = _.clone(cascade[key]); + memo[key].affects = memo[key].affects.reduce((m,a)=>{ + if(/^repeating/.test(a)){ + addAllRows(a,m,sections); + }else{ + m.push(a); + } + return m; + },[]); +}; + +const triggerFunctions = function(obj,attributes,sections){ + debug(`triggering functions for ${obj.name}`); + obj.triggeredFuncs && obj.triggeredFuncs.forEach(func=>func(obj,attributes,sections)); +}; + +const initialFunction = function(obj,attributes,sections){ + debug(`initial functions for ${obj.name}`); + obj.initialFunc && obj.initialFunc(obj,attributes,sections); +}; + +const addAllRows = function(affected,memo,sections){ + affected.replace(/(repeating_[^_]+?)_[^_]+?_(.+)/,(match,section,field)=>{ + sections[section].forEach(id=>memo.push(`${section}_${id}_${field}`)); + }); +}; + +let clickDelay = 500; +const defaultThrottle = callback => _.throttle(callback,clickDelay,{trailing:false}); +const isDieRoll = function(field){ + return /(?:d(?:8|10|12)(?:Crit)?|exertion)/.test(field); +}; \ No newline at end of file diff --git a/rapidfire_system/Javascript/variables.js b/rapidfire_system/Javascript/variables.js new file mode 100644 index 0000000000..dc85fb040a --- /dev/null +++ b/rapidfire_system/Javascript/variables.js @@ -0,0 +1,131 @@ +/*jshint esversion: 11, laxcomma:true, eqeqeq:true*/ +/*jshint -W014,-W084,-W030,-W033*/ +//Sheet Variables +const sheetName = 'Rapidfire System'; +const version = 1.0; +let debugMode = false; +//Object that defines how the attributes affect each other +const repeatingSectionDetails = [ + {section:'repeating_health',fields:['damaged','penalty','fill']}, + {section:'repeating_structure',fields:['damaged','penalty','fill']}, + {section:'repeating_skill',fields:['name','level','stat','xp','raw','roll_action']}, + {section:'repeating_weapon',fields:['name','skill','stat','translate skill','damage','notes','collapse','roll_action']}, + {section:'repeating_remnant-weapon',fields:['name','skill','bonus','damage','damage_bonus','type','notes','collapse','roll_action','notes']}, + {section:'repeating_drone',fields:['name','active','sa','collapse','def','arm','spd','struct','assault','assault_dam','strike','strike_dam','strikerange','strike_action','assault_action','description']} +]; +//const actionAttributes = ['body','mind','spirit','initiative','repeating_skill_$x_roll','repeating_weapon_$x_roll','situational_awareness','remnant_initiative','assault_roll','strike_roll','motion_roll','repeating_remnant-weapon_$x_roll','repeating_drone_$x_assault','repeating_drone_$x_strike']; +const systemDefaults = { + 'remnants':{ + repeating_skill:{field:'name',additional:true,values:{"archery / throwing":"body","athletics":"body","awareness":"mind","bureaucracy":"mind","command":"mind or spirit","craft":"body / mind / spirit","dodge":"body","etiquette":"spirit","history":"mind","investigation":"mind / spirit","language":"mind","larceny":"mind / body / spirit","lore":"mind","medicine":"mind","melee":"body","perform":"spirit","ride":"body / spirit","sail":"mind / spirit","sciences":"mind","social sciences":"mind","stealth":"body","survival":"mind","unarmed combat":"body"}}, + repeating_health:{field:'penalty',additional:true,values:[0,-1,-1],alternate:true}, + repeating_structure:{field:'penalty',additional:true,values:[0,0,-1,-1,-2],alternate:true}, + attributes:{system_header:'https://s3.amazonaws.com/files.d20.io/images/260489274/xCVgiDGF-dMYpVGKXL5UXA/original.png',armour:5,speed:3,assault_damage:4,strike_damage:2,inspiring:1,terrifying:1} + } +}; + +const cascades = { + /*template + attribute_name:{ + name:'attribute_name', + affects:['array','of','attributes','affected'], + calculation:funcCall,//Calculation for this attribute; optional property + triggeredFuncs:[func,func] + }*/ + // ## Character stats ## + character_name:{name:'character_name',type:'text',affects:[],triggeredFuncs:[setActionCalls]}, + sheet_version:{name:'sheet_version',type:'number',defaultValue:0,affects:[]}, + system:{name:'system',affects:[],triggeredFuncs:[setupSystem]}, + + //Stats + body:{name:'body',type:'number',defaultValue:0,affects:['defence','health_max','situational_awareness'],triggerdFuncs:[syncHealth]}, + mind:{name:'mind',type:'number',defaultValue:0,affects:['initiative','situational_awareness']}, + spirit:{name:'spirit',type:'number',defaultValue:0,affects:['resist','health_max','situational_awareness'],triggerdFuncs:[syncHealth]}, + + //Secondary Stats + initiative:{name:'initiative',type:'number',defaultValue:0,affects:[],calculation:calcInitiative}, + initiative_mod:{name:'initiative_mod',type:'number',defaultValue:0,affects:['initiative']}, + defence:{name:'defence',type:'number',defaultValue:3,affects:[],calculation:calcDefence}, + resist:{name:'resist',type:'number',defaultValue:0,affects:[],calculation:calcResist}, + defence_mod:{name:'defence_mod',type:'number',defaultValue:0,affects:['defence']}, + resist_mod:{name:'resist_mod',type:'number',defaultValue:0,affects:['resist']}, + health:{name:'health',type:'number',defaultValue:3,affects:['defence'],calculation:totalHealth,initialFunc:syncHealth}, + health_max:{name:'health_max',type:'number',defaultValue:3,affects:['defence'],triggeredFuncs:[calcHealth]}, + health_mod:{name:'health_mod',type:'number',defaultValue:0,affects:['health_max']}, + + //Combat Gear + armour_bonus:{name:'armour_bonus',type:'number',defaultValue:0,affects:['resist']}, + shield_bonus:{name:'shield_bonus',type:'number',defaultValue:0,affects:['defence']}, + action_penalty:{name:'action_penalty',type:'number',defaultValue:0,affects:[],triggeredFuncs:[validateActionPenalty]}, + + //Health Track + repeating_health_$x_damaged:{name:'repeating_health_$x_damaged',type:'number',defaultValue:0,affects:['health'],triggeredFuncs:[checkHealth]}, + repeating_health_$x_fill:{name:'repeating_health_$x_fill',type:'number',defaultValue:0,affects:[]}, + repeating_health_$x_penalty:{name:'repeating_health_$x_penalty',type:'number',defaultValue:0,affects:['defence']}, + + //Skills + repeating_skill_$x_level:{name:'repeating_skill_$x_level',type:'number',defaultValue:0,affects:[],triggeredFuncs:[skillEffects]}, + + // ## Remnant Attributes ## + remnant_token:{name:'structure',type:'number',defaultValue:3,affects:[],triggeredFuncs:[imageInput]}, + + //Ratings + situational_awareness:{name:'situational_awareness',type:'number',defaultValue:0,affects:['remnant_initiative','remnant_defence'],calculation:calcSA}, + remnant_defence:{name:'remnant_defence',type:'number',defaultValue:0,affects:[],calculation:calcRemnantDefence}, + remnant_initiative:{name:'remnant_initiative',type:'number',defaultValue:0,affects:[],calculation:calcRemnantInitiative}, + + //Stats + speed:{name:'speed',type:'number',defaultValue:0,affects:['remnant_defence']}, + strike_range:{name:'strike_range',type:'number',defaultValue:0,affects:[],calculation:calcStrikeRange}, + + structure:{name:'structure',type:'number',defaultValue:5,affects:['remnant_defence'],calculation:totalHealth,initialFunc:syncHealth}, + structure_base:{name:'structure_base',type:'number',defaultValue:5,affects:['structure_max']}, + structure_max:{name:'structure_max',type:'number',defaultValue:5,affects:['remnant_defence'],triggeredFuncs:[calcHealth]}, + strike_damage:{name:'strike_damage',type:'number',defaultValue:0,affects:['repeating_remnant-weapon_$x_damage']}, + assault_damage:{name:'assault_damage',type:'number',defaultValue:0,affects:['repeating_remnant-weapon_$x_damage']}, + + //Remnant Skills + strike_level:{name:'strike_level',type:'number',defaultValue:0,affects:['strike_range']}, + assault_level:{name:'assault_level',type:'number',defaultValue:0,affects:[]}, + motion_level:{name:'motion_level',type:'number',defaultValue:0,affects:['remnant_defence']}, + + //Structure Track + repeating_structure_$x_damaged:{name:'repeating_structure_$x_damaged',type:'number',defaultValue:0,affects:['structure'],triggeredFuncs:[checkHealth]}, + repeating_structure_$x_fill:{name:'repeating_structure_$x_fill',type:'number',defaultValue:0,affects:[]}, + repeating_structure_$x_penalty:{name:'repeating_structure_$x_penalty',type:'number',defaultValue:0,affects:['remnant_defence']}, + + //remnant-weapons + 'repeating_remnant-weapon_$x_damage':{name:'repeating_remnant-weapon_$x_damage',type:'number',defaultValue:0,affects:[],calculation:calcRemnantDamage}, + 'repeating_remnant-weapon_$x_skill':{name:'repeating_remnant-weapon_$x_skill',type:'text',defaultValue:'assault',affects:['repeating_remnant-weapon_$x_damage']}, + 'repeating_remnant-weapon_$x_damage_bonus':{name:'repeating_remnant-weapon_$x_damage_bonus',type:'number',defaultValue:0,affects:['repeating_remnant-weapon_$x_damage']}, + + //remnant Drones + 'repeating_drone_$x_strike':{name:'repeating_drone_$x_strike',type:'number',defaultValue:0,affects:['repeating_drone_$x_strikerange']}, + 'repeating_drone_$x_active':{name:'repeating_drone_$x_active',type:'number',defaultValue:0,affects:[]}, + 'repeating_drone_$x_strikerange':{name:'repeating_drone_$x_strikerange',type:'number',defaultValue:0,affects:[],calculation:calcStrikeRange}, +}; +const systems = ['remnants']; +const repeatMonitor = []; +//const rollMonitor = ['body-action','mind-action','spirit-action','initiative-action','situational-awareness-action','remnant-initiative-action','assault-roll-action','strike-roll-action','motion-roll-action','repeating_skill:roll-action','repeating_weapon:roll-action','repeating_drone:assault-action','repeating_drone:strike-action','repeating_remnant-weapon:roll-action']; +//const navButtons = ['character','settings','battle-remnant']; +//const repeatAddMonitors = ['skill','weapon','advantage','disadvantage','adjustment','specialty','trait','drone','remnant-weapon']; +//const queryButtons = ['repeating_weapon:skill']; +//const trackerMonitors = ['repeating_structure:clear','repeating_health:clear']; +const dynamicQueries = {skill:skillQuery}; +const baseGet = ['sheet_state','section_state','character_name']; +let toMonitor = Object.keys(cascades).reduce((m,k)=>{ + if(!/repeating/.test(k)){ + baseGet.push(k); + if(!/max/.test(k)){ + m.push(k); + } + }else if(/repeating/.test(k)){ + k.replace(/(repeating_[^_]+?)_[^_]+?_(.+)/,(match,section,field)=>{ + repeatMonitor.push(`${section}:${field}`); + }); + } + return m; +},[]); +debug({cascades,baseGet}); +toMonitor = [...toMonitor,...repeatMonitor]; +registerEventHandlers(); +log(`Sheet Loaded`); \ No newline at end of file diff --git a/rapidfire_system/Mixins/_Sheet Mixins.pug b/rapidfire_system/Mixins/_Sheet Mixins.pug new file mode 100644 index 0000000000..21343b007d --- /dev/null +++ b/rapidfire_system/Mixins/_Sheet Mixins.pug @@ -0,0 +1,42 @@ +//- File for system specific mixins +- const characterFields = ['character name','player name','nationality','organization affiliations']; +- const stats = ['body','mind','spirit']; +- const secondaries = ['defence','resist']; +- const secondaryDefaults = {defence:3,resist:0}; +- const combatGear = ['armour bonus','shield bonus','action penalty']; +- const remnantRatings = ['situational awareness','remnant defence']; +- const remnantStats = ['armour','speed','inspiring','terrifying','structure']; +- const remnantCombatStats = ['assault damage','strike damage','strike range']; +- const droneStats = ['sa','def','arm','spd','struct','assault','assault dam','strike','strike dam','strikerange']; +- const abbreviations = {'situational awareness':'situation awareness abbreviation','remnant defence':'defence','strike dam':'strike damage','assault dam':'assault damage','strikerange':'strike range',sa:'situation awareness abbreviation',def:'defence',arm:'armour',spd:'speed',struct:'structure'}; +- const remnantSkills = ['assault','strike','motion']; +- const remnantWeaponInputs = ['name','skill','bonus','damage','damage bonus','type']; +- varObjects.trackerMonitors = []; +mixin track(header,name) + .health-track + +h2({'data-i18n':header,class:'health-track__header'}) + +hidden({name:`${name} max`,value:'1',class:'health-track__max-control'}) + +fieldset(name) + +checkbox({name:'fill',hidden:'',class:'health-track__fill-control',value:'1'}) + +checkbox({name:'damaged',class:'health-track__clear-control health-track__checkbox',value:'1',title:attrTitle('health','damaged')}) + - addIfUnique(`repeating_${name}:clear`,'trackerMonitors'); + +action({name:'clear',class:'health-track__clearer',title:buttonTitle('health','clear')}) + +number({name:'penalty',class:'boxed health-track__number',title:attrTitle('health','penalty')}) +//- End Mixin +mixin hexagon(attribs={},status) + .hexagon&attributes(attributes)&attributes(attribs) + if status + +rollLess({values:`computed::${status} -2`}) + span(hidden='').fumble-toggle + +rollGreater({values:`computed::${status} 4`}) + span(hidden='').crit-toggle + .hexagon__hex-wrapper + .hexagon__hex-wrapper__hex-border + .hexagon__hex-wrapper__hex-border__hex-content + block +//-End Mixin +mixin userTemplateFields + +allProps({values:`description damage difficulty roll ${[1,2,3,4,5,6].map((num)=>`roll${num}`).join(' ')} header footer character_id system single-roll custom_description status`}) + h4 {{key}} + span {{value}} +//- End Mixin \ No newline at end of file diff --git a/rapidfire_system/Mixins/_genericplaceholders.scss b/rapidfire_system/Mixins/_genericplaceholders.scss new file mode 100644 index 0000000000..43c3ea2574 --- /dev/null +++ b/rapidfire_system/Mixins/_genericplaceholders.scss @@ -0,0 +1,658 @@ +@import url('https://fonts.googleapis.com/css?family=Bakbak+One|Oxanium:wght@700|Raleway:wght@500;600;700;800&display=swap'); +//Mixins +@mixin borderedLabel($color:black){ + color: $color; + padding: 5px; + border-radius: 5px; + border: 1px solid black; +} +@mixin selectedLabel($backColor:black, $color:white){ + background-color: $backColor; + color: $color; +} +@mixin pseudoRadio($backColor:black, $color:white){ + input:checked+label, + label:hover{ + @include selectedLabel($backColor, $color); + } +} +%font-vars{ + --topHeaderFont:Bakbak One; + --midHeaderFont:Oxanium; + --contentFont:Raleway; +} +//Placeholders +// Clears the default Roll20 styling from all elements +.ui-dialog{ + @extend %font-vars; + .tab-content .charsheet{ + select, + textarea, + input, + .uneditable-input, + label, + button{ + all: initial; + } + } +} +%stackedGrid{ + &.stacked{ + flex-direction:column-reverse; + &.center>*{ + text-align: center; + } + &:not(.center)> *{ + text-align: left; + } + > [name]{ + width:100%; + } + } +} +%inputHighlight{ + border-width: 1px 3px; + border-style: solid; + border-color: black; + border-radius: 5px; + box-sizing: border-box; + transition: var(--focusTrans); +} +%ratio1_1{ + aspect-ratio: 1/1; +} +%grid{ + display:grid; +} +%inline-grid{ + display: inline-grid; +} +%circle{ + border-radius: 50%; +} +%split{ + display:flex; + gap:var(--grid-gap); + > *{ + width:0px !important; + flex: 1 1 0; + } +} +%base-border{ + border-width: 1px 3px; + border-style: solid; + border-radius: 5px; + border-color: transparent; + box-sizing: border-box; +} +%base-button{ + background-color: #DCDCDC33; + border-radius: 5px; + box-shadow: 0 2px 4px black; + border-width: 0; + transition:{ + property:box-shadow,backdrop-filter; + duration:200ms; + timing-function:ease-out; + }; + backdrop-filter:blur(1px); + overflow:hidden; + &:is(:hover,:focus){ + background-color: #85858580; + box-shadow: 0 4px 6px black; + backdrop-filter:blur(2px); + } + &:active{ + background-color: #858585ff; + box-shadow: 0 1px 2px black; + backdrop-filter:blur(0px); + } +} + +%die-button{ + @extend %base-button; + line-height: 14px; + /*height to vertically center a 2rem dicefontd10*/ + font-size: 2rem; + font-weight: normal; + font-style: normal; + padding: 5px 3px 7px; +} + +%text-button{ + padding: 5px 7px; + @extend %base-button; +} +%adaptiveText{ + @extend %grid; + grid-template-columns: auto; + grid-template-rows: auto; + grid-template-areas: "content"; + >*{ + grid-area: content; + } + >span{ + opacity: 0; + z-index: -10; + white-space: pre-wrap; + @extend %base-border; + text-transform: initial; + } + textarea{ + resize: none; + } +} +%pictos{ + font-family: pictos; + text-transform: initial; +} +%pictos3{ + font-family: pictos three; + text-transform: initial; +} +%pictosCustom{ + font-family: pictos custom; + text-transform: initial; +} +%uppercase{ + text-transform:uppercase; +} +%roller{ + display: inline-flex; + align-items: center; + align-self:start; + gap: var(--half-gap); + &:before{ + content:'L'; + font-family:dicefontd6; + } +} +%hidden{ + display: none!important; +} +%italics{ + font-style: italic; +} +%baseText{ + line-height: normal; +} +%baseHeader{ + @extend %baseText; + color:black; + display: block; + white-space: nowrap; + margin-top: 0px; + margin-bottom: 0px; + font-weight:normal; +} +%importantHeader{ + text-transform: uppercase; + font-weight: normal; +} +%midHeader{ + &:not(input){ + text-transform:capitalize; + } +} +%h1-style{ + @extend %baseHeader; + @extend %importantHeader; + font-size: 2rem; + font-family: var(--topHeaderFont); + &:not(input){ + text-align: center; + } +} +%h1{ + @extend %h1-style; + *{ + @extend %h1-style; + } +} +%h2-style{ + @extend %baseHeader; + @extend %importantHeader; + font-size: 1.75rem; + font-family: var(--topHeaderFont); + grid-area:header; + &:not(input){ + text-align: center; + } +} +%h2{ + @extend %h2-style; + *{ + @extend %h2-style; + } +} +%h3-style{ + @extend %baseHeader; + @extend %importantHeader; + font-size: 1.5rem; + font-family: var(--topHeaderFont); + &:not(input){ + text-align: center; + } +} +%h3{ + @extend %h3-style; + *{ + @extend %h3-style; + } +} +%h4-style{ + @extend %baseHeader; + @extend %midHeader; + font-size: 1.25rem; + font-family: var(--midHeaderFont); + &:not(input){ + text-align: center; + } +} +%h4{ + @extend %h4-style; + *{ + @extend %h4-style; + } +} +%h5-style{ + @extend %baseHeader; + @extend %midHeader; + font-size: 1rem; + font-style:normal; + font-family: var(--midHeaderFont); + &:not(input){ + text-align: center; + } +} +%h5{ + @extend %h5-style; + *{ + @extend %h5-style; + } +} +%contents{ + display:contents; +} +%checked{ + background-color: var(--selectedColor); +} +%boxed{ + border: 1px solid black; + border-radius:0; + box-sizing:border-box; +} +//- Default styles +%defaultStyles{ + --grid-gap: 1rem; + --half-gap: calc(var(--grid-gap) / 2); + --tiny-gap: calc(var(--half-gap) / 2); + --big-gap: calc(var(--grid-gap) * 2); + --revealTime: 500ms; + --delayTime: 200ms; + --inputSwap: opacity var(--revealTime) ease var(--delayTime); + --focusTiming: 500ms ease; + --focusTrans: all var(--focusTiming); + --borderColor: black; + --fontColor: black; + --backColor: #ffffff; + --spanSectionColumn:1/-1; + --displayBorderWidth: 2px; + --subHeadBackColor:grey; + --unselectedColor:lightgrey; + --selectedColor:black; + //Images + --topCorner:url('https://s3.amazonaws.com/files.d20.io/images/258525471/MZYT-HjOvfJOqUXufyBkww/original.png'); + --bottomCorner:url('https://s3.amazonaws.com/files.d20.io/images/258525472/d7gSQyNdXW4tfBUa3osltQ/original.png'); + --headerBottom:url('https://s3.amazonaws.com/files.d20.io/images/258525865/9moWl3pE8miL8gqQC2UPRw/original.png'); + --footerTop:url('https://s3.amazonaws.com/files.d20.io/images/258525864/dzZKV6kH_fltY8yH9D-ptA/original.png'); + position: relative; + gap: var(--grid-gap); + button{ + cursor: pointer; + } + textarea{ + resize: vertical; + min-height: 3.5rem; + white-space: pre-wrap; + &.fixed{ + resize: none; + overflow: auto; + } + } + .span-2{ + grid-column:span 2; + } + .span-all{ + grid-column:1/-1; + } + select, + .pseudo-select span, + textarea, + input:not(:is([type='radio'],[type='checkbox'])), + .uneditable-input{ + padding: 2px; + font-size:1rem; + } + input:is([type="text"],[type="number"]),textarea{ + cursor:auto; + } + select, + .pseudo-select span, + input:not(:where([type='checkbox'], [type='radio'])), + .uneditable-input, + textarea{ + @extend %base-border; + } + select, + .pseudo-select span{ + -webkit-apperance: none; + appearance: none; + text-transform: capitalize; + overflow: hidden!important; + white-space: nowrap; + text-overflow: ellipsis; + text-align: center; + } + input{ + width: auto; + &:placeholder{ + color: #ededed80; + } + &.plus-control:not([value*="-"])+span:before{ + content: '+'; + } + } + span, + input, + textarea{ + font-size: 1rem; + @extend %baseText; + } + span,input,textarea,button,select{ + font-family:var(--contentFont); + --fontWght: 600; + font-weight: var(--fontWght); + font-variation-settings: "wght" var(--fontWght); + } + .hidden, + *[hidden]{ + @extend %hidden; + } + .italics{ + @extend %italics; + } + h1, + *[aria-level='1']{ + @extend %h1; + } + h2, + *[aria-level='2']{ + @extend %h2; + } + h3, + *[aria-level='3']{ + @extend %h3; + } + h4, + *[aria-level='4']{ + @extend %h4; + } + h5, + *[aria-level='5']{ + @extend %h5; + } + input{ + &[type='checkbox']{ + align-self: center; + border: 1px solid black; + cursor: pointer; + &:checked{ + @extend %checked; + } + } + &[type='radio']{ + appearance: radio; + } + &[type='number']{ + width: 3rem; + -moz-appearance: textfield !important; + text-align: center; + &::-webkit-inner-spin-button, + &::-webkit-outer-spin-button{ + -webkit-appearance: none; + margin: 0; + } + } + } + .number{ + width:2rem; + box-sizing:border-box; + } + section{ + @extend %grid; + gap:var(--half-gap); + align-self:start; + &.page{ + display: none; + } + &.inactive{ + display:none !important; + } + } + .pictos{ + @extend %pictos; + } + .pictos3{ + @extend %pictos3; + } + .pictoscustom{ + @extend %pictosCustom; + } + .pseudo-button{ + display: inline; + cursor: pointer; + border-radius: 5px; + text-transform: uppercase; + border: 1px solid black; + text-align: center; + padding: 0 5px; + } + .input-label{ + display: inline-flex; + gap: var(--half-gap); + align-items:center; + @extend %stackedGrid; + &:not(.stacked){ + > [name]:not([type="number"],[type="checkbox"],[type='radio']){ + width:0; + flex:1 1 0; + } + >:not([name]){ + flex:0 0 auto; + } + &.large > [name]{ + @extend h2; + } + } + } + .input-label--dual{ + grid-template-columns: 1fr auto 1fr; + grid-template-areas: 'over over over' 'under under under'; + >span:last-of-type{ + grid-column: 1 / -1; + } + >input{ + width: 100%; + } + >.slash{ + line-height: 0rem; + font-weight: normal; + } + } + .headed-textarea{ + @extend %grid; + grid-template-rows: auto 1fr; + grid-template-columns: auto; + h5{ + justify-self: start; + } + } + .contents, + .sheet-contents{ + @extend %contents; + } + .boxed, + .sheet-boxed{ + @extend %boxed; + &.thick-left{ + border-left-width: 5px; + } + &.thick-bottom{ + border-bottom-width: 5px; + } + &.thick-right{ + border-right-width: 5px; + } + &.thick-top{ + border-top-width: 5px; + } + } + .underlined, + .sheet-underlined{ + border-radius: 0; + border-bottom: 1px solid black; + transition: var(--focusTrans); + } + :is(.underlined,.boxed){ + &:not([readonly]):is(:hover, :focus,:focus-within){ + @extend %inputHighlight; + } + &:not([readonly]):is(:focus,:focus-within){ + background-color: #DCDCDC; + transition: var(--focusTrans); + } + } + .ratio1-1{ + @extend %ratio1_1; + } + .small-scale-grid, + fieldset.small-scale-grid+.repcontainer{ + @extend %grid; + grid-template-columns: [header-start]repeat(auto-fit, minmax(15rem, 1fr))[header-end]; + grid-template-rows: [header-start]auto[header-end]; + gap: var(--half-gap); + >.repitem{ + display: flex; + gap: var(--half-gap); + > :is(.dot-row,input[type='text']){ + flex: 1 1 0; + width: 100%; + } + } + .repcontrol_move{ + display: none; + } + } + .short-text{ + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + text-transform: initial; + } + .roll-container{ + @extend %grid; + align-self:center; + opacity:0; + grid-row:1 / 2; + } + .repitem{ + > input:not([type='checkbox']){ + width:100%; + } + .headed-textarea{ + grid-column:1/-1; + } + .collapse{ + opacity:0; + position:absolute; + right:-10px; + top:0px; + border:0px solid black; + border-radius:0; + color:var(--selectedColor); + text-transform:none; + &:before{ + content:'y'; + font-family:pictos; + } + &:checked{ + background-color:transparent; + color:var(--unselectedColor); + ~ .expanded{ + display:none; + } + ~ .expanded--empty:is(:not([value]),[value='']) + *{ + display:none + } + } + &:hover{ + color:var(--selectedColor); + } + } + &:hover{ + .collapse,.roll-container{ + opacity:1; + } + } + } + .repcontainer.editmode{ + .collapse{ + display:none; + } + } + .repcontainer{ + display:grid; + row-gap:var(--grid-gap); + } + .repeating-container{ + &:is(:hover,:focus-within,:focus) .repcontrol-button{ + opacity:1; + } + } + .repcontrol-button{ + @extend %text-button; + grid-area:header; + align-self:center; + text-transform:none; + opacity:0; + transition:opacity var(--revealTime); + ~ .repcontrol{ + display:none; + } + } + .repcontrol-button--add{ + justify-self:start; + &:before{ + font-family:pictos; + content:'&'; + } + } + .repcontrol-button--edit{ + justify-self:end; + &:before{ + font-family:pictos; + content:'p'; + } + } + .box{ + border-radius:0; + width:10px; + height:10px; + } +} +#main{ + .uppercase{ + @extend %uppercase; + } +} \ No newline at end of file diff --git a/rapidfire_system/Mixins/_htmlelements.pug b/rapidfire_system/Mixins/_htmlelements.pug new file mode 100644 index 0000000000..bb57e10460 --- /dev/null +++ b/rapidfire_system/Mixins/_htmlelements.pug @@ -0,0 +1,400 @@ + +//- Element shortcut mixins +- const varObjects = {}; +mixin input(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + - obj.name = replaceSpaces(obj.name); + - obj.title = obj.title || attrTitle(obj.name); + - obj.name = `attr_${obj.name}`; + input&attributes(obj) +//-End Mixin +mixin text(obj) + -obj.type = 'text'; + +input(obj) +//-End Mixin +mixin checkbox(obj) + -obj.type = 'checkbox'; + +input(obj) +//-End Mixin +mixin radio(obj) + -obj.type = 'radio'; + +input(obj) +//-End Mixin +mixin number(obj) + -obj.type = 'number'; + +input(obj) +//-End Mixin +mixin range(obj) + -obj.type = 'range'; + +input(obj) +//-End Mixin +mixin hidden(obj) + -obj.type = 'hidden'; + +input(obj) +//-End Mixin +mixin radioGroup(objArray) + each obj in objArray + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + - obj.type='radio'; + +input(obj) +//-End Mixin +mixin textarea(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + - obj.name = replaceSpaces(obj.name); + - obj.title = obj.title || attrTitle(obj.name); + - obj.name = `attr_${obj.name}`; + textarea&attributes(obj) +//-End Mixin +mixin option(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + option&attributes(obj) + block +//-End Mixin +mixin select(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + - obj.name = replaceSpaces(obj.name); + - obj.title = obj.title || attrTitle(obj.name); + - obj.name = `attr_${obj.name}`; + select&attributes(obj) + if block + block + else + +option({value:'empty select, PEBKAC',selected:true}) +//-End Mixin +mixin img(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + - obj['data-i18n-alt'] = obj['data-i18n-alt'] || obj.name; + - obj.name = replaceSpaces(obj.name); + - obj.title = obj.title || attrTitle(obj.name); + - obj.name = `attr_${obj.name}`; + img&attributes(obj) +//-End Mixin +mixin span(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + if obj.name + - obj.name = replaceSpaces(obj.name); + - obj.title = obj.title || attrTitle(obj.name); + - obj.name = `attr_${obj.name}`; + span&attributes(obj) + block +//-End Mixin +mixin datalist(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + datalist&attributes(obj) + block +//-End Mixin +mixin div(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + if obj.name + - obj.name = replaceSpaces(obj.name); + - obj.title = obj.title || attrTitle(obj.name); + - obj.name = `attr_${obj.name}`; + div&attributes(obj) + block +//-End Mixin +mixin h1(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + h1&attributes(obj) + block +//-End Mixin +mixin h2(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + h2&attributes(obj) + block +//-End Mixin +mixin h3(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + h3&attributes(obj) + block +//-End Mixin +mixin h4(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + h4&attributes(obj) + block +//-End Mixin +mixin h5(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + h5&attributes(obj) + block +//-End Mixin +mixin h6(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + h6&attributes(obj) + block +//-End Mixin +mixin p(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + p&attributes(obj) + block +//-End Mixin +mixin button(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + - obj.name = replaceSpaces(obj.name); + - obj.title = obj.title || `%{${obj.name}}`; + if obj.type === 'action' + - obj.name = `act_${obj.name}`; + else + - obj.type = 'roll'; + - obj.name = `roll_${obj.name}`; + button&attributes(obj) + block +//-End Mixin +mixin action(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + - obj.type = 'action'; + - obj.name = obj.name.replace(/\s+/g,'-'); + +button(obj) + block +//- End Mixin +mixin navButton(obj) + -obj.name = `nav ${obj.name}`; + +action(obj) + block + - let actionTitle = obj.title.replace(/(repeating_[^_]+_).+/,`$1:${actionName}`).replace(/%{|}|nav-/g,''); + - addIfUnique(actionTitle,'navButtons'); +//- End Mixin +mixin actionQuery(obj) + -obj.class = obj.class ? `${obj.class} pseudo-select` : 'pseudo-select'; + +action(obj) + block + - let actionTitle = obj.title.replace(/(repeating_[^_]+).+/,`$1:${actionButtonName(obj.name)}`).replace(/%{|}/g,''); + - addIfUnique(actionTitle,'queryButtons'); +//- End Mixin +mixin rollerExtras(obj) + - obj.class = obj.class ? `${replaceProblems(obj.class)} roller` : 'roller'; + - let attrName = replaceSpaces(actionInputName(obj.name)); + - let actionName = actionButtonName(obj.name); + - obj.value = `@{${attrName}}`; + !=`` + block + !=`` + - let actionTitle = /repeating/.test(obj.title) ? obj.title.replace(/(repeating_[^_]+).+/,`$1:${actionName}`).replace(/%{|}/g,'') : actionName; + - actionTitle = `${actionTitle.replace(/-action$/,'')}-action`; + - let attrTitle = `${obj.title.replace(/(repeating_[^_]+_).+/,`$1\$x_${attrName}`).replace(/%{|}/g,'').replace(/_action$/,'')}_action`; + !=`` + - addIfUnique(actionTitle,'rollMonitor'); + - addIfUnique(attrTitle,'actionAttributes'); + +action({name:actionName,hidden:''}) + +hidden({name:attrName}) +//- End Mixin +mixin roller(obj) + +rollerExtras(obj) + +button(obj) + block +mixin section(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + section&attributes(obj) + block +//-End Mixin +mixin main(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + main&attributes(obj) + block +//-End Mixin +mixin header(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + header&attributes(obj) + block +//-End Mixin +mixin footer(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + footer&attributes(obj) + block +//-End Mixin +mixin details(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + details&attributes(obj) + block +//-End Mixin +mixin summary(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + summary&attributes(obj) + block +//-End Mixin +mixin label(obj) + - obj.class = obj.class ? replaceProblems(obj.class) : undefined; + label&attributes(obj) + block +//-End Mixin +mixin repeating_section(name,header,columnArr,id) + section(class=`repeating-container--${name} repeating-container section` id=`${(id||name).replace(/\s+/g,'-')}`) + if header + h2(data-i18n=header) + if columnArr + .repeat-columns + each head in columnArr + h5(data-i18n=head) + +customControlFieldset(name) + block +mixin customControlFieldset(name) + - addIfUnique(name.replace(/\s+/g,'-'),'repeatAddMonitors'); + +action({name:`add ${name}`,class:'repcontrol-button repcontrol-button--add'}) + +action({name:`edit ${name}`,class:'repcontrol-button repcontrol-button--edit'}) + +fieldset(name) + block +mixin fieldset(name) + - name = name.replace(/\s+/g,'-'); + fieldset(class=`repeating_${name}`) + block +//-End Mixin +mixin pseudo-button(label,inputObj) + - inputObj.class = inputObj.class ? replaceProblems(inputObj.class) : undefined; + - hiddenObj = inputObj; + - hiddenObj.type = 'hidden'; + +input(hiddenObj) + label.pseudo-button + -inputObj.class = inputObj.class ? `${inputObj.class} pseudo-button__input` : 'pseudo-button__input'; + span(data-i18n=label class='pseudo-button__span') + +input(inputObj) +//-End Mixin +mixin button-label(inputObj,buttonObj,divObj) + if divObj + - divObj.class = divObj.class ? replaceProblems(divObj.class) : undefined; + - inputObj.class = inputObj.class ? replaceProblems(inputObj.class) : undefined; + - buttonObj.class = buttonObj.class ? replaceProblems(buttonObj.class) : undefined; + - inputObj.name = inputObj.name.replace(/\s+/g,'_'); + - buttonObj.name = (buttonObj.name || inputObj.name).replace(/\s+/g,'_'); + .input-label.input-label--button&attributes(divObj) + - inputObj.class = inputObj.class ? `${inputObj.class} input-label__input` : 'input-label__input'; + if spanObj + - buttonObj.class = buttonObj.class ? `${buttonObj.class} input-label__text` : 'input-label__text'; + +button(buttonObj) + +input(inputObj) +//-End Mixin +mixin roller-label(inputObj,buttonObj,divObj) + +rollerExtras(buttonObj) + +button-label(inputObj,buttonObj,divObj) +//-End Mixin +mixin action-label(inputObj,buttonObj,divObj) + - buttonObj.type = 'action'; + +button-label(inputObj,buttonObj,divObj) +//-End Mixin +mixin select-label(label,inputObj,divObj,spanObj) + if divObj + - divObj.class = divObj.class ? replaceProblems(divObj.class) : undefined; + if inputObj + - inputObj.class = inputObj.class ? replaceProblems(inputObj.class) : undefined; + if spanObj + - spanObj.class = spanObj.class ? replaceProblems(spanObj.class) : undefined; + label.input-label&attributes(divObj) + - inputObj.name = inputObj.name.replace(/\s+/g,'_'); + - inputObj.class = inputObj.class ? `${inputObj.class} input-label__input` : 'input-label__input'; + if spanObj + - spanObj.class = spanObj.class ? `${spanObj.class} input-label__text` : 'input-label__text'; + span(data-i18n=label)&attributes(spanObj) + +select(inputObj) + block +//-End Mixin +mixin input-label(label,inputObj,divObj,spanObj) + if divObj + - divObj.class = divObj.class ? replaceProblems(divObj.class) : undefined; + if inputObj + - inputObj.class = inputObj.class ? replaceProblems(inputObj.class) : undefined; + if spanObj + - spanObj.class = spanObj.class ? replaceProblems(spanObj.class) : undefined; + label.input-label&attributes(divObj) + - inputObj.name = inputObj.name.replace(/\s+/g,'_'); + - inputObj.class = inputObj.class ? `${inputObj.class} input-label__input` : 'input-label__input'; + if spanObj + - spanObj.class = spanObj.class ? `${spanObj.class} input-label__text` : 'input-label__text'; + span(data-i18n=label)&attributes(spanObj) + +input(inputObj) +//-End Mixin +mixin dual-input-label(label,inputArr,divObj,spanObj) + if divObj + - divObj.class = divObj.class ? replaceProblems(divObj.class) : undefined; + if spanObj + - spanObj.class = spanObj.class ? replaceProblems(spanObj.class) : undefined; + .input-label.input-label--dual&attributes(divObj) + span(data-i18n=label)&attributes(spanObj) + each inputObj,i in inputArr + if inputObj + - inputObj.class = inputObj.class ? replaceProblems(inputObj.class) : undefined; + - inputObj.name = inputObj.name.replace(/\s+/g,'_'); + +input(inputObj) + if i<1 + span(class='slash h2')='/' +//-End Mixin +mixin headedTextarea(obj,header) + .headed-textarea&attributes(attributes) + - obj.class = obj.class ? `${obj.class} headed-textarea__textarea` : 'headed-textarea__textarea'; + +h3({'data-i18n':header,class:'headed-textarea__header'}) + +textarea(obj) +//-End Mixin +mixin script() + script(type='text/worker') + block +//-End Mixin +mixin pseudoEdit(name) + +action({name:`edit-${name}`,class:'repcontrol-edit','data-i18n-title':`edit section`}) +//- End Mixin +mixin pseudoAdd(name,content) + - let obj = {name:`add-${name}`,class:'repcontrol-add','data-i18n-title':`create a ${name}`}; + if content + - obj['data-i18n'] = content; + +action(obj) +//- End Mixin +mixin pseudoControl(name) + .pseudo-control + +pseudoAdd(name) + +pseudoEdit(name) +//- End Mixin +mixin pseudoCollapse(attrName,labelObj) + +hidden({name:attrName,value:'0',class:'collapse-control'}) + -labelObj.class = labelObj.class ? `${labelObj.class} collapse-interface`:'collapse-interface'; + +label(labelObj) + +checkbox({name:attrName,value:'1',hidden:''}) +//- End Mixin +mixin expandHeader(obj) + - obj.role='heading'; + - obj['aria-level'] = obj['aria-level'] || 2; + - obj.class = obj.class ? `${obj.class} expandable-header ${obj.name}` : `${replaceSpaces(obj.name)} expandable-header`; + - obj['data-i18n-title'] = obj['data-i18n-title'] || 'collapse/expand the section'; + +action(obj) + if !obj['data-i18n'] + block +//- End Mixin +mixin subsectionContent(attribs) + .display-target&attributes(attribs) + if value!=='add-detail' + - collapseTitle; + if value==='master' + -collapseTitle = 'collapse/expand section'; + else if /short/.test(value) + - collapseTitle = 'expand subsection'; + else + - collapseTitle = 'collapse subsection'; + +pseudoCollapse('collapse',{'data-i18n-title':collapseTitle}) + block +mixin subsection(value) + +radio({name:'display state',value,class:'display-control',hidden:''}) + +subsectionContent(attributes) + block +//- End Mixin +mixin complexSubsection(def) + +hidden({name:'display state',value:def,class:'expanded-control'}) + +subsectionContent(attributes) + block +//- End Mixin +mixin adaptiveTextarea(textObj) + .adaptive-text&attributes(attributes) + - let spanObj = {name:textObj.name,class:'adaptive-text__span'}; + - textObj.class = textObj.class ? `${textObj.class} adaptive-text__textarea` : 'adaptive-text__textarea'; + +span(spanObj) + +textarea(textObj) +//- Functions +- const attrTitle = (string,section) => section ? repeatAttrTitle(string,section) : `@{${replaceSpaces(string).replace(/_max$/,'|max')}}`; +- const buttonTitle = (string,section) => section ? repeatButtonTitle(string,section) : `%{${replaceSpaces(string)}}`; +- const replaceSpaces = (string) => string.replace(/\s+/g,'_'); +- const replaceProblems = (string) => string.replace(/[\(\)\[\]\|\/\\]/g,'-'); +- const repeatAttrTitle = (section,attr) => `@{repeating_${section}_$X_${replaceSpaces(attr).replace(/_max$/,'|max')}}`; +- const repeatButtonTitle = (section,attr) => `%{repeating_${section}_$X_${replaceSpaces(attr||'roll')}}`; +- const actionButtonName = (name) => `${name.replace(/act_/,'').replace(/_|\s+/g,'-').replace(/-action$/,'')}-action`; +- const actionInputName = (name) => `${name}_action`; +- + const addIfUnique = (item,arrName) => { + varObjects[arrName] = varObjects[arrName] || []; + if(varObjects[arrName].indexOf(item) === -1){ + varObjects[arrName].push(item); + } + }; \ No newline at end of file diff --git a/rapidfire_system/Mixins/_rolltemplate mixins.pug b/rapidfire_system/Mixins/_rolltemplate mixins.pug new file mode 100644 index 0000000000..4a39e3d6ad --- /dev/null +++ b/rapidfire_system/Mixins/_rolltemplate mixins.pug @@ -0,0 +1,85 @@ +//-Roll Template Mixins to be included in Sheet files +mixin rolltemplate(name) + rolltemplate(class=`sheet-rolltemplate-${name}`) + div(class=`template ${name} system-{{system}}`) + block + div(class='image-border{{#header}} has-header{{/header}}{{#footer}} has-footer{{/footer}}') +mixin multiPartTemplate(name) + rolltemplate(class=`sheet-rolltemplate-${name}`) + +templateHelperFunction({func:'rollTotal',invert:true,values:'computed::finished 0'}) + div(class=`template ${name} system-{{system}}{{#continuation}} continuation{{/continuation}}{{#first}} first{{/first}} finished`) + block + +templateHelperFunction({func:'rollBetween',values:'computed::finished 0 0'}) + div(class=`template ${name} system-{{system}}{{#continuation}} continuation{{/continuation}}{{#first}} first{{/first}}`) + block +//- End Mixin +mixin characterLink() + +templateConditionalDisplay('footer') + .footer + .footer__background.background + +templateConditionalDisplay('character_id') + h4(tabindex='-1').character_name [{{footer}}](http://journal.roll20.net/character/{{character_id}}) + +templateConditionalDisplay('character_id',true) + h4(tabindex='-1').character_name {{footer}} + .footer__content + +templateConditionalDisplay('character_id') + h4.character_name [{{footer}}](http://journal.roll20.net/character/{{character_id}}) + +templateConditionalDisplay('character_id',true) + h4.character_name {{footer}} + .footer__image +//-End mixin +mixin templateBase(name) + - name = name.replace(/\s+/g,'_'); + +rolltemplate(name) + +characterLink() + block +//-End mixin +mixin templateConditionalDisplay(fieldBool,invert) + !=`{{${invert ? '^' : '#'}${fieldBool}}}` + block + !=`{{/${fieldBool}}}` +//- End mixin +mixin templateHelperFunction(helperObj) + !=`{{${helperObj.invert ? '#^':'#'}${helperObj.func ? `${helperObj.func}() `:''}${helperObj.values ? `${helperObj.values}` : ''}}}` + block + !=`{{/${(helperObj.invert) ? '^' : ''}${helperObj.func ? `${helperObj.func}() `:''}${helperObj.values}}}` +//- End Mixin +mixin rollWasCrit(helperObj) + - helperObj.func = 'rollWasCrit'; + +templateHelperFunction(helperObj) + block +//- End Mixin +mixin rollWasFumble(helperObj) + - helperObj.func = 'rollWasFumble'; + +templateHelperFunction(helperObj) + block +//- End Mixin +mixin rollTotal(helperObj) + - helperObj.func = 'rollTotal'; + +templateHelperFunction(helperObj) + block +//- End Mixin +mixin rollGreater(helperObj) + - helperObj.func = 'rollGreater'; + +templateHelperFunction(helperObj) + block +//- End Mixin +mixin rollLess(helperObj) + - helperObj.func = 'rollLess'; + +templateHelperFunction(helperObj) + block +//- End Mixin +mixin rollBetween(helperObj) + - helperObj.func = 'rollBetween'; + +templateHelperFunction(helperObj) + block +//- End Mixin +mixin allProps(helperObj) + - helperObj.func = 'allprops'; + +templateHelperFunction(helperObj) + block +//- End Mixin +mixin templateField(name) + != `${tField(name)}` +//- End Mixin +- const tField = name => `{{${name}}}`; \ No newline at end of file diff --git a/rapidfire_system/Mixins/_rolltemplate.scss b/rapidfire_system/Mixins/_rolltemplate.scss new file mode 100644 index 0000000000..65b243c234 --- /dev/null +++ b/rapidfire_system/Mixins/_rolltemplate.scss @@ -0,0 +1,76 @@ +/* +Roll Template +#rolltemplate +*/ + +.sheet-rolltemplate-storypath{ + --templateRadius: 1rem; + --dieSize: 50px; + --templateBorderW: 2px 5px 2px 5px; + --fumbleColor: red; + --critColor: green; + --innerBorderRadius: 5px; + --borderSize:1px; + margin:{//ensures that the template fills the chat window + left: -40px; + right: -5px; + } + &:not(:first-child){//Moves the template to accomodate the sender tag + margin-top:10px; + } + > .sheet-template{ + overflow:hidden; + span{ + font-size:13px; + } + } + .inlinerollresult{ + position: relative; + &[title*="[computed value]"], + &[original-title*="[computed value]"]{ + pointer-events: none; + } + &, + &.fullcrit, + &.fullfail, + &.importantroll{ + border: none; + background-color: transparent; + } + &.fullcrit{ + color: green; + } + &.fullfail{ + color: red; + } + &.importantroll{ + color: blue; + } + } + .sheet-header{ + padding: 5px; + display:grid; + grid-template-columns:1fr 2rem 1fr; + gap:var(--half-gap); + .sheet-character_name{ + grid-column:1/-1; + place-self:center end; + } + .sheet-title{ + grid-column:1/-1; + place-self:center; + } + } + .sheet-template-row{ + padding: 5px; + @extend %grid; + grid-template-columns: minmax(6em, 1fr) repeat(auto-fit, minmax(1rem, 1fr)); + place-items: center; + &:nth-child(odd){ + background-color: lightgrey; + } + >*:first-child{ + place-self: center start; + } + } +} \ No newline at end of file diff --git a/rapidfire_system/Mixins/_systemplaceholders.scss b/rapidfire_system/Mixins/_systemplaceholders.scss new file mode 100644 index 0000000000..1ddc79fabd --- /dev/null +++ b/rapidfire_system/Mixins/_systemplaceholders.scss @@ -0,0 +1,124 @@ +@forward '_genericplaceholders.scss'; +@mixin activeTab{ + --tabBorder:drop-shadow(1px 0 0 black) drop-shadow(-1px 0 0 black) drop-shadow(0 -1px 0 black); + top:1px; + color:black; +} +.ui-dialog .tab-content .charsheet{ + *[data-i18n='xp']{ + text-transform:uppercase; + } + .stat-grid{ + gap:var(--half-gap) var(--tiny-gap); + > :not(input):not(h2){ + place-self:center end; + } + } + .boxed.span-2{ + @extend %grid; + grid-auto-flow: column; + place-content:center; + width:6.5rem; + } + .roll-plus{ + justify-self: center; + } + .health-track{ + .repcontainer{ + @extend %grid; + grid-template-columns:repeat(auto-fill,2rem); + row-gap:var(--tiny-gap); + &:hover{ + .health-track__clearer{ + background-image:linear-gradient(45deg, transparent 0% 48%, white 48% calc(48% + 1px), transparent calc(48% + 1px)), linear-gradient(-45deg, transparent 0% 48%, white 48% calc(48% + 1px), transparent calc(48% + 1px)); + } + } + > .repitem{ + @extend %grid; + grid-template:{ + columns:2rem; + rows:repeat(2,2rem); + areas: + 'check' + 'penalty' + ; + } + &:first-child{ + .itemcontrol{ + display:none !important; + } + } + .repcontrol_move{ + display:none !important; + } + } + } + .repcontrol{ + display:none; + } + } + .health-track__max-control[value="1"] ~ .repcontrol .repcontrol_edit{ + display:none; + } + .health-track__number{ + &:is(:hover,:focus){ + border-radius:0; + } + } + .health-track__checkbox{ + border-radius:0; + width:100%; + height:100%; + box-sizing:border-box; + grid-area:check; + } + .health-track__clear-control:not(:checked) ~ .health-track__clearer{ + display:none; + } + .health-track__fill-control{ + &:checked + *{ + @extend %checked; + } + } + .health-track__clearer{ + grid-area:check; + button{ + width:100%; + height:100%; + } + } +} +%hex-base{ + @extend %grid; + overflow:hidden; + grid-template-areas:'content'; +} +%hex-component{ + @extend %hex-base; + width:100%; + height:100%; + grid-area:content; +} +%hex-rotate{ + @extend %hex-component; + transform:rotate(-60deg); +} +%hex-shape{ + box-sizing:border-box; + content:''; + box-shadow:0 0 0 1px black inset, 0 0 4px #ffffff inset; +} +%article-layout{ + @extend %grid; + gap:var(--big-gap); + &.system-remnant{ + grid-template-columns:repeat(auto-fill,minmax(280px,1fr)); + } +} +%repeat-section-layout{ + @extend %grid; + grid-template-areas:"header"; + gap:var(--half-gap); + align-self:start; +} +// End Placeholders \ No newline at end of file diff --git a/rapidfire_system/prepros.config b/rapidfire_system/prepros.config new file mode 100644 index 0000000000..cde9c70bb2 --- /dev/null +++ b/rapidfire_system/prepros.config @@ -0,0 +1,930 @@ +{ + "version": "7", + "about": "This is a Prepros (https://prepros.io) configuration file. You can commit this file to a git repo to backup and sync project configurations.", + "config": { + "proxy": { + "enable": false, + "target": "", + "useLocalAssets": false + }, + "reload": { + "enable": true, + "delay": 0, + "animate": true, + "afterUpload": false + }, + "sync": { + "enable": false, + "mouse": true, + "keyboard": true, + "form": true, + "scroll": true + }, + "watcher": { + "enable": true, + "maxFiles": 2000, + "usePolling": false, + "pollingInterval": 500, + "extensions": [ + ".html", + ".htm", + ".php" + ], + "ignore": { + "patterns": [ + ".*", + "wp-admin", + "wp-includes", + "node_modules", + "Prepros Export", + "bower_components" + ], + "exceptions": [] + } + }, + "exporter": { + "ignore": { + "patterns": [ + ".*", + "desktop.ini", + "prepros.cfg", + "node_modules", + "Prepros Export", + "prepros.config", + "prepros-6.config", + "*-original.jpg", + "*-original.jpeg", + "*-original.png", + "*-original.svg", + "*.scss", + "*.sass", + "*.less", + "*.pug", + "*.jade", + "*.styl", + "*.haml", + "*.slim", + "*.coffee", + "*.kit", + "*.turf", + "*.ts" + ], + "exceptions": [] + } + }, + "uploader": { + "remotePath": "", + "timeout": 20000, + "autoUpload": false, + "reuseConnection": true, + "connectionType": "ftp", + "history": [] + }, + "packages": { + "createPackageLock": true + }, + "images": { + "preserveOriginal": true + }, + "tasks": { + "autoprefixer": { + "cascade": true, + "add": true, + "remove": true, + "supports": true, + "flexbox": true, + "grid": "autoplace", + "browsers": [ + "last 2 versions" + ], + "sourceMap": false + }, + "babel": { + "sourceMap": false, + "presets": { + "@babel/preset-env": { + "enable": true, + "options": { + "targets": [ + "last 2 versions" + ], + "preserveImports": false, + "polyfills": false + } + }, + "@babel/preset-react": true, + "@babel/preset-flow": false + }, + "plugins": { + "@babel/plugin-proposal-class-static-block": false, + "@babel/plugin-proposal-class-properties": false, + "@babel/plugin-proposal-decorators": { + "enable": false, + "options": { + "decoratorsBeforeExport": true + } + }, + "@babel/plugin-proposal-export-namespace-from": false, + "@babel/plugin-proposal-function-sent": false, + "@babel/plugin-proposal-logical-assignment-operators": false, + "@babel/plugin-proposal-nullish-coalescing-operator": false, + "@babel/plugin-proposal-numeric-separator": false, + "@babel/plugin-proposal-optional-chaining": false, + "@babel/plugin-proposal-private-methods": false, + "@babel/plugin-proposal-throw-expressions": false + }, + "customPresets": [], + "customPlugins": [] + }, + "bundle-js": { + "sourceMap": false, + "exclude": [ + "node_modules", + "bower_components" + ], + "devMode": true, + "globals": [], + "externals": [], + "babel": { + "enable": true, + "options": { + "sourceMap": false, + "presets": { + "@babel/preset-env": { + "enable": true, + "options": { + "targets": [ + "last 2 versions" + ], + "preserveImports": false, + "polyfills": false + } + }, + "@babel/preset-react": true, + "@babel/preset-flow": false + }, + "plugins": { + "@babel/plugin-proposal-class-static-block": false, + "@babel/plugin-proposal-class-properties": false, + "@babel/plugin-proposal-decorators": { + "enable": false, + "options": { + "decoratorsBeforeExport": true + } + }, + "@babel/plugin-proposal-export-namespace-from": false, + "@babel/plugin-proposal-function-sent": false, + "@babel/plugin-proposal-logical-assignment-operators": false, + "@babel/plugin-proposal-nullish-coalescing-operator": false, + "@babel/plugin-proposal-numeric-separator": false, + "@babel/plugin-proposal-optional-chaining": false, + "@babel/plugin-proposal-private-methods": false, + "@babel/plugin-proposal-throw-expressions": false + }, + "customPresets": [], + "customPlugins": [] + } + }, + "css": { + "enable": true + }, + "fonts": { + "enable": true + } + }, + "coffeescript": { + "header": false, + "bare": false, + "sourceMap": false + }, + "command": { + "command": "", + "rootDir": "" + }, + "concat-js": { + "sourceMap": false, + "rootDir": "" + }, + "copy": { + "sourceMap": false + }, + "dart-sass": { + "indentType": "space", + "allowWildcardImports": false, + "indentWidth": 2, + "linefeed": "lf", + "sourceMap": false + }, + "haml": { + "doubleQuoteAttributes": true + }, + "jpg": { + "quality": 90 + }, + "less": { + "javascriptEnabled": false, + "strictImports": false, + "insecure": false, + "math": "always", + "strictUnits": false, + "dumpLineNumbers": false, + "sourceMap": false + }, + "markdown": { + "githubFlavored": true, + "wrapWithHtml": false + }, + "minify-css": { + "sourceMap": false + }, + "minify-html": { + "caseSensitive": false, + "collapseBooleanAttributes": true, + "collapseInlineTagWhitespace": false, + "collapseWhitespace": true, + "conservativeCollapse": false, + "decodeEntities": false, + "html5": true, + "includeAutoGeneratedTags": true, + "keepClosingSlash": false, + "minifyCSS": true, + "minifyJS": true, + "preserveLineBreaks": false, + "preventAttributesEscaping": false, + "processConditionalComments": false, + "removeAttributeQuotes": false, + "removeComments": true, + "removeEmptyAttributes": false, + "removeEmptyElement": false, + "removeOptionalTags": false, + "removeRedundantAttributes": false, + "removeScriptTypeAttributes": false, + "removeStyleLinkTypeAttributes": false, + "removeTagWhitespace": false, + "sortAttributes": false, + "sortClassName": false, + "useShortDoctype": true + }, + "minify-js": { + "parse": { + "bare_returns": false + }, + "compress": { + "arrows": true, + "arguments": false, + "booleans": true, + "booleans_as_integers": false, + "collapse_vars": true, + "comparisons": true, + "computed_props": true, + "conditionals": true, + "dead_code": true, + "directives": true, + "drop_console": false, + "drop_debugger": true, + "evaluate": true, + "expression": false, + "global_defs": [], + "hoist_funs": false, + "hoist_props": true, + "hoist_vars": false, + "if_return": true, + "inline": 3, + "join_vars": true, + "keep_fargs": true, + "keep_infinity": false, + "loops": true, + "negate_iife": true, + "properties": true, + "pure_funcs": [], + "pure_getters": false, + "reduce_funcs": true, + "reduce_vars": true, + "sequences": true, + "side_effects": true, + "switches": true, + "top_retain": [], + "typeofs": true, + "unsafe": false, + "unsafe_arrows": false, + "unsafe_comps": false, + "unsafe_Function": false, + "unsafe_math": false, + "unsafe_proto": false, + "unsafe_regexp": false, + "unsafe_undefined": false, + "unused": true + }, + "mangle": { + "eval": false, + "reserved": [] + }, + "output": { + "ascii_only": false, + "braces": false, + "comments": "none", + "inline_script": true, + "keep_numbers": false, + "keep_quoted_props": false, + "preamble": null, + "quote_keys": false, + "quote_style": 0, + "semicolons": true, + "shebang": true, + "webkit": false, + "wrap_iife": false, + "wrap_func_args": true + }, + "sourceMap": false, + "toplevel": false, + "ie8": false, + "keep_classnames": false, + "keep_fnames": false, + "safari10": false + }, + "node-sass": { + "indentType": "space", + "allowWildcardImports": false, + "indentWidth": 2, + "linefeed": "lf", + "outputStyle": "expanded", + "precision": 10, + "sourceMap": false, + "sourceComments": false + }, + "png": { + "quality": 90 + }, + "postcss-import": { + "ignoreKeywords": [], + "sourceMap": false + }, + "postcss-preset-env": { + "stage": 2, + "browsers": [ + "last 2 versions" + ], + "sourceMap": false + }, + "pug": { + "pretty": true + }, + "slim": { + "indent": "space", + "indentSize": 2, + "pretty": true + }, + "stylus": { + "useNib": true, + "sourceMap": false, + "linenos": false + }, + "svg": { + "cleanupAttrs": true, + "removeDoctype": true, + "removeXMLProcInst": true, + "removeComments": true, + "removeMetadata": true, + "removeTitle": true, + "removeDesc": true, + "removeUselessDefs": true, + "removeEditorsNSData": true, + "removeEmptyAttrs": true, + "removeHiddenElems": true, + "removeEmptyText": true, + "removeEmptyContainers": true, + "removeViewBox": false, + "cleanupEnableBackground": true, + "convertStyleToAttrs": true, + "convertColors": true, + "convertPathData": true, + "convertTransform": true, + "removeUnknownsAndDefaults": true, + "removeNonInheritableGroupAttrs": true, + "removeUselessStrokeAndFill": true, + "removeUnusedNS": true, + "cleanupIDs": true, + "cleanupNumericValues": true, + "moveElemsAttrsToGroup": true, + "moveGroupAttrsToElems": true, + "collapseGroups": true, + "removeRasterImages": false, + "mergePaths": true, + "convertShapeToPath": true, + "sortAttrs": true, + "removeDimensions": true + }, + "turf": { + "rootDir": "" + }, + "typescript": { + "allowJs": false, + "allowSyntheticDefaultImports": true, + "allowUmdGlobalAccess": false, + "allowUnreachableCode": false, + "allowUnusedLabels": false, + "alwaysStrict": false, + "charset": "utf8", + "checkJs": false, + "declaration": false, + "disableSizeLimit": false, + "downlevelIteration": false, + "emitBOM": false, + "emitDecoratorMetadata": false, + "experimentalDecorators": false, + "forceConsistentCasingInFileNames": false, + "importHelpers": false, + "jsx": "React", + "keyofStringsOnly": false, + "lib": [], + "maxNodeModuleJsDepth": 0, + "module": "ES2015", + "moduleResolution": "NodeJs", + "newLine": "LineFeed", + "noFallthroughCasesInSwitch": false, + "noImplicitAny": false, + "noImplicitReturns": false, + "noImplicitThis": false, + "noStrictGenericChecks": false, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noImplicitUseStrict": false, + "noLib": false, + "noResolve": false, + "preserveConstEnums": false, + "jsxFactory": "React.createElement", + "removeComments": false, + "skipLibCheck": false, + "sourceMap": false, + "strict": false, + "strictFunctionTypes": false, + "strictBindCallApply": false, + "strictNullChecks": false, + "strictPropertyInitialization": false, + "suppressExcessPropertyErrors": false, + "suppressImplicitAnyIndexErrors": false, + "target": "ES3", + "resolveJsonModule": false, + "esModuleInterop": false, + "useDefineForClassFields": false + } + }, + "fileTypes": { + "sass": { + "extensions": [ + ".scss", + ".sass" + ], + "autoCompile": true, + "sourceMap": false, + "tasks": [ + { + "task": "dart-sass", + "enable": true + }, + { + "task": "autoprefixer", + "enable": false + }, + { + "task": "minify-css", + "enable": false + } + ], + "output": { + "extension": ".css", + "type": "SOURCE_RELATIVE", + "segments": [ + { + "segment": "scss", + "replaceWith": "css" + }, + { + "segment": "sass", + "replaceWith": "css" + } + ] + } + }, + "less": { + "extensions": [ + ".less" + ], + "autoCompile": true, + "sourceMap": false, + "tasks": [ + { + "task": "less", + "enable": true + }, + { + "task": "autoprefixer", + "enable": true + }, + { + "task": "minify-css", + "enable": false + } + ], + "output": { + "extension": ".css", + "type": "REPLACE_SEGMENTS", + "segments": [ + { + "segment": "less", + "replaceWith": "css" + } + ] + } + }, + "pug": { + "extensions": [ + ".pug", + ".jade" + ], + "autoCompile": true, + "tasks": [ + { + "task": "pug", + "enable": true + }, + { + "task": "minify-html", + "enable": false + } + ], + "output": { + "extension": ".html", + "type": "SOURCE_RELATIVE", + "segments": [ + { + "segment": "pug", + "replaceWith": "html" + } + ] + } + }, + "css": { + "extensions": [ + ".css" + ], + "autoCompile": false, + "sourceMap": false, + "tasks": [ + { + "task": "copy", + "enable": true + }, + { + "task": "postcss-import", + "enable": false + }, + { + "task": "postcss-preset-env", + "enable": false + }, + { + "task": "autoprefixer", + "enable": false + }, + { + "task": "minify-css", + "enable": false + } + ], + "output": { + "extension": ".css", + "type": "SOURCE_RELATIVE", + "relativePath": "", + "suffix": "-dist", + "alwaysSuffix": false + } + }, + "javascript": { + "extensions": [ + ".js", + ".jsx" + ], + "autoCompile": false, + "sourceMap": false, + "tasks": [ + { + "task": "copy", + "enable": true + }, + { + "task": "concat-js", + "enable": false + }, + { + "task": "babel", + "enable": false + }, + { + "task": "bundle-js", + "enable": false + }, + { + "task": "minify-js", + "enable": true + } + ], + "output": { + "extension": ".js", + "type": "SOURCE_RELATIVE", + "relativePath": "", + "suffix": "-dist", + "alwaysSuffix": false + } + }, + "stylus": { + "extensions": [ + ".styl" + ], + "autoCompile": true, + "sourceMap": false, + "tasks": [ + { + "task": "stylus", + "enable": true + }, + { + "task": "autoprefixer", + "enable": true + }, + { + "task": "minify-css", + "enable": false + } + ], + "output": { + "extension": ".css", + "type": "REPLACE_SEGMENTS", + "segments": [ + { + "segment": "stylus", + "replaceWith": "css" + }, + { + "segment": "styl", + "replaceWith": "css" + } + ] + } + }, + "markdown": { + "extensions": [ + ".md", + ".markdown", + ".mkd" + ], + "autoCompile": false, + "tasks": [ + { + "task": "markdown", + "enable": true + }, + { + "task": "minify-html", + "enable": false + } + ], + "output": { + "extension": ".html", + "type": "REPLACE_SEGMENTS", + "segments": [ + { + "segment": "markdown", + "replaceWith": "html" + } + ] + } + }, + "haml": { + "extensions": [ + ".haml" + ], + "autoCompile": true, + "tasks": [ + { + "task": "haml", + "enable": true + }, + { + "task": "minify-html", + "enable": false + } + ], + "output": { + "extension": ".html", + "type": "REPLACE_SEGMENTS", + "segments": [ + { + "segment": "haml", + "replaceWith": "html" + } + ] + } + }, + "slim": { + "extensions": [ + ".slim" + ], + "autoCompile": true, + "tasks": [ + { + "task": "slim", + "enable": true + }, + { + "task": "minify-html", + "enable": false + } + ], + "output": { + "extension": ".html", + "type": "REPLACE_SEGMENTS", + "segments": [ + { + "segment": "slim", + "replaceWith": "html" + } + ] + } + }, + "coffeescript": { + "extensions": [ + ".coffee" + ], + "autoCompile": true, + "sourceMap": false, + "tasks": [ + { + "task": "coffeescript", + "enable": true + }, + { + "task": "babel", + "enable": false + }, + { + "task": "bundle-js", + "enable": false + }, + { + "task": "minify-js", + "enable": false + } + ], + "output": { + "extension": ".js", + "type": "REPLACE_SEGMENTS", + "segments": [ + { + "segment": "coffee-script", + "replaceWith": "js" + }, + { + "segment": "coffeescript", + "replaceWith": "js" + }, + { + "segment": "coffee", + "replaceWith": "js" + } + ] + } + }, + "turf": { + "extensions": [ + ".turf", + ".kit" + ], + "autoCompile": true, + "tasks": [ + { + "task": "turf", + "enable": true + }, + { + "task": "minify-html", + "enable": false + } + ], + "output": { + "extension": ".html", + "type": "REPLACE_SEGMENTS", + "segments": [ + { + "segment": "turf", + "replaceWith": "html" + } + ] + } + }, + "typescript": { + "extensions": [ + ".ts", + ".tsx" + ], + "autoCompile": true, + "sourceMap": false, + "tasks": [ + { + "task": "typescript", + "enable": true + }, + { + "task": "babel", + "enable": false + }, + { + "task": "bundle-js", + "enable": false + }, + { + "task": "minify-js", + "enable": false + } + ], + "output": { + "extension": ".js", + "type": "REPLACE_SEGMENTS", + "segments": [ + { + "segment": "typescript", + "replaceWith": "js" + }, + { + "segment": "ts", + "replaceWith": "js" + } + ] + } + }, + "jpg": { + "extensions": [ + ".jpg", + ".jpeg" + ], + "tasks": [ + { + "task": "jpg", + "enable": true + } + ], + "output": { + "extension": ".jpg", + "type": "SOURCE_RELATIVE", + "relativePath": "" + } + }, + "png": { + "extensions": [ + ".png" + ], + "tasks": [ + { + "task": "png", + "enable": true + } + ], + "output": { + "extension": ".png", + "type": "SOURCE_RELATIVE", + "relativePath": "" + } + }, + "svg": { + "extensions": [ + ".svg" + ], + "tasks": [ + { + "task": "svg", + "enable": true + } + ], + "output": { + "extension": ".svg", + "type": "SOURCE_RELATIVE", + "relativePath": "" + } + } + }, + "files": [ + { + "file": "style.scss", + "config": { + "customOutput": "style.css" + } + }, + { + "file": "system.pug", + "config": { + "customOutput": "system.html" + } + } + ] + } +} diff --git a/rapidfire_system/rapidfire_preview.jpg b/rapidfire_system/rapidfire_preview.jpg new file mode 100644 index 0000000000..aff46fb1f2 Binary files /dev/null and b/rapidfire_system/rapidfire_preview.jpg differ diff --git a/rapidfire_system/sheet.json b/rapidfire_system/sheet.json new file mode 100644 index 0000000000..079b9a5bb9 --- /dev/null +++ b/rapidfire_system/sheet.json @@ -0,0 +1,9 @@ +{ + "html": "system.html", + "css": "style.css", + "authors": "Scott Casey", + "roll20userid": "459831", + "preview": "rapidfire_preview.jpg", + "instructions": "This sheet is compatible with all Rapidfire system games by [Outrider Studios](https://outriderstudios.com/). Check out the [Rapidfire System sheet guide](https://wiki.roll20.net/Rapidfire_System) for full details on how to use the sheet and all the features included in it.", + "legacy": false +} \ No newline at end of file diff --git a/rapidfire_system/style.css b/rapidfire_system/style.css new file mode 100644 index 0000000000..f8910d4c5d --- /dev/null +++ b/rapidfire_system/style.css @@ -0,0 +1,1513 @@ +@import url("https://fonts.googleapis.com/css?family=Bakbak+One|Oxanium:wght@700|Raleway:wght@500;600;700;800&display=swap"); +.sheet-rolltemplate-rapidfire, .ui-dialog { + --topHeaderFont:Bakbak One; + --midHeaderFont:Oxanium; + --contentFont:Raleway; +} + +.ui-dialog .tab-content .charsheet select, +.ui-dialog .tab-content .charsheet textarea, +.ui-dialog .tab-content .charsheet input, +.ui-dialog .tab-content .charsheet .uneditable-input, +.ui-dialog .tab-content .charsheet label, +.ui-dialog .tab-content .charsheet button { + all: initial; +} + +.ui-dialog .tab-content .charsheet .stacked.input-label, .sheet-rolltemplate-rapidfire .stacked.input-label { + flex-direction: column-reverse; +} +.ui-dialog .tab-content .charsheet .stacked.center.input-label > *, .sheet-rolltemplate-rapidfire .stacked.center.input-label > * { + text-align: center; +} +.ui-dialog .tab-content .charsheet .stacked.input-label:not(.center) > *, .sheet-rolltemplate-rapidfire .stacked.input-label:not(.center) > * { + text-align: left; +} +.ui-dialog .tab-content .charsheet .stacked.input-label > [name], .sheet-rolltemplate-rapidfire .stacked.input-label > [name] { + width: 100%; +} + +.ui-dialog .tab-content .charsheet :is(.underlined, .boxed):not([readonly]):is(:hover, :focus, :focus-within), .sheet-rolltemplate-rapidfire :is(.underlined, .boxed):not([readonly]):is(:hover, :focus, :focus-within) { + border-width: 1px 3px; + border-style: solid; + border-color: black; + border-radius: 5px; + box-sizing: border-box; + transition: var(--focusTrans); +} + +.ui-dialog .tab-content .charsheet .ratio1-1, .sheet-rolltemplate-rapidfire .ratio1-1 { + aspect-ratio: 1/1; +} + +.ui-dialog .tab-content .charsheet .boxed.span-2, .ui-dialog .tab-content .charsheet .health-track .repcontainer, .ui-dialog .tab-content .charsheet .health-track .repcontainer > .repitem, .ui-dialog .tab-content .charsheet .repeat-columns, .ui-dialog .tab-content .charsheet .image-container, .ui-dialog .tab-content .charsheet .base-container, #stats .equipment, #stats .equipment .repitem, #secondary > .secondaries, #secondary > .combat-gear, #skill .repitem, #weapon .repitem, #adjustments .repitem, #remnant-ratings, #remnant-stats, #remnant-trait .repitem, #remnant-drone .repitem, #remnant-weapons .repitem, .sheet-rolltemplate-rapidfire .sheet-content, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-header, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-footer, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-background, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-header__content, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-footer__content, #settings, #character, #remnant, #character-info, #skill, #weapon, #adjustments .subsection, #remnant-ratings .remnant-skills, #remnant-specialty, #remnant-trait, #remnant-drone, #remnant-weapons, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border:before, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border:after, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border__hex-content, .ui-dialog .tab-content .charsheet .roll-container, .sheet-rolltemplate-rapidfire .roll-container, .ui-dialog .tab-content .charsheet .small-scale-grid, .sheet-rolltemplate-rapidfire .small-scale-grid, +.ui-dialog .tab-content .charsheet fieldset.small-scale-grid + .repcontainer, +.sheet-rolltemplate-rapidfire fieldset.small-scale-grid + .repcontainer, .ui-dialog .tab-content .charsheet .headed-textarea, .sheet-rolltemplate-rapidfire .headed-textarea, .ui-dialog .tab-content .charsheet section, .sheet-rolltemplate-rapidfire section, .ui-dialog .tab-content .charsheet .adaptive-text { + display: grid; +} + +.ui-dialog .tab-content .charsheet select, .sheet-rolltemplate-rapidfire select, +.ui-dialog .tab-content .charsheet .pseudo-select span, +.sheet-rolltemplate-rapidfire .pseudo-select span, +.ui-dialog .tab-content .charsheet input:not(:where([type="checkbox"], [type="radio"])), +.sheet-rolltemplate-rapidfire input:not(:where([type="checkbox"], [type="radio"])), +.ui-dialog .tab-content .charsheet .uneditable-input, +.sheet-rolltemplate-rapidfire .uneditable-input, +.ui-dialog .tab-content .charsheet textarea, +.sheet-rolltemplate-rapidfire textarea, .ui-dialog .tab-content .charsheet .adaptive-text > span { + border-width: 1px 3px; + border-style: solid; + border-radius: 5px; + border-color: transparent; + box-sizing: border-box; +} + +.ui-dialog .tab-content .charsheet .repcontrol-button, .sheet-rolltemplate-rapidfire .repcontrol-button { + background-color: #DCDCDC33; + border-radius: 5px; + box-shadow: 0 2px 4px black; + border-width: 0; + transition-property: box-shadow, backdrop-filter; + transition-duration: 200ms; + transition-timing-function: ease-out; + backdrop-filter: blur(1px); + overflow: hidden; +} +.ui-dialog .tab-content .charsheet .repcontrol-button:is(:hover, :focus), .sheet-rolltemplate-rapidfire .repcontrol-button:is(:hover, :focus) { + background-color: #85858580; + box-shadow: 0 4px 6px black; + backdrop-filter: blur(2px); +} +.ui-dialog .tab-content .charsheet .repcontrol-button:active, .sheet-rolltemplate-rapidfire .repcontrol-button:active { + background-color: #858585ff; + box-shadow: 0 1px 2px black; + backdrop-filter: blur(0px); +} + +.ui-dialog .tab-content .charsheet .repcontrol-button, .sheet-rolltemplate-rapidfire .repcontrol-button { + padding: 5px 7px; +} + +.ui-dialog .tab-content .charsheet .adaptive-text { + grid-template-columns: auto; + grid-template-rows: auto; + grid-template-areas: "content"; +} +.ui-dialog .tab-content .charsheet .adaptive-text > * { + grid-area: content; +} +.ui-dialog .tab-content .charsheet .adaptive-text > span { + opacity: 0; + z-index: -10; + white-space: pre-wrap; + text-transform: initial; +} +.ui-dialog .tab-content .charsheet .adaptive-text textarea { + resize: none; +} + +#main-nav .nav__button--settings, .ui-dialog .tab-content .charsheet .pictos, .sheet-rolltemplate-rapidfire .pictos { + font-family: pictos; + text-transform: initial; +} + +.ui-dialog .tab-content .charsheet .pictos3, .sheet-rolltemplate-rapidfire .pictos3 { + font-family: pictos three; + text-transform: initial; +} + +.ui-dialog .tab-content .charsheet .pictoscustom, .sheet-rolltemplate-rapidfire .pictoscustom { + font-family: pictos custom; + text-transform: initial; +} + +#main .uppercase { + text-transform: uppercase; +} + +#main .roller { + display: inline-flex; + align-items: center; + align-self: start; + gap: var(--half-gap); +} +#main .roller:before { + content: "L"; + font-family: dicefontd6; +} + +.ui-dialog .tab-content .charsheet .hidden, .sheet-rolltemplate-rapidfire .hidden, +.ui-dialog .tab-content .charsheet *[hidden], +.sheet-rolltemplate-rapidfire *[hidden] { + display: none !important; +} + +.ui-dialog .tab-content .charsheet .italics, .sheet-rolltemplate-rapidfire .italics { + font-style: italic; +} + +.ui-dialog .tab-content .charsheet span, .sheet-rolltemplate-rapidfire span, +.ui-dialog .tab-content .charsheet input, +.sheet-rolltemplate-rapidfire input, +.ui-dialog .tab-content .charsheet textarea, +.sheet-rolltemplate-rapidfire textarea, .ui-dialog .tab-content .charsheet h5 *, .sheet-rolltemplate-rapidfire h5 *, +.ui-dialog .tab-content .charsheet *[aria-level="5"] *, +.sheet-rolltemplate-rapidfire *[aria-level="5"] *, .ui-dialog .tab-content .charsheet h5, .sheet-rolltemplate-rapidfire h5, +.ui-dialog .tab-content .charsheet *[aria-level="5"], +.sheet-rolltemplate-rapidfire *[aria-level="5"], .ui-dialog .tab-content .charsheet h4 *, .sheet-rolltemplate-rapidfire h4 *, +.ui-dialog .tab-content .charsheet *[aria-level="4"] *, +.sheet-rolltemplate-rapidfire *[aria-level="4"] *, .ui-dialog .tab-content .charsheet h4, .sheet-rolltemplate-rapidfire h4, +.ui-dialog .tab-content .charsheet *[aria-level="4"], +.sheet-rolltemplate-rapidfire *[aria-level="4"], .ui-dialog .tab-content .charsheet h3 *, .sheet-rolltemplate-rapidfire h3 *, +.ui-dialog .tab-content .charsheet *[aria-level="3"] *, +.sheet-rolltemplate-rapidfire *[aria-level="3"] *, .ui-dialog .tab-content .charsheet h3, .sheet-rolltemplate-rapidfire h3, +.ui-dialog .tab-content .charsheet *[aria-level="3"], +.sheet-rolltemplate-rapidfire *[aria-level="3"], .ui-dialog .tab-content .charsheet h2 *, .sheet-rolltemplate-rapidfire h2 *, .ui-dialog .tab-content .charsheet .input-label:not(.stacked).large > [name] *, .sheet-rolltemplate-rapidfire .input-label:not(.stacked).large > [name] *, +.ui-dialog .tab-content .charsheet *[aria-level="2"] *, +.sheet-rolltemplate-rapidfire *[aria-level="2"] *, .ui-dialog .tab-content .charsheet h2, .sheet-rolltemplate-rapidfire h2, .ui-dialog .tab-content .charsheet .input-label:not(.stacked).large > [name], .sheet-rolltemplate-rapidfire .input-label:not(.stacked).large > [name], +.ui-dialog .tab-content .charsheet *[aria-level="2"], +.sheet-rolltemplate-rapidfire *[aria-level="2"], .ui-dialog .tab-content .charsheet h1 *, .sheet-rolltemplate-rapidfire h1 *, +.ui-dialog .tab-content .charsheet *[aria-level="1"] *, +.sheet-rolltemplate-rapidfire *[aria-level="1"] *, .ui-dialog .tab-content .charsheet h1, .sheet-rolltemplate-rapidfire h1, +.ui-dialog .tab-content .charsheet *[aria-level="1"], +.sheet-rolltemplate-rapidfire *[aria-level="1"] { + line-height: normal; +} + +.ui-dialog .tab-content .charsheet h5 *, .sheet-rolltemplate-rapidfire h5 *, +.ui-dialog .tab-content .charsheet *[aria-level="5"] *, +.sheet-rolltemplate-rapidfire *[aria-level="5"] *, .ui-dialog .tab-content .charsheet h5, .sheet-rolltemplate-rapidfire h5, +.ui-dialog .tab-content .charsheet *[aria-level="5"], +.sheet-rolltemplate-rapidfire *[aria-level="5"], .ui-dialog .tab-content .charsheet h4 *, .sheet-rolltemplate-rapidfire h4 *, +.ui-dialog .tab-content .charsheet *[aria-level="4"] *, +.sheet-rolltemplate-rapidfire *[aria-level="4"] *, .ui-dialog .tab-content .charsheet h4, .sheet-rolltemplate-rapidfire h4, +.ui-dialog .tab-content .charsheet *[aria-level="4"], +.sheet-rolltemplate-rapidfire *[aria-level="4"], .ui-dialog .tab-content .charsheet h3 *, .sheet-rolltemplate-rapidfire h3 *, +.ui-dialog .tab-content .charsheet *[aria-level="3"] *, +.sheet-rolltemplate-rapidfire *[aria-level="3"] *, .ui-dialog .tab-content .charsheet h3, .sheet-rolltemplate-rapidfire h3, +.ui-dialog .tab-content .charsheet *[aria-level="3"], +.sheet-rolltemplate-rapidfire *[aria-level="3"], .ui-dialog .tab-content .charsheet h2 *, .sheet-rolltemplate-rapidfire h2 *, .ui-dialog .tab-content .charsheet .input-label:not(.stacked).large > [name] *, .sheet-rolltemplate-rapidfire .input-label:not(.stacked).large > [name] *, +.ui-dialog .tab-content .charsheet *[aria-level="2"] *, +.sheet-rolltemplate-rapidfire *[aria-level="2"] *, .ui-dialog .tab-content .charsheet h2, .sheet-rolltemplate-rapidfire h2, .ui-dialog .tab-content .charsheet .input-label:not(.stacked).large > [name], .sheet-rolltemplate-rapidfire .input-label:not(.stacked).large > [name], +.ui-dialog .tab-content .charsheet *[aria-level="2"], +.sheet-rolltemplate-rapidfire *[aria-level="2"], .ui-dialog .tab-content .charsheet h1 *, .sheet-rolltemplate-rapidfire h1 *, +.ui-dialog .tab-content .charsheet *[aria-level="1"] *, +.sheet-rolltemplate-rapidfire *[aria-level="1"] *, .ui-dialog .tab-content .charsheet h1, .sheet-rolltemplate-rapidfire h1, +.ui-dialog .tab-content .charsheet *[aria-level="1"], +.sheet-rolltemplate-rapidfire *[aria-level="1"] { + color: black; + display: block; + white-space: nowrap; + margin-top: 0px; + margin-bottom: 0px; + font-weight: normal; +} + +.ui-dialog .tab-content .charsheet h3 *, .sheet-rolltemplate-rapidfire h3 *, +.ui-dialog .tab-content .charsheet *[aria-level="3"] *, +.sheet-rolltemplate-rapidfire *[aria-level="3"] *, .ui-dialog .tab-content .charsheet h3, .sheet-rolltemplate-rapidfire h3, +.ui-dialog .tab-content .charsheet *[aria-level="3"], +.sheet-rolltemplate-rapidfire *[aria-level="3"], .ui-dialog .tab-content .charsheet h2 *, .sheet-rolltemplate-rapidfire h2 *, .ui-dialog .tab-content .charsheet .input-label:not(.stacked).large > [name] *, .sheet-rolltemplate-rapidfire .input-label:not(.stacked).large > [name] *, +.ui-dialog .tab-content .charsheet *[aria-level="2"] *, +.sheet-rolltemplate-rapidfire *[aria-level="2"] *, .ui-dialog .tab-content .charsheet h2, .sheet-rolltemplate-rapidfire h2, .ui-dialog .tab-content .charsheet .input-label:not(.stacked).large > [name], .sheet-rolltemplate-rapidfire .input-label:not(.stacked).large > [name], +.ui-dialog .tab-content .charsheet *[aria-level="2"], +.sheet-rolltemplate-rapidfire *[aria-level="2"], .ui-dialog .tab-content .charsheet h1 *, .sheet-rolltemplate-rapidfire h1 *, +.ui-dialog .tab-content .charsheet *[aria-level="1"] *, +.sheet-rolltemplate-rapidfire *[aria-level="1"] *, .ui-dialog .tab-content .charsheet h1, .sheet-rolltemplate-rapidfire h1, +.ui-dialog .tab-content .charsheet *[aria-level="1"], +.sheet-rolltemplate-rapidfire *[aria-level="1"] { + text-transform: uppercase; + font-weight: normal; +} + +.ui-dialog .tab-content .charsheet h5 :not(input), .sheet-rolltemplate-rapidfire h5 :not(input), +.ui-dialog .tab-content .charsheet *[aria-level="5"] :not(input), +.sheet-rolltemplate-rapidfire *[aria-level="5"] :not(input), .ui-dialog .tab-content .charsheet h5:not(input), .sheet-rolltemplate-rapidfire h5:not(input), +.ui-dialog .tab-content .charsheet [aria-level="5"]:not(input), +.sheet-rolltemplate-rapidfire [aria-level="5"]:not(input), .ui-dialog .tab-content .charsheet h4 :not(input), .sheet-rolltemplate-rapidfire h4 :not(input), +.ui-dialog .tab-content .charsheet *[aria-level="4"] :not(input), +.sheet-rolltemplate-rapidfire *[aria-level="4"] :not(input), .ui-dialog .tab-content .charsheet h4:not(input), .sheet-rolltemplate-rapidfire h4:not(input), +.ui-dialog .tab-content .charsheet [aria-level="4"]:not(input), +.sheet-rolltemplate-rapidfire [aria-level="4"]:not(input) { + text-transform: capitalize; +} + +.ui-dialog .tab-content .charsheet h1 *, .sheet-rolltemplate-rapidfire h1 *, +.ui-dialog .tab-content .charsheet *[aria-level="1"] *, +.sheet-rolltemplate-rapidfire *[aria-level="1"] *, .ui-dialog .tab-content .charsheet h1, .sheet-rolltemplate-rapidfire h1, +.ui-dialog .tab-content .charsheet *[aria-level="1"], +.sheet-rolltemplate-rapidfire *[aria-level="1"] { + font-size: 2rem; + font-family: var(--topHeaderFont); +} +.ui-dialog .tab-content .charsheet h1 :not(input), .sheet-rolltemplate-rapidfire h1 :not(input), +.ui-dialog .tab-content .charsheet *[aria-level="1"] :not(input), +.sheet-rolltemplate-rapidfire *[aria-level="1"] :not(input), .ui-dialog .tab-content .charsheet h1:not(input), .sheet-rolltemplate-rapidfire h1:not(input), +.ui-dialog .tab-content .charsheet [aria-level="1"]:not(input), +.sheet-rolltemplate-rapidfire [aria-level="1"]:not(input) { + text-align: center; +} + +.ui-dialog .tab-content .charsheet h2 *, .sheet-rolltemplate-rapidfire h2 *, .ui-dialog .tab-content .charsheet .input-label:not(.stacked).large > [name] *, .sheet-rolltemplate-rapidfire .input-label:not(.stacked).large > [name] *, +.ui-dialog .tab-content .charsheet *[aria-level="2"] *, +.sheet-rolltemplate-rapidfire *[aria-level="2"] *, .ui-dialog .tab-content .charsheet h2, .sheet-rolltemplate-rapidfire h2, .ui-dialog .tab-content .charsheet .input-label:not(.stacked).large > [name], .sheet-rolltemplate-rapidfire .input-label:not(.stacked).large > [name], +.ui-dialog .tab-content .charsheet *[aria-level="2"], +.sheet-rolltemplate-rapidfire *[aria-level="2"] { + font-size: 1.75rem; + font-family: var(--topHeaderFont); + grid-area: header; +} +.ui-dialog .tab-content .charsheet h2 :not(input), .sheet-rolltemplate-rapidfire h2 :not(input), .ui-dialog .tab-content .charsheet .input-label:not(.stacked).large > [name] :not(input), .sheet-rolltemplate-rapidfire .input-label:not(.stacked).large > [name] :not(input), +.ui-dialog .tab-content .charsheet *[aria-level="2"] :not(input), +.sheet-rolltemplate-rapidfire *[aria-level="2"] :not(input), .ui-dialog .tab-content .charsheet h2:not(input), .sheet-rolltemplate-rapidfire h2:not(input), .ui-dialog .tab-content .charsheet .input-label:not(.stacked).large > [name]:not(input), .sheet-rolltemplate-rapidfire .input-label:not(.stacked).large > [name]:not(input), +.ui-dialog .tab-content .charsheet [aria-level="2"]:not(input), +.sheet-rolltemplate-rapidfire [aria-level="2"]:not(input) { + text-align: center; +} + +.ui-dialog .tab-content .charsheet h3 *, .sheet-rolltemplate-rapidfire h3 *, +.ui-dialog .tab-content .charsheet *[aria-level="3"] *, +.sheet-rolltemplate-rapidfire *[aria-level="3"] *, .ui-dialog .tab-content .charsheet h3, .sheet-rolltemplate-rapidfire h3, +.ui-dialog .tab-content .charsheet *[aria-level="3"], +.sheet-rolltemplate-rapidfire *[aria-level="3"] { + font-size: 1.5rem; + font-family: var(--topHeaderFont); +} +.ui-dialog .tab-content .charsheet h3 :not(input), .sheet-rolltemplate-rapidfire h3 :not(input), +.ui-dialog .tab-content .charsheet *[aria-level="3"] :not(input), +.sheet-rolltemplate-rapidfire *[aria-level="3"] :not(input), .ui-dialog .tab-content .charsheet h3:not(input), .sheet-rolltemplate-rapidfire h3:not(input), +.ui-dialog .tab-content .charsheet [aria-level="3"]:not(input), +.sheet-rolltemplate-rapidfire [aria-level="3"]:not(input) { + text-align: center; +} + +.ui-dialog .tab-content .charsheet h4 *, .sheet-rolltemplate-rapidfire h4 *, +.ui-dialog .tab-content .charsheet *[aria-level="4"] *, +.sheet-rolltemplate-rapidfire *[aria-level="4"] *, .ui-dialog .tab-content .charsheet h4, .sheet-rolltemplate-rapidfire h4, +.ui-dialog .tab-content .charsheet *[aria-level="4"], +.sheet-rolltemplate-rapidfire *[aria-level="4"] { + font-size: 1.25rem; + font-family: var(--midHeaderFont); +} +.ui-dialog .tab-content .charsheet h4 :not(input), .sheet-rolltemplate-rapidfire h4 :not(input), +.ui-dialog .tab-content .charsheet *[aria-level="4"] :not(input), +.sheet-rolltemplate-rapidfire *[aria-level="4"] :not(input), .ui-dialog .tab-content .charsheet h4:not(input), .sheet-rolltemplate-rapidfire h4:not(input), +.ui-dialog .tab-content .charsheet [aria-level="4"]:not(input), +.sheet-rolltemplate-rapidfire [aria-level="4"]:not(input) { + text-align: center; +} + +.ui-dialog .tab-content .charsheet h5 *, .sheet-rolltemplate-rapidfire h5 *, +.ui-dialog .tab-content .charsheet *[aria-level="5"] *, +.sheet-rolltemplate-rapidfire *[aria-level="5"] *, .ui-dialog .tab-content .charsheet h5, .sheet-rolltemplate-rapidfire h5, +.ui-dialog .tab-content .charsheet *[aria-level="5"], +.sheet-rolltemplate-rapidfire *[aria-level="5"] { + font-size: 1rem; + font-style: normal; + font-family: var(--midHeaderFont); +} +.ui-dialog .tab-content .charsheet h5 :not(input), .sheet-rolltemplate-rapidfire h5 :not(input), +.ui-dialog .tab-content .charsheet *[aria-level="5"] :not(input), +.sheet-rolltemplate-rapidfire *[aria-level="5"] :not(input), .ui-dialog .tab-content .charsheet h5:not(input), .sheet-rolltemplate-rapidfire h5:not(input), +.ui-dialog .tab-content .charsheet [aria-level="5"]:not(input), +.sheet-rolltemplate-rapidfire [aria-level="5"]:not(input) { + text-align: center; +} + +.ui-dialog .tab-content .charsheet .contents, .sheet-rolltemplate-rapidfire .contents, +.ui-dialog .tab-content .charsheet .sheet-contents, +.sheet-rolltemplate-rapidfire .sheet-contents { + display: contents; +} + +.ui-dialog .tab-content .charsheet .health-track__fill-control:checked + *, .ui-dialog .tab-content .charsheet input[type=checkbox]:checked, .sheet-rolltemplate-rapidfire input[type=checkbox]:checked { + background-color: var(--selectedColor); +} + +.ui-dialog .tab-content .charsheet .boxed, .sheet-rolltemplate-rapidfire .boxed, +.ui-dialog .tab-content .charsheet .sheet-boxed, +.sheet-rolltemplate-rapidfire .sheet-boxed { + border: 1px solid black; + border-radius: 0; + box-sizing: border-box; +} + +.ui-dialog .tab-content .charsheet, .sheet-rolltemplate-rapidfire { + --grid-gap: 1rem; + --half-gap: calc(var(--grid-gap) / 2); + --tiny-gap: calc(var(--half-gap) / 2); + --big-gap: calc(var(--grid-gap) * 2); + --revealTime: 500ms; + --delayTime: 200ms; + --inputSwap: opacity var(--revealTime) ease var(--delayTime); + --focusTiming: 500ms ease; + --focusTrans: all var(--focusTiming); + --borderColor: black; + --fontColor: black; + --backColor: #ffffff; + --spanSectionColumn:1/-1; + --displayBorderWidth: 2px; + --subHeadBackColor:grey; + --unselectedColor:lightgrey; + --selectedColor:black; + --topCorner:url("https://s3.amazonaws.com/files.d20.io/images/258525471/MZYT-HjOvfJOqUXufyBkww/original.png"); + --bottomCorner:url("https://s3.amazonaws.com/files.d20.io/images/258525472/d7gSQyNdXW4tfBUa3osltQ/original.png"); + --headerBottom:url("https://s3.amazonaws.com/files.d20.io/images/258525865/9moWl3pE8miL8gqQC2UPRw/original.png"); + --footerTop:url("https://s3.amazonaws.com/files.d20.io/images/258525864/dzZKV6kH_fltY8yH9D-ptA/original.png"); + position: relative; + gap: var(--grid-gap); +} +.ui-dialog .tab-content .charsheet button, .sheet-rolltemplate-rapidfire button { + cursor: pointer; +} +.ui-dialog .tab-content .charsheet textarea, .sheet-rolltemplate-rapidfire textarea { + resize: vertical; + min-height: 3.5rem; + white-space: pre-wrap; +} +.ui-dialog .tab-content .charsheet textarea.fixed, .sheet-rolltemplate-rapidfire textarea.fixed { + resize: none; + overflow: auto; +} +.ui-dialog .tab-content .charsheet .span-2, .sheet-rolltemplate-rapidfire .span-2 { + grid-column: span 2; +} +.ui-dialog .tab-content .charsheet .span-all, .sheet-rolltemplate-rapidfire .span-all { + grid-column: 1/-1; +} +.ui-dialog .tab-content .charsheet select, .sheet-rolltemplate-rapidfire select, +.ui-dialog .tab-content .charsheet .pseudo-select span, +.sheet-rolltemplate-rapidfire .pseudo-select span, +.ui-dialog .tab-content .charsheet textarea, +.sheet-rolltemplate-rapidfire textarea, +.ui-dialog .tab-content .charsheet input:not(:is([type=radio], [type=checkbox])), +.sheet-rolltemplate-rapidfire input:not(:is([type=radio], [type=checkbox])), +.ui-dialog .tab-content .charsheet .uneditable-input, +.sheet-rolltemplate-rapidfire .uneditable-input { + padding: 2px; + font-size: 1rem; +} +.ui-dialog .tab-content .charsheet input:is([type=text], [type=number]), .sheet-rolltemplate-rapidfire input:is([type=text], [type=number]), .ui-dialog .tab-content .charsheet textarea, .sheet-rolltemplate-rapidfire textarea { + cursor: auto; +} +.ui-dialog .tab-content .charsheet select, .sheet-rolltemplate-rapidfire select, +.ui-dialog .tab-content .charsheet .pseudo-select span, +.sheet-rolltemplate-rapidfire .pseudo-select span { + -webkit-apperance: none; + appearance: none; + text-transform: capitalize; + overflow: hidden !important; + white-space: nowrap; + text-overflow: ellipsis; + text-align: center; +} +.ui-dialog .tab-content .charsheet input, .sheet-rolltemplate-rapidfire input { + width: auto; +} +.ui-dialog .tab-content .charsheet input:placeholder, .sheet-rolltemplate-rapidfire input:placeholder { + color: #ededed80; +} +.ui-dialog .tab-content .charsheet input.plus-control:not([value*="-"]) + span:before, .sheet-rolltemplate-rapidfire input.plus-control:not([value*="-"]) + span:before { + content: "+"; +} +.ui-dialog .tab-content .charsheet span, .sheet-rolltemplate-rapidfire span, +.ui-dialog .tab-content .charsheet input, +.sheet-rolltemplate-rapidfire input, +.ui-dialog .tab-content .charsheet textarea, +.sheet-rolltemplate-rapidfire textarea { + font-size: 1rem; +} +.ui-dialog .tab-content .charsheet span, .sheet-rolltemplate-rapidfire span, .ui-dialog .tab-content .charsheet input, .sheet-rolltemplate-rapidfire input, .ui-dialog .tab-content .charsheet textarea, .sheet-rolltemplate-rapidfire textarea, .ui-dialog .tab-content .charsheet button, .sheet-rolltemplate-rapidfire button, .ui-dialog .tab-content .charsheet select, .sheet-rolltemplate-rapidfire select { + font-family: var(--contentFont); + --fontWght: 600; + font-weight: var(--fontWght); + font-variation-settings: "wght" var(--fontWght); +} +.ui-dialog .tab-content .charsheet input[type=checkbox], .sheet-rolltemplate-rapidfire input[type=checkbox] { + align-self: center; + border: 1px solid black; + cursor: pointer; +} +.ui-dialog .tab-content .charsheet input[type=radio], .sheet-rolltemplate-rapidfire input[type=radio] { + appearance: radio; +} +.ui-dialog .tab-content .charsheet input[type=number], .sheet-rolltemplate-rapidfire input[type=number] { + width: 3rem; + -moz-appearance: textfield !important; + text-align: center; +} +.ui-dialog .tab-content .charsheet input[type=number]::-webkit-inner-spin-button, .sheet-rolltemplate-rapidfire input[type=number]::-webkit-inner-spin-button, .ui-dialog .tab-content .charsheet input[type=number]::-webkit-outer-spin-button, .sheet-rolltemplate-rapidfire input[type=number]::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; +} +.ui-dialog .tab-content .charsheet .number, .sheet-rolltemplate-rapidfire .number { + width: 2rem; + box-sizing: border-box; +} +.ui-dialog .tab-content .charsheet section, .sheet-rolltemplate-rapidfire section { + gap: var(--half-gap); + align-self: start; +} +.ui-dialog .tab-content .charsheet section.page, .sheet-rolltemplate-rapidfire section.page { + display: none; +} +.ui-dialog .tab-content .charsheet section.inactive, .sheet-rolltemplate-rapidfire section.inactive { + display: none !important; +} +.ui-dialog .tab-content .charsheet .pseudo-button, .sheet-rolltemplate-rapidfire .pseudo-button { + display: inline; + cursor: pointer; + border-radius: 5px; + text-transform: uppercase; + border: 1px solid black; + text-align: center; + padding: 0 5px; +} +.ui-dialog .tab-content .charsheet .input-label, .sheet-rolltemplate-rapidfire .input-label { + display: inline-flex; + gap: var(--half-gap); + align-items: center; +} +.ui-dialog .tab-content .charsheet .input-label:not(.stacked) > [name]:not([type=number], [type=checkbox], [type=radio]), .sheet-rolltemplate-rapidfire .input-label:not(.stacked) > [name]:not([type=number], [type=checkbox], [type=radio]) { + width: 0; + flex: 1 1 0; +} +.ui-dialog .tab-content .charsheet .input-label:not(.stacked) > :not([name]), .sheet-rolltemplate-rapidfire .input-label:not(.stacked) > :not([name]) { + flex: 0 0 auto; +} +.ui-dialog .tab-content .charsheet .input-label--dual, .sheet-rolltemplate-rapidfire .input-label--dual { + grid-template-columns: 1fr auto 1fr; + grid-template-areas: "over over over" "under under under"; +} +.ui-dialog .tab-content .charsheet .input-label--dual > span:last-of-type, .sheet-rolltemplate-rapidfire .input-label--dual > span:last-of-type { + grid-column: 1/-1; +} +.ui-dialog .tab-content .charsheet .input-label--dual > input, .sheet-rolltemplate-rapidfire .input-label--dual > input { + width: 100%; +} +.ui-dialog .tab-content .charsheet .input-label--dual > .slash, .sheet-rolltemplate-rapidfire .input-label--dual > .slash { + line-height: 0rem; + font-weight: normal; +} +.ui-dialog .tab-content .charsheet .headed-textarea, .sheet-rolltemplate-rapidfire .headed-textarea { + grid-template-rows: auto 1fr; + grid-template-columns: auto; +} +.ui-dialog .tab-content .charsheet .headed-textarea h5, .sheet-rolltemplate-rapidfire .headed-textarea h5 { + justify-self: start; +} +.ui-dialog .tab-content .charsheet .boxed.thick-left, .sheet-rolltemplate-rapidfire .boxed.thick-left, +.ui-dialog .tab-content .charsheet .sheet-boxed.thick-left, +.sheet-rolltemplate-rapidfire .sheet-boxed.thick-left { + border-left-width: 5px; +} +.ui-dialog .tab-content .charsheet .boxed.thick-bottom, .sheet-rolltemplate-rapidfire .boxed.thick-bottom, +.ui-dialog .tab-content .charsheet .sheet-boxed.thick-bottom, +.sheet-rolltemplate-rapidfire .sheet-boxed.thick-bottom { + border-bottom-width: 5px; +} +.ui-dialog .tab-content .charsheet .boxed.thick-right, .sheet-rolltemplate-rapidfire .boxed.thick-right, +.ui-dialog .tab-content .charsheet .sheet-boxed.thick-right, +.sheet-rolltemplate-rapidfire .sheet-boxed.thick-right { + border-right-width: 5px; +} +.ui-dialog .tab-content .charsheet .boxed.thick-top, .sheet-rolltemplate-rapidfire .boxed.thick-top, +.ui-dialog .tab-content .charsheet .sheet-boxed.thick-top, +.sheet-rolltemplate-rapidfire .sheet-boxed.thick-top { + border-top-width: 5px; +} +.ui-dialog .tab-content .charsheet .underlined, .sheet-rolltemplate-rapidfire .underlined, +.ui-dialog .tab-content .charsheet .sheet-underlined, +.sheet-rolltemplate-rapidfire .sheet-underlined { + border-radius: 0; + border-bottom: 1px solid black; + transition: var(--focusTrans); +} +.ui-dialog .tab-content .charsheet :is(.underlined, .boxed):not([readonly]):is(:focus, :focus-within), .sheet-rolltemplate-rapidfire :is(.underlined, .boxed):not([readonly]):is(:focus, :focus-within) { + background-color: #DCDCDC; + transition: var(--focusTrans); +} +.ui-dialog .tab-content .charsheet .small-scale-grid, .sheet-rolltemplate-rapidfire .small-scale-grid, +.ui-dialog .tab-content .charsheet fieldset.small-scale-grid + .repcontainer, +.sheet-rolltemplate-rapidfire fieldset.small-scale-grid + .repcontainer { + grid-template-columns: [header-start] repeat(auto-fit, minmax(15rem, 1fr)) [header-end]; + grid-template-rows: [header-start] auto [header-end]; + gap: var(--half-gap); +} +.ui-dialog .tab-content .charsheet .small-scale-grid > .repitem, .sheet-rolltemplate-rapidfire .small-scale-grid > .repitem, +.ui-dialog .tab-content .charsheet fieldset.small-scale-grid + .repcontainer > .repitem, +.sheet-rolltemplate-rapidfire fieldset.small-scale-grid + .repcontainer > .repitem { + display: flex; + gap: var(--half-gap); +} +.ui-dialog .tab-content .charsheet .small-scale-grid > .repitem > :is(.dot-row, input[type=text]), .sheet-rolltemplate-rapidfire .small-scale-grid > .repitem > :is(.dot-row, input[type=text]), +.ui-dialog .tab-content .charsheet fieldset.small-scale-grid + .repcontainer > .repitem > :is(.dot-row, input[type=text]), +.sheet-rolltemplate-rapidfire fieldset.small-scale-grid + .repcontainer > .repitem > :is(.dot-row, input[type=text]) { + flex: 1 1 0; + width: 100%; +} +.ui-dialog .tab-content .charsheet .small-scale-grid .repcontrol_move, .sheet-rolltemplate-rapidfire .small-scale-grid .repcontrol_move, +.ui-dialog .tab-content .charsheet fieldset.small-scale-grid + .repcontainer .repcontrol_move, +.sheet-rolltemplate-rapidfire fieldset.small-scale-grid + .repcontainer .repcontrol_move { + display: none; +} +.ui-dialog .tab-content .charsheet .short-text, .sheet-rolltemplate-rapidfire .short-text { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + text-transform: initial; +} +.ui-dialog .tab-content .charsheet .roll-container, .sheet-rolltemplate-rapidfire .roll-container { + align-self: center; + opacity: 0; + grid-row: 1/2; +} +.ui-dialog .tab-content .charsheet .repitem > input:not([type=checkbox]), .sheet-rolltemplate-rapidfire .repitem > input:not([type=checkbox]) { + width: 100%; +} +.ui-dialog .tab-content .charsheet .repitem .headed-textarea, .sheet-rolltemplate-rapidfire .repitem .headed-textarea { + grid-column: 1/-1; +} +.ui-dialog .tab-content .charsheet .repitem .collapse, .sheet-rolltemplate-rapidfire .repitem .collapse { + opacity: 0; + position: absolute; + right: -10px; + top: 0px; + border: 0px solid black; + border-radius: 0; + color: var(--selectedColor); + text-transform: none; +} +.ui-dialog .tab-content .charsheet .repitem .collapse:before, .sheet-rolltemplate-rapidfire .repitem .collapse:before { + content: "y"; + font-family: pictos; +} +.ui-dialog .tab-content .charsheet .repitem .collapse:checked, .sheet-rolltemplate-rapidfire .repitem .collapse:checked { + background-color: transparent; + color: var(--unselectedColor); +} +.ui-dialog .tab-content .charsheet .repitem .collapse:checked ~ .expanded, .sheet-rolltemplate-rapidfire .repitem .collapse:checked ~ .expanded { + display: none; +} +.ui-dialog .tab-content .charsheet .repitem .collapse:checked ~ .expanded--empty:is(:not([value]), [value=""]) + *, .sheet-rolltemplate-rapidfire .repitem .collapse:checked ~ .expanded--empty:is(:not([value]), [value=""]) + * { + display: none; +} +.ui-dialog .tab-content .charsheet .repitem .collapse:hover, .sheet-rolltemplate-rapidfire .repitem .collapse:hover { + color: var(--selectedColor); +} +.ui-dialog .tab-content .charsheet .repitem:hover .collapse, .sheet-rolltemplate-rapidfire .repitem:hover .collapse, .ui-dialog .tab-content .charsheet .repitem:hover .roll-container, .sheet-rolltemplate-rapidfire .repitem:hover .roll-container { + opacity: 1; +} +.ui-dialog .tab-content .charsheet .repcontainer.editmode .collapse, .sheet-rolltemplate-rapidfire .repcontainer.editmode .collapse { + display: none; +} +.ui-dialog .tab-content .charsheet .repcontainer, .sheet-rolltemplate-rapidfire .repcontainer { + display: grid; + row-gap: var(--grid-gap); +} +.ui-dialog .tab-content .charsheet .repeating-container:is(:hover, :focus-within, :focus) .repcontrol-button, .sheet-rolltemplate-rapidfire .repeating-container:is(:hover, :focus-within, :focus) .repcontrol-button { + opacity: 1; +} +.ui-dialog .tab-content .charsheet .repcontrol-button, .sheet-rolltemplate-rapidfire .repcontrol-button { + grid-area: header; + align-self: center; + text-transform: none; + opacity: 0; + transition: opacity var(--revealTime); +} +.ui-dialog .tab-content .charsheet .repcontrol-button ~ .repcontrol, .sheet-rolltemplate-rapidfire .repcontrol-button ~ .repcontrol { + display: none; +} +.ui-dialog .tab-content .charsheet .repcontrol-button--add, .sheet-rolltemplate-rapidfire .repcontrol-button--add { + justify-self: start; +} +.ui-dialog .tab-content .charsheet .repcontrol-button--add:before, .sheet-rolltemplate-rapidfire .repcontrol-button--add:before { + font-family: pictos; + content: "&"; +} +.ui-dialog .tab-content .charsheet .repcontrol-button--edit, .sheet-rolltemplate-rapidfire .repcontrol-button--edit { + justify-self: end; +} +.ui-dialog .tab-content .charsheet .repcontrol-button--edit:before, .sheet-rolltemplate-rapidfire .repcontrol-button--edit:before { + font-family: pictos; + content: "p"; +} +.ui-dialog .tab-content .charsheet .box, .sheet-rolltemplate-rapidfire .box { + border-radius: 0; + width: 10px; + height: 10px; +} + +.ui-dialog .tab-content .charsheet *[data-i18n=xp] { + text-transform: uppercase; +} +.ui-dialog .tab-content .charsheet .stat-grid { + gap: var(--half-gap) var(--tiny-gap); +} +.ui-dialog .tab-content .charsheet .stat-grid > :not(input):not(h2) { + place-self: center end; +} +.ui-dialog .tab-content .charsheet .boxed.span-2 { + grid-auto-flow: column; + place-content: center; + width: 6.5rem; +} +.ui-dialog .tab-content .charsheet .roll-plus { + justify-self: center; +} +.ui-dialog .tab-content .charsheet .health-track .repcontainer { + grid-template-columns: repeat(auto-fill, 2rem); + row-gap: var(--tiny-gap); +} +.ui-dialog .tab-content .charsheet .health-track .repcontainer:hover .health-track__clearer { + background-image: linear-gradient(45deg, transparent 0% 48%, white 48% calc(48% + 1px), transparent calc(48% + 1px)), linear-gradient(-45deg, transparent 0% 48%, white 48% calc(48% + 1px), transparent calc(48% + 1px)); +} +.ui-dialog .tab-content .charsheet .health-track .repcontainer > .repitem { + grid-template-columns: 2rem; + grid-template-rows: repeat(2, 2rem); + grid-template-areas: "check" "penalty"; +} +.ui-dialog .tab-content .charsheet .health-track .repcontainer > .repitem:first-child .itemcontrol { + display: none !important; +} +.ui-dialog .tab-content .charsheet .health-track .repcontainer > .repitem .repcontrol_move { + display: none !important; +} +.ui-dialog .tab-content .charsheet .health-track .repcontrol { + display: none; +} +.ui-dialog .tab-content .charsheet .health-track__max-control[value="1"] ~ .repcontrol .repcontrol_edit { + display: none; +} +.ui-dialog .tab-content .charsheet .health-track__number:is(:hover, :focus) { + border-radius: 0; +} +.ui-dialog .tab-content .charsheet .health-track__checkbox { + border-radius: 0; + width: 100%; + height: 100%; + box-sizing: border-box; + grid-area: check; +} +.ui-dialog .tab-content .charsheet .health-track__clear-control:not(:checked) ~ .health-track__clearer { + display: none; +} +.ui-dialog .tab-content .charsheet .health-track__clearer { + grid-area: check; +} +.ui-dialog .tab-content .charsheet .health-track__clearer button { + width: 100%; + height: 100%; +} + +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border:after, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border__hex-content, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border:before { + overflow: hidden; + grid-template-areas: "content"; +} + +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border:after, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border__hex-content, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border:before { + width: 100%; + height: 100%; + grid-area: content; +} + +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border:before { + transform: rotate(-60deg); +} + +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border:before, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border:after { + box-sizing: border-box; + content: ""; + box-shadow: 0 0 0 1px black inset, 0 0 4px #ffffff inset; +} + +#settings, #character, #remnant { + gap: var(--big-gap); +} +.system-remnant#settings, .system-remnant#character, .system-remnant#remnant { + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); +} + +#character-info, #skill, #weapon, #adjustments .subsection, #remnant-ratings .remnant-skills, #remnant-specialty, #remnant-trait, #remnant-drone, #remnant-weapons { + grid-template-areas: "header"; + gap: var(--half-gap); + align-self: start; +} + +html { + font-size: 13px; +} + +ul.nav-tabs.nav { + position: sticky; + top: 0; + background-color: white; + z-index: 9999; + margin-bottom: 0px; +} + +.nav-tabs li a { + font-family: var(--midHeaderFont); + padding-top: 18px; + padding-bottom: 15px; +} +.nav-tabs li a[data-tab=charsheet] { + background-image: url(https://s3.amazonaws.com/files.d20.io/images/259063058/V4Hm27FqfgBujU8bI74Xaw/original.png); + background-size: contain; + background-repeat: no-repeat; + padding-left: 50px; + padding-right: 12px; +} + +.itemcontrol { + z-index: 10; +} + +.image-input { + cursor: pointer; +} + +.ui-dialog .tab-content .charsheet { + padding-top: 0px; +} +.ui-dialog .tab-content .charsheet .repeat-columns > * { + background-color: var(--subHeadBackColor); + border: 1px solid black; +} +.ui-dialog .tab-content .charsheet .image-container { + grid-template-columns: "content"; +} +.ui-dialog .tab-content .charsheet .image-container__input { + z-index: 10; + background-color: white; + box-shadow: 0 0 var(--grid-gap) var(--grid-gap) white; + grid-area: content; + place-self: center; + width: calc(100% - (var(--big-gap) * 2)); + transition: opacity var(--focusTiming), height var(--focusTiming); + opacity: 0; + height: 0; + overflow: hidden; +} +.ui-dialog .tab-content .charsheet .image-container__input span { + white-space: pre-wrap; +} +.ui-dialog .tab-content .charsheet .image-container__input input { + width: 100%; + box-sizing: border-box; +} +.ui-dialog .tab-content .charsheet .image-container__input.active { + opacity: 1; + height: auto; +} +.ui-dialog .tab-content .charsheet .image-container__button { + grid-area: content; +} +.ui-dialog .tab-content .charsheet .base-container { + grid-template-areas: "content"; +} +.ui-dialog .tab-content .charsheet .base-container__actual { + grid-area: content; +} +.ui-dialog .tab-content .charsheet .base-container__interact { + grid-area: content; + z-index: 1; +} + +#main-nav { + --tabColor:white; + --tabBorder:drop-shadow(1px 0 0 grey) drop-shadow(-1px 0 0 grey) drop-shadow(0 -1px 0 grey) drop-shadow(0 1px 0 black); + display: grid; + gap: var(--half-gap); + grid-template-columns: 1fr auto 1fr; + align-items: center; + position: sticky; + top: 60px; + background: white; + box-shadow: -10px 0 0 0 white, 10px 0 0 0 white, 0 -6px white; + z-index: 100; + border-bottom: 1px solid black; +} +#main-nav .nav__button { + font-style: normal; + color: grey; +} +#main-nav .nav__button--settings.active, #main-nav .nav__button--settings:hover { + color: black; +} +#main-nav.system-remnant { + /* + .tab:nth-of-type(2) { + background-color: #555; + top: 10px; + left: 30px; + z-index: 1; + color: #EEE; + } + .tab:nth-of-type(2):before { + background-color: #555; + } + .tab:nth-of-type(2):hover, + .tab:nth-of-type(2):hover:before { + background-color: #159; + transition: 0.3s ease-out; + }*/ +} +#main-nav.system-remnant .nav__button--tab { + background-color: var(--tabColor); + position: relative; + display: inline-block; + z-index: 2; + padding: calc(var(--half-gap) + 0.1rem); + filter: var(--tabBorder); +} +#main-nav.system-remnant .nav__button--tab.active, #main-nav.system-remnant .nav__button--tab:hover { + --tabBorder:drop-shadow(1px 0 0 black) drop-shadow(-1px 0 0 black) drop-shadow(0 -1px 0 black); + top: 1px; + color: black; +} +#main-nav.system-remnant .nav__button--tab.active { + pointer-events: none; +} +#main-nav.system-remnant .nav__button--tab:before { + height: calc(100% - 1px); + width: 50px; + background-color: var(--tabColor); + content: ""; + position: absolute; + z-index: -1; +} +#main-nav.system-remnant .nav__button--tab--left { + border-radius: 0 50% 0 0; + margin-left: 1px; + justify-self: start; +} +#main-nav.system-remnant .nav__button--tab--left:before { + border-radius: 0 2px 0 0; + left: calc(100% - 40px); + top: 0px; + -webkit-transform: skewX(45deg); + transform: skewX(45deg); +} +#main-nav.system-remnant .nav__button--tab--right { + border-radius: 50% 0 0 0; + margin-right: 1px; + justify-self: end; +} +#main-nav.system-remnant .nav__button--tab--right:before { + border-radius: 2px 0 0 0; + left: -5px; + top: 0px; + -webkit-transform: skewX(-45deg); + transform: skewX(-45deg); +} + +#main .system-header { + margin: 0 auto; + width: 200px; +} +#main article { + padding: var(--grid-gap); +} +#main article:not(.active) { + display: none; +} +#main .translate-control:checked ~ .untranslated, #main .translate-control:not(:checked) ~ .translated { + display: none; +} +#main .section { + transition: box-shadow var(--focusTiming), transform; + border-radius: 6px; + padding: var(--half-gap); +} +#main .section:hover { + box-shadow: rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px; +} + +#settings .input-label { + justify-content: space-between; +} +#settings .input-label [name]:not([type=number], [type=checkbox], [type=radio]) { + width: auto; + flex: 0 0 auto; +} +#settings section { + align-self: stretch; + align-content: start; +} + +#character.system-remnant { + grid-template-areas: "." "skills" "skills"; + border-left: 1px solid black; + grid-template-rows: repeat(2, auto) 1fr; +} + +#character-info > .health-track { + margin: 0 -5px; +} + +#stats { + grid-template-columns: auto 1fr repeat(2, auto); + grid-template-areas: "header header header header" "stat_points . . ." "reserve . . ." ". . . ." "header2 header2 header2 header2"; +} +#stats h2 { + grid-area: auto; + grid-column: 1/-1; +} +#stats > button { + grid-column: 2; +} +#stats > .stat_points { + grid-area: stat_points; + justify-self: end; +} +#stats > .reserve { + grid-area: reserve; + justify-self: end; +} +#stats > .reserve { + box-sizing: border-box; +} +#stats .equipment { + grid-template-areas: "header"; + gap: var(--half-gap); + grid-column: 1/-1; + place-self: stretch; +} +#stats .equipment h2 { + grid-area: header; +} +#stats .equipment .repeat-columns, +#stats .equipment .repitem { + grid-template-columns: 1fr 2.5rem; +} + +#secondary > .secondaries { + grid-template-columns: 1fr repeat(3, auto); + grid-template-areas: "header header header header"; +} +#secondary > .combat-gear { + grid-template-areas: "header"; +} + +#skill { + grid-area: skills; +} +#skill .repcontainer { + gap: 0; +} +#skill .repitem { + position: relative; +} +#skill .repitem span { + align-self: center; + text-align: left; +} +#skill .repeat-columns, +#skill .repitem { + grid-template-columns: 1rem 1fr 3rem 4rem 2.5rem; +} +#skill .repeat-columns > input, +#skill .repitem > input { + width: 100%; +} +#skill .repeat-columns :nth-child(1) { + grid-column: 2; +} +#skill .repeat-columns :nth-child(2) { + grid-column: 3; +} +#skill .repeat-columns :nth-child(3) { + grid-column: 4; +} +#skill .repeat-columns :nth-child(4) { + grid-column: 5; +} +#skill .raw-control:not(:checked) + .raw, +#skill .raw-control:checked ~ .custom { + display: none; +} +#skill .roller.raw { + grid-column: span 2; +} + +@media (min-width: 680px) { + #weapon, #remnant-weapons { + grid-column: span 2; + } +} +@media (min-width: 1300px) { + #main { + display: grid; + grid-template-columns: 1fr 1fr; + column-gap: var(--big-gap); + } + #main .system-header { + grid-column: 1/-1; + } + #main .sheet-state:not([value=settings]) ~ article:not(#settings) { + display: grid; + align-self: start; + } + #main .sheet-state:not([value=settings]) ~ #main-nav .nav__button--tab { + --tabBorder:drop-shadow(1px 0 0 black) drop-shadow(-1px 0 0 black) drop-shadow(0 -1px 0 black); + top: 1px; + color: black; + pointer-events: none; + } + + #settings { + grid-column: 1/-1; + } + + #main-nav { + grid-column: 1/-1; + } +} +#weapon input[type=text] { + width: 100%; +} +#weapon .repitem { + row-gap: var(--half-gap); +} +#weapon .repitem > .underlined { + width: 100%; +} +#weapon span.underlined { + display: block; + text-align: center; + padding: 2px; + box-sizing: border-box; + overflow: hidden; + text-overflow: ellipsis; + border-width: 1px 3px; + border-style: solid; + border-color: transparent transparent black transparent; +} +#weapon .repeat-columns, +#weapon .repitem { + grid-template-columns: 1rem 1fr 10rem 7rem; + align-items: end; +} +#weapon .repeat-columns :nth-child(1) { + grid-column: 2; +} +#weapon .repeat-columns :nth-child(2) { + grid-column: 3; +} +#weapon .repeat-columns :nth-child(3) { + grid-column: 4; +} +#weapon .headed-textarea { + grid-column: 1/-1; +} + +#adjustments { + display: contents; +} +#adjustments .repitem { + gap: var(--half-gap); +} +#adjustments input[type=text] { + width: 100%; +} +#remnant.system-remnant { + grid-template-areas: "image" "image"; + border-right: 1px solid black; + grid-template-rows: auto 1fr; +} + +#remnant-pic { + grid-area: image; +} +#remnant-pic > .input-label { + justify-self: start; +} + +#remnant-ratings { + grid-template-columns: 1fr repeat(2, auto); + grid-template-areas: "header header header"; +} +#remnant-ratings .remnant-skills { + grid-template-areas: "header header header"; + place-self: stretch; + grid-column: 1/-1; + gap: 0; +} +#remnant-ratings .remnant-skills * { + place-self: stretch; +} +#remnant-ratings .remnant-skills input { + width: 100%; +} +#remnant-ratings .remnant-skills, +#remnant-ratings .remnant-skills .repeat-columns { + grid-template-columns: 1fr 4rem 3rem; +} +#remnant-ratings .remnant-skills *, +#remnant-ratings .remnant-skills .repeat-columns * { + align-self: center; +} +#remnant-ratings .remnant-skills .repeat-columns { + grid-column: 1/-1; +} +#remnant-ratings .remnant-skills .repeat-columns :not(:first-child) { + text-align: center; +} +#remnant-ratings .remnant-skills .roller { + justify-self: start; +} +#remnant-ratings .remnant-skills input { + justify-self: center; +} + +#remnant-stats { + grid-template-columns: 1fr repeat(2, auto) 1fr repeat(2, auto); + grid-template-areas: "header header header header header header" ". . . . . ." ". . . . . ." ". . . . . ." "assault_damage_label assault_damage_label assault_damage_label assault_damage_label assault_damage_label assault_damage_input" "strike_damage_label strike_damage_label strike_damage_label strike_damage_label strike_damage_label strike_damage_input" "strike_range_label strike_range_label strike_range_label strike_range_label strike_range_label strike_range_input"; +} +#remnant-stats .strike_damage_label { + grid-area: strike_damage_label; +} +#remnant-stats .strike_damage_input { + grid-area: strike_damage_input; +} +#remnant-stats .strike_range_label { + grid-area: strike_range_label; +} +#remnant-stats .strike_range_input { + grid-area: strike_range_input; +} +#remnant-stats .assault_damage_label { + grid-area: assault_damage_label; +} +#remnant-stats .assault_damage_input { + grid-area: assault_damage_input; +} + +#remnant-trait .repeat-columns, +#remnant-trait .repitem { + grid-template-columns: 1fr 4rem 4rem; +} +#remnant-drone .repitem { + grid-template-columns: repeat(2, 1fr); + gap: var(--tiny-gap) var(--half-gap); +} +#remnant-drone .input-label--button { + grid-column: 1; +} +#remnant-drone .strikerange { + grid-column: 2; +} +#remnant-drone .input-label span, #remnant-drone .input-label button { + text-align: left; +} +#remnant-drone .input-label:not(.input-label--dual) :not([name]) { + flex: 1 1 0; +} +#remnant-drone .structure { + display: flex; + gap: var(--half-gap); + grid-column: 1/-1; + place-self: center end; + grid-column: span 2; +} +#remnant-drone .structure * { + align-self: center; +} + +#remnant-weapons .repeat-columns, +#remnant-weapons .repitem { + grid-template-columns: 1rem 1fr 5rem 4rem 7rem 8rem 5rem; +} +#remnant-weapons .repeat-columns :nth-child(1) { + grid-column: 2; +} +#remnant-weapons .repeat-columns :nth-child(2) { + grid-column: 3; +} +#remnant-weapons .repeat-columns :nth-child(3) { + grid-column: 4; +} +#remnant-weapons .repeat-columns :nth-child(4) { + grid-column: 5; +} +#remnant-weapons .repeat-columns :nth-child(5) { + grid-column: 6; +} +#remnant-weapons .repeat-columns :nth-child(6) { + grid-column: 7; +} +/* +Roll Template +#rolltemplate +*/ +.sheet-rolltemplate-rapidfire { + --templateRadius: 1rem; + --dieSize: 50px; + --templateBorderW: 2px 5px 2px 5px; + --fumbleColor: red; + --critColor: green; + --innerBorderRadius: 5px; + --borderSize:1px; + --sizeFactor: 6; + --cornerSize: calc(1107px / var(--sizeFactor)) calc(952px / var(--sizeFactor)); + --headSideMargin:40px; + --headVerticalMargin:10px; + --circleSize:73px; + --hexagonBackgroundImage:url("https://s3.amazonaws.com/files.d20.io/images/258492885/gzYgspdnfa8K2zUgTrgV3g/original.png"); + margin-left: -40px; + margin-right: -5px; +} +.sheet-rolltemplate-rapidfire a[href^="!"], +.sheet-rolltemplate-rapidfire a[href^="~"] { + font-family: var(--topHeaderFont); + background-color: transparent; + color: black; + font-weight: 700; + padding: 0; +} +.sheet-rolltemplate-rapidfire h1, .sheet-rolltemplate-rapidfire h2, .sheet-rolltemplate-rapidfire h3, .sheet-rolltemplate-rapidfire h4, .sheet-rolltemplate-rapidfire h5, .sheet-rolltemplate-rapidfire a { + white-space: pre-wrap; +} +.sheet-rolltemplate-rapidfire:not(:first-child) { + margin-top: 10px; +} +.sheet-rolltemplate-rapidfire .sheet-content { + overflow: hidden; +} +.sheet-rolltemplate-rapidfire > .sheet-template { + overflow: hidden; + --hexColor:#000000; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants { + padding: 15px 10px; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants > .sheet-content { + background-color: #c2c2c2; + background-image: var(--hexagonBackgroundImage); + background-position: top left; + background-size: 400px auto; + background-repeat: no-repeat; + padding: 0 10px; + border-radius: 10px; + border: 5px solid black; + grid-template-columns: [roll-start footer-start] var(--headSideMargin) [header-start] 1fr [damage-start] 1fr [roll-end difficulty-start] 1fr [damage-end] 1fr [footer-end] var(--headSideMargin) [difficulty-end header-end]; + grid-template-areas: ". header header header header header" ". . . . . ." ". . . . . ." ". . . . . ." ". . . . . ." "description description description description description description" "footer footer footer footer footer ."; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants > .sheet-content.sheet-single-roll .sheet-hexagon { + grid-column: damage-start/damage-end; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants + .sheet-image-border { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-repeat: no-repeat; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants + .sheet-image-border.sheet-has-header.sheet-has-footer { + background-image: var(--topCorner), var(--bottomCorner); + background-position: top left, bottom right; + background-size: var(--cornerSize), var(--cornerSize); +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants + .sheet-image-border.sheet-has-header:not(.sheet-has-footer) { + background-image: var(--topCorner); + background-position: top left; + background-size: var(--cornerSize); +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants + .sheet-image-border.sheet-has-footer:not(.sheet-has-header) { + background-image: var(--bottomCorner); + background-position: bottom right; + background-size: var(--cornerSize); +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-header, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-footer { + min-height: 30px; + align-items: center; + grid-template-areas: "content"; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-header *, .sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-footer * { + box-sizing: border-box; + grid-area: content; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-header { + --headBorder:0 3px 3px 3px; + --headRadius:0 0 10px 10px; + --headItems:center start; + --headSelf:start; + --headMargin:0 0 10px -3px; + --headPadding:5px 10px 10px 15px; + grid-column: 2/7; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-header * { + text-align: left; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-footer { + --headBorder:3px 3px 0 3px; + --headRadius:10px 10px 0 0; + --headItems:center end; + --headSelf:end; + --headMargin:9px -3px 0 0; + --headPadding:15px 15px 5px 5px; + grid-column: 1/6; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-footer * { + text-align: right; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-background { + grid-template-areas: "content"; + background-color: #aac1dd80; + border-color: black; + border-style: solid; + border-color: black; + border-width: var(--headBorder); + border-radius: var(--headRadius); + place-items: var(--headPlace); + margin: var(--headMargin); + place-self: var(--headSelf); + padding: var(--headPadding); + box-sizing: border-box; + backdrop-filter: blur(2px); + min-width: 120px; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-background * { + opacity: 0; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-header__content { + place-self: var(--headSelf); + grid-template-areas: "content"; + padding: var(--headPadding); + place-items: var(--headItems); + margin: var(--headMargin); + border-radius: var(--headRadius); +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-header__image { + width: 100%; + height: 100%; + background-image: var(--headerBottom); + background-position: bottom left; + background-size: calc(699px / var(--sizeFactor)) calc(130px / var(--sizeFactor)); + background-repeat: no-repeat; + z-index: 1; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-footer__content { + place-self: var(--headSelf); + grid-template-areas: "content"; + place-items: var(--headItems); + padding: var(--headPadding); + margin: var(--headMargin); + border-radius: var(--headRadius); +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-footer__image { + width: 100%; + height: 100%; + background-image: var(--footerTop); + background-position: top right; + background-size: calc(699px / var(--sizeFactor)) calc(130px / var(--sizeFactor)); + background-repeat: no-repeat; + z-index: 1; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-fumble-toggle + .sheet-hexagon__hex-wrapper { + --hexColor:#db1a1a; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-crit-toggle + .sheet-hexagon__hex-wrapper { + --hexColor:#02a98d; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon { + --shadow:black; + width: var(--circleSize); + aspect-ratio: 1/1.1547005; + transform: rotate(150deg); +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon h4 * { + font-family: var(--midHeaderFont); + font-weight: normal; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border { + background: radial-gradient(at 150%, #585858, var(--hexColor)); +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border:after { + transform: rotate(-120deg); +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-hexagon__hex-wrapper__hex-border__hex-content { + transform: rotate(-30deg); + grid-template-columns: auto; + grid-template-rows: auto auto; + gap: var(--half-gap); + place-items: center; + place-content: center; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-roll, +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-difficulty { + align-self: start; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-container-background { + background-color: white; + margin-right: -10px; + margin-left: -10px; + margin-bottom: -17px; + border-top: 2px solid black; + border-bottom: 2px solid black; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-container-background, +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-container-background + div { + margin-top: 15px; + padding-block: 5px; +} +.sheet-rolltemplate-rapidfire > .sheet-template.sheet-system-remnants .sheet-description.sheet-text h4 { + text-align: left; + margin-top: var(--grid-gap); + font-weight: 700; +} +.sheet-rolltemplate-rapidfire > .sheet-template span:not(.inlinerollresult) { + font-size: 13px; +} +.sheet-rolltemplate-rapidfire .sheet-roll:nth-child(even), +.sheet-rolltemplate-rapidfire .sheet-difficulty:nth-child(even) { + grid-column: roll-start/roll-end; +} +.sheet-rolltemplate-rapidfire .sheet-roll:nth-child(odd), +.sheet-rolltemplate-rapidfire .sheet-difficulty:nth-child(odd) { + grid-column: difficulty-start/difficulty-end; +} +.sheet-rolltemplate-rapidfire .sheet-damage:nth-child(even) { + grid-column: damage-start/damage-end; +} +.sheet-rolltemplate-rapidfire .sheet-damage:nth-child(odd) { + grid-column: difficulty-start/difficulty-end; +} +.sheet-rolltemplate-rapidfire .sheet-header { + grid-area: header; +} +.sheet-rolltemplate-rapidfire .sheet-description { + grid-area: description; +} +.sheet-rolltemplate-rapidfire .sheet-footer { + grid-area: footer; +} +.sheet-rolltemplate-rapidfire :not(div), +.sheet-rolltemplate-rapidfire .sheet-hexagon, +.sheet-rolltemplate-rapidfire .sheet-hexagon div, +.sheet-rolltemplate-rapidfire .sheet-text, +.sheet-rolltemplate-rapidfire .sheet-description:not(.sheet-container-background) { + position: relative; + z-index: 10; +} +.sheet-rolltemplate-rapidfire .inlinerollresult { + font-size: 1.5rem; +} +.sheet-rolltemplate-rapidfire .inlinerollresult[title*="[computed value]"], .sheet-rolltemplate-rapidfire .inlinerollresult[original-title*="[computed value]"] { + pointer-events: none; +} +.sheet-rolltemplate-rapidfire .inlinerollresult, .sheet-rolltemplate-rapidfire .inlinerollresult.fullcrit, .sheet-rolltemplate-rapidfire .inlinerollresult.fullfail, .sheet-rolltemplate-rapidfire .inlinerollresult.importantroll { + border: none; + background-color: transparent; +} +.sheet-rolltemplate-rapidfire .sheet-hexagon, .sheet-rolltemplate-rapidfire .sheet-circle { + place-self: center; +} +.sheet-rolltemplate-rapidfire .sheet-hexagon.sheet-damage, .sheet-rolltemplate-rapidfire .sheet-circle.sheet-damage { + justify-self: center; +} +.sheet-rolltemplate-rapidfire .sheet-hexagon :not(div), .sheet-rolltemplate-rapidfire .sheet-circle :not(div) { + color: white; +} \ No newline at end of file diff --git a/rapidfire_system/style.scss b/rapidfire_system/style.scss new file mode 100644 index 0000000000..d17377ca35 --- /dev/null +++ b/rapidfire_system/style.scss @@ -0,0 +1,902 @@ +@use 'Mixins/_systemplaceholders.scss'; + +//Sets the font-size to be used by rem unit calls +html{ + font-size: 13px; +} +//Sets the bio/charsheet/a&a tab container to be sticky and float at the top +ul.nav-tabs.nav{ + position:sticky; + top:0; + background-color:white; + z-index:9999; + margin-bottom:0px; +} +.nav-tabs li a{ + font-family:var(--midHeaderFont); + padding:{ + top: 18px; + bottom:15px; + }; + &[data-tab='charsheet']{ + background-image: url(https://s3.amazonaws.com/files.d20.io/images/259063058/V4Hm27FqfgBujU8bI74Xaw/original.png); + background-size: contain; + background-repeat: no-repeat; + padding:{ + left:50px; + right:12px; + }; + } +} +.itemcontrol{ + z-index:10; +} +.image-input{ + cursor:pointer; +} +//Default settings for the .charsheet container +.ui-dialog .tab-content .charsheet{ + padding-top:0px; + @extend %defaultStyles; + .adaptive-text{ + @extend %adaptiveText; + } + .repeat-columns{ + @extend %grid; + > *{ + background-color:var(--subHeadBackColor); + border:1px solid black; + } + } + .image-container{ + @extend %grid; + grid-template-columns:"content"; + } + .image-container__input{ + z-index:10; + background-color:white; + box-shadow:0 0 var(--grid-gap) var(--grid-gap) white; + grid-area:content; + place-self:center; + width:calc(100% - (var(--big-gap) * 2)); + transition:opacity var(--focusTiming),height var(--focusTiming); + opacity:0; + height:0; + overflow:hidden; + span{ + white-space: pre-wrap; + } + input{ + width:100%; + box-sizing:border-box; + } + &.active{ + opacity:1; + height:auto; + } + } + .image-container__button{ + grid-area:content; + } + .base-container{ + @extend %grid; + grid-template-areas:'content'; + } + .base-container__actual{ + grid-area:content; + } + .base-container__interact{ + grid-area:content; + z-index:1; + } +} +#main-nav{ + --tabColor:white; + --tabBorder:drop-shadow(1px 0 0 grey) drop-shadow(-1px 0 0 grey) drop-shadow(0 -1px 0 grey) drop-shadow(0 1px 0 black); + display:grid; + gap:var(--half-gap); + grid-template-columns:1fr auto 1fr; + align-items:center; + position:sticky; + top:60px; + background:white; + box-shadow:-10px 0 0 0 white,10px 0 0 0 white,0 -6px white; + z-index:100; + border-bottom:1px solid black; + .nav__button{ + font-style:normal; + color:grey; + } + .nav__button--settings{ + @extend %pictos; + &.active, + &:hover{ + color:black; + } + } + &.system-remnant{ + .nav__button--tab { + background-color: var(--tabColor); + position: relative; + display: inline-block; + z-index: 2; + padding:calc(var(--half-gap) + 0.1rem); + filter:var(--tabBorder); + &.active, + &:hover{ + @include systemplaceholders.activeTab; + } + &.active{ + pointer-events: none; + } + &:before{ + height: calc(100% - 1px); + width: 50px; + background-color: var(--tabColor); + content: ""; + position: absolute; + z-index: -1; + } + } + .nav__button--tab--left{ + border-radius:0 50% 0 0; + margin-left:1px; + justify-self:start; + &:before{ + border-radius: 0 2px 0 0; + left: calc(100% - 40px); + top: 0px; + -webkit-transform: skewX(45deg); + transform: skewX(45deg); + } + } + .nav__button--tab--right{ + border-radius:50% 0 0 0; + margin-right:1px; + justify-self:end; + &:before{ + border-radius: 2px 0 0 0; + left: -5px; + top: 0px; + -webkit-transform: skewX(-45deg); + transform: skewX(-45deg); + } + }/* + .tab:nth-of-type(2) { + background-color: #555; + top: 10px; + left: 30px; + z-index: 1; + color: #EEE; + } + .tab:nth-of-type(2):before { + background-color: #555; + } + .tab:nth-of-type(2):hover, + .tab:nth-of-type(2):hover:before { + background-color: #159; + transition: 0.3s ease-out; + }*/ + } +} +#main{ + .system-header{ + margin:0 auto; + width:200px; + } + article{ + padding:var(--grid-gap); + } + article:not(.active){ + display:none; + } + .roller{ + @extend %roller; + } + .translate-control{ + &:checked ~ .untranslated, + &:not(:checked) ~ .translated{ + display:none; + } + } + .section{ + transition:box-shadow var(--focusTiming),transform; + border-radius:6px; + padding:var(--half-gap); + &:hover{ + box-shadow: rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px; + } + } +} +// Settings Styling +#settings{ + @extend %article-layout; + .input-label{ + justify-content: space-between; + [name]:not([type=number], [type=checkbox], [type=radio]){ + width:auto; + flex: 0 0 auto; + } + } + section{ + align-self:stretch; + align-content:start; + } +} +// Character styling +#character{ + @extend %article-layout; + &.system-remnant{ + grid-template-areas: + "." + "skills" + "skills" + ; + border:{ + left:1px solid black; + } + grid-template-rows:repeat(2,auto) 1fr; + } +} +#character-info{ + @extend %repeat-section-layout; + > .health-track{ + margin:0 -5px; + } +} +#stats{ + grid-template-columns: auto 1fr repeat(2,auto); + grid-template-areas: + 'header header header header' + 'stat_points . . .' + 'reserve . . .' + '. . . .' + 'header2 header2 header2 header2' + ; + h2{ + grid-area:auto; + grid-column:1/-1; + } + > button{ + grid-column:2; + } + @each $point in stat_points,reserve{ + > .#{$point}{ + grid-area:$point; + justify-self:end; + } + } + > .reserve{ + box-sizing:border-box; + } + .equipment{ + @extend %grid; + grid-template-areas: 'header'; + gap:var(--half-gap); + grid-column:1/-1; + place-self:stretch; + h2{ + grid-area:header; + } + .repitem{ + @extend %grid; + } + .repeat-columns, + .repitem{ + grid-template-columns: 1fr 2.5rem; + } + } +} +#secondary{ + > .secondaries{ + @extend %grid; + grid-template-columns:1fr repeat(3,auto); + grid-template-areas:'header header header header'; + } + > .combat-gear{ + @extend %grid; + grid-template-areas:'header'; + } +} +#skill{ + @extend %repeat-section-layout; + grid-area:skills; + .repcontainer{ + gap:0; + } + .repitem{ + @extend %grid; + position:relative; + span{ + align-self:center; + text-align:left; + } + } + .repeat-columns, + .repitem{ + grid-template-columns:1rem 1fr 3rem 4rem 2.5rem; + > input{ + width:100%; + } + } + .repeat-columns{ + @each $num in 1,2,3,4{ + :nth-child(#{$num}){ + grid-column:$num + 1; + } + } + } + .raw-control:not(:checked) + .raw, + .raw-control:checked ~ .custom{ + display:none; + } + .roller.raw{ + grid-column:span 2; + } +} +@media (min-width:680px) { + #weapon,#remnant-weapons{ + grid-column:span 2; + } +} +@media(min-width:1300px){ + #main{ + display:grid; + grid-template-columns:1fr 1fr; + column-gap:var(--big-gap); + .system-header{ + grid-column:1/-1; + } + .sheet-state:not([value='settings']){ + ~ article:not(#settings){ + display:grid; + align-self:start; + } + ~ #main-nav{ + .nav__button--tab{ + @include systemplaceholders.activeTab; + pointer-events: none; + } + } + } + } + #settings{ + grid-column:1/-1; + } + #main-nav{ + grid-column:1/-1; + } +} +#weapon{ + @extend %repeat-section-layout; + input[type='text']{ + width:100%; + } + .repitem{ + @extend %grid; + row-gap:var(--half-gap); + > .underlined{ + width:100%; + } + } + span.underlined{ + display:block; + text-align:center; + padding:2px; + box-sizing: border-box; + overflow: hidden; + text-overflow: ellipsis; + border:{ + width:1px 3px; + style:solid; + color:transparent transparent black transparent; + }; + } + .repeat-columns, + .repitem{ + grid-template-columns:1rem 1fr 10rem 7rem; + align-items:end; + } + .repeat-columns{ + @each $num in 1,2,3{ + :nth-child(#{$num}){ + grid-column:$num + 1; + } + } + } + .headed-textarea{ + grid-column:1/-1; + } +} +#adjustments{ + display:contents; + .repitem{ + @extend %grid; + gap:var(--half-gap); + } + input[type='text']{ + width:100%; + } + .subsection{ + @extend %repeat-section-layout; + } +} + +// Battle Remnant Styling +#remnant{ + @extend %article-layout; + &.system-remnant{ + grid-template-areas: + "image" + "image" + ; + border:{ + right:1px solid black; + } + grid-template-rows:auto 1fr; + } +} +#remnant-pic{ + grid-area:image; + >.input-label{ + justify-self:start; + } +} +#remnant-ratings{ + @extend %grid; + grid-template-columns:1fr repeat(2,auto); + grid-template-areas:'header header header'; + .remnant-skills{ + @extend %repeat-section-layout; + grid-template-areas:'header header header'; + place-self:stretch; + grid-column:1/-1; + gap:0; + *{ + place-self:stretch; + } + input{ + width:100%; + } + &, + .repeat-columns{ + grid-template-columns:1fr 4rem 3rem; + *{ + align-self:center; + } + } + .repeat-columns{ + grid-column:1/-1; + :not(:first-child){ + text-align:center; + } + } + .roller{ + justify-self:start; + } + input{ + justify-self:center; + } + } +} +#remnant-stats{ + @extend %grid; + grid-template-columns:1fr repeat(2,auto) 1fr repeat(2,auto); + grid-template-areas: + 'header header header header header header' + '. . . . . .' + '. . . . . .' + '. . . . . .' + 'assault_damage_label assault_damage_label assault_damage_label assault_damage_label assault_damage_label assault_damage_input' + 'strike_damage_label strike_damage_label strike_damage_label strike_damage_label strike_damage_label strike_damage_input' + 'strike_range_label strike_range_label strike_range_label strike_range_label strike_range_label strike_range_input' + ; + @each $field in strike_damage,strike_range,assault_damage{ + .#{$field}_label{ + grid-area:#{$field}_label; + } + .#{$field}_input{ + grid-area:#{$field}_input; + } + } +} +#remnant-specialty{ + @extend %repeat-section-layout; +} +#remnant-trait{ + @extend %repeat-section-layout; + .repeat-columns, + .repitem{ + grid-template-columns:1fr 4rem 4rem; + } + .repitem{ + @extend %grid; + } +} +#remnant-drone{ + @extend %repeat-section-layout; + .repitem{ + @extend %grid; + grid-template-columns:repeat(2,1fr); + gap:var(--tiny-gap) var(--half-gap); + } + .input-label--button{ + grid-column:1; + } + .strikerange{ + grid-column:2; + } + .input-label{ + span,button{ + text-align:left; + } + &:not(.input-label--dual){ + :not([name]){ + flex:1 1 0; + } + } + } + .structure{ + display:flex; + gap:var(--half-gap); + grid-column:1/-1; + place-self:center end; + grid-column:span 2; + *{ + align-self:center; + } + } +} +#remnant-weapons{ + @extend %repeat-section-layout; + .repeat-columns, + .repitem{ + grid-template-columns:1rem 1fr 5rem 4rem 7rem 8rem 5rem; + } + .repeat-columns{ + @each $num in 1,2,3,4,5,6{ + :nth-child(#{$num}){ + grid-column:$num + 1; + } + } + } + .repitem{ + @extend %grid; + } +} +/* +Roll Template +#rolltemplate +*/ +.sheet-rolltemplate-rapidfire{ + @extend %font-vars; + --templateRadius: 1rem; + --dieSize: 50px; + --templateBorderW: 2px 5px 2px 5px; + --fumbleColor: red; + --critColor: green; + --innerBorderRadius: 5px; + --borderSize:1px; + --sizeFactor: 6; + --cornerSize: calc(1107px / var(--sizeFactor)) calc(952px / var(--sizeFactor)); + --headSideMargin:40px; + --headVerticalMargin:10px; + --circleSize:73px; + --hexagonBackgroundImage:url('https://s3.amazonaws.com/files.d20.io/images/258492885/gzYgspdnfa8K2zUgTrgV3g/original.png'); + margin:{//ensures that the template fills the chat window + left: -40px; + right: -5px; + } + @extend %defaultStyles; + a[href^='!'], + a[href^='~']{ + font-family: var(--topHeaderFont); + background-color: transparent; + color: black; + font-weight: 700; + padding: 0; + } + h1,h2,h3,h4,h5,a{ + white-space: pre-wrap; + } + &:not(:first-child){//Moves the template to accomodate the sender tag + margin-top:10px; + } + .sheet-content{ + @extend %grid; + overflow:hidden; + } + > .sheet-template{ + overflow:hidden; + --hexColor:#000000; + &.sheet-system-remnants{ + padding:15px 10px; + > .sheet-content{ + background-color: #c2c2c2; + background:{ + image:var(--hexagonBackgroundImage); + position:top left; + size:400px auto; + repeat:no-repeat; + }; + padding:0 10px; + border-radius:10px; + border:5px solid black; + grid-template-columns:[roll-start footer-start] var(--headSideMargin) [header-start] 1fr [damage-start] 1fr [roll-end difficulty-start] 1fr [damage-end] 1fr [footer-end] var(--headSideMargin)[difficulty-end header-end]; + grid-template-areas: + '. header header header header header' + '. . . . . .' + '. . . . . .' + '. . . . . .' + '. . . . . .' + 'description description description description description description' + 'footer footer footer footer footer .' + ; + &.sheet-single-roll{ + .sheet-hexagon{ + grid-column:damage-start / damage-end; + } + } + } + + .sheet-image-border{ + position:absolute; + top:0; + left:0; + right:0; + bottom:0; + background-repeat:no-repeat; + &.sheet-has-header.sheet-has-footer{ + background:{ + image:var(--topCorner), var(--bottomCorner); + position:top left, bottom right; + size:var(--cornerSize),var(--cornerSize); + }; + } + &.sheet-has-header:not(.sheet-has-footer){ + background:{ + image:var(--topCorner); + position:top left; + size:var(--cornerSize); + }; + } + &.sheet-has-footer:not(.sheet-has-header){ + background:{ + image:var(--bottomCorner); + position:bottom right; + size:var(--cornerSize); + }; + } + } + .sheet-header,.sheet-footer{ + @extend %grid; + min-height: 30px; + align-items: center; + grid-template-areas:'content'; + *{ + box-sizing:border-box; + grid-area:content; + } + } + .sheet-header{ + --headBorder:0 3px 3px 3px; + --headRadius:0 0 10px 10px; + --headItems:center start; + --headSelf:start; + --headMargin:0 0 10px -3px; + --headPadding:5px 10px 10px 15px; + grid-column:2/7; + *{ + text-align:left; + } + } + .sheet-footer{ + --headBorder:3px 3px 0 3px; + --headRadius:10px 10px 0 0; + --headItems:center end; + --headSelf:end; + --headMargin:9px -3px 0 0; + --headPadding:15px 15px 5px 5px; + grid-column:1/6; + *{ + text-align:right; + } + } + .sheet-background{ + @extend %grid; + grid-template-areas: 'content'; + background-color: #aac1dd80; + border-color:black; + border-style: solid; + border-color: black; + border-width:var(--headBorder); + border-radius:var(--headRadius); + place-items:var(--headPlace); + margin:var(--headMargin); + place-self:var(--headSelf); + padding:var(--headPadding); + box-sizing:border-box; + backdrop-filter: blur(2px); + min-width:120px; + *{ + opacity:0; + } + } + .sheet-header__content{ + @extend %grid; + place-self:var(--headSelf); + grid-template-areas:'content'; + padding:var(--headPadding); + place-items:var(--headItems); + margin:var(--headMargin); + border-radius:var(--headRadius); + } + .sheet-header__image{ + width:100%; + height:100%; + background:{ + image:var(--headerBottom); + position:bottom left; + size:calc(699px / var(--sizeFactor)) calc(130px / var(--sizeFactor)); + repeat:no-repeat; + }; + z-index:1; + } + .sheet-footer__content{ + @extend %grid; + place-self:var(--headSelf); + grid-template-areas:'content'; + place-items:var(--headItems); + padding: var(--headPadding); + margin:var(--headMargin); + border-radius:var(--headRadius); + } + .sheet-footer__image{ + width:100%; + height:100%; + background:{ + image:var(--footerTop); + position:top right; + size:calc(699px / var(--sizeFactor)) calc(130px / var(--sizeFactor)); + repeat:no-repeat; + }; + z-index:1; + } + .sheet-fumble-toggle + .sheet-hexagon__hex-wrapper{ + --hexColor:#db1a1a; + } + .sheet-crit-toggle + .sheet-hexagon__hex-wrapper{ + --hexColor:#02a98d; + } + .sheet-hexagon{ + @extend %hex-base; + --shadow:black; + width:var(--circleSize); + aspect-ratio: 1 / 1.1547005; + transform:rotate(150deg); + h4 *{ + font-family:var(--midHeaderFont); + font-weight:normal; + } + } + .sheet-hexagon__hex-wrapper{ + @extend %hex-rotate; + } + .sheet-hexagon__hex-wrapper__hex-border{ + @extend %hex-rotate; + @extend %hex-shape; + background:radial-gradient(at 150%,#585858,var(--hexColor)); + &:before{ + @extend %hex-shape; + @extend %hex-rotate; + } + &:after{ + @extend %hex-shape; + @extend %hex-component; + transform:rotate(-120deg); + } + } + .sheet-hexagon__hex-wrapper__hex-border__hex-content{ + @extend %hex-component; + transform:rotate(-30deg); + grid-template-columns:auto; + grid-template-rows:auto auto; + gap:var(--half-gap); + place-items:center; + place-content:center; + } + .sheet-roll, + .sheet-difficulty{ + align-self:start; + } + .sheet-container-background{ + background-color:white; + margin:{ + right:-10px; + left:-10px; + bottom: -17px; + }; + border:{ + top:2px solid black; + bottom:2px solid black; + } + &, + + div{ + margin-top:15px; + padding-block:5px; + } + } + .sheet-description.sheet-text{ + h4{ + text-align:left; + margin-top:var(--grid-gap); + font-weight:700; + } + } + } + span:not(.inlinerollresult){ + font-size:13px; + } + } + .sheet-roll, + .sheet-difficulty{ + &:nth-child(even){ + grid-column:roll-start / roll-end; + } + &:nth-child(odd){ + grid-column:difficulty-start / difficulty-end; + } + } + .sheet-damage{ + &:nth-child(even){ + grid-column:damage-start / damage-end; + } + &:nth-child(odd){ + grid-column:difficulty-start / difficulty-end; + } + } + @each $area in header,description,footer{ + .sheet-#{$area}{ + grid-area:$area; + } + } + :not(div), + .sheet-hexagon, + .sheet-hexagon div, + .sheet-text, + .sheet-description:not(.sheet-container-background){ + position:relative; + z-index:10; + } + .inlinerollresult{ + font-size:1.5rem; + &[title*="[computed value]"], + &[original-title*="[computed value]"]{ + pointer-events: none; + } + &, + &.fullcrit, + &.fullfail, + &.importantroll{ + border: none; + background-color: transparent; + } + &.fullcrit{ + + } + &.fullfail{ + + } + &.importantroll{ + + } + } + .sheet-hexagon,.sheet-circle{ + place-self:center; + &.sheet-damage{ + justify-self:center; + } + :not(div){ + color:white; + } + } +} \ No newline at end of file diff --git a/rapidfire_system/system.html b/rapidfire_system/system.html new file mode 100644 index 0000000000..50bcdc4b4f --- /dev/null +++ b/rapidfire_system/system.html @@ -0,0 +1,1829 @@ + + + + +
+ + + +
+
+ + + +
+
+ +
+
+
+
+

+

+ + + + +
+
+
+
+ +
+
+
+

+

+ +
+ + + + +
+
+
+
+

+

+ + + + + + + + + + + + + + + + + +
+

+

+ +
+
+
+
+ + +
+ + + +
+
+
+
+ +
+
+
+
+
+
+
+

+

+ + + + + + + + + + + + +
+ / + +
+ +
+
+

+

+ + + +
+
+
+

+
+
+
+
+
+
+ + +
+ + + + + + + + + + + +
+
+
+
+

+

+
+
+
+ + +
+ + +
+
+
+
+ +
+
+
+
+
+

+

+
+
+
+ + +
+ + +
+
+
+
+ +
+
+
+
+
+

+

+
+
+
+ + +
+ + +
+
+
+
+ +
+
+
+
+
+
+

+
+
+
+
+
+ + +
+ + + + + + + +
+ + +
+
+
+
+
+ +
+
+
+
+
+
+
+
+

+

+ +
+ + + + +
+
+ +
+ + +
+
+
+

+

+ + + + + +

+ + + + + + + +
+

+

+
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + +
+
+
+

+

+ + + + + + + + +
+ +
+ / + + +
+
+ + + + + + +
+
+

+
+
+
+ + +
+ + +
+
+
+
+ +
+
+
+
+
+

+
+
+
+
+
+ + +
+ + + + +
+
+
+
+ +
+
+
+
+
+

+

+ + +
+ + + + + + + +
+
+ / + +
+
+ +
+ + +
+ + + + + +
+ + +
+ + + + + + +
+
+
+
+ +
+
+
+
+
+

+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +
+ + + + + + + +
+ + +
+ + +
+
+
+
+ +
+
+
+
+
+
+ +
+
{{#header}} +
+
+

{{header}}

+
+
+

{{header}}

+
+
+
{{/header}}{{#roll}} +
{{#rollLess() computed::status -2}}{{/rollLess() computed::status -2}}{{#rollGreater() computed::status 4}}{{/rollGreater() computed::status 4}} +
+
+
+

{{roll}} +
+
+
+
{{/roll}}{{#roll1}} +
{{#rollLess() computed::status1 -2}}{{/rollLess() computed::status1 -2}}{{#rollGreater() computed::status1 4}}{{/rollGreater() computed::status1 4}} +
+
+
+

{{roll1}} +
+
+
+
{{/roll1}}{{#roll2}} +
{{#rollLess() computed::status2 -2}}{{/rollLess() computed::status2 -2}}{{#rollGreater() computed::status2 4}}{{/rollGreater() computed::status2 4}} +
+
+
+

{{roll2}} +
+
+
+
{{/roll2}}{{#roll3}} +
{{#rollLess() computed::status3 -2}}{{/rollLess() computed::status3 -2}}{{#rollGreater() computed::status3 4}}{{/rollGreater() computed::status3 4}} +
+
+
+

{{roll3}} +
+
+
+
{{/roll3}}{{#roll4}} +
{{#rollLess() computed::status4 -2}}{{/rollLess() computed::status4 -2}}{{#rollGreater() computed::status4 4}}{{/rollGreater() computed::status4 4}} +
+
+
+

{{roll4}} +
+
+
+
{{/roll4}}{{#roll5}} +
{{#rollLess() computed::status5 -2}}{{/rollLess() computed::status5 -2}}{{#rollGreater() computed::status5 4}}{{/rollGreater() computed::status5 4}} +
+
+
+

{{roll5}} +
+
+
+
{{/roll5}}{{#roll6}} +
{{#rollLess() computed::status6 -2}}{{/rollLess() computed::status6 -2}}{{#rollGreater() computed::status6 4}}{{/rollGreater() computed::status6 4}} +
+
+
+

{{roll6}} +
+
+
+
{{/roll6}}{{#difficulty}} +
+
+
+
+

{{difficulty}} +
+
+
+
{{/difficulty}}{{#damage}} +
+
+
+
{{#damage_label}} +

{{computed::damage_label}}

{{/damage_label}}{{^damage_label}} +

{{/damage_label}}{{computed::damage}} +
+
+
+
{{/damage}}{{#description}} +
+
+

{{description}}{{#allprops() description damage difficulty roll roll1 roll2 roll3 roll4 roll5 roll6 header footer character_id system single-roll custom_description status}} +

{{key}}

{{value}}{{/allprops() description damage difficulty roll roll1 roll2 roll3 roll4 roll5 roll6 header footer character_id system single-roll custom_description status}} +
{{/description}}{{^description}}{{#custom_description}} +
+
{{#allprops() description damage difficulty roll roll1 roll2 roll3 roll4 roll5 roll6 header footer character_id system single-roll custom_description status}} +

{{key}}

{{value}}{{/allprops() description damage difficulty roll roll1 roll2 roll3 roll4 roll5 roll6 header footer character_id system single-roll custom_description status}} +
{{/custom_description}}{{/description}}{{#footer}} + {{/footer}} +
+
+
+
+ \ No newline at end of file diff --git a/rapidfire_system/system.pug b/rapidfire_system/system.pug new file mode 100644 index 0000000000..fe742789bf --- /dev/null +++ b/rapidfire_system/system.pug @@ -0,0 +1,321 @@ +include Mixins/_htmlelements.pug +include Mixins/_rolltemplate mixins.pug +include Mixins/_Sheet Mixins.pug ++hidden({name:'template_start',value:'&{template:rapidfire} {{footer=@{character_name}}} {{character_id=@{character_id}}} {{system=@{system}}}'}) ++hidden({name:'collapsed',value:''}) ++hidden({name:'system',value:'remnants'}) +main#main.subsystem-style.system-remnant + +hidden({name:'sheet_state',value:'settings',class:'sheet-state'}) + +hidden({name:'system header'}) + +img({name:'system header',role:'heading','aria-level':1,class:'system-header','data-i18n':'system header'}) + nav#main-nav.subsystem-style.system-remnant + +navButton({name:'character','data-i18n':'character',class:'nav__button nav__button--tab nav__button--tab--left character',role:'heading','aria-level':4}) + +navButton({name:'settings',class:'active nav__button nav__button--settings settings'}) + |y + +navButton({name:'battle remnant','data-i18n':'battle remnant',class:'nav__button nav__button--tab nav__button--tab--right battle-remnant',role:'heading','aria-level':4}) + article#settings.subsystem-style.system-remnant.settings.active + section#system-behavior.section + +select-label('setting',{name:'system',class:'underlined'},null,{role:'heading','aria-level':4}) + +option({value:'remnants','data-i18n':'remnants',selected:''}) + +input-label('difficulty automation',{name:'difficulty',value:'1',checked:'',class:'box',type:'checkbox'},null,{role:'heading','aria-level':4}) + +select-label('action penalty automation',{name:'action penalty automation',class:'underlined'},null,{role:'heading','aria-level':4}) + each value,index in ['disabled','ask','use input'] + - let optObj = {value,'data-i18n':value}; + if index === 0 + - optObj.selected = ''; + +option({value,'data-i18n':value}) + section#sheet-behavior.section + +select-label('whisper rolls to gm',{name:'whisper',class:'underlined'},null,{role:'heading','aria-level':4}) + +option({value:' ','data-i18n':'never',selected:''}) + +option({value:'/w gm ','data-i18n':'always'}) + +option({value:'?{Whisper|No, |Yes,/w gm }','data-i18n':'ask'}) + article#character.character.subsystem-style.system-remnant + section#character-info.section + +h2({'data-i18n':'character info'}) + each field in characterFields + +input-label(field,{name:field,type:'text',class:`underlined ${replaceSpaces(field)}`},{},{role:'heading','aria-level':5}) + .headed-textarea.appearance + +h5({'data-i18n':'appearance / mannerisms'}) + +adaptiveTextarea({name:'appearance/mannerisms',class:'underlined'}) + +track('health track','health') + section#stats.stat-grid.section.repeating-container + +h2({'data-i18n':'stats'}) + +input-label('stat points',{name:'stat points',class:'boxed',type:'number'},{class:'stat_points'},{role:'heading','aria-level':4}) + +input-label('reserve',{name:'reserve',class:'boxed',type:'number'},{class:'reserve'},{role:'heading','aria-level':4}) + each name in stats + +roller({name,role:'heading','aria-level':4,'data-i18n':name}) + +select({name,class:'boxed number'}) + each value in [-3,-2,-1,0,1,2,3] + - let optObj = {value}; + if value === 0 + - optObj.selected = ''; + +option(optObj) + !=value + +number({name:`${name} mod`,class:'boxed'}) + .repeating-container__equipment.equipment.subsection + +h2({'data-i18n':'gear and money'}) + +input-label('easy living',{name:'easy living',class:'boxed',type:'number'},{},{role:'heading','aria-level':4}) + .repeat-columns + h5(data-i18n='name') + h5(data-i18n='quantity abbreviation') + +customControlFieldset('equipment') + +checkbox({name:'collapse',class:'collapse',title:attrTitle('equipment','collapse')}) + +text({name:'name',class:'underlined',role:'heading','aria-level':3,title:attrTitle('equipment','name')}) + +number({name:'quantity',class:'underlined',title:attrTitle('equipment','quantity')}) + .headed-textarea.notes.expanded + +h5({'data-i18n':'notes'}) + +adaptiveTextarea({name:'notes',class:'underlined',title:attrTitle('equipment','notes')}) + section#secondary.section + .secondaries.stat-grid + +h2({'data-i18n':'secondary stats'}) + +roller({name:'initiative',class:`initiative-label span-2`,'data-i18n':'initiative',role:'heading','aria-level':4}) + +number({name:'initiative',class:`boxed initiative`,readonly:'',value:'0'}) + +number({name:`initiative mod`,class:`boxed initiative_mod`}) + each name in secondaries + label(for=`${name}-mod` class=`${name}-label span-2` data-i18n=name role='heading' aria-level=4) + +number({name,class:`boxed ${name}`,readonly:'',value:secondaryDefaults[name]}) + +number({name:`${name} mod`,class:`boxed ${name}_mod`,id:`${name}-mod`}) + label(for='health' class='health-label' data-i18n='health',role='heading' aria-level=4) + .boxed.span-2 + +number({name:'health',id:'health'}) + span.slash / + +number({name:'health max',readonly:''}) + +number({name:`health mod`,class:`boxed health_mod`}) + .combat-gear.stat-grid + +h2({'data-i18n':'combat gear'}) + each name in combatGear + +input-label(name,{name,class:'boxed',type:'number'},{class:`${name} contents`},{role:'heading','aria-level':4}) + +repeating_section('skill','skills',['skills','level','stat','xp']) + +checkbox({name:'raw',hidden:'',class:'raw-control',value:1,title:attrTitle('skill','raw')}) + +roller({name:'roll',title:buttonTitle('skill','roll'),class:'raw'}) + +span({name:'name','data-i18n-dynamic':'',role:'heading','aria-level':5,title:attrTitle('skill','name')}) + +roller({name:'roll',title:buttonTitle('skill','roll'),class:'custom'}) + +text({name:'name',role:'heading','aria-level':5,class:'custom underlined',title:attrTitle('skill','name')}) + +number({name:'level',class:'underlined',title:attrTitle('skill','level')}) + +select({name:'stat',class:'underlined',title:attrTitle('skill','stat')}) + +option({value:'query','data-i18n':'ask'}) + each value in stats + +option({value,'data-i18n':value}) + +number({name:'xp',class:'underlined',title:attrTitle('skill','xp')}) + section#adjustments + .repeating-container.repeating-container--advantages.advantages.subsection.section + +h2({'data-i18n':'advantages'}) + .repeat-columns + h5(data-i18n='name') + +customControlFieldset('advantage') + +checkbox({name:'collapse',class:'collapse',title:attrTitle('advantage','collapse')}) + +text({name:'name',class:'underlined',role:'heading','aria-level':3,title:attrTitle('advantage','name')}) + .headed-textarea.notes.expanded + +h5({'data-i18n':'notes'}) + +adaptiveTextarea({name:'notes',class:'underlined',title:attrTitle('advantage','notes')}) + .repeating-container.repeating-container--disadvantages.disadvantages.subsection.section + +h2({'data-i18n':'disadvantages'}) + .repeat-columns + h5(data-i18n='name') + +customControlFieldset('disadvantage') + +checkbox({name:'collapse',class:'collapse',title:attrTitle('disadvantage','collapse')}) + +text({name:'name',class:'underlined',role:'heading','aria-level':3,title:attrTitle('disadvantage','name')}) + .headed-textarea.notes.expanded + +h5({'data-i18n':'notes'}) + +adaptiveTextarea({name:'notes',class:'underlined',title:attrTitle('disadvantage','notes')}) + .repeating-container.repeating-container--adjustments.adjustments.subsection.section + +h2({'data-i18n':'adjustments'}) + .repeat-columns + h5(data-i18n='name') + +customControlFieldset('adjustment') + +checkbox({name:'collapse',class:'collapse',title:attrTitle('adjustment','collapse')}) + +text({name:'name',class:'underlined',role:'heading','aria-level':3,title:attrTitle('adjustment','name')}) + .headed-textarea.mod.expanded + +h5({'data-i18n':'notes'}) + +adaptiveTextarea({name:'notes',class:'underlined',title:attrTitle('adjustment','notes')}) + //- + .headed-textarea.mods.expanded + +h5({'data-i18n':'mods'}) + +adaptiveTextarea({name:'mods',class:'underlined',title:attrTitle('adjustment','mods')}) + +repeating_section('weapon','weapons',['weapon','skill','damage']) + +checkbox({name:'collapse',class:'collapse'}) + +roller({name:'roll',title:buttonTitle('weapon','roll')}) + +text({name:'name',class:'underlined',title:attrTitle('weapon','name')}) + +hidden({name:'skill',value:'select',title:attrTitle('weapon','skill')}) + +actionQuery({name:'skill action',title:buttonTitle('weapon','skill')}) + +checkbox({name:'translate skill',hidden:'',value:'1',class:'translate-control',checked:''}) + +span({name:'skill',class:'underlined translated','data-i18n-dynamic':'',title:attrTitle('weapon','skill')}) + +span({name:'skill',class:'underlined untranslated',title:attrTitle('weapon','skill')}) + .roll-plus + +span({'data-i18n':'lead'}) + span.plus + + +number({name:'damage',class:'underlined',title:attrTitle('weapon','damage')}) + .headed-textarea.notes.expanded + +h5({'data-i18n':'notes'}) + +adaptiveTextarea({name:'notes',class:'underlined',title:attrTitle('weapon','notes')}) + article#remnant.battle-remnant.subsystem-style.system-remnant + section#remnant-pic.section + +track('structure track','structure') + +input-label('duress',{name:'duress',type:'number',class:'boxed'},{},{role:'heading','aria-level':2}) + .image-container.remnant-token + +input-label('image prompt',{name:'remnant token',type:'text',class:'boxed',value:'https://s3.amazonaws.com/files.d20.io/images/259054779/OzN3yQwg7MbfXNtMYs-iOg/original.png'},{class:'image-container__input stacked'},{role:'heading','aria-level':5}) + +action({name:'remnant token',class:'image-container__button'}) + +img({name:'remnant token',class:'image-container__image',src:'https://s3.amazonaws.com/files.d20.io/images/259054779/OzN3yQwg7MbfXNtMYs-iOg/original.png'}) + section#remnant-ratings.stat-grid.section + +h2({'data-i18n':'total ratings'}) + each name in remnantRatings + - let label = abbreviations[name] || name; + if name === 'situational awareness' + +roller({name:'situational awareness',class:'uppercase',role:'heading','aria-level':4,'data-i18n':label,class:'uppercase'}) + else + h4(data-i18n=label) + +number({name,readonly:'',class:'boxed'}) + +number({name:`${name} mod`,class:'boxed'}) + +roller({name:'remnant initiative','data-i18n':'initiative',role:'heading','aria-level':4}) + +number({name:'remnant initiative',readonly:'',class:'boxed'}) + +number({name:'remnant initiative mod',class:'boxed'}) + .remnant-skills + +h2({'data-i18n':'skills'}) + .repeat-columns + each value in ['skill','level','xp'] + +h5({'data-i18n':value}) + each name in remnantSkills + +roller({name:`${name} roll`,'data-i18n':name,role:'heading','aria-level':4}) + +number({name:`${name} level`,class:'underlined'}) + +number({name:`${name} experience`,class:'underlined'}) + section#remnant-stats.stat-grid.section + +h2({'data-i18n':'remnant stats'}) + each name in remnantStats + if name === 'structure' + .input-label.span-all.structure + label(data-i18n='structure' for='structure' role='heading' aria-level=4) + .boxed.span-2 + +number({name:'structure',id:'structure'}) + span.slash / + +hidden({name:'structure max'}) + +number({name:'structure base',title:attrTitle('structure max')}) + else + label(data-i18n=name for=replaceSpaces(name) role='heading' aria-level=4).span-2 + +number({name,class:'boxed',type:'number',id:replaceSpaces(name)}) + each name in remnantCombatStats + - let inputObj = {name,class:`boxed ${replaceSpaces(name)}_input`,type:'number',id:replaceSpaces(name)}; + label(data-i18n=name role='heading' aria-level=4 for=replaceSpaces(name) class=`${replaceSpaces(name)}_label`) + +input(inputObj) + +repeating_section('specialty','specialty',['name'],'remnant-specialty') + +checkbox({name:'collapse',class:'collapse'}) + +text({name:'name',class:'underlined',title:attrTitle('specialty','name')}) + .headed-textarea.description.expanded + +h5({'data-i18n':'description'}) + +adaptiveTextarea({name:'description',class:'underlined',title:attrTitle('specialty','description')}) + +repeating_section('trait','traits',['name','duress','focus'],'remnant-trait') + +checkbox({name:'collapse',class:'collapse'}) + +text({name:'name',class:'underlined'}) + +number({name:'duress',class:'underlined',title:attrTitle('trait','duress')}) + +number({name:'focus',class:'underlined',title:attrTitle('trait','focus')}) + .headed-textarea.description.expanded + +h5({'data-i18n':'description'}) + +adaptiveTextarea({name:'description',class:'underlined',title:attrTitle('trait','description')}) + section#remnant-drone.repeating-container.repeating-container--drone.section + +h2({'data-i18n':'drones'}) + +customControlFieldset('drone') + +checkbox({name:'collapse',class:'collapse'}) + +text({name:'name',class:'underlined remnant-drone__name',role:'heading','aria-level':3,title:attrTitle('drone','name')}) + +input-label('# active',{name:'active',type:'number',class:'boxed'},null,{role:'heading','aria-level':5,'data-i18n':label,'data-i18n':'# active'}) + each name in droneStats + - let label = abbreviations[name] || name; + if /^(?:strike|assault)/.test(label) + - let hiddenName = /strike/.test(label) ? 'strike' : 'assault'; + +hidden({name:hiddenName,type:'number',class:`underlined expanded--empty`}) + if /^(?:strike|assault)$/.test(name) + +roller-label({name,type:'number',class:`boxed`,title:attrTitle('drone',name)},{name,role:'heading','aria-level':5,'data-i18n':label,title:buttonTitle('drone',name)},{class:`${replaceSpaces(name)}`}) + else if name === 'struct' + .structure + +span({role:'heading','aria-level':5,'data-i18n':label}) + .boxed.span-2 + +number({name:'structure',id:'structure'}) + span.slash / + +number({name:'structure max'}) + else if name=== 'strikerange' + +input-label(label,{name,type:'number',class:`boxed`,title:attrTitle('drone',name),readonly:''},{class:replaceSpaces(name)},{role:'heading','aria-level':5,'data-i18n':label}) + else + +input-label(label,{name,type:'number',class:`boxed`,title:attrTitle('drone',name)},{class:replaceSpaces(name)},{role:'heading','aria-level':5,'data-i18n':label}) + .headed-textarea.description.expanded + +h5({'data-i18n':'description'}) + +adaptiveTextarea({name:'description',class:'underlined',title:attrTitle('drone','description')}) + section#remnant-weapons.repeating-container.repeating-container--remnant-weapons.section + +h2({'data-i18n':'weapons'}) + .repeat-columns + each name in remnantWeaponInputs + +h5({'data-i18n':name}) + +customControlFieldset('remnant weapon') + +checkbox({name:'collapse',class:'collapse'}) + +roller({name:'roll',title:buttonTitle('remnant-weapon','roll')}) + +text({name:'name',class:'underlined',title:attrTitle('remnant-weapon','name'),role:'heading','aria-level':4}) + +select({name:'skill',class:'underlined',title:attrTitle('remnant-weapon','skill')}) + +option({value:' ','data-i18n':'select',selected:''}) + +option({value:'assault','data-i18n':'assault'}) + +option({value:'strike','data-i18n':'strike'}) + +number({name:'bonus',class:'underlined',title:attrTitle('remnant-weapon','bonus')}) + .roll-plus + +span({'data-i18n':'lead'}) + span.plus + + +number({name:'damage',class:'underlined',title:attrTitle('weapon','damage'),readonly:''}) + +number({name:'damage bonus',class:'underlined damage-bonus',title:attrTitle('remnant-weapon','damage bonus')}) + +text({name:'type',class:'underlined',title:attrTitle('remnant-weapon','type')}) + .headed-textarea.description.expanded + +h5({'data-i18n':'notes'}) + +adaptiveTextarea({name:'notes',class:'underlined',title:attrTitle('remnant-weapon','notes')}) +//-Rolltemplate definitions ++rolltemplate('rapidfire') + .content(class='{{#singleroll}}single-roll{{/singleroll}}') + +templateConditionalDisplay('header') + .header + .header__background.background + h3(tabindex='-1') {{header}} + .header__content + h3 {{header}} + .header__image + +templateConditionalDisplay('roll') + +hexagon({},'status').sheet-roll + h4(data-i18n='roll') + |{{roll}} + each num in [1,2,3,4,5,6] + +templateConditionalDisplay(`roll${num}`) + - let hexObj = {class:`sheet-roll`}; + +hexagon(hexObj,`status${num}`) + h4(data-i18n='roll') + |{{roll#{num}}} + +templateConditionalDisplay('difficulty') + +hexagon().difficulty + h4(data-i18n='difficulty') + |{{difficulty}} + +templateConditionalDisplay('damage') + +hexagon().damage + +templateConditionalDisplay('damage_label') + h4 {{computed::damage_label}} + +templateConditionalDisplay('damage_label',true) + h4(data-i18n='damage') + |{{computed::damage}} + +templateConditionalDisplay('description') + .container-background.description + .description.text + h4(data-i18n='notes') + span {{description}} + +userTemplateFields + +templateConditionalDisplay('description',true) + +templateConditionalDisplay('custom_description') + .container-background.description + .description.text + +userTemplateFields + +characterLink() ++script() + include Javascript/utility.js + include Javascript/setupfunctions.js + include Javascript/clickfunctions.js + include Javascript/rollfunctions.js + include Javascript/initialchangefunctions.js + include Javascript/triggeredfunctions.js + include Javascript/calculators.js + include Javascript/listeners.js + //- The below declarations import variables from the pug file and mixins into the sheetworker code + each content,prop in varObjects + | + |const !{prop} = !{JSON.stringify(content)}; + | + | + include Javascript/variables.js \ No newline at end of file diff --git a/rapidfire_system/translation.json b/rapidfire_system/translation.json new file mode 100644 index 0000000000..2e0f214604 --- /dev/null +++ b/rapidfire_system/translation.json @@ -0,0 +1,128 @@ +{ + "remnants":"remnants", + "character info":"character info", + "character name":"character name", + "player name":"player name", + "nationality":"nationality", + "organization affiliations":"organization affiliations", + "appearance / mannerisms":"appearance / mannerisms", + "stats":"stats", + "body":"body", + "mind":"mind", + "spirit":"spirit", + "stat points":"stat points", + "reserve":"reserve", + "secondary stats":"secondary stats", + "defence":"defence", + "resist":"resist", + "health":"health", + "initiative":"initiative", + "combat gear":"combat gear", + "armour bonus":"armour bonus", + "shield bonus":"shield bonus", + "action penalty":"action penalty", + "health track":"health track", + "gear and money":"gear and money", + "easy living":"easy living", + "skills":"skills", + "level":"level", + "stat":"stat", + "xp":"xp", + "weapons":"weapons", + "weapon":"weapon", + "attack":"attack", + "damage":"damage", + "query":"query", + "ask":"ask", + "select":"select", + "1d6":"1d6", + "lead":"lead", + "notes":"notes", + "mods":"mods", + "adjustments":"adjustments", + "advantages":"advantages", + "disadvantages":"disadvantages", + "structure track":"structure track", + "duress":"duress", + "total ratings":"total ratings", + "situational awareness":"situational awareness", + "remnant stats":"remnant stats", + "armour":"armour", + "speed":"speed", + "structure":"structure", + "inspiring":"inspiring", + "terrifying":"terrifying", + "assault damage":"assault damage", + "strike damage":"strike damage", + "strike range":"strike range", + "strike range (km)":"strike range (km)", + "remnant skills":"remnant skills", + "skill":"skill", + "remnant weapons":"remnant weapons", + "name":"name", + "bonus":"bonus", + "damage":"damage", + "damage bonus":"damage bonus", + "type":"type", + "assault":"assault", + "strike":"strike", + "description":"description", + "traits":"traits", + "type":"type", + "focus":"focus", + "specialty":"specialty", + "skill query":"Which skill would you like to use", + "archery / throwing":"Archery / throwing", + "athletics":"athletics", + "awareness":"awareness", + "bureaucracy":"bureaucracy", + "command":"command", + "craft":"craft", + "dodge":"dodge", + "etiquette":"etiquette", + "history":"history", + "investigation":"investigation", + "language":"language", + "larceny":"larceny", + "lore":"lore", + "medicine":"medicine", + "melee":"melee", + "perform":"perform", + "ride":"ride", + "sail":"sail", + "sciences":"sciences", + "social sciences":"social sciences", + "stealth":"stealth", + "survival":"survival", + "unarmed combat":"unarmed combat", + "drones":"drones", + "difficulty query":"What is the difficulty of the roll", + "stat query":"Which stat are you using", + "roll":"roll", + "difficulty":"difficulty", + "character":"character", + "battle remnant":"battle remnant", + "whisper rolls to gm":"whisper rolls to gm", + "setting":"setting", + "difficulty automation":"difficulty automation", + "never":"never", + "always":"always", + "ask":"ask", + "enabled":"enabled", + "disabled":"disabled", + "motion":"motion", + "remnant defence":"remnant defence", + "situation awareness abbreviation":"sa", + "image prompt":"Enter the url for the image you would like to add. Leave blank to reset.", + "remnant token":"remnant token", + "drone query":"How many drones are attacking", + "remnant-initiative":"remnant initiative", + "action penalty automation":"action penalty automation", + "use input":"use input", + "quantity abbreviation":"qty", + "action penalty query":"What is your current action penalty", + "system header":"system header", + "# active":"# active", + "lead":"lead", + "trail":"trail" +} \ No newline at end of file