Compare commits

...

6 Commits

5 changed files with 124 additions and 39 deletions

20
TODO.md
View File

@ -51,12 +51,26 @@
### open ### open
- SVG Improvements
- verbleibende Bilder in SVGs umwandeln/nachbauen
- umwandeln: Inkscape
- nachbauen: svgedit.netlify.com,
- betrifft: add.png, newround.png, cross.png, zzz.png
- dann muss ich add und newround auch nicht mehr mit CSS filter auf die richtige Farbe bringen
- bestehende SVGs vereinfachen (polygon oder rect statt path)
- betrifft act
- macht es Sinn, die SVGs in eigene Dateien zu packen? Derzeit sind sie im HTML Sourcecode
- als Symbole definieren: https://stackoverflow.com/a/59614656
- make color scheme friendly for people with red green bindness (Felix)
- see here: https://venngage.com/tools/accessible-color-palette-generator
- tests
- weiß: ghostwhite, white, lightgrey
- gelb: gold, yellow, orange
- grün: lawngreen, lime, greenyellow
- rot: orangered, red, darkred
- im FP3T Tor Browser kann ich rauszoomen, bis ich die ganzen damage monitors und action menus sehe -> verhindern! - im FP3T Tor Browser kann ich rauszoomen, bis ich die ganzen damage monitors und action menus sehe -> verhindern!
- action-menu und damage-monitor sliden jetzt nicht mehr rein, sondern bleiben an Ort und Stelle - action-menu und damage-monitor sliden jetzt nicht mehr rein, sondern bleiben an Ort und Stelle
- das sollte die Sache verhindern - das sollte die Sache verhindern
- make color scheme friendly for people with red green bindness (Felix)
- see here: https://venngage.com/tools/accessible-color-palette-generator
- current main color (turquoise): #001d1d
- warum fkt. das Ganze nicht als Webapp? - warum fkt. das Ganze nicht als Webapp?
- Firefox (android) sieht die Seite nicht als installable an - Firefox (android) sieht die Seite nicht als installable an
- Webmanifest ist aber da und scheint auch in Ordnung zu sein (sagt Firefox on Linux) - Webmanifest ist aber da und scheint auch in Ordnung zu sein (sagt Firefox on Linux)

View File

@ -21,17 +21,8 @@
"jest": "^29.4.3", "jest": "^29.4.3",
"jest-environment-jsdom": "^29.4.3", "jest-environment-jsdom": "^29.4.3",
"jsdom": "^21.1.0", "jsdom": "^21.1.0",
"parcel": "^2.8.3", "parcel": "^2.8.3"
"parcel-reporter-static-files-copy": "^1.5.0"
}, },
"staticFiles": [
{
"staticPath": "src/img/zzz.png"
},
{
"staticPath": "src/img/cross.png"
}
],
"scripts": { "scripts": {
"start": "npx parcel serve src/index.html --public-url / --dist-dir dist", "start": "npx parcel serve src/index.html --public-url / --dist-dir dist",
"prebuild": "rm -rf dist/", "prebuild": "rm -rf dist/",

View File

@ -57,6 +57,8 @@ body {
background-size: cover; background-size: cover;
} }
.svg-icons { display: none; }
.icon { fill: $fg; } .icon { fill: $fg; }
.sr2-button:focus-visible { .sr2-button:focus-visible {
@ -97,10 +99,10 @@ header.navbar {
margin-right: 3px; margin-right: 3px;
width: 38px; width: 38px;
img { svg {
width: 32px; width: 32px;
height: 32px; height: 32px;
filter: invert(34%) sepia(78%) saturate(7014%) hue-rotate(316deg) brightness(95%) contrast(105%); fill: $fg;
} }
} }
@ -262,7 +264,7 @@ header.navbar {
.damage-dropdown, .damage-dropdown,
.actions-dropdown { .actions-dropdown {
display: inline-block; display: inline-block;
position: relative; position: relative; // required in order to center dropdowns vertically
} }
.damage-monitor, .damage-monitor,
@ -275,24 +277,18 @@ header.navbar {
padding-top: 10px; padding-top: 10px;
padding-bottom: 10px; padding-bottom: 10px;
position: absolute; position: absolute;
// top: calc(100% - 2px);
// transition: transform .25s ease-in-out;
z-index: 200; z-index: 200;
// center element horizontally w/ respect to parent
right: 50%; right: 50%;
transform: translateX(50%); transform: translateX(50%);
opacity: 0%; // transition: fade in/out
transition: opacity .2s ease-in-out, visibility .2s; transition: opacity .2s ease-in-out, visibility .2s;
opacity: 0%;
visibility: hidden; visibility: hidden;
} }
//.damage-monitor { left: calc(100vw - 1em); }
//.actions-menu { left: calc(100vw + 3.5em); }
//.seen { transform: translateX(-100vw); }
.seen { .seen {
visibility: visible; visibility: visible;
opacity: 100%; opacity: 100%;
@ -337,6 +333,11 @@ header.navbar {
background: radial-gradient(circle at center, $fg-bright, $fg); background: radial-gradient(circle at center, $fg-bright, $fg);
box-shadow: 0 0 3px $fg-bright, 0 0 6px $fg, 0 0 12px $fg-dark; box-shadow: 0 0 3px $fg-bright, 0 0 6px $fg, 0 0 12px $fg-dark;
} }
svg {
height: 16px;
width: 16px;
}
} }
@ -369,7 +370,7 @@ footer {
user-select: auto; user-select: auto;
a { a {
color: hotpink; color: $bg-bright;
text-decoration: none; text-decoration: none;
} }
} }

