index : btroops | |
Virtual board game-aid for BattleTroops, an infantry combat simulator wargame published by FASA in 1989. |
aboutsummaryrefslogtreecommitdiff |
diff options
author | Catalin Mititiuc <webdevcat@proton.me> | 2024-07-29 10:29:54 -0700 |
---|---|---|
committer | Catalin Mititiuc <webdevcat@proton.me> | 2024-07-29 10:29:54 -0700 |
commit | 63fb4139d5ac5207b057bce46c4288df982bbeb1 (patch) | |
tree | 80b2b0c839d94e3af04cc9f2df6c45c169f600d2 /src | |
parent | e746cfb216836e26a6c060558278d724bd3ed5d5 (diff) |
Add ability to deactivate/reactivate soldier records; make hex clearing work with right-click and add a confirmation modal dialog
Diffstat (limited to 'src')
-rw-r--r-- | src/index.js | 8 | ||||
-rw-r--r-- | src/modules/gameboard.js | 103 | ||||
-rw-r--r-- | src/modules/record_sheet.js | 49 |
3 files changed, 74 insertions, 86 deletions
diff --git a/src/index.js b/src/index.js index 2cd2db6..2e2e306 100644 --- a/src/index.js +++ b/src/index.js @@ -145,7 +145,7 @@ async function load() { document.querySelectorAll('.end-turn').forEach(el => el.addEventListener('click', ({ target: { dataset: { allegiance: opponent }}}) => { const dataSelector = `[data-allegiance="${opponent}"]`, - opponentRecords = Array.from(document.querySelectorAll(`.soldier-record${dataSelector}`)), + opponentRecords = Array.from(document.querySelectorAll(`.soldier-record${dataSelector}:not(.inactive)`)), firstOpponentRecord = opponentRecords.sort((el1, el2) => el1.dataset.number > el2.dataset.number).at(0); el.setAttribute('disabled', ''); @@ -154,7 +154,11 @@ document.querySelectorAll('.end-turn').forEach(el => clearMoveEndedIndicators(opponentRecords); gameboard.clearFiringArcs(opponent); - Observable.notify('select', firstOpponentRecord); + + if (firstOpponentRecord) { + Observable.notify('select', firstOpponentRecord); + firstOpponentRecord.scrollIntoView({ behavior: 'smooth' }); + } }) ); diff --git a/src/modules/gameboard.js b/src/modules/gameboard.js index 7c22dce..02b9c0f 100644 --- a/src/modules/gameboard.js +++ b/src/modules/gameboard.js @@ -205,6 +205,14 @@ function endMove() { } } +// Work around webkit bug https://bugs.webkit.org/show_bug.cgi?id=233432 +function workaroundForWebKitBug233432(listener) { + return e => { + const elUnderCursor = svg.parentNode.elementFromPoint(e.clientX, e.clientY); + if (!e.target.contains(elUnderCursor)) listener(e); + }; +} + export function start(el) { svg = el; const gridTop = svg.querySelector('.grid-top'); @@ -221,20 +229,20 @@ export function start(el) { } }); - gridTop.addEventListener('pointerleave', e => { - // Work around webkit bug https://bugs.webkit.org/show_bug.cgi?id=233432 - const elUnderCursor = svg.parentNode.elementFromPoint(e.clientX, e.clientY); - if (!e.target.contains(elUnderCursor)) { - console.log(['pointerleave', gridTop]); - [...top.container.children].forEach(child => { - top.collection.get(child).parent.append(child); - top.collection.delete(child); - }); - - top.cell = null; - } + clearHexDialog.querySelector('button[value="confirm"]').addEventListener('click', function(e) { + e.preventDefault(); + clearHexDialog.close(this.value); }); + gridTop.addEventListener('pointerleave', workaroundForWebKitBug233432(e => { + [...top.container.children].forEach(child => { + top.collection.get(child).parent.append(child); + top.collection.delete(child); + }); + + top.cell = null; + })); + topHex.addEventListener('click', clickHandler); topHex.addEventListener('contextmenu', e => { @@ -246,8 +254,6 @@ export function start(el) { startingLocations && getUnits(startingLocations).forEach(unit => unit.addEventListener('click', selectOffBoard)); function clickHandler(e) { - console.log('top hex click event'); - //const occupant = getCellOccupant(this); const occupant = svg.querySelector('.grid-top .container .counter') let toPlace = placing.pop(); @@ -257,10 +263,8 @@ export function start(el) { if (isCounter(toPlace)) arrangeCounters(top.container); removeEventListener("keydown", handleMechTemplateRotation); } else if (toPlace && !occupant) { - //soldier.place(svg, toPlace, this); top.collection.set(toPlace, { parent: top.cell }); top.container.prepend(toPlace); - //toPlace.removeEventListener('click', selectOffBoard); placing.push(toPlace); getLockedSightLine(svg) ? updateSightLine(top.cell) : clearSightLine(); } else if (toPlace && occupant) { @@ -271,79 +275,14 @@ export function start(el) { } } else if (!toPlace && occupant) { Observable.notify('select', occupant); - } else { - console.log(['removing this contents', this]); - getCellContents(this).forEach(el => el.remove()); } const selected = getSelected(); } getCells(svg).forEach(cell => { - cell.addEventListener('click', e => { - console.log('cell clickevent'); - const occupant = getCellOccupant(cell); - let toPlace = placing.pop(); - - if (isCounter(toPlace) || isMechTemplate(toPlace)) { - //getHex(cell).after(toPlace); - top.collection.set(toPlace, { parent: cell }); - top.container.append(toPlace); - //if (isCounter(toPlace)) arrangeCounters(cell); - if (isCounter(toPlace)) arrangeCounters(top.container); - removeEventListener("keydown", handleMechTemplateRotation); - } else if (toPlace && !occupant) { - soldier.place(svg, toPlace, cell); - toPlace.removeEventListener('click', selectOffBoard); - placing.push(toPlace); - getLockedSightLine(svg) ? updateSightLine(cell) : clearSightLine(); - } else if (toPlace && occupant) { - if (toPlace === occupant) { - if (hasPreviousMoveInHistory(toPlace)) { - toPlace = moveBackOneStepInHistory(toPlace); - placing.push(toPlace); - getLockedSightLine(svg) ? updateSightLine(toPlace.parentElement) : drawSightLine(toPlace.parentElement, cell); - } else { - Observable.notify('select'); - } - } else if (!occupant.classList.contains('clone')) { - Observable.notify('select', occupant); - } else { - if (isClone(occupant).of(toPlace)) { - if (hasPreviousMoveInHistory(occupant)) { - deleteClone(occupant, toPlace, cell); - } else { - toPlace = clearMoveHistory(occupant, toPlace); - getLockedSightLine(svg) ? updateSightLine(cell) : clearSightLine(); - } - } - placing.push(toPlace); - } - } else if (!toPlace && occupant) { - Observable.notify('select', occupant); - } else { - console.log('removing cell contents', cell); - getCellContents(cell).forEach(el => el.remove()); - } - - const selected = getSelected(); - }); - - //cell.addEventListener('dblclick', e => { - // const toPlace = placing.pop(), - // occupant = getCellOccupant(cell); - // - // if (toPlace && occupant && toPlace === occupant) { - // const { number, allegiance } = toPlace.dataset, - // selector = `[data-allegiance="${allegiance}"][data-number="${number}"]`; - // - // svg.querySelectorAll(selector).forEach(el => el.remove()); - // Observable.notify('select'); - // } - //}); - cell.addEventListener('pointerover', () => { - console.log(['pointerenter', cell]); + //console.log(['pointerenter', cell]); top.cell = cell; diff --git a/src/modules/record_sheet.js b/src/modules/record_sheet.js index 584bcf7..931177f 100644 --- a/src/modules/record_sheet.js +++ b/src/modules/record_sheet.js @@ -99,6 +99,45 @@ function createRecord(unit) { spans.forEach(el => div.appendChild(el)); + function makeInactiveDivider(parent) { + const div = document.createElement('div'); + div.classList.add('inactive-divider'); + div.textContent = 'Inactive'; + parent.append(div); + return div; + } + + div.addEventListener('contextmenu', e => { + e.preventDefault(); + + if (!div.classList.contains('inactive')) { + const inactiveDivider = div.parentElement.querySelector('.inactive-divider') || makeInactiveDivider(div.parentElement); + + div.addEventListener('transitionend', e => { + inactiveDivider.after(div); + inactiveDivider.scrollIntoView({ behavior: 'smooth' }); + }); + + div.classList.add('inactive'); + div.setAttributeNS(null, 'style', 'transform: scale(0.9);'); + } else { + const squadRecords = div.parentElement.querySelectorAll(`.soldier-record:not(.inactive)[data-squad="${div.dataset.squad}"]`); + const sorted = [...squadRecords, div].sort(({dataset: { number: a }}, {dataset: { number: b }}) => +a > +b); + const index = sorted.findIndex(record => record === div); + + if (index === 0) + div.parentElement.prepend(div); + else if (index === sorted.length - 1) + sorted[sorted.length - 2].after(div) + else + sorted[index - 1].after(div) + + div.classList.remove('inactive'); + div.removeAttributeNS(null, 'style'); + div.scrollIntoView({ behavior: 'smooth' }); + } + }); + return div; } @@ -144,6 +183,7 @@ function select(data) { if (isSelected || !data) return; record.classList.add('selected'); + record.scrollIntoView({ behavior: 'smooth' }); } function endMove() { @@ -151,9 +191,14 @@ function endMove() { if (selected) { selected.classList.toggle('movement-ended'); - } + const next = selected.parentElement.querySelector(`.soldier-record[data-squad="${selected.dataset.squad}"]:not(.movement-ended, .inactive)`); + deselect(); - deselect(); + if (next) { + Observable.notify('select', next); + next.scrollIntoView({ behavior: 'smooth' }); + } + } } export function extractWeaponFromRecord(recordEl) { |