index : btroops | |
Virtual board game-aid for BattleTroops, an infantry combat simulator wargame published by FASA in 1989. |
aboutsummaryrefslogtreecommitdiff |
diff options
Diffstat (limited to 'index.js')
-rw-r--r-- | index.js | 189 |
1 files changed, 123 insertions, 66 deletions
@@ -357,6 +357,10 @@ const Counter = new function() { return `use.counter${dataSelector(troopNumber, allegiance)}`; }, + position = function(x, y) { + return `use.counter[data-x="${x}"][data-x="${y}"]`; + }, + traceSelector = function(troopNumber, allegiance) { return `polyline.move-trace${dataSelector(troopNumber, allegiance)}`; }, @@ -433,6 +437,10 @@ const Counter = new function() { return container.querySelector(`${selector(troopNumber, allegiance)}:not(.clone)`); }; + this.getAt = function(x, y) { + return container.querySelector(`${position(x, y)}:not(.clone)`); + }; + this.select = function({ dataset: { troopNumber, troopAllegiance }}) { this.unSelect(); @@ -557,6 +565,41 @@ const Counter = new function() { }; }; +const RecordSheet = new function() { + let clipUnclippedFiringArcs = function() { + let unclipped = document.querySelectorAll('#firing-arcs polygon:not([clip-path])'); + + unclipped.forEach(el => { + let { troopNumber, troopAllegiance } = el.dataset; + el.setAttributeNS(null, 'clip-path', `url(#${troopAllegiance}-${troopNumber})`); + }); + }; + + this.unSelect = function() { + let selected = this.getSelected(); + + if (selected) { + selected.classList.remove('selected'); + } + + clipUnclippedFiringArcs(); + Counter.unSelect(); + }; + + this.getSelected = function() { + return document.querySelector('.soldier-record.selected'); + }; + + this.select = function(el) { + let { troopNumber, troopAllegiance } = el.dataset; + this.unSelect(); + + el.classList.add('selected'); + existingArcs = document.querySelectorAll(`#firing-arcs polygon[data-troop-number="${troopNumber}"][data-troop-allegiance="${troopAllegiance}"]`); + existingArcs.forEach(el => el.removeAttribute('clip-path')); + }; +}; + POINTS.forEach((row, index) => row.forEach(([x, y]) => { var cx = x * INRADIUS * 2 + (isEven(index) ? INRADIUS : 0), cy = y * 3 / 2 * CIRCUMRADIUS, @@ -604,27 +647,17 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => { }); point.addEventListener('mouseover', e => { - let selectedSoldier = document.querySelector('.soldier-record.selected'); + let selected = RecordSheet.getSelected(); - if (selectedSoldier) { - // e.target.classList.add('active'); - let { troopNumber: tn, troopAllegiance: ta } = selectedSoldier.dataset; - - // let counter = svg.querySelector(`circle.counter[data-troop-number="${tn}"][data-troop-allegiance="${ta}"]`); - let counter = Counter.get(tn, ta); - let sl = svg.querySelector('.sight-line'); + if (selected) { + let { troopNumber: tn, troopAllegiance: ta } = selected.dataset, + counter = Counter.get(tn, ta), + sl = document.querySelector('line.sight-line'); if (counter && (!sl || sl.classList.contains('active'))) { - if (sl) { - info.querySelector('#hex-count').textContent = '-'; - info.style.display = 'none'; - ptGrp.querySelectorAll('.active').forEach(el => el.removeAttribute('class')); - svg.querySelectorAll('.sight-line').forEach(el => el.remove()); - } - - let source = ptGrp.querySelector(`use[data-x="${counter.dataset.x}"][data-y="${counter.dataset.y}"]`); - let [x1, y1] = [source.x.baseVal.value, source.y.baseVal.value]; - let [x2, y2] = [e.target.x.baseVal.value, e.target.y.baseVal.value]; + let source = ptGrp.querySelector(`use[data-x="${counter.dataset.x}"][data-y="${counter.dataset.y}"]`), + [x1, y1] = [source.getAttribute('x'), source.getAttribute('y')], + [x2, y2] = [e.target.getAttribute('x'), e.target.getAttribute('y')]; if (x1 !== x2 || y1 !== y2) { let { x: svgX1, y: svgY1 } = ptGrpToSvgPt(x1, y1); @@ -676,17 +709,8 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => { document.querySelectorAll('.soldier-record').forEach(el => el.addEventListener('click', e => { - if (el.classList.contains('selected')) { - el.classList.remove('selected'); - Counter.unSelect(); - } else { - document.querySelectorAll('.soldier-record.selected').forEach(el => - el.classList.remove('selected') - ); - - el.classList.add('selected'); - Counter.select(el); - } + RecordSheet.select(el); + Counter.select(el); let sl = svg.querySelector('.sight-line'); @@ -699,6 +723,42 @@ document.querySelectorAll('.soldier-record').forEach(el => }) ); +document.querySelector('#grid').addEventListener('click', e => { + let point = ptGrp.querySelector(`[data-x="${e.target.dataset.x}"][data-y="${e.target.dataset.y}"]`), + sl = svg.querySelector('.sight-line'); + + if (sl) { + sl.classList.add('active'); + point.dispatchEvent(new MouseEvent('mouseout')); + point.dispatchEvent(new MouseEvent('mouseover')); + } +}); + +document.querySelectorAll('.end-move').forEach(el => el.addEventListener('click', e => { + let selected = RecordSheet.getSelected(); + + if (selected) { + Counter.endMove(selected); + RecordSheet.unSelect(); + selected.classList.toggle('movement-ended'); + } +})); + +document.querySelectorAll('.end-turn').forEach(el => + el.addEventListener('click', ({ target: { dataset: { allegiance }}}) => { + let dataSelector = `[data-troop-allegiance="${allegiance}"]`, + records = Array.from(qA(`.soldier-record${dataSelector}`)); + + qA(`#firing-arcs ${dataSelector}`).forEach(el => el.remove()); + + records + .sort((el1, el2) => el1.dataset.troopNumber > el2.dataset.troopNumber) + .forEach(el => el.classList.remove('movement-ended')); + + RecordSheet.select(records.at(0)); + }) +); + document.querySelectorAll('.set-firing-arc').forEach(el => el.addEventListener('click', e => { let selectedSoldier = document.querySelector('.soldier-record.selected'); @@ -715,6 +775,7 @@ document.querySelectorAll('.set-firing-arc').forEach(el => el.addEventListener(' if (counter) { let arcLayer = document.getElementById('shapes'); let outlineLayer = document.getElementById('lines'); + let arcContainer = document.getElementById('firing-arcs'); let grid = document.getElementById('grid'); const transform = getComputedStyle(grid).transform.match(/-?\d+\.?\d*/g); @@ -736,19 +797,49 @@ document.querySelectorAll('.set-firing-arc').forEach(el => el.addEventListener(' firingArcOutline.dataset.troopAllegiance = troopAllegiance; firingArcOutline.setAttributeNS(null, 'points', `${pivotPoint} ${pivotPoint} ${pivotPoint}`); + let clipShape = document.createElementNS(svgns, 'circle'); + clipShape.setAttributeNS(null, 'cx', tPt.x); + clipShape.setAttributeNS(null, 'cy', tPt.y); + clipShape.setAttributeNS(null, 'r', 100); + + let clipPath = document.createElementNS(svgns, 'clipPath'); + clipPath.setAttributeNS(null, 'id', `${troopAllegiance}-${troopNumber}`); + clipPath.dataset.troopNumber = troopNumber; + clipPath.dataset.troopAllegiance = troopAllegiance; + clipPath.appendChild(clipShape); + + arcContainer.appendChild(clipPath); arcLayer.appendChild(firingArc); outlineLayer.appendChild(firingArcOutline); let firingArcPlacementListener = e => { document.querySelectorAll('.firing-arc.active').forEach(el => el.classList.remove('active')); - ptGrp.style.pointerEvents = ''; - svg.removeEventListener('click', firingArcPlacementListener); + ptGrp.removeAttribute('style'); + svg.removeEventListener('mousemove', positionFiringArc); + firingArc.removeEventListener('click', firingArcPlacementListener); + firingArc.removeEventListener('contextmenu', cancelFiringArcPlacement); + }; + + let cancelFiringArcPlacement = e => { + e.preventDefault(); + + firingArc.removeEventListener('click', firingArcPlacementListener); + firingArc.removeEventListener('contextmenu', cancelFiringArcPlacement); + + let existingArcs = document.querySelectorAll( + `#firing-arcs [data-troop-number="${troopNumber}"][data-troop-allegiance="${troopAllegiance}"]` + ); + + existingArcs.forEach(el => el.remove()); + + ptGrp.removeAttribute('style'); svg.removeEventListener('mousemove', positionFiringArc); }; ptGrp.style.pointerEvents = 'none'; svg.addEventListener('mousemove', positionFiringArc); - svg.addEventListener('click', firingArcPlacementListener); + firingArc.addEventListener('click', firingArcPlacementListener); + firingArc.addEventListener('contextmenu', cancelFiringArcPlacement); } } })); @@ -831,40 +922,6 @@ recordSheetVisibility.addEventListener('input', e => { localStorage.setItem('recordsVisibility', recordSheetVisibility.checked); }); -document.querySelectorAll('.end-move').forEach(el => el.addEventListener('click', e => { - let selectedSoldier = document.querySelector('.soldier-record.selected'); - - if (selectedSoldier) { - Counter.endMove(selectedSoldier); - - selectedSoldier.classList.toggle('selected'); - selectedSoldier.classList.toggle('movement-ended'); - } -})); - -let endTurnButtons = document.querySelectorAll('.end-turn'); -let [al1, al2] = Array.from(endTurnButtons).map(el => el.dataset.allegiance); - -endTurnButtons.forEach(el => - el.addEventListener('click', ({target: {dataset: {allegiance}}}) => { - let al = allegiance == al1 ? al2 : al1; - - qA(`#firing-arcs [data-troop-allegiance="${al}"]`).forEach(el => el.remove()); - - qA(`.soldier-record[data-troop-allegiance="${al}"]`).forEach(el => - el.classList.remove('movement-ended') - ); - - let selected = q(`.soldier-record.selected`); - - if (selected) { - selected.classList.remove('selected'); - } - - q(`.soldier-record[data-troop-allegiance="${al}"]`).classList.add('selected'); - }) -); - (function debug() { function drawLine(x1, y1, x2, y2) { let start = ptGrp.querySelector(`[data-x="${x1}"][data-y="${y1}"]`); |