View File

@ -30,12 +30,91 @@
</head> </head>
<body> <body>
<svg version="2.0" class="svg-icons">
<defs>
<!-- add combatant -->
<symbol id="add" viewbox="0 0 512 512">
<path d="M 192 96 h -96 q 0 -96 96 -96 z" />
<rect height="96" width="64" x="224" y="0" />
<path d="M 320 96 h 96 q 0 -96 -96 -96 z" />
<path d="M 96 128 h 320 v 80 q 0 32 -32 32 h -256 q -32 0 -32 -32 z" />
<path d="M 128 272 q 64 32 128 32 v -32 Z" />
<path d="M 128 304 q 64 28 128 28 v 52 h -128 Z" />
<path d="M 96 416 h -96 q 0 -128 96 -128 z" />
<rect x="0" y="448" width="96" height="64" />
<path d="M 128 512 v -96 h 128 v 32 h -80 q -16 0 -16 16 v 48 Z" />
<rect x="192" y="480" width="64" height="32" />
<rect x="288" y="368" width="228" height="64" />
<rect x="368" y="288" width="64" height="228" />
</symbol>
<!-- new round -->
<symbol id="newround" viewbox="0 0 512 512">
<path d="M 464 512 h -160 q -48 0 -48 -48 v -160 q 0 -48 48 -48 h 160 q 48 0 48 48 v 160 q 0 48 -48 48 Z M 444 472 a 16 16 0 1 0 -1 0 Z m 0 -72 a 16 16 0 1 0 -1 0 Z m 0 -72 a 16 16 0 1 0 -1 0 Z m -112 0 a 16 16 0 1 0 -1 0 Z m 0 72 a 16 16 0 1 0 -1 0 Z m 0 72 a 16 16 0 1 0 -1 0 Z " fill-rule="evenodd" />
<path d="M 208 320 q -34 34 -68 0 l -113 -113 q -34 -34 0 -68 l 113 -113 q 34 -34 68 0 l 113 113 q 34 34 0 68 l -16 16 h -16 q -64 0 -64 64 v 16 z M 172 264 a 16 16 0 1 0 -1 0 Z m 0 -80 a 16 16 0 1 0 -1 0 Z m 0 -80 a 16 16 0 1 0 -1 0 Z" fill-rule="evenodd" />
</symbol>
<!-- act (-10) -->
<symbol id="act" viewBox="0 0 512 512">
<rect x="0" y="272" height="64" width="96" />
<path d="M 160 64 h 64 v 384 h -64 v -296 l -64 64 l -40 -40 Z" />
<path d="M 352 64 h 96 l 64 64 v 256 l -64 64 h -96 l -64 -64 v -256 l 64 -64 l 32 64 h 32 l 32 32 v 192 l -32 32 h -32 l -32 -32 v -192 l 32 -32" fill-rule="evenodd" />
</symbol>
<!-- take damage -->
<symbol id="take-damage" viewBox="0 0 512 512">
<path d="M 0 288 L 144 224 L 64 32 L 224 128 L 272 0 L 336 144 L 480 96 L 400 224 L 512 304 L 384 352 L 432 512 L 272 416 L 128 512 L 160 352 L 0 288 L 166 267 L 222 290 L 211 346 L 262 312 L 318 346 L 301 290 L 346 273 L 306 245 L 334 200 L 284 217 L 262 166 L 245 211 L 189 178 L 217 245 L 166 267" fill-rule="evenodd" />
</symbol>
<!-- more actions -->
<symbol id="more-actions" viewbox="0 0 512 512">
<polygon points="32 32 480 32 256 480" />
</symbol>
<!-- edit combatant -->
<symbol id="edit" viewbox="0 0 512 512">
<polygon points="0 512 0 352 224 128 384 288 160 512" />
<polygon points="352 0 512 160 416 256 256 96" />
</symbol>
<!-- clone combatant -->
<symbol id="clone" viewbox="0 0 512 512">
<rect x="0" y="0" width="512" height="128" />
<rect x="0" y="384" width="512" height="128" />
<polygon points="128 192 384 192 256 320" />
</symbol>
<!-- delete combatant -->
<symbol id="delete" viewbox="0 0 512 512">
<polygon points="96 0 416 0 416 64 480 64 480 128 32 128 32 64 96 64" />
<path d="M 64 512 H 448 V 160 H 64 V 512 L 128 480 V 192 H 192 V 480 H 224 V 192 H 288 V 480 H 320 V 192 H 384 V 480 H 128" fill-rule="evenodd" />
</symbol>
<!-- K.O. -->
<symbol id="ko" viewbox="0 0 512 512">
<polygon points="512 0 288 0 288 64 424 64 288 240 288 304 512 304 512 240 376 240 512 64" />
<polygon points="512 0 288 0 288 64 424 64 288 240 288 304 512 304 512 240 372 240 512 64" transform="scale(.8) translate(-160,328) rotate(-20)" />
<polygon points="512 0 288 0 288 64 424 64 288 240 288 304 512 304 512 240 372 240 512 64" transform="scale(.6) translate(-232,768) rotate(-35) " />
</symbol>
<!-- dead -->
<symbol id="dead" viewbox="0 0 512 512">
<rect x="208" y="0" width="96" height="512" />
<rect x="80" y="112" width="352" height="96" />
</symbol>
</defs>
</svg>
<div class="container"> <div class="container">
<header class="navbar navbar-expand" data-augmented-ui="tl-2-clip-x tr-clip-y bl-clip-y br-2-clip-x b-scoop-x both"> <header class="navbar navbar-expand" data-augmented-ui="tl-2-clip-x tr-clip-y bl-clip-y br-2-clip-x b-scoop-x both">
<span class="navbar-brand ps-4">SR2 Initiative Tracker</span> <span class="navbar-brand ps-4">SR2 Initiative Tracker</span>
<nav class="container-fluid justify-content-end" aria-label="Main navigation"> <nav class="container-fluid justify-content-end" aria-label="Main navigation">
<button type="submit" class="sr2-button" id="add-combatant-button" title="Add combatant" data-bs-toggle="modal" data-bs-target="#combatant-modal"><img src="img/add.png" alt="user outline with a plus sign"></button> <button type="submit" class="sr2-button" id="add-combatant-button" title="Add combatant" data-bs-toggle="modal" data-bs-target="#combatant-modal"><svg version="2.0">
<button type="submit" class="sr2-button" id="new-round-button" title="Start new round" data-bs-toggle="modal" data-bs-target="#confirm-modal"><img src="img/newround.png" alt="a die being rolled"></button> <use href="#add" />
</svg>
</button>
<button type="submit" class="sr2-button" id="new-round-button" title="Start new round" data-bs-toggle="modal" data-bs-target="#confirm-modal"><svg version="2.0"><use href="#newround" /></svg>
</button>
</nav> </nav>
</header> </header>
</div> </div>

