diff --git a/Top Secret/TopSecret.css b/Top Secret/TopSecret.css
index 2a3ad12ccc..2511f1aafd 100644
--- a/Top Secret/TopSecret.css
+++ b/Top Secret/TopSecret.css
@@ -23,6 +23,17 @@
width: 100%;
}
+.ui-dialog .tab-content .charsheet label:has(input[type="checkbox"]):hover,
+.ui-dialog .tab-content .charsheet label:has(input[type="radio"]):hover {
+ cursor: pointer;
+}
+
+.ui-dialog .tab-content .charsheet label:has(input[type="checkbox"]:checked) > span,
+.ui-dialog .tab-content .charsheet label:has(input[type="checkbox"]):hover > span {
+ text-shadow: 0 0 black;
+ background-color: #cbcbcb;
+}
+
.ui-dialog .tab-content .charsheet .flex-row > label {
display: flex;
flex: 1 1 6em;
@@ -64,6 +75,16 @@
margin-inline: -7px;
}
+.ui-dialog .tab-content .charsheet details summary > * {
+ display: inline;
+}
+
+.ui-dialog .tab-content .charsheet details > summary {
+ display: list-item;
+ position: relative;
+ cursor: pointer;
+}
+
.ui-dialog .tab-content .charsheet button[type=roll]:before {
content: "t";
font-family: "dicefontd20";
@@ -71,6 +92,25 @@
top: 2px;
}
+.ui-dialog .tab-content .charsheet button[type="action"] {
+ line-height: normal;
+ margin-inline: auto;
+ margin-left: -8px;
+ width: max-content;
+}
+
+.ui-dialog .tab-content .charsheet .hit-determination-grid [type="action"] {
+ margin-left: -8px;
+}
+
+.ui-dialog .tab-content .charsheet .reset-image::after {
+ content: '1';
+ display: inline-block;
+ font-family: 'Pictos';
+ position: relative;
+ top: -1px;
+}
+
.ui-dialog .tab-content .charsheet .logo-text {
color: red;
float: left;
@@ -104,7 +144,8 @@
}
.ui-dialog .tab-content .charsheet label,
-.ui-dialog .tab-content .charsheet label span {
+.ui-dialog .tab-content .charsheet label > span {
+ display: inline-block;
font-size: 1em;
margin: 2px;
}
@@ -116,19 +157,27 @@
color: #777;
cursor: default;
max-width: 3em;
+ text-align: center;
+}
+
+.ui-dialog .tab-content .charsheet input.larger {
+ max-width: 3.75em;
+}
+
+.ui-dialog .tab-content .charsheet nav {
+ display: inline-block;
+ margin-block: .5em 1em;
}
.ui-dialog .tab-content .charsheet input.tab {
border: 5px #888888;
cursor: pointer;
height: 20px;
- left: 6px;
- margin: 10px -1.5px;
- min-width: 132px;
+ margin-top: 6px;
outline: none;
padding: 0;
position: relative;
- width: 132px;
+ width: 95px;
z-index: 1;
}
@@ -142,7 +191,7 @@
font-size: 16px;
height: 20px;
text-align: center;
- width: 150px;
+ width: 95px;
}
.ui-dialog .tab-content .charsheet input.tab:checked::before {
@@ -155,18 +204,18 @@
display: none;
}
-.ui-dialog .tab-content .charsheet input.tab1:checked ~ div.tab1,
-.ui-dialog .tab-content .charsheet input.tab2:checked ~ div.tab2,
-.ui-dialog .tab-content .charsheet input.tab3:checked ~ div.tab3,
-.ui-dialog .tab-content .charsheet input.tab4:checked ~ div.tab4,
-.ui-dialog .tab-content .charsheet input.tab5:checked ~ div.tab5,
-.ui-dialog .tab-content .charsheet input.tab6:checked ~ div.tab6 {
+.ui-dialog .tab-content .charsheet nav:has(input.tab1:checked) ~ div.tab1,
+.ui-dialog .tab-content .charsheet nav:has(input.tab2:checked) ~ div.tab2,
+.ui-dialog .tab-content .charsheet nav:has(input.tab3:checked) ~ div.tab3,
+.ui-dialog .tab-content .charsheet nav:has(input.tab4:checked) ~ div.tab4,
+.ui-dialog .tab-content .charsheet nav:has(input.tab5:checked) ~ div.tab5,
+.ui-dialog .tab-content .charsheet nav:has(input.tab6:checked) ~ div.tab6 {
display: block;
}
.ui-dialog .tab-content .charsheet .instruction {
- font-size: 0.8em;
- font-style: italic;
+ font-family: monospace;
+ font-size: 1.1rem;
padding-bottom: 10px;
}
@@ -189,18 +238,95 @@
.ui-dialog .tab-content .charsheet .hit-determination-grid {
background-color: #dddddd;
- column-gap: 2px;
display: grid;
- grid-template-columns: auto auto auto;
- justify-content: space-around;
+ gap: 4px;
+ grid-template-columns: repeat(3, minmax(18em, 1fr));
margin-bottom: 1em;
+ min-width: min-content;
outline: 1px solid #000;
+ padding: 5px;
+}
+
+.ui-dialog .tab-content .charsheet .mph {
+ display: none;
+}
+
+.ui-dialog .tab-content .charsheet select:has(.show-mph:checked) + .mph {
+ align-items: center;
+ display: inline-flex;
+ margin: -1em auto 1em auto;
+}
+
+.ui-dialog .tab-content .charsheet .hit-determination-misc {
+ margin-block: 0 .5em;
+ max-width: 33%;
+}
+
+.ui-dialog .tab-content .charsheet .hit-determination-misc[open] {
+ background-color: #fff;
+ margin-bottom: 5px;
+ outline: 1px solid #000;
+ padding-left: 4px;
+ position: relative;
+ max-width: 100%;
+}
+
+.ui-dialog .tab-content .charsheet details[open] > summary::after {
+ content: '*';
+ opacity: .35;
+ font-family: 'Pictos';
+ float: right;
+ margin-right: 8px;
+ margin-top: 4px;
+}
+
+.ui-dialog .tab-content .charsheet details[open] > summary:hover::after {
+ opacity: 1;
+}
+
+.ui-dialog .tab-content .charsheet .hit-determination-misc label {
+ font-weight: normal;
+}
+
+.ui-dialog .tab-content .charsheet .hit-determination-automatic-grid {
+ display: grid;
+ grid-template-columns: 4em repeat(10, auto);
+ height: min-content;
+ margin: -3em auto 0 auto;
+ max-width: 28em;
+ text-align: center;
+ width: 55%;
+}
+
+.ui-dialog .tab-content .charsheet .range-of-target {
+ align-self: center;
+ margin-bottom: -1em;
+ margin-inline: auto -2em;
+ max-width: 16em;
+ outline: 1px solid #000;
+ outline-offset: .5em;
+ width: 70%;
+}
+
+.ui-dialog .tab-content .charsheet .range-of-target span {
+ display: inline-flex;
+ width: 100%;
+ justify-content: space-evenly;
+}
+
+.ui-dialog .tab-content .charsheet .range-of-target span > * {
+ flex: 0 1 3em;
+}
+
+.charsheet .hit-determination-automatic-grid > span,
+.charsheet .hit-determination-automatic-grid > input {
+ width: 14px;
}
.ui-dialog .tab-content .charsheet .weapons-grid {
display: grid;
gap: 2px;
- grid-template-columns: 2em minmax(12em, 3fr) minmax(8em, 1.5fr) 4em 2.5em 5em 3em 3em 3em 3em 3em;
+ grid-template-columns: 2em minmax(12em, 3fr) 3em 3em 3em 3em 3.5em 4em 3em 7em 4em 5em 3.5em;
padding-bottom: 2px;
}
@@ -215,6 +341,7 @@
}
.ui-dialog .tab-content .charsheet .weapon-range-modifier-column {
+ border-bottom: 1px solid #000;
grid-column: span 4;
margin-bottom: -1.5em;
}
@@ -222,6 +349,7 @@
.ui-dialog .tab-content .charsheet .general-column-header {
font-weight: bold;
text-align: center;
+ width: auto;
}
.ui-dialog .tab-content .charsheet .full-width-element {
diff --git a/Top Secret/TopSecret.html b/Top Secret/TopSecret.html
index 4c77e49161..b39309bbed 100644
--- a/Top Secret/TopSecret.html
+++ b/Top Secret/TopSecret.html
@@ -20,12 +20,14 @@
Code Name
-
-
-
-
-
-
+
@@ -526,16 +705,18 @@
});
// weapon calcs
- on('change:repeating_weapons:weaponspeedmodifier change:repeating_weapons:pwv', (eventInfo) => {
+ on('change:repeating_weapons', (eventInfo) => {
console.log(`Change detected: ${eventInfo.sourceAttribute}`);
const id = eventInfo.sourceAttribute.split('_')[2];
- getAttrs(['offense', `repeating_weapons_${id}_weaponspeedmodifier`, `repeating_weapons_${id}_pwv`], (v) => {
+ getAttrs(['offense', 'hit_det_total', `repeating_weapons_${id}_weaponspeedmodifier`, `repeating_weapons_${id}_pwv`], (v) => {
const output = {};
const offense = +v.offense || 0;
const weaponSpeed = +v[`repeating_weapons_${id}_weaponspeedmodifier`] || 0;
const PWV = +v[`repeating_weapons_${id}_pwv`] || 0;
+ const hitDetTotal = v.hit_det_total || 0;
output[`repeating_weapons_${id}_basespeed`] = offense + weaponSpeed;
output[`repeating_weapons_${id}_baseaccuracy`] = offense + PWV;
+ output[`repeating_weapons_${id}_hit_det`] = hitDetTotal;
setAttrs(output, {silent: true});
});
});
@@ -562,6 +743,223 @@
});
});
+ // hit determination chart
+
+ // movement of shooter
+ on('change:hit_det_move_of_shooter change:hit_det_shooter_speed_multiplier clicked:hitDetResetAll clicked:hitDetResetMovementOfShooter', (eventInfo) => {
+ console.log(`Change detected: ${eventInfo.sourceAttribute}`);
+ getAttrs(['hit_det_move_of_shooter', 'hit_det_shooter_speed_multiplier'], (v) => {
+ const output = {};
+ let actionButton = eventInfo.triggerName;
+ actionButton = actionButton.replace('clicked:', '');
+ if (actionButton !== 'hitdetresetmovementofshooter' && actionButton !== 'hitdetresetall') {
+ let moveShooter = +v['hit_det_move_of_shooter'] || 0;
+ let speedMult = 0;
+ if (moveShooter === 7) {
+ speedMult = +Math.max(0, v['hit_det_shooter_speed_multiplier'] || 0);
+ }
+ const moveShooterValues = {
+ 0: 0, // Stationary
+ 1: 5, // Stationary and prone
+ 2: -5, // Walking
+ 3: -10, // Wading
+ 4: -10, // Crawling
+ 5: -30, // Running and dodging
+ 6: -20, // Running
+ 7: -10, // Vehicular Movement
+ 8: -20, // Drops Prone
+ };
+ moveShooter = moveShooterValues[moveShooter] || 0;
+ output.hit_det_move_of_shooter_total = moveShooter - speedMult;
+ output.hit_det_shooter_speed_multiplier = speedMult;
+ } else {
+ console.log(`Change detected: Reset`);
+ output.hit_det_move_of_shooter_total = 0;
+ output.hit_det_move_of_shooter = 0;
+ output.hit_det_shooter_speed_multiplier = 0;
+ }
+ setAttrs(output);
+ });
+ });
+
+ // movement of target
+ on('change:hit_det_move_of_target change:hit_det_target_speed_multiplier clicked:hitDetResetAll clicked:hitDetResetMovementOfTarget', (eventInfo) => {
+ console.log(`Change detected: ${eventInfo.sourceAttribute}`);
+ getAttrs(['hit_det_move_of_target', 'hit_det_target_speed_multiplier'], (v) => {
+ const output = {};
+ let actionButton = eventInfo.triggerName;
+ actionButton = actionButton.replace('clicked:', '');
+ if (actionButton !== 'hitdetresetmovementoftarget' && actionButton !== 'hitdetresetall') {
+ let moveTarget = +v['hit_det_move_of_target'] || 0;
+ let speedMult = 0;
+ if (moveTarget === 6) {
+ speedMult = +Math.max(0, v['hit_det_target_speed_multiplier'] || 0);
+ }
+ const moveTargetValues = {
+ 0: 0, // Stationary
+ 1: -5, // Walking
+ 2: -5, // Wading
+ 3: -5, // Crawling
+ 4: -10, // Running
+ 5: -20, // Running and dodging
+ 6: -10, // Vehicular Movement
+ 7: -5, // Drops Prone
+ };
+ moveTarget = moveTargetValues[moveTarget] || 0;
+ output.hit_det_move_of_target_total = moveTarget - speedMult;
+ output.hit_det_target_speed_multiplier = speedMult;
+ } else {
+ console.log(`Change detected: Reset`);
+ output.hit_det_move_of_target_total = 0;
+ output.hit_det_move_of_target = 0;
+ output.hit_det_target_speed_multiplier = 0;
+ }
+ setAttrs(output);
+ });
+ });
+
+ // wounds
+ on('change:hit_det_wounds clicked:hitDetResetAll clicked:hitDetResetWounds', (eventInfo) => {
+ console.log(`Change detected: ${eventInfo.sourceAttribute}`);
+ getAttrs(['hit_det_wounds'], (v) => {
+ const output = {};
+ let actionButton = eventInfo.triggerName;
+ actionButton = actionButton.replace('clicked:', '');
+ if (actionButton !== 'hitdetresetwounds' && actionButton !== 'hitdetresetall') {
+ const valWounds = +v['hit_det_wounds'] || 0;
+ output.hit_det_wounds_total = valWounds;
+ } else {
+ console.log(`Change detected: Reset`);
+ output.hit_det_wounds_total = 0;
+ output.hit_det_wounds = 0;
+ }
+ setAttrs(output);
+ });
+ });
+
+ // miscellaneous
+ on(
+ 'change:hit_det_misc_weapon_at_rest change:hit_det_misc_2nd_consecutive change:hit_det_misc_additional_consecutive change:hit_det_misc_additional_consecutive_multiplier change:hit_det_misc_wrong_hand change:hit_det_misc_wounded_gun_hand change:hit_det_misc_wounded_gun_hand_multiplier change:hit_det_misc_two_weapons change:hit_det_misc_hip_shooting change:hit_det_misc_obscured change:hit_det_misc_gyrojet change:hit_det_misc_total clicked:hitDetResetAll clicked:hitDetResetMisc',
+ (eventInfo) => {
+ console.log(`Change detected: ${eventInfo.sourceAttribute}`);
+ getAttrs(
+ [
+ 'hit_det_misc_weapon_at_rest',
+ 'hit_det_misc_2nd_consecutive',
+ 'hit_det_misc_additional_consecutive',
+ 'hit_det_misc_additional_consecutive_multiplier',
+ 'hit_det_misc_wrong_hand',
+ 'hit_det_misc_wounded_gun_hand',
+ 'hit_det_misc_wounded_gun_hand_multiplier',
+ 'hit_det_misc_two_weapons',
+ 'hit_det_misc_hip_shooting',
+ 'hit_det_misc_obscured',
+ 'hit_det_misc_gyrojet',
+ 'hit_det_misc_total',
+ ],
+ (v) => {
+ const output = {};
+ let actionButton = eventInfo.triggerName;
+ actionButton = actionButton.replace('clicked:', '');
+ if (actionButton !== 'hitdetresetmisc' && actionButton !== 'hitdetresetall') {
+ const valWeapon_at_rest = +v.hit_det_misc_weapon_at_rest || 0;
+ const val2nd_consecutive = +v.hit_det_misc_2nd_consecutive || 0;
+ const valAdditional_consecutive = +v.hit_det_misc_additional_consecutive || 0;
+ const valAdditional_consecutive_multiplier = +v.hit_det_misc_additional_consecutive_multiplier || 0;
+ const valWrong_hand = +v.hit_det_misc_wrong_hand || 0;
+ const valWounded_gun_hand = +v.hit_det_misc_wounded_gun_hand || 0;
+ const valWounded_gun_hand_multiplier = +v.hit_det_misc_wounded_gun_hand_multiplier || 0;
+ const valTwo_weapons = +v.hit_det_misc_two_weapons || 0;
+ const valHip_shooting = +v.hit_det_misc_hip_shooting || 0;
+ const valObscured = +v.hit_det_misc_obscured || 0;
+ const valGyrojet = +v.hit_det_misc_gyrojet || 0;
+
+ output.hit_det_misc_weapon_at_rest = valWeapon_at_rest;
+ output.hit_det_misc_2nd_consecutive = val2nd_consecutive;
+ output.hit_det_misc_additional_consecutive = valAdditional_consecutive;
+ output.hit_det_misc_additional_consecutive_multiplier = valAdditional_consecutive_multiplier;
+ output.hit_det_misc_wrong_hand = valWrong_hand;
+ output.hit_det_misc_wounded_gun_hand = valWounded_gun_hand;
+ output.hit_det_misc_wounded_gun_hand_multiplier = valWounded_gun_hand_multiplier;
+ output.hit_det_misc_two_weapons = valTwo_weapons;
+ output.hit_det_misc_hip_shooting = valHip_shooting;
+ output.hit_det_misc_obscured = valObscured;
+ output.hit_det_misc_gyrojet = valGyrojet;
+ output.hit_det_misc_total =
+ valWeapon_at_rest +
+ val2nd_consecutive +
+ valAdditional_consecutive * valAdditional_consecutive_multiplier +
+ valWrong_hand +
+ valWounded_gun_hand * valWounded_gun_hand_multiplier +
+ valTwo_weapons +
+ valHip_shooting +
+ valObscured +
+ valGyrojet;
+ } else {
+ console.log(`Change detected: Reset`);
+ output.hit_det_misc_weapon_at_rest = 0;
+ output.hit_det_misc_2nd_consecutive = 0;
+ output.hit_det_misc_additional_consecutive = 0;
+ output.hit_det_misc_additional_consecutive_multiplier = 1;
+ output.hit_det_misc_wrong_hand = 0;
+ output.hit_det_misc_wounded_gun_hand = 0;
+ output.hit_det_misc_wounded_gun_hand_multiplier = 1;
+ output.hit_det_misc_two_weapons = 0;
+ output.hit_det_misc_hip_shooting = 0;
+ output.hit_det_misc_obscured = 0;
+ output.hit_det_misc_gyrojet = 0;
+ output.hit_det_misc_total = 0;
+ }
+ setAttrs(output);
+ },
+ );
+ },
+ );
+
+ // automatic weapons
+ on('change:hit_det_automatic clicked:hitDetResetAll clicked:hitDetResetAutomaticWeapons', (eventInfo) => {
+ console.log(`Change detected: ${eventInfo.sourceAttribute}`);
+ getAttrs(['hit_det_automatic'], (v) => {
+ const output = {};
+ let actionButton = eventInfo.triggerName;
+ actionButton = actionButton.replace('clicked:', '');
+ if (actionButton !== 'hitdetresetautomaticweapons' && actionButton !== 'hitdetresetall') {
+ const valAutomatic = +v['hit_det_automatic'] || 0;
+ output.hit_det_automatic_total = valAutomatic;
+ } else {
+ console.log(`Change detected: Reset`);
+ output.hit_det_automatic_total = 0;
+ output.hit_det_automatic = 0;
+ }
+ setAttrs(output);
+ });
+ });
+
+ // hit determination total
+ on('change:hit_det_move_of_shooter_total change:hit_det_move_of_target_total change:hit_det_wounds_total change:hit_det_misc_total change:hit_det_automatic_total', (eventInfo) => {
+ console.log(`Change detected: ${eventInfo.sourceAttribute}`);
+ getSectionIDs('repeating_weapons', (idArray) => {
+ const output = {};
+ const fields = ['hit_det_move_of_shooter_total', 'hit_det_move_of_target_total', 'hit_det_wounds_total', 'hit_det_misc_total', 'hit_det_automatic_total'];
+ _.each(idArray, (id) => {
+ fields.push(section_attribute('weapons', id, 'hit_det'));
+ });
+ getAttrs(fields, (v) => {
+ const hit_det_move_of_shooter_total = +v.hit_det_move_of_shooter_total || 0;
+ const hit_det_move_of_target_total = +v.hit_det_move_of_target_total || 0;
+ const hit_det_wounds_total = +v.hit_det_wounds_total || 0;
+ const hit_det_misc_total = +v.hit_det_misc_total || 0;
+ const hit_det_automatic_total = +v.hit_det_automatic_total || 0;
+ const hitDetTotal = hit_det_move_of_shooter_total + hit_det_move_of_target_total + hit_det_wounds_total + hit_det_misc_total + hit_det_automatic_total;
+ output.hit_det_total = hitDetTotal;
+ idArray.forEach((id) => {
+ output[section_attribute('weapons', id, 'hit_det')] = hitDetTotal;
+ });
+ setAttrs(output, {silent: true});
+ });
+ });
+ });
+
// one-time update
on('sheet:opened', (eventInfo) => {
console.log(`Change detected: sheet_version check`);
diff --git a/Top Secret/sheet.json b/Top Secret/sheet.json
index 48b78b9030..4e8783194f 100644
--- a/Top Secret/sheet.json
+++ b/Top Secret/sheet.json
@@ -4,6 +4,5 @@
"authors": "Richard Gavin (@rocketheadent)",
"roll20userid": "1649310",
"preview": "TopSecret.png",
- "instructions": "",
- "legacy": true
+ "instructions": ""
}
\ No newline at end of file