diff --git a/Shadowrun5thEdition/Shadowrun5thEdition.css b/Shadowrun5thEdition/Shadowrun5thEdition.css index 02938f2c09..f8dda6b38f 100644 --- a/Shadowrun5thEdition/Shadowrun5thEdition.css +++ b/Shadowrun5thEdition/Shadowrun5thEdition.css @@ -1,8 +1,6 @@ -/********************************************************************************************************/ -/********************************* GLOBAL SETTINGS *******************************************************/ -/********************************************************************************************************/ -/* GLOBALS - ============================= */ +/******************************************************************************/ +/********************************* VARIABLES *********************************/ +/****************************************************************************/ * { box-sizing: border-box; font-family: sans-serif; } @@ -13,24 +11,24 @@ button { text-shadow: none; } button[type='roll'], button[type='action'] { font-size: 1em; - margin: 0px !important; padding: 1px 2px; border-bottom: 0.01em solid #666; border-bottom-right-radius: 0.01em; - border-color: #b3b3b3; + border-color: #9a9a9a; border-radius: 0.25em !important; - border-right: 0.02em solid #333333; + border-right: 0.02em solid rgba(28, 28, 28, 0.14902); border-style: outset; } - button:before { - display: none; } button:hover, button:focus, button:active { font-weight: bold; - background-color: #FCD116; } + background-color: #610b0d; + color: #fff; } button > span { display: block; overflow: hidden; text-overflow: ellipsis; width: 100%; } + button:before { + display: none; } div { background-color: transparent; } @@ -66,14 +64,19 @@ input { input[type='text']:placeholder-shown, input[type='number']:placeholder-shown { border: 1px dotted #555; background-color: rgba(28, 28, 28, 0.14902); - color: white; } + color: #fff; } input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } + input[name='attr_stats_toggle'], input[name='attr_stats_toggle'] + span { + position: relative; } + input[name='attr_stats_toggle'] { + opacity: 0; + z-index: 2; } select { border-radius: 2px; - border: 1px solid #000; + border: 1px solid #040404; box-shadow: inset 0px 0px 3px 1px #7c7c7c; margin-bottom: 0px; width: auto; } @@ -83,7 +86,7 @@ span { textarea { border-radius: 2px; - border: 1px solid #000; + border: 1px solid #040404; box-shadow: inset 0px 0px 3px 1px #7c7c7c; height: 50px; overflow-wrap: break-word; @@ -98,24 +101,137 @@ textarea { .sheet-red { color: #610b0d; } -.sheet-text-align-center { +.sheet-text-center { text-align: center; } -input[name='attr_stats_toggle'], -input[name='attr_stats_toggle'] + span { - position: relative; } - -input[name='attr_stats_toggle'] { - opacity: 0; - z-index: 2; } - .sheet-eclipse { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } -/* SWITCHES - ============================= */ +.sheet-text-left { + text-align: left; } + +.sheet-text-capitalize { + text-transform: capitalize; } + +.sheet-dicefontd6 { + font-family: "dicefontd6"; } + +.sheet-pc div.sheet-skill-box input[name='attr_specialization'][value=' '] ~ div.sheet-buttons button[name*='specialization'], +.sheet-pc div.sheet-skill-box input[name='attr_specialization'][value=''] ~ div.sheet-buttons button[name*='specialization'], .sheet-pc div.sheet-magic input.sheet-magic-toggle[value='rituals'] ~ .sheet-headers h2:nth-of-type(1n+2), .sheet-matrix, +.sheet-magic, +.sheet-resonance, +.sheet-optional, +.sheet-textboxes, +.sheet-optional-flag[value='0'] + .sheet-attr-header, +.sheet-category + div, +.sheet-category + div + div, .sheet-npc, .sheet-pc, .sheet-options_toggle:not([value='arms']) ~ .sheet-arms, .sheet-options_toggle:not([value='augs']) ~ .sheet-augs, .sheet-options_toggle:not([value='core']) ~ .sheet-core, .sheet-options_toggle:not([value='gear']) ~ .sheet-gear, .sheet-options_toggle:not([value='options']) ~ .sheet-options, .sheet-options_toggle:not([value='social']) ~ .sheet-social, .sheet-options_toggle:not([value='magic']) ~ .sheet-magic, .sheet-options_toggle:not([value='matrix']) ~ .sheet-matrix, .sheet-options_toggle:not([value='vehicle']) ~ .sheet-vehicle, .sheet-skills-active, +.sheet-skills-know, +.sheet-skills-lang, .sheet-magic-spells, .sheet-magic-preps, .sheet-magic-rituals, .sheet-quality, .sheet-martial, .sheet-settings, input.sheet-settings-toggle:checked ~ div.sheet-display, +input.sheet-settings-toggle:checked ~ .sheet-attr-col .sheet-attr-und div.sheet-display, +input.sheet-settings-toggle ~ .sheet-attr-lim div.sheet-settings, +input.sheet-settings-toggle:checked ~ .sheet-attr-lim div.sheet-display, +input.sheet-settings-toggle[value='settings'] ~ div.sheet-display, +input.sheet-settings-toggle[value='display'] ~ div.sheet-settings, +input.sheet-settings-toggle[value='display'] ~ div.sheet-settings-grid, input.sheet-settings-toggle[value='display'] ~ .sheet-settings, .sheet-hide-magic, .sheet-hide-resonance, div.sheet-weapon-range, +div.sheet-weapon-melee, .sheet-grunt, .sheet-host, .sheet-sprite, .sheet-vehicle, input[name='attr_sheet_type'][value='host'] ~ .sheet-npc .sheet-column:nth-of-type(2), +input[name='attr_sheet_type'][value='sprite'] ~ .sheet-npc .sheet-column:nth-of-type(1n+2), input[name='attr_flag_special'][value='mundane'] ~ div.sheet-npc .sheet-hide-magic, +input[name='attr_flag_special'][value='mundane'] ~ div.sheet-npc .sheet-hide-resonance, +input[name='attr_flag_special'][value='mundane'] ~ div.sheet-npc .sheet-grunt.sheet-hide-magic, +input[name='attr_flag_special'][value='mundane'] ~ div.sheet-npc .sheet-grunt.sheet-hide-resonance, +input[name='attr_flag_special'][value='resonance'] ~ div.sheet-npc .sheet-hide-magic, +input[name='attr_flag_special'][value='resonance'] ~ div.sheet-npc .sheet-grunt.sheet-hide-magic, +input[name='attr_flag_special'][value='magic'] ~ div.sheet-npc .sheet-hide-resonance, +input[name='attr_flag_special'][value='magic'] ~ div.sheet-npc .sheet-grunt.sheet-hide-resonance, +input[name='attr_stats_toggle']:not([value='settings']) ~ div.sheet-attribute .sheet-settings.sheet-hide-magic, +input[name='attr_stats_toggle']:not([value='settings']) ~ div.sheet-attribute .sheet-settings.sheet-hide-resonance, +input[name='attr_stats_toggle']:not([value='settings']) ~ div.sheet-body .sheet-settings.sheet-hide-magic, +input[name='attr_stats_toggle']:not([value='settings']) ~ div.sheet-body .sheet-settings.sheet-hide-resonance, input[name='attr_stats_toggle']:not([value='settings']) ~ div.sheet-body input[type='hidden'][value=''] + div.sheet-textrow, input[name='attr_stats_toggle']:not([value='settings']) ~ div.sheet-body input[type='hidden'][value=''] + div.sheet-rows.sheet-grunt, input[name='attr_specialization'][value=''] ~ button[name*='specialization'], +input[name='attr_specialization'][value=' '] ~ button[name*='specialization'], +input[name='attr_specialization'][value=''] ~ div.sheet-row-long div.sheet-buttons button[name*='specialization'], +input[name='attr_specialization'][value=' '] ~ div.sheet-row-long div.sheet-buttons button[name*='specialization'], input[name='attr_weapon_range'][value='range'] ~ div.sheet-settings h2[data-i18n='reach'], +input[name='attr_weapon_range'][value='range'] ~ div.sheet-settings label[data-i18n-title='reach'], input[name='attr_weapon_range'][value='melee'] ~ div.sheet-settings h2[data-i18n='modes'], +input[name='attr_weapon_range'][value='melee'] ~ div.sheet-settings h2[data-i18n='recoil'], +input[name='attr_weapon_range'][value='melee'] ~ div.sheet-settings h2[data-i18n='ammo'], +input[name='attr_weapon_range'][value='melee'] ~ div.sheet-settings label[data-i18n-title='modes'], +input[name='attr_weapon_range'][value='melee'] ~ div.sheet-settings label[data-i18n-title='recoil'], +input[name='attr_weapon_range'][value='melee'] ~ div.sheet-settings label[data-i18n-title='ammo'], +input[name='attr_weapon_range'][value='melee'] ~ div.sheet-settings span, input[name='attr_category']:not([value='Combat']) ~ h2[data-i18n='combat'], +input[name='attr_category']:not([value='Combat']) ~ h2[data-i18n='dam'], +input[name='attr_category']:not([value='Combat']) ~ select[name='attr_combat_type'], +input[name='attr_category']:not([value='Combat']) ~ label[data-i18n-title='dam'], +.sheet-display-none { + display: none; } + +.sheet-tab-switch[value='active'] ~ .sheet-skills-active, +.sheet-tab-switch[value='knowledge'] ~ .sheet-skills-know, +.sheet-tab-switch[value='language'] ~ .sheet-skills-lang, .sheet-magic-toggle[value='spells'] ~ .sheet-magic-spells, .sheet-magic-toggle[value='preps'] ~ .sheet-magic-preps, .sheet-magic-toggle[value='rituals'] ~ .sheet-magic-rituals, .sheet-tab-switch[value='quality'] ~ .sheet-quality, .sheet-tab-switch[value='martial'] ~ .sheet-martial { + display: inline; } + +.sheet-pc h2, .sheet-pc h3, .sheet-pc .sheet-tabs, .sheet-pc div.sheet-skill-box div.sheet-row-long, .sheet-npc div.sheet-tabs, .sheet-npc div.sheet-mid, input[name='attr_sheet_type'][value='grunt'] ~ .sheet-npc .sheet-attribute.sheet-grunt, input[name='attr_sheet_type'][value='host'] ~ .sheet-npc .sheet-attribute.sheet-host, input[name='attr_sheet_type'][value='sprite'] ~ .sheet-npc .sheet-attribute.sheet-sprite, input[name='attr_sheet_type'][value='vehicle'] ~ .sheet-npc .sheet-attribute.sheet-vehicle { + display: inline-grid; } + +.sheet-pictos, .sheet-settings-toggle input[type='checkbox'] + span, +.sheet-settings-flag input[type='checkbox'] + span, .sheet-flag-primary + div > span, .repcontrol .repcontrol_edit:after, +.repcontrol .repcontrol_add:after, .itemcontrol .repcontrol_del { + font-family: 'Pictos'; } + +.sheet-optional-flag:not([value='0']) + .sheet-optional, .sheet-npc div.sheet-mid div.sheet-column, input[name='attr_sheet_type']:not([value='pc']) ~ .sheet-npc, +input[name='attr_sheet_type'][value='pc'] ~ .sheet-pc, .sheet-options_toggle[value='arms'] ~ .sheet-arms, .sheet-options_toggle[value='augs'] ~ .sheet-augs, .sheet-options_toggle[value='core'] ~ .sheet-core, .sheet-options_toggle[value='gear'] ~ .sheet-gear, .sheet-options_toggle[value='options'] ~ .sheet-options, .sheet-options_toggle[value='social'] ~ .sheet-social, .sheet-options_toggle[value='magic'] ~ .sheet-magic, .sheet-options_toggle[value='matrix'] ~ .sheet-matrix, .sheet-options_toggle[value='vehicle'] ~ .sheet-vehicle, input[name='attr_stats_toggle'][value='settings'] ~ .sheet-attribute .sheet-settings, +input[name='attr_stats_toggle'][value='settings'] ~ .sheet-body .sheet-column .sheet-settings, +input[name='attr_stats_toggle'][value='settings'] ~ .sheet-body .sheet-textrow .sheet-settings, input.sheet-settings-toggle[value='settings'] ~ .sheet-settings, .sheet-character-type[value='magic'] ~ .sheet-pc .sheet-pc-row .sheet-attr-col .sheet-hide-magic, input[name='attr_flag_special'][value='magic'] ~ .sheet-npc .sheet-hide-magic, .sheet-character-type[value='resonance'] ~ .sheet-pc .sheet-pc-row .sheet-attr-col .sheet-hide-resonance, input[name='attr_flag_special'][value='resonance'] ~ .sheet-npc .sheet-hide-resonance, input.sheet-tab-switch[value='range'] ~ .sheet-weapon-range, +input.sheet-tab-switch[value='melee'] ~ .sheet-weapon-melee, input[name='attr_sheet_type'][value='grunt'] ~ .sheet-npc .sheet-rows.sheet-grunt, +input[name='attr_sheet_type'][value='grunt'] ~ .sheet-npc .sheet-textrow.sheet-grunt, input[name='attr_sheet_type'][value='host'] ~ .sheet-npc .sheet-rows.sheet-host, +input[name='attr_sheet_type'][value='host'] ~ .sheet-npc .sheet-textrow.sheet-host, input[name='attr_sheet_type'][value='sprite'] ~ .sheet-npc .sheet-rows.sheet-sprite, +input[name='attr_sheet_type'][value='sprite'] ~ .sheet-npc .sheet-textrow.sheet-sprite, input[name='attr_sheet_type'][value='vehicle'] ~ .sheet-npc .sheet-rows.sheet-vehicle, +input[name='attr_sheet_type'][value='vehicle'] ~ .sheet-npc .sheet-textrow.sheet-vehicle, input[name='attr_flag_matrix'][value='matrix'] ~ div.sheet-matrix, +.sheet-static { + display: inline-block; } + +.sheet-npc div.sheet-end div.sheet-weapons span[name='attr_weapon_dice'], .sheet-npc div.sheet-end div.sheet-spells span[name='attr_dice'], .sheet-npc div.sheet-end div.sheet-forms span[name='attr_form_dice'], .sheet-npc div.sheet-end div.sheet-ic span[name='attr_software_dice'] { + vertical-align: middle; } + .sheet-npc div.sheet-end div.sheet-weapons span[name='attr_weapon_dice']:before, .sheet-npc div.sheet-end div.sheet-spells span[name='attr_dice']:before, .sheet-npc div.sheet-end div.sheet-forms span[name='attr_form_dice']:before, .sheet-npc div.sheet-end div.sheet-ic span[name='attr_software_dice']:before { + content: '('; } + .sheet-npc div.sheet-end div.sheet-weapons span[name='attr_weapon_dice']:after, .sheet-npc div.sheet-end div.sheet-spells span[name='attr_dice']:after, .sheet-npc div.sheet-end div.sheet-forms span[name='attr_form_dice']:after, .sheet-npc div.sheet-end div.sheet-ic span[name='attr_software_dice']:after { + content: ')'; } + +.sheet-npc div.sheet-repeating input[name='attr_flag'], +input.sheet-toggle { + position: absolute; + opacity: 0; + z-index: 2; } + +.sheet-pc input.sheet-settings-toggle, +.sheet-pc input.sheet-settings-flag, +.sheet-pc input.sheet-collapse-flag, +.sheet-pc input[type='radio'] { + position: relative; + opacity: 0; + z-index: 2; } + +.sheet-npc div.sheet-repeating input[name='attr_flag'] + span { + opacity: 0; } +.sheet-npc div.sheet-repeating input[name='attr_flag']:checked + span { + opacity: 1; } +.sheet-npc div.sheet-repeating input[name='attr_flag']:checked ~ .sheet-settings { + display: inline-grid; + margin-bottom: 2%; } + +.sheet-pc div.sheet-repeating-container div.repitem, .sheet-pc div.sheet-repeating-container div.repitem input[type='text'], .sheet-pc div.sheet-repeating-container div.repitem input[type='number'], .sheet-pc div.sheet-skill-box label > input, .sheet-pc div.sheet-skill-box input[name='attr_skill'], .sheet-pc div.sheet-matrix div.sheet-programs div.repitem { + border-bottom: 1px solid #040404; } + +div.sheet-grid { + display: inline-grid; + grid-column-gap: 1%; + grid-row-gap: 0.5%; } + +div.sheet-2column { + grid-template-columns: 1fr 1fr; } + +div.sheet-2autocolumn { + grid-template-columns: auto 1fr; } + /* The switch - the box around the slider */ .sheet-switch { position: relative; @@ -165,39 +281,71 @@ input:checked + .sheet-slider:before { -ms-transform: translateX(26px); transform: translateX(26px); } -/* MIXIN - ============================= */ -/***** TABS FOR SHEETS *****/ -.sheet-tabs button[type='action'] { - background-color: #333; - border-radius: 2px; - border: 1px solid #000; - box-shadow: inset 0px 0px 3px 1px #7c7c7c; - color: #fff; - font-size: 1em; - font-weight: bolder; - text-transform: capitalize; - padding: 5px; } - .sheet-tabs button[type='action'].sheet-pictos, .sheet-tabs .sheet-cc-row button[type='action'][name*='shots'], .sheet-cc-row .sheet-tabs button[type='action'][name*='shots'], .sheet-tabs .sheet-cc-row button[type='action'][name='act_reload'], .sheet-cc-row .sheet-tabs button[type='action'][name='act_reload'], .sheet-tabs .sheet-cc-row button[type='action'][name='act_primary_ammo'], .sheet-cc-row .sheet-tabs button[type='action'][name='act_primary_ammo'], .sheet-tabs .repcontrol button[type='action'].repcontrol_edit:after, .repcontrol .sheet-tabs button[type='action'].repcontrol_edit:after, - .sheet-tabs .repcontrol button[type='action'].repcontrol_add:after, - .repcontrol .sheet-tabs button[type='action'].repcontrol_add:after, .sheet-tabs .itemcontrol button[type='action'].repcontrol_del, .itemcontrol .sheet-tabs button[type='action'].repcontrol_del { - text-transform: lowercase; } -.sheet-tabs button[type='roll'] { - background: none; - border: none; - color: #fff; - font-family: 'dicefontd6'; - font-size: 2.5em; - vertical-align: top; } - .sheet-tabs button[type='roll']:hover { - text-shadow: 1px 1px 2px black, 0 0 25px red, 0 0 5px #e31715; } -.sheet-tabs h2 { - color: #fff; - font-size: 1em; - text-transform: capitalize; - text-align: right; - line-height: 2em; - margin-right: 5%; } +div.sheet-collapse { + opacity: 0; + height: 0; + transition: all .5s; } + +input.sheet-collapse-flag:checked ~ div.sheet-collapse { + opacity: 1; + height: 100%; + transition: all .5s; } + +input.sheet-indicator { + height: 1.8em; + width: 1.5em; + transition: all .2s; + top: 5px; } + input.sheet-indicator + span { + display: inline-block; + height: 1.5em; + width: 1.5em; } + input.sheet-indicator:hover + span { + transform: scale(1.3); } + input.sheet-indicator:checked + span { + background-color: #610b0d; + color: #fff; + font-weight: bolder; + border-radius: 3px; + padding: 15%; } + input.sheet-indicator:checked + span + span { + font-weight: bolder; } + +.sheet-tabs { + color: #fff; } + .sheet-tabs button[type='action'] { + background-color: #333; + border-radius: 2px; + border: 1px solid #7c7c7c; + font-size: 1em; + font-weight: bolder; + text-transform: capitalize; + padding: 5px; + transition: transform .2s; } + .sheet-tabs button[type='action'].sheet-pictos, .sheet-tabs .repcontrol button[type='action'].repcontrol_edit:after, .repcontrol .sheet-tabs button[type='action'].repcontrol_edit:after, + .sheet-tabs .repcontrol button[type='action'].repcontrol_add:after, + .repcontrol .sheet-tabs button[type='action'].repcontrol_add:after, .sheet-tabs .itemcontrol button[type='action'].repcontrol_del, .itemcontrol .sheet-tabs button[type='action'].repcontrol_del { + text-transform: lowercase; } + .sheet-tabs button[type='action']:hover, .sheet-tabs button[type='action']:focus, .sheet-tabs button[type='action']:active { + text-shadow: inset 0px 0px 3px 1px #e31715; + background-color: #610b0d; + transform: scale(1.1); } + .sheet-tabs button[type='roll'] { + background: none; + border: none; + color: #fff; + font-family: 'dicefontd6'; + font-size: 2.5em; + vertical-align: top; } + .sheet-tabs button[type='roll']:hover { + text-shadow: 1px 1px 2px #040404, 0 0 25px #610b0d, 0 0 5px #e31715; } + .sheet-tabs h2 { + color: #fff; + font-size: 1em; + text-transform: capitalize; + text-align: right; + line-height: 2em; + margin-right: 5%; } /***** TABS FOR SHEETS *****/ .sheet-settings-toggle input, @@ -212,41 +360,6 @@ input:checked + .sheet-slider:before { width: 20px; } /***** GENERIC STYLES *****/ -.sheet-npc div.sheet-end div.sheet-weapons span[name='attr_weapon_dice'], .sheet-npc div.sheet-end div.sheet-spells span[name='attr_dice'], .sheet-npc div.sheet-end div.sheet-forms span[name='attr_form_dice'], .sheet-npc div.sheet-end div.sheet-ic span[name='attr_software_dice'] { - vertical-align: middle; } - .sheet-npc div.sheet-end div.sheet-weapons span[name='attr_weapon_dice']:before, .sheet-npc div.sheet-end div.sheet-spells span[name='attr_dice']:before, .sheet-npc div.sheet-end div.sheet-forms span[name='attr_form_dice']:before, .sheet-npc div.sheet-end div.sheet-ic span[name='attr_software_dice']:before { - content: '('; } - .sheet-npc div.sheet-end div.sheet-weapons span[name='attr_weapon_dice']:after, .sheet-npc div.sheet-end div.sheet-spells span[name='attr_dice']:after, .sheet-npc div.sheet-end div.sheet-forms span[name='attr_form_dice']:after, .sheet-npc div.sheet-end div.sheet-ic span[name='attr_software_dice']:after { - content: ')'; } - -.sheet-npc div.sheet-repeating input[name='attr_flag'], -input.sheet-toggle { - position: absolute; - opacity: 0; - z-index: 2; } - -.sheet-pc input.sheet-settings-toggle, -.sheet-pc input.sheet-settings-flag, -.sheet-pc input.sheet-collapse-flag, -.sheet-pc input[type='radio'] { - position: relative; - opacity: 0; - z-index: 2; } - -.sheet-npc div.sheet-repeating input[name='attr_flag'] + span { - opacity: 0; } -.sheet-npc div.sheet-repeating input[name='attr_flag']:checked + span { - opacity: 1; } -.sheet-npc div.sheet-repeating input[name='attr_flag']:checked ~ .sheet-settings { - display: inline-grid; - margin-bottom: 2%; } - -.sheet-pc div.sheet-repeating-container div.repitem, .sheet-pc div.sheet-repeating-container div.repitem input[type='text'], .sheet-pc div.sheet-repeating-container div.repitem input[type='number'], .sheet-pc div.sheet-skill-box label > input, .sheet-pc div.sheet-skill-box input[name='attr_skill'], .sheet-pc div.sheet-matrix div.sheet-programs div.repitem { - border-bottom: 1px solid #333; } - -.sheet-center { - text-align: center; } - select.sheet-attribute-select option:nth-of-type(1n+5) { color: #610b0d; } select.sheet-attribute-select option:nth-of-type(1n+9) { @@ -278,20 +391,11 @@ div.sheet-matrix-device .sheet-matrixData { div.sheet-matrix-device .sheet-matrixFirewall { box-shadow: 0px 0px 29px 8px #f88703; } -.sheet-text-capitalize { - text-transform: capitalize; } - -.sheet-text-left { - text-align: left; } - /***** GRID *****/ .sheet-pc div.sheet-repeating-container div.repitem, .sheet-pc div.sheet-repeating-container div.repitem div.sheet-settings, .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-quality div.sheet-headers, .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-martial div.sheet-headers, .sheet-pc div.sheet-skill-box div.sheet-row-long, .sheet-pc div.sheet-arms div.sheet-headers, .sheet-pc div.sheet-magic div.sheet-headers, .sheet-pc div.sheet-matrix div.sheet-complex-forms div.sheet-headers { grid-column-gap: 1%; grid-row-gap: 1%; } -/******************************************************************************/ -/********************************* VARIABLES *********************************/ -/****************************************************************************/ /***************************************************************************************/ /************************** START OF THE PC SHEET *************************************/ /*************************************************************************************/ @@ -313,8 +417,8 @@ div.sheet-matrix-device .sheet-matrixFirewall { /*** GEAR ****/ /***** MAGIC *****/ /*** MATRIX ****/ - /*** SOCIAL ****/ - /*** Vehicle ****/ } + /*** SOCIAL ****/ } + .sheet-pc button[name*='shots']:hover, .sheet-pc button > h2:hover, .sheet-pc button > span:hover, .sheet-pc label > button[type='roll']:hover, @@ -322,7 +426,9 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-pc .sheet-con-track button[type='action']:hover, .sheet-pc button[data-i18n='default']:hover { color: #fff; - text-shadow: 1px 1px 2px black, 0 0 25px red, 0 0 5px #610b0d; } + text-shadow: 1px 1px 2px #555, 0 0 25px #fff, 0 0 5px #fff; } + .sheet-pc button:hover > span { + color: #fff; } .sheet-pc h1 { background-color: #610b0d; color: #fff; @@ -399,6 +505,11 @@ div.sheet-matrix-device .sheet-matrixFirewall { grid-area: 3 / 2 / 3 / 3; } .sheet-pc .sheet-tabs label[data-i18n-title='edge'] { grid-area: 3 / 4 / 3 / 5; } + .sheet-pc input.sheet-settings-toggle:hover, + .sheet-pc input.sheet-settings-flag:hover, + .sheet-pc input.sheet-collapse-flag:hover, + .sheet-pc input[type='radio']:hover { + cursor: pointer; } .sheet-pc input.sheet-settings-toggle + span, .sheet-pc input.sheet-settings-flag + span, .sheet-pc input.sheet-collapse-flag + span, @@ -409,6 +520,11 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-pc input.sheet-collapse-flag:checked + span, .sheet-pc input[type='radio']:checked + span { color: #610b0d; } + .sheet-pc input.sheet-settings-toggle:hover + span, + .sheet-pc input.sheet-settings-flag:hover + span, + .sheet-pc input.sheet-collapse-flag:hover + span, + .sheet-pc input[type='radio']:hover + span { + transform: scale(1.1); } .sheet-pc select { height: 1.8em; padding: 0px; @@ -440,10 +556,10 @@ div.sheet-matrix-device .sheet-matrixFirewall { border-top-left-radius: 0px; } .sheet-pc div.sheet-repeating-container div.repitem { display: inline-grid; - padding: 1% 0.5%; - margin-bottom: 0px; } + padding: 1% 0.5%; } .sheet-pc div.sheet-repeating-container div.repitem button[type='roll'] { - text-align: left; } + text-align: left; + margin: 0px; } .sheet-pc div.sheet-repeating-container div.repitem input:nth-of-type(1n+2) { text-align: center; } .sheet-pc div.sheet-repeating-container div.repitem input[type='text'], .sheet-pc div.sheet-repeating-container div.repitem input[type='number'] { @@ -470,11 +586,16 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-pc div.repitem input[type='number'] { text-align: center; } .sheet-pc div.sheet-static { - margin-right: 0.5%; } + margin-right: 0.5%; + transition: transform .2s; } .sheet-pc div.sheet-static div.sheet-border-box, .sheet-pc div.sheet-static div.sheet-border-box .sheet-pc-box { border-top-right-radius: 0px; border-top-left-radius: 10px; } + .sheet-pc div.sheet-static div.sheet-attr-box button { + margin-bottom: 2%; } + .sheet-pc div.sheet-static div.sheet-attr-box button:hover, .sheet-pc div.sheet-static div.sheet-attr-box button:focus, .sheet-pc div.sheet-static div.sheet-attr-box button:active { + transform: scale(1.1); } .sheet-pc div.sheet-core { /***** QUALITIES *****/ } .sheet-pc div.sheet-core div.sheet-armor-buttons { @@ -490,6 +611,8 @@ div.sheet-matrix-device .sheet-matrixFirewall { color: #fff; } .sheet-pc div.sheet-core div.sheet-armor-buttons span { font-size: 1em; } + .sheet-pc div.sheet-core button[name="act_primary_ammo"]:hover > img { + filter: brightness(0) invert(1); } .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-htab input[type='radio'] { margin-right: -100px; width: 100px; } @@ -507,6 +630,10 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-quality div.repitem h3[data-i18n='notes'], .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-quality div.repitem div.sheet-collapse { grid-column: 1 / 6; } + .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-quality div.repitem label[data-i18n-title='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-quality div.repitem h3[data-i18n='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-quality div.repitem div.sheet-collapse span[name='attr_notes'] { + white-space: pre-line; } .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-quality div.repitem input.sheet-collapse-flag { grid-area: 1 / 4 / 1 / 5; } .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-quality div.repitem input.sheet-collapse-flag + span.sheet-pictos, .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-quality div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-collapse-flag + span, .sheet-settings-toggle .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-quality div.repitem input[type='checkbox'].sheet-collapse-flag + span, @@ -543,6 +670,10 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-martial div.repitem h3[data-i18n='notes'], .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-martial div.repitem div.sheet-collapse { grid-column: 1 / 6; } + .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-martial div.repitem label[data-i18n-title='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-martial div.repitem h3[data-i18n='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-martial div.repitem div.sheet-collapse span[name='attr_notes'] { + white-space: pre-line; } .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-martial div.repitem input.sheet-collapse-flag { grid-area: 1 / 4 / 1 / 5; } .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-martial div.repitem input.sheet-collapse-flag + span.sheet-pictos, .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-martial div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-collapse-flag + span, .sheet-settings-toggle .sheet-pc div.sheet-core div.sheet-quality-box div.sheet-martial div.repitem input[type='checkbox'].sheet-collapse-flag + span, @@ -612,6 +743,10 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-pc div.sheet-skill-box div.repitem h3[data-i18n='notes'], .sheet-pc div.sheet-skill-box div.repitem div.sheet-collapse { grid-column: 1 / 7; } + .sheet-pc div.sheet-skill-box div.repitem label[data-i18n-title='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-skill-box div.repitem h3[data-i18n='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-skill-box div.repitem div.sheet-collapse span[name='attr_notes'] { + white-space: pre-line; } .sheet-pc div.sheet-skill-box div.repitem input.sheet-collapse-flag { grid-area: 1 / 5 / 1 / 6; } .sheet-pc div.sheet-skill-box div.repitem input.sheet-collapse-flag + span.sheet-pictos, .sheet-pc div.sheet-skill-box div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-collapse-flag + span, .sheet-settings-toggle .sheet-pc div.sheet-skill-box div.repitem input[type='checkbox'].sheet-collapse-flag + span, @@ -659,6 +794,10 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-pc div.sheet-arms div.sheet-weapons div.repitem h3[data-i18n='notes'], .sheet-pc div.sheet-arms div.sheet-weapons div.repitem div.sheet-collapse { grid-column: 1 / 10; } + .sheet-pc div.sheet-arms div.sheet-weapons div.repitem label[data-i18n-title='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-arms div.sheet-weapons div.repitem h3[data-i18n='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-arms div.sheet-weapons div.repitem div.sheet-collapse span[name='attr_notes'] { + white-space: pre-line; } .sheet-pc div.sheet-arms div.sheet-weapons div.repitem input.sheet-collapse-flag { grid-area: 1 / 8 / 1 / 9; } .sheet-pc div.sheet-arms div.sheet-weapons div.repitem input.sheet-collapse-flag + span.sheet-pictos, .sheet-pc div.sheet-arms div.sheet-weapons div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-collapse-flag + span, .sheet-settings-toggle .sheet-pc div.sheet-arms div.sheet-weapons div.repitem input[type='checkbox'].sheet-collapse-flag + span, @@ -715,6 +854,10 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-pc div.sheet-arms div.sheet-armor div.repitem h3[data-i18n='notes'], .sheet-pc div.sheet-arms div.sheet-armor div.repitem div.sheet-collapse { grid-column: 1 / 11; } + .sheet-pc div.sheet-arms div.sheet-armor div.repitem label[data-i18n-title='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-arms div.sheet-armor div.repitem h3[data-i18n='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-arms div.sheet-armor div.repitem div.sheet-collapse span[name='attr_notes'] { + white-space: pre-line; } .sheet-pc div.sheet-arms div.sheet-armor div.repitem input.sheet-collapse-flag { grid-area: 1 / 9 / 1 / 10; } .sheet-pc div.sheet-arms div.sheet-armor div.repitem input.sheet-collapse-flag + span.sheet-pictos, .sheet-pc div.sheet-arms div.sheet-armor div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-collapse-flag + span, .sheet-settings-toggle .sheet-pc div.sheet-arms div.sheet-armor div.repitem input[type='checkbox'].sheet-collapse-flag + span, @@ -751,6 +894,10 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-pc div.sheet-augs div.repitem h3[data-i18n='notes'], .sheet-pc div.sheet-augs div.repitem div.sheet-collapse { grid-column: 1 / 6; } + .sheet-pc div.sheet-augs div.repitem label[data-i18n-title='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-augs div.repitem h3[data-i18n='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-augs div.repitem div.sheet-collapse span[name='attr_notes'] { + white-space: pre-line; } .sheet-pc div.sheet-augs div.repitem input.sheet-collapse-flag { grid-area: 1/1/1 / 5; position: absolute; @@ -775,30 +922,32 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-pc div.sheet-augs div.repitem .itemcontrol input.sheet-settings-flag + span.repcontrol_del, .itemcontrol .sheet-pc div.sheet-augs div.repitem input.sheet-settings-flag + span.repcontrol_del { grid-area: 1 / 5 / 1 / 6; } - .sheet-pc div.sheet-augs div.repitem input[name='attr_augementation'] { - text-align: left; } .sheet-pc div.sheet-augs div.repitem div.sheet-settings { grid-column: 1 / 6; grid-template-columns: 1fr 5em 5em 1em 1em; } .sheet-pc div.sheet-gear div.sheet-headers { display: grid; - grid-template-columns: 1fr 5em 5em 1em 1em; } + grid-template-columns: 1.5em 1fr 5em 5em 1em 1em; } + .sheet-pc div.sheet-gear div.sheet-headers h2[data-i18n='item'] { + grid-column: 1 / 3; } .sheet-pc div.sheet-gear div.repitem { - grid-template-columns: 1fr 5em 5em 1em 1em; } + grid-template-columns: 1.5em 1fr 5em 5em 1em 1em; } .sheet-pc div.sheet-gear div.repitem label[data-i18n-title='notes'], .sheet-pc div.sheet-gear div.repitem h3[data-i18n='notes'], .sheet-pc div.sheet-gear div.repitem div.sheet-collapse { - grid-column: 1 / 6; } + grid-column: 1 / 7; } + .sheet-pc div.sheet-gear div.repitem label[data-i18n-title='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-gear div.repitem h3[data-i18n='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-gear div.repitem div.sheet-collapse span[name='attr_notes'] { + white-space: pre-line; } .sheet-pc div.sheet-gear div.repitem input.sheet-collapse-flag { - grid-area: 1/1/1 / 5; - position: absolute; - width: 100%; } + grid-area: 1 / 5 / 1 / 6; } .sheet-pc div.sheet-gear div.repitem input.sheet-collapse-flag + span.sheet-pictos, .sheet-pc div.sheet-gear div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-collapse-flag + span, .sheet-settings-toggle .sheet-pc div.sheet-gear div.repitem input[type='checkbox'].sheet-collapse-flag + span, .sheet-pc div.sheet-gear div.repitem .sheet-settings-flag input[type='checkbox'].sheet-collapse-flag + span, .sheet-settings-flag .sheet-pc div.sheet-gear div.repitem input[type='checkbox'].sheet-collapse-flag + span, .sheet-pc div.sheet-gear div.repitem .sheet-flag-primary + div > input.sheet-collapse-flag + span, .sheet-pc div.sheet-gear div.repitem .repcontrol input.sheet-collapse-flag + span.repcontrol_edit:after, .repcontrol .sheet-pc div.sheet-gear div.repitem input.sheet-collapse-flag + span.repcontrol_edit:after, .sheet-pc div.sheet-gear div.repitem .repcontrol input.sheet-collapse-flag + span.repcontrol_add:after, .repcontrol .sheet-pc div.sheet-gear div.repitem input.sheet-collapse-flag + span.repcontrol_add:after, .sheet-pc div.sheet-gear div.repitem .itemcontrol input.sheet-collapse-flag + span.repcontrol_del, .itemcontrol .sheet-pc div.sheet-gear div.repitem input.sheet-collapse-flag + span.repcontrol_del { - grid-area: 1 / 4 / 1 / 5; } + grid-area: 1 / 5 / 1 / 6; } .sheet-pc div.sheet-gear div.repitem input.sheet-settings-flag, .sheet-pc div.sheet-gear div.repitem input.sheet-settings-flag + span.sheet-pictos, .sheet-pc div.sheet-gear div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-settings-flag + span, @@ -812,12 +961,35 @@ div.sheet-matrix-device .sheet-matrixFirewall { .repcontrol .sheet-pc div.sheet-gear div.repitem input.sheet-settings-flag + span.repcontrol_add:after, .sheet-pc div.sheet-gear div.repitem .itemcontrol input.sheet-settings-flag + span.repcontrol_del, .itemcontrol .sheet-pc div.sheet-gear div.repitem input.sheet-settings-flag + span.repcontrol_del { - grid-area: 1 / 5 / 1 / 6; } - .sheet-pc div.sheet-gear div.repitem input[name='attr_item'] { - text-align: left; } + grid-area: 1 / 6 / 1 / 7; } + .sheet-pc div.sheet-gear div.repitem label[data-i18n-title='item'] { + grid-column: 1 / 3; } + .sheet-pc div.sheet-gear div.repitem label[data-i18n-title='item'] input[type='number'] { + width: 100%; } + .sheet-pc div.sheet-gear div.repitem label[data-i18n-title='rating'] { + grid-column: 3 / 4; } + .sheet-pc div.sheet-gear div.repitem label[data-i18n-title='quantity'] { + grid-column: 4 / 5; } + .sheet-pc div.sheet-gear div.repitem select { + -webkit-appearance: none; + -moz-appearance: none; + text-indent: 3px; + border: none; + background: transparent; + box-shadow: none; + font-size: 1.3em; + max-height: 18px; + transition: all .2s; } + .sheet-pc div.sheet-gear div.repitem select:hover { + cursor: pointer; + transform: scale(1.3); } + .sheet-pc div.sheet-gear div.repitem input[name='attr_location'][value='person'] + span { + font-weight: bold; } .sheet-pc div.sheet-gear div.repitem div.sheet-settings { - grid-column: 1 / 6; - grid-template-columns: 1fr 5em 5em 1em 1em; } + grid-column: 1 / 7; + grid-template-columns: 1.5em 1fr 5em 5em 1em 1em; } + .sheet-pc select.sheet-attribute-select { + margin-top: 1%; } .sheet-pc div.sheet-magic { /***** SPELLS & PREPARTATIONS *****/ /***** RITUALS *****/ @@ -838,6 +1010,10 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-pc div.sheet-magic div.sheet-spellsForumlas div.repitem h3[data-i18n='notes'], .sheet-pc div.sheet-magic div.sheet-spellsForumlas div.repitem div.sheet-collapse { grid-column: 1 / 8; } + .sheet-pc div.sheet-magic div.sheet-spellsForumlas div.repitem label[data-i18n-title='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-magic div.sheet-spellsForumlas div.repitem h3[data-i18n='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-magic div.sheet-spellsForumlas div.repitem div.sheet-collapse span[name='attr_notes'] { + white-space: pre-line; } .sheet-pc div.sheet-magic div.sheet-spellsForumlas div.repitem input.sheet-collapse-flag { grid-area: 1 / 6 / 1 / 7; } .sheet-pc div.sheet-magic div.sheet-spellsForumlas div.repitem input.sheet-collapse-flag + span.sheet-pictos, .sheet-pc div.sheet-magic div.sheet-spellsForumlas div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-collapse-flag + span, .sheet-settings-toggle .sheet-pc div.sheet-magic div.sheet-spellsForumlas div.repitem input[type='checkbox'].sheet-collapse-flag + span, @@ -874,6 +1050,10 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-pc div.sheet-magic div.sheet-magic-rituals h3[data-i18n='notes'], .sheet-pc div.sheet-magic div.sheet-magic-rituals div.sheet-collapse { grid-column: 1 / 4; } + .sheet-pc div.sheet-magic div.sheet-magic-rituals label[data-i18n-title='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-magic div.sheet-magic-rituals h3[data-i18n='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-magic div.sheet-magic-rituals div.sheet-collapse span[name='attr_notes'] { + white-space: pre-line; } .sheet-pc div.sheet-magic div.sheet-magic-rituals input.sheet-collapse-flag { grid-area: 1 / 2 / 1 / 3; } .sheet-pc div.sheet-magic div.sheet-magic-rituals input.sheet-collapse-flag + span.sheet-pictos, .sheet-pc div.sheet-magic div.sheet-magic-rituals .sheet-settings-toggle input[type='checkbox'].sheet-collapse-flag + span, .sheet-settings-toggle .sheet-pc div.sheet-magic div.sheet-magic-rituals input[type='checkbox'].sheet-collapse-flag + span, @@ -917,6 +1097,10 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-pc div.sheet-magic div.sheet-magic-preps div.sheet-prepared-preparations div.repitem h3[data-i18n='notes'], .sheet-pc div.sheet-magic div.sheet-magic-preps div.sheet-prepared-preparations div.repitem div.sheet-collapse { grid-column: 1 / 7; } + .sheet-pc div.sheet-magic div.sheet-magic-preps div.sheet-prepared-preparations div.repitem label[data-i18n-title='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-magic div.sheet-magic-preps div.sheet-prepared-preparations div.repitem h3[data-i18n='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-magic div.sheet-magic-preps div.sheet-prepared-preparations div.repitem div.sheet-collapse span[name='attr_notes'] { + white-space: pre-line; } .sheet-pc div.sheet-magic div.sheet-magic-preps div.sheet-prepared-preparations div.repitem input.sheet-collapse-flag { grid-area: 1 / 5 / 1 / 6; } .sheet-pc div.sheet-magic div.sheet-magic-preps div.sheet-prepared-preparations div.repitem input.sheet-collapse-flag + span.sheet-pictos, .sheet-pc div.sheet-magic div.sheet-magic-preps div.sheet-prepared-preparations div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-collapse-flag + span, .sheet-settings-toggle .sheet-pc div.sheet-magic div.sheet-magic-preps div.sheet-prepared-preparations div.repitem input[type='checkbox'].sheet-collapse-flag + span, @@ -954,6 +1138,10 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-pc div.sheet-magic div.sheet-powers div.repitem h3[data-i18n='notes'], .sheet-pc div.sheet-magic div.sheet-powers div.repitem div.sheet-collapse { grid-column: 1 / 5; } + .sheet-pc div.sheet-magic div.sheet-powers div.repitem label[data-i18n-title='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-magic div.sheet-powers div.repitem h3[data-i18n='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-magic div.sheet-powers div.repitem div.sheet-collapse span[name='attr_notes'] { + white-space: pre-line; } .sheet-pc div.sheet-magic div.sheet-powers div.repitem input.sheet-collapse-flag { grid-area: 1/1/1 / 4; position: absolute; @@ -981,96 +1169,116 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-pc div.sheet-magic div.sheet-powers div.repitem div.sheet-settings { grid-column: 1 / 5; grid-template-columns: 1fr 3em 1em 1em; } - .sheet-pc div.sheet-matrix h3 { - color: #040404; } - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem { - grid-template-columns: 1em 1fr 1.5em 1em 1em; } - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem label[data-i18n-title='notes'], - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem h3[data-i18n='notes'], - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem div.sheet-collapse { - grid-column: 1 / 6; } - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-collapse-flag { - grid-area: 1 / 4 / 1 / 5; } - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-collapse-flag + span.sheet-pictos, .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-collapse-flag + span, .sheet-settings-toggle .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input[type='checkbox'].sheet-collapse-flag + span, - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .sheet-settings-flag input[type='checkbox'].sheet-collapse-flag + span, - .sheet-settings-flag .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input[type='checkbox'].sheet-collapse-flag + span, .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .sheet-flag-primary + div > input.sheet-collapse-flag + span, .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .repcontrol input.sheet-collapse-flag + span.repcontrol_edit:after, .repcontrol .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-collapse-flag + span.repcontrol_edit:after, - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .repcontrol input.sheet-collapse-flag + span.repcontrol_add:after, - .repcontrol .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-collapse-flag + span.repcontrol_add:after, .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .itemcontrol input.sheet-collapse-flag + span.repcontrol_del, .itemcontrol .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-collapse-flag + span.repcontrol_del { - grid-area: 1 / 4 / 1 / 5; } - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-settings-flag, - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-settings-flag + span.sheet-pictos, - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-settings-flag + span, - .sheet-settings-toggle .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input[type='checkbox'].sheet-settings-flag + span, - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .sheet-settings-flag input[type='checkbox'].sheet-settings-flag + span, - .sheet-settings-flag .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input[type='checkbox'].sheet-settings-flag + span, - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .sheet-flag-primary + div > input.sheet-settings-flag + span, - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .repcontrol input.sheet-settings-flag + span.repcontrol_edit:after, - .repcontrol .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-settings-flag + span.repcontrol_edit:after, - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .repcontrol input.sheet-settings-flag + span.repcontrol_add:after, - .repcontrol .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-settings-flag + span.repcontrol_add:after, - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .itemcontrol input.sheet-settings-flag + span.repcontrol_del, - .itemcontrol .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-settings-flag + span.repcontrol_del { - grid-area: 1 / 5 / 1 / 6; } - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input[name='attr_program_on'] { - grid-area: 1 / 1 / 1 / 1; } - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input[name='attr_program_on']:checked + span { - color: #FCD116; - font-weight: bolder; } - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input[name='attr_program_on']:checked + span + span { - font-weight: bolder; } - .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input[name='attr_program_on'] + span { + .sheet-pc div.sheet-matrix { + /* Needs to be refactored into Grid */ } + .sheet-pc div.sheet-matrix button[type='roll'] { + font-size: 0.9em; } + .sheet-pc div.sheet-matrix h3 { + color: #040404; } + .sheet-pc div.sheet-matrix div.sheet-device-attr { + display: inline; + transition: transform .2s; } + .sheet-pc div.sheet-matrix div.sheet-device-attr span { + position: relative; } + .sheet-pc div.sheet-matrix div.sheet-device-attr input[type='radio']:hover + span { + transform: scale(1.3); } + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem { + grid-template-columns: 1.5em 1fr 1.5em 1em 1em; } + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem label[data-i18n-title='notes'], + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem h3[data-i18n='notes'], + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem div.sheet-collapse { + grid-column: 1 / 6; } + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem label[data-i18n-title='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem h3[data-i18n='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem div.sheet-collapse span[name='attr_notes'] { + white-space: pre-line; } + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-collapse-flag { + grid-area: 1 / 4 / 1 / 5; } + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-collapse-flag + span.sheet-pictos, .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-collapse-flag + span, .sheet-settings-toggle .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input[type='checkbox'].sheet-collapse-flag + span, + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .sheet-settings-flag input[type='checkbox'].sheet-collapse-flag + span, + .sheet-settings-flag .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input[type='checkbox'].sheet-collapse-flag + span, .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .sheet-flag-primary + div > input.sheet-collapse-flag + span, .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .repcontrol input.sheet-collapse-flag + span.repcontrol_edit:after, .repcontrol .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-collapse-flag + span.repcontrol_edit:after, + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .repcontrol input.sheet-collapse-flag + span.repcontrol_add:after, + .repcontrol .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-collapse-flag + span.repcontrol_add:after, .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .itemcontrol input.sheet-collapse-flag + span.repcontrol_del, .itemcontrol .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-collapse-flag + span.repcontrol_del { + grid-area: 1 / 4 / 1 / 5; } + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-settings-flag, + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-settings-flag + span.sheet-pictos, + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-settings-flag + span, + .sheet-settings-toggle .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input[type='checkbox'].sheet-settings-flag + span, + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .sheet-settings-flag input[type='checkbox'].sheet-settings-flag + span, + .sheet-settings-flag .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input[type='checkbox'].sheet-settings-flag + span, + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .sheet-flag-primary + div > input.sheet-settings-flag + span, + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .repcontrol input.sheet-settings-flag + span.repcontrol_edit:after, + .repcontrol .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-settings-flag + span.repcontrol_edit:after, + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .repcontrol input.sheet-settings-flag + span.repcontrol_add:after, + .repcontrol .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-settings-flag + span.repcontrol_add:after, + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem .itemcontrol input.sheet-settings-flag + span.repcontrol_del, + .itemcontrol .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-settings-flag + span.repcontrol_del { + grid-area: 1 / 5 / 1 / 6; } + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-indicator { grid-area: 1 / 1 / 1 / 1; } - .sheet-pc div.sheet-matrix div.sheet-programs div.sheet-settings { - grid-column: 1 / 5; } - .sheet-pc div.sheet-matrix div.sheet-programs div.sheet-settings input[type='text'] { - grid-column: 1 / 4; - text-align: left; } - .sheet-pc div.sheet-matrix div.sheet-programs div.sheet-settings label { - grid-column: 1 / 4; } - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.sheet-headers { - display: grid; - grid-template-columns: 30% 1fr 1fr 4em 1em 1em; } - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.sheet-headers h2:nth-of-type(1n+2) { - text-align: center; } - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem { - grid-template-columns: 30% 1fr 1fr 4em 1em 1em; } - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem label[data-i18n-title='notes'], - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem h3[data-i18n='notes'], - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem div.sheet-collapse { - grid-column: 1 / 7; } - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-collapse-flag { - grid-area: 1 / 5 / 1 / 6; } - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-collapse-flag + span.sheet-pictos, .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-collapse-flag + span, .sheet-settings-toggle .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input[type='checkbox'].sheet-collapse-flag + span, - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .sheet-settings-flag input[type='checkbox'].sheet-collapse-flag + span, - .sheet-settings-flag .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input[type='checkbox'].sheet-collapse-flag + span, .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .sheet-flag-primary + div > input.sheet-collapse-flag + span, .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .repcontrol input.sheet-collapse-flag + span.repcontrol_edit:after, .repcontrol .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-collapse-flag + span.repcontrol_edit:after, - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .repcontrol input.sheet-collapse-flag + span.repcontrol_add:after, - .repcontrol .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-collapse-flag + span.repcontrol_add:after, .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .itemcontrol input.sheet-collapse-flag + span.repcontrol_del, .itemcontrol .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-collapse-flag + span.repcontrol_del { - grid-area: 1 / 5 / 1 / 6; } - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-settings-flag, - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-settings-flag + span.sheet-pictos, - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-settings-flag + span, - .sheet-settings-toggle .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input[type='checkbox'].sheet-settings-flag + span, - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .sheet-settings-flag input[type='checkbox'].sheet-settings-flag + span, - .sheet-settings-flag .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input[type='checkbox'].sheet-settings-flag + span, - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .sheet-flag-primary + div > input.sheet-settings-flag + span, - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .repcontrol input.sheet-settings-flag + span.repcontrol_edit:after, - .repcontrol .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-settings-flag + span.repcontrol_edit:after, - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .repcontrol input.sheet-settings-flag + span.repcontrol_add:after, - .repcontrol .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-settings-flag + span.repcontrol_add:after, - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .itemcontrol input.sheet-settings-flag + span.repcontrol_del, - .itemcontrol .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-settings-flag + span.repcontrol_del { - grid-area: 1 / 6 / 1 / 7; } - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem div.sheet-row { - grid-column: 1 / 7; } - .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem div.sheet-settings { - grid-column: 1 / 7; + .sheet-pc div.sheet-matrix div.sheet-programs div.repitem input.sheet-indicator + span { + grid-area: 1 / 1 / 1 / 1; } + .sheet-pc div.sheet-matrix div.sheet-programs div.sheet-settings { + grid-column: 1 / 5; } + .sheet-pc div.sheet-matrix div.sheet-programs div.sheet-settings input[type='text'] { + grid-column: 1 / 4; + text-align: left; } + .sheet-pc div.sheet-matrix div.sheet-programs div.sheet-settings label { + grid-column: 1 / 4; } + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.sheet-headers { + display: grid; grid-template-columns: 30% 1fr 1fr 4em 1em 1em; } + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.sheet-headers h2:nth-of-type(1n+2) { + text-align: center; } + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem { + grid-template-columns: 30% 1fr 1fr 4em 1em 1em; } + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem label[data-i18n-title='notes'], + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem h3[data-i18n='notes'], + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem div.sheet-collapse { + grid-column: 1 / 7; } + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem label[data-i18n-title='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem h3[data-i18n='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem div.sheet-collapse span[name='attr_notes'] { + white-space: pre-line; } + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-collapse-flag { + grid-area: 1 / 5 / 1 / 6; } + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-collapse-flag + span.sheet-pictos, .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-collapse-flag + span, .sheet-settings-toggle .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input[type='checkbox'].sheet-collapse-flag + span, + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .sheet-settings-flag input[type='checkbox'].sheet-collapse-flag + span, + .sheet-settings-flag .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input[type='checkbox'].sheet-collapse-flag + span, .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .sheet-flag-primary + div > input.sheet-collapse-flag + span, .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .repcontrol input.sheet-collapse-flag + span.repcontrol_edit:after, .repcontrol .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-collapse-flag + span.repcontrol_edit:after, + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .repcontrol input.sheet-collapse-flag + span.repcontrol_add:after, + .repcontrol .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-collapse-flag + span.repcontrol_add:after, .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .itemcontrol input.sheet-collapse-flag + span.repcontrol_del, .itemcontrol .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-collapse-flag + span.repcontrol_del { + grid-area: 1 / 5 / 1 / 6; } + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-settings-flag, + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-settings-flag + span.sheet-pictos, + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-settings-flag + span, + .sheet-settings-toggle .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input[type='checkbox'].sheet-settings-flag + span, + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .sheet-settings-flag input[type='checkbox'].sheet-settings-flag + span, + .sheet-settings-flag .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input[type='checkbox'].sheet-settings-flag + span, + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .sheet-flag-primary + div > input.sheet-settings-flag + span, + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .repcontrol input.sheet-settings-flag + span.repcontrol_edit:after, + .repcontrol .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-settings-flag + span.repcontrol_edit:after, + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .repcontrol input.sheet-settings-flag + span.repcontrol_add:after, + .repcontrol .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-settings-flag + span.repcontrol_add:after, + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem .itemcontrol input.sheet-settings-flag + span.repcontrol_del, + .itemcontrol .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem input.sheet-settings-flag + span.repcontrol_del { + grid-area: 1 / 6 / 1 / 7; } + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem div.sheet-row { + grid-column: 1 / 7; } + .sheet-pc div.sheet-matrix div.sheet-complex-forms div.repitem div.sheet-settings { + grid-column: 1 / 7; + grid-template-columns: 30% 1fr 1fr 4em 1em 1em; } + .sheet-pc div.sheet-social input:not(:placeholder-shown) { + background-color: transparent; } .sheet-pc div.sheet-social div.sheet-lifestyle div.repitem { grid-template-columns: 1fr 1.5em 1em 1em; } .sheet-pc div.sheet-social div.sheet-lifestyle div.repitem label[data-i18n-title='notes'], .sheet-pc div.sheet-social div.sheet-lifestyle div.repitem h3[data-i18n='notes'], .sheet-pc div.sheet-social div.sheet-lifestyle div.repitem div.sheet-collapse { grid-column: 1 / 5; } + .sheet-pc div.sheet-social div.sheet-lifestyle div.repitem label[data-i18n-title='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-social div.sheet-lifestyle div.repitem h3[data-i18n='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-social div.sheet-lifestyle div.repitem div.sheet-collapse span[name='attr_notes'] { + white-space: pre-line; } .sheet-pc div.sheet-social div.sheet-lifestyle div.repitem input.sheet-collapse-flag { grid-area: 1 / 3 / 1 / 4; } .sheet-pc div.sheet-social div.sheet-lifestyle div.repitem input.sheet-collapse-flag + span.sheet-pictos, .sheet-pc div.sheet-social div.sheet-lifestyle div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-collapse-flag + span, .sheet-settings-toggle .sheet-pc div.sheet-social div.sheet-lifestyle div.repitem input[type='checkbox'].sheet-collapse-flag + span, @@ -1107,6 +1315,7 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-pc div.sheet-social div.sheet-contacts div.sheet-headers { display: grid; grid-template-columns: 1fr 4em 5.5em 4em 1.5em 1em 1em; + grid-column-gap: 0.5%; width: 100%; } .sheet-pc div.sheet-social div.sheet-contacts div.repitem { grid-template-columns: 1fr 4em 5.5em 4em 1.5em 1em 1em; } @@ -1114,6 +1323,10 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-pc div.sheet-social div.sheet-contacts div.repitem h3[data-i18n='notes'], .sheet-pc div.sheet-social div.sheet-contacts div.repitem div.sheet-collapse { grid-column: 1 / 8; } + .sheet-pc div.sheet-social div.sheet-contacts div.repitem label[data-i18n-title='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-social div.sheet-contacts div.repitem h3[data-i18n='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-social div.sheet-contacts div.repitem div.sheet-collapse span[name='attr_notes'] { + white-space: pre-line; } .sheet-pc div.sheet-social div.sheet-contacts div.repitem input.sheet-collapse-flag { grid-area: 1 / 6 / 1 / 7; } .sheet-pc div.sheet-social div.sheet-contacts div.repitem input.sheet-collapse-flag + span.sheet-pictos, .sheet-pc div.sheet-social div.sheet-contacts div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-collapse-flag + span, .sheet-settings-toggle .sheet-pc div.sheet-social div.sheet-contacts div.repitem input[type='checkbox'].sheet-collapse-flag + span, @@ -1138,6 +1351,71 @@ div.sheet-matrix-device .sheet-matrixFirewall { grid-area: 1 / 7 / 1 / 8; } .sheet-pc div.sheet-social div.sheet-contacts div.repitem div.sheet-settings { grid-column: 1 / 8; } + .sheet-pc div.sheet-vehicle div.sheet-row-long { + display: inline-grid; + grid-column: 1 / 5; } + .sheet-pc div.sheet-vehicle div.sheet-vehicle-name { + grid-column: 1 / 3; } + .sheet-pc div.sheet-vehicle h3 { + color: #1c1c1c; + overflow: hidden; } + .sheet-pc div.sheet-vehicle label { + width: 100%; } + .sheet-pc div.sheet-vehicle div.sheet-col { + display: inline-grid; + grid-template-columns: 1fr 5em; } + .sheet-pc div.sheet-vehicle div.repitem { + grid-template-columns: 1fr 1fr 1em 1em; } + .sheet-pc div.sheet-vehicle div.repitem label[data-i18n-title='notes'], + .sheet-pc div.sheet-vehicle div.repitem h3[data-i18n='notes'], + .sheet-pc div.sheet-vehicle div.repitem div.sheet-collapse { + grid-column: 1 / 5; } + .sheet-pc div.sheet-vehicle div.repitem label[data-i18n-title='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-vehicle div.repitem h3[data-i18n='notes'] span[name='attr_notes'], + .sheet-pc div.sheet-vehicle div.repitem div.sheet-collapse span[name='attr_notes'] { + white-space: pre-line; } + .sheet-pc div.sheet-vehicle div.repitem input.sheet-collapse-flag { + grid-area: 1/1/1 / 4; + position: absolute; + width: 100%; } + .sheet-pc div.sheet-vehicle div.repitem input.sheet-collapse-flag + span.sheet-pictos, .sheet-pc div.sheet-vehicle div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-collapse-flag + span, .sheet-settings-toggle .sheet-pc div.sheet-vehicle div.repitem input[type='checkbox'].sheet-collapse-flag + span, + .sheet-pc div.sheet-vehicle div.repitem .sheet-settings-flag input[type='checkbox'].sheet-collapse-flag + span, + .sheet-settings-flag .sheet-pc div.sheet-vehicle div.repitem input[type='checkbox'].sheet-collapse-flag + span, .sheet-pc div.sheet-vehicle div.repitem .sheet-flag-primary + div > input.sheet-collapse-flag + span, .sheet-pc div.sheet-vehicle div.repitem .repcontrol input.sheet-collapse-flag + span.repcontrol_edit:after, .repcontrol .sheet-pc div.sheet-vehicle div.repitem input.sheet-collapse-flag + span.repcontrol_edit:after, + .sheet-pc div.sheet-vehicle div.repitem .repcontrol input.sheet-collapse-flag + span.repcontrol_add:after, + .repcontrol .sheet-pc div.sheet-vehicle div.repitem input.sheet-collapse-flag + span.repcontrol_add:after, .sheet-pc div.sheet-vehicle div.repitem .itemcontrol input.sheet-collapse-flag + span.repcontrol_del, .itemcontrol .sheet-pc div.sheet-vehicle div.repitem input.sheet-collapse-flag + span.repcontrol_del { + grid-area: 1 / 3 / 1 / 4; } + .sheet-pc div.sheet-vehicle div.repitem input.sheet-settings-flag, + .sheet-pc div.sheet-vehicle div.repitem input.sheet-settings-flag + span.sheet-pictos, + .sheet-pc div.sheet-vehicle div.repitem .sheet-settings-toggle input[type='checkbox'].sheet-settings-flag + span, + .sheet-settings-toggle .sheet-pc div.sheet-vehicle div.repitem input[type='checkbox'].sheet-settings-flag + span, + .sheet-pc div.sheet-vehicle div.repitem .sheet-settings-flag input[type='checkbox'].sheet-settings-flag + span, + .sheet-settings-flag .sheet-pc div.sheet-vehicle div.repitem input[type='checkbox'].sheet-settings-flag + span, + .sheet-pc div.sheet-vehicle div.repitem .sheet-flag-primary + div > input.sheet-settings-flag + span, + .sheet-pc div.sheet-vehicle div.repitem .repcontrol input.sheet-settings-flag + span.repcontrol_edit:after, + .repcontrol .sheet-pc div.sheet-vehicle div.repitem input.sheet-settings-flag + span.repcontrol_edit:after, + .sheet-pc div.sheet-vehicle div.repitem .repcontrol input.sheet-settings-flag + span.repcontrol_add:after, + .repcontrol .sheet-pc div.sheet-vehicle div.repitem input.sheet-settings-flag + span.repcontrol_add:after, + .sheet-pc div.sheet-vehicle div.repitem .itemcontrol input.sheet-settings-flag + span.repcontrol_del, + .itemcontrol .sheet-pc div.sheet-vehicle div.repitem input.sheet-settings-flag + span.repcontrol_del { + grid-area: 1 / 4 / 1 / 5; } + .sheet-pc div.sheet-vehicle div.repitem div.sheet-settings { + grid-column: 1 / 5; + grid-template-columns: 1fr 1fr 1em 1em; } + .sheet-pc div.sheet-vehicle div.repitem div.sheet-settings div.sheet-col { + grid-column-gap: 2%; } + .sheet-pc div.sheet-vehicle div.repitem div.sheet-settings div.sheet-col:nth-of-type(1) { + grid-template-columns: 40% 2.1em 2.1em 2.1em; + margin-right: 5px; } + .sheet-pc div.sheet-vehicle div.repitem div.sheet-settings div.sheet-col:nth-of-type(2) { + grid-template-columns: 1fr 2.1em 2.1em 2.1em; } + .sheet-pc div.sheet-vehicle div.repitem div.sheet-settings div.sheet-headers h2[data-i18n='base'] { + grid-column: 2 / 3; } + .sheet-pc div.sheet-vehicle div.repitem div.sheet-settings div.sheet-headers h2[data-i18n='mod'] { + grid-column: 3 / 4; } + .sheet-pc div.sheet-vehicle div.repitem div.sheet-settings div.sheet-headers h2[data-i18n='temp'] { + grid-column: 4 / 5; } + .sheet-pc div.sheet-vehicle div.repcontrol { + margin-top: 5%; } /***** PC ROWS & COLUMNS SETTINGS *****/ .sheet-pc-row { @@ -1158,62 +1436,6 @@ div.sheet-matrix-device .sheet-matrixFirewall { .sheet-settings-row select.sheet-skill-select { width: 29%; } -/***** VEHICLE *****/ -.sheet-vehicle-box .sheet-settings div, -.sheet-vehicle-box .sheet-display { - display: inline-block; - width: 100%; } - -.sheet-vehicle-box input[type='text'] { - width: 44%; } - -.sheet-vehicle-box label { - width: 20%; } - -.sheet-vehicle-box .sheet-row-long:first-child label { - width: 12%; } - -.sheet-vehicle-box label:nth-child(1n+4) { - text-align: right; - width: 21%; } - -/***** VEHICLE SETTING *****/ -.sheet-vehicle-box .sheet-settings h3 { - margin-right: 2%; } - -.sheet-vehicle-box .sheet-settings h3:nth-child(1) { - margin-left: 18%; - margin-top: -5px; } - -.sheet-vehicle-box .sheet-settings h3:nth-child(4) { - margin-left: 22%; } - -.sheet-vehicle-box .sheet-settings h3:nth-child(6) { - margin-right: 0px; } - -.sheet-vehicle-box .sheet-settings input[type='text'], -.sheet-vehicle-box .sheet-settings input[type='number'] { - border: none; } - -/***** VEHICLE DISPLAY *****/ -.sheet-vehicle-box .sheet-display-row { - text-align: left; - width: 49%; } - -.sheet-vehicle-box .sheet-display-row h3 { - width: 35%; } - -.sheet-vehicle-box .sheet-display-row div { - display: inline-block; - font-weight: normal; - text-align: center; } - -.sheet-vehicle-box .sheet-display-row div.sheet-vehicle-stat { - width: 60%; } - -.sheet-vehicle-box .sheet-collapsable { - padding-left: 0.2em; } - /***** HEADERS AND TRIANGLES *****/ div.sheet-header { display: inline-flex; @@ -1322,13 +1544,16 @@ div.sheet-htab { border-color: #aaa; border-radius: 5px; border-right: 3px solid #999; - border-style: outset; } + border-style: outset; + font-family: 'Pictos'; } .sheet-cc-row button[name*='shots_remove'] { transform: rotate(180deg); -ms-transform: rotate(180deg); /* IE 9 */ -webkit-transform: rotate(180deg); /* Safari 3-8 */ } + .sheet-cc-row button[name="act_reload"]:hover { + color: #fff; } .sheet-cc-row button[type='roll'] > span, .sheet-cc-row h3 + span { display: inline-block; @@ -1512,13 +1737,18 @@ div.sheet-htab { box-shadow: inset 0px 0px 3px 1px #7c7c7c; display: inline-block; margin-bottom: -25px; - margin-right: -7px; } + margin-right: -7px; + transition: transform .3s; } .sheet-squares input[type='radio']:checked ~ input[type='radio'] + span, .sheet-con-track input[type='radio']:checked ~ .sheet-squares span, .sheet-con-track input[type='hidden'][value='0'] ~ .sheet-squares span { background-color: transparent; } +.sheet-squares input[type='radio']:hover + span { + background-color: rgba(124, 124, 124, 0.5); + transform: scale(1.1); } + /***** MAKE CONDTION SQUARES APPEAR & DISPPEAR *****/ .sheet-hex-hider[value='8'] ~ input[type='radio']:nth-child(1n+19), .sheet-hex-hider[value='9'] ~ input[type='radio']:nth-child(1n+21), @@ -1583,7 +1813,7 @@ div.sheet-htab { .sheet-repeat-box h3 { color: #000; margin-bottom: -3px; } - .sheet-repeat-box button.sheet-pictos, .sheet-repeat-box .sheet-cc-row button[name*='shots'], .sheet-cc-row .sheet-repeat-box button[name*='shots'], .sheet-repeat-box .sheet-cc-row button[name='act_reload'], .sheet-cc-row .sheet-repeat-box button[name='act_reload'], .sheet-repeat-box .sheet-cc-row button[name='act_primary_ammo'], .sheet-cc-row .sheet-repeat-box button[name='act_primary_ammo'], .sheet-repeat-box .repcontrol button.repcontrol_edit:after, .repcontrol .sheet-repeat-box button.repcontrol_edit:after, + .sheet-repeat-box button.sheet-pictos, .sheet-repeat-box .repcontrol button.repcontrol_edit:after, .repcontrol .sheet-repeat-box button.repcontrol_edit:after, .sheet-repeat-box .repcontrol button.repcontrol_add:after, .repcontrol .sheet-repeat-box button.repcontrol_add:after, .sheet-repeat-box .itemcontrol button.repcontrol_del, .itemcontrol .sheet-repeat-box button.repcontrol_del, .sheet-repeat-box button.sheet-settings-button { @@ -1639,24 +1869,6 @@ div.sheet-htab { text-align: center; width: 10%; } -/***** COLLAPSABLE DIVS *****/ -.sheet-collapsable { - padding-left: 1.5em; - width: 100%; - word-break: break-word; } - .sheet-collapsable span { - white-space: pre-line; } - .sheet-display-flag:checked ~ .sheet-collapsable .sheet-desc-lifestyle { - width: 100%; } - -/***** DISPLAY FLAG FOR THE COLLAPSABLE DIVS *****/ -.sheet-quality-box .sheet-display-flag, .sheet-contacts .sheet-display-flag, .sheet-social-box .sheet-display-flag, .sheet-vehicle-box .sheet-display-flag, div.sheet-augs div.sheet-repeat-box .sheet-display-flag { - opacity: 0; - position: absolute; - top: 0px; - width: 90%; - height: 100%; } - /***** DISPLAY ROWS *****/ .sheet-display-row { display: inline-block; @@ -1667,14 +1879,6 @@ div.sheet-htab { .sheet-display-row:nth-of-type(1), .sheet-display-row:nth-of-type(1) button { text-align: left; } -/***** DISPLAY & SETTINGS *****/ -.sheet-skills-row, .sheet-contacts .sheet-display, -.sheet-contacts .sheet-settings div, .sheet-item-box .sheet-display, -.sheet-item-box .sheet-settings div, -.sheet-lifestyle .sheet-settings div { - display: inline-block; - width: 100%; } - /***** MATRIX *****/ .sheet-matrix select.sheet-skill-select { width: 26.5%; } @@ -1697,13 +1901,6 @@ div.sheet-htab { vertical-align: top; } /***** CYBERDECK *****/ -.sheet-cyberdeck button { - font-weight: bold; } - .sheet-cyberdeck button input[name="attr_flag"] { - position: absolute; } - .sheet-cyberdeck button input[name="attr_flag"] + span { - position: absolute; } - .sheet-cyberdeck h3 { line-height: 20px; } .sheet-cyberdeck h3[data-i18n="total"] { @@ -1737,11 +1934,6 @@ div.sheet-htab { margin-right: 1%; } /**** MATRIX BUBBLES ****/ -.sheet-pc .sheet-device-attr { - display: inline; } - .sheet-pc .sheet-device-attr span { - position: relative; } - .sheet-matrix-tot { display: inline-block; height: 20px; @@ -1850,15 +2042,8 @@ div.sheet-htab { .sheet-edg-hex, .sheet-con-hex { position: relative; - top: -60px; } - .sheet-edg-hex .sheet-edg-hex input[type='checkbox'], - .sheet-edg-hex .sheet-con-hex input[type='radio'], - .sheet-con-hex .sheet-edg-hex input[type='checkbox'], - .sheet-con-hex .sheet-con-hex input[type='radio'] { - height: 20px; - margin-right: -21px; - top: -9px; - width: 20px; } + top: -60px; + transition: transform .2s; } .sheet-edg-hex input[type='checkbox'], .sheet-con-hex input[type='radio'] { @@ -1869,6 +2054,9 @@ div.sheet-htab { opacity: 0; z-index: 2; position: relative; } + .sheet-edg-hex input[type='checkbox']:hover + span, + .sheet-con-hex input[type='radio']:hover + span { + transform: scale(1.3); } .sheet-hexagon { display: inline-block; @@ -1911,7 +2099,6 @@ div.sheet-htab { border-top-color: #9a9a9a; } .sheet-edg-hex input[type='checkbox']:checked + .sheet-hexagon, -.sheet-con-hex input[type='radio'] + .sheet-hexagon, .sheet-con-hex input[type='radio']:checked + .sheet-hexagon { background-color: #222; } @@ -2360,77 +2547,6 @@ span.sheet-d6 { /************************************************************************/ /* DISPLAY SETTINGS ============================= */ -.sheet-pc div.sheet-skill-box input[name='attr_specialization'][value=' '] ~ div.sheet-buttons button[name*='specialization'], -.sheet-pc div.sheet-skill-box input[name='attr_specialization'][value=''] ~ div.sheet-buttons button[name*='specialization'], .sheet-pc div.sheet-magic input.sheet-magic-toggle[value='rituals'] ~ .sheet-headers h2:nth-of-type(1n+2), .sheet-collapsable .sheet-desc, .sheet-collapsable .sheet-desc-lifestyle, .sheet-matrix, -.sheet-magic, -.sheet-resonance, -.sheet-optional, -.sheet-textboxes, -.sheet-optional-flag[value='0'] + .sheet-attr-header, -.sheet-category + div, -.sheet-category + div + div, .sheet-npc, .sheet-pc, .sheet-arms, .sheet-augs, .sheet-core, .sheet-gear, .sheet-options, .sheet-social, .sheet-vehicle, .sheet-skills-active, -.sheet-skills-know, -.sheet-skills-lang, .sheet-magic-spells, .sheet-magic-preps, .sheet-magic-rituals, .sheet-quality, .sheet-martial, div.sheet-collapse, -.sheet-settings, input.sheet-settings-toggle:checked ~ div.sheet-display, -input.sheet-settings-toggle:checked ~ .sheet-attr-col .sheet-attr-und div.sheet-display, -input.sheet-settings-toggle ~ .sheet-attr-lim div.sheet-settings, -input.sheet-settings-toggle:checked ~ .sheet-attr-lim div.sheet-display, -input.sheet-settings-toggle[value='settings'] ~ div.sheet-display, -input.sheet-settings-toggle[value='display'] ~ div.sheet-settings, -input.sheet-settings-toggle[value='display'] ~ div.sheet-settings-grid, input.sheet-settings-toggle[value='display'] ~ .sheet-settings, .sheet-hide-magic, .sheet-hide-resonance, div.sheet-weapon-range, -div.sheet-weapon-melee, .sheet-grunt, .sheet-host, .sheet-sprite, input[name='attr_sheet_type'][value='host'] ~ .sheet-npc .sheet-column:nth-of-type(2), -input[name='attr_sheet_type'][value='sprite'] ~ .sheet-npc .sheet-column:nth-of-type(1n+2), input[name='attr_flag_special'][value='mundane'] ~ div.sheet-npc .sheet-hide-magic, -input[name='attr_flag_special'][value='mundane'] ~ div.sheet-npc .sheet-hide-resonance, -input[name='attr_flag_special'][value='mundane'] ~ div.sheet-npc .sheet-grunt.sheet-hide-magic, -input[name='attr_flag_special'][value='mundane'] ~ div.sheet-npc .sheet-grunt.sheet-hide-resonance, -input[name='attr_flag_special'][value='resonance'] ~ div.sheet-npc .sheet-hide-magic, -input[name='attr_flag_special'][value='resonance'] ~ div.sheet-npc .sheet-grunt.sheet-hide-magic, -input[name='attr_flag_special'][value='magic'] ~ div.sheet-npc .sheet-hide-resonance, -input[name='attr_flag_special'][value='magic'] ~ div.sheet-npc .sheet-grunt.sheet-hide-resonance, -input[name='attr_stats_toggle']:not([value='settings']) ~ div.sheet-attribute .sheet-settings.sheet-hide-magic, -input[name='attr_stats_toggle']:not([value='settings']) ~ div.sheet-attribute .sheet-settings.sheet-hide-resonance, -input[name='attr_stats_toggle']:not([value='settings']) ~ div.sheet-body .sheet-settings.sheet-hide-magic, -input[name='attr_stats_toggle']:not([value='settings']) ~ div.sheet-body .sheet-settings.sheet-hide-resonance, input[name='attr_stats_toggle']:not([value='settings']) ~ div.sheet-body input[type='hidden'][value=''] + div.sheet-textrow, input[name='attr_stats_toggle']:not([value='settings']) ~ div.sheet-body input[type='hidden'][value=''] + div.sheet-rows.sheet-grunt, input[name='attr_specialization'][value=''] ~ button[name*='specialization'], -input[name='attr_specialization'][value=' '] ~ button[name*='specialization'], -input[name='attr_specialization'][value=''] ~ div.sheet-row-long div.sheet-buttons button[name*='specialization'], -input[name='attr_specialization'][value=' '] ~ div.sheet-row-long div.sheet-buttons button[name*='specialization'], input[name='attr_weapon_range'][value='range'] ~ div.sheet-settings h2[data-i18n='reach'], -input[name='attr_weapon_range'][value='range'] ~ div.sheet-settings label[data-i18n-title='reach'], input[name='attr_weapon_range'][value='melee'] ~ div.sheet-settings h2[data-i18n='modes'], -input[name='attr_weapon_range'][value='melee'] ~ div.sheet-settings h2[data-i18n='recoil'], -input[name='attr_weapon_range'][value='melee'] ~ div.sheet-settings h2[data-i18n='ammo'], -input[name='attr_weapon_range'][value='melee'] ~ div.sheet-settings label[data-i18n-title='modes'], -input[name='attr_weapon_range'][value='melee'] ~ div.sheet-settings label[data-i18n-title='recoil'], -input[name='attr_weapon_range'][value='melee'] ~ div.sheet-settings label[data-i18n-title='ammo'], -input[name='attr_weapon_range'][value='melee'] ~ div.sheet-settings span, input[name='attr_category']:not([value='Combat']) ~ h2[data-i18n='combat'], -input[name='attr_category']:not([value='Combat']) ~ h2[data-i18n='dam'], -input[name='attr_category']:not([value='Combat']) ~ select[name='attr_combat_type'], -input[name='attr_category']:not([value='Combat']) ~ label[data-i18n-title='dam'] { - display: none; } - -.sheet-display-flag:checked ~ .sheet-collapsable .sheet-desc, .sheet-tab-switch[value='active'] ~ .sheet-skills-active, -.sheet-tab-switch[value='knowledge'] ~ .sheet-skills-know, -.sheet-tab-switch[value='language'] ~ .sheet-skills-lang, .sheet-magic-toggle[value='spells'] ~ .sheet-magic-spells, .sheet-magic-toggle[value='preps'] ~ .sheet-magic-preps, .sheet-magic-toggle[value='rituals'] ~ .sheet-magic-rituals, .sheet-tab-switch[value='quality'] ~ .sheet-quality, .sheet-tab-switch[value='martial'] ~ .sheet-martial { - display: inline; } - -.sheet-pc h2, .sheet-pc h3, .sheet-pc .sheet-tabs, .sheet-pc div.sheet-skill-box div.sheet-row-long, .sheet-npc div.sheet-tabs, .sheet-npc div.sheet-mid, input[name='attr_sheet_type'][value='grunt'] ~ .sheet-npc .sheet-attribute.sheet-grunt, input[name='attr_sheet_type'][value='host'] ~ .sheet-npc .sheet-attribute.sheet-host, input[name='attr_sheet_type'][value='sprite'] ~ .sheet-npc .sheet-attribute.sheet-sprite, input[name='attr_sheet_type'][value='vehicle'] ~ .sheet-npc .sheet-attribute.sheet-vehicle { - display: inline-grid; } - -.sheet-pictos, .sheet-settings-toggle input[type='checkbox'] + span, -.sheet-settings-flag input[type='checkbox'] + span, .sheet-flag-primary + div > span, .sheet-cc-row button[name*='shots'], .sheet-cc-row button[name='act_reload'], .sheet-cc-row button[name='act_primary_ammo'], .repcontrol .repcontrol_edit:after, -.repcontrol .repcontrol_add:after, .itemcontrol .repcontrol_del { - font-family: 'Pictos'; } - -.sheet-display-flag:checked ~ .sheet-collapsable .sheet-desc-lifestyle, .sheet-optional-flag:not([value='0']) + .sheet-optional, .sheet-npc div.sheet-mid div.sheet-column, input[name='attr_sheet_type']:not([value='pc']) ~ .sheet-npc, -input[name='attr_sheet_type'][value='pc'] ~ .sheet-pc, .sheet-options_toggle[value='arms'] ~ .sheet-arms, .sheet-options_toggle[value='augs'] ~ .sheet-augs, .sheet-options_toggle[value='core'] ~ .sheet-core, .sheet-options_toggle[value='gear'] ~ .sheet-gear, .sheet-options_toggle[value='options'] ~ .sheet-options, .sheet-options_toggle[value='social'] ~ .sheet-social, .sheet-options_toggle[value='magic'] ~ .sheet-magic, .sheet-options_toggle[value='matrix'] ~ .sheet-matrix, .sheet-options_toggle[value='vehicle'] ~ .sheet-vehicle, input[name='attr_stats_toggle'][value='settings'] ~ .sheet-attribute .sheet-settings, -input[name='attr_stats_toggle'][value='settings'] ~ .sheet-body .sheet-column .sheet-settings, -input[name='attr_stats_toggle'][value='settings'] ~ .sheet-body .sheet-textrow .sheet-settings, input.sheet-settings-toggle[value='settings'] ~ .sheet-settings, .sheet-character-type[value='magic'] ~ .sheet-pc .sheet-pc-row .sheet-attr-col .sheet-hide-magic, input[name='attr_flag_special'][value='magic'] ~ .sheet-npc .sheet-hide-magic, .sheet-character-type[value='resonance'] ~ .sheet-pc .sheet-pc-row .sheet-attr-col .sheet-hide-resonance, input[name='attr_flag_special'][value='resonance'] ~ .sheet-npc .sheet-hide-resonance, input.sheet-tab-switch[value='range'] ~ .sheet-weapon-range, -input.sheet-tab-switch[value='melee'] ~ .sheet-weapon-melee, input[name='attr_sheet_type'][value='grunt'] ~ .sheet-npc .sheet-rows.sheet-grunt, -input[name='attr_sheet_type'][value='grunt'] ~ .sheet-npc .sheet-textrow.sheet-grunt, input[name='attr_sheet_type'][value='host'] ~ .sheet-npc .sheet-rows.sheet-host, -input[name='attr_sheet_type'][value='host'] ~ .sheet-npc .sheet-textrow.sheet-host, input[name='attr_sheet_type'][value='sprite'] ~ .sheet-npc .sheet-rows.sheet-sprite, -input[name='attr_sheet_type'][value='sprite'] ~ .sheet-npc .sheet-textrow.sheet-sprite, input[name='attr_sheet_type'][value='vehicle'] ~ .sheet-npc .sheet-rows.sheet-vehicle, -input[name='attr_sheet_type'][value='vehicle'] ~ .sheet-npc .sheet-textrow.sheet-vehicle, input[name='attr_flag_matrix'][value='matrix'] ~ div.sheet-matrix, -.sheet-static { - display: inline-block; } - /***** PC AND NPC *****/ /***** TABS *****/ /***** SWITCH BETWEEN DIFFERENT TABS *****/ @@ -2451,9 +2567,6 @@ input.sheet-settings-toggle:checked ~ .sheet-attr-lim div.sheet-settings { input.sheet-settings-flag:checked ~ div.sheet-settings { display: inherit; } -input.sheet-collapse-flag:checked ~ div.sheet-collapse { - display: block; } - /* OLD WAY TO SHOW & HIDE THINGS */ /***** PC WEAPONS *****/ /***** NPC TYPES *****/ @@ -2463,13 +2576,11 @@ input[name='attr_stats_toggle']:not([value='settings']) ~ div.sheet-body div.she .sheet-pc .sheet-tabs input[value*='arms'] ~ button[name*='arms'], .sheet-pc .sheet-tabs input[value*='augs'] ~ button[name*='augs'], .sheet-pc .sheet-tabs input[value*='core'] ~ button[name*='core'], .sheet-pc .sheet-tabs input[value*='gear'] ~ button[name*='gear'], .sheet-pc .sheet-tabs input[value*='options'] ~ button[name*='options'], .sheet-pc .sheet-tabs input[value*='social'] ~ button[name*='social'], .sheet-pc .sheet-tabs input[value*='magic'] ~ button[name*='magic'], .sheet-pc .sheet-tabs input[value*='matrix'] ~ button[name*='matrix'], .sheet-pc .sheet-tabs input[value*='vehicle'] ~ button[name*='vehicle'] { background-color: #610b0d; - box-shadow: inset 0px 0px 3px 1px #e31715; - color: #fff; } + box-shadow: inset 0px 0px 3px 1px #e31715; } /*****************************************************************************************/ /**************************************** FOOTER ****************************************/ /***************************************************************************************/ -/**** Footer ****/ .sheet-footer { border: none; font-size: 0.55em; @@ -2497,19 +2608,18 @@ div.sheet-footer img { display: inline-block; vertical-align: top; min-height: 27px; } - -.repcontrol .btn { - background: none; - border: medium none; - box-shadow: none; - color: transparent !important; - display: inline-block; - font-size: 15px; - margin-left: 10px; - outline: 0; - padding: 0px 0px 0px 0px; - text-shadow: none; - width: 25px; } + .repcontrol .btn { + background: none; + border: medium none; + box-shadow: none; + color: transparent !important; + display: inline-block; + font-size: 15px; + margin-left: 10px; + outline: 0; + padding: 0px; + text-shadow: none; + width: 25px; } .repcontrol .repcontrol_edit:after, .repcontrol .repcontrol_add:after { @@ -2532,7 +2642,7 @@ div.sheet-footer img { .repcontrol .repcontrol_edit:after, .repcontrol .repcontrol_add:after { - color: #000; + color: #040404; position: relative; } .sheet-npc .repcontrol .repcontrol_edit:after, @@ -2556,48 +2666,63 @@ div.sheet-footer img { width: 18px; } .itemcontrol .repcontrol_del { - background-color: darkred; } + background-color: #610b0d; } /********************************************************************************************************/ /**************************************** Roll template *******************************************/ /********************************************************************************************************/ .sheet-rolltemplate-rolls div.sheet-template-body { - border: 2px solid #000 !important; + border: 2px solid #040404 !important; border-radius: 3px 3px 3px 3px; } .sheet-rolltemplate-rolls .sheet-template-header { - background-color: #431714; - border: 1px solid #000; - border-bottom: 2px solid #000; - box-shadow: inset 0px 0px 3px 1px #000; + background-color: #610b0d; + border: 1px solid #040404; + border-bottom: 2px solid #040404; + box-shadow: inset 0px 0px 3px 1px #040404; color: #fff; font-size: 1.5em; font-variant: small-caps; - font-weight: bold; letter-spacing: 2px; - padding: 8px 0px 3px 0px; + padding: 3px 0px 5px 0px; text-align: center; - text-transform: capitalize; } - -.sheet-rolltemplate-rolls .sheet-template-header span { - font-family: 'tahoma'; - font-size: 0.5em; - font-weight: normal; - font-variant: normal; - letter-spacing: 1px; } + text-transform: capitalize; + font-weight: bold; } + .sheet-rolltemplate-rolls .sheet-template-header h1 { + font-size: 1em; + color: #fff; + line-height: 1em; } + .sheet-rolltemplate-rolls .sheet-template-header span { + font-family: 'tahoma'; + font-size: 0.5em; + font-variant: normal; + letter-spacing: 1px; } .sheet-rolltemplate-rolls .sheet-template-row { color: #fff; text-align: center; font-size: 18px; - background-color: #555; - box-shadow: inset 0px 0px 3px 1px #000; + background-color: #1c1c1c; + box-shadow: inset 0px 0px 3px 1px #040404; line-height: 1.1em; font-family: 'helvetica'; padding: 5px 5px 3px 5px; } - -.sheet-rolltemplate-rolls .sheet-template-row:nth-child(2n+0) { - background-color: #1c1c1c; } + .sheet-rolltemplate-rolls .sheet-template-row:nth-child(2n+0) { + background-color: #555; } + .sheet-rolltemplate-rolls .sheet-template-row a[href^="~"] { + font-family: "dicefontd6"; + color: #1c1c1c; + border: none; + box-shadow: outset 0px 0px 3px 1px #040404; + font-size: 1.8em; + background: none !important; + padding: 1px; + color: #fff; + text-shadow: 1px 1px 2px black, 0 0 25px #1c1c1c, 0 0 5px #1c1c1c; } + .sheet-rolltemplate-rolls .sheet-template-row a[href^="~"]:hover, .sheet-rolltemplate-rolls .sheet-template-row a[href^="~"]:focus, .sheet-rolltemplate-rolls .sheet-template-row a[href^="~"]:active { + font-weight: bold; + color: #fff; + text-shadow: 1px 1px 2px black, 0 0 25px red, 0 0 5px #610b0d; } .sheet-rolltemplate-rolls .inlinerollresult { display: inline-block; @@ -2768,9 +2893,6 @@ div.sheet-hidden div { margin-right: 2%; width: 40%; } -/********************************************************************************************************/ -/******************************* FireFox *******************************************/ -/******************************************************************************************************/ input[type=number]::-webkit-outer-spin-button, input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; @@ -2779,9 +2901,6 @@ input[type=number]::-webkit-inner-spin-button { input[type=number] { -moz-appearance: textfield; } -/********************************************************************************************/ -/***************** French Adjustments ********************************/ -/*******************************************************************************************/ .charsheet.lang-fr .sheet-tab-whisper, .charsheet.lang-fr .sheet-tab-toggles { margin-right: 2%; } diff --git a/Shadowrun5thEdition/Shadowrun5thEdition.html b/Shadowrun5thEdition/Shadowrun5thEdition.html index 435be2009d..dd8e08e61c 100644 --- a/Shadowrun5thEdition/Shadowrun5thEdition.html +++ b/Shadowrun5thEdition/Shadowrun5thEdition.html @@ -1,5 +1,5 @@ - +
@@ -28,7 +28,7 @@ - + @@ -404,7 +404,7 @@
- - + -
- - -
+ + +
- - -
+ + +
- - -
+ + +
i x
- + i x
- +

notes

-
+
i x

notes

-
+
+ + i x
@@ -1320,7 +1328,8 @@
- + + i x
@@ -1350,8 +1359,8 @@

Category

- + @@ -1395,7 +1404,8 @@
- + + i x
@@ -1425,8 +1435,8 @@

Category

- + @@ -1474,7 +1484,7 @@

- + i x
@@ -1508,7 +1518,7 @@
- + i x
@@ -1580,10 +1590,10 @@

Name

-

Rating

+

Rating

-
+
i x
@@ -1730,7 +1740,7 @@

Programs

- Q + Q i x @@ -1794,7 +1804,8 @@
- + + i x
@@ -1857,15 +1868,15 @@

- +

- +

- +

@@ -1915,7 +1926,7 @@

favor

-
+
i x @@ -1935,145 +1946,211 @@
-
-
-

Vehicle

-
-
-
- -
-
-
- - - - - - - - -
-
- - - - - - - - - - - - -
-
- - - - - - - - - - - - -
-
- - - - - - - - - - - - -
-
-

Base

Modifier

-

Temp

Base

-

Modifier

Temp

-
-

Notes

- -
-
-
- -
-
-

Vehicle

-
- -
-
-
-

Handling

-
- -
-
-
-
-
-

Acceleration

-
- -
-
-
-

Speed

-
- -
-
-
-
-
-

Pilot

-
- -
-
-
-

Body

-
- -
-
-
-
-
-

Armor

-
- -
-
-
-

Sensor

-
- -
-
-
-
-
-
-
- x -
-
-
-
-
-
+
+
+
+
+

Vehicle

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

+
+
+

+
+
+
+
+

+
+
+

+
+
+
+
+

+
+
+

+
+
+
+
+

+
+
+

+
+
+ i + x +
+
+
+

+ +
+
+
+

+ + + + + +
+
+

+ + + + + +
+
+
+
+

+ + + + + +
+
+

+ + + + + +
+
+
+
+

+ + + + + +
+
+

+ + + + + +
+
+
+
+

+ + + + + +
+
+

+ + + + + +
+
+
+
+

+

+

+
+
+

+

+

+
+
+

notes

+ +
+
+
+
+
+
+

Options

@@ -2324,7 +2401,6 @@
-

Bonuses

Professional Rating

@@ -2332,6 +2408,7 @@
+

Bonuses

-

Modifier

+

Modifier

+ =
@@ -2614,8 +2691,8 @@ x - - + +

Skill

Rating

@@ -2700,7 +2777,7 @@ - + @@ -2738,7 +2815,7 @@ x - - + +

Skill

Rating

@@ -2793,7 +2870,7 @@ x - - + +

Skill

Rating

@@ -2848,7 +2925,7 @@ +
+ +
+
{{#header}} +

{{header}}

{{/header}} + {{#base}}{{base}}{{/base}} + {{#rollLess() wound 0}} ♦ {{/rollLess() wound 0}} + {{#rollLess() mod 0}} ♦ {{/rollLess() mod 0}} + {{#rollGreater() mod 0}} ♦ {{/rollGreater() mod 0}} + {{#rollGreater() edge 0}} ♦ {{/rollGreater() edge 0}} +
+
{{#dice}} +
{{dice}}
{{/dice}} + {{#desc}} +
+ {{desc}} + {{#rollGreater() rea 0}},{{rea}} + {{/rollGreater() rea 0}} + {{#rollGreater() drain 1}},{{drain}} + {{/rollGreater() drain 1}} + {{#rollLess() drain 2}},{{drain}} + {{/rollLess() drain 2}}
{{/desc}} +
+
+
+
@@ -3501,7 +3576,6 @@ class PrimaryArmor { - const processingFunctions = { convertIntegerNegative: number => number > 0 ? -Math.abs(number) : number, convertIntegersNegatives: numbers => { @@ -3536,159 +3610,176 @@ const processingFunctions = { setAttributes: (update, silent) => silent && typeof update === 'object' ? setAttrs(update, {silent:true}) : typeof update === 'object' ? setAttrs(update) : console.error(`${update} is not an object`), sliceAttr: attribute => attribute.slice(2, -1), sumIntegers: numbers => numbers.reduce((a,b) => a + b, 0), +} + //for Mocha Unit Testing +//-const processingFunctions = require('../js/processingFunctions'); - shadowrun: { - addRepRow: (repRowID, attributeList) => { - let weaponAttributeWithRepeatingRow = [] - attributeList.forEach(weaponAttribute => weaponAttributeWithRepeatingRow.push(`${repRowID}_${weaponAttribute}`)) - return weaponAttributeWithRepeatingRow - }, - attributeFactory: attrs => { - attrs = processingFunctions.shadowrun.findFlagInKeys(attrs) ? processingFunctions.shadowrun.processTempFlags(attrs) : attrs - attrs = processingFunctions.parseIntegers(attrs) - attrs = processingFunctions.shadowrun.calculateBonuses(attrs) - attrs.total = processingFunctions.sumIntegers(Object.values(attrs)) - attrs.base = attrs.total - attrs.bonus - return attrs - }, - conditionFactory: attrs => { - attrs.attribute = processingFunctions.shadowrun.determineConditionAttribute(attrs) - attrs.base = processingFunctions.shadowrun.determineConditionBase(attrs.sheet_type, attrs.flag_drone) - attrs.modifier = attrs[processingFunctions.shadowrun.findModifierInKeys(attrs)] - Object.keys(attrs).forEach(key => !['attribute', 'base', 'modifier'].includes(key) ? delete attrs[key] : false) - attrs = processingFunctions.parseIntegers(attrs) - return attrs - }, - contructRepeatingWeaponAttributes: (repRowID, type) => { - const attributeList = processingFunctions.shadowrun.determineWeaponAttributesByType(type) - const constructedWeaponAttributes = processingFunctions.shadowrun.addRepRow(repRowID, attributeList) - return constructedWeaponAttributes - }, - buildDisplay: (base, bonus) => bonus === 0 ? base : `${base} (${base + bonus})`, - calculateBonuses: attrs => { - attrs.bonus = 0 - for (let [key, value] of Object.entries(attrs)) { - if (key.includes('modifier') || key.includes('temp')) { - attrs.bonus += value - delete attrs[key] - } - } - return attrs - }, - calculateConditionTracks: conditionInts => Math.ceil(conditionInts.attribute/2) + conditionInts.base + conditionInts.modifier, - calculateLimitTotal: attrs => Math.ceil((attrs[0] + attrs[1] + (attrs[2] * 2))/3), - calculateRunSpeed: (agility, modifier) => (agility * 4) + modifier, - calculateWalkSpeed:(agility, modifier) => (agility * 2) + modifier, - calculateWounds: attrs => { - const divisor = attrs.low_pain_tolerance === 2 ? attrs.low_pain_tolerance : 3; - const highPain = attrs.high_pain_tolerance >= 1 ? attrs.high_pain_tolerance : 0; - let sum = 0; +const shadowrunFunctions = { + addRepRow: (repRowID, attributeList) => { + let weaponAttributeWithRepeatingRow = [] + attributeList.forEach(weaponAttribute => weaponAttributeWithRepeatingRow.push(`${repRowID}_${weaponAttribute}`)) + return weaponAttributeWithRepeatingRow + }, - ["stun", "physical"].forEach(attr => { - const damageCompensator = attrs[`damage_compensators_${attr}`] || 0 - let dividend = Math.max(attrs[`${attr}`] - (highPain + damageCompensator), 0) - sum -= Math.floor(dividend / divisor) || 0 - }) - return sum - }, - convertSkillSelectToHiddenSkill: skillName => { - let skill = skillName.toLowerCase() - skill = skill.includes('group') ? skill.slice(0, -6) : skill - skill = skill.includes(" ") ? skill.replace(/ /g,"") : skill - return skill - }, - determineConditionBase: (type, drone) => drone && drone === 'drone' ? 6 : type === 'vehicle' ? 12 : 8, - determineConditionAttribute: attrs => attrs.willpower ? attrs.willpower : attrs.body ? attrs.body : attrs.device_rating ? attrs.device_rating : 0, - determineWeaponAttributesByType: weaponType => weaponType === 'range' ? sheetAttributes.rangeAttributes : sheetAttributes.meleeAttributes, - findFlagInKeys: attrs => Object.keys(attrs).find(key => key.includes('_flag')), - findModifierInKeys: attrs => Object.keys(attrs).find(key => key.includes('_modifier')), - processTempFlags: attrs => { - try { - const tempFlag = processingFunctions.shadowrun.findFlagInKeys(attrs) - const attrName = tempFlag.split('_temp_flag')[0] - attrs[`${tempFlag}`] === 'on' ? false : delete attrs[`${attrName}_temp`]; - delete attrs[`${tempFlag}`]; - return attrs - } catch (error) { - console.error(error) - } - }, - resetRepeatingFieldsPrimaries: (repeatingSection, repRowID) => { - getSectionIDs(repeatingSection, ids => { - let attributesWithIDs = []; - let update = {}; - ids.forEach(id => attributesWithIDs.push(`${repeatingSection}_${id}_primary`)) - attributesWithIDs.forEach(attribute => !attribute.includes(repRowID) ? update[attribute] = 0 : false) - setAttrs(update); - }) - }, - shotsFired: (shots, trigger) => shots > 0 && trigger.includes('remove') ? shots -= 1 : trigger.includes('add') ? shots += 1 : shots, - updateLimitTotal: attrs => { - attrs.essence ? Math.ceil(attrs.essence) || 0 : false; - return processingFunctions.shadowrun.calculateLimitTotal(Object.values(attrs)) - }, - resetPrimaryArmor: () => { - const resetPrimary = new PrimaryArmor() - let update = {} - for (let [key, value] of Object.entries(resetPrimary)) { - update[key] = value - } - return update - }, - resetPrimaryWeapon: type => { - const resetPrimary = type === 'range' ? new PrimaryRangeWeapon(type) : new PrimaryMeleeWeapon(type) - let update = {} - for (let [key, value] of Object.entries(resetPrimary)) { - update[key] = value - } - return update - }, - updatePrimaryArmor: attrs => { - let update = {} + attributeFactory: attrs => { + attrs = shadowrunFunctions.findFlagInKeys(attrs) ? shadowrunFunctions.processTempFlags(attrs) : attrs + attrs = processingFunctions.parseIntegers(attrs) + attrs = shadowrunFunctions.calculateBonuses(attrs) + attrs.total = processingFunctions.sumIntegers(Object.values(attrs)) + attrs.base = attrs.total - attrs.bonus + return attrs + }, + conditionFactory: attrs => { + attrs.attribute = shadowrunFunctions.determineConditionAttribute(attrs) + attrs.base = shadowrunFunctions.determineConditionBase(attrs.sheet_type, attrs.flag_drone) + attrs.modifier = attrs[shadowrunFunctions.findModifierInKeys(attrs)] + Object.keys(attrs).forEach(key => !['attribute', 'base', 'modifier'].includes(key) ? delete attrs[key] : false) + attrs = processingFunctions.parseIntegers(attrs) + return attrs + }, - for (let [key, value] of Object.entries(attrs)) { - const repRowID = processingFunctions.getReprowid(key) - if (key.includes('name')) { - update['armor_name'] = attrs[`${repRowID}_name`] - } else if (key.includes('rating')) { - update['armor_rating'] = value - } else if (key.includes('dicepool_modifier')) { - update['soak_modifier'] = value - } else { - const type = key.split('_')[3] - update[`${type}_modifier`] = value - } - } + contructRepeatingWeaponAttributes: (repRowID, type) => { + const attributeList = shadowrunFunctions.determineWeaponAttributesByType(type) + const constructedWeaponAttributes = shadowrunFunctions.addRepRow(repRowID, attributeList) + return constructedWeaponAttributes + }, - return update - }, - updatePrimaryWeapons: attrs => { - let update = {} - for (let [key, value] of Object.entries(attrs)) { - const type = processingFunctions.findRepeatingField(key) - const weaponAttribute = processingFunctions.getReprowAttribute(key) - const primaryAttributeName = key.includes('weapon') ? `primary_${type}_weapon` : `primary_${type}_weapon_${weaponAttribute}` - update[primaryAttributeName] = value + buildDisplay: (base, bonus) => bonus === 0 ? base : `${base} (${base + bonus})`, - if (key.includes('ammo')) { - update[`${primaryAttributeName}_max`] = value - } + calculateBonuses: attrs => { + attrs.bonus = 0 + for (let [key, value] of Object.entries(attrs)) { + if (key.includes('modifier') || key.includes('temp')) { + attrs.bonus += value + delete attrs[key] } - return update } + return attrs + }, + calculateConditionTracks: conditionInts => Math.ceil(conditionInts.attribute/2) + conditionInts.base + conditionInts.modifier, + calculateLimitTotal: attrs => Math.ceil((attrs[0] + attrs[1] + (attrs[2] * 2))/3), + calculateRunSpeed: (agility, modifier) => (agility * 4) + modifier, + calculateWalkSpeed:(agility, modifier) => (agility * 2) + modifier, + calculateWounds: attrs => { + const divisor = attrs.low_pain_tolerance === 2 ? attrs.low_pain_tolerance : 3; + const highPain = attrs.high_pain_tolerance >= 1 ? attrs.high_pain_tolerance : 0; + let sum = 0; + + ["stun", "physical"].forEach(attr => { + const damageCompensator = attrs[`damage_compensators_${attr}`] || 0 + let dividend = Math.max(attrs[`${attr}`] - (highPain + damageCompensator), 0) + sum -= Math.floor(dividend / divisor) || 0 + }) + return sum + }, + + convertSkillSelectToHiddenSkill: skillName => { + let skill = skillName.toLowerCase() + skill = skill.includes('group') ? skill.slice(0, -6) : skill + skill = skill.includes(" ") ? skill.replace(/ /g,"") : skill + return skill + }, + + determineConditionBase: (type, drone) => drone && drone === 'drone' ? 6 : type === 'vehicle' ? 12 : 8, + determineConditionAttribute: attrs => attrs.willpower ? attrs.willpower : attrs.body ? attrs.body : attrs.device_rating ? attrs.device_rating : 0, + determineExplodingEdge: newValue => newValue === `@{edge}` ? "!" : "", + determineWeaponAttributesByType: weaponType => weaponType === 'range' ? sheetAttributes.rangeAttributes : sheetAttributes.meleeAttributes, + + findFlagInKeys: attrs => Object.keys(attrs).find(key => key.includes('_flag')), + findModifierInKeys: attrs => Object.keys(attrs).find(key => key.includes('_modifier')), + + processTempFlags: attrs => { + try { + const tempFlag = shadowrunFunctions.findFlagInKeys(attrs) + const attrName = tempFlag.split('_temp_flag')[0] + attrs[`${tempFlag}`] === 'on' ? false : delete attrs[`${attrName}_temp`]; + delete attrs[`${tempFlag}`]; + return attrs + } catch (error) { + console.error(error) + } + }, + + resetRepeatingFieldsPrimaries: (repeatingSection, repRowID) => { + getSectionIDs(repeatingSection, ids => { + let attributesWithIDs = []; + let update = {}; + ids.forEach(id => attributesWithIDs.push(`${repeatingSection}_${id}_primary`)) + attributesWithIDs.forEach(attribute => !attribute.includes(repRowID) ? update[attribute] = 0 : false) + setAttrs(update); + }) + }, + + shotsFired: (shots, trigger) => shots > 0 && trigger.includes('remove') ? shots -= 1 : trigger.includes('add') ? shots += 1 : shots, + + //Reset will remove data in Primary entries on Core tab + resetPrimaryArmor: () => { + const resetPrimary = new PrimaryArmor() + let update = {} + for (let [key, value] of Object.entries(resetPrimary)) { + update[key] = value + } + return update + }, + resetPrimaryWeapon: type => { + const resetPrimary = type === 'range' ? new PrimaryRangeWeapon(type) : new PrimaryMeleeWeapon(type) + let update = {} + for (let [key, value] of Object.entries(resetPrimary)) { + update[key] = value + } + return update + }, + + updateLimitTotal: attrs => { + attrs.essence ? Math.ceil(attrs.essence) || 0 : false; + return shadowrunFunctions.calculateLimitTotal(Object.values(attrs)) + }, + + //Update Functions take data from one place and applies it to other attributes + updatePrimaryArmor: attrs => { + let update = {} + + for (let [key, value] of Object.entries(attrs)) { + const repRowID = processingFunctions.getReprowid(key) + if (key.includes('name')) { + update['armor_name'] = attrs[`${repRowID}_name`] + } else if (key.includes('rating')) { + update['armor_rating'] = value + } else if (key.includes('dicepool_modifier')) { + update['soak_modifier'] = value + } else { + const type = key.split('_')[3] + update[`${type}_modifier`] = value + } + } + + return update + }, + updatePrimaryWeapons: attrs => { + let update = {} + for (let [key, value] of Object.entries(attrs)) { + const type = processingFunctions.findRepeatingField(key) + const weaponAttribute = processingFunctions.getReprowAttribute(key) + const primaryAttributeName = key.includes('weapon') ? `primary_${type}_weapon` : `primary_${type}_weapon_${weaponAttribute}` + update[primaryAttributeName] = value + + if (key.includes('ammo')) { + update[`${primaryAttributeName}_max`] = value + } + } + return update } } +//for Mocha Unit Testing +//-module.exports = shadowrunFunctions; -//for Mocha Unit Texting -//module.exports = processingFunctions; - - //Edge toggle to include ! for exploding dice - const edgeToggle = eventinfo => { - processingFunctions.setAttributes({ - explode_toggle: eventinfo.newValue != 0 ? "!" : "" - }) - } + //Edge toggle to include ! for exploding dice +const edgeToggle = newValue => { + processingFunctions.setAttributes({ + explode_toggle: shadowrunFunctions.determineExplodingEdge(newValue) + }) +} const updateHostAttributes = newValue => { newValue = processingFunctions.parseInteger(newValue) @@ -3725,42 +3816,32 @@ const updatePrimary = eventinfo => { let update = {} if (repRowID.includes('armor')) { - update = processingFunctions.shadowrun.updatePrimaryArmor({[eventinfo.triggerName]: eventinfo.newValue}) + update = shadowrunFunctions.updatePrimaryArmor({[eventinfo.triggerName]: eventinfo.newValue}) } else { - update = processingFunctions.shadowrun.updatePrimaryWeapons({[eventinfo.triggerName]: eventinfo.newValue}) + update = shadowrunFunctions.updatePrimaryWeapons({[eventinfo.triggerName]: eventinfo.newValue}) } - processingFunctions.setAttributes(update) } }) } -const updateRepeatingWeaponPrimary = (eventinfo, type) => { +const updateRepeatingPrimary = (eventinfo, type) => { const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) - if (eventinfo.newValue === 'primary') { - const constructedWeaponAttributes = processingFunctions.shadowrun.contructRepeatingWeaponAttributes(repRowID, type) - getAttrs(constructedWeaponAttributes, attrs => { - const update = processingFunctions.shadowrun.updatePrimaryWeapons(attrs) + if (eventinfo.newValue === undefined) { + return false + } else if (eventinfo.newValue === 'primary') { + const constructedAttributes = type === 'armor' ? shadowrunFunctions.addRepRow(repRowID, sheetAttributes.armorAttributes) : shadowrunFunctions.contructRepeatingWeaponAttributes(repRowID, type); + + //get the attributes to update primary + getAttrs(constructedAttributes, attrs => { + const update = type === 'armor' ? shadowrunFunctions.updatePrimaryArmor(attrs) : shadowrunFunctions.updatePrimaryWeapons(attrs); processingFunctions.setAttributes(update) }) - processingFunctions.shadowrun.resetRepeatingFieldsPrimaries(`repeating_${type}`, repRowID) - } else { - const update = processingFunctions.shadowrun.resetPrimaryWeapon(type) - processingFunctions.setAttributes(update) - } -} -const updateRepeatingArmorPrimary = eventinfo => { - const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) - if (eventinfo.newValue === 'primary') { - const constructedArmorAttributes = processingFunctions.shadowrun.addRepRow(repRowID, sheetAttributes.armorAttributes) - getAttrs(constructedArmorAttributes, attrs => { - const update = processingFunctions.shadowrun.updatePrimaryArmor(attrs) - processingFunctions.setAttributes(update) - }) - processingFunctions.shadowrun.resetRepeatingFieldsPrimaries(`repeating_armor`, repRowID) + //Reset all the other primaries + shadowrunFunctions.resetRepeatingFieldsPrimaries(`repeating_${type}`, repRowID) } else { - const update = processingFunctions.shadowrun.resetPrimaryArmor() + const update = type === 'armor' ? shadowrunFunctions.resetPrimaryArmor() : shadowrunFunctions.resetPrimaryWeapon(type); processingFunctions.setAttributes(update) } } @@ -3778,7 +3859,7 @@ const updateRepeatingWeaponDicepool = trigger => { const updateRepeatingSkillDicepool = eventinfo => { const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) getAttrs([`${repRowID}_skill`], attrs => { - let skill = processingFunctions.shadowrun.convertSkillSelectToHiddenSkill(attrs[`${repRowID}_skill`]) + let skill = shadowrunFunctions.convertSkillSelectToHiddenSkill(attrs[`${repRowID}_skill`]) processingFunctions.setAttributes({ [`${skill}`]: eventinfo.newValue }) @@ -3792,9 +3873,8 @@ const updateRepeatingSkillLimit = eventinfo => { } else { const translationKey = processingFunctions.sliceAttr(eventinfo.newValue) const translation = getTranslationByKey(translationKey); - getAttrs([translationKey], attrs => { - const limitDisplay = `${translation} ${attrs[translationKey]}` - processingFunctions.setAttributes({[`${repRowID}_display_limit`]: limitDisplay}) + processingFunctions.setAttributes({ + [`${repRowID}_display_limit`]: translation }) } } @@ -3820,10 +3900,10 @@ const updateRepeatingSkillAttribute = eventinfo => { const updateRepeatingSkillRating = trigger => { const repRowID = processingFunctions.getReprowid(trigger) getAttrs([`${repRowID}_rating`, `${repRowID}_rating_modifier`], attrs => { - attrs = processingFunctions.shadowrun.attributeFactory(attrs) + attrs = shadowrunFunctions.attributeFactory(attrs) processingFunctions.setAttributes({ [`${repRowID}_dicepool`]: attrs.total, - [`${repRowID}_display_rating`]: processingFunctions.shadowrun.buildDisplay(attrs.base, attrs.bonus) + [`${repRowID}_display_rating`]: shadowrunFunctions.buildDisplay(attrs.base, attrs.bonus) }) }) } @@ -3831,15 +3911,15 @@ const updateRepeatingSkillRating = trigger => { const updateWounds = () => { getAttrs(sheetAttributes.woundCalculation, attrs => { attrs = processingFunctions.parseIntegers(attrs) - const sum = processingFunctions.shadowrun.calculateWounds(attrs) + const sum = shadowrunFunctions.calculateWounds(attrs) processingFunctions.setAttributes({wounds: sum}) }) } const updateConditionTracks= conditionTrack => { getAttrs(sheetAttributes[conditionTrack], attrs => { - attrs = processingFunctions.shadowrun.conditionFactory(attrs) - const conditionTotal = processingFunctions.shadowrun.calculateConditionTracks(attrs) + attrs = shadowrunFunctions.conditionFactory(attrs) + const conditionTotal = shadowrunFunctions.calculateConditionTracks(attrs) processingFunctions.setAttributes({[`${conditionTrack}_max`]: conditionTotal}, true) }) } @@ -3858,7 +3938,7 @@ const translations = () => { const updateShotsFired = trigger => { getAttrs([`shots_fired`], attrs => { attrs = processingFunctions.parseIntegers(attrs) - const shots = processingFunctions.shadowrun.shotsFired(attrs.shots_fired, trigger) + const shots = shadowrunFunctions.shotsFired(attrs.shots_fired, trigger) processingFunctions.setAttributes({shots_fired: shots}) }); } @@ -3882,7 +3962,7 @@ const updateTab = attr => processingFunctions.setAttributes({tab: attr}) const updateAttributes = (array, attribute) => { getAttrs(array, attrs => { - attrs = processingFunctions.shadowrun.attributeFactory(attrs) + attrs = shadowrunFunctions.attributeFactory(attrs) processingFunctions.setAttributes({ [attribute]: attrs.total, [`display_${attribute}`]: attrs.base === attrs.total ? attrs.base : `${attrs.base} (${attrs.total})` @@ -3892,16 +3972,16 @@ const updateAttributes = (array, attribute) => { const updateLimitTotal = attrs => { attrs.essence ? Math.ceil(attrs.essence) || 0 : false; - return processingFunctions.shadowrun.calculateLimitTotal(Object.values(attrs)) + return shadowrunFunctions.calculateLimitTotal(Object.values(attrs)) } const updateLimits = attributeLimit => { const array = sheetAttributes[attributeLimit].concat([`${attributeLimit}_modifier`, `${attributeLimit}_temp`, `${attributeLimit}_temp_flag`]) getAttrs(array, attrs => { - attrs = processingFunctions.shadowrun.attributeFactory(attrs) + attrs = shadowrunFunctions.attributeFactory(attrs) const bonus = attrs.bonus delete attrs.bonus - const base = processingFunctions.shadowrun.updateLimitTotal(attrs) + const base = shadowrunFunctions.updateLimitTotal(attrs) processingFunctions.setAttributes({ [attributeLimit]: processingFunctions.sumIntegers([base, bonus]) }) @@ -3912,15 +3992,15 @@ const updateMovement = () => { getAttrs(['agility', 'walk_modifier', 'run_modifier'], attrs => { attrs = processingFunctions.parseIntegers(attrs) processingFunctions.setAttributes({ - walk: processingFunctions.shadowrun.calculateWalkSpeed(attrs.agility, attrs.walk_modifier), - run: processingFunctions.shadowrun.calculateRunSpeed(attrs.agility, attrs.run_modifier) + walk: shadowrunFunctions.calculateWalkSpeed(attrs.agility, attrs.walk_modifier), + run: shadowrunFunctions.calculateRunSpeed(attrs.agility, attrs.run_modifier) }) }) } const updateDerivedAttribute = derivedAttribute => { getAttrs(sheetAttributes[derivedAttribute], attrs => { - attrs = processingFunctions.shadowrun.attributeFactory(attrs) + attrs = shadowrunFunctions.attributeFactory(attrs) processingFunctions.setAttributes({[derivedAttribute]: attrs.total}) }) } @@ -3928,9 +4008,9 @@ const updateDerivedAttribute = derivedAttribute => { const updateInitiativeDice = () => { getAttrs(["initiative_dice_modifier", "edge_toggle", "initiative_dice_temp", "initiative_dice_temp_flag"], values => { const edgeFlag = values.edge_toggle === "@{edge}" ? true : false; - values = processingFunctions.shadowrun.processTempFlags(values) + values = shadowrunFunctions.processTempFlags(values) values = processingFunctions.parseIntegers(values) - const bonus = processingFunctions.shadowrun.calculateBonuses(values) + const bonus = shadowrunFunctions.calculateBonuses(values) const total = Math.min(values.bonus+1,5) processingFunctions.setAttributes({ initiative_dice: edgeFlag ? 5 : total @@ -3938,6 +4018,10 @@ const updateInitiativeDice = () => { }) } + +//- +======== EVERYTHING BELOW THIS LINE LACKS UNIT TESTS =======+ +//- +======== NEEDS REFACTORING =======+ + const resetConditionTrack = eventinfo => { const attr = eventinfo.triggerName.split("_").pop(); processingFunctions.setAttributes({[`${attr}`] : 0}) @@ -3979,150 +4063,173 @@ const updateDefaultAttribute = newValue => { }) } + //Calculate Astral Initiatve +const updateAstralInitiative = () => { + getAttrs(["intuition", "astral_mod_modifier"], v => { + v = processingFunctions.parseIntegers(v); + const base = v.intuition * 2, bonus = v.astral_mod_modifier, total = base + bonus; + + setAttrs({ + ["astral_mod"]: total, + ["display_astral_mod"]: bonus === 0 ? base : `${base} (${total})` + }) + }) +} + +const updateAstralInitiativeDice = () => { + getAttrs(["astral_dice_modifier", "edge_toggle"], v => { + const edgeFlag = v.edge_toggle === "@{edge}" ? true : false; + const bonus = parseInt(v.astral_dice_modifier) || 0; + + setAttrs({ + astral_dice: edgeFlag ? 5 : Math.min(bonus+3,5) + }) + }) +} + - //Weapon displays set into an Array - // Builder function to display details properly - // Note that since undefined are falsey if there's no label or sign we can leave the parameters blank - function repeatingStringBuilder(v, keyBase) { - return function(key, label, sign) { - // fetch the attr from v checking if it has a value - const val = v[`${keyBase}${key}`]; - if (!val) return ''; + // Builder function to display details properly + // Note that since undefined are falsey if there's no label or sign we can leave the parameters blank + function repeatingStringBuilder(v, keyBase) { + return function(key, label, sign) { + // fetch the attr from v checking if it has a value + const val = v[`${keyBase}${key}`]; + if (!val) return ''; - // Apply the sign if needed - const disp = sign && val > 0 ? `+${val}` : val; + // Apply the sign if needed + const disp = sign && val > 0 ? `+${val}` : val; - // Apply label if needed - return label ? `${label} ${disp}` : disp; - } - } + // Apply label if needed + return label ? `${label} ${disp}` : disp; + } + } - on("change:repeating_weapon", () => { - const source = "repeating_weapon_weapon"; - getAttrs([`${source}_range`, `${source}_type`, `${source}_reach`, `${source}_acc`, `${source}_dv`, `${source}_ap`, `${source}_mode`, `${source}_rc`, `${source}_ammo`, `${source}_note`, `${source}_primary`], (v) => { - // Local builder putting the needed variables into scope for repeatingStringBuilder - const b = repeatingStringBuilder(v, `${source}_`); - // Determine fields to display and in their proper order and formatting - // Anonymous function is purely stylistic and adds more overhead than just a simple switch/case. Personally I find the function looks cleaner and hides any internal scope that might conflict with outside - const display = (() => { - // 0 for weapon_range is a ranged weapon. A 1 is a melee weapon. - switch(v.repeating_weapon_weapon_range) { - case '0': - // Not a fan of how ammo has to be handled. Could potentially be placed in the repeatingStringBuilder if used more often for other change:repeating functions as some sort of suffix parameter - const ammo = b('amm'); - return [ - b('type'), - b('acc', 'ACC'), - b('dv', 'DV'), - b('ap', 'AP', true), - b('mode'), - b('rc', 'RC'), - ammo ? `${ammo} (c)` : '', - b('note') - ]; - case '1': return [ - b('type'), - b('reach', 'Reach', true), - b('acc', 'ACC'), - b('dv', 'DV'), - b('ap', 'AP', true), - b('note') - ]; - default: return [ - b('type'), - b('acc', 'ACC'), - b('dv', 'DV'), - b('ap', 'AP', true), - b('note') - ]; - } - })() - // Remove all empty strings - .filter(s => s) - // Concat all the strings and add comma between - .join(', '); + on("change:repeating_weapon", () => { + const source = "repeating_weapon_weapon"; + getAttrs([`${source}_range`, `${source}_type`, `${source}_reach`, `${source}_acc`, `${source}_dv`, `${source}_ap`, `${source}_mode`, `${source}_rc`, `${source}_ammo`, `${source}_note`, `${source}_primary`], (v) => { + // Local builder putting the needed variables into scope for repeatingStringBuilder + const b = repeatingStringBuilder(v, `${source}_`); + // Determine fields to display and in their proper order and formatting + // Anonymous function is purely stylistic and adds more overhead than just a simple switch/case. Personally I find the function looks cleaner and hides any internal scope that might conflict with outside + const display = (() => { + // 0 for weapon_range is a ranged weapon. A 1 is a melee weapon. + switch(v.repeating_weapon_weapon_range) { + case '0': + // Not a fan of how ammo has to be handled. Could potentially be placed in the repeatingStringBuilder if used more often for other change:repeating functions as some sort of suffix parameter + const ammo = b('amm'); + return [ + b('type'), + b('acc', 'ACC'), + b('dv', 'DV'), + b('ap', 'AP', true), + b('mode'), + b('rc', 'RC'), + ammo ? `${ammo} (c)` : '', + b('note') + ]; + case '1': return [ + b('type'), + b('reach', 'Reach', true), + b('acc', 'ACC'), + b('dv', 'DV'), + b('ap', 'AP', true), + b('note') + ]; + default: return [ + b('type'), + b('acc', 'ACC'), + b('dv', 'DV'), + b('ap', 'AP', true), + b('note') + ]; + } + })() + // Remove all empty strings + .filter(s => s) + // Concat all the strings and add comma between + .join(', '); - let update = {}; - update[`${source}`] = `[${display}]`; + let update = {}; + update[`${source}`] = `[${display}]`; - // Finally wrap square brackets around the weapon display - setAttrs(update); - }); - }); + // Finally wrap square brackets around the weapon display + setAttrs(update); + }); + }); - //Spell displays set into an Array - on("change:repeating_NPCspell", () => { - getAttrs(["repeating_NPCspell_combat_type", "repeating_NPCspell_type", "repeating_NPCspell_range", "repeating_NPCspell_damage", "repeating_NPCspell_duration", "repeating_NPCspell_drain", "repeating_NPCspell_note"], (v) =>{ - const com = v.repeating_NPCspell_combat_type; - const typ = `Type ${v.repeating_NPCspell_type}, `; - const ran = `${v.repeating_NPCspell_range}, `; - const dam = `Damage ${v.repeating_NPCspell_damage}, `; - const dur = `Duration ${v.repeating_NPCspell_duration}, `; - const not = `, ${v.repeating_NPCspell_note}`; - const dra = v.repeating_NPCspell_drain; +//Spell displays set into an Array + on("change:repeating_NPCspell", () => { + getAttrs(["repeating_NPCspell_combat_type", "repeating_NPCspell_type", "repeating_NPCspell_range", "repeating_NPCspell_damage", "repeating_NPCspell_duration", "repeating_NPCspell_drain", "repeating_NPCspell_note"], (v) =>{ + const com = v.repeating_NPCspell_combat_type; + const typ = `Type ${v.repeating_NPCspell_type}, `; + const ran = `${v.repeating_NPCspell_range}, `; + const dam = `Damage ${v.repeating_NPCspell_damage}, `; + const dur = `Duration ${v.repeating_NPCspell_duration}, `; + const not = `, ${v.repeating_NPCspell_note}`; + const dra = v.repeating_NPCspell_drain; - const drain = (dra > 0) ? `F+${dra} ` : (dra < 0) ? `F${dra} ` :"F "; - const info = `[${typ}${ran}${dam}${dur}${drain}${not}]`; + const drain = (dra > 0) ? `F+${dra} ` : (dra < 0) ? `F${dra} ` :"F "; + const info = `[${typ}${ran}${dam}${dur}${drain}${not}]`; - display = (com === "Direct, Force ") ? ` (Direct) ${info}` : - (com === "Indirect, Force ?{Force|}, AP -") ? ` (Indirect) ${info}` : `${info}`; - setAttrs({repeating_NPCspell_spell: display}); - }); - }); + display = (com === "Direct, Force ") ? ` (Direct) ${info}` : + (com === "Indirect, Force ?{Force|}, AP -") ? ` (Indirect) ${info}` : `${info}`; + setAttrs({repeating_NPCspell_spell: display}); + }); + }); - //Complex Form displays set into an Array - on("change:repeating_form", () => { - getAttrs(["repeating_form_form_duration", "repeating_form_form_target", "repeating_form_form_fade", "repeating_form_form_note", ], (v) =>{ - const tar = `Target ${v.repeating_form_form_target}, `; - const dur = `Duration ${v.repeating_form_form_duration}, `; - const not = `, ${v.repeating_form_form_note}` || ''; - const fad = (v.repeating_form_form_fade > 0) ? `L+${v.repeating_form_form_fade}` : - (v.repeating_form_form_fade < 0) ? `L${v.repeating_form_form_fade}` : "L"; +//Complex Form displays set into an Array + on("change:repeating_form", () => { + getAttrs(["repeating_form_form_duration", "repeating_form_form_target", "repeating_form_form_fade", "repeating_form_form_note", ], (v) =>{ + const tar = `Target ${v.repeating_form_form_target}, `; + const dur = `Duration ${v.repeating_form_form_duration}, `; + const not = `, ${v.repeating_form_form_note}` || ''; + const fad = (v.repeating_form_form_fade > 0) ? `L+${v.repeating_form_form_fade}` : + (v.repeating_form_form_fade < 0) ? `L${v.repeating_form_form_fade}` : "L"; - setAttrs({ - repeating_form_form: ` [${tar}${dur}${fad}${not}]` - }); - }); - }); + setAttrs({ + repeating_form_form: ` [${tar}${dur}${fad}${not}]` + }); + }); + }); - //IC displays are set into an Array - on("change:repeating_IC", () => { - getAttrs(["attack", "data_processing", "repeating_IC_IC_limit", "repeating_IC_IC_attribute", "repeating_IC_IC_matrix", "repeating_IC_IC_note"], (v) =>{ - const att = parseInt(v.attack) || 0; - const data = parseInt(v.data_processing) || 0; - const attr = v.repeating_IC_IC_attribute; - const mat = v.repeating_IC_IC_matrix; - const not = v.repeating_IC_IC_note; +//IC displays are set into an Array + on("change:repeating_IC", () => { + getAttrs(["attack", "data_processing", "repeating_IC_IC_limit", "repeating_IC_IC_attribute", "repeating_IC_IC_matrix", "repeating_IC_IC_note"], (v) =>{ + const att = parseInt(v.attack) || 0; + const data = parseInt(v.data_processing) || 0; + const attr = v.repeating_IC_IC_attribute; + const mat = v.repeating_IC_IC_matrix; + const not = v.repeating_IC_IC_note; - setAttrs({ - repeating_IC_IC: (v.repeating_IC_IC_limit === "@{data_processing}") ? ` ([${data}] vs. ${attr} + ${mat}, ${not})` : `([${att}] vs. ${attr} + ${mat}, ${not})` - }); - }); - }); + setAttrs({ + repeating_IC_IC: (v.repeating_IC_IC_limit === "@{data_processing}") ? ` ([${data}] vs. ${attr} + ${mat}, ${not})` : `([${att}] vs. ${attr} + ${mat}, ${not})` + }); + }); + }); - ['acceleration', 'armor', 'body', 'data_processing', 'handling', 'pilot', 'sensor','speed'].forEach(attr => { - // Attach listener - on(`change:repeating_vehicle:${attr}_base change:repeating_vehicle:${attr}_modifier change:repeating_vehicle:${attr}_temp`, () => { - // Load attribute values - getAttrs([`repeating_vehicle_${attr}_base`, `repeating_vehicle_${attr}_modifier`, `repeating_vehicle_${attr}_temp`], (v) => { - // Do some math to calculate the total - const bas = parseInt(v[`repeating_vehicle_${attr}_base`]) || 0; - const mod = parseInt(v[`repeating_vehicle_${attr}_modifier`]) || 0; - const tem = parseInt(v[`repeating_vehicle_${attr}_temp`]) || 0; - const bon = mod + tem; - const stat = bas + bon; + ['acceleration', 'armor', 'body', 'data_processing', 'handling', 'handling_off', 'pilot', 'sensor','speed'].forEach(attr => { + // Attach listener + on(`change:repeating_vehicle:${attr}_base change:repeating_vehicle:${attr}_modifier change:repeating_vehicle:${attr}_temp`, () => { + // Load attribute values + getAttrs([`repeating_vehicle_${attr}_base`, `repeating_vehicle_${attr}_modifier`, `repeating_vehicle_${attr}_temp`], (v) => { + // Do some math to calculate the total + const bas = parseInt(v[`repeating_vehicle_${attr}_base`]) || 0; + const mod = parseInt(v[`repeating_vehicle_${attr}_modifier`]) || 0; + const tem = parseInt(v[`repeating_vehicle_${attr}_temp`]) || 0; + const bon = mod + tem; + const stat = bas + bon; - // Update the finalized total - setAttrs({ - [attr]: stat, - [`repeating_vehicle_display_${attr}`]: bon === 0 ? bas : `${bas} (${stat})` - }, {silent: true}); - }); - }); - }); + // Update the finalized total + setAttrs({ + [attr]: stat, + [`repeating_vehicle_display_${attr}`]: bon === 0 ? bas : `${bas} (${stat})` + }, {silent: true}); + }); + }); + }); const versioning = version => { console.log(`%c Shadowrun 5th Edition versioning, ${version}`, "color: darkblue; font-weight:bold"); @@ -4148,11 +4255,42 @@ const updateDefaultAttribute = newValue => { fourpointoneone() setAttrs({version: 4.11}, () => versioning(4.11)) break; + case version < 4.15: + fourpointonefive() + setAttrs({version: 4.15}, () => versioning(4.15)) + break; default: console.log(`%c Shadowrun 5th Edition is update to date. Version ${version}`, "color: green; font-weight:bold"); } }; +const fourpointonefive = () => { + updateDerivedAttribute('defense') + updateAttributes(sheetAttributes.initiative_mod, 'initiative_mod') + updateAstralInitiative() + + sheetAttributes.repeatingSkills.forEach(skill => { + getSectionIDs(skill, idarray => { + let attributes = [] + idarray.forEach(id => attributes.push(`repeating_${skill}_${id}_limit`)) + + getAttrs(attributes, values => { + let update = {} + for (let [key, value] of Object.entries(values)) { + const repRowID = processingFunctions.getReprowid(key) + if (value.includes('limit')) { + const translationKey = processingFunctions.sliceAttr(value) + update[`${repRowID}_display_limit`] = getTranslationByKey(translationKey) + } else { + update[`${repRowID}_display_limit`] = ' ' + } + } + processingFunctions.setAttributes(update) + }) + }) + }) +} + const fourpointoneone = () => { getSectionIDs('forms', idarray => { let attributes = []; @@ -4306,7 +4444,7 @@ const onepointthreefive = () => { sheetAttributes.weaponTypes.forEach(type => { on(`change:repeating_${type}:dicepool_modifier change:repeating_${type}:specialization`, eventinfo => updateRepeatingWeaponDicepool(eventinfo.triggerName)) - on(`change:repeating_${type}:primary`, eventinfo => updateRepeatingWeaponPrimary(eventinfo, type)) + on(`change:repeating_${type}:primary`, eventinfo => updateRepeatingPrimary(eventinfo, type)) }) sheetAttributes.rangeAttributes.forEach(attr => on(`change:repeating_range:${attr}`, eventinfo => updatePrimary(eventinfo))) @@ -4315,13 +4453,13 @@ const onepointthreefive = () => { sheetAttributes.armorAttributes.forEach(attr => on(`change:repeating_armor:${attr}`, eventinfo => updatePrimary(eventinfo))) - on("change:repeating_armor:primary", eventinfo => updateRepeatingArmorPrimary(eventinfo)) + on("change:repeating_armor:primary", eventinfo => updateRepeatingPrimary(eventinfo, 'armor')) on(`change:repeating_active:skill`, eventinfo => updateRepeatingSkillName(eventinfo)) on('clicked:cond_reset_physical clicked:cond_reset_stun', eventinfo => resetConditionTrack(eventinfo)) - on('change:edge_toggle', eventinfo => edgeToggle(eventinfo)) + on('change:edge_toggle', eventinfo => edgeToggle(eventinfo.newValue)) on('change:device_rating change:matrix_modifier', () => updateMatrixMaximum()) diff --git a/Shadowrun5thEdition/Shadowrun5thEdition.pug b/Shadowrun5thEdition/Shadowrun5thEdition.pug index 29faac12f8..25a4f52855 100644 --- a/Shadowrun5thEdition/Shadowrun5thEdition.pug +++ b/Shadowrun5thEdition/Shadowrun5thEdition.pug @@ -1,4 +1,4 @@ -input(name='attr_version' type='hidden' value='4.14') +input(name='attr_version' type='hidden' value='4.15') //- CHARACTER SHEET PAGE input.sheet_type(name='attr_sheet_type' type='hidden' value='pc') @@ -30,598 +30,42 @@ include src/pug/_variables.pug each val, key in {'wounds': '@{wounds}', 'modifiers':'?{Modifiers +/-|0}', 'edge':'@{edge}'} h2(data-i18n-title=key) #{key} label.switch(data-i18n-title=key title=key) - input.whisper-toggle(name='attr_'+key+'_toggle' type='checkbox' value=val) + input.whisper-toggle(name=`attr_${key}_toggle` type='checkbox' value=val) span.slider - button(name='d6' title='Roll D6s' type='roll' value!='@{gm_toggle} &{template:rolls}{{header=^{d6}}}{{base=^{d6}}}{{dice=[[(?{d6s|0}d6>5)]]}}') L + button(name='d6' title='Roll D6s' type='roll' value!='@{gm_toggle} &{template:rolls}{{header=^{d6}}}{{base=^{d6}}}{{dice=[[(?{d6s|0}d6>5@{explode_toggle})]]}}') L input(name='attr_tab' type='hidden' value='options') button.pictos(name='act_tab_options' title='@{tab}' type='action' ) y each val in ['core', 'arms', 'augs', 'gear', 'magic', 'matrix', 'social', 'vehicle'] button(data-i18n=val name='act_tab_'+val type='action' title='@{tab}') #{val} input.options_toggle(name='attr_tab' type='hidden' value='options') + //- STATIC TAB - .static.pc-col - include src/static.html - //- SKILLS - .pc-row - .header - - const skillTypes = {'Active': 'active', 'Knowledge': 'know', 'Language': 'lang'} - each val, key in skillTypes - - const attrName = key.toLowerCase(); - .header.htab - .triangle - input.tab-switch(name='attr_skill_toggle' title=key + ' skills' type='radio' value=attrName) - h1(data-i18n=val) #{val}.. - .right-tri - .triangle - h1(data-i18n='skills') Skills - .border-box.skill-box - .pc-box.medium-box - .rows.repeating-container - .row-long.headers - each val in ['Skill', 'RTG', 'Attribute', 'Limit'] - - const translationKey = val.toLowerCase(); - h2(data-i18n=translationKey) #{val} - input.tab-switch(name='attr_skill_toggle' type='hidden' value='active') - each val, key in {'active': ['active', 'Agility', 'Physical'],'knowledge':['know', 'Logic', 'Mental'], 'language': ['lang', 'Charisma', 'Social']} - div(class=`skills-${val[0]}`) - .rows.repeating-container - if key === 'active' - .row-long - input(name='attr_default_display' type='hidden' value='Agility') - +rollButton('default', '@{default_display}', '@{default_attribute}+-1') - span.text-align-center - - select.attribute-select(name='attr_default_attribute' title='Skill attribute') - +attributeSelect('Agility') - select.limit-select(name='attr_limit' title='Skill limit') - +limitSelect('Physical') - fieldset(class=`repeating_${key}`) - - const skillsRepeatingSection = `@{repeating_${key}`+'_${x}'; - - input(name='attr_display_rating' type='hidden') - input(name='attr_specialization' type='hidden' value='') - input(name='attr_display_limit' type='hidden' value=val[2]) - input(name='attr_display_attribute' type='hidden' value=val[1]) - input(name='attr_dicepool' type='hidden' value='0') - - if key === 'active' - input(name='attr_display_skill' type='hidden' value='') - - input.settings-flag(name='attr_flag' type='hidden' value='settings' title=`${skillsRepeatingSection}_flag}`) - .buttons - //- SKILL BUTTON - +skillButton(false, key) - //- SPECILIZATION BUTTON - +skillButton(true) - span.text-align-center(name='attr_display_rating' title=`${skillsRepeatingSection}_display_rating}`) - select.attribute-select(name='attr_attribute' title=`${skillsRepeatingSection}_attribute}`) - +attributeSelect(val[1]) - select.limit-select(name='attr_limit' value='physical_limit' title=`${skillsRepeatingSection}_limit}`) - +limitSelect(val[2]) - +repeatingSectionFlags() - .settings - if key === 'active' - select.skill-select(name='attr_skill' value='Close Combat Group' title=`${skillsRepeatingSection}_skill}`) - include src/html/skillselect.html - else - label(data-i18n-title='skill' title='skill') - input(name='attr_skill' placeholder=key type='text' title=`${skillsRepeatingSection}_skill}`) - label(data-i18n-title='rating' title='rating') - input(name='attr_rating' min='0' placeholder='0' type='number' title=`${skillsRepeatingSection}_rating}`) - label(data-i18n-title='ratingmodifier' title='Rating Modifier') - span(data-i18n='ratingmodifier') Rating Modifier - input(name='attr_rating_modifier' placeholder='0' type='number' title=`${skillsRepeatingSection}_rating_modifier}`) - label(data-i18n-title='specialization' title='specialization') - span(data-i18n='specialization') specialization - input(name='attr_specialization' placeholder='Specalizations' type='text' title=`${skillsRepeatingSection}_specialization}`) - label(data-i18n-title='notes' title='notes') - span(data-i18n='notes') Notes - textarea(name='attr_notes' value='' placeholder='Notes' title=`${skillsRepeatingSection}_notes}`) - + include src/pug/tabs/static.pug //- CORE TAB - .core.pc-col - include src/core.html - .quality-box - .header.right-header - .header.htab - input.tab-switch(input name='attr_quality_toggle' type='radio' value='quality' checked) - h1(data-i18n='qualities') Qualities - .right-tri - .header.htab - .triangle - input.tab-switch(input name='attr_quality_toggle' type='radio' value='martial') - h1(data-i18n='martialarts') Martial Arts - .right-tri - .border-box - .pc-box.medium-box - input.tab-switch(input name='attr_quality_toggle' type='hidden' value='quality') - .quality - .row-long.headers - each val in ['Quality', 'Type'] - h2(data-i18n=`${val.toLowerCase()}`) #{val} - .rows.repeating-container - fieldset(class='repeating_quality') - span.eclipse(name="attr_quality") - span.center(name="attr_type") - button.pictos(name="quality_chat" type="roll" value="@{gm_toggle} &{template:rolls}{{header=@{quality}}}{{desc=@{notes}}}") w - +repeatingSectionFlags() - .settings - input(name="attr_quality" placeholder="quality name" title="@{repeating_quality_${x}_quality}" type="text") - select(name="attr_type" title="@{repeating_quality_${x}_type}" value='p') - option(data-i18n="p" value="P" selected) P - option(data-i18n="n" value="N") N - +repeatingSectionNotes('quality') - .martial - .row-long.headers - each val in ['Technique', 'Style'] - h2(data-i18n=`${val.toLowerCase()}`) #{val} - .rows.repeating-container - fieldset(class='repeating_martial') - span.eclipse(name="attr_technique") - span.center(name="attr_style") - button.pictos(name="technique_chat" type="roll" value="@{gm_toggle} &{template:rolls}{{header=@{technique}}}{{desc=@{notes}}}") w - +repeatingSectionFlags() - .settings - input(name="attr_technique" placeholder="technique name" title="@{repeating_martial_${x}_technique}" type="text") - input(name="attr_style" placeholder="style name" title="@{repeating_martial_${x}_style}" type="text") - +repeatingSectionNotes('martial') - + include src/pug/tabs/core.pug //- ARMS TAB - .arms.pc-col - .pc-row.weapons - .header.right-header - h1(data-i18n='weapons') Weapons - .right-tri - .header.right-header - .header.htab - .triangle - input.tab-switch(name='attr_weapon_type_toggle' type='radio' value='range' checked) - h1(data-i18n='ranged') Ranged - .right-tri - .header.htab - .triangle - input.tab-switch(name='attr_weapon_type_toggle' type='radio' value='melee') - h1(data-i18n='melee') Melee - .right-tri - .border-box - .pc-box.medium-box - input.tab-switch(name='attr_weapon_type_toggle' type='hidden' value='range') - .rows.repeating-container.weapon-range - - const rangeRepeatingSection = '@{repeating_range_${x}'; - +h2Headers(pcRangeWeaponObject) - fieldset(class='repeating_range') - input(name='attr_dicepool' type='hidden' value='0') - input.flag-primary(name='attr_primary' type='hidden' value='') - +weaponRollButton(pcRangeWeaponButton) - each val in ['Dam', 'Acc', 'AP', 'Mode', 'RC', 'Ammo'] - - const attrName = val === 'Dam' ? 'damage' : val === 'RC' ? 'recoil' : val.toLowerCase(); - if val === 'Mode' - select(name='attr_mode' title='@{mode}' value='BF') - each val in weaponModes - option(data-i18n=val.toLowerCase() value=val) #{val} - else - span.center(name=`attr_${attrName}`) - +repeatingSectionFlags() - .settings - each val, key in pcRangeWeaponObject - - const attrName = key === 'Dam' ? 'damage' : key.toLowerCase(); - if key === 'Mode' - select(name='attr_mode' title='@{mode}' value='BF') - each val in weaponModes - option(data-i18n=val.toLowerCase() value=val) #{val} - else - label(data-i18n-title=key.toLowerCase() title=key.toLowerCase()) - input(name=`attr_${attrName}` placeholder=val['placeholder'] title=`${rangeRepeatingSection}_${attrName}}` type=val['type'] value='') - .row - h3(data-i18n='modeoptions') Mode Options - label(data-i18n-title='modeoptions' title='Mode Options') - input(name='attr_mode_options' placeholder='SA/BF/FA' type='text' title=`${rangeRepeatingSection}_mode_options}}`) - h3(data-i18n='range') range - label(data-i18n-title='range' title='Range') - input(name='attr_range' placeholder='25/150/350/550' type='text' title='') - h3(data-i18n='primary') primary - label(data-i18n-title='primary' title='Primary') - input(name='attr_primary' type='checkbox' title=`${rangeRepeatingSection}_primary}` value='primary') - - .row - h3(data-i18n='skill') skill - select(name=`attr_skill` title=`${rangeRepeatingSection}_skill}` value='@{firearms}') - optgroup(label='Combat Skills' ) Combat Skills - option(data-i18n='firearmsgroup' value='@{firearms}' selected) Firearms Group - option(data-i18n='automatics' value='@{automatics}') Automatics - option(data-i18n='archery' value='@{archery}') Archery - option(data-i18n='exoticrange' value='0') Exotic Range - option(data-i18n='heavyweapons' value='@{heavyweapons}') Heavy Weapons - option(data-i18n='longarms' value='@{longarms}') Longarms - option(data-i18n='pistols' value='@{pistols}') Pistols - option(data-i18n='throwingweapons' value='@{throwingweapons}') Throwing Weapons - optgroup(label='Vehicle Skills') Vehicle Skills - option(data-i18n='gunnery' value='@{gunnery}') Gunnery - h3(data-i18n='specialization') specialization - label(data-i18n-title='specialization' title='specialization') - input(name='attr_specialization' value='2' title=`${rangeRepeatingSection}_specialization}` type='checkbox') - h3(data-i18n='modifier') modifier - label(data-i18n-title='modifier' title='modifier') - input(name='attr_dicepool_modifier' title=`${rangeRepeatingSection}_dicepool_modifier}` type='number') - input(name=`attr_skill` type='hidden' value='') - .exotic-warning - i(data-i18n='exoticnote') Exotic weapons are not linked to a skill. Use Modifier input to set dicepool. - +repeatingSectionNotes('range') - .rows.repeating-container.weapon-melee - - const meleeRepeatingSection = '@{repeating_melee_${x}'; - +h2Headers(pcMeleeWeaponObject) - fieldset(class='repeating_melee') - input(name='attr_dicepool' type='hidden' value='0') - input.flag-primary(name='attr_primary' type='hidden' value='') - +weaponRollButton(pcMeleeWeaponButton) - each val in ['Dam', 'Acc', 'AP', 'Reach'] - - const attrName = val === 'Dam' ? 'damage' : val.toLowerCase(); - span.center(name=`attr_${attrName}`) - +repeatingSectionFlags() - .settings - each val, key in pcMeleeWeaponObject - - const attrName = key === 'Dam' ? 'damage' : key.toLowerCase(); - label(data-i18n-title=key.toLowerCase() title=key.toLowerCase()) - input(name=`attr_${attrName}` placeholder=val['placeholder'] title=`${meleeRepeatingSection}_${attrName}}` type=val['type'] value='') - h3(data-i18n='primary') primary - label(data-i18n-title='primary' title='Primary') - input(name='attr_primary' type='checkbox' title=`${meleeRepeatingSection}_primary}` value='primary') - .row - h3(data-i18n='skill') skill - select(name=`attr_skill` title=`${meleeRepeatingSection}_skill}` value='@{closecombat}') - optgroup(label='Combat Skills' ) Combat Skills - option(data-i18n='closecombatgroup' value='@{closecombat}' selected) Close Combat Group - option(data-i18n='blades' value='@{blades}') Blades - option(data-i18n='clubs' value='@{clubs}') Clubs - option(data-i18n='exoticmelee' value='0') Blades - option(data-i18n='unarmedcombat' value='@{unarmedcombat}') Unarmed Combat - optgroup(label='Vehicle Skills') Vehicle Skills - option(data-i18n='gunnery' value='@{gunnery}') Gunnery - h3(data-i18n='specialization') specialization - label(data-i18n-title='specialization' title='specialization') - input(name='attr_specialization' value='2' title=`${meleeRepeatingSection}_specialization}` type='checkbox') - h3(data-i18n='modifier') modifier - label(data-i18n-title='modifier' title='modifier') - input(name='attr_dicepool_modifier' title=`${meleeRepeatingSection}_dicepool_modifier}` type='number') - input(name=`attr_skill` type='hidden' value='') - .exotic-warning - i(data-i18n='exoticnote') Exotic weapons are not linked to a skill. Use Modifier input to set dicepool. - +repeatingSectionNotes('melee') - .pc-row.armor - .header.right-header - h1(data-i18n='armor') Armor - .right-tri - .border-box - .pc-box.medium-box - .rows.repeating-container - - const armorRepeatingSection = '@{repeating_armor_${x}'; - .row-long.headers - each val in ['Armor', 'Rating', 'Acid', 'Cold', 'Elec', 'Fire', 'Radi'] - h2(data-i18n=`${val.toLowerCase()}`) #{val} - fieldset(class='repeating_armor') - input.flag-primary(name='attr_primary' type='hidden' value='') - button(name=`roll_soak` type='roll' value!=noWoundsRollBegining+'{{header=^{soak}}}{{base=^{body} ♦ ^{armor}}}{{dice=[[((@{body}+@{rating}+@{dicepool_modifier})'+noWoundsRollEnding) - span(name='attr_name') - button(name=`roll_armor` type='roll' value!=noWoundsRollBegining+'{{header=@{name}}}{{base= ^{armor}}}{{dice=[[((@{rating})'+noWoundsRollEnding) - span.center(name='attr_rating') - each val in ['Acid', 'Cold', 'Electrical', 'Fire', 'Radiation'] - - const attrName = val.toLowerCase(); - button(name=`roll_${attrName}` type='roll' value!=noWoundsRollBegining+`{{header=^{${attrName}protection}}}{{base= ^{armor}}}{{dice=[[((@{body}+@{rating}+@{dicepool_modifier}+@{${attrName}_modifier})`+noWoundsRollEnding) - span.center(name=`attr_${attrName}_modifier`) - +repeatingSectionFlags() - .settings - each val, key in pcArmorObject - - const attrName = key === 'Name' || key === 'Rating' ? key.toLowerCase() : `${key.toLowerCase()}_modifier`; - label(data-i18n-title=key.toLowerCase() title=key.toLowerCase()) - input(name=`attr_${attrName}` placeholder=val['placeholder'] title=`@{${armorRepeatingSection}_${attrName}}` type=val['type'] value='') - .row - h3(data-i18n='primary') primary - label(data-i18n-title='primary' title='Primary') - input(name='attr_primary' type='checkbox' title=`@{${armorRepeatingSection}_primary}` value='primary') - h3(data-i18n='modifier') modifier - label(data-i18n-title='modifier' title='modifier') - input(name='attr_dicepool_modifier' placeholder='0' title=`@{${armorRepeatingSection}_dicepool_modifier}` type='number' value='0') - +repeatingSectionNotes('armor') + include src/pug/tabs/arms.pug //- AUGS TAB - .augs.pc-col - .pc-row - .header.right-header - h1(data-i18n='augmentations') Augmentations - .right-tri - .border-box - .pc-box.medium-box - .row-long.headers - each val in augementations - h2(data-i18n=`${val.toLowerCase()}`) #{val} - .rows.repeating-container - fieldset(class=`repeating_augementations`) - span(name=`attr_augmentation`) - span.center(name=`attr_rating`) - span.center(name=`attr_essence`) - +repeatingSectionFlags() - .settings - each val in augementations - - const attrName = val === 'Augmentations' ? 'augmentation' : val.toLowerCase(); - - const type = val === 'Augmentations' ? 'text' : 'number'; - - const placeholder = val === 'Augmentations' ? 'name' : '0'; - label(data-i18n-title=val title=val) - input(name=`attr_${attrName}` placeholder=placeholder title=`@{repeating_augementations_`+'${x}'+`_${attrName}}` type=type value='') - +repeatingSectionNotes('augementations') + include src/pug/tabs/augs.pug //- GEAR TAB - .gear.pc-col - .pc-row - .header.right-header - h1(data-i18n='gear') gear - .right-tri - .border-box - .pc-box.medium-box - .row-long.headers - each val in ['Item', 'Rating', 'Quantity'] - h2(data-i18n=`${val.toLowerCase()}`) #{val} - .rows.repeating-container - fieldset(class=`repeating_items`) - span(name=`attr_item`) - span.center(name=`attr_rating`) - span.center(name=`attr_quantity`) - +repeatingSectionFlags() - .settings - label(data-i18n-title='item' title='item') - input(name=`attr_item` placeholder='Jammer' title=`@{repeating_items_`+'${x}'+`_item}` type='text' value='') - label(data-i18n-title='rating' title='rating') - input(name=`attr_rating` placeholder='3' title=`@{repeating_items_`+'${x}'+`_rating}` type='text' value='') - label(data-i18n-title='quantity' title='quantity') - input(name=`attr_quantity` placeholder='x3' title=`@{repeating_items_`+'${x}'+`_quantity}` type='text' value='') - +repeatingSectionNotes('items') + include src/pug/tabs/gear.pug //- MAGIC TAB - .magic.pc-col - .pc-row.spell-box - .header.right-header - h1(data-i18n='magic') Magic - .right-tri - .header.right-header - .header.htab - .triangle - input.magic-toggle(name='attr_magic_toggle' title='@{magic_toggle}' type='radio' value='spells' checked) - h1(data-i18n='spells') Spells - .right-tri - .header.htab - .triangle - input.magic-toggle(name='attr_magic_toggle' title='@{magic_toggle}' type='radio' value='preps') - h1(data-i18n='prep') Prep... - .right-tri - .header.htab - .triangle - input.magic-toggle(name='attr_magic_toggle' title='@{magic_toggle}' type='radio' value='rituals') - h1(data-i18n='rituals') Rituals - .right-tri - .border-box - .pc-box.medium-box - +fadeDrainSection('drain') - input.magic-toggle(name='attr_magic_toggle' type='hidden' value='spells') - .row-long.headers - each val in ['spells', 'type', 'range', 'duration', 'drain'] - h2(data-i18n=val) #{val} - - .magic-spells.spellsForumlas - +pcSpells('spell') - - .magic-preps.spellsForumlas - +pcSpells('preps') - - .rows.repeating-container.prepared-preparations - h2(data-i18n='preperations') - .row-long.headers - each val in ['name', 'force', 'potency', 'trigger'] - h3(data-i18n=val) - fieldset(class='repeating_preperations') - +displayRollButton(prepButton, false) - each val in ['force', 'potency', 'trigger'] - span.center(name=`attr_${val}`) - +repeatingSectionFlags() - .settings - label(data-i18n-title='name' title='name') - input(name='attr_name' placeholder='Name' title='@{repeating_preperations_${x}_name}' type='text' value='') - label(data-i18n-title='force' title='force') - input(name='attr_force' placeholder='1' title='@{repeating_preperations_${x}_force}' type='number' value='') - label(data-i18n-title='potency' title='potency') - input(name='attr_potency' placeholder='1' title='@{repeating_preperations_${x}_potency}' type='number' value='') - select(name='attr_trigger' title='@{repeating_preperations_${x}_trigger}' value='Command') - optgroup(label='Trigger') Trigger - option(data-i18n='command' value='Command') command - option(data-i18n='contact' value='Contact' selected) contact - option(data-i18n='time' value='Time') time - option(data-i18n='special' value='Special') special - +repeatingSectionNotes('preperations') - - .magic-rituals - .rows.repeating-container - fieldset(class=`repeating_ritual`) - - const repeatingRitualSection = `@{repeating_${type}`+'_${x}'; - input(name='attr_dicepool' type='hidden' value='0') - +displayRollButton(pcRitualButton, true) - each val in ['type', 'range', 'duration', 'drain'] - span.center(name='attr_'+val) - +repeatingSectionFlags() - .settings - label(data-i18n-title='name' title='name') - input(name='attr_name' placeholder='Curse (MATERIAL LINK, SPELL)' title=`@{${repeatingRitualSection}_name}` type='text') - .rows - h3(data-i18n='skill') skill - select(name='attr_skill' title=`@{${repeatingRitualSection}_skill}`) - option(data-i18n='sorcerygroup' value='@{sorcery}') Sorcery Group - option(data-i18n='ritualspellcasting' value='@{ritualspellcasting}' selected) Ritual Spellcasting - h3(data-i18n='specialization') specialization - label(data-i18n-title='specialization' title='specialization') - input(name='attr_specialization' title=`@{${repeatingRitualSection}_specialization}` type='checkbox' value='2') - h3(data-i18n='modifier') modifier - label(data-i18n-title='modifier' title='modifier') - input(name='attr_dicepool_modifier' title=`@{${repeatingRitualSection}_dicepool_modifier}` type='number') - +repeatingSectionNotes('ritual') - - .pc-row.powers - .header.right-header - h1(data-i18n='adeptpowers') Adept Powers or Other Abilities - .right-tri - .border-box - .pc-box.medium-box - +fadeDrainSection('drain', true) - .row-long.headers - h2(data-i18n='name') Name - h2.center(data-i18n='rating') Rating - .rows.repeating-container.powers - fieldset(class=`repeating_powers`) - span(name='attr_name') - span.center(name='attr_rating') - +repeatingSectionFlags() - .settings - label(data-i18n-title='name' title='name') - input(name='attr_name' placeholder='name' title='@{repeating_powers_${x}_name}' type='text' value='') - label(data-i18n-title='rating' title='rating') - input(name='attr_rating' placeholder='rating' title='@{repeating_powers_${x}_rating}' type='number' value='') - +repeatingSectionNotes('powers') + include src/pug/tabs/magic.pug //- MATRIX TAB - .matrix.pc-col - .pc-row.matrix-box - .header.right-header - h1(data-i18n='cyberdeck') Cyberdeck - .right-tri - .border-box - .pc-box.medium-box - .cyberdeck - include src/html/matrix.html - .rows.repeating-container.programs - h2(data-i18n='programs') Programs - fieldset(class=`repeating_programs`) - input.toggle(name='attr_program_on' type='checkbox' checked) - span.pictos Q - span.eclipse(name='attr_program') - button.pictos(name="program_chat" type="roll" value="@{gm_toggle} &{template:rolls}{{header=@{program}}}{{desc=@{notes}}}") w - +repeatingSectionFlags() - .settings - label(data-i18n-title='programs' title='programs') - input(name='attr_program' placeholder='Program name' title='@{repeating_programs_${x}_program}' type='text' value='') - +repeatingSectionNotes('programs') - .pc-row - .header.right-header - h1(data-i18n='complex form') Complex Forms - .right-tri - .border-box - .pc-box.medium-box - +fadeDrainSection('fade') - .rows.repeating-container.complex-forms - - const formsrepeatingSection = `@{repeating_forms_` + "${x}"; - .row-long.headers - each val in complexFormAttributes - h2.text-capitalize(data-i18n=val) - fieldset(class=`repeating_forms`) - input(name='attr_dicepool' type='hidden' value='0') - +displayRollButton(pcComplexFormButton, true) - - const complexFormSpans = complexFormAttributes.shift(); - each val in complexFormSpans - span.center.eclipse(name=`attr_${val}`) - +repeatingSectionFlags() - .settings - label(data-i18n-title='name' title='name') - input(name='attr_name' placeholder='name' title=`${formsrepeatingSection}_name}` type='text' value='') - select(name=`attr_target` title=`${formsrepeatingSection}_target}` value='Device') - each val in formTargets - option.text-capitalize(data-i18n=val value=val) #{val} - select(name=`attr_duration` title=`${formsrepeatingSection}_duration}` value='Instant') - each val in formDurations - option.text-capitalize(data-i18n=val value=val) - label(data-i18n-title='fade' title='fade') - input(name='attr_fade' placeholder='-1' title=`${formsrepeatingSection}_fade}` type='number' value='') - .row - h3(data-i18n='skill') skill - select(name=`attr_skill` title=`${formsrepeatingSection}_skill}` value='@{software}') - option(data-i18n='electronicsgroup' value='@{electronics}') Electronics Group - option(data-i18n='software' value='@{software}' selected) Software - h3(data-i18n='specialization') - label(data-i18n-title='specialization' title='specialization') - input(name='attr_specialization' value='2' title=`${formsrepeatingSection}_specialization}` type='checkbox') - h3(data-i18n='modifier') modifier - label(data-i18n-title='modifier' title='modifier') - input(name='attr_dicepool_modifier' title=`${formsrepeatingSection}_dicepool_modifier}` type='number') - +repeatingSectionNotes('forms') + include src/pug/tabs/matrix.pug //- SOCIAL TAB - .social.pc-col - .pc-row - .header.right-header - h1(data-i18n="idslifestylecurrency") - .right-tri - .border-box.lifestyle - .pc-box.small-box - .row-long - h3(data-i18n="primarylifestyle") - input(name="attr_primary_lifestyle" placeholder="Middle /w GRID subscription" style="width: 77%" title="@{primary_lifestyle}" type="text") - .row-long - h3(data-i18n="nuyen") - input(type="text" name="attr_primary_nuyen" placeholder="$1,000 UCAS" style="width: 90%" title="@{primary_nuyen}") - .row-long - h3(data-i18n="licenses") - input(type="text" name="attr_primary_licenses" placeholder="Technomancer, Pistols..." style="width: 87%" title="@{primary_licenses}") - .row-long.headers - h2(data-i18n="fakeidsrelated") - .rows.repeating-container - fieldset(class='repeating_lifestyle') - span.eclipse(name="attr_name") - button.pictos(name="lifestyle_chat" type="roll" value="@{gm_toggle} &{template:rolls}{{header=@{name}}}{{desc=^{relatedlifestyle} @{lifestyle} , ^{nuyen} @{funds}, ^{licenses} @{licenses}}}") w - input.collapse-flag(name='attr_display_flag' type='checkbox') - span.pictos i - input.settings-flag(name='attr_flag' title='Settings toggle' type='checkbox' checked) - span.pictos x - .collapse - .rows - h3(data-i18n="relatedlifestyle") - span(name='attr_lifestyle') - .rows - h3(data-i18n="nuyen") - span(name='attr_funds') - .rows - h3(data-i18n="licenses") - span(name='attr_licenses') - .settings - h3(data-i18n="fakeid") - input.text-left(name="attr_name" placeholder="John Doe" title="@{repeating_lifestyle_${x}_name}" type='text') - h3(data-i18n="relatedlifestyle") - textarea(name="attr_lifestyle" placeholder="Middle" title="@{repeating_lifestyle_${x}_lifestyle}") - h3(data-i18n="funds") - textarea(name="attr_funds" placeholder="$1,000 UCAS" title="@{repeating_lifestyle_${x}_funds}") - h3(data-i18n="licenses") - textarea(name="attr_licenses" placeholder="Technomancer, Pistols" title="@{repeating_lifestyle_${x}_licenses}") - .pc-row - .header.right-header - h1(data-i18n="contacts") - .right-tri - .border-box.contacts - .pc-box.small-box - .row-long.headers - each val in ['name', 'loyalty', 'connection', 'favor'] - h2(data-i18n=`${val.toLowerCase()}`) #{val} - .rows.repeating-container - fieldset(class='repeating_contacts') - span.eclipse(name="attr_name") - span.center(name="attr_loyalty") - span.center(name="attr_connection") - span.center(name="attr_favors") - button.pictos(name="ontact_chat" type="roll" value="@{gm_toggle} &{template:rolls}{{header=@{name}}}{{desc=^{loyalty} @{loyalty} , ^{connection} @{connection}, ^{favor} @{favors}}}") w - +repeatingSectionFlags() - .settings - input(type="text" name="attr_name" placeholder="Old Crow" title="@{repeating_contacts_${x}_name}") - input(type="number" name="attr_loyalty" min="1" placeholder="3" title="@{repeating_contacts_${x}_name}") - input(type="number" name="attr_connection" min="1" placeholder="8" title="@{repeating_contacts_${x}_name}") - input(type="number" name="attr_favors" placeholder="+2" title="@{repeating_contacts_${x}_name}") - +repeatingSectionNotes('contacts') + include src/pug/tabs/social.pug //- VEHICLE TAB - include src/vehicle.html + include src/pug/tabs/vehicle.pug //- OPTIONS TAB include src/options.html @@ -638,7 +82,8 @@ include src/pug/_npc.pug img(alt='Emerald Productins, LLC' src=`${imageSource}/EProd_Emerald_Gloss.png`) //- ROLL TEMPLATES -include src/rolltemplates.html +//- include src/rolltemplates.html +include src/pug/_rolltemplates.pug //- HIDDEN include src/html/hidden.html @@ -651,19 +96,25 @@ script(type="text/worker") include src/js/Classes/PrimaryWeapon.js include src/js/Classes/PrimaryArmor.js + //- Generic helper functions used by shadowrunFunctions + //- Has unit tests include src/js/processingFunctions.js - include src/js/newScripts.js - - //Old functions working to become obsolete + //- Functions called by scripts to handle Shaodwrun specific rules + //- Has unit tests + include src/js/shadowrunFunctions.js + + //- Functions are called by the eventhandlers include src/js/scripts.js + //- Handle version updates include src/js/versioning.js + //- Listeners for changes include src/js/eventhandlers.js + //- Chummer Importer Functions include src/js/importer.js - include src/js/importerUI.js //- CHUMMER IMPORTER diff --git a/Shadowrun5thEdition/Shadowrun5thEdition.scss b/Shadowrun5thEdition/Shadowrun5thEdition.scss index 54e95a5339..419d40eee6 100644 --- a/Shadowrun5thEdition/Shadowrun5thEdition.scss +++ b/Shadowrun5thEdition/Shadowrun5thEdition.scss @@ -1,156 +1,37 @@ -//- Colors: - $gold: #FCD116; - $red: #610b0d; - $purple: #7a2593; - $lightgray: #9a9a9a; - $graytrans: rgba(28, 28, 28, 0.14902); - $grayshadow: #7c7c7c; - $blacker: #040404; - $ccc: #cccccc; - //- GRAY IN ROLL TEMPLATE - $blackish: #1c1c1c; - //-(primaryly on the NPC sheet) - $gray: #555; - $blacker: #040404; - $white: #fff; +@import 'src/scss/abstracts/variables'; +@import 'src/scss/abstracts/mixins'; +@import 'src/scss/base/base'; +@import 'src/scss/base/utilities'; -/********************************************************************************************************/ -/********************************* GLOBAL SETTINGS *******************************************************/ -/********************************************************************************************************/ -/* GLOBALS - ============================= */ - @import 'src/scss/_global'; +@import 'src/scss/components/switch'; +@import 'src/scss/components/collapse'; +@import 'src/scss/components/indicator'; -/* SWITCHES - ============================= */ - @import 'src/scss/_switch'; - -/* MIXIN - ============================= */ -@mixin repeatingInformation($endColumn, $longCollapseFlag) { - label[data-i18n-title='notes'], - h3[data-i18n='notes'], - div.sheet-collapse { - grid-column: 1 / #{$endColumn}; - } - - input.sheet-collapse-flag { - @if $longCollapseFlag { - grid-area: 1 / 1 / 1 / #{$endColumn - 1}; - position: absolute; - width: 100%; - } @else { - grid-area: 1 / #{$endColumn - 2} / 1 / #{$endColumn - 1}; - } - } - - input.sheet-collapse-flag + span.sheet-pictos { - grid-area: 1 / #{$endColumn - 2} / 1 / #{$endColumn - 1}; - } - - input.sheet-settings-flag, - input.sheet-settings-flag + span.sheet-pictos { - grid-area: 1 / #{$endColumn - 1} / 1 / #{$endColumn}; - } -} - -/***** TABS FOR SHEETS *****/ - .sheet-tabs { - button { - &[type='action'] { - background-color: #333; - border-radius : 2px; - border : 1px solid #000; - box-shadow : inset 0px 0px 3px 1px #7c7c7c; - color : #fff; - font-size : 1em; - font-weight : bolder; - text-transform : capitalize; - padding : 5px; - - &.sheet-pictos {text-transform: lowercase;} - } - - &[type='roll'] { - background: none; - border: none; - color : #fff; - font-family : 'dicefontd6'; - font-size : 2.5em; - vertical-align: top; - - &:hover { - text-shadow: 1px 1px 2px black, 0 0 25px red, 0 0 5px #e31715; - } - } - } - - h2 { - color: #fff; - font-size: 1em; - text-transform: capitalize; - text-align: right; - line-height: 2em; - margin-right: 5%; - } - } +@import 'src/scss/layout/tabs'; /***** TABS FOR SHEETS *****/ .sheet-settings-toggle, .sheet-settings-flag { - input { width: 3em;} + input { + width: 3em; + } input[type='checkbox'] + span { - background : transparent; - @extend .sheet-pictos; - font-size : 20px; - height : 20px; - text-align : center; - width : 20px; - } -} - - -/***** GENERIC STYLES *****/ -%parantheseNumbers { - vertical-align: middle; - - &:before { content: '('; } - &:after { content: ')'; } -} - -%toggleCheckbox, -input.sheet-toggle { - position: absolute; - opacity: 0; - z-index: 2; -} - -%toggleRelative { - position: relative; - opacity: 0; - z-index: 2; -} - -%settingsCheckboxes { - & + span { opacity: 0; } - &:checked + span { opacity: 1; } - - &:checked ~ .sheet-settings { - display: inline-grid; - margin-bottom: 2%; + background : transparent; + @extend .sheet-pictos; + font-size : 20px; + height : 20px; + text-align : center; + width : 20px; } } -%borderBottom { border-bottom: 1px solid #333; } - -.sheet-center { text-align: center; } - +/***** GENERIC STYLES *****/ select { &.sheet-attribute-select { option:nth-of-type(1n+5) { color: $red; } - option:nth-of-type(1n+9) { color: #7a2593; } + option:nth-of-type(1n+9) { color: $purple; } } &.sheet-limit-select { @@ -160,29 +41,12 @@ select { @import 'src/scss/_matrixdevice'; -.sheet-text-capitalize { - text-transform: capitalize; -} - -.sheet-text-left { - text-align: left; -} - /***** GRID *****/ %gridGap { grid-column-gap: 1%; grid-row-gap: 1%; } - -/******************************************************************************/ -/********************************* VARIABLES *********************************/ -/****************************************************************************/ -$tabs:'arms', 'augs', 'core', 'gear', 'options', 'social', 'magic', 'matrix', 'vehicle'; -$characterTypes: 'npc', 'pc'; -$specialCharacters: 'magic', 'resonance'; -$npcTypes: 'grunt', 'host', 'sprite', 'vehicle'; - /***************************************************************************************/ /************************** START OF THE PC SHEET *************************************/ /*************************************************************************************/ @@ -191,23 +55,28 @@ $npcTypes: 'grunt', 'host', 'sprite', 'vehicle'; background-image: url('https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/Shadowrun5thEdition/images/Blackbackground.jpg'); background-size : cover; border : 3px solid; - box-shadow : inset 0px 0px 3px 1px #7c7c7c; + box-shadow : inset 0px 0px 3px 1px $grayshadow; margin-left : -1%; padding-left : 0.5%; + button[name*='shots']:hover, button > h2:hover, button > span:hover, label > button[type='roll']:hover, .sheet-repeat-box button[type='roll']:hover, .sheet-con-track button[type='action']:hover, button[data-i18n='default']:hover { - color : #fff; - text-shadow: 1px 1px 2px black, 0 0 25px red, 0 0 5px $red; + color : $white; + text-shadow: $text-shadow; + } + + button:hover > span { + color: $white; } h1 { background-color: $red; - color : #fff; + color : $white; font-size : 1em; letter-spacing : 2px; line-height : 20px; @@ -245,12 +114,14 @@ $npcTypes: 'grunt', 'host', 'sprite', 'vehicle'; margin-top: 1%; grid-row-gap: 10%; - button[type='roll'] {grid-area: 2 / 5 / 2 / 5;} + button[type='roll'] { + grid-area: 2 / 5 / 2 / 5; + } /***** PLAYER DATA INPUTS *****/ h1 { background-color: transparent; - color: #fff; + color: $white; display: inline-block; font-size : 1em; grid-column: 6 / 8; @@ -283,12 +154,12 @@ $npcTypes: 'grunt', 'host', 'sprite', 'vehicle'; label { &[data-i18n-title='character name'] > input[type='text'], &[data-i18n-title='player name'] > input[type='text'] { - color : #fff; + color : $white; font-weight : bolder; background-color: transparent; border : none; box-shadow : none; - border-bottom : 2px solid #fff; + border-bottom : 2px solid $white; border-radius : 0px; height : 30px; width : 100%; @@ -311,9 +182,21 @@ $npcTypes: 'grunt', 'host', 'sprite', 'vehicle'; input[type='radio'] { @extend %toggleRelative; - & + span { font-family: 'pictos'; } + &:hover { + cursor: pointer; + } + + & + span { + font-family: 'pictos'; + } - &:checked + span { color: $red; } + &:checked + span { + color: $red; + } + + &:hover + span { + transform: $button-scale-small; + } } select { @@ -365,12 +248,12 @@ $npcTypes: 'grunt', 'host', 'sprite', 'vehicle'; div.repitem { display: inline-grid; padding: 1% 0.5%; - margin-bottom: 0px; @extend %gridGap; @extend %borderBottom; button[type='roll'] { - text-align: left; + text-align: left; + margin: 0px; } input { @@ -417,95 +300,9 @@ $npcTypes: 'grunt', 'host', 'sprite', 'vehicle'; input[type='number'] { text-align: center; } } - /***** STATIC *****/ - div.sheet-static { - margin-right: 0.5%; + @import 'src/scss/pages/tabs/static'; - div.sheet-border-box, - div.sheet-border-box .sheet-pc-box { - border-top-right-radius: 0px; - border-top-left-radius : 10px; - } - } - - - /***** CORE *****/ - div.sheet-core { - div.sheet-armor-buttons { - display : inline-block; - font-size : 1.5em; - line-height: 20px; - margin-left: 1%; - width : 35%; - - button { - &[type='roll'] { margin-right: -5px; } - &[name='roll_defense'] { - background-color: $gray; - color: $white; - } - } - - span { font-size : 1em; } - } - - /***** QUALITIES *****/ - div.sheet-quality-box { - div.sheet-htab input[type='radio'] { - margin-right: -100px; - width : 100px; - } - - div.sheet-header:nth-of-type(2) .sheet-htab input[type='radio'] { - margin-right: -150px; - width : 150px; - } - - div.sheet-quality { - $qualityGrid: 1fr 3em 1.5em 1em 1em; - - h2:nth-of-type(2) { text-align: center; } - - div.sheet-headers { - display: grid; - grid-template-columns: $qualityGrid; - @extend %gridGap; - } - - div.repitem { - grid-template-columns: $qualityGrid; - @include repeatingInformation(6, false); - - div.sheet-settings { - grid-column: 1 / 6; - grid-template-columns: $qualityGrid; - } - } - } - - div.sheet-martial { - $martialGrid: 2fr 1fr 1.5em 1em 1em; - - h2:nth-of-type(2) { text-align: center; } - - div.sheet-headers { - display: grid; - grid-template-columns: $martialGrid; - @extend %gridGap; - } - - div.repitem { - grid-template-columns: $martialGrid; - @include repeatingInformation(6, false); - - div.sheet-settings { - grid-column: 1 / 6; - grid-template-columns: $martialGrid; - } - } - } - } - } + @import 'src/scss/pages/tabs/core'; /***** SKILLS *****/ div.sheet-skill-box { @@ -536,16 +333,16 @@ $npcTypes: 'grunt', 'host', 'sprite', 'vehicle'; } } - div.sheet-buttons { - display: grid; - grid-template-columns: 1.5fr 1.5fr; - overflow: hidden; - } + div.sheet-buttons { + display: grid; + grid-template-columns: 1.5fr 1.5fr; + overflow: hidden; + } - input[name='attr_specialization'][value=''] ~ div.sheet-buttons { - grid-template-columns: 1fr; - } - + input[name='attr_specialization'][value=''] ~ div.sheet-buttons { + grid-template-columns: 1fr; + } + input[name='attr_skill'] { @extend %borderBottom; } input[name='attr_rating_modifier'] { width: 3.5em; } @@ -564,14 +361,14 @@ $npcTypes: 'grunt', 'host', 'sprite', 'vehicle'; h3:nth-of-type(1n+2) { text-align: center; } } - option.sheet-option-headers { - opacity: 0.2; - } + option.sheet-option-headers { + opacity: 0.2; + } - option.sheet-option-groups { - font-size: 1em; - font-style: italic; - } + option.sheet-option-groups { + font-size: 1em; + font-style: italic; + } div.repitem { grid-template-columns: $skillGrid; @@ -590,382 +387,34 @@ $npcTypes: 'grunt', 'host', 'sprite', 'vehicle'; } } - /*** ARMS ****/ - div.sheet-arms { - div.sheet-headers { - display: grid; - @extend %gridGap; + @import 'src/scss/pages/tabs/arms'; - h2:nth-of-type(1n+2) { text-align: center; } - } + @import 'src/scss/pages/tabs/augs'; - div.repitem { - h3 { color: $blacker; } + @import 'src/scss/pages/tabs/gear'; - input { - &:nth-of-type(1n+2) { text-align: center; } - &.sheet-flag-primary[value='primary'] + button { - background-color: $gold; - border-bottom: 2px solid $blacker; - } - } - } - - div.sheet-weapons { - $weaponsGrid: 25% 1.25fr 3em 2.5em 3em 1fr 1fr 1em 1em; - div.sheet-headers { grid-template-columns:$weaponsGrid; } - - div.repitem { - grid-template-columns: $weaponsGrid; - @include repeatingInformation(10, false); - - div.sheet-settings { - grid-column: 1 / 10; - grid-template-columns: $weaponsGrid; - } - } - - div.sheet-weapon-range, - div.sheet-weapon-melee { - width: 100%; - div.sheet-row { - grid-column: 1 / 9; - - label[data-i18n-title="modeoptions"], - label[data-i18n-title="range"]{ - width: 25%; - } - - input[type='number'] {width: 3em;} - - select {width: 30%;} - }; - - div.sheet-exotic-warning { display: none; } - - input[value='0'] + div.sheet-exotic-warning { display: block; } - } - } - - div.sheet-armor { - $armorGrid: 30% 3.5em 2.5em 2.5em 2.5em 2.5em 2.5em 1em 1em; - div.sheet-headers { grid-template-columns:$armorGrid; } - - div.repitem { - grid-template-columns: $armorGrid; - @include repeatingInformation(11, false); - - div.sheet-settings { - grid-column: 1 / 11; - grid-template-columns: $armorGrid; - - div.sheet-row { - grid-column: 1 / 11; - } - } - } - - } + //used in magic & complex forms + select.sheet-attribute-select { + margin-top: 1%; } - /*** AUGS ****/ - div.sheet-augs { - $augsGrid: 1fr 5em 5em 1em 1em;; + @import 'src/scss/pages/tabs/magic'; - div.sheet-headers { - display: grid; - grid-template-columns:$augsGrid; - } + @import 'src/scss/pages/tabs/matrix'; - div.repitem { - grid-template-columns: $augsGrid; - @include repeatingInformation(6, true); + @import 'src/scss/pages/tabs/social'; - input[name='attr_augementation'] { text-align: left; } + @import 'src/scss/pages/tabs/vehicle'; +} - div.sheet-settings { - grid-column: 1 / 6; - grid-template-columns: $augsGrid; - } - } - } - - /*** GEAR ****/ - div.sheet-gear { - $gearGrid: 1fr 5em 5em 1em 1em;; - - div.sheet-headers { - display: grid; - grid-template-columns:$gearGrid; - } - - div.repitem { - grid-template-columns: $gearGrid; - @include repeatingInformation(6, true); - - input[name='attr_item'] { text-align: left; } - - div.sheet-settings { - grid-column: 1 / 6; - grid-template-columns: $gearGrid; - } - } - } - - /***** MAGIC *****/ - div.sheet-magic { - $magicGrid: 30% 1.5fr 1.5fr 2fr 2em 1em 1em; - - input.sheet-magic-toggle[value='rituals'] ~ .sheet-headers h2:nth-of-type(1n+2) { - @extend %display-none; - } - - h2:nth-of-type(1n+2) { text-align: center; } - h3 { color: $blacker; } - - div.sheet-headers { - display: grid; - @extend %gridGap; - grid-template-columns:$magicGrid; - - h3:nth-of-type(1n+2) { text-align: center; } - } - - - /***** SPELLS & PREPARTATIONS *****/ - div.sheet-spellsForumlas { - div.repitem { - grid-template-columns: $magicGrid; - - @include repeatingInformation(8, false); - - input[name='attr_damage'], - input[name='attr_dicepool_modifier'] { - width: 3.5em; - } - - select[name='attr_category'] { grid-row: 2; } - - div.sheet-row { grid-column: 1 / 6; } - - div.sheet-settings { - grid-column: 1 / 8; - grid-template-columns: $magicGrid; - } - } - } - - /***** RITUALS *****/ - div.sheet-magic-rituals { - $ritualsGrid: 1fr 1em 1em; - - @include repeatingInformation(4, false); - - div.repitem { - grid-template-columns: $ritualsGrid; - - label { - &[data-i18n-title='name'] { grid-column: 1 / 4; } - } - - div.sheet-row { grid-column: 1 / 4; } - } - - div.sheet-settings { - grid-template-columns: $ritualsGrid; - grid-column: 1 / 4; - } - } - - div.sheet-magic-preps, div.sheet-magic-spells { - textarea { width: 93%; } - } - - /***** PREPARATIONS *****/ - div.sheet-magic-preps { - /* READIED PREPARATIONS */ - div.sheet-prepared-preparations { - $preparationsGrid: 40% 1fr 1fr 2fr 1em 1em; - - div.sheet-headers { - grid-template-columns:$preparationsGrid ; - } - - div.repitem { - grid-template-columns: $preparationsGrid ; - - @include repeatingInformation(7, false); - - div.sheet-settings { - grid-column: 1 / 7; - grid-template-columns: $preparationsGrid; - - select { grid-column: 4 / 7; } - - textarea { width: 100%; } - } - } - } - } - - - /***** ADEPT POWERS *****/ - div.sheet-powers { - $powersGrid: 1fr 3em 1em 1em;; - - div.sheet-headers { - grid-template-columns:$powersGrid; - } - - div.repitem { - grid-template-columns: $powersGrid; - @include repeatingInformation(5, true); - - div.sheet-settings { - grid-column: 1 / 5; - grid-template-columns: $powersGrid; - } - } - } - } - - /*** MATRIX ****/ - div.sheet-matrix { - h3 { color: $blacker; } - - div.sheet-programs { - $programGrid: 1em 1fr 1.5em 1em 1em; - - div.repitem { - grid-template-columns: $programGrid; - @extend %borderBottom; - @include repeatingInformation(6, false); - - input[name='attr_program_on'] { - grid-area: 1 / 1 / 1 / 1; - - &:checked + span { - color: $gold; - font-weight: bolder; - - & + span { - font-weight: bolder; - } - } - - & + span { - grid-area: 1 / 1 / 1 / 1; - } - } - } - - div.sheet-settings { - grid-column: 1 / 5; - - input[type='text'] { - grid-column: 1 / 4; - text-align: left; - } - - label { - grid-column: 1 / 4; - } - } - } - - div.sheet-complex-forms { - $complexFormsGrid: 30% 1fr 1fr 4em 1em 1em; - - div.sheet-headers { - display: grid; - @extend %gridGap; - grid-template-columns: $complexFormsGrid; - - h2:nth-of-type(1n+2) { text-align: center; } - } - - div.repitem { - grid-template-columns: $complexFormsGrid; - - @include repeatingInformation(7, false); - - div.sheet-row { - grid-column: 1 / 7; - } - - div.sheet-settings { - grid-column: 1 / 7; - grid-template-columns: $complexFormsGrid; - - } - } - } - } - - /*** SOCIAL ****/ - div.sheet-social { - - div.sheet-lifestyle { - $lifestyleGrid: 1fr 1.5em 1em 1em; - div.repitem { - grid-template-columns: $lifestyleGrid; - @include repeatingInformation(5, false); - - div.sheet-collapse { - padding-left: 2%; - - h3 { - margin-right: 1%; - } - } - - div.sheet-settings { - grid-column: 1 / 5; - padding: 1% 2% 5% 2%; - min-height: 300px; - - textarea { - height: 45px; - min-height: 45px; - } - } - } - } - - div.sheet-contacts { - $contactsGrid: 1fr 4em 5.5em 4em 1.5em 1em 1em; - - div.sheet-headers { - display: grid; - grid-template-columns: $contactsGrid; - width: 100%; - } - - div.repitem { - grid-template-columns: $contactsGrid; - @include repeatingInformation(8, false); - - - div.sheet-settings { - grid-column: 1 / 8; - } - } - } - } - - /*** Vehicle ****/ - div.sheet-vehicle { - - } - } @import 'src/scss/_pc'; /******************************************************************************************/ /**************************** START OF THE NPC SHEET *************************************/ /****************************************************************************************/ - @import 'src/scss/_npc'; + @import 'src/scss/pages/npc'; /**************************************************************************/ /***************** PC & NPC SHEET SHOW & HIDE SETTINGS *******************/ @@ -979,25 +428,7 @@ $npcTypes: 'grunt', 'host', 'sprite', 'vehicle'; /*****************************************************************************************/ /**************************************** FOOTER ****************************************/ /***************************************************************************************/ - /**** Footer ****/ - .sheet-footer { - border : none; - font-size : 0.55em; - line-height: 15px; - margin-top : 15px; - text-align : left; - width : 700px;} - - div.sheet-footer div { - display: inline-block; - width: 90%; - } - - div.sheet-footer img { - float: right; - vertical-align: top; - width: 5%; - } +@import 'src/scss/layout/footer'; /********************************************************************************************************/ /**************************************** REPEATING SECTIONS *******************************************/ @@ -1016,20 +447,7 @@ $npcTypes: 'grunt', 'host', 'sprite', 'vehicle'; @import 'src/scss/_importer'; -/********************************************************************************************************/ -/******************************* FireFox *******************************************/ -/******************************************************************************************************/ -input[type=number]::-webkit-outer-spin-button, -input[type=number]::-webkit-inner-spin-button { - -webkit-appearance: none; - margin: 0;} +@import 'src/scss/layout/firefox'; -input[type=number] { - -moz-appearance:textfield;} - - - /********************************************************************************************/ -/***************** French Adjustments ********************************/ -/*******************************************************************************************/ - @import 'src/scss/_lang-fr'; \ No newline at end of file +@import 'src/scss/layout/lang-fr'; \ No newline at end of file diff --git a/Shadowrun5thEdition/src/core.html b/Shadowrun5thEdition/src/html/core.html similarity index 100% rename from Shadowrun5thEdition/src/core.html rename to Shadowrun5thEdition/src/html/core.html diff --git a/Shadowrun5thEdition/src/html/skillselect.html b/Shadowrun5thEdition/src/html/skillselect.html index a8d150965e..bf2213a415 100644 --- a/Shadowrun5thEdition/src/html/skillselect.html +++ b/Shadowrun5thEdition/src/html/skillselect.html @@ -76,7 +76,7 @@ - + diff --git a/Shadowrun5thEdition/src/js/eventhandlers.js b/Shadowrun5thEdition/src/js/eventhandlers.js index cb80b13bbf..7a84bcb8cf 100644 --- a/Shadowrun5thEdition/src/js/eventhandlers.js +++ b/Shadowrun5thEdition/src/js/eventhandlers.js @@ -47,7 +47,7 @@ sheetAttributes.weaponTypes.forEach(type => { on(`change:repeating_${type}:dicepool_modifier change:repeating_${type}:specialization`, eventinfo => updateRepeatingWeaponDicepool(eventinfo.triggerName)) - on(`change:repeating_${type}:primary`, eventinfo => updateRepeatingWeaponPrimary(eventinfo, type)) + on(`change:repeating_${type}:primary`, eventinfo => updateRepeatingPrimary(eventinfo, type)) }) sheetAttributes.rangeAttributes.forEach(attr => on(`change:repeating_range:${attr}`, eventinfo => updatePrimary(eventinfo))) @@ -56,13 +56,13 @@ sheetAttributes.armorAttributes.forEach(attr => on(`change:repeating_armor:${attr}`, eventinfo => updatePrimary(eventinfo))) - on("change:repeating_armor:primary", eventinfo => updateRepeatingArmorPrimary(eventinfo)) + on("change:repeating_armor:primary", eventinfo => updateRepeatingPrimary(eventinfo, 'armor')) on(`change:repeating_active:skill`, eventinfo => updateRepeatingSkillName(eventinfo)) on('clicked:cond_reset_physical clicked:cond_reset_stun', eventinfo => resetConditionTrack(eventinfo)) - on('change:edge_toggle', eventinfo => edgeToggle(eventinfo)) + on('change:edge_toggle', eventinfo => edgeToggle(eventinfo.newValue)) on('change:device_rating change:matrix_modifier', () => updateMatrixMaximum()) diff --git a/Shadowrun5thEdition/src/js/newScripts.js b/Shadowrun5thEdition/src/js/newScripts.js deleted file mode 100644 index ac0bd9c2e8..0000000000 --- a/Shadowrun5thEdition/src/js/newScripts.js +++ /dev/null @@ -1,296 +0,0 @@ - //Edge toggle to include ! for exploding dice - const edgeToggle = eventinfo => { - processingFunctions.setAttributes({ - explode_toggle: eventinfo.newValue != 0 ? "!" : "" - }) - } - -const updateHostAttributes = newValue => { - newValue = processingFunctions.parseInteger(newValue) - processingFunctions.setAttributes({ - matrix_max: 8 + Math.ceil(newValue/2), - ic_attack: Math.min(newValue + newValue) - }) -} - -const updateSpriteConditionTrack = newValue => { - newValue = processingFunctions.parseInteger(newValue) - processingFunctions.setAttributes({ - matrix_max: 8 + Math.ceil(newValue/2) - }) -} - -//ALSO COVER COMPLEX FORMS -const updateSpellsDicepool = eventinfo => { - const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) - getAttrs([`${repRowID}_specialization`, `${repRowID}_dicepool_modifier`], attrs => { - attrs = processingFunctions.parseIntegers(attrs) - processingFunctions.setAttributes({ - [`${repRowID}_dicepool`]: processingFunctions.sumIntegers(Object.values(attrs)) - }) - }) -} - -const resetNpcCondition = () => setAttributes({physical: 0, stun: 0, matrix: 0}) - -const updatePrimary = eventinfo => { - const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) - getAttrs([`${repRowID}_primary`], attrs => { - if (attrs[`${repRowID}_primary`] === 'primary') { - let update = {} - - if (repRowID.includes('armor')) { - update = processingFunctions.shadowrun.updatePrimaryArmor({[eventinfo.triggerName]: eventinfo.newValue}) - } else { - update = processingFunctions.shadowrun.updatePrimaryWeapons({[eventinfo.triggerName]: eventinfo.newValue}) - } - - processingFunctions.setAttributes(update) - } - }) -} - -const updateRepeatingWeaponPrimary = (eventinfo, type) => { - const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) - if (eventinfo.newValue === 'primary') { - const constructedWeaponAttributes = processingFunctions.shadowrun.contructRepeatingWeaponAttributes(repRowID, type) - getAttrs(constructedWeaponAttributes, attrs => { - const update = processingFunctions.shadowrun.updatePrimaryWeapons(attrs) - processingFunctions.setAttributes(update) - }) - processingFunctions.shadowrun.resetRepeatingFieldsPrimaries(`repeating_${type}`, repRowID) - } else { - const update = processingFunctions.shadowrun.resetPrimaryWeapon(type) - processingFunctions.setAttributes(update) - } -} - -const updateRepeatingArmorPrimary = eventinfo => { - const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) - if (eventinfo.newValue === 'primary') { - const constructedArmorAttributes = processingFunctions.shadowrun.addRepRow(repRowID, sheetAttributes.armorAttributes) - getAttrs(constructedArmorAttributes, attrs => { - const update = processingFunctions.shadowrun.updatePrimaryArmor(attrs) - processingFunctions.setAttributes(update) - }) - processingFunctions.shadowrun.resetRepeatingFieldsPrimaries(`repeating_armor`, repRowID) - } else { - const update = processingFunctions.shadowrun.resetPrimaryArmor() - processingFunctions.setAttributes(update) - } -} - -const updateRepeatingWeaponDicepool = trigger => { - const repRowID = processingFunctions.getReprowid(trigger) - getAttrs([`${repRowID}_dicepool_modifier`, `${repRowID}_specialization`], attrs => { - attrs = processingFunctions.parseIntegers(attrs) - processingFunctions.setAttributes({ - [`${repRowID}_dicepool`]: processingFunctions.sumIntegers(Object.values(attrs)) - }) - }) -} - -const updateRepeatingSkillDicepool = eventinfo => { - const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) - getAttrs([`${repRowID}_skill`], attrs => { - let skill = processingFunctions.shadowrun.convertSkillSelectToHiddenSkill(attrs[`${repRowID}_skill`]) - processingFunctions.setAttributes({ - [`${skill}`]: eventinfo.newValue - }) - }) -} - -const updateRepeatingSkillLimit = eventinfo => { - const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) - if (eventinfo.newValue === "none") { - processingFunctions.setAttributes({[`${repRowID}_display_limit`]: ' '}) - } else { - const translationKey = processingFunctions.sliceAttr(eventinfo.newValue) - const translation = getTranslationByKey(translationKey); - getAttrs([translationKey], attrs => { - const limitDisplay = `${translation} ${attrs[translationKey]}` - processingFunctions.setAttributes({[`${repRowID}_display_limit`]: limitDisplay}) - }) - } -} - -const updateRepeatingSkillName = eventinfo => { - const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) - const translationKey = eventinfo.newValue.replace(/ /g, '').toLowerCase() - const translation = getTranslationByKey(translationKey); - processingFunctions.setAttributes({ - [`${repRowID}_display_skill`]: translation - }) -} - -const updateRepeatingSkillAttribute = eventinfo => { - const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) - const translationKey = processingFunctions.sliceAttr(eventinfo.newValue) - const translation = getTranslationByKey(translationKey); - processingFunctions.setAttributes({ - [`${repRowID}_display_attribute`]: translation - }) -} - -const updateRepeatingSkillRating = trigger => { - const repRowID = processingFunctions.getReprowid(trigger) - getAttrs([`${repRowID}_rating`, `${repRowID}_rating_modifier`], attrs => { - attrs = processingFunctions.shadowrun.attributeFactory(attrs) - processingFunctions.setAttributes({ - [`${repRowID}_dicepool`]: attrs.total, - [`${repRowID}_display_rating`]: processingFunctions.shadowrun.buildDisplay(attrs.base, attrs.bonus) - }) - }) -} - -const updateWounds = () => { - getAttrs(sheetAttributes.woundCalculation, attrs => { - attrs = processingFunctions.parseIntegers(attrs) - const sum = processingFunctions.shadowrun.calculateWounds(attrs) - processingFunctions.setAttributes({wounds: sum}) - }) -} - -const updateConditionTracks= conditionTrack => { - getAttrs(sheetAttributes[conditionTrack], attrs => { - attrs = processingFunctions.shadowrun.conditionFactory(attrs) - const conditionTotal = processingFunctions.shadowrun.calculateConditionTracks(attrs) - processingFunctions.setAttributes({[`${conditionTrack}_max`]: conditionTotal}, true) - }) -} - -const translations = () => { - const attributes = sheetAttributes.translationsAttributes - const translations = processingFunctions.getTranslations(attributes) - let attribute_roll = `?{${translations.attribute}` - delete translations.attribute - for (let [key, value] of Object.entries(translations)) { - attribute_roll += key !== 'none' ? `|${value},@{${key}}` : `|${value},0}` - } - processingFunctions.setAttributes({attribute_roll: attribute_roll}) -} - -const updateShotsFired = trigger => { - getAttrs([`shots_fired`], attrs => { - attrs = processingFunctions.parseIntegers(attrs) - const shots = processingFunctions.shadowrun.shotsFired(attrs.shots_fired, trigger) - processingFunctions.setAttributes({shots_fired: shots}) - }); -} - -const updateAmmoWithShotsFired = () => { - getAttrs([`primary_range_weapon_ammo`, `shots_fired`], attrs => { - attrs = processingFunctions.parseIntegers(attrs) - attrs.shots_fired = processingFunctions.convertIntegerNegative(attrs.shots_fired) - processingFunctions.setAttributes({primary_range_weapon_ammo: processingFunctions.sumIntegers(Object.values(attrs))}) - }); -} - -const updateAmmoWithMax = () => { - getAttrs([`primary_range_weapon_ammo_max`], attrs => { - attrs = processingFunctions.parseIntegers(attrs) - processingFunctions.setAttributes({primary_range_weapon_ammo: attrs.primary_range_weapon_ammo_max}) - }); -} - -const updateTab = attr => processingFunctions.setAttributes({tab: attr}) - -const updateAttributes = (array, attribute) => { - getAttrs(array, attrs => { - attrs = processingFunctions.shadowrun.attributeFactory(attrs) - processingFunctions.setAttributes({ - [attribute]: attrs.total, - [`display_${attribute}`]: attrs.base === attrs.total ? attrs.base : `${attrs.base} (${attrs.total})` - }) - }) -} - -const updateLimitTotal = attrs => { - attrs.essence ? Math.ceil(attrs.essence) || 0 : false; - return processingFunctions.shadowrun.calculateLimitTotal(Object.values(attrs)) -} - -const updateLimits = attributeLimit => { - const array = sheetAttributes[attributeLimit].concat([`${attributeLimit}_modifier`, `${attributeLimit}_temp`, `${attributeLimit}_temp_flag`]) - getAttrs(array, attrs => { - attrs = processingFunctions.shadowrun.attributeFactory(attrs) - const bonus = attrs.bonus - delete attrs.bonus - const base = processingFunctions.shadowrun.updateLimitTotal(attrs) - processingFunctions.setAttributes({ - [attributeLimit]: processingFunctions.sumIntegers([base, bonus]) - }) - }) -} - -const updateMovement = () => { - getAttrs(['agility', 'walk_modifier', 'run_modifier'], attrs => { - attrs = processingFunctions.parseIntegers(attrs) - processingFunctions.setAttributes({ - walk: processingFunctions.shadowrun.calculateWalkSpeed(attrs.agility, attrs.walk_modifier), - run: processingFunctions.shadowrun.calculateRunSpeed(attrs.agility, attrs.run_modifier) - }) - }) -} - -const updateDerivedAttribute = derivedAttribute => { - getAttrs(sheetAttributes[derivedAttribute], attrs => { - attrs = processingFunctions.shadowrun.attributeFactory(attrs) - processingFunctions.setAttributes({[derivedAttribute]: attrs.total}) - }) -} - -const updateInitiativeDice = () => { - getAttrs(["initiative_dice_modifier", "edge_toggle", "initiative_dice_temp", "initiative_dice_temp_flag"], values => { - const edgeFlag = values.edge_toggle === "@{edge}" ? true : false; - values = processingFunctions.shadowrun.processTempFlags(values) - values = processingFunctions.parseIntegers(values) - const bonus = processingFunctions.shadowrun.calculateBonuses(values) - const total = Math.min(values.bonus+1,5) - processingFunctions.setAttributes({ - initiative_dice: edgeFlag ? 5 : total - }) - }) -} - -const resetConditionTrack = eventinfo => { - const attr = eventinfo.triggerName.split("_").pop(); - processingFunctions.setAttributes({[`${attr}`] : 0}) -} - -//Calculate Matrix Initiatve. -const updateMatrixInitiative = () => { - getAttrs(["sheet_type", "data_processing", "pilot", "intuition", "matrix_mod_modifier", "host_rating", "level", "matrix_dice_modifier", "edge_toggle"], v => { - const sheetType = v.sheet_type; - const edgeFlag = v.edge_toggle === "@{edge}" ? true : false; - - v = processingFunctions.parseIntegers(v); - - let base = v.data_processing; - base += sheetType === "sprite" ? v.level : sheetType === "vehicle" ? v.pilot : sheetType === "host" ? v.host_rating : v.intuition; - - const total = base + v.matrix_mod_modifier; - - setAttrs({ - ["matrix_mod"]: total, - ["matrix_dice"]: sheetType === "grunt" && edgeFlag ? 5 : sheetType === "grunt" && !edgeFlag ? 4 + v.matrix_dice_modifier : 4, - ["display_matrix_mod"]: v.matrix_mod_modifier === 0 ? base : `${base} (${total})` - }) - }) -} - -//Setting the Default attribute name for default skill -const updateDefaultAttribute = newValue => { - getAttrs(["default_display"], value => { - const display = value.default_display - let update = {}; - - //This sets a hidden input with the Attribute name so the roll template can use it to indicate what attribute was rolled - const attribute = processingFunctions.sliceAttr(newValue) - const translation = getTranslationByKey(`${attribute}`) - if (translation != display) { - processingFunctions.setAttributes({default_display: translation}) - } - }) -} - diff --git a/Shadowrun5thEdition/src/js/processingFunctions.js b/Shadowrun5thEdition/src/js/processingFunctions.js index d97728664c..6ff8bce598 100644 --- a/Shadowrun5thEdition/src/js/processingFunctions.js +++ b/Shadowrun5thEdition/src/js/processingFunctions.js @@ -1,5 +1,4 @@ - const processingFunctions = { convertIntegerNegative: number => number > 0 ? -Math.abs(number) : number, convertIntegersNegatives: numbers => { @@ -34,150 +33,4 @@ const processingFunctions = { setAttributes: (update, silent) => silent && typeof update === 'object' ? setAttrs(update, {silent:true}) : typeof update === 'object' ? setAttrs(update) : console.error(`${update} is not an object`), sliceAttr: attribute => attribute.slice(2, -1), sumIntegers: numbers => numbers.reduce((a,b) => a + b, 0), - - shadowrun: { - addRepRow: (repRowID, attributeList) => { - let weaponAttributeWithRepeatingRow = [] - attributeList.forEach(weaponAttribute => weaponAttributeWithRepeatingRow.push(`${repRowID}_${weaponAttribute}`)) - return weaponAttributeWithRepeatingRow - }, - attributeFactory: attrs => { - attrs = processingFunctions.shadowrun.findFlagInKeys(attrs) ? processingFunctions.shadowrun.processTempFlags(attrs) : attrs - attrs = processingFunctions.parseIntegers(attrs) - attrs = processingFunctions.shadowrun.calculateBonuses(attrs) - attrs.total = processingFunctions.sumIntegers(Object.values(attrs)) - attrs.base = attrs.total - attrs.bonus - return attrs - }, - conditionFactory: attrs => { - attrs.attribute = processingFunctions.shadowrun.determineConditionAttribute(attrs) - attrs.base = processingFunctions.shadowrun.determineConditionBase(attrs.sheet_type, attrs.flag_drone) - attrs.modifier = attrs[processingFunctions.shadowrun.findModifierInKeys(attrs)] - Object.keys(attrs).forEach(key => !['attribute', 'base', 'modifier'].includes(key) ? delete attrs[key] : false) - attrs = processingFunctions.parseIntegers(attrs) - return attrs - }, - contructRepeatingWeaponAttributes: (repRowID, type) => { - const attributeList = processingFunctions.shadowrun.determineWeaponAttributesByType(type) - const constructedWeaponAttributes = processingFunctions.shadowrun.addRepRow(repRowID, attributeList) - return constructedWeaponAttributes - }, - buildDisplay: (base, bonus) => bonus === 0 ? base : `${base} (${base + bonus})`, - calculateBonuses: attrs => { - attrs.bonus = 0 - for (let [key, value] of Object.entries(attrs)) { - if (key.includes('modifier') || key.includes('temp')) { - attrs.bonus += value - delete attrs[key] - } - } - return attrs - }, - calculateConditionTracks: conditionInts => Math.ceil(conditionInts.attribute/2) + conditionInts.base + conditionInts.modifier, - calculateLimitTotal: attrs => Math.ceil((attrs[0] + attrs[1] + (attrs[2] * 2))/3), - calculateRunSpeed: (agility, modifier) => (agility * 4) + modifier, - calculateWalkSpeed:(agility, modifier) => (agility * 2) + modifier, - calculateWounds: attrs => { - const divisor = attrs.low_pain_tolerance === 2 ? attrs.low_pain_tolerance : 3; - const highPain = attrs.high_pain_tolerance >= 1 ? attrs.high_pain_tolerance : 0; - let sum = 0; - - ["stun", "physical"].forEach(attr => { - const damageCompensator = attrs[`damage_compensators_${attr}`] || 0 - let dividend = Math.max(attrs[`${attr}`] - (highPain + damageCompensator), 0) - sum -= Math.floor(dividend / divisor) || 0 - }) - return sum - }, - convertSkillSelectToHiddenSkill: skillName => { - let skill = skillName.toLowerCase() - skill = skill.includes('group') ? skill.slice(0, -6) : skill - skill = skill.includes(" ") ? skill.replace(/ /g,"") : skill - return skill - }, - determineConditionBase: (type, drone) => drone && drone === 'drone' ? 6 : type === 'vehicle' ? 12 : 8, - determineConditionAttribute: attrs => attrs.willpower ? attrs.willpower : attrs.body ? attrs.body : attrs.device_rating ? attrs.device_rating : 0, - determineWeaponAttributesByType: weaponType => weaponType === 'range' ? sheetAttributes.rangeAttributes : sheetAttributes.meleeAttributes, - findFlagInKeys: attrs => Object.keys(attrs).find(key => key.includes('_flag')), - findModifierInKeys: attrs => Object.keys(attrs).find(key => key.includes('_modifier')), - processTempFlags: attrs => { - try { - const tempFlag = processingFunctions.shadowrun.findFlagInKeys(attrs) - const attrName = tempFlag.split('_temp_flag')[0] - attrs[`${tempFlag}`] === 'on' ? false : delete attrs[`${attrName}_temp`]; - delete attrs[`${tempFlag}`]; - return attrs - } catch (error) { - console.error(error) - } - }, - resetRepeatingFieldsPrimaries: (repeatingSection, repRowID) => { - getSectionIDs(repeatingSection, ids => { - let attributesWithIDs = []; - let update = {}; - ids.forEach(id => attributesWithIDs.push(`${repeatingSection}_${id}_primary`)) - attributesWithIDs.forEach(attribute => !attribute.includes(repRowID) ? update[attribute] = 0 : false) - setAttrs(update); - }) - }, - shotsFired: (shots, trigger) => shots > 0 && trigger.includes('remove') ? shots -= 1 : trigger.includes('add') ? shots += 1 : shots, - updateLimitTotal: attrs => { - attrs.essence ? Math.ceil(attrs.essence) || 0 : false; - return processingFunctions.shadowrun.calculateLimitTotal(Object.values(attrs)) - }, - resetPrimaryArmor: () => { - const resetPrimary = new PrimaryArmor() - let update = {} - for (let [key, value] of Object.entries(resetPrimary)) { - update[key] = value - } - return update - }, - resetPrimaryWeapon: type => { - const resetPrimary = type === 'range' ? new PrimaryRangeWeapon(type) : new PrimaryMeleeWeapon(type) - let update = {} - for (let [key, value] of Object.entries(resetPrimary)) { - update[key] = value - } - return update - }, - updatePrimaryArmor: attrs => { - let update = {} - - for (let [key, value] of Object.entries(attrs)) { - const repRowID = processingFunctions.getReprowid(key) - if (key.includes('name')) { - update['armor_name'] = attrs[`${repRowID}_name`] - } else if (key.includes('rating')) { - update['armor_rating'] = value - } else if (key.includes('dicepool_modifier')) { - update['soak_modifier'] = value - } else { - const type = key.split('_')[3] - update[`${type}_modifier`] = value - } - } - - return update - }, - updatePrimaryWeapons: attrs => { - let update = {} - for (let [key, value] of Object.entries(attrs)) { - const type = processingFunctions.findRepeatingField(key) - const weaponAttribute = processingFunctions.getReprowAttribute(key) - const primaryAttributeName = key.includes('weapon') ? `primary_${type}_weapon` : `primary_${type}_weapon_${weaponAttribute}` - update[primaryAttributeName] = value - - if (key.includes('ammo')) { - update[`${primaryAttributeName}_max`] = value - } - } - return update - } - } } - - -//for Mocha Unit Texting -//module.exports = processingFunctions; - diff --git a/Shadowrun5thEdition/src/js/scripts.js b/Shadowrun5thEdition/src/js/scripts.js index 15de939748..8abab6eb72 100644 --- a/Shadowrun5thEdition/src/js/scripts.js +++ b/Shadowrun5thEdition/src/js/scripts.js @@ -1,143 +1,456 @@ +//Edge toggle to include ! for exploding dice +const edgeToggle = newValue => { + processingFunctions.setAttributes({ + explode_toggle: shadowrunFunctions.determineExplodingEdge(newValue) + }) +} + +const updateHostAttributes = newValue => { + newValue = processingFunctions.parseInteger(newValue) + processingFunctions.setAttributes({ + matrix_max: 8 + Math.ceil(newValue/2), + ic_attack: Math.min(newValue + newValue) + }) +} + +const updateSpriteConditionTrack = newValue => { + newValue = processingFunctions.parseInteger(newValue) + processingFunctions.setAttributes({ + matrix_max: 8 + Math.ceil(newValue/2) + }) +} + +//ALSO COVER COMPLEX FORMS +const updateSpellsDicepool = eventinfo => { + const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) + getAttrs([`${repRowID}_specialization`, `${repRowID}_dicepool_modifier`], attrs => { + attrs = processingFunctions.parseIntegers(attrs) + processingFunctions.setAttributes({ + [`${repRowID}_dicepool`]: processingFunctions.sumIntegers(Object.values(attrs)) + }) + }) +} + +const resetNpcCondition = () => setAttributes({physical: 0, stun: 0, matrix: 0}) + +const updatePrimary = eventinfo => { + const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) + getAttrs([`${repRowID}_primary`], attrs => { + if (attrs[`${repRowID}_primary`] === 'primary') { + let update = {} + + if (repRowID.includes('armor')) { + update = shadowrunFunctions.updatePrimaryArmor({[eventinfo.triggerName]: eventinfo.newValue}) + } else { + update = shadowrunFunctions.updatePrimaryWeapons({[eventinfo.triggerName]: eventinfo.newValue}) + } + processingFunctions.setAttributes(update) + } + }) +} + +const updateRepeatingPrimary = (eventinfo, type) => { + const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) + if (eventinfo.newValue === undefined) { + return false + } else if (eventinfo.newValue === 'primary') { + const constructedAttributes = type === 'armor' ? shadowrunFunctions.addRepRow(repRowID, sheetAttributes.armorAttributes) : shadowrunFunctions.contructRepeatingWeaponAttributes(repRowID, type); + + //get the attributes to update primary + getAttrs(constructedAttributes, attrs => { + const update = type === 'armor' ? shadowrunFunctions.updatePrimaryArmor(attrs) : shadowrunFunctions.updatePrimaryWeapons(attrs); + processingFunctions.setAttributes(update) + }) + + //Reset all the other primaries + shadowrunFunctions.resetRepeatingFieldsPrimaries(`repeating_${type}`, repRowID) + } else { + const update = type === 'armor' ? shadowrunFunctions.resetPrimaryArmor() : shadowrunFunctions.resetPrimaryWeapon(type); + processingFunctions.setAttributes(update) + } +} + +const updateRepeatingWeaponDicepool = trigger => { + const repRowID = processingFunctions.getReprowid(trigger) + getAttrs([`${repRowID}_dicepool_modifier`, `${repRowID}_specialization`], attrs => { + attrs = processingFunctions.parseIntegers(attrs) + processingFunctions.setAttributes({ + [`${repRowID}_dicepool`]: processingFunctions.sumIntegers(Object.values(attrs)) + }) + }) +} + +const updateRepeatingSkillDicepool = eventinfo => { + const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) + getAttrs([`${repRowID}_skill`], attrs => { + let skill = shadowrunFunctions.convertSkillSelectToHiddenSkill(attrs[`${repRowID}_skill`]) + processingFunctions.setAttributes({ + [`${skill}`]: eventinfo.newValue + }) + }) +} + +const updateRepeatingSkillLimit = eventinfo => { + const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) + if (eventinfo.newValue === "none") { + processingFunctions.setAttributes({[`${repRowID}_display_limit`]: ' '}) + } else { + const translationKey = processingFunctions.sliceAttr(eventinfo.newValue) + const translation = getTranslationByKey(translationKey); + processingFunctions.setAttributes({ + [`${repRowID}_display_limit`]: translation + }) + } +} + +const updateRepeatingSkillName = eventinfo => { + const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) + const translationKey = eventinfo.newValue.replace(/ /g, '').toLowerCase() + const translation = getTranslationByKey(translationKey); + processingFunctions.setAttributes({ + [`${repRowID}_display_skill`]: translation + }) +} + +const updateRepeatingSkillAttribute = eventinfo => { + const repRowID = processingFunctions.getReprowid(eventinfo.triggerName) + const translationKey = processingFunctions.sliceAttr(eventinfo.newValue) + const translation = getTranslationByKey(translationKey); + processingFunctions.setAttributes({ + [`${repRowID}_display_attribute`]: translation + }) +} + +const updateRepeatingSkillRating = trigger => { + const repRowID = processingFunctions.getReprowid(trigger) + getAttrs([`${repRowID}_rating`, `${repRowID}_rating_modifier`], attrs => { + attrs = shadowrunFunctions.attributeFactory(attrs) + processingFunctions.setAttributes({ + [`${repRowID}_dicepool`]: attrs.total, + [`${repRowID}_display_rating`]: shadowrunFunctions.buildDisplay(attrs.base, attrs.bonus) + }) + }) +} + +const updateWounds = () => { + getAttrs(sheetAttributes.woundCalculation, attrs => { + attrs = processingFunctions.parseIntegers(attrs) + const sum = shadowrunFunctions.calculateWounds(attrs) + processingFunctions.setAttributes({wounds: sum}) + }) +} + +const updateConditionTracks= conditionTrack => { + getAttrs(sheetAttributes[conditionTrack], attrs => { + attrs = shadowrunFunctions.conditionFactory(attrs) + const conditionTotal = shadowrunFunctions.calculateConditionTracks(attrs) + processingFunctions.setAttributes({[`${conditionTrack}_max`]: conditionTotal}, true) + }) +} + +const translations = () => { + const attributes = sheetAttributes.translationsAttributes + const translations = processingFunctions.getTranslations(attributes) + let attribute_roll = `?{${translations.attribute}` + delete translations.attribute + for (let [key, value] of Object.entries(translations)) { + attribute_roll += key !== 'none' ? `|${value},@{${key}}` : `|${value},0}` + } + processingFunctions.setAttributes({attribute_roll: attribute_roll}) +} + +const updateShotsFired = trigger => { + getAttrs([`shots_fired`], attrs => { + attrs = processingFunctions.parseIntegers(attrs) + const shots = shadowrunFunctions.shotsFired(attrs.shots_fired, trigger) + processingFunctions.setAttributes({shots_fired: shots}) + }); +} + +const updateAmmoWithShotsFired = () => { + getAttrs([`primary_range_weapon_ammo`, `shots_fired`], attrs => { + attrs = processingFunctions.parseIntegers(attrs) + attrs.shots_fired = processingFunctions.convertIntegerNegative(attrs.shots_fired) + processingFunctions.setAttributes({primary_range_weapon_ammo: processingFunctions.sumIntegers(Object.values(attrs))}) + }); +} + +const updateAmmoWithMax = () => { + getAttrs([`primary_range_weapon_ammo_max`], attrs => { + attrs = processingFunctions.parseIntegers(attrs) + processingFunctions.setAttributes({primary_range_weapon_ammo: attrs.primary_range_weapon_ammo_max}) + }); +} + +const updateTab = attr => processingFunctions.setAttributes({tab: attr}) + +const updateAttributes = (array, attribute) => { + getAttrs(array, attrs => { + attrs = shadowrunFunctions.attributeFactory(attrs) + processingFunctions.setAttributes({ + [attribute]: attrs.total, + [`display_${attribute}`]: attrs.base === attrs.total ? attrs.base : `${attrs.base} (${attrs.total})` + }) + }) +} + +const updateLimitTotal = attrs => { + attrs.essence ? Math.ceil(attrs.essence) || 0 : false; + return shadowrunFunctions.calculateLimitTotal(Object.values(attrs)) +} + +const updateLimits = attributeLimit => { + const array = sheetAttributes[attributeLimit].concat([`${attributeLimit}_modifier`, `${attributeLimit}_temp`, `${attributeLimit}_temp_flag`]) + getAttrs(array, attrs => { + attrs = shadowrunFunctions.attributeFactory(attrs) + const bonus = attrs.bonus + delete attrs.bonus + const base = shadowrunFunctions.updateLimitTotal(attrs) + processingFunctions.setAttributes({ + [attributeLimit]: processingFunctions.sumIntegers([base, bonus]) + }) + }) +} + +const updateMovement = () => { + getAttrs(['agility', 'walk_modifier', 'run_modifier'], attrs => { + attrs = processingFunctions.parseIntegers(attrs) + processingFunctions.setAttributes({ + walk: shadowrunFunctions.calculateWalkSpeed(attrs.agility, attrs.walk_modifier), + run: shadowrunFunctions.calculateRunSpeed(attrs.agility, attrs.run_modifier) + }) + }) +} + +const updateDerivedAttribute = derivedAttribute => { + getAttrs(sheetAttributes[derivedAttribute], attrs => { + attrs = shadowrunFunctions.attributeFactory(attrs) + processingFunctions.setAttributes({[derivedAttribute]: attrs.total}) + }) +} + +const updateInitiativeDice = () => { + getAttrs(["initiative_dice_modifier", "edge_toggle", "initiative_dice_temp", "initiative_dice_temp_flag"], values => { + const edgeFlag = values.edge_toggle === "@{edge}" ? true : false; + values = shadowrunFunctions.processTempFlags(values) + values = processingFunctions.parseIntegers(values) + const bonus = shadowrunFunctions.calculateBonuses(values) + const total = Math.min(values.bonus+1,5) + processingFunctions.setAttributes({ + initiative_dice: edgeFlag ? 5 : total + }) + }) +} + + +//- +======== EVERYTHING BELOW THIS LINE LACKS UNIT TESTS =======+ +//- +======== NEEDS REFACTORING =======+ + +const resetConditionTrack = eventinfo => { + const attr = eventinfo.triggerName.split("_").pop(); + processingFunctions.setAttributes({[`${attr}`] : 0}) +} + +//Calculate Matrix Initiatve. +const updateMatrixInitiative = () => { + getAttrs(["sheet_type", "data_processing", "pilot", "intuition", "matrix_mod_modifier", "host_rating", "level", "matrix_dice_modifier", "edge_toggle"], v => { + const sheetType = v.sheet_type; + const edgeFlag = v.edge_toggle === "@{edge}" ? true : false; + + v = processingFunctions.parseIntegers(v); + + let base = v.data_processing; + base += sheetType === "sprite" ? v.level : sheetType === "vehicle" ? v.pilot : sheetType === "host" ? v.host_rating : v.intuition; + + const total = base + v.matrix_mod_modifier; + + setAttrs({ + ["matrix_mod"]: total, + ["matrix_dice"]: sheetType === "grunt" && edgeFlag ? 5 : sheetType === "grunt" && !edgeFlag ? 4 + v.matrix_dice_modifier : 4, + ["display_matrix_mod"]: v.matrix_mod_modifier === 0 ? base : `${base} (${total})` + }) + }) +} + +//Setting the Default attribute name for default skill +const updateDefaultAttribute = newValue => { + getAttrs(["default_display"], value => { + const display = value.default_display + let update = {}; + + //This sets a hidden input with the Attribute name so the roll template can use it to indicate what attribute was rolled + const attribute = processingFunctions.sliceAttr(newValue) + const translation = getTranslationByKey(`${attribute}`) + if (translation != display) { + processingFunctions.setAttributes({default_display: translation}) + } + }) +} + + //Calculate Astral Initiatve +const updateAstralInitiative = () => { + getAttrs(["intuition", "astral_mod_modifier"], v => { + v = processingFunctions.parseIntegers(v); + const base = v.intuition * 2, bonus = v.astral_mod_modifier, total = base + bonus; + + setAttrs({ + ["astral_mod"]: total, + ["display_astral_mod"]: bonus === 0 ? base : `${base} (${total})` + }) + }) +} + +const updateAstralInitiativeDice = () => { + getAttrs(["astral_dice_modifier", "edge_toggle"], v => { + const edgeFlag = v.edge_toggle === "@{edge}" ? true : false; + const bonus = parseInt(v.astral_dice_modifier) || 0; + + setAttrs({ + astral_dice: edgeFlag ? 5 : Math.min(bonus+3,5) + }) + }) +} + //Weapon displays set into an Array - // Builder function to display details properly - // Note that since undefined are falsey if there's no label or sign we can leave the parameters blank - function repeatingStringBuilder(v, keyBase) { - return function(key, label, sign) { - // fetch the attr from v checking if it has a value - const val = v[`${keyBase}${key}`]; - if (!val) return ''; + // Builder function to display details properly + // Note that since undefined are falsey if there's no label or sign we can leave the parameters blank + function repeatingStringBuilder(v, keyBase) { + return function(key, label, sign) { + // fetch the attr from v checking if it has a value + const val = v[`${keyBase}${key}`]; + if (!val) return ''; - // Apply the sign if needed - const disp = sign && val > 0 ? `+${val}` : val; + // Apply the sign if needed + const disp = sign && val > 0 ? `+${val}` : val; - // Apply label if needed - return label ? `${label} ${disp}` : disp; - } - } + // Apply label if needed + return label ? `${label} ${disp}` : disp; + } + } - on("change:repeating_weapon", () => { - const source = "repeating_weapon_weapon"; - getAttrs([`${source}_range`, `${source}_type`, `${source}_reach`, `${source}_acc`, `${source}_dv`, `${source}_ap`, `${source}_mode`, `${source}_rc`, `${source}_ammo`, `${source}_note`, `${source}_primary`], (v) => { - // Local builder putting the needed variables into scope for repeatingStringBuilder - const b = repeatingStringBuilder(v, `${source}_`); - // Determine fields to display and in their proper order and formatting - // Anonymous function is purely stylistic and adds more overhead than just a simple switch/case. Personally I find the function looks cleaner and hides any internal scope that might conflict with outside - const display = (() => { - // 0 for weapon_range is a ranged weapon. A 1 is a melee weapon. - switch(v.repeating_weapon_weapon_range) { - case '0': - // Not a fan of how ammo has to be handled. Could potentially be placed in the repeatingStringBuilder if used more often for other change:repeating functions as some sort of suffix parameter - const ammo = b('amm'); - return [ - b('type'), - b('acc', 'ACC'), - b('dv', 'DV'), - b('ap', 'AP', true), - b('mode'), - b('rc', 'RC'), - ammo ? `${ammo} (c)` : '', - b('note') - ]; - case '1': return [ - b('type'), - b('reach', 'Reach', true), - b('acc', 'ACC'), - b('dv', 'DV'), - b('ap', 'AP', true), - b('note') - ]; - default: return [ - b('type'), - b('acc', 'ACC'), - b('dv', 'DV'), - b('ap', 'AP', true), - b('note') - ]; - } - })() - // Remove all empty strings - .filter(s => s) - // Concat all the strings and add comma between - .join(', '); + on("change:repeating_weapon", () => { + const source = "repeating_weapon_weapon"; + getAttrs([`${source}_range`, `${source}_type`, `${source}_reach`, `${source}_acc`, `${source}_dv`, `${source}_ap`, `${source}_mode`, `${source}_rc`, `${source}_ammo`, `${source}_note`, `${source}_primary`], (v) => { + // Local builder putting the needed variables into scope for repeatingStringBuilder + const b = repeatingStringBuilder(v, `${source}_`); + // Determine fields to display and in their proper order and formatting + // Anonymous function is purely stylistic and adds more overhead than just a simple switch/case. Personally I find the function looks cleaner and hides any internal scope that might conflict with outside + const display = (() => { + // 0 for weapon_range is a ranged weapon. A 1 is a melee weapon. + switch(v.repeating_weapon_weapon_range) { + case '0': + // Not a fan of how ammo has to be handled. Could potentially be placed in the repeatingStringBuilder if used more often for other change:repeating functions as some sort of suffix parameter + const ammo = b('amm'); + return [ + b('type'), + b('acc', 'ACC'), + b('dv', 'DV'), + b('ap', 'AP', true), + b('mode'), + b('rc', 'RC'), + ammo ? `${ammo} (c)` : '', + b('note') + ]; + case '1': return [ + b('type'), + b('reach', 'Reach', true), + b('acc', 'ACC'), + b('dv', 'DV'), + b('ap', 'AP', true), + b('note') + ]; + default: return [ + b('type'), + b('acc', 'ACC'), + b('dv', 'DV'), + b('ap', 'AP', true), + b('note') + ]; + } + })() + // Remove all empty strings + .filter(s => s) + // Concat all the strings and add comma between + .join(', '); - let update = {}; - update[`${source}`] = `[${display}]`; + let update = {}; + update[`${source}`] = `[${display}]`; - // Finally wrap square brackets around the weapon display - setAttrs(update); - }); - }); + // Finally wrap square brackets around the weapon display + setAttrs(update); + }); + }); - //Spell displays set into an Array - on("change:repeating_NPCspell", () => { - getAttrs(["repeating_NPCspell_combat_type", "repeating_NPCspell_type", "repeating_NPCspell_range", "repeating_NPCspell_damage", "repeating_NPCspell_duration", "repeating_NPCspell_drain", "repeating_NPCspell_note"], (v) =>{ - const com = v.repeating_NPCspell_combat_type; - const typ = `Type ${v.repeating_NPCspell_type}, `; - const ran = `${v.repeating_NPCspell_range}, `; - const dam = `Damage ${v.repeating_NPCspell_damage}, `; - const dur = `Duration ${v.repeating_NPCspell_duration}, `; - const not = `, ${v.repeating_NPCspell_note}`; - const dra = v.repeating_NPCspell_drain; +//Spell displays set into an Array + on("change:repeating_NPCspell", () => { + getAttrs(["repeating_NPCspell_combat_type", "repeating_NPCspell_type", "repeating_NPCspell_range", "repeating_NPCspell_damage", "repeating_NPCspell_duration", "repeating_NPCspell_drain", "repeating_NPCspell_note"], (v) =>{ + const com = v.repeating_NPCspell_combat_type; + const typ = `Type ${v.repeating_NPCspell_type}, `; + const ran = `${v.repeating_NPCspell_range}, `; + const dam = `Damage ${v.repeating_NPCspell_damage}, `; + const dur = `Duration ${v.repeating_NPCspell_duration}, `; + const not = `, ${v.repeating_NPCspell_note}`; + const dra = v.repeating_NPCspell_drain; - const drain = (dra > 0) ? `F+${dra} ` : (dra < 0) ? `F${dra} ` :"F "; - const info = `[${typ}${ran}${dam}${dur}${drain}${not}]`; + const drain = (dra > 0) ? `F+${dra} ` : (dra < 0) ? `F${dra} ` :"F "; + const info = `[${typ}${ran}${dam}${dur}${drain}${not}]`; - display = (com === "Direct, Force ") ? ` (Direct) ${info}` : - (com === "Indirect, Force ?{Force|}, AP -") ? ` (Indirect) ${info}` : `${info}`; - setAttrs({repeating_NPCspell_spell: display}); - }); - }); + display = (com === "Direct, Force ") ? ` (Direct) ${info}` : + (com === "Indirect, Force ?{Force|}, AP -") ? ` (Indirect) ${info}` : `${info}`; + setAttrs({repeating_NPCspell_spell: display}); + }); + }); - //Complex Form displays set into an Array - on("change:repeating_form", () => { - getAttrs(["repeating_form_form_duration", "repeating_form_form_target", "repeating_form_form_fade", "repeating_form_form_note", ], (v) =>{ - const tar = `Target ${v.repeating_form_form_target}, `; - const dur = `Duration ${v.repeating_form_form_duration}, `; - const not = `, ${v.repeating_form_form_note}` || ''; - const fad = (v.repeating_form_form_fade > 0) ? `L+${v.repeating_form_form_fade}` : - (v.repeating_form_form_fade < 0) ? `L${v.repeating_form_form_fade}` : "L"; +//Complex Form displays set into an Array + on("change:repeating_form", () => { + getAttrs(["repeating_form_form_duration", "repeating_form_form_target", "repeating_form_form_fade", "repeating_form_form_note", ], (v) =>{ + const tar = `Target ${v.repeating_form_form_target}, `; + const dur = `Duration ${v.repeating_form_form_duration}, `; + const not = `, ${v.repeating_form_form_note}` || ''; + const fad = (v.repeating_form_form_fade > 0) ? `L+${v.repeating_form_form_fade}` : + (v.repeating_form_form_fade < 0) ? `L${v.repeating_form_form_fade}` : "L"; - setAttrs({ - repeating_form_form: ` [${tar}${dur}${fad}${not}]` - }); - }); - }); + setAttrs({ + repeating_form_form: ` [${tar}${dur}${fad}${not}]` + }); + }); + }); - //IC displays are set into an Array - on("change:repeating_IC", () => { - getAttrs(["attack", "data_processing", "repeating_IC_IC_limit", "repeating_IC_IC_attribute", "repeating_IC_IC_matrix", "repeating_IC_IC_note"], (v) =>{ - const att = parseInt(v.attack) || 0; - const data = parseInt(v.data_processing) || 0; - const attr = v.repeating_IC_IC_attribute; - const mat = v.repeating_IC_IC_matrix; - const not = v.repeating_IC_IC_note; +//IC displays are set into an Array + on("change:repeating_IC", () => { + getAttrs(["attack", "data_processing", "repeating_IC_IC_limit", "repeating_IC_IC_attribute", "repeating_IC_IC_matrix", "repeating_IC_IC_note"], (v) =>{ + const att = parseInt(v.attack) || 0; + const data = parseInt(v.data_processing) || 0; + const attr = v.repeating_IC_IC_attribute; + const mat = v.repeating_IC_IC_matrix; + const not = v.repeating_IC_IC_note; - setAttrs({ - repeating_IC_IC: (v.repeating_IC_IC_limit === "@{data_processing}") ? ` ([${data}] vs. ${attr} + ${mat}, ${not})` : `([${att}] vs. ${attr} + ${mat}, ${not})` - }); - }); - }); + setAttrs({ + repeating_IC_IC: (v.repeating_IC_IC_limit === "@{data_processing}") ? ` ([${data}] vs. ${attr} + ${mat}, ${not})` : `([${att}] vs. ${attr} + ${mat}, ${not})` + }); + }); + }); - ['acceleration', 'armor', 'body', 'data_processing', 'handling', 'pilot', 'sensor','speed'].forEach(attr => { - // Attach listener - on(`change:repeating_vehicle:${attr}_base change:repeating_vehicle:${attr}_modifier change:repeating_vehicle:${attr}_temp`, () => { - // Load attribute values - getAttrs([`repeating_vehicle_${attr}_base`, `repeating_vehicle_${attr}_modifier`, `repeating_vehicle_${attr}_temp`], (v) => { - // Do some math to calculate the total - const bas = parseInt(v[`repeating_vehicle_${attr}_base`]) || 0; - const mod = parseInt(v[`repeating_vehicle_${attr}_modifier`]) || 0; - const tem = parseInt(v[`repeating_vehicle_${attr}_temp`]) || 0; - const bon = mod + tem; - const stat = bas + bon; + ['acceleration', 'armor', 'body', 'data_processing', 'handling', 'handling_off', 'pilot', 'sensor','speed'].forEach(attr => { + // Attach listener + on(`change:repeating_vehicle:${attr}_base change:repeating_vehicle:${attr}_modifier change:repeating_vehicle:${attr}_temp`, () => { + // Load attribute values + getAttrs([`repeating_vehicle_${attr}_base`, `repeating_vehicle_${attr}_modifier`, `repeating_vehicle_${attr}_temp`], (v) => { + // Do some math to calculate the total + const bas = parseInt(v[`repeating_vehicle_${attr}_base`]) || 0; + const mod = parseInt(v[`repeating_vehicle_${attr}_modifier`]) || 0; + const tem = parseInt(v[`repeating_vehicle_${attr}_temp`]) || 0; + const bon = mod + tem; + const stat = bas + bon; - // Update the finalized total - setAttrs({ - [attr]: stat, - [`repeating_vehicle_display_${attr}`]: bon === 0 ? bas : `${bas} (${stat})` - }, {silent: true}); - }); - }); - }); + // Update the finalized total + setAttrs({ + [attr]: stat, + [`repeating_vehicle_display_${attr}`]: bon === 0 ? bas : `${bas} (${stat})` + }, {silent: true}); + }); + }); + }); diff --git a/Shadowrun5thEdition/src/js/shadowrunFunctions.js b/Shadowrun5thEdition/src/js/shadowrunFunctions.js new file mode 100644 index 0000000000..2237c2a524 --- /dev/null +++ b/Shadowrun5thEdition/src/js/shadowrunFunctions.js @@ -0,0 +1,163 @@ +//for Mocha Unit Testing +//-const processingFunctions = require('../js/processingFunctions'); + +const shadowrunFunctions = { + addRepRow: (repRowID, attributeList) => { + let weaponAttributeWithRepeatingRow = [] + attributeList.forEach(weaponAttribute => weaponAttributeWithRepeatingRow.push(`${repRowID}_${weaponAttribute}`)) + return weaponAttributeWithRepeatingRow + }, + + attributeFactory: attrs => { + attrs = shadowrunFunctions.findFlagInKeys(attrs) ? shadowrunFunctions.processTempFlags(attrs) : attrs + attrs = processingFunctions.parseIntegers(attrs) + attrs = shadowrunFunctions.calculateBonuses(attrs) + attrs.total = processingFunctions.sumIntegers(Object.values(attrs)) + attrs.base = attrs.total - attrs.bonus + return attrs + }, + conditionFactory: attrs => { + attrs.attribute = shadowrunFunctions.determineConditionAttribute(attrs) + attrs.base = shadowrunFunctions.determineConditionBase(attrs.sheet_type, attrs.flag_drone) + attrs.modifier = attrs[shadowrunFunctions.findModifierInKeys(attrs)] + Object.keys(attrs).forEach(key => !['attribute', 'base', 'modifier'].includes(key) ? delete attrs[key] : false) + attrs = processingFunctions.parseIntegers(attrs) + return attrs + }, + + contructRepeatingWeaponAttributes: (repRowID, type) => { + const attributeList = shadowrunFunctions.determineWeaponAttributesByType(type) + const constructedWeaponAttributes = shadowrunFunctions.addRepRow(repRowID, attributeList) + return constructedWeaponAttributes + }, + + buildDisplay: (base, bonus) => bonus === 0 ? base : `${base} (${base + bonus})`, + + calculateBonuses: attrs => { + attrs.bonus = 0 + for (let [key, value] of Object.entries(attrs)) { + if (key.includes('modifier') || key.includes('temp')) { + attrs.bonus += value + delete attrs[key] + } + } + return attrs + }, + calculateConditionTracks: conditionInts => Math.ceil(conditionInts.attribute/2) + conditionInts.base + conditionInts.modifier, + calculateLimitTotal: attrs => Math.ceil((attrs[0] + attrs[1] + (attrs[2] * 2))/3), + calculateRunSpeed: (agility, modifier) => (agility * 4) + modifier, + calculateWalkSpeed:(agility, modifier) => (agility * 2) + modifier, + calculateWounds: attrs => { + const divisor = attrs.low_pain_tolerance === 2 ? attrs.low_pain_tolerance : 3; + const highPain = attrs.high_pain_tolerance >= 1 ? attrs.high_pain_tolerance : 0; + let sum = 0; + + ["stun", "physical"].forEach(attr => { + const damageCompensator = attrs[`damage_compensators_${attr}`] || 0 + let dividend = Math.max(attrs[`${attr}`] - (highPain + damageCompensator), 0) + sum -= Math.floor(dividend / divisor) || 0 + }) + return sum + }, + + convertSkillSelectToHiddenSkill: skillName => { + let skill = skillName.toLowerCase() + skill = skill.includes('group') ? skill.slice(0, -6) : skill + skill = skill.includes(" ") ? skill.replace(/ /g,"") : skill + return skill + }, + + determineConditionBase: (type, drone) => drone && drone === 'drone' ? 6 : type === 'vehicle' ? 12 : 8, + determineConditionAttribute: attrs => attrs.willpower ? attrs.willpower : attrs.body ? attrs.body : attrs.device_rating ? attrs.device_rating : 0, + determineExplodingEdge: newValue => newValue === `@{edge}` ? "!" : "", + determineWeaponAttributesByType: weaponType => weaponType === 'range' ? sheetAttributes.rangeAttributes : sheetAttributes.meleeAttributes, + + findFlagInKeys: attrs => Object.keys(attrs).find(key => key.includes('_flag')), + findModifierInKeys: attrs => Object.keys(attrs).find(key => key.includes('_modifier')), + + processTempFlags: attrs => { + try { + const tempFlag = shadowrunFunctions.findFlagInKeys(attrs) + const attrName = tempFlag.split('_temp_flag')[0] + attrs[`${tempFlag}`] === 'on' ? false : delete attrs[`${attrName}_temp`]; + delete attrs[`${tempFlag}`]; + return attrs + } catch (error) { + console.error(error) + } + }, + + resetRepeatingFieldsPrimaries: (repeatingSection, repRowID) => { + getSectionIDs(repeatingSection, ids => { + let attributesWithIDs = []; + let update = {}; + ids.forEach(id => attributesWithIDs.push(`${repeatingSection}_${id}_primary`)) + attributesWithIDs.forEach(attribute => !attribute.includes(repRowID) ? update[attribute] = 0 : false) + setAttrs(update); + }) + }, + + shotsFired: (shots, trigger) => shots > 0 && trigger.includes('remove') ? shots -= 1 : trigger.includes('add') ? shots += 1 : shots, + + //Reset will remove data in Primary entries on Core tab + resetPrimaryArmor: () => { + const resetPrimary = new PrimaryArmor() + let update = {} + for (let [key, value] of Object.entries(resetPrimary)) { + update[key] = value + } + return update + }, + resetPrimaryWeapon: type => { + const resetPrimary = type === 'range' ? new PrimaryRangeWeapon(type) : new PrimaryMeleeWeapon(type) + let update = {} + for (let [key, value] of Object.entries(resetPrimary)) { + update[key] = value + } + return update + }, + + updateLimitTotal: attrs => { + attrs.essence ? Math.ceil(attrs.essence) || 0 : false; + return shadowrunFunctions.calculateLimitTotal(Object.values(attrs)) + }, + + //Update Functions take data from one place and applies it to other attributes + updatePrimaryArmor: attrs => { + let update = {} + + for (let [key, value] of Object.entries(attrs)) { + const repRowID = processingFunctions.getReprowid(key) + if (key.includes('name')) { + update['armor_name'] = attrs[`${repRowID}_name`] + } else if (key.includes('rating')) { + update['armor_rating'] = value + } else if (key.includes('dicepool_modifier')) { + update['soak_modifier'] = value + } else { + const type = key.split('_')[3] + update[`${type}_modifier`] = value + } + } + + return update + }, + updatePrimaryWeapons: attrs => { + let update = {} + for (let [key, value] of Object.entries(attrs)) { + const type = processingFunctions.findRepeatingField(key) + const weaponAttribute = processingFunctions.getReprowAttribute(key) + const primaryAttributeName = key.includes('weapon') ? `primary_${type}_weapon` : `primary_${type}_weapon_${weaponAttribute}` + update[primaryAttributeName] = value + + if (key.includes('ammo')) { + update[`${primaryAttributeName}_max`] = value + } + } + return update + } +} + +//for Mocha Unit Testing +//-module.exports = shadowrunFunctions; + diff --git a/Shadowrun5thEdition/src/js/tests/Deprecated Mocha Tests/Processing_tests.js b/Shadowrun5thEdition/src/js/tests/Deprecated Mocha Tests/Processing_tests.js new file mode 100644 index 0000000000..c7f9de84c7 --- /dev/null +++ b/Shadowrun5thEdition/src/js/tests/Deprecated Mocha Tests/Processing_tests.js @@ -0,0 +1,37 @@ +const assert = require('assert') +const Functions = require('../js/processingFunctions'); + +describe('Roll20', () => { + it('setAttributes returns error if update is not an object', () => assert.ifError(Functions.setAttributes(6))) +}) + +describe('processingFunctions are generic functions not specific to the sytem', () => { + it('parseIntegers returns a number', () => { + const actual = Functions.parseIntegers({newValue: '6'}) + assert.ok(actual.newValue, 'number') + }) + + it('sumIntegers adds an array of numbers together', () => assert.strictEqual(Functions.sumIntegers([5, 10, 20]), 35)) + + it('convertInteger converts a string to number', () => assert.strictEqual(typeof Functions.parseInteger('6'), 'number')) + + it('getReprowid splits triggerName to get the repeating row id', () => { + const expected = 'repeating_advancement_-m1czg68yzicwhfdpyys' + const actual = Functions.getReprowid('repeating_advancement_-m1czg68yzicwhfdpyys_earned_xp') + assert.strictEqual(actual, expected) + }) + + it('convertIntegerNegative turns positive integar into negative', () => assert.strictEqual(Functions.convertIntegerNegative(6), -6)) + + it('sliceAttr removes the @{} from a value', () => assert.ok(Functions.sliceAttr('@{strength}'), 'strength')) + + it('The repeating name from the trigger', () => { + const actual = Functions.findRepeatingField('repeating_range_-m1czg68yzicwhfdpyys') + assert.ok(actual, 'range') + }) + + it('Get the attribute name from the trigger', () => { + const actual = Functions.getReprowAttribute('repeating_range_-m1czg68yzicwhfdpyys_attrName') + assert.ok(actual, 'attrName') + }) +}) diff --git a/Shadowrun5thEdition/src/test/Processing_tests.js b/Shadowrun5thEdition/src/js/tests/Deprecated Mocha Tests/ShadowrunFunctions_tests.js similarity index 51% rename from Shadowrun5thEdition/src/test/Processing_tests.js rename to Shadowrun5thEdition/src/js/tests/Deprecated Mocha Tests/ShadowrunFunctions_tests.js index 770de5c84c..2f48238197 100644 --- a/Shadowrun5thEdition/src/test/Processing_tests.js +++ b/Shadowrun5thEdition/src/js/tests/Deprecated Mocha Tests/ShadowrunFunctions_tests.js @@ -1,57 +1,34 @@ const assert = require('assert') -const Functions = require('../js/processingFunctions'); - -describe('Roll20', () => { - it('setAttributes returns error if update is not an object', () => assert.ifError(Functions.setAttributes(6))) -}) - -describe('Helper functions', () => { - it('parseIntegers returns a number', () => { - const actual = Functions.parseIntegers({newValue: '6'}) - assert.ok(actual.newValue, 'number') - }) - - it('sumIntegers adds an array of numbers together', () => assert.strictEqual(Functions.sumIntegers([5, 10, 20]), 35)) - - it('convertInteger converts a string to number', () => assert.strictEqual(typeof Functions.parseInteger('6'), 'number')) - - it('getReprowid splits triggerName to get the repeating row id', () => { - const expected = 'repeating_advancement_-m1czg68yzicwhfdpyys' - const actual = Functions.getReprowid('repeating_advancement_-m1czg68yzicwhfdpyys_earned_xp') - assert.strictEqual(actual, expected) - }) - - it('convertIntegerNegative turns positive integar into negative', () => assert.strictEqual(Functions.convertIntegerNegative(6), -6)) - - it('sliceAttr removes the @{} from a value', () => assert.ok(Functions.sliceAttr('@{strength}'), 'strength')) +const Functions = require('../js/shadowrunFunctions'); +describe('Shadowrun skill selects handling', () => { it('convertSkillSelectToHiddenSkill removes " Group" in skill groups ', () => { - const actual = Functions.shadowrun.convertSkillSelectToHiddenSkill('Firearms Group') + const actual = Functions.convertSkillSelectToHiddenSkill('Firearms Group') assert.ok(actual, 'firearms') }) it('convertSkillSelectToHiddenSkill removes all " " in skill groups ', () => { - const actual = Functions.shadowrun.convertSkillSelectToHiddenSkill('Close Combat Group') + const actual = Functions.convertSkillSelectToHiddenSkill('Close Combat Group') assert.ok(actual, 'closecombat') }) }) describe('Shadowrun shotsFired', () => { - it('shots_fired attribute are not greater than 0 && trigger "remove" there is no change', () => assert.strictEqual(Functions.shadowrun.shotsFired(-1, "shots_remove"), -1)) + it('shots_fired attribute are not greater than 0 && trigger "remove" there is no change', () => assert.strictEqual(Functions.shotsFired(-1, "shots_remove"), -1)) - it('trigger was "add" increment shots by 1', () => assert.strictEqual(Functions.shadowrun.shotsFired(5, "shots_add"), 6)) + it('trigger was "add" increment shots by 1', () => assert.strictEqual(Functions.shotsFired(5, "shots_add"), 6)) }) describe('Shadowrun calculateBonuses', () => { it('return an object with a only a base and bonus key', () => { const expected = {strength: 20, bonus: 5} - const actual = Functions.shadowrun.calculateBonuses({strength: 20, strength_modifier: 2, strength_temp: 3}) + const actual = Functions.calculateBonuses({strength: 20, strength_modifier: 2, strength_temp: 3}) assert.deepStrictEqual(actual, expected) }) it('add the value if the key contains "modifier" || "temp"', () => { const expected = 5; - const actual = Functions.shadowrun.calculateBonuses({strength: 20, strength_modifier: 2, strength_temp: 3}) + const actual = Functions.calculateBonuses({strength: 20, strength_modifier: 2, strength_temp: 3}) assert.strictEqual(actual.bonus, expected) }) }) @@ -59,236 +36,242 @@ describe('Shadowrun calculateBonuses', () => { describe('Shadowrun processTempFlags', () => { it('removes the flag property', () => { const expected = {reaction_base: 1, reaction_modifier: 2, reaction_temp: 0} - const actual = Functions.shadowrun.processTempFlags({reaction_base: 1, reaction_modifier: 2, reaction_temp: 0, reaction_temp_flag: "on"}) + const actual = Functions.processTempFlags({reaction_base: 1, reaction_modifier: 2, reaction_temp: 0, reaction_temp_flag: "on"}) assert.deepStrictEqual(actual, expected) }) it('removes temp if flag is not "on"', () => { const expected = {reaction_base: 1, reaction_modifier: 2} - const actual = Functions.shadowrun.processTempFlags({reaction_base: 1, reaction_modifier: 2, reaction_temp: 10, reaction_temp_flag: "off"}) + const actual = Functions.processTempFlags({reaction_base: 1, reaction_modifier: 2, reaction_temp: 10, reaction_temp_flag: "off"}) assert.deepStrictEqual(actual, expected) }) it('returns attribute name by splitting the flag', () => { - const actual = Functions.shadowrun.processTempFlags({physical_limit_temp_flag: "off"}) + const actual = Functions.processTempFlags({physical_limit_temp_flag: "off"}) assert.ok(actual, "physical_limit") }) }) describe('Shadowrun buildDisplay', () => { - it('returns the only base if bonus is 0', () => assert.strictEqual(Functions.shadowrun.buildDisplay(5, 0), 5)) - it('returns a string of "base (base+bonus)"', () => assert.ok(Functions.shadowrun.buildDisplay(5, 1), '5 (6)')) + it('returns the only base if bonus is 0', () => assert.strictEqual(Functions.buildDisplay(5, 0), 5)) + it('returns a string of "base (base+bonus)"', () => assert.ok(Functions.buildDisplay(5, 1), '5 (6)')) }) describe('Shadowrun calculateLimitTotal', () => { - it('calculates total of (z + y (x * 2))/3', () => assert.strictEqual(Functions.shadowrun.calculateLimitTotal([1, 3, 4]), 4)) + it('calculates total of (z + y (x * 2))/3', () => assert.strictEqual(Functions.calculateLimitTotal([1, 3, 4]), 4)) }) describe('Shadowrun calculate walk & run', () => { - it('walk speed is agility * 2 then add modifier', () => assert.strictEqual(Functions.shadowrun.calculateWalkSpeed(2, 20), 24)) + it('walk speed is agility * 2 then add modifier', () => assert.strictEqual(Functions.calculateWalkSpeed(2, 20), 24)) - it('run speed is agility * 4 then add modifier', () => assert.strictEqual(Functions.shadowrun.calculateRunSpeed(2, 20), 28)) + it('run speed is agility * 4 then add modifier', () => assert.strictEqual(Functions.calculateRunSpeed(2, 20), 28)) }) describe('Shadowrun findFlagInKeys', () => { it('searchs an array of keys for any containing "_flag"', () => { - const actual = Functions.shadowrun.findFlagInKeys({body: "5", soak_modifier: "6", soak_temp_flag: 'on'}) + const actual = Functions.findFlagInKeys({body: "5", soak_modifier: "6", soak_temp_flag: 'on'}) assert.ok(actual, "soak_temp_flag") }) }) describe('Shadowrun findModifierInKeys', () => { it('searchs an array of keys for any containing modifier', () => { - const actual = Functions.shadowrun.findModifierInKeys({body: "5", soak_modifier: "6", soak_temp_flag: 'on'}) + const actual = Functions.findModifierInKeys({body: "5", soak_modifier: "6", soak_temp_flag: 'on'}) assert.ok(actual, "soak_modifier") }) }) describe('Shadowrun condition factory', () => { it('should return an object', () => { - const actual = Functions.shadowrun.conditionFactory({}) + const actual = Functions.conditionFactory({}) assert.ok(actual, 'object') }) it('should contain an attribute key', () => { - const actual = Functions.shadowrun.conditionFactory({body: 3}) + const actual = Functions.conditionFactory({body: 3}) assert.ok(actual.attribute, true) }) it('should return attribute key with the value of willpower', () => { - const actual = Functions.shadowrun.conditionFactory({body: 3, willpower: 5}) + const actual = Functions.conditionFactory({body: 3, willpower: 5}) assert.strictEqual(actual.attribute, 5) }) it('should return base key', () => { - const actual = Functions.shadowrun.conditionFactory({}) + const actual = Functions.conditionFactory({}) assert.ok(actual.base, true) }) it('should return modifier key', () => { - const actual = Functions.shadowrun.conditionFactory({stun_modifier: 6}) + const actual = Functions.conditionFactory({stun_modifier: 6}) assert.ok(actual.modifier, true) }) it('should convert the attrs object into condition object', () => { const expected = {modifier: 7, attribute: 10, base: 8} - const actual = Functions.shadowrun.conditionFactory({stun_modifier: 7, willpower: 10}) + const actual = Functions.conditionFactory({stun_modifier: 7, willpower: 10}) assert.deepStrictEqual(actual, expected) }) }) describe('Shadowrun calculate condition tracks', () => { it('divide attribute by 2 then add base and modiifer', () => { - const actual = Functions.shadowrun.calculateConditionTracks({attribute: 3, base: 8, modifier: 2}) + const actual = Functions.calculateConditionTracks({attribute: 3, base: 8, modifier: 2}) assert.strictEqual(actual, 12) }) }) describe('Shadowrun determine condition base', () => { it('default base is 8', () => { - const actual = Functions.shadowrun.determineConditionBase() + const actual = Functions.determineConditionBase() assert.strictEqual(actual, 8) }) it('sheet is a vehicle and is a drone return 10', () => { - const actual = Functions.shadowrun.determineConditionBase('vehicle', 'drone') + const actual = Functions.determineConditionBase('vehicle', 'drone') assert.strictEqual(actual, 6) }) it('sheet is a vehicle but not a drone return 10', () => { - const actual = Functions.shadowrun.determineConditionBase('vehicle') + const actual = Functions.determineConditionBase('vehicle') assert.strictEqual(actual, 12) }) }) describe('Shadowrun determine condition attribute', () => { it('default attribute should be 0', () => { - const actual = Functions.shadowrun.determineConditionAttribute({}) + const actual = Functions.determineConditionAttribute({}) assert.strictEqual(actual, 0) }) it('stun will return willpower attribute', () => { - const actual = Functions.shadowrun.determineConditionAttribute({willpower: 8}, 'stun') + const actual = Functions.determineConditionAttribute({willpower: 8}, 'stun') assert.strictEqual(actual, 8) }) it('physical will return body attribute', () => { - const actual = Functions.shadowrun.determineConditionAttribute({body: 18}, 'physical') + const actual = Functions.determineConditionAttribute({body: 18}, 'physical') assert.strictEqual(actual, 18) }) it('matrix will return device rating attribute', () => { - const actual = Functions.shadowrun.determineConditionAttribute({device_rating: 5}, 'matrix') + const actual = Functions.determineConditionAttribute({device_rating: 5}, 'matrix') assert.strictEqual(actual, 5) }) }) describe('Shadowrun calculate wounds', () => { it('default is 0', () => { - const actual = Functions.shadowrun.calculateWounds({}) + const actual = Functions.calculateWounds({}) assert.strictEqual(actual, 0) }) it('low pain tolerance is false then divide by 3', () => { - const actual = Functions.shadowrun.calculateWounds({physical: 6}) + const actual = Functions.calculateWounds({physical: 6}) assert.strictEqual(actual, -2) }) it('low pain tolerance is equal 2 then divide by 2', () => { - const actual = Functions.shadowrun.calculateWounds({low_pain_tolerance: 2, physical: 6}) + const actual = Functions.calculateWounds({low_pain_tolerance: 2, physical: 6}) assert.strictEqual(actual, -3) }) it('add physical & stun wounds together', () => { - const actual = Functions.shadowrun.calculateWounds({physical: 6, stun: 9}) + const actual = Functions.calculateWounds({physical: 6, stun: 9}) assert.strictEqual(actual, -5) }) it('high pain tolerance should subtract from the divisor', () => { - const actual = Functions.shadowrun.calculateWounds({high_pain_tolerance: 2, physical: 6, stun: 9}) + const actual = Functions.calculateWounds({high_pain_tolerance: 2, physical: 6, stun: 9}) assert.strictEqual(actual, -3) }) it('damage compensator should subtract from its type', () => { - const actual = Functions.shadowrun.calculateWounds({physical: 6, stun: 9, damage_compensators_physical: 3}) + const actual = Functions.calculateWounds({physical: 6, stun: 9, damage_compensators_physical: 3}) assert.strictEqual(actual, -4) }) it('damage compensator and high paintolerance stack', () => { - const actual = Functions.shadowrun.calculateWounds({high_pain_tolerance: 2, physical: 6, damage_compensators_physical: 3}) + const actual = Functions.calculateWounds({high_pain_tolerance: 2, physical: 6, damage_compensators_physical: 3}) assert.strictEqual(actual, 0) }) it('minimum of 0', () => { - const actual = Functions.shadowrun.calculateWounds({physical: 6, damage_compensators_physical: 13}) + const actual = Functions.calculateWounds({physical: 6, damage_compensators_physical: 13}) assert.strictEqual(actual, 0) }) }) describe('Shadowrun attribute factory', () => { it('should return an object', () => { - const actual = Functions.shadowrun.attributeFactory({}) + const actual = Functions.attributeFactory({}) assert.ok(actual, 'object') }) it('should remove temp keys if flag is "on" and return bonus with temp value', () => { - const actual = Functions.shadowrun.attributeFactory({reaction_temp: 123, reaction_temp_flag: "on"}) + const actual = Functions.attributeFactory({reaction_temp: 123, reaction_temp_flag: "on"}) assert.deepStrictEqual(actual, {total: 123, base: 0, bonus: 123}) }) it('should return base values', () => { - const actual = Functions.shadowrun.attributeFactory({intuition: 1, reaction: 3}) + const actual = Functions.attributeFactory({intuition: 1, reaction: 3}) assert.deepStrictEqual(actual.base, 4) }) it('should return modifier + temp as bonus if flag is "on"', () => { - const actual = Functions.shadowrun.attributeFactory({reaction_modifier: 20, reaction_temp: 1, reaction_temp_flag: "on"}) + const actual = Functions.attributeFactory({reaction_modifier: 20, reaction_temp: 1, reaction_temp_flag: "on"}) assert.equal(actual.total, 21) }) it('should return total values', () => { - const actual = Functions.shadowrun.attributeFactory({intuition: 1, reaction: 3, initiative_modifier: 6, initiative_temp: 10, initiative_temp_flag: 'on'}) + const actual = Functions.attributeFactory({intuition: 1, reaction: 3, initiative_modifier: 6, initiative_temp: 10, initiative_temp_flag: 'on'}) assert.deepStrictEqual(actual.base, 4) }) }) -describe('Shadowrun findRepeatingField', () => { - it('Shadowrun get type out of the trigger', () => { - const actual = Functions.findRepeatingField('repeating_range_-m1czg68yzicwhfdpyys') - assert.ok(actual, 'range') - }) -}) - describe('Shadowrun addRepRow', () => { it('Shadowrun should return an array', () => { - const actual = Functions.shadowrun.addRepRow('repeating_range_-m1czg68yzicwhfdpyys', ['ammo']) + const actual = Functions.addRepRow('repeating_range_-m1czg68yzicwhfdpyys', ['ammo']) assert.ok(typeof actual, 'array') }) it('Shadowrun should entries with the reprowid added to the attribute name', () => { - const actual = Functions.shadowrun.addRepRow('repeating_range_-m1czg68yzicwhfdpyys', ['ammo']) + const actual = Functions.addRepRow('repeating_range_-m1czg68yzicwhfdpyys', ['ammo']) assert.ok(actual, ['repeating_range_-m1czg68yzicwhfdpyys_ammo']) }) }) describe('Shadowrun updatePrimaryWeapons', () => { it('should return an object', () => { - const actual = Functions.shadowrun.updatePrimaryWeapons({}) + const actual = Functions.updatePrimaryWeapons({}) assert.ok(typeof actual, 'object') }) it('should return weapon with the string in weapon from the attrs', () => { - const actual = Functions.shadowrun.updatePrimaryWeapons({"repeating_range_-m2wiegzcjb0w5vewbnj_weapon": "Test Name"}) + const actual = Functions.updatePrimaryWeapons({"repeating_range_-m2wiegzcjb0w5vewbnj_weapon": "Test Name"}) assert.ok(actual.primary_range_weapon, 'Test Name') }) it('all other attributes should add weapon before the descritive attribute name', () => { - const actual = Functions.shadowrun.updatePrimaryWeapons({"repeating_melee_-m2wiegzcjb0w5vewbnj_dicepool": 12}) + const actual = Functions.updatePrimaryWeapons({"repeating_melee_-m2wiegzcjb0w5vewbnj_dicepool": 12}) assert.deepStrictEqual(actual, {"primary_melee_weapon_dicepool":12}) }) it('if ammo is the key then ammo_maxs should also be in update', () => { - const actual = Functions.shadowrun.updatePrimaryWeapons({"repeating_range_-m2wiegzcjb0w5vewbnj_ammo": 12}) + const actual = Functions.updatePrimaryWeapons({"repeating_range_-m2wiegzcjb0w5vewbnj_ammo": 12}) assert.deepStrictEqual(actual, {"primary_range_weapon_ammo": 12, "primary_range_weapon_ammo_max": 12}) }) }) + + +describe('Shadowrun determineExplodingEdge', () => { + it('should return "!" if newValue is @{edge}', () => { + const actual = Functions.determineExplodingEdge('@{edge}') + assert.ok(actual, "!") + }) + + it('should return nothing if newValue is not @{edge}', () => { + const actual = Functions.determineExplodingEdge('8') + assert.ok(!actual, "!") + }) +}) \ No newline at end of file diff --git a/Shadowrun5thEdition/src/test/Roll20Mockups.js b/Shadowrun5thEdition/src/js/tests/Mocks/Mocks.js similarity index 90% rename from Shadowrun5thEdition/src/test/Roll20Mockups.js rename to Shadowrun5thEdition/src/js/tests/Mocks/Mocks.js index e6e60de91c..b3770938d6 100644 --- a/Shadowrun5thEdition/src/test/Roll20Mockups.js +++ b/Shadowrun5thEdition/src/js/tests/Mocks/Mocks.js @@ -1,8 +1,9 @@ let attributes = {}; let sectionIDS = {}; const maxAsyncDelay = 2000; -const getRandomInt = max => Math.floor(Math.random() * Math.floor(max)) - +const getRandomInt = function(max) { + return Math.floor(Math.random() * Math.floor(max)); +}; const getAttrs = function(attrs, callback) { let values = {}; setTimeout(() => { @@ -12,7 +13,6 @@ const getAttrs = function(attrs, callback) { callback(values); }, getRandomInt(maxAsyncDelay)); }; - const setAttrs = function(attrs, callback) { let values = {}; setTimeout(() => { @@ -27,10 +27,9 @@ const setAttrs = function(attrs, callback) { callback(attributes); }, getRandomInt(maxAsyncDelay)); }; - const getSectionIDs = function(section, callback) { setTimeout(() => { let ids = sectionIDS[section] || []; callback(ids); }, getRandomInt(maxAsyncDelay)); -}; +}; \ No newline at end of file diff --git a/Shadowrun5thEdition/src/js/tests/tests.html b/Shadowrun5thEdition/src/js/tests/tests.html new file mode 100644 index 0000000000..87a79a1011 --- /dev/null +++ b/Shadowrun5thEdition/src/js/tests/tests.html @@ -0,0 +1,19 @@ + + + + + + dropFunctions + + + +
+
+ + + + + + + + \ No newline at end of file diff --git a/Shadowrun5thEdition/src/js/tests/tests.js b/Shadowrun5thEdition/src/js/tests/tests.js new file mode 100644 index 0000000000..9bdc4abddf --- /dev/null +++ b/Shadowrun5thEdition/src/js/tests/tests.js @@ -0,0 +1,252 @@ +QUnit.module('Shadowrun 5th Edition tests', { + before: () => maxAsyncDelay = 100, //Sets the mock delay for getAttrs and setAttrs to a maximum of 1000ms. + beforeEach: () => { + //Resets attributes before each test + attributes = {} + sectionIDS = {} + } +}) + +QUnit.test('setAttributes returns error if update is not an object', assert => assert.throws(processingFunctions.setAttributes(6))) + +QUnit.test('parseIntegers returns a number', assert => { + const actual = processingFunctions.parseIntegers({newValue: '6'}) + assert.ok(actual.newValue, 'number') +}) + +QUnit.test('sumIntegers adds an array of numbers together', assert => assert.strictEqual(processingFunctions.sumIntegers([5, 10, 20]), 35)) + +QUnit.test('convertInteger converts a string to number', assert => assert.strictEqual(typeof processingFunctions.parseInteger('6'), 'number')) + +QUnit.test('getReprowid splQUnit.tests triggerName to get the repeating row id', assert => { + const expected = 'repeating_advancement_-m1czg68yzicwhfdpyys' + const actual = processingFunctions.getReprowid('repeating_advancement_-m1czg68yzicwhfdpyys_earned_xp') + assert.strictEqual(actual, expected) +}) + +QUnit.test('convertIntegerNegative turns posQUnit.testive integar into negative', assert => assert.strictEqual(processingFunctions.convertIntegerNegative(6), -6)) + +QUnit.test('sliceAttr removes the @{} from a value', assert => assert.ok(processingFunctions.sliceAttr('@{strength}'), 'strength')) + +QUnit.test('The repeating name from the trigger', assert => { + const actual = processingFunctions.findRepeatingField('repeating_range_-m1czg68yzicwhfdpyys') + assert.ok(actual, 'range') +}) + +QUnit.test('Get the attribute name from the trigger', assert => { + const actual = processingFunctions.getReprowAttribute('repeating_range_-m1czg68yzicwhfdpyys_attrName') + assert.ok(actual, 'attrName') +}) + +QUnit.test('convertSkillSelectToHiddenSkill removes " Group" in skill groups ', assert => { + const actual = shadowrunFunctions.convertSkillSelectToHiddenSkill('Firearms Group') + assert.ok(actual, 'firearms') +}) + +QUnit.test('convertSkillSelectToHiddenSkill removes all " " in skill groups ', assert => { + const actual = shadowrunFunctions.convertSkillSelectToHiddenSkill('Close Combat Group') + assert.ok(actual, 'closecombat') +}) + +QUnit.test('shots_fired attribute are not greater than 0 && trigger "remove" there is no change', assert => assert.strictEqual(shadowrunFunctions.shotsFired(-1, "shots_remove"), -1)) + +QUnit.test('trigger was "add" increment shots by 1', assert => assert.strictEqual(shadowrunFunctions.shotsFired(5, "shots_add"), 6)) + +QUnit.test('return an object wQUnit.testh a only a base and bonus key', assert => { + const expected = {strength: 20, bonus: 5} + const actual = shadowrunFunctions.calculateBonuses({strength: 20, strength_modifier: 2, strength_temp: 3}) + assert.deepEqual(actual, expected) +}) + +QUnit.test('add the value if the key contains "modifier" || "temp"', assert => { + const expected = 5; + const actual = shadowrunFunctions.calculateBonuses({strength: 20, strength_modifier: 2, strength_temp: 3}) + assert.strictEqual(actual.bonus, expected) +}) + +QUnit.test('removes the flag property', assert => { + const expected = {reaction_base: 1, reaction_modifier: 2, reaction_temp: 0} + const actual = shadowrunFunctions.processTempFlags({reaction_base: 1, reaction_modifier: 2, reaction_temp: 0, reaction_temp_flag: "on"}) + assert.deepEqual(actual, expected) +}) + +QUnit.test('removes temp if flag is not "on"', assert => { + const expected = {reaction_base: 1, reaction_modifier: 2} + const actual = shadowrunFunctions.processTempFlags({reaction_base: 1, reaction_modifier: 2, reaction_temp: 10, reaction_temp_flag: "off"}) + assert.deepEqual(actual, expected) +}) + +QUnit.test('returns the only base if bonus is 0', assert => assert.strictEqual(shadowrunFunctions.buildDisplay(5, 0), 5)) +QUnit.test('returns a string of "base (base+bonus)"', assert => assert.ok(shadowrunFunctions.buildDisplay(5, 1), '5 (6)')) + +QUnit.test('calculates total of (z + y (x * 2))/3', assert => assert.strictEqual(shadowrunFunctions.calculateLimitTotal([1, 3, 4]), 4)) + +QUnit.test('walk speed is agilQUnit.testy * 2 then add modifier', assert => assert.strictEqual(shadowrunFunctions.calculateWalkSpeed(2, 20), 24)) + +QUnit.test('run speed is agilQUnit.testy * 4 then add modifier', assert => assert.strictEqual(shadowrunFunctions.calculateRunSpeed(2, 20), 28)) + +QUnit.test('searchs an array of keys for any containing "_flag"', assert => { + const actual = shadowrunFunctions.findFlagInKeys({body: "5", soak_modifier: "6", soak_temp_flag: 'on'}) + assert.ok(actual, "soak_temp_flag") +}) + +QUnit.test('searchs an array of keys for any containing modifier', assert => { + const actual = shadowrunFunctions.findModifierInKeys({body: "5", soak_modifier: "6", soak_temp_flag: 'on'}) + assert.ok(actual, "soak_modifier") +}) + +QUnit.test('should return an object', assert => { + const actual = shadowrunFunctions.conditionFactory({}) + assert.ok(actual, 'object') +}) + +QUnit.test('should contain an attribute key', assert => { + const actual = shadowrunFunctions.conditionFactory({body: 3}) + assert.ok(actual.attribute, true) +}) + +QUnit.test('should return attribute key wQUnit.testh the value of willpower', assert => { + const actual = shadowrunFunctions.conditionFactory({body: 3, willpower: 5}) + assert.strictEqual(actual.attribute, 5) +}) + +QUnit.test('should return base key', assert => { + const actual = shadowrunFunctions.conditionFactory({}) + assert.ok(actual.base, true) +}) + +QUnit.test('should return modifier key', assert => { + const actual = shadowrunFunctions.conditionFactory({stun_modifier: 6}) + assert.ok(actual.modifier, true) +}) + +QUnit.test('should convert the attrs object into condQUnit.testion object', assert => { + const expected = {modifier: 7, attribute: 10, base: 8} + const actual = shadowrunFunctions.conditionFactory({stun_modifier: 7, willpower: 10}) + assert.deepEqual(actual, expected) +}) + +QUnit.test('divide attribute by 2 then add base and modiifer', assert => { + const actual = shadowrunFunctions.calculateConditionTracks({attribute: 3, base: 8, modifier: 2}) + assert.strictEqual(actual, 12) +}) + +QUnit.test('default base is 8', assert => { + const actual = shadowrunFunctions.determineConditionBase() + assert.strictEqual(actual, 8) +}) + +QUnit.test('sheet is a vehicle and is a drone return 10', assert => { + const actual = shadowrunFunctions.determineConditionBase('vehicle', 'drone') + assert.strictEqual(actual, 6) +}) + +QUnit.test('sheet is a vehicle but not a drone return 10', assert => { + const actual = shadowrunFunctions.determineConditionBase('vehicle') + assert.strictEqual(actual, 12) +}) + +QUnit.test('default attribute should be 0', assert => { + const actual = shadowrunFunctions.determineConditionAttribute({}) + assert.strictEqual(actual, 0) +}) + +QUnit.test('stun will return willpower attribute', assert => { + const actual = shadowrunFunctions.determineConditionAttribute({willpower: 8}, 'stun') + assert.strictEqual(actual, 8) +}) + +QUnit.test('physical will return body attribute', assert => { + const actual = shadowrunFunctions.determineConditionAttribute({body: 18}, 'physical') + assert.strictEqual(actual, 18) +}) + +QUnit.test('matrix will return device rating attribute', assert => { + const actual = shadowrunFunctions.determineConditionAttribute({device_rating: 5}, 'matrix') + assert.strictEqual(actual, 5) +}) + +QUnit.test('default is 0', assert => { + const actual = shadowrunFunctions.calculateWounds({}) + assert.strictEqual(actual, 0) +}) + +QUnit.test('low pain tolerance is false then divide by 3', assert => { + const actual = shadowrunFunctions.calculateWounds({physical: 6}) + assert.strictEqual(actual, -2) +}) + +QUnit.test('low pain tolerance is equal 2 then divide by 2', assert => { + const actual = shadowrunFunctions.calculateWounds({low_pain_tolerance: 2, physical: 6}) + assert.strictEqual(actual, -3) +}) + +QUnit.test('add physical & stun wounds together', assert => { + const actual = shadowrunFunctions.calculateWounds({physical: 6, stun: 9}) + assert.strictEqual(actual, -5) +}) + +QUnit.test('high pain tolerance should subtract from the divisor', assert => { + const actual = shadowrunFunctions.calculateWounds({high_pain_tolerance: 2, physical: 6, stun: 9}) + assert.strictEqual(actual, -3) +}) + +QUnit.test('damage compensator should subtract from condition type', assert => { + const actual = shadowrunFunctions.calculateWounds({physical: 6, stun: 9, damage_compensators_physical: 3}) + assert.strictEqual(actual, -4) +}) + +QUnit.test('damage compensator and high paintolerance stack', assert => { + const actual = shadowrunFunctions.calculateWounds({high_pain_tolerance: 2, physical: 6, damage_compensators_physical: 3}) + assert.strictEqual(actual, 0) +}) + +QUnit.test('minimum of 0', assert => { + const actual = shadowrunFunctions.calculateWounds({physical: 6, damage_compensators_physical: 13}) + assert.strictEqual(actual, 0) +}) + +QUnit.test('should return an object', assert => { + const actual = shadowrunFunctions.attributeFactory({}) + assert.ok(actual, 'object') +}) + +QUnit.test('should remove temp keys if flag is "on" and return bonus wQUnit.testh temp value', assert => { + const actual = shadowrunFunctions.attributeFactory({reaction_temp: 123, reaction_temp_flag: "on"}) + assert.deepEqual(actual, {total: 123, base: 0, bonus: 123}) +}) + +QUnit.test('should return base values', assert => { + const actual = shadowrunFunctions.attributeFactory({intuition: 1, reaction: 3}) + assert.deepEqual(actual.base, 4) +}) + +QUnit.test('should return modifier + temp as bonus if flag is "on"', assert => { + const actual = shadowrunFunctions.attributeFactory({reaction_modifier: 20, reaction_temp: 1, reaction_temp_flag: "on"}) + assert.equal(actual.total, 21) +}) + +QUnit.test('returns attribute name by splQUnit.testting the flag', assert => { + const actual = shadowrunFunctions.processTempFlags({physical_limit_temp_flag: "off"}) + assert.ok(actual, "physical_limQUnit.test") +}) + +QUnit.test('should return modifier + temp as bonus if flag is "on"', assert => { + const actual = shadowrunFunctions.attributeFactory({reaction_modifier: 20, reaction_temp: 1, reaction_temp_flag: "on"}) + assert.equal(actual.total, 21) +}) + +QUnit.test('should return total values', assert => { + const actual = shadowrunFunctions.attributeFactory({intuition: 1, reaction: 3, initiative_modifier: 6, initiative_temp: 10, initiative_temp_flag: 'on'}) + assert.deepEqual(actual.base, 4) +}) + +QUnit.test('Shadowrun should return an array', assert => { + const actual = shadowrunFunctions.addRepRow('repeating_range_-m1czg68yzicwhfdpyys', ['ammo']) + assert.ok(typeof actual, 'array') +}) + +QUnit.test('Shadowrun should entries with the reprowid added to the attribute name', assert => { + const actual = shadowrunFunctions.addRepRow('repeating_range_-m1czg68yzicwhfdpyys', ['ammo']) + assert.ok(actual, ['repeating_range_-m1czg68yzicwhfdpyys_ammo']) +}) diff --git a/Shadowrun5thEdition/src/js/versioning.js b/Shadowrun5thEdition/src/js/versioning.js index d9465f7463..509523d853 100644 --- a/Shadowrun5thEdition/src/js/versioning.js +++ b/Shadowrun5thEdition/src/js/versioning.js @@ -23,11 +23,42 @@ const versioning = version => { fourpointoneone() setAttrs({version: 4.11}, () => versioning(4.11)) break; + case version < 4.15: + fourpointonefive() + setAttrs({version: 4.15}, () => versioning(4.15)) + break; default: console.log(`%c Shadowrun 5th Edition is update to date. Version ${version}`, "color: green; font-weight:bold"); } }; +const fourpointonefive = () => { + updateDerivedAttribute('defense') + updateAttributes(sheetAttributes.initiative_mod, 'initiative_mod') + updateAstralInitiative() + + sheetAttributes.repeatingSkills.forEach(skill => { + getSectionIDs(skill, idarray => { + let attributes = [] + idarray.forEach(id => attributes.push(`repeating_${skill}_${id}_limit`)) + + getAttrs(attributes, values => { + let update = {} + for (let [key, value] of Object.entries(values)) { + const repRowID = processingFunctions.getReprowid(key) + if (value.includes('limit')) { + const translationKey = processingFunctions.sliceAttr(value) + update[`${repRowID}_display_limit`] = getTranslationByKey(translationKey) + } else { + update[`${repRowID}_display_limit`] = ' ' + } + } + processingFunctions.setAttributes(update) + }) + }) + }) +} + const fourpointoneone = () => { getSectionIDs('forms', idarray => { let attributes = []; diff --git a/Shadowrun5thEdition/src/pug/_mixins.pug b/Shadowrun5thEdition/src/pug/_mixins.pug index 7d13edf1ee..580d9a5ce3 100644 --- a/Shadowrun5thEdition/src/pug/_mixins.pug +++ b/Shadowrun5thEdition/src/pug/_mixins.pug @@ -6,7 +6,7 @@ mixin rollButton(header, base, rollFormula) mixin skillButton(specialization, skillType) - const rollName = specialization === true ? 'specialization' : 'skill'; - const rollFormula = specialization === true ? '@{dicepool}+@{attribute}+2' : '@{dicepool}+@{attribute}'; - - const desc = specialization === true ? 'Spec: @{specialization}, @{display_limit}' : '@{display_limit}'; + - const desc = specialization === true ? 'Spec: @{specialization}, @{display_limit} @{limit}' : '@{display_limit} @{limit}'; - const display = specialization === true ? 'attr_specialization' : skillType != 'active' ? 'attr_skill' : 'attr_display_skill'; button.eclipse(name=`roll_${rollName}` type='roll' value!=rollBeginging+'{{header=@{skill}}}{{base=@{display_attribute}}}{{dice=[[(('+rollFormula+')'+rollEnding+'{{desc='+desc+'}}') span(name=display) @@ -53,13 +53,13 @@ mixin attributeSelect(selectedDefault) //- LIMIT SElECTS mixin limitSelect(selectedDefault) - option(value='none') - + option(value='') - each val, key in limitObject - const attributeName = key.toLowerCase().replace(' ', '_'); if key === selectedDefault - option(data-i18n=attributeName value='@{' + val + '}' selected) #{key} + option(data-i18n=attributeName value=`@{${val}}` selected) #{key} else - option(data-i18n=attributeName value='@{' + val + '}') #{key} + option(data-i18n=attributeName value=`@{${val}}`) #{key} //- HOST & SPRITE NPCS mixin hostSprite(object, attrName) @@ -103,75 +103,80 @@ mixin fadeDrainSection(fadeOrDrain, adept) //- PC SPELLS AND PREPARATIONS mixin pcSpells(type) - - const rollInfoObject = type === 'preps' ? pcAlchemySpellObject : pcSorcerySpellObject; - - const repeatingSection = `@{repeating_${type}`+'_${x}'; + - const rollInfoObject = type === 'preps' ? pcAlchemySpellObject : pcSorcerySpellObject; + - const repeatingSection = `@{repeating_${type}`+'_${x}'; - .rows.repeating-container - fieldset(class=`repeating_${type}`) - input(name='attr_dicepool' type='hidden' value='0') - button(name=`roll_${type}}` type='roll' value!=rollBeginging+'{{header=@{name}}}{{base=^{magic}}}{{dice=[[((@{skill}+@{dicepool}+@{magic})'+rollEnding+'{{desc=@{combat_type}?{Force|}}}{{drain=[[?{Force|}+(@{drain})]]}}') - span(name='attr_name') - each val in ['type', 'range', 'duration', 'drain'] - span.center(name='attr_'+val) - input.collapse-flag(name='attr_display_flag' type='checkbox' checked) - span.pictos i - input.settings-flag(name='attr_flag' title='Settings toggle' type='checkbox' checked) - span.pictos x - .collapse - span(name='attr_notes') - .settings - each val, key in pcCoreSpellObject - - const translationKey = key.toLowerCase(); - - const attrName = key.toLowerCase(); + .rows.repeating-container + fieldset(class=`repeating_${type}`) + input(name='attr_dicepool' type='hidden' value='0') + + //- This button displays in the roll template in chat window + button.display-none(name="roll_drain" type="roll" value="@{gm_toggle} &{template:rolls}{{mod=[[@{modifiers_toggle}]]}}{{edge=[[@{edge_toggle}]]}}{{header=^{drain}}}{{base=^{base}}}{{dice=[[((@{drain_attribute_1}+@{drain_attribute_2}+@{drain_modifier})+@{modifiers_toggle}+@{edge_toggle})d6>5@{explode_toggle}]]}}") + + //- This the spell rolling button on the sheet + button(name=`roll_${type}` type='roll' value!=rollBeginging+'{{header=@{name}}}{{base=^{magic}}}{{dice=[[((@{skill}+@{dicepool}+@{magic})'+rollEnding+`{{desc=@{combat_type}?{Force|}}}{{drain=[[?{Force|}+(@{drain})]] [f](~repeating_${type}_drain)}}`) + span(name='attr_name') + each val in ['type', 'range', 'duration', 'drain'] + span.text-center(name='attr_'+val) + input.collapse-flag(name='attr_display_flag' type='checkbox' checked) + span.pictos i + input.settings-flag(name='attr_flag' title='Settings toggle' type='checkbox' checked) + span.pictos x + .collapse + span(name='attr_notes') + .settings + each val, key in pcCoreSpellObject + - const translationKey = key.toLowerCase(); + - const attrName = key.toLowerCase(); + if val['type'] === 'select' + select(name=`attr_${attrName}` title=`${repeatingSection}_${attrName}}` value=val['default']) + each type in val['array'] + - const i18n = type.toLowerCase(); + if val['default'] === i18n + option(data-i18n=i18n value=type 'selected') #{i18n} + else + option(data-i18n=i18n value=type) #{i18n} + else + label(data-i18n-title=translationKey title=key) + input(name=`attr_${attrName}` placeholder=val['placeholder'] title=`${repeatingSection}_${attrName}}` type=val['type']) + .row + each val, key in pcCatagorySpellObject + - const translationKey = key.toLowerCase().replace(' ', ''); + - const attrName = key === 'Combat' ? 'combat_type' : key.toLowerCase(); + h3(data-i18n=translationKey) #{key} if val['type'] === 'select' select(name=`attr_${attrName}` title=`${repeatingSection}_${attrName}}` value=val['default']) - each type in val['array'] - - const i18n = type.toLowerCase(); - if val['default'] === i18n - option(data-i18n=i18n value=type 'selected') #{i18n} - else - option(data-i18n=i18n value=type) #{i18n} + each type in val['array'] + - const i18n = key === 'Combat' ? type.split(' ')[0].replace(',','').toLowerCase() : type.toLowerCase(); + if val['default'] === i18n + option(data-i18n=i18n value=type 'selected') #{i18n} + else if i18n === 'force' + option(value=type 'selected') + else + option(data-i18n=i18n value=type) #{i18n} else label(data-i18n-title=translationKey title=key) input(name=`attr_${attrName}` placeholder=val['placeholder'] title=`${repeatingSection}_${attrName}}` type=val['type']) - .row - each val, key in pcCatagorySpellObject - - const translationKey = key.toLowerCase().replace(' ', ''); - - const attrName = key === 'Combat' ? 'combat_type' : key.toLowerCase(); - h3(data-i18n=translationKey) #{key} - if val['type'] === 'select' - select(name=`attr_${attrName}` title=`${repeatingSection}_${attrName}}` value=val['default']) - each type in val['array'] - - const i18n = key === 'Combat' ? type.split(' ')[0].replace(',','').toLowerCase() : type.toLowerCase(); - if val['default'] === i18n - option(data-i18n=i18n value=type 'selected') #{i18n} - else if i18n === 'force' - option(value=type 'selected') - else - option(data-i18n=i18n value=type) #{i18n} - else - label(data-i18n-title=translationKey title=key) - input(name=`attr_${attrName}` placeholder=val['placeholder'] title=`${repeatingSection}_${attrName}}` type=val['type']) - .row - each val, key in rollInfoObject - - const translationKey = key.toLowerCase().replace(' ', ''); - - const attrName = key === 'modifier dice' ? 'dicepool_modifier' : key.includes('Group') ? key.split(' ')[0].toLowerCase() : key === 'Notes' ? 'note' : key.toLowerCase(); - h3(data-i18n=translationKey) #{key} - if val['type'] === 'select' - select(name=`attr_${attrName}` title=`${repeatingSection}_${attrName}}` value=val['default']) - each skill in val['array'] - - const i18n = skill.includes('Group') ? skill.toLowerCase().replace(' ', '') : skill.toLowerCase(); - - const attrName = skill.includes('Group') ? skill.toLowerCase().split(' ')[0] : skill.toLowerCase(); - if val['default'] === `@{${attrName}}` - option(data-i18n=i18n value=`@{${attrName}}` 'selected') #{i18n} - else - option(data-i18n=i18n value=`@{${attrName}}`) #{i18n} - else - label(data-i18n-title=translationKey title=key) - input(name=`attr_${attrName}` placeholder=val['placeholder'] title=`${repeatingSection}_${attrName}}` type=val['type'] value=val['default']) - h3(data-i18n='notes') notes - label(data-i18n-title='notes' title='notes') - textarea(name='attr_notes' placeholder='Notes' title=`${repeatingSection}_notes}` type='text' value='') + .row + each val, key in rollInfoObject + - const translationKey = key.toLowerCase().replace(' ', ''); + - const attrName = key === 'modifier dice' ? 'dicepool_modifier' : key.includes('Group') ? key.split(' ')[0].toLowerCase() : key === 'Notes' ? 'note' : key.toLowerCase(); + h3(data-i18n=translationKey) #{key} + if val['type'] === 'select' + select(name=`attr_${attrName}` title=`${repeatingSection}_${attrName}}` value=val['default']) + each skill in val['array'] + - const i18n = skill.includes('Group') ? skill.toLowerCase().replace(' ', '') : skill.toLowerCase(); + - const attrName = skill.includes('Group') ? skill.toLowerCase().split(' ')[0] : skill.toLowerCase(); + if val['default'] === `@{${attrName}}` + option(data-i18n=i18n value=`@{${attrName}}` 'selected') #{i18n} + else + option(data-i18n=i18n value=`@{${attrName}}`) #{i18n} + else + label(data-i18n-title=translationKey title=key) + input(name=`attr_${attrName}` placeholder=val['placeholder'] title=`${repeatingSection}_${attrName}}` type=val['type'] value=val['default']) + h3(data-i18n='notes') notes + label(data-i18n-title='notes' title='notes') + textarea(name='attr_notes' placeholder='Notes' title=`${repeatingSection}_notes}` type='text' value='') //- PC ARMS @@ -193,4 +198,13 @@ mixin repeatingSectionFlags() mixin repeatingSectionNotes(section) h3(data-i18n='notes') notes label(data-i18n-title='notes' title='notes') - textarea(name='attr_notes' placeholder='Notes' title=`@{repeating_${section}_`+'${x}_notes}' type='text' value='') \ No newline at end of file + textarea(name='attr_notes' placeholder='Notes' title=`@{repeating_${section}_`+'${x}_notes}' type='text' value='') + +mixin repeatingPCVehicles(attribute) + - const repeatingRowVehicle = '@{repeating_vehicle_${x}'; + h3(data-i18n=`${attribute}`) + input(name=`attr_${attribute}` type="hidden") + input( type="hidden" name=`attr_display_${attribute}`) + each val in ['base', 'modifier', 'temp'] + label(data-i18n-title=`${attribute} ${val}`) + input(name=`attr_${attribute}_${val}` placeholder="#" title=`${repeatingRowVehicle}_${val}` type="number") \ No newline at end of file diff --git a/Shadowrun5thEdition/src/pug/_npc.pug b/Shadowrun5thEdition/src/pug/_npc.pug index 856d3edda1..5982d22367 100644 --- a/Shadowrun5thEdition/src/pug/_npc.pug +++ b/Shadowrun5thEdition/src/pug/_npc.pug @@ -65,7 +65,6 @@ //-BODY .mid.body .column - h1.settings(data-i18n='bonuses') Bonuses //- PROFESSIONAL RATINGS input(name='attr_pr' type='hidden' value='') .rows.grunt @@ -73,6 +72,7 @@ span(name='attr_pr' style='margin-left: 2%;') label.settings(data-i18n-title='pr' title='Professional Rating') input(name='attr_pr' title='@{pr}' type='number') + h1.settings(data-i18n='bonuses') Bonuses //- INITAITIVE each val, key in {'Initiative': ['initiative', 'initiative', 'grunt'], 'Astral Initiative': ['astral', 'astralinitiative', 'grunt hide-magic'], 'Matrix Initiative': ['matrix', 'matrixinitiative', 'grunt vehicle sprite host']} @@ -157,23 +157,25 @@ //- MODIFIERS .column - h1.settings(data-i18n='modifier') Modifier .rows +rollButton('armorrating', 'base', '@{armor_rating}') label.settings(data-i18n-title='armorrating' title='armorrating') input(name='attr_armor_rating' placeholder='9' title='@{armor_rating}' type='number' value='0') + h1.settings(data-i18n='modifier') Modifier .rows +rollButton('defense', 'base', '@{defense}') label.settings(data-i18n-title='defense' title='defense') input(name='attr_defense_modifier' placeholder='9' title='@{defense_modifier}' type='number' value='0') + span.settings.tiny-span() = + span(name=`attr_defense`) each val, key in {'Soak': ['soak', 'soak'], 'Acid Protection': ['acid', 'acidprotection'], 'Cold Protection': ['cold', 'coldprotection'], 'Electrical Protection': ['electrical', 'electricalprotection'], 'Fire Protection': ['fire', 'fireprotection'], 'Radiation Protection': ['radiation', 'radiationprotection']} .rows - +rollButton(val[1], 'base', '@{soak}+@{'+val[0]+'_modifier}') + +rollButton(val[1], 'base', `@{soak}+@{${val[0]}_modifier}`) label.settings(data-i18n-title=val[1] title=val[1]) - input(name='attr_'+val[0]+'_modifier' placeholder='0' title='@{'+val[0]+'_modifier}' type='number' value='0') - if (key === 'Defense' || key === 'Soak') + input(name=`attr_${val[0]}_modifier` placeholder='0' title=`@{${val[0]}_modifier}` type='number' value='0') + if (key === 'Soak') span.settings.tiny-span() = - span(name='attr_'+val[0]) + span(name=`attr_${val[0]}`) ///- OPTIONS .column diff --git a/Shadowrun5thEdition/src/pug/_rolltemplates.pug b/Shadowrun5thEdition/src/pug/_rolltemplates.pug new file mode 100644 index 0000000000..a81de2861b --- /dev/null +++ b/Shadowrun5thEdition/src/pug/_rolltemplates.pug @@ -0,0 +1,54 @@ +.rolltemplates + rolltemplate.sheet-rolltemplate-rolls + .sheet-template-container + //- Display a header on the template - + .sheet-template-header + | {{#header}} + h1 {{header}} + | {{/header}} + | {{#base}} + span {{base}} + | {{/base}} + | {{#rollLess() wound 0}} + span ♦ + span(data-i18n="wounds") + | {{/rollLess() wound 0}} + | {{#rollLess() mod 0}} + span ♦ + span(data-i18n="modifier") + | {{/rollLess() mod 0}} + | {{#rollGreater() mod 0}} + span ♦ + span(data-i18n="modifier") + | {{/rollGreater() mod 0}} + | {{#rollGreater() edge 0}} + span ♦ + span(data-i18n="edge") + | {{/rollGreater() edge 0}} + //- Display the dice roll in the template - + .sheet-template-body + | {{#dice}} + .sheet-template-row + span.inlinerollresult {{dice}} + | {{/dice}} + //- Display a description. This is great for text included with a roll - + | {{#desc}} + .sheet-template-row + span.sheet-template-desc + | {{desc}} + | {{#rollGreater() rea 0}} + span , + span(data-i18n="reach") + | {{rea}} + | {{/rollGreater() rea 0}} + | {{#rollGreater() drain 1}} + span , + span(data-i18n="drain") + | {{drain}} + | {{/rollGreater() drain 1}} + | {{#rollLess() drain 2}} + span , + span(data-i18n="drain-2") + | {{drain}} + | {{/rollLess() drain 2}} + | {{/desc}} diff --git a/Shadowrun5thEdition/src/pug/_variables.pug b/Shadowrun5thEdition/src/pug/_variables.pug index 4af65e561f..4d5536e9c3 100644 --- a/Shadowrun5thEdition/src/pug/_variables.pug +++ b/Shadowrun5thEdition/src/pug/_variables.pug @@ -31,12 +31,12 @@ //- PC MAGIC - const pcCoreSpellObject = {'Name': {'type': 'text', 'placeholder': 'Fireball'}, 'Type': {'type': 'select', 'default': 'physical', 'array': spellTypes}, 'Range': {'type': 'select', 'default': 'los', 'array':spellRanges}, 'Duration': {'type': 'select', 'default': 'instant', 'array':spellDurations}, 'Drain': {'type': 'number', 'placeholder': '-1'}}; -- const pcCatagorySpellObject = {'Category': {'type': 'select', 'default': 'combat', 'array': spellCatagories}, 'Combat': {'type': 'select', 'default': 'force', 'array':spellCombatTypes}, 'Damage': {'type': 'text', 'placeholder': 'P'}}; +- const pcCatagorySpellObject = {'Category': {'type': 'select', 'default': 'Combat', 'array': spellCatagories}, 'Combat': {'type': 'select', 'default': 'force', 'array':spellCombatTypes}, 'Damage': {'type': 'text', 'placeholder': 'P'}}; - const pcAlchemySpellObject = {'Skill': {'type': 'select', 'default': '@{alchemy}', 'array':['Enchanting Group', 'Alchemy']}, 'Specialization': {'type': 'checkbox', 'default': '2'}, 'modifier dice': {'type': 'number', 'placeholder': '0', 'default': '0'}}; - const pcSorcerySpellObject = {'Skill': {'type': 'select', 'default': '@{spellcasting}', 'array':['Sorcery Group', 'Spellcasting']}, 'Specialization': {'type': 'checkbox', 'default': '2'}, 'modifier dice': {'type': 'number', 'placeholder': '0', 'default': '0'}}; //- PC MATRIX -- const pcComplexFormButton = {'name': 'complex_form', 'header': '@{name}', 'rollFormula': '@{skill}+@{dicepool}+@{resonance}', 'desc': '{{desc=Level ?{Level|}, Fade [[?{Level|}+(@{fade})]]}}', 'display': 'name'}; +- const pcComplexFormButton = {'name': 'complex_form', 'header': '@{name}', 'rollFormula': '@{skill}+@{dicepool}+@{resonance}', 'desc': '{{desc=Level ?{Level|}, Fade [[?{Level|}+(@{fade})]] [f](~repeating_forms_fade)}}', 'display': 'name'}; //- PC WEAPONS - const pcRangeWeaponObject = {'Weapon': {'type': 'text', 'placeholder': 'Ares Predator'}, 'Dam': {'type': 'text', 'placeholder': '9P'}, 'ACC': {'type': 'text', 'placeholder': '5'}, 'AP': {'type': 'number', 'placeholder': '-2'}, 'Mode': {'type': 'select', 'default': 'SS', 'array':weaponModes}, 'Recoil': {'type': 'number', 'placeholder': '+2'},'Ammo': {'type': 'number', 'placeholder': '15'}}; diff --git a/Shadowrun5thEdition/src/pug/tabs/arms.pug b/Shadowrun5thEdition/src/pug/tabs/arms.pug new file mode 100644 index 0000000000..af239722eb --- /dev/null +++ b/Shadowrun5thEdition/src/pug/tabs/arms.pug @@ -0,0 +1,155 @@ +.arms.pc-col + .pc-row.weapons + .header.right-header + h1(data-i18n='weapons') Weapons + .right-tri + .header.right-header + .header.htab + .triangle + input.tab-switch(name='attr_weapon_type_toggle' type='radio' value='range' checked) + h1(data-i18n='ranged') Ranged + .right-tri + .header.htab + .triangle + input.tab-switch(name='attr_weapon_type_toggle' type='radio' value='melee') + h1(data-i18n='melee') Melee + .right-tri + .border-box + .pc-box.medium-box + input.tab-switch(name='attr_weapon_type_toggle' type='hidden' value='range') + .rows.repeating-container.weapon-range + - const rangeRepeatingSection = '@{repeating_range_${x}'; + +h2Headers(pcRangeWeaponObject) + fieldset(class='repeating_range') + input(name='attr_dicepool' type='hidden' value='0') + input.flag-primary(name='attr_primary' type='hidden' value='') + +weaponRollButton(pcRangeWeaponButton) + each val in ['Dam', 'Acc', 'AP', 'Mode', 'RC', 'Ammo'] + - const attrName = val === 'Dam' ? 'damage' : val === 'RC' ? 'recoil' : val.toLowerCase(); + if val === 'Mode' + select(name='attr_mode' title='@{mode}' value='BF') + each val in weaponModes + option(data-i18n=val.toLowerCase() value=val) #{val} + else + span.text-center(name=`attr_${attrName}`) + +repeatingSectionFlags() + .settings + each val, key in pcRangeWeaponObject + - const attrName = key === 'Dam' ? 'damage' : key.toLowerCase(); + if key === 'Mode' + select(name='attr_mode' title='@{mode}' value='BF') + each val in weaponModes + option(data-i18n=val.toLowerCase() value=val) #{val} + else + label(data-i18n-title=key.toLowerCase() title=key.toLowerCase()) + input(name=`attr_${attrName}` placeholder=val['placeholder'] title=`${rangeRepeatingSection}_${attrName}}` type=val['type'] value='') + .row + h3(data-i18n='modeoptions') Mode Options + label(data-i18n-title='modeoptions' title='Mode Options') + input(name='attr_mode_options' placeholder='SA/BF/FA' type='text' title=`${rangeRepeatingSection}_mode_options}}`) + h3(data-i18n='range') range + label(data-i18n-title='range' title='Range') + input(name='attr_range' placeholder='25/150/350/550' type='text' title='') + h3(data-i18n='primary') primary + label(data-i18n-title='primary' title='Primary') + input(name='attr_primary' type='checkbox' title=`${rangeRepeatingSection}_primary}` value='primary') + + .row + h3(data-i18n='skill') skill + select(name=`attr_skill` title=`${rangeRepeatingSection}_skill}` value='@{firearms}') + optgroup(label='Combat Skills' ) Combat Skills + option(data-i18n='firearmsgroup' value='@{firearms}' selected) Firearms Group + option(data-i18n='automatics' value='@{automatics}') Automatics + option(data-i18n='archery' value='@{archery}') Archery + option(data-i18n='exoticrange' value='0') Exotic Range + option(data-i18n='heavyweapons' value='@{heavyweapons}') Heavy Weapons + option(data-i18n='longarms' value='@{longarms}') Longarms + option(data-i18n='pistols' value='@{pistols}') Pistols + option(data-i18n='throwingweapons' value='@{throwingweapons}') Throwing Weapons + optgroup(label='Vehicle Skills') Vehicle Skills + option(data-i18n='gunnery' value='@{gunnery}') Gunnery + h3(data-i18n='specialization') specialization + label(data-i18n-title='specialization' title='specialization') + input(name='attr_specialization' value='2' title=`${rangeRepeatingSection}_specialization}` type='checkbox') + h3(data-i18n='modifier') modifier + label(data-i18n-title='modifier' title='modifier') + input(name='attr_dicepool_modifier' title=`${rangeRepeatingSection}_dicepool_modifier}` type='number') + input(name=`attr_skill` type='hidden' value='') + .exotic-warning + i(data-i18n='exoticnote') Exotic weapons are not linked to a skill. Use Modifier input to set dicepool. + +repeatingSectionNotes('range') + .rows.repeating-container.weapon-melee + - const meleeRepeatingSection = '@{repeating_melee_${x}'; + +h2Headers(pcMeleeWeaponObject) + fieldset(class='repeating_melee') + input(name='attr_dicepool' type='hidden' value='0') + input.flag-primary(name='attr_primary' type='hidden' value='') + +weaponRollButton(pcMeleeWeaponButton) + each val in ['Dam', 'Acc', 'AP', 'Reach'] + - const attrName = val === 'Dam' ? 'damage' : val.toLowerCase(); + span.text-center(name=`attr_${attrName}`) + +repeatingSectionFlags() + .settings + each val, key in pcMeleeWeaponObject + - const attrName = key === 'Dam' ? 'damage' : key.toLowerCase(); + label(data-i18n-title=key.toLowerCase() title=key.toLowerCase()) + input(name=`attr_${attrName}` placeholder=val['placeholder'] title=`${meleeRepeatingSection}_${attrName}}` type=val['type'] value='') + h3(data-i18n='primary') primary + label(data-i18n-title='primary' title='Primary') + input(name='attr_primary' type='checkbox' title=`${meleeRepeatingSection}_primary}` value='primary') + .row + h3(data-i18n='skill') skill + select(name=`attr_skill` title=`${meleeRepeatingSection}_skill}` value='@{closecombat}') + optgroup(label='Combat Skills' ) Combat Skills + option(data-i18n='closecombatgroup' value='@{closecombat}' selected) Close Combat Group + option(data-i18n='blades' value='@{blades}') Blades + option(data-i18n='clubs' value='@{clubs}') Clubs + option(data-i18n='exoticmelee' value='0') Blades + option(data-i18n='unarmedcombat' value='@{unarmedcombat}') Unarmed Combat + optgroup(label='Vehicle Skills') Vehicle Skills + option(data-i18n='gunnery' value='@{gunnery}') Gunnery + h3(data-i18n='specialization') specialization + label(data-i18n-title='specialization' title='specialization') + input(name='attr_specialization' value='2' title=`${meleeRepeatingSection}_specialization}` type='checkbox') + h3(data-i18n='modifier') modifier + label(data-i18n-title='modifier' title='modifier') + input(name='attr_dicepool_modifier' title=`${meleeRepeatingSection}_dicepool_modifier}` type='number') + input(name=`attr_skill` type='hidden' value='') + .exotic-warning + i(data-i18n='exoticnote') Exotic weapons are not linked to a skill. Use Modifier input to set dicepool. + +repeatingSectionNotes('melee') + .pc-row.armor + .header.right-header + h1(data-i18n='armor') Armor + .right-tri + .border-box + .pc-box.medium-box + .rows.repeating-container + - const armorRepeatingSection = '@{repeating_armor_${x}'; + .row-long.headers + each val in ['Armor', 'Rating', 'Acid', 'Cold', 'Elec', 'Fire', 'Radi'] + h2(data-i18n=`${val.toLowerCase()}`) #{val} + fieldset(class='repeating_armor') + input.flag-primary(name='attr_primary' type='hidden' value='') + button(name=`roll_soak` type='roll' value!=noWoundsRollBegining+'{{header=^{soak}}}{{base=^{body} ♦ ^{armor}}}{{dice=[[((@{body}+@{rating}+@{dicepool_modifier})'+noWoundsRollEnding) + span(name='attr_name') + button(name=`roll_armor` type='roll' value!=noWoundsRollBegining+'{{header=@{name}}}{{base= ^{armor}}}{{dice=[[((@{rating})'+noWoundsRollEnding) + span.text-center(name='attr_rating') + each val in ['Acid', 'Cold', 'Electrical', 'Fire', 'Radiation'] + - const attrName = val.toLowerCase(); + button(name=`roll_${attrName}` type='roll' value!=noWoundsRollBegining+`{{header=^{${attrName}protection}}}{{base= ^{armor}}}{{dice=[[((@{body}+@{rating}+@{dicepool_modifier}+@{${attrName}_modifier})`+noWoundsRollEnding) + span.text-center(name=`attr_${attrName}_modifier`) + +repeatingSectionFlags() + .settings + each val, key in pcArmorObject + - const attrName = key === 'Name' || key === 'Rating' ? key.toLowerCase() : `${key.toLowerCase()}_modifier`; + label(data-i18n-title=key.toLowerCase() title=key.toLowerCase()) + input(name=`attr_${attrName}` placeholder=val['placeholder'] title=`@{${armorRepeatingSection}_${attrName}}` type=val['type'] value='') + .row + h3(data-i18n='primary') primary + label(data-i18n-title='primary' title='Primary') + input(name='attr_primary' type='checkbox' title=`@{${armorRepeatingSection}_primary}` value='primary') + h3(data-i18n='modifier') modifier + label(data-i18n-title='modifier' title='modifier') + input(name='attr_dicepool_modifier' placeholder='0' title=`@{${armorRepeatingSection}_dicepool_modifier}` type='number' value='0') + +repeatingSectionNotes('armor') diff --git a/Shadowrun5thEdition/src/pug/tabs/augs.pug b/Shadowrun5thEdition/src/pug/tabs/augs.pug new file mode 100644 index 0000000000..0bd93906aa --- /dev/null +++ b/Shadowrun5thEdition/src/pug/tabs/augs.pug @@ -0,0 +1,28 @@ +.augs.pc-col + .pc-row + .header.right-header + h1(data-i18n='augmentations') Augmentations + .right-tri + .border-box + .pc-box.medium-box + .row-long.headers + each val in augementations + h2(data-i18n=`${val.toLowerCase()}`) #{val} + .rows.repeating-container + fieldset(class=`repeating_augementations`) + span(name=`attr_augmentation`) + span.text-center(name=`attr_rating`) + span.text-center(name=`attr_essence`) + +repeatingSectionFlags() + .settings + each val in augementations + - const attrName = val === 'Augmentations' ? 'augmentation' : val.toLowerCase(); + - const type = val === 'Augmentations' ? 'text' : 'number'; + - const placeholder = val === 'Augmentations' ? 'name' : '0'; + label(data-i18n-title=val title=val) + if type === 'text' + input.text-left(name=`attr_${attrName}` placeholder=placeholder title='@{repeating_augementations_${x}'+`_${attrName}}` type=type value='') + else + input.text-center(name=`attr_${attrName}` placeholder=placeholder title='@{repeating_augementations_${x}'+`_${attrName}}` type=type value='') + +repeatingSectionNotes('augementations') + diff --git a/Shadowrun5thEdition/src/pug/tabs/core.pug b/Shadowrun5thEdition/src/pug/tabs/core.pug new file mode 100644 index 0000000000..44ec2d69dc --- /dev/null +++ b/Shadowrun5thEdition/src/pug/tabs/core.pug @@ -0,0 +1,46 @@ +.core.pc-col + include ../../html/core.html + .quality-box + .header.right-header + .header.htab + input.tab-switch(input name='attr_quality_toggle' type='radio' value='quality' checked) + h1(data-i18n='qualities') Qualities + .right-tri + .header.htab + .triangle + input.tab-switch(input name='attr_quality_toggle' type='radio' value='martial') + h1(data-i18n='martialarts') Martial Arts + .right-tri + .border-box + .pc-box.medium-box + input.tab-switch(input name='attr_quality_toggle' type='hidden' value='quality') + .quality + .row-long.headers + each val in ['Quality', 'Type'] + h2(data-i18n=`${val.toLowerCase()}`) #{val} + .rows.repeating-container + fieldset(class='repeating_quality') + span.eclipse(name="attr_quality") + span.text-center(name="attr_type") + button.pictos(name="quality_chat" type="roll" value="@{gm_toggle} &{template:rolls}{{header=@{quality}}}{{desc=@{notes}}}") w + +repeatingSectionFlags() + .settings + input.text-left(name="attr_quality" placeholder="quality name" title="@{repeating_quality_${x}_quality}" type="text") + select(name="attr_type" title="@{repeating_quality_${x}_type}" value='p') + option(data-i18n="p" value="P" selected) P + option(data-i18n="n" value="N") N + +repeatingSectionNotes('quality') + .martial + .row-long.headers + each val in ['Technique', 'Style'] + h2(data-i18n=`${val.toLowerCase()}`) #{val} + .rows.repeating-container + fieldset(class='repeating_martial') + span.eclipse(name="attr_technique") + span.text-center(name="attr_style") + button.pictos(name="technique_chat" type="roll" value="@{gm_toggle} &{template:rolls}{{header=@{technique}}}{{desc=@{notes}}}") w + +repeatingSectionFlags() + .settings + input.text-left(name="attr_technique" placeholder="technique name" title="@{repeating_martial_${x}_technique}" type="text") + input(name="attr_style" placeholder="style name" title="@{repeating_martial_${x}_style}" type="text") + +repeatingSectionNotes('martial') diff --git a/Shadowrun5thEdition/src/pug/tabs/gear.pug b/Shadowrun5thEdition/src/pug/tabs/gear.pug new file mode 100644 index 0000000000..27b4f66f4e --- /dev/null +++ b/Shadowrun5thEdition/src/pug/tabs/gear.pug @@ -0,0 +1,31 @@ +.gear.pc-col + .pc-row + .header.right-header + h1(data-i18n='gear') gear + .right-tri + .border-box + .pc-box.medium-box + .row-long.headers + each val in ['Item', 'Rating', 'Quantity'] + h2(data-i18n=`${val.toLowerCase()}`) #{val} + .rows.repeating-container + fieldset(class=`repeating_items`) + //-input.toggle.indicator(name='attr_gear_on_character' type='checkbox' checked) + //-span.pictos(title='on character') U + select.pictos(name='attr_location' value='person') + each val, key in {'person':'U', 'bag': 'O', 'home':'H', 'vehicle':'X', 'other':'.'} + option.pictos(value=key) #{val} + input(name='attr_location' type='hidden' value='person') + span.text-left(name=`attr_item`) + span.text-center(name=`attr_rating`) + span.text-center(name=`attr_quantity`) + +repeatingSectionFlags() + .settings + label(data-i18n-title='item' title='item') + input.text-left(name=`attr_item` placeholder='Jammer' title=`@{repeating_items_`+'${x}'+`_item}` type='text' value='') + label(data-i18n-title='rating' title='rating') + input(name=`attr_rating` placeholder='3' title='@{repeating_items_${x}_rating}' type='text' value='') + label(data-i18n-title='quantity' title='quantity') + input(name=`attr_quantity` placeholder='x3' title='@{repeating_items_${x}_quantity}' type='text' value='') + +repeatingSectionNotes('items') + diff --git a/Shadowrun5thEdition/src/pug/tabs/magic.pug b/Shadowrun5thEdition/src/pug/tabs/magic.pug new file mode 100644 index 0000000000..11946d4482 --- /dev/null +++ b/Shadowrun5thEdition/src/pug/tabs/magic.pug @@ -0,0 +1,101 @@ +//- MAGIC TAB +.magic.pc-col + .pc-row.spell-box + .header.right-header + h1(data-i18n='magic') Magic + .right-tri + .header.right-header + each val in ['spells', 'preps', 'rituals'] + .header.htab + .triangle + if (val === 'spells') + input.magic-toggle(name='attr_magic_toggle' title='@{magic_toggle}' type='radio' value=val checked) + else + input.magic-toggle(name='attr_magic_toggle' title='@{magic_toggle}' type='radio' value=val) + h1(data-i18n=val) + .right-tri + .border-box + .pc-box.medium-box + +fadeDrainSection('drain') + input.magic-toggle(name='attr_magic_toggle' type='hidden' value='spells') + .row-long.headers + each val in ['spells', 'type', 'range', 'duration', 'drain'] + h2(data-i18n=val) #{val} + + .magic-spells.spellsForumlas + +pcSpells('spell') + + .magic-preps.spellsForumlas + +pcSpells('preps') + + .rows.repeating-container.prepared-preparations + h2(data-i18n='preperations') + .row-long.headers + each val in ['name', 'force', 'potency', 'trigger'] + h3(data-i18n=val) + fieldset(class='repeating_preperations') + +displayRollButton(prepButton, false) + each val in ['force', 'potency', 'trigger'] + span.text-center(name=`attr_${val}`) + +repeatingSectionFlags() + .settings + label(data-i18n-title='name' title='name') + input(name='attr_name' placeholder='Name' title='@{repeating_preperations_${x}_name}' type='text' value='') + label(data-i18n-title='force' title='force') + input(name='attr_force' placeholder='1' title='@{repeating_preperations_${x}_force}' type='number' value='') + label(data-i18n-title='potency' title='potency') + input(name='attr_potency' placeholder='1' title='@{repeating_preperations_${x}_potency}' type='number' value='') + select(name='attr_trigger' title='@{repeating_preperations_${x}_trigger}' value='Command') + optgroup(label='Trigger') Trigger + option(data-i18n='command' value='Command') command + option(data-i18n='contact' value='Contact' selected) contact + option(data-i18n='time' value='Time') time + option(data-i18n='special' value='Special') special + +repeatingSectionNotes('preperations') + + .magic-rituals + .rows.repeating-container + fieldset(class=`repeating_ritual`) + - const repeatingRitualSection = `@{repeating_${type}`+'_${x}'; + input(name='attr_dicepool' type='hidden' value='0') + +displayRollButton(pcRitualButton, true) + each val in ['type', 'range', 'duration', 'drain'] + span.text-center(name='attr_'+val) + +repeatingSectionFlags() + .settings + label(data-i18n-title='name' title='name') + input(name='attr_name' placeholder='Curse (MATERIAL LINK, SPELL)' title=`@{${repeatingRitualSection}_name}` type='text') + .rows + h3(data-i18n='skill') skill + select(name='attr_skill' title=`@{${repeatingRitualSection}_skill}`) + option(data-i18n='sorcerygroup' value='@{sorcery}') Sorcery Group + option(data-i18n='ritualspellcasting' value='@{ritualspellcasting}' selected) Ritual Spellcasting + h3(data-i18n='specialization') specialization + label(data-i18n-title='specialization' title='specialization') + input(name='attr_specialization' title=`@{${repeatingRitualSection}_specialization}` type='checkbox' value='2') + h3(data-i18n='modifier') modifier + label(data-i18n-title='modifier' title='modifier') + input(name='attr_dicepool_modifier' title=`@{${repeatingRitualSection}_dicepool_modifier}` type='number') + +repeatingSectionNotes('ritual') + + .pc-row.powers + .header.right-header + h1(data-i18n='adeptpowers') Adept Powers or Other Abilities + .right-tri + .border-box + .pc-box.medium-box + +fadeDrainSection('drain', true) + .row-long.headers + h2(data-i18n='name') Name + h2.text-center(data-i18n='rating') Rating + .rows.repeating-container.powers + fieldset(class=`repeating_powers`) + span(name='attr_name') + span.text-center(name='attr_rating') + +repeatingSectionFlags() + .settings + label(data-i18n-title='name' title='name') + input(name='attr_name' placeholder='name' title='@{repeating_powers_${x}_name}' type='text' value='') + label(data-i18n-title='rating' title='rating') + input(name='attr_rating' placeholder='rating' title='@{repeating_powers_${x}_rating}' type='number' value='') + +repeatingSectionNotes('powers') diff --git a/Shadowrun5thEdition/src/pug/tabs/matrix.pug b/Shadowrun5thEdition/src/pug/tabs/matrix.pug new file mode 100644 index 0000000000..260236ece7 --- /dev/null +++ b/Shadowrun5thEdition/src/pug/tabs/matrix.pug @@ -0,0 +1,68 @@ +.matrix.pc-col + .pc-row.matrix-box + .header.right-header + h1(data-i18n='cyberdeck') Cyberdeck + .right-tri + .border-box + .pc-box.medium-box + .cyberdeck + include ../../html/matrix.html + .rows.repeating-container.programs + h2(data-i18n='programs') Programs + fieldset(class=`repeating_programs`) + input.toggle.indicator(name='attr_program_on' type='checkbox' checked) + span.pictos Q + span.eclipse(name='attr_program') + button.pictos(name="program_chat" type="roll" value="@{gm_toggle} &{template:rolls}{{header=@{program}}}{{desc=@{notes}}}") w + +repeatingSectionFlags() + .settings + label(data-i18n-title='programs' title='programs') + input(name='attr_program' placeholder='Program name' title='@{repeating_programs_${x}_program}' type='text' value='') + +repeatingSectionNotes('programs') + .pc-row + .header.right-header + h1(data-i18n='complex form') Complex Forms + .right-tri + .border-box + .pc-box.medium-box + +fadeDrainSection('fade') + .rows.repeating-container.complex-forms + - const formsrepeatingSection = `@{repeating_forms_` + "${x}"; + .row-long.headers + each val in complexFormAttributes + h2.text-capitalize(data-i18n=val) + fieldset(class=`repeating_forms`) + input(name='attr_dicepool' type='hidden' value='0') + + //- This button displays in the roll template in chat window + button.display-none(name="roll_fade" type="roll" value="@{gm_toggle} &{template:rolls}{{mod=[[@{modifiers_toggle}]]}}{{edge=[[@{edge_toggle}]]}}{{header=^{fade}}}{{base=^{base}}}{{dice=[[((@{fade_attribute_1}+@{fade_attribute_2}+@{fade_modifier})+@{modifiers_toggle}+@{edge_toggle})d6>5@{explode_toggle}]]}}") + + +displayRollButton(pcComplexFormButton, true) + - const complexFormSpans = complexFormAttributes.shift(); + each val in complexFormSpans + span.text-center.eclipse(name=`attr_${val}`) + +repeatingSectionFlags() + .settings + label(data-i18n-title='name' title='name') + input(name='attr_name' placeholder='name' title=`${formsrepeatingSection}_name}` type='text' value='') + select(name=`attr_target` title=`${formsrepeatingSection}_target}` value='Device') + each val in formTargets + option.text-capitalize(data-i18n=val value=val) #{val} + select(name=`attr_duration` title=`${formsrepeatingSection}_duration}` value='Instant') + each val in formDurations + option.text-capitalize(data-i18n=val value=val) + label(data-i18n-title='fade' title='fade') + input(name='attr_fade' placeholder='-1' title=`${formsrepeatingSection}_fade}` type='number' value='') + .row + h3(data-i18n='skill') skill + select(name=`attr_skill` title=`${formsrepeatingSection}_skill}` value='@{software}') + option(data-i18n='electronicsgroup' value='@{electronics}') Electronics Group + option(data-i18n='software' value='@{software}' selected) Software + h3(data-i18n='specialization') + label(data-i18n-title='specialization' title='specialization') + input(name='attr_specialization' value='2' title=`${formsrepeatingSection}_specialization}` type='checkbox') + h3(data-i18n='modifier') modifier + label(data-i18n-title='modifier' title='modifier') + input(name='attr_dicepool_modifier' title=`${formsrepeatingSection}_dicepool_modifier}` type='number') + +repeatingSectionNotes('forms') + diff --git a/Shadowrun5thEdition/src/pug/tabs/social.pug b/Shadowrun5thEdition/src/pug/tabs/social.pug new file mode 100644 index 0000000000..db7223c8fd --- /dev/null +++ b/Shadowrun5thEdition/src/pug/tabs/social.pug @@ -0,0 +1,69 @@ +.social.pc-col + .pc-row + .header.right-header + h1(data-i18n="idslifestylecurrency") + .right-tri + .border-box.lifestyle + .pc-box.small-box + .row-long + h3(data-i18n="primarylifestyle") + input.text-left(name="attr_primary_lifestyle" placeholder="Middle /w GRID subscription" style="width: 77%" title="@{primary_lifestyle}" type="text") + .row-long + h3(data-i18n="nuyen") + input.text-left(type="text" name="attr_primary_nuyen" placeholder="$1,000 UCAS" style="width: 90%" title="@{primary_nuyen}") + .row-long + h3(data-i18n="licenses") + input.text-left(type="text" name="attr_primary_licenses" placeholder="Technomancer, Pistols..." style="width: 87%" title="@{primary_licenses}") + .row-long.headers + h2(data-i18n="fakeidsrelated") + .rows.repeating-container + fieldset(class='repeating_lifestyle') + span.eclipse(name="attr_name") + button.pictos(name="lifestyle_chat" type="roll" value="@{gm_toggle} &{template:rolls}{{header=@{name}}}{{desc=^{relatedlifestyle} @{lifestyle} , ^{nuyen} @{funds}, ^{licenses} @{licenses}}}") w + input.collapse-flag(name='attr_display_flag' type='checkbox') + span.pictos i + input.settings-flag(name='attr_flag' title='Settings toggle' type='checkbox' checked) + span.pictos x + .collapse + .rows + h3(data-i18n="relatedlifestyle") + span(name='attr_lifestyle') + .rows + h3(data-i18n="nuyen") + span(name='attr_funds') + .rows + h3(data-i18n="licenses") + span(name='attr_licenses') + .settings + h3(data-i18n="fakeid") + input.text-left(name="attr_name" placeholder="John Doe" title="@{repeating_lifestyle_${x}_name}" type='text') + h3(data-i18n="relatedlifestyle") + textarea(name="attr_lifestyle" placeholder="Middle" title="@{repeating_lifestyle_${x}_lifestyle}") + h3(data-i18n="funds") + textarea(name="attr_funds" placeholder="$1,000 UCAS" title="@{repeating_lifestyle_${x}_funds}") + h3(data-i18n="licenses") + textarea(name="attr_licenses" placeholder="Technomancer, Pistols" title="@{repeating_lifestyle_${x}_licenses}") + .pc-row + .header.right-header + h1(data-i18n="contacts") + .right-tri + .border-box.contacts + .pc-box.small-box + .row-long.headers + each val in ['name', 'loyalty', 'connection', 'favor'] + h2(data-i18n=`${val.toLowerCase()}`) #{val} + .rows.repeating-container + fieldset(class='repeating_contacts') + span.eclipse(name="attr_name") + span.text-center(name="attr_loyalty") + span.text-center(name="attr_connection") + span.text-center(name="attr_favors") + button.pictos(name="ontact_chat" type="roll" value="@{gm_toggle} &{template:rolls}{{header=@{name}}}{{desc=^{loyalty} @{loyalty} , ^{connection} @{connection}, ^{favor} @{favors}}}") w + +repeatingSectionFlags() + .settings + input(type="text" name="attr_name" placeholder="Old Crow" title="@{repeating_contacts_${x}_name}") + input(type="number" name="attr_loyalty" min="1" placeholder="3" title="@{repeating_contacts_${x}_name}") + input(type="number" name="attr_connection" min="1" placeholder="8" title="@{repeating_contacts_${x}_name}") + input(type="number" name="attr_favors" placeholder="+2" title="@{repeating_contacts_${x}_name}") + +repeatingSectionNotes('contacts') + diff --git a/Shadowrun5thEdition/src/pug/tabs/static.pug b/Shadowrun5thEdition/src/pug/tabs/static.pug new file mode 100644 index 0000000000..a9b562d5a0 --- /dev/null +++ b/Shadowrun5thEdition/src/pug/tabs/static.pug @@ -0,0 +1,78 @@ +.static.pc-col + include ../../static.html + //- SKILLS + .pc-row + .header + - const skillTypes = {'Active': 'active', 'Knowledge': 'know', 'Language': 'lang'} + each val, key in skillTypes + - const attrName = key.toLowerCase(); + .header.htab + .triangle + input.tab-switch(name='attr_skill_toggle' title=key + ' skills' type='radio' value=attrName) + h1(data-i18n=val) #{val}.. + .right-tri + .triangle + h1(data-i18n='skills') Skills + .border-box.skill-box + .pc-box.medium-box + .rows.repeating-container + .row-long.headers + each val in ['Skill', 'RTG', 'Attribute', 'Limit'] + - const translationKey = val.toLowerCase(); + h2(data-i18n=translationKey) #{val} + input.tab-switch(name='attr_skill_toggle' type='hidden' value='active') + each val, key in {'active': ['active', 'Agility', 'Physical'],'knowledge':['know', 'Logic', 'Mental'], 'language': ['lang', 'Charisma', 'Social']} + div(class=`skills-${val[0]}`) + .rows.repeating-container + if key === 'active' + .row-long + input(name='attr_default_display' type='hidden' value='Agility') + +rollButton('default', '@{default_display}', '@{default_attribute}+-1') + span.text-center - + select.attribute-select(name='attr_default_attribute' title='Skill attribute') + +attributeSelect('Agility') + select.limit-select(name='attr_limit' title='Skill limit') + +limitSelect('Physical') + fieldset(class=`repeating_${key}`) + - const skillsRepeatingSection = `@{repeating_${key}`+'_${x}'; + + input(name='attr_display_rating' type='hidden') + input(name='attr_specialization' type='hidden' value='') + input(name='attr_display_limit' type='hidden' value=val[2]) + input(name='attr_display_attribute' type='hidden' value=val[1]) + input(name='attr_dicepool' type='hidden' value='0') + + if key === 'active' + input(name='attr_display_skill' type='hidden' value='') + + input.settings-flag(name='attr_flag' type='hidden' value='settings' title=`${skillsRepeatingSection}_flag}`) + .buttons + //- SKILL BUTTON + +skillButton(false, key) + //- SPECILIZATION BUTTON + +skillButton(true) + span.text-center(name='attr_display_rating' title=`${skillsRepeatingSection}_display_rating}`) + select.attribute-select(name='attr_attribute' title=`${skillsRepeatingSection}_attribute}`) + +attributeSelect(val[1]) + select.limit-select(name='attr_limit' value='physical_limit' title=`${skillsRepeatingSection}_limit}`) + +limitSelect(val[2]) + +repeatingSectionFlags() + .settings + if key === 'active' + select.skill-select(name='attr_skill' value='Close Combat Group' title=`${skillsRepeatingSection}_skill}`) + include ../../html/skillselect.html + else + label(data-i18n-title='skill' title='skill') + input(name='attr_skill' placeholder=key type='text' title=`${skillsRepeatingSection}_skill}`) + label(data-i18n-title='rating' title='rating') + input(name='attr_rating' min='0' placeholder='0' type='number' title=`${skillsRepeatingSection}_rating}`) + label(data-i18n-title='ratingmodifier' title='Rating Modifier') + span(data-i18n='ratingmodifier') Rating Modifier + input(name='attr_rating_modifier' placeholder='0' type='number' title=`${skillsRepeatingSection}_rating_modifier}`) + label(data-i18n-title='specialization' title='specialization') + span(data-i18n='specialization') specialization + input(name='attr_specialization' placeholder='Specalizations' type='text' title=`${skillsRepeatingSection}_specialization}`) + label(data-i18n-title='notes' title='notes') + span(data-i18n='notes') Notes + textarea(name='attr_notes' value='' placeholder='Notes' title=`${skillsRepeatingSection}_notes}`) + diff --git a/Shadowrun5thEdition/src/pug/tabs/vehicle.pug b/Shadowrun5thEdition/src/pug/tabs/vehicle.pug new file mode 100644 index 0000000000..05e1d5decb --- /dev/null +++ b/Shadowrun5thEdition/src/pug/tabs/vehicle.pug @@ -0,0 +1,79 @@ +.vehicle.pc-col + .pc-row + .header.right-header + h1(data-i18n='vehicle') Vehicle + .right-tri + .border-box + .pc-box.medium-box + .rows.repeating-container + fieldset(class=`repeating_vehicle`) + each val in ['handling', 'handling_off', 'acceleration', 'speed', 'pilot', 'body', 'armor', 'sensor'] + input(name=`attr_${val}` type='hidden') + .row-long.grid.vehicle-name + span(name="attr_name") + .row-long.grid.2column + .col + h3(data-i18n='handling') + span(name="attr_display_handling") + .col + h3(data-i18n='handling_off') + span(name="attr_display_handling_off") + .row-long.grid.2column + .col + h3(data-i18n='acceleration') + span(name="attr_display_acceleration") + .col + h3(data-i18n='speed') + span(name="attr_display_speed") + .row-long.grid.2column + .col + h3(data-i18n='pilot') + span(name="attr_display_pilot") + .col + h3(data-i18n='body') + span(name="attr_display_body") + .row-long.grid.2column + .col + h3(data-i18n='armor') + span(name="attr_display_armor") + .col + h3(data-i18n='sensor') + span(name="attr_display_sensor") + +repeatingSectionFlags() + .settings + .row-long.grid.2autocolumn + h3(data-i18n="name") + label(data-i18n-title="vehicle name") + input(name="attr_name" placeholder="name" title="vehicle name" type="text" ) + .row-long.2column + .col + +repeatingPCVehicles('handling') + .col + +repeatingPCVehicles('handling_off') + .row-long.2column + .col + +repeatingPCVehicles('acceleration') + .col + +repeatingPCVehicles('speed') + .row-long.2column + .col + +repeatingPCVehicles('pilot') + .col + +repeatingPCVehicles('body') + .row-long.2column + .col + +repeatingPCVehicles('armor') + .col + +repeatingPCVehicles('sensor') + .row-long.2column.headers + .col + each val in ['base', 'mod', 'temp'] + h2.text-capitalize.text-center(data-i18n=`${val}`) + .col + each val in ['base', 'mod', 'temp'] + h2.text-capitalize.text-center(data-i18n=`${val}`) + +repeatingSectionNotes('vehicle') + + + + diff --git a/Shadowrun5thEdition/src/rolltemplates.html b/Shadowrun5thEdition/src/rolltemplates.html deleted file mode 100644 index 8f04413348..0000000000 --- a/Shadowrun5thEdition/src/rolltemplates.html +++ /dev/null @@ -1,28 +0,0 @@ -
- - -
-
- {{#header}}{{header}}{{/header}}{{#spec}} ({{spec}}){{/spec}}
- {{#arm}}{{arm}}{{/arm}} - {{#base}}{{base}}{{/base}} - {{#rollLess() wound 0}} ♦ Wounds{{/rollLess() wound 0}} - {{#rollLess() mod 0}} ♦ Modifier{{/rollLess() mod 0}} - {{#rollGreater() mod 0}} ♦ Modifier{{/rollGreater() mod 0}} - {{#rollGreater() edge 0}} ♦ Edge{{/rollGreater() edge 0}} -
- {{#dice}}
{{dice}}
{{/dice}} - {{#desc}} -
- - {{desc}} - {{#rollGreater() rea 0}}, Reach {{rea}}{{/rollGreater() rea 0}} - {{#rollGreater() drain 1}}, Drain {{drain}}{{/rollGreater() drain 1}} - {{#rollLess() drain 2}}, Drain 2{{/rollLess() drain 2}} - -
- {{/desc}} - {{#opp}}
{{opp}}
{{/opp}} -
-
-
diff --git a/Shadowrun5thEdition/src/scss/_global.scss b/Shadowrun5thEdition/src/scss/_global.scss deleted file mode 100644 index 8b5598a49f..0000000000 --- a/Shadowrun5thEdition/src/scss/_global.scss +++ /dev/null @@ -1,128 +0,0 @@ - * { - box-sizing: border-box; - font-family: sans-serif;} - - button { - background-image: none; - font-size : 0.8em; - text-shadow : none; - - &[type='roll'], - &[type='action'] { - font-size: 1em; - margin: 0px !important; - padding: 1px 2px; - - border: { - bottom : 0.01em solid #666; - bottom-right-radius: 0.01em; - color : hsl(0, 0%, 70%); - radius : 0.25em !important; - right : 0.02em solid hsl(0, 0%, 20%); - style : outset; - } - } - - &:before {display: none;} - &:hover, &:focus, &:active { - font-weight : bold; - background-color: $gold; - } - - & > span { - display: block; - overflow: hidden; - text-overflow: ellipsis; - width: 100%; - } - } - - div {background-color: transparent;} - - fieldset { background: transparent;} - - hr { - border: 0.5px solid #555; - } - - label { - display: inline-block; - font-size: 0.9em; - margin-bottom: 0px; - padding-right: 5px; - text-transform: capitalize; - width: auto;} - - input { - background-color: $lightgray; - color: $blacker; - border: none; - cursor: auto; - font-weight: normal; - margin: 0px; - text-align: center; - vertical-align: middle; - - &[type='text'], - &[type='number'] { - height : 20px; - - &:hover, &:focus { - background-color: #d2d1cd; - color: $blackish; - } - - &:placeholder-shown { - border: 1px dotted $gray; - background-color: $graytrans; - color: white; - } - } - - &::-webkit-outer-spin-button, - &::-webkit-inner-spin-button { - -webkit-appearance: none; - margin: 0; - } - } - - select { - border-radius: 2px; - border: 1px solid #000; - box-shadow: inset 0px 0px 3px 1px #7c7c7c; - margin-bottom: 0px; - width: auto;} - - span { word-break: break-word; } - - textarea { - border-radius: 2px; - border: 1px solid #000; - box-shadow: inset 0px 0px 3px 1px #7c7c7c; - height: 50px; - overflow-wrap: break-word; - overflow: hidden; - resize: vertical; - vertical-align: top; - white-space: pre-line;} - - .charsheet { width: 850px; } - - .sheet-red {color: $red; } - .sheet-text-align-center {text-align: center;} - - input[name='attr_stats_toggle'], - input[name='attr_stats_toggle'] + span { - position: relative; - } - - input[name='attr_stats_toggle'] { - opacity: 0; - z-index: 2; - } - - .sheet-eclipse { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } diff --git a/Shadowrun5thEdition/src/scss/_hide.scss b/Shadowrun5thEdition/src/scss/_hide.scss index 4bb7232111..b53a97977b 100644 --- a/Shadowrun5thEdition/src/scss/_hide.scss +++ b/Shadowrun5thEdition/src/scss/_hide.scss @@ -1,16 +1,4 @@ - %display-none { display: none; } - %display-inline { display: inline; } - %display-inline-grid { display: inline-grid; } - - %display-grid { display: grid; } - - .sheet-pictos { font-family: 'Pictos'; } - - %display-inline-block, - .sheet-static { - display: inline-block; - } /***** PC AND NPC *****/ @each $characterType in $characterTypes { @@ -24,8 +12,13 @@ /***** TABS *****/ @each $tab in $tabs { - .sheet-#{$tab} { @extend %display-none; } - .sheet-options_toggle[value='#{$tab}'] ~ .sheet-#{$tab} { @extend %display-inline-block; } + .sheet-options_toggle[value='#{$tab}'] ~ .sheet-#{$tab} { + @extend %display-inline-block; + } + + .sheet-options_toggle:not([value='#{$tab}']) ~ .sheet-#{$tab} { + @extend %display-none; + } } /***** SWITCH BETWEEN DIFFERENT TABS *****/ @@ -52,8 +45,9 @@ } /***** SETTINGS *****/ - div.sheet-collapse, - .sheet-settings { @extend %display-none; } + .sheet-settings { + @extend %display-none; + } input[name='attr_stats_toggle'][value='settings'] ~ .sheet-attribute .sheet-settings, input[name='attr_stats_toggle'][value='settings'] ~ .sheet-body .sheet-column .sheet-settings, @@ -85,8 +79,9 @@ /* NEW REPEATING CONTAINER WAY TO SHOW & HIDE SETTINGS */ /* SLOWLY ELIMINATE ALL TRACES OF SETTINGS-TOGGLE WITH THIS WAY OF DOING THINGS */ - input.sheet-settings-flag:checked ~ div.sheet-settings { display : inherit; } - input.sheet-collapse-flag:checked ~ div.sheet-collapse { display: block; } + input.sheet-settings-flag:checked ~ div.sheet-settings { + display : inherit; + } /* OLD WAY TO SHOW & HIDE THINGS */ input.sheet-settings-toggle[value='display'] ~ .sheet-settings { @extend %display-none; } @@ -207,6 +202,5 @@ %highlight-button { background-color: $red; - box-shadow : inset 0px 0px 3px 1px #e31715; - color : #fff; + box-shadow: $box-shadow-red; } \ No newline at end of file diff --git a/Shadowrun5thEdition/src/scss/_importer.scss b/Shadowrun5thEdition/src/scss/_importer.scss index 40687f6ebe..ec11ae43ba 100644 --- a/Shadowrun5thEdition/src/scss/_importer.scss +++ b/Shadowrun5thEdition/src/scss/_importer.scss @@ -59,8 +59,8 @@ padding : 5px; text-transform : capitalize; background-color: #333; - box-shadow : inset 0px 0px 3px 1px #7c7c7c; - color : #fff + box-shadow : inset 0px 0px 3px 1px $grayshadow; + color : $white } div.sheet-mancer-box button:not(disabled):hover, @@ -100,7 +100,7 @@ div.sheet-mancer-box .sheet-results, div.sheet-mancer-box .sheet-error { border: 1px solid #333; - box-shadow: inset 0px 0px 3px 1px #7c7c7c; + box-shadow: inset 0px 0px 3px 1px $grayshadow; height: 30em; margin-top: 2%; overflow: scroll; diff --git a/Shadowrun5thEdition/src/scss/_pc.scss b/Shadowrun5thEdition/src/scss/_pc.scss index 0071ba84c1..b28341296f 100644 --- a/Shadowrun5thEdition/src/scss/_pc.scss +++ b/Shadowrun5thEdition/src/scss/_pc.scss @@ -18,60 +18,6 @@ select.sheet-skill-select {width: 29%;} } - - /***** VEHICLE *****/ - .sheet-vehicle-box .sheet-settings div, - .sheet-vehicle-box .sheet-display { - display: inline-block; - width : 100%;} - - .sheet-vehicle-box input[type='text'] { - width: 44%;} - - .sheet-vehicle-box label { - width: 20%;} - - .sheet-vehicle-box .sheet-row-long:first-child label { - width : 12%;} - - .sheet-vehicle-box label:nth-child(1n+4) { - text-align: right; - width : 21%;} - - /***** VEHICLE SETTING *****/ - .sheet-vehicle-box .sheet-settings h3 {margin-right: 2%;} - - .sheet-vehicle-box .sheet-settings h3:nth-child(1) { - margin-left: 18%; - margin-top : -5px;} - - .sheet-vehicle-box .sheet-settings h3:nth-child(4) {margin-left: 22%;} - .sheet-vehicle-box .sheet-settings h3:nth-child(6) {margin-right: 0px;} - - .sheet-vehicle-box .sheet-settings input[type='text'], - .sheet-vehicle-box .sheet-settings input[type='number'] { - border: none;} - - /***** VEHICLE DISPLAY *****/ - .sheet-vehicle-box .sheet-display-row { - text-align: left; - width : 49%;} - - .sheet-vehicle-box .sheet-display-row h3 { - width: 35%;} - - .sheet-vehicle-box .sheet-display-row div { - display : inline-block; - font-weight: normal; - text-align : center; - } - - .sheet-vehicle-box .sheet-display-row div.sheet-vehicle-stat { - width: 60%; - } - - .sheet-vehicle-box .sheet-collapsable {padding-left: 0.2em;} - /***** HEADERS AND TRIANGLES *****/ div.sheet-header { display: inline-flex; @@ -187,13 +133,17 @@ width : 5%; } - &[name*='primary_ammo'] { width: 10%; } + &[name*='primary_ammo'] { + width: 10%; + } &[type='action'] > span { display: inline; margin-left: 0px; - &:before { content: 'x'; } /** The x# after ammo button **/ + &:before { + content: 'x'; + } /** The x# after ammo button **/ } &[name*='shots'], @@ -205,13 +155,18 @@ border-radius : 5px; border-right : 3px solid #999; border-style : outset; - @extend .sheet-pictos;} + font-family: 'Pictos'; + } &[name*='shots_remove'] { transform: rotate(180deg); -ms-transform: rotate(180deg); /* IE 9 */ -webkit-transform: rotate(180deg); /* Safari 3-8 */ } + + &[name="act_reload"]:hover { + color: #fff; + } } button[type='roll'] > span, @@ -438,13 +393,22 @@ display : inline-block; margin-bottom : -25px; margin-right : -7px; + transition: transform .3s; } } .sheet-squares input[type='radio']:checked ~ input[type='radio'] + span, .sheet-con-track input[type='radio']:checked ~ .sheet-squares span, .sheet-con-track input[type='hidden'][value='0'] ~ .sheet-squares span { - background-color: transparent;} + background-color: transparent; + } + + .sheet-squares { + input[type='radio']:hover + span { + background-color: rgba($grayshadow, .5); + transform: scale(1.1); + } + } /***** MAKE CONDTION SQUARES APPEAR & DISPPEAR *****/ .sheet-hex-hider[value='8'] ~ input[type='radio']:nth-child(1n+19), @@ -599,48 +563,6 @@ width : 10%; } -/***** COLLAPSABLE DIVS *****/ - .sheet-collapsable { - padding-left: 1.5em; - width : 100%; - word-break : break-word; - - span { white-space: pre-line; } - - .sheet-desc { - @extend %display-none; - - .sheet-display-flag:checked ~ & { @extend %display-inline; } - } - - .sheet-desc-lifestyle { - @extend %display-none; - - .sheet-display-flag:checked ~ & { - @extend %display-inline-block; - width: 100%; - } - } - } - - /***** DISPLAY FLAG FOR THE COLLAPSABLE DIVS *****/ - %display-flag { - opacity : 0; - position: absolute; - top : 0px; - width : 90%; - height : 100%; - } - - $displayFlags: 'quality-box', 'contacts', 'social-box', 'vehicle-box'; - @each $flag in $displayFlags { - .sheet-#{$flag} .sheet-display-flag { @extend %display-flag;} - } - - div.sheet-augs div.sheet-repeat-box { - .sheet-display-flag { @extend %display-flag;} - } - /***** DISPLAY ROWS *****/ .sheet-display-row { display : inline-block; @@ -655,19 +577,6 @@ } } -/***** DISPLAY & SETTINGS *****/ - .sheet-skills-row, - .sheet-lifestyle .sheet-settings div { - display: inline-block; - width : 100%; - } - - @each $box in 'contacts', 'item-box' { - .sheet-#{$box} .sheet-display, - .sheet-#{$box} .sheet-settings div { - @extend .sheet-skills-row; - } - } /***** MATRIX *****/ .sheet-matrix { @@ -698,17 +607,6 @@ } /***** CYBERDECK *****/ - .sheet-cyberdeck button { - font-weight: bold; - - input[name="attr_flag"] { - position: absolute; - - & + span { - position: absolute; - } - } - } .sheet-cyberdeck h3 { line-height: 20px; @@ -748,14 +646,6 @@ margin-right: 1%;} /**** MATRIX BUBBLES ****/ - .sheet-pc .sheet-device-attr { - display: inline; - - span { - position: relative; - } - } - .sheet-matrix-tot { display: inline-block; height : 20px; @@ -871,15 +761,7 @@ .sheet-con-hex { position: relative; top : -60px; - - .sheet-edg-hex input[type='checkbox'], - .sheet-con-hex input[type='radio'] { - height : 20px; - margin-right: -21px; - top : -9px; - width : 20px; - } - + transition: transform .2s; } .sheet-edg-hex input[type='checkbox'], @@ -891,6 +773,10 @@ opacity: 0; z-index: 2; position: relative; + + &:hover + span { + transform: $button-scale-medium; + } } .sheet-hexagon { @@ -935,9 +821,9 @@ border-top-color: $lightgray;} .sheet-edg-hex input[type='checkbox']:checked + .sheet-hexagon, - .sheet-con-hex input[type='radio'] + .sheet-hexagon, .sheet-con-hex input[type='radio']:checked + .sheet-hexagon { - background-color: #222;} + background-color: #222; + } .sheet-edg-hex input[type='checkbox']:checked + .sheet-hexagon:before, .sheet-con-hex input[type='radio']:checked + .sheet-hexagon:before { @@ -964,8 +850,6 @@ .sheet-hex-hider[value='7'] ~ input[type='checkbox']:nth-child(1n+17) + span { display: none;} - - .sheet-settings .sheet-textrow label {margin-bottom: 36px;} .sheet-augmentation div.sheet-display {text-indent: 125px;} diff --git a/Shadowrun5thEdition/src/scss/_repeatingsection.scss b/Shadowrun5thEdition/src/scss/_repeatingsection.scss index 08ccb7e796..d13a9fabc4 100644 --- a/Shadowrun5thEdition/src/scss/_repeatingsection.scss +++ b/Shadowrun5thEdition/src/scss/_repeatingsection.scss @@ -1,65 +1,68 @@ - .repcontainer .repitem { - margin-bottom: 5px;} +.repcontainer .repitem { + margin-bottom: 5px; +} - .repcontrol { - display : inline-block; - vertical-align: top; - min-height : 27px;} +.repcontrol { + display : inline-block; + vertical-align: top; + min-height : 27px; - .repcontrol .btn { - background : none; - border : medium none; - box-shadow : none; - color : transparent !important; - display : inline-block; - font-size: 15px; - margin-left: 10px; - outline : 0; - padding : 0px 0px 0px 0px; - text-shadow: none; - width : 25px; - } +.btn { + background : none; + border : medium none; + box-shadow : none; + color : transparent !important; + display : inline-block; + font-size: 15px; + margin-left: 10px; + outline : 0; + padding : 0px; + text-shadow: none; + width : 25px; + } +} - .repcontrol .repcontrol_edit:after, - .repcontrol .repcontrol_add:after { - background-color: none; - color: #fff; - @extend .sheet-pictos; - font-size: 16px; - height: 12px; - padding: 2px 4px 2px 4px; - visibility: visible; - width: 12px; - } + .repcontrol .repcontrol_edit:after, + .repcontrol .repcontrol_add:after { + background-color: none; + color: $white; + @extend .sheet-pictos; + font-size: 16px; + height: 12px; + padding: 2px 4px 2px 4px; + visibility: visible; + width: 12px; +} - .repcontrol .repcontrol_edit:after {content: '(';} - .repcontrol .repcontrol_add:after {content: '&';} - .editmode ~ .repcontrol .repcontrol_edit:after {content: ')';} +.repcontrol .repcontrol_edit:after {content: '(';} +.repcontrol .repcontrol_add:after {content: '&';} +.editmode ~ .repcontrol .repcontrol_edit:after {content: ')';} - .repcontrol .repcontrol_edit:after, - .repcontrol .repcontrol_add:after { - color : #000; - position: relative;} +.repcontrol .repcontrol_edit:after, +.repcontrol .repcontrol_add:after { + color : $blacker; + position: relative;} - .sheet-npc .repcontrol .repcontrol_edit:after, - .sheet-npc .repcontrol .repcontrol_add:after { - color: #fff;} + .sheet-npc .repcontrol .repcontrol_edit:after, + .sheet-npc .repcontrol .repcontrol_add:after { + color: $white;} - .repcontrol .repcontrol_edit:hover:after, - .repcontrol .repcontrol_add:hover:after { - color : #FCD116; - background-color: none;} + .repcontrol .repcontrol_edit:hover:after, + .repcontrol .repcontrol_add:hover:after { + color : $gold; + background-color: none;} - .itemcontrol {z-index: 10;} +.itemcontrol {z-index: 10;} - .itemcontrol .repcontrol_del, - .itemcontrol .repcontrol_move { - font-size : 10px; - height : 18px; - margin-top: 3px; - padding : 0px; - width : 18px;} +.itemcontrol .repcontrol_del, +.itemcontrol .repcontrol_move { + font-size : 10px; + height : 18px; + margin-top: 3px; + padding : 0px; + width : 18px;} - .itemcontrol .repcontrol_del { - background-color: darkred; - @extend .sheet-pictos;} \ No newline at end of file +.itemcontrol .repcontrol_del { + background-color: $red; + @extend .sheet-pictos; +} \ No newline at end of file diff --git a/Shadowrun5thEdition/src/scss/_rolltemplate.scss b/Shadowrun5thEdition/src/scss/_rolltemplate.scss index 3c5feea924..0fc5e5cf61 100644 --- a/Shadowrun5thEdition/src/scss/_rolltemplate.scss +++ b/Shadowrun5thEdition/src/scss/_rolltemplate.scss @@ -1,55 +1,85 @@ .sheet-rolltemplate-rolls div.sheet-template-body { - border : 2px solid #000 !important; + border : 2px solid $blacker !important; border-radius: 3px 3px 3px 3px;} .sheet-rolltemplate-rolls .sheet-template-header { - background-color: #431714; - border : 1px solid #000; - border-bottom : 2px solid #000; - box-shadow : inset 0px 0px 3px 1px #000; - color : #fff; + background-color: $red; + border : 1px solid $blacker; + border-bottom : 2px solid $blacker; + box-shadow : inset 0px 0px 3px 1px $blacker; + color : $white; font-size : 1.5em; font-variant : small-caps; - font-weight : bold; letter-spacing : 2px; - padding : 8px 0px 3px 0px; + padding : 3px 0px 5px 0px; text-align : center; - text-transform : capitalize;} + text-transform : capitalize; + font-weight: bold; - .sheet-rolltemplate-rolls .sheet-template-header span { - font-family : 'tahoma'; - font-size : 0.5em; - font-weight : normal; - font-variant : normal; - letter-spacing: 1px;} + h1 { + font-size: 1em; + color: $white; + line-height: 1em; + } + + span { + font-family : 'tahoma'; + font-size : 0.5em; + font-variant : normal; + letter-spacing: 1px; + } + } .sheet-rolltemplate-rolls .sheet-template-row { - color : #fff; + color : $white; text-align : center; font-size : 18px; - background-color: #555; - box-shadow : inset 0px 0px 3px 1px #000; + background-color: #1c1c1c; + box-shadow : inset 0px 0px 3px 1px $blacker; line-height : 1.1em; font-family : 'helvetica'; - padding : 5px 5px 3px 5px;} + padding : 5px 5px 3px 5px; - .sheet-rolltemplate-rolls .sheet-template-row:nth-child(2n+0) {background-color: #1c1c1c;} + &:nth-child(2n+0) { + background-color: #555; + } + + //Drain button + a[href^="~"] { + font-family: "dicefontd6"; + color: #1c1c1c;; + border: none; + box-shadow: outset 0px 0px 3px 1px $blacker; + font-size: 1.8em; + background: none !important; + padding: 1px; + color: $white; + text-shadow: $text-shadow-dark; + + &:hover, &:focus, &:active { + font-weight: bold; + color: $white; + text-shadow: $text-shadow-red; + } + } + } .sheet-rolltemplate-rolls .inlinerollresult { display :inline-block; - color : #fff; + color : $white; font-size : 25px; background-color: transparent; - border : none;} + border : none; + } .sheet-rolltemplate-rolls .inlinerollresult.fullfail, .sheet-rolltemplate-rolls .inlinerollresult.fullcrit, .sheet-rolltemplate-rolls .inlinerollresult.importantroll { border: none;} - .sheet-rolltemplate-rolls .inlinerollresult.fullfail {color: #FCD116;} + .sheet-rolltemplate-rolls .inlinerollresult.fullfail {color: $gold;} - .sheet-rolltemplate-rolls .inlinerollresult.fullcrit {color: #fff;} + .sheet-rolltemplate-rolls .inlinerollresult.fullcrit {color: $white;} .sheet-rolltemplate-rolls .sheet-template-desc {font-size: 0.8em;} diff --git a/Shadowrun5thEdition/src/scss/abstracts/_mixins.scss b/Shadowrun5thEdition/src/scss/abstracts/_mixins.scss new file mode 100644 index 0000000000..033cea0611 --- /dev/null +++ b/Shadowrun5thEdition/src/scss/abstracts/_mixins.scss @@ -0,0 +1,31 @@ +@mixin repeatingInformation($endColumn, $longCollapseFlag) { + label[data-i18n-title='notes'], + h3[data-i18n='notes'], + div.sheet-collapse { + grid-column: 1 / #{$endColumn}; + + span[name='attr_notes'] { + white-space: pre-line; + } + } + + input.sheet-collapse-flag { + @if $longCollapseFlag { + grid-area: 1 / 1 / 1 / #{$endColumn - 1}; + position: absolute; + width: 100%; + } @else { + grid-area: 1 / #{$endColumn - 2} / 1 / #{$endColumn - 1}; + } + } + + input.sheet-collapse-flag + span.sheet-pictos { + grid-area: 1 / #{$endColumn - 2} / 1 / #{$endColumn - 1}; + } + + input.sheet-settings-flag, + input.sheet-settings-flag + span.sheet-pictos { + grid-area: 1 / #{$endColumn - 1} / 1 / #{$endColumn}; + } +} + diff --git a/Shadowrun5thEdition/src/scss/abstracts/_variables.scss b/Shadowrun5thEdition/src/scss/abstracts/_variables.scss new file mode 100644 index 0000000000..7d726e434d --- /dev/null +++ b/Shadowrun5thEdition/src/scss/abstracts/_variables.scss @@ -0,0 +1,36 @@ + +/******************************************************************************/ +/********************************* VARIABLES *********************************/ +/****************************************************************************/ +$tabs:'arms', 'augs', 'core', 'gear', 'options', 'social', 'magic', 'matrix', 'vehicle'; +$characterTypes: 'npc', 'pc'; +$specialCharacters: 'magic', 'resonance'; +$npcTypes: 'grunt', 'host', 'sprite', 'vehicle'; + +//- Colors: + $gold: #FCD116; + $red: #610b0d; + $red-light: #e31715; + $purple: #7a2593; + $lightgray: #9a9a9a; + $graytrans: rgba(28, 28, 28, 0.14902); + $grayshadow: #7c7c7c; + $blacker: #040404; + $ccc: #cccccc; + //- GRAY IN ROLL TEMPLATE + $blackish: #1c1c1c; + //-(primaryly on the NPC sheet) + $gray: #555; + $white: #fff; + + + $text-shadow: 1px 1px 2px $gray, 0 0 25px $white, 0 0 5px $white; + $text-shadow-dark: 1px 1px 2px black, 0 0 25px #1c1c1c, 0 0 5px #1c1c1c; + $text-shadow-red: 1px 1px 2px black, 0 0 25px red, 0 0 5px $red; + + $box-shadow: inset 0px 0px 3px 1px $grayshadow; + $box-shadow-outset: -1px -1px 1px 1px $grayshadow; + $box-shadow-red: inset 0px 0px 3px 1px $red-light; + + $button-scale-small: scale(1.1); + $button-scale-medium: scale(1.3); \ No newline at end of file diff --git a/Shadowrun5thEdition/src/scss/base/_base.scss b/Shadowrun5thEdition/src/scss/base/_base.scss new file mode 100644 index 0000000000..5c81c5be6c --- /dev/null +++ b/Shadowrun5thEdition/src/scss/base/_base.scss @@ -0,0 +1,124 @@ +* { + box-sizing: border-box; + font-family: sans-serif; +} + +button { + background-image: none; + font-size: 0.8em; + text-shadow: none; + + &[type='roll'], + &[type='action'] { + font-size: 1em; + padding: 1px 2px; + + border: { + bottom : 0.01em solid #666; + bottom-right-radius: 0.01em; + color : $lightgray; + radius : 0.25em !important; + right : 0.02em solid $graytrans; + style : outset; + } + } + + &:hover, &:focus, &:active { + font-weight: bold; + background-color: $red; + color: $white; + } + + & > span { + display: block; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + } + + &:before { + display: none; + } +} + +div {background-color: transparent;} + +fieldset { background: transparent;} + +hr { + border: 0.5px solid $gray; +} + +label { + display: inline-block; + font-size: 0.9em; + margin-bottom: 0px; + padding-right: 5px; + text-transform: capitalize; + width: auto;} + +input { + background-color: $lightgray; + color: $blacker; + border: none; + cursor: auto; + font-weight: normal; + margin: 0px; + text-align: center; + vertical-align: middle; + + &[type='text'], + &[type='number'] { + height : 20px; + + &:hover, &:focus { + background-color: #d2d1cd; + color: $blackish; + } + + &:placeholder-shown { + border: 1px dotted $gray; + background-color: $graytrans; + color: $white; + } + } + + &::-webkit-outer-spin-button, + &::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; + } + + &[name='attr_stats_toggle'], + &[name='attr_stats_toggle'] + span { + position: relative; + } + + &[name='attr_stats_toggle'] { + opacity: 0; + z-index: 2; + } +} + +select { + border-radius: 2px; + border: 1px solid $blacker; + box-shadow: $box-shadow; + margin-bottom: 0px; + width: auto;} + +span { + word-break: break-word; +} + +textarea { + border-radius: 2px; + border: 1px solid $blacker; + box-shadow: $box-shadow; + height: 50px; + overflow-wrap: break-word; + overflow: hidden; + resize: vertical; + vertical-align: top; + white-space: pre-line; +} \ No newline at end of file diff --git a/Shadowrun5thEdition/src/scss/base/_utilities.scss b/Shadowrun5thEdition/src/scss/base/_utilities.scss new file mode 100644 index 0000000000..b73c1d61a4 --- /dev/null +++ b/Shadowrun5thEdition/src/scss/base/_utilities.scss @@ -0,0 +1,104 @@ + +.charsheet { + width: 850px; +} + +.sheet-red { + color: $red; +} + +.sheet-text-center { + text-align: center; +} + +.sheet-eclipse { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.sheet-text-left { + text-align: left; +} + +.sheet-text-capitalize { + text-transform: capitalize; +} + +.sheet-dicefontd6 { + font-family: "dicefontd6" +} + +%display-none, +.sheet-display-none { + display: none; +} + +%display-inline { + display: inline; +} + +%display-inline-grid { + display: inline-grid; +} + +%display-grid { + display: grid; +} + +.sheet-pictos { + font-family: 'Pictos'; +} + +%display-inline-block, +.sheet-static { + display: inline-block; +} + +%parantheseNumbers { + vertical-align: middle; + + &:before { content: '('; } + &:after { content: ')'; } +} + +%toggleCheckbox, +input.sheet-toggle { + position: absolute; + opacity: 0; + z-index: 2; +} + +%toggleRelative { + position: relative; + opacity: 0; + z-index: 2; +} + +%settingsCheckboxes { + & + span { opacity: 0; } + &:checked + span { opacity: 1; } + + &:checked ~ .sheet-settings { + display: inline-grid; + margin-bottom: 2%; + } +} + +%borderBottom { + border-bottom: 1px solid $blacker; +} + +div.sheet-grid { + display: inline-grid; + grid-column-gap: 1%; + grid-row-gap: 0.5%; +} + +div.sheet-2column { + grid-template-columns: 1fr 1fr; +} + +div.sheet-2autocolumn { + grid-template-columns: auto 1fr; +} \ No newline at end of file diff --git a/Shadowrun5thEdition/src/scss/components/_collapse.scss b/Shadowrun5thEdition/src/scss/components/_collapse.scss new file mode 100644 index 0000000000..4def678f38 --- /dev/null +++ b/Shadowrun5thEdition/src/scss/components/_collapse.scss @@ -0,0 +1,13 @@ + //Hide the collapse section by default + div.sheet-collapse { + opacity: 0; + height: 0; + transition: all .5s; + } + + //Expand it out to be visible with animation + input.sheet-collapse-flag:checked ~ div.sheet-collapse { + opacity: 1; + height: 100%; + transition: all .5s; + } \ No newline at end of file diff --git a/Shadowrun5thEdition/src/scss/components/_indicator.scss b/Shadowrun5thEdition/src/scss/components/_indicator.scss new file mode 100644 index 0000000000..6851b17e32 --- /dev/null +++ b/Shadowrun5thEdition/src/scss/components/_indicator.scss @@ -0,0 +1,28 @@ +input.sheet-indicator { + height: 1.8em; + width: 1.5em; + transition: all .2s; + top: 5px; + + & + span { + display: inline-block; + height: 1.5em; + width: 1.5em; + } + + &:hover + span { + transform: $button-scale-medium; + } + + &:checked + span { + background-color: $red; + color: $white; + font-weight: bolder; + border-radius: 3px; + padding: 15%; + + & + span { + font-weight: bolder; + } + } +} diff --git a/Shadowrun5thEdition/src/scss/_switch.scss b/Shadowrun5thEdition/src/scss/components/_switch.scss similarity index 100% rename from Shadowrun5thEdition/src/scss/_switch.scss rename to Shadowrun5thEdition/src/scss/components/_switch.scss diff --git a/Shadowrun5thEdition/src/scss/layout/_firefox.scss b/Shadowrun5thEdition/src/scss/layout/_firefox.scss new file mode 100644 index 0000000000..b19e4ca79b --- /dev/null +++ b/Shadowrun5thEdition/src/scss/layout/_firefox.scss @@ -0,0 +1,9 @@ +input[type=number]::-webkit-outer-spin-button, +input[type=number]::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type=number] { + -moz-appearance:textfield; +} diff --git a/Shadowrun5thEdition/src/scss/layout/_footer.scss b/Shadowrun5thEdition/src/scss/layout/_footer.scss new file mode 100644 index 0000000000..1d58dc69c0 --- /dev/null +++ b/Shadowrun5thEdition/src/scss/layout/_footer.scss @@ -0,0 +1,18 @@ + .sheet-footer { + border : none; + font-size : 0.55em; + line-height: 15px; + margin-top : 15px; + text-align : left; + width : 700px;} + + div.sheet-footer div { + display: inline-block; + width: 90%; + } + + div.sheet-footer img { + float: right; + vertical-align: top; + width: 5%; + } \ No newline at end of file diff --git a/Shadowrun5thEdition/src/scss/_lang-fr.scss b/Shadowrun5thEdition/src/scss/layout/_lang-fr.scss similarity index 100% rename from Shadowrun5thEdition/src/scss/_lang-fr.scss rename to Shadowrun5thEdition/src/scss/layout/_lang-fr.scss diff --git a/Shadowrun5thEdition/src/scss/layout/_tabs.scss b/Shadowrun5thEdition/src/scss/layout/_tabs.scss new file mode 100644 index 0000000000..8c7ae41af1 --- /dev/null +++ b/Shadowrun5thEdition/src/scss/layout/_tabs.scss @@ -0,0 +1,48 @@ +.sheet-tabs { + color: $white; + + button { + &[type='action'] { + background-color: #333; + border-radius : 2px; + border : 1px solid $grayshadow; + font-size : 1em; + font-weight : bolder; + text-transform : capitalize; + padding : 5px; + transition: transform .2s; + + &.sheet-pictos { + text-transform: lowercase; + } + + &:hover, &:focus, &:active { + text-shadow: $box-shadow-red; + background-color: $red; + transform: $button-scale-small; + } + } + + &[type='roll'] { + background: none; + border: none; + color : $white; + font-family : 'dicefontd6'; + font-size : 2.5em; + vertical-align: top; + + &:hover { + text-shadow: 1px 1px 2px $blacker, 0 0 25px $red, 0 0 5px $red-light; + } + } + } + + h2 { + color: $white; + font-size: 1em; + text-transform: capitalize; + text-align: right; + line-height: 2em; + margin-right: 5%; + } +} \ No newline at end of file diff --git a/Shadowrun5thEdition/src/scss/_npc.scss b/Shadowrun5thEdition/src/scss/pages/_npc.scss similarity index 97% rename from Shadowrun5thEdition/src/scss/_npc.scss rename to Shadowrun5thEdition/src/scss/pages/_npc.scss index d7e5b167dc..e8a7ca8e80 100644 --- a/Shadowrun5thEdition/src/scss/_npc.scss +++ b/Shadowrun5thEdition/src/scss/pages/_npc.scss @@ -1,7 +1,7 @@ .sheet-npc { background-color: #040404; border-radius : 3px; - color : #fff; + color : $white; margin-top : -20px; min-height : 800px; padding : 10px 10px; @@ -19,7 +19,7 @@ } } - h1, h2, h3, h4, label { color: #fff; } + h1, h2, h3, h4, label { color: $white; } h1 { line-height: unset; @@ -45,7 +45,7 @@ } textarea, select { - color : #fff; + color : $white; background-color: #555; } @@ -138,8 +138,8 @@ /*:+:+:+: NPC ATTRIBUTES :+:+:+:*/ div.sheet-attribute { - border-bottom: 1px solid #fff; - border-top : 1px solid #fff; + border-bottom: 1px solid $white; + border-top : 1px solid $white; grid-row-gap: 5%; margin : 2% 0px; padding: 1% 1% 3% 1%; diff --git a/Shadowrun5thEdition/src/scss/pages/tabs/_arms.scss b/Shadowrun5thEdition/src/scss/pages/tabs/_arms.scss new file mode 100644 index 0000000000..7fc733c9cc --- /dev/null +++ b/Shadowrun5thEdition/src/scss/pages/tabs/_arms.scss @@ -0,0 +1,78 @@ + /*** ARMS ****/ + div.sheet-arms { + div.sheet-headers { + display: grid; + @extend %gridGap; + + h2:nth-of-type(1n+2) { text-align: center; } + } + + div.repitem { + h3 { color: $blacker; } + + input { + &:nth-of-type(1n+2) { text-align: center; } + + &.sheet-flag-primary[value='primary'] + button { + background-color: $gold; + border-bottom: 2px solid $blacker; + } + } + } + + div.sheet-weapons { + $weaponsGrid: 25% 1.25fr 3em 2.5em 3em 1fr 1fr 1em 1em; + div.sheet-headers { grid-template-columns:$weaponsGrid; } + + div.repitem { + grid-template-columns: $weaponsGrid; + @include repeatingInformation(10, false); + + div.sheet-settings { + grid-column: 1 / 10; + grid-template-columns: $weaponsGrid; + } + } + + div.sheet-weapon-range, + div.sheet-weapon-melee { + width: 100%; + div.sheet-row { + grid-column: 1 / 9; + + label[data-i18n-title="modeoptions"], + label[data-i18n-title="range"]{ + width: 25%; + } + + input[type='number'] {width: 3em;} + + select {width: 30%;} + }; + + div.sheet-exotic-warning { display: none; } + + input[value='0'] + div.sheet-exotic-warning { display: block; } + } + } + + div.sheet-armor { + $armorGrid: 30% 3.5em 2.5em 2.5em 2.5em 2.5em 2.5em 1em 1em; + div.sheet-headers { grid-template-columns:$armorGrid; } + + div.repitem { + grid-template-columns: $armorGrid; + @include repeatingInformation(11, false); + + div.sheet-settings { + grid-column: 1 / 11; + grid-template-columns: $armorGrid; + + div.sheet-row { + grid-column: 1 / 11; + } + } + } + } + } + \ No newline at end of file diff --git a/Shadowrun5thEdition/src/scss/pages/tabs/_augs.scss b/Shadowrun5thEdition/src/scss/pages/tabs/_augs.scss new file mode 100644 index 0000000000..4ceaad3498 --- /dev/null +++ b/Shadowrun5thEdition/src/scss/pages/tabs/_augs.scss @@ -0,0 +1,19 @@ +/*** AUGS ****/ +div.sheet-augs { + $augsGrid: 1fr 5em 5em 1em 1em; + + div.sheet-headers { + display: grid; + grid-template-columns:$augsGrid; + } + + div.repitem { + grid-template-columns: $augsGrid; + @include repeatingInformation(6, true); + + div.sheet-settings { + grid-column: 1 / 6; + grid-template-columns: $augsGrid; + } + } +} diff --git a/Shadowrun5thEdition/src/scss/pages/tabs/_core.scss b/Shadowrun5thEdition/src/scss/pages/tabs/_core.scss new file mode 100644 index 0000000000..cf90665970 --- /dev/null +++ b/Shadowrun5thEdition/src/scss/pages/tabs/_core.scss @@ -0,0 +1,84 @@ +/***** CORE *****/ +div.sheet-core { + div.sheet-armor-buttons { + display : inline-block; + font-size: 1.5em; + line-height: 20px; + margin-left: 1%; + width : 35%; + + button { + &[type='roll'] { margin-right: -5px; } + &[name='roll_defense'] { + background-color: $gray; + color: $white; + } + } + + span { + font-size: 1em; + } + } + + button[name="act_primary_ammo"]:hover > img { + filter: brightness(0) invert(1); + } + + /***** QUALITIES *****/ + div.sheet-quality-box { + div.sheet-htab input[type='radio'] { + margin-right: -100px; + width : 100px; + } + + div.sheet-header:nth-of-type(2) .sheet-htab input[type='radio'] { + margin-right: -150px; + width : 150px; + } + + div.sheet-quality { + $qualityGrid: 1fr 3em 1.5em 1em 1em; + + h2:nth-of-type(2) { text-align: center; } + + div.sheet-headers { + display: grid; + grid-template-columns: $qualityGrid; + @extend %gridGap; + } + + div.repitem { + grid-template-columns: $qualityGrid; + @include repeatingInformation(6, false); + + div.sheet-settings { + grid-column: 1 / 6; + grid-template-columns: $qualityGrid; + } + } + } + + div.sheet-martial { + $martialGrid: 2fr 1fr 1.5em 1em 1em; + + h2:nth-of-type(2) { text-align: center; } + + div.sheet-headers { + display: grid; + grid-template-columns: $martialGrid; + @extend %gridGap; + } + + div.repitem { + grid-template-columns: $martialGrid; + @include repeatingInformation(6, false); + + div.sheet-settings { + grid-column: 1 / 6; + grid-template-columns: $martialGrid; + } + } + } + } +} + diff --git a/Shadowrun5thEdition/src/scss/pages/tabs/_gear.scss b/Shadowrun5thEdition/src/scss/pages/tabs/_gear.scss new file mode 100644 index 0000000000..2214dff457 --- /dev/null +++ b/Shadowrun5thEdition/src/scss/pages/tabs/_gear.scss @@ -0,0 +1,60 @@ +/*** GEAR ****/ +div.sheet-gear { + $gearGrid: 1.5em 1fr 5em 5em 1em 1em;; + + div.sheet-headers { + display: grid; + grid-template-columns:$gearGrid; + + h2[data-i18n='item'] { + grid-column: 1 / 3; + } + } + + div.repitem { + grid-template-columns: $gearGrid; + @include repeatingInformation(7, false); + + label[data-i18n-title='item'] { + grid-column: 1 / 3; + + input[type='number'] { + width: 100%; + } + } + + label[data-i18n-title='rating'] { + grid-column: 3 / 4; + } + + label[data-i18n-title='quantity'] { + grid-column: 4 / 5; + } + + select { + -webkit-appearance: none; + -moz-appearance: none; + text-indent: 3px; + border: none; + background: transparent; + box-shadow: none; + font-size: 1.3em; + max-height: 18px; + transition: all .2s; + + &:hover { + cursor: pointer; + transform: $button-scale-medium; + } + } + + input[name='attr_location'][value='person'] + span { + font-weight: bold; + } + + div.sheet-settings { + grid-column: 1 / 7; + grid-template-columns: $gearGrid; + } + } +} diff --git a/Shadowrun5thEdition/src/scss/pages/tabs/_magic.scss b/Shadowrun5thEdition/src/scss/pages/tabs/_magic.scss new file mode 100644 index 0000000000..227bf404ea --- /dev/null +++ b/Shadowrun5thEdition/src/scss/pages/tabs/_magic.scss @@ -0,0 +1,114 @@ +/***** MAGIC *****/ +div.sheet-magic { + $magicGrid: 30% 1.5fr 1.5fr 2fr 2em 1em 1em; + + input.sheet-magic-toggle[value='rituals'] ~ .sheet-headers h2:nth-of-type(1n+2) { + @extend %display-none; + } + + h2:nth-of-type(1n+2) { text-align: center; } + h3 { color: $blacker; } + + div.sheet-headers { + display: grid; + @extend %gridGap; + grid-template-columns:$magicGrid; + + h3:nth-of-type(1n+2) { text-align: center; } + } + + /***** SPELLS & PREPARTATIONS *****/ + div.sheet-spellsForumlas { + div.repitem { + grid-template-columns: $magicGrid; + + @include repeatingInformation(8, false); + + input[name='attr_damage'], + input[name='attr_dicepool_modifier'] { + width: 3.5em; + } + + select[name='attr_category'] { grid-row: 2; } + + div.sheet-row { grid-column: 1 / 6; } + + div.sheet-settings { + grid-column: 1 / 8; + grid-template-columns: $magicGrid; + } + } + } + + /***** RITUALS *****/ + div.sheet-magic-rituals { + $ritualsGrid: 1fr 1em 1em; + + @include repeatingInformation(4, false); + + div.repitem { + grid-template-columns: $ritualsGrid; + + label { + &[data-i18n-title='name'] { grid-column: 1 / 4; } + } + + div.sheet-row { grid-column: 1 / 4; } + } + + div.sheet-settings { + grid-template-columns: $ritualsGrid; + grid-column: 1 / 4; + } + } + + div.sheet-magic-preps, div.sheet-magic-spells { + textarea { width: 93%; } + } + + /***** PREPARATIONS *****/ + div.sheet-magic-preps { + /* READIED PREPARATIONS */ + div.sheet-prepared-preparations { + $preparationsGrid: 40% 1fr 1fr 2fr 1em 1em; + + div.sheet-headers { + grid-template-columns:$preparationsGrid ; + } + + div.repitem { + grid-template-columns: $preparationsGrid ; + + @include repeatingInformation(7, false); + + div.sheet-settings { + grid-column: 1 / 7; + grid-template-columns: $preparationsGrid; + + select { grid-column: 4 / 7; } + + textarea { width: 100%; } + } + } + } + } + + /***** ADEPT POWERS *****/ + div.sheet-powers { + $powersGrid: 1fr 3em 1em 1em;; + + div.sheet-headers { + grid-template-columns:$powersGrid; + } + + div.repitem { + grid-template-columns: $powersGrid; + @include repeatingInformation(5, true); + + div.sheet-settings { + grid-column: 1 / 5; + grid-template-columns: $powersGrid; + } + } + } +} \ No newline at end of file diff --git a/Shadowrun5thEdition/src/scss/pages/tabs/_matrix.scss b/Shadowrun5thEdition/src/scss/pages/tabs/_matrix.scss new file mode 100644 index 0000000000..cf431499d5 --- /dev/null +++ b/Shadowrun5thEdition/src/scss/pages/tabs/_matrix.scss @@ -0,0 +1,83 @@ +/*** MATRIX ****/ +div.sheet-matrix { + button[type='roll'] { + font-size: 0.9em; + } + + h3 { + color: $blacker; + } + + /* Needs to be refactored into Grid */ + div.sheet-device-attr { + display: inline; + transition: transform .2s; + + span { + position: relative; + } + + input[type='radio']:hover + span { + transform: $button-scale-medium; + } + } + + div.sheet-programs { + $programGrid: 1.5em 1fr 1.5em 1em 1em; + + div.repitem { + grid-template-columns: $programGrid; + @extend %borderBottom; + @include repeatingInformation(6, false); + + input.sheet-indicator { + grid-area: 1 / 1 / 1 / 1; + + & + span { + grid-area: 1 / 1 / 1 / 1; + } + } + } + + div.sheet-settings { + grid-column: 1 / 5; + + input[type='text'] { + grid-column: 1 / 4; + text-align: left; + } + + label { + grid-column: 1 / 4; + } + } + } + + div.sheet-complex-forms { + $complexFormsGrid: 30% 1fr 1fr 4em 1em 1em; + + div.sheet-headers { + display: grid; + @extend %gridGap; + grid-template-columns: $complexFormsGrid; + + h2:nth-of-type(1n+2) { text-align: center; } + } + + div.repitem { + grid-template-columns: $complexFormsGrid; + + @include repeatingInformation(7, false); + + div.sheet-row { + grid-column: 1 / 7; + } + + div.sheet-settings { + grid-column: 1 / 7; + grid-template-columns: $complexFormsGrid; + + } + } + } +} \ No newline at end of file diff --git a/Shadowrun5thEdition/src/scss/pages/tabs/_social.scss b/Shadowrun5thEdition/src/scss/pages/tabs/_social.scss new file mode 100644 index 0000000000..0c28fbdb7d --- /dev/null +++ b/Shadowrun5thEdition/src/scss/pages/tabs/_social.scss @@ -0,0 +1,55 @@ +/*** SOCIAL ****/ +div.sheet-social { + + input:not(:placeholder-shown) { + background-color: transparent;; + } + + div.sheet-lifestyle { + $lifestyleGrid: 1fr 1.5em 1em 1em; + div.repitem { + grid-template-columns: $lifestyleGrid; + @include repeatingInformation(5, false); + + div.sheet-collapse { + padding-left: 2%; + + h3 { + margin-right: 1%; + } + } + + div.sheet-settings { + grid-column: 1 / 5; + padding: 1% 2% 5% 2%; + min-height: 300px; + + textarea { + height: 45px; + min-height: 45px; + } + } + } + } + + div.sheet-contacts { + $contactsGrid: 1fr 4em 5.5em 4em 1.5em 1em 1em; + + div.sheet-headers { + display: grid; + grid-template-columns: $contactsGrid; + grid-column-gap: 0.5%; + width: 100%; + } + + div.repitem { + grid-template-columns: $contactsGrid; + @include repeatingInformation(8, false); + + + div.sheet-settings { + grid-column: 1 / 8; + } + } + } +} \ No newline at end of file diff --git a/Shadowrun5thEdition/src/scss/pages/tabs/_static.scss b/Shadowrun5thEdition/src/scss/pages/tabs/_static.scss new file mode 100644 index 0000000000..08c3223d19 --- /dev/null +++ b/Shadowrun5thEdition/src/scss/pages/tabs/_static.scss @@ -0,0 +1,20 @@ +/***** STATIC *****/ +div.sheet-static { + margin-right: 0.5%; + transition: transform .2s; + + div.sheet-border-box, + div.sheet-border-box .sheet-pc-box { + border-top-right-radius: 0px; + border-top-left-radius : 10px; + } + + div.sheet-attr-box { + button { + margin-bottom: 2%; + &:hover, &:focus, &:active { + transform: scale(1.1); + } + } + } +} \ No newline at end of file diff --git a/Shadowrun5thEdition/src/scss/pages/tabs/_vehicle.scss b/Shadowrun5thEdition/src/scss/pages/tabs/_vehicle.scss new file mode 100644 index 0000000000..37b1dd79be --- /dev/null +++ b/Shadowrun5thEdition/src/scss/pages/tabs/_vehicle.scss @@ -0,0 +1,67 @@ +div.sheet-vehicle { + $vehicleGrid: 1fr 1fr 1em 1em; + + div.sheet-row-long { + display: inline-grid; + grid-column: 1 / 5; + } + + div.sheet-vehicle-name { + grid-column: 1 / 3; + } + + h3 { + color: $blackish; + overflow: hidden; + } + + label { + width: 100%; + } + + div.sheet-col { + display: inline-grid; + grid-template-columns: 1fr 5em; + } + + div.repitem { + grid-template-columns: $vehicleGrid; + @include repeatingInformation(5, true); + + div.sheet-settings { + grid-column: 1 / 5; + grid-template-columns: $vehicleGrid; + + div.sheet-col { + grid-column-gap: 2%; + + &:nth-of-type(1) { + grid-template-columns: 40% 2.1em 2.1em 2.1em; + margin-right: 5px; + } + + &:nth-of-type(2) { + grid-template-columns: 1fr 2.1em 2.1em 2.1em; + } + } + + div.sheet-headers { + h2[data-i18n='base'] { + grid-column: 2 / 3; + } + + h2[data-i18n='mod'] { + grid-column: 3 / 4; + } + + h2[data-i18n='temp'] { + grid-column: 4 / 5; + } + } + } + } + + div.repcontrol { + margin-top: 5%; + } +} \ No newline at end of file diff --git a/Shadowrun5thEdition/src/test/Scripts_tests.js b/Shadowrun5thEdition/src/test/Scripts_tests.js deleted file mode 100644 index 58c6b86652..0000000000 --- a/Shadowrun5thEdition/src/test/Scripts_tests.js +++ /dev/null @@ -1,4 +0,0 @@ -const assert = require('assert') -const updateFunctions = require('../js/newScripts'); - - diff --git a/Shadowrun5thEdition/src/vehicle.html b/Shadowrun5thEdition/src/vehicle.html deleted file mode 100644 index 181ce8c61a..0000000000 --- a/Shadowrun5thEdition/src/vehicle.html +++ /dev/null @@ -1,138 +0,0 @@ -
-
-

Vehicle

-
-
-
- -
-
-
- - - - - - - - -
-
- - - - - - - - - - - - -
-
- - - - - - - - - - - - -
-
- - - - - - - - - - - - -
-
-

Base

Modifier

-

Temp

Base

-

Modifier

Temp

-
-

Notes

- -
-
-
- -
-
-

Vehicle

-
- -
-
-
-

Handling

-
- -
-
-
-
-
-

Acceleration

-
- -
-
-
-

Speed

-
- -
-
-
-
-
-

Pilot

-
- -
-
-
-

Body

-
- -
-
-
-
-
-

Armor

-
- -
-
-
-

Sensor

-
- -
-
-
-
-
-
-
- x -
-
-
-
-
diff --git a/Shadowrun5thEdition/translation.json b/Shadowrun5thEdition/translation.json index 69b8f26795..c7c0545131 100644 --- a/Shadowrun5thEdition/translation.json +++ b/Shadowrun5thEdition/translation.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep":"Prep...", + "preps":"Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", @@ -400,4 +400,28 @@ ,"time":"time" ,"adeptpowers": "Adept Powers or Other Abilities" ,"whisper rolls to gm":"whisper rolls to gm" + ,"handling base":"handling base" + ,"handling temp":"handling temp" + ,"handling modifier":"handling modifier" + ,"vehicle name":"vehicle name" + ,"acceleration base":"acceleration base" + ,"acceleration temp":"acceleration temp" + ,"acceleration modifier":"acceleration modifier" + ,"speed base":"speed base" + ,"speed temp":"speed temp" + ,"speed modifier":"speed modifier" + ,"pilot base":"pilot base" + ,"pilot temp":"pilot temp" + ,"pilot modifier":"pilot modifier" + ,"body base":"body base" + ,"body temp":"body temp" + ,"body modifier":"body modifier" + ,"armor base":"armor base" + ,"armor temp":"armor temp" + ,"armor modifier":"armor modifier" + ,"sensor base":"sensor base" + ,"sensor temp":"sensor temp" + ,"sensor modifier":"sensor modifier" + ,"handling_off":"Handling (Off-Road)" + ,"mod":"mod" } \ No newline at end of file diff --git a/Shadowrun5thEdition/translations/af.json b/Shadowrun5thEdition/translations/af.json index c0169e65d4..c53a6cff3a 100644 --- a/Shadowrun5thEdition/translations/af.json +++ b/Shadowrun5thEdition/translations/af.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/cs.json b/Shadowrun5thEdition/translations/cs.json index c0169e65d4..c53a6cff3a 100644 --- a/Shadowrun5thEdition/translations/cs.json +++ b/Shadowrun5thEdition/translations/cs.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/da.json b/Shadowrun5thEdition/translations/da.json index c0169e65d4..c53a6cff3a 100644 --- a/Shadowrun5thEdition/translations/da.json +++ b/Shadowrun5thEdition/translations/da.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/de.json b/Shadowrun5thEdition/translations/de.json index b96bd2f12c..d28c010d5f 100644 --- a/Shadowrun5thEdition/translations/de.json +++ b/Shadowrun5thEdition/translations/de.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/el.json b/Shadowrun5thEdition/translations/el.json index c0169e65d4..c53a6cff3a 100644 --- a/Shadowrun5thEdition/translations/el.json +++ b/Shadowrun5thEdition/translations/el.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/en.json b/Shadowrun5thEdition/translations/en.json index 21e3244ecb..7ecead8b37 100644 --- a/Shadowrun5thEdition/translations/en.json +++ b/Shadowrun5thEdition/translations/en.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/es.json b/Shadowrun5thEdition/translations/es.json index ec47665853..a906726bcb 100644 --- a/Shadowrun5thEdition/translations/es.json +++ b/Shadowrun5thEdition/translations/es.json @@ -276,7 +276,7 @@ "power": "Poder", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/fr.json b/Shadowrun5thEdition/translations/fr.json index 2177fec016..2bdd6a8e29 100644 --- a/Shadowrun5thEdition/translations/fr.json +++ b/Shadowrun5thEdition/translations/fr.json @@ -276,7 +276,7 @@ "power": "Puissance", "powers": "Pouvoirs", "pr": "Indice professionnel", - "prep": "Prép...", + "preps": "Prép...", "primary": "Principale", "primaryarmor": "Armure principale", "primarylifestyle": "Style de vie principal", diff --git a/Shadowrun5thEdition/translations/he.json b/Shadowrun5thEdition/translations/he.json index c0169e65d4..c53a6cff3a 100644 --- a/Shadowrun5thEdition/translations/he.json +++ b/Shadowrun5thEdition/translations/he.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/it.json b/Shadowrun5thEdition/translations/it.json index 3f2a8da5b6..ad5c750124 100644 --- a/Shadowrun5thEdition/translations/it.json +++ b/Shadowrun5thEdition/translations/it.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/ja.json b/Shadowrun5thEdition/translations/ja.json index c0169e65d4..c53a6cff3a 100644 --- a/Shadowrun5thEdition/translations/ja.json +++ b/Shadowrun5thEdition/translations/ja.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/ko.json b/Shadowrun5thEdition/translations/ko.json index c0169e65d4..c53a6cff3a 100644 --- a/Shadowrun5thEdition/translations/ko.json +++ b/Shadowrun5thEdition/translations/ko.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/nl.json b/Shadowrun5thEdition/translations/nl.json index c0169e65d4..c53a6cff3a 100644 --- a/Shadowrun5thEdition/translations/nl.json +++ b/Shadowrun5thEdition/translations/nl.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/pl.json b/Shadowrun5thEdition/translations/pl.json index c0169e65d4..c53a6cff3a 100644 --- a/Shadowrun5thEdition/translations/pl.json +++ b/Shadowrun5thEdition/translations/pl.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/pt.json b/Shadowrun5thEdition/translations/pt.json index c0169e65d4..c53a6cff3a 100644 --- a/Shadowrun5thEdition/translations/pt.json +++ b/Shadowrun5thEdition/translations/pt.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/ru.json b/Shadowrun5thEdition/translations/ru.json index c0169e65d4..c53a6cff3a 100644 --- a/Shadowrun5thEdition/translations/ru.json +++ b/Shadowrun5thEdition/translations/ru.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/sv.json b/Shadowrun5thEdition/translations/sv.json index c0169e65d4..c53a6cff3a 100644 --- a/Shadowrun5thEdition/translations/sv.json +++ b/Shadowrun5thEdition/translations/sv.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/tr.json b/Shadowrun5thEdition/translations/tr.json index c0169e65d4..c53a6cff3a 100644 --- a/Shadowrun5thEdition/translations/tr.json +++ b/Shadowrun5thEdition/translations/tr.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/zh.json b/Shadowrun5thEdition/translations/zh.json index c0169e65d4..c53a6cff3a 100644 --- a/Shadowrun5thEdition/translations/zh.json +++ b/Shadowrun5thEdition/translations/zh.json @@ -276,7 +276,7 @@ "power": "Power", "powers": "Powers", "pr": "Professional Rating", - "prep": "Prep...", + "preps": "Prep...", "primary": "Primary", "primaryarmor": "Primary Armor", "primarylifestyle": "Primary Lifestyle", diff --git a/Shadowrun5thEdition/translations/zu.json b/Shadowrun5thEdition/translations/zu.json index 53cdf03ef8..449131a3a8 100644 --- a/Shadowrun5thEdition/translations/zu.json +++ b/Shadowrun5thEdition/translations/zu.json @@ -276,7 +276,7 @@ "power": "crwdns81474:0crwdne81474:0", "powers": "crwdns81476:0crwdne81476:0", "pr": "crwdns84396:0crwdne84396:0", - "prep": "crwdns81478:0crwdne81478:0", + "preps": "crwdns81478:0crwdne81478:0", "primary": "crwdns81480:0crwdne81480:0", "primaryarmor": "crwdns81482:0crwdne81482:0", "primarylifestyle": "crwdns81484:0crwdne81484:0",