View File

@ -33,16 +33,16 @@ const COMBATANT_TABLE_ROW = [
'<td class="combatant-ini" title="Effective initiative (w/ wound penalties)" data-bs-toggle="modal" data-bs-target="#combatant-modal" data-augmented-ui="both"></td>\n', '<td class="combatant-ini" title="Effective initiative (w/ wound penalties)" data-bs-toggle="modal" data-bs-target="#combatant-modal" data-augmented-ui="both"></td>\n',
'<td class="combatant-dice-and-rea" title="Iniative dice and reaction" data-bs-toggle="modal" data-bs-target="#combatant-modal" data-augmented-ui="both"><span class="combatant-dice"></span>D+<span class="combatant-rea"></span></td>\n', '<td class="combatant-dice-and-rea" title="Iniative dice and reaction" data-bs-toggle="modal" data-bs-target="#combatant-modal" data-augmented-ui="both"><span class="combatant-dice"></span>D+<span class="combatant-rea"></span></td>\n',
'<td class="combatant-actions" data-augmented-ui="tr-clip-y br-scoop both">\n', '<td class="combatant-actions" data-augmented-ui="tr-clip-y br-scoop both">\n',
'<button type="button" class="sr2-button act-button" title="Act and reduce ini by 10"><svg class="icon" viewBox="0 0 512 512"><path d="M 0 272 h 96 v 64 h -96 Z" /><path d="M 160 64 h 64 v 384 h -64 v -296 l -64 64 l -40 -40 Z" /><path d="M 352 64 h 96 l 64 64 v 256 l -64 64 h -96 l -64 -64 v -256 l 64 -64 l 32 64 h 32 l 32 32 v 192 l -32 32 h -32 l -32 -32 v -192 l 32 -32" fill-rule="evenodd" /></svg></button>\n', '<button type="button" class="sr2-button act-button" title="Act and reduce ini by 10"><svg class="icon"><use href="#act" /></svg></button>\n',
'<div class="damage-dropdown">\n', '<div class="damage-dropdown">\n',
'<button type="button" class="sr2-button damage-button" title="Take damage"><svg class="icon" viewBox="0 0 512 512"><path d="M 0 288 L 144 224 L 64 32 L 224 128 L 272 0 L 336 144 L 480 96 L 400 224 L 512 304 L 384 352 L 432 512 L 272 416 L 128 512 L 160 352 L 0 288 L 166 267 L 222 290 L 211 346 L 262 312 L 318 346 L 301 290 L 346 273 L 306 245 L 334 200 L 284 217 L 262 166 L 245 211 L 189 178 L 217 245 L 166 267" fill-rule="evenodd" /></svg></button>\n', '<button type="button" class="sr2-button damage-button" title="Take damage"><svg class="icon"><use href="#take-damage" /></svg></button>\n',
'</div>\n', '</div>\n',
'<div class="actions-dropdown">\n', '<div class="actions-dropdown">\n',
'<button type="button" class="sr2-button actions-button" title="More actions"><svg class="icon" viewBox="0 0 512 512"><polygon points="32 32 480 32 256 480" /></svg></button>\n', '<button type="button" class="sr2-button actions-button" title="More actions"><svg class="icon"><use href="#more-actions" /</svg></button>\n',
'<div class="actions-menu" data-augmented-ui="tl-scoop bl-clip-y tr-clip-y br-scoop both">\n', '<div class="actions-menu" data-augmented-ui="tl-scoop bl-clip-y tr-clip-y br-scoop both">\n',
'<button type="button" class="sr2-button edit-button" title="Edit combatant" data-bs-toggle="modal" data-bs-target="#combatant-modal" tabindex="-1"><svg class="icon" viewBox="0 0 512 512"><polygon points="0 512 0 352 224 128 384 288 160 512" /><polygon points="352 0 512 160 416 256 256 96" /></svg></button>\n', '<button type="button" class="sr2-button edit-button" title="Edit combatant" data-bs-toggle="modal" data-bs-target="#combatant-modal" tabindex="-1"><svg class="icon"><use href="#edit" /></svg></button>\n',
'<button type="button" class="sr2-button clone-button" title="Clone combatant" data-bs-toggle="modal" data-bs-target="#combatant-modal" tabindex="-1"><svg class="icon" viewBox="0 0 512 512"><rect x="0" y="0" width="512" height="128" /><rect x="0" y="384" width="512" height="128" /><polygon points="128 192 384 192 256 320" />/svg></button>\n', '<button type="button" class="sr2-button clone-button" title="Clone combatant" data-bs-toggle="modal" data-bs-target="#combatant-modal" tabindex="-1"><svg class="icon"><use href="#clone" /></svg></button>\n',
'<button type="button" class="sr2-button remove-button" title="Remove combatant" data-bs-toggle="modal" data-bs-target="#confirm-modal" tabindex="-1"><svg class="icon" viewBox="0 0 512 512"><polygon points="96 0 416 0 416 64 480 64 480 128 32 128 32 64 96 64" /><path d="M 64 512 H 448 V 160 H 64 V 512 L 128 480 V 192 H 192 V 480 H 224 V 192 H 288 V 480 H 320 V 192 H 384 V 480 H 128" fill-rule="evenodd" /></svg></button>\n', '<button type="button" class="sr2-button remove-button" title="Remove combatant" data-bs-toggle="modal" data-bs-target="#confirm-modal" tabindex="-1"><svg class="icon"><use href="#delete" /></svg></button>\n',
'</div>\n', '</div>\n',
'</div>\n', '</div>\n',
'</td>\n', '</td>\n',
@ -60,7 +60,7 @@ const DAMAGE_MONITOR_HTML = [
'<tr><td><button type="button" class="damage-stun active" tabindex="-1"></button></td><td><button type="button" class="damage-physical active" tabindex="-1"></button></td></tr>\n', '<tr><td><button type="button" class="damage-stun active" tabindex="-1"></button></td><td><button type="button" class="damage-physical active" tabindex="-1"></button></td></tr>\n',
'<tr><td><button type="button" class="damage-stun active" tabindex="-1"></button></td><td><button type="button" class="damage-physical active" tabindex="-1"></button></td></tr>\n', '<tr><td><button type="button" class="damage-stun active" tabindex="-1"></button></td><td><button type="button" class="damage-physical active" tabindex="-1"></button></td></tr>\n',
'<tr><td><button type="button" class="damage-stun active" tabindex="-1"></button></td><td><button type="button" class="damage-physical active" tabindex="-1"></button></td></tr>\n', '<tr><td><button type="button" class="damage-stun active" tabindex="-1"></button></td><td><button type="button" class="damage-physical active" tabindex="-1"></button></td></tr>\n',
'<tr><td><button type="button" class="damage-stun active" title="K.O." tabindex="-1"><img src="zzz.png" height="16" /></button></td><td><button type="button" class="damage-physical active" title="Dead" tabindex="-1" ><img src="cross.png" height="16"/></button></td></tr>\n', '<tr><td><button type="button" class="damage-stun active" title="K.O." tabindex="-1"><svg><use href="#ko" /></svg></button></td><td><button type="button" class="damage-physical active" title="Dead" tabindex="-1" ><svg><use href="#dead" /></svg></button></td></tr>\n',
'</table>\n', '</table>\n',
'</div>'].join(""); '</div>'].join("");
@ -105,9 +105,9 @@ function whoGoesFirst(a, b) {
// compute a combatant's effective ini value (modified by wound penalties) // compute a combatant's effective ini value (modified by wound penalties)
function getEffectiveIni(tr) { function getEffectiveIni(tr) {
// return -1 if combatant is K.O. or dead // return 0 if combatant is K.O. or dead
if ($(tr).hasClass("ko-or-dead")) { if ($(tr).hasClass("ko-or-dead")) {
return -1; return 0;
} }
// otherwise compute effective ini (true ini minus wound penalties) // otherwise compute effective ini (true ini minus wound penalties)
let effectiveIni = parseInt($(tr).attr("data-true-ini")) - DAMAGE_PENALTY[parseInt($(tr).attr("data-damage-stun")) || 0] - DAMAGE_PENALTY[parseInt($(tr).attr("data-damage-physical")) || 0]; let effectiveIni = parseInt($(tr).attr("data-true-ini")) - DAMAGE_PENALTY[parseInt($(tr).attr("data-damage-stun")) || 0] - DAMAGE_PENALTY[parseInt($(tr).attr("data-damage-physical")) || 0];
@ -291,7 +291,7 @@ function addCombatant(e) {
// apply damage to combatant // apply damage to combatant
function applyDamage(e) { function applyDamage(e) {
let $btn = $(e.target).is("button") ? $(e.target) : $(e.target).parent(); let $btn = $(e.target).is("button") ? $(e.target) : $(e.target).closest("button");
// retrieve new damage level and type from button position and "damage-[type]" class // retrieve new damage level and type from button position and "damage-[type]" class
let damageLevel = $btn.parent().parent().index(); let damageLevel = $btn.parent().parent().index();
if ( $btn.hasClass("active") ) { if ( $btn.hasClass("active") ) {
@ -511,4 +511,4 @@ $(document).ready(function () {
addTestCombatant(); addTestCombatant();
}); });
module.exports = { rollForInitiative, validateCombatant }; module.exports = { rollForInitiative, validateCombatant, whoGoesFirst, getEffectiveIni };