Sloped belts and filters, laid by a 45° drag (t40)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-25 23:17:55 -04:00
co-authored by Claude Opus 5.5
parent 24eb9559f8
commit e19cb784d2
26 changed files with 531 additions and 110 deletions
+6 -4
View File
@@ -27,16 +27,16 @@ function doInteract() {
if (fb >= 0) {
if (!inReach(ax, ay)) { setStatus('Out of reach.'); playSfx('error'); return; }
const run = filterRun(fb);
openFilterPicker(Object.assign(filterInfo(fb), { dir: blockV[fb] & 128 ? 1 : 0 }), f => {
openFilterPicker(Object.assign(filterInfo(fb), { dir: blockV[fb] & 128 ? 1 : 0, code: blockP[fb] }), f => {
applyFilterRun(run, f);
GAME.filterCfg = { m: f.m.slice(), inv: f.inv }; GAME.pieceDir.filter = f.dir;
setStatus(`${run.length} ${run.length === 1 ? 'filter' : 'filters'} updated, carrying ${f.dir ? 'right' : 'left'}.`, 'info');
setStatus(`${run.length} ${run.length === 1 ? 'filter' : 'filters'} updated, carrying ${beltDirection(blockP[fb], f.dir ? 128 : 0)}.`, 'info');
}, run.length > 1 ? `Filter (${run.length} in this row)` : 'Filter');
GAME.editRun = run;
return;
}
if (toolId() === 'build' && pieceUsesWall(piece())) { openWallPicker(); return; }
if (toolId() === 'build' && piece().filter) { openFilterPicker(Object.assign({}, GAME.filterCfg, { dir: GAME.pieceDir.filter || 0 }), f => { GAME.filterCfg = { m: f.m, inv: f.inv }; GAME.pieceDir.filter = f.dir; }, 'New filters'); return; }
if (toolId() === 'build' && piece().filter) { openFilterPicker(Object.assign({}, GAME.filterCfg, { dir: GAME.pieceDir.filter || 0, code: pieceCode(piece()) }), f => { GAME.filterCfg = { m: f.m, inv: f.inv }; GAME.pieceDir.filter = f.dir; }, 'New filters'); return; }
let msg = '';
outer: for (let r = 0; r <= 2; r++) for (let dy = -r; dy <= r; dy++) for (let dx = -r; dx <= r; dx++) {
if (!inReach(ax + dx, ay + dy)) continue;
@@ -59,6 +59,7 @@ function pickUnderCursor() {
else if (blockP[bi] || ghost) {
const code = blockP[bi] || ghost[0], v = blockP[bi] ? blockV[bi] : ghost[1];
const P = PIECE_BY_CODE[code]; pid = P.id;
if (isBelt(code) || isFilter(code)) { GAME.pieceShape = GAME.pieceShape || {}; GAME.pieceShape[P.id] = code; }
if (isWall(code)) { GAME.wallMat = v; GAME.pieceDir.wall = isSlope(code) ? code - BP_SLOPE_BL + 1 : 0; }
else if (P.filter) { GAME.filterCfg = blockP[bi] ? filterInfo(bi) : cleanFilterCfg(ghost[2]); GAME.pieceDir[P.id] = v >> 7; }
else if (P.dirs) GAME.pieceDir[P.id] = v % P.dirs.length;
@@ -99,6 +100,7 @@ function dragDirFor(P, a, b) {
if (!a || !P.dirs || !(P.id === 'belt' || P.id === 'tube' || P.filter)) return -1;
const dx = b.bx - a.bx, dy = b.by - a.by;
if (!dx && !dy) return -1;
if ((P.id === 'belt' || P.filter) && diagonalDrag(dx, dy)) return dx > 0 ? 1 : 0;
if (P.id === 'tube' && diagonalDrag(dx, dy)) return dx > 0 ? (dy < 0 ? 4 : 5) : (dy > 0 ? 6 : 7);
if (P.id === 'tube') return Math.abs(dx) >= Math.abs(dy) ? (dx > 0 ? 1 : 3) : (dy > 0 ? 2 : 0);
return Math.abs(dx) >= Math.abs(dy) ? (dx > 0 ? 1 : 0) : -1;
@@ -163,7 +165,7 @@ function primaryRelease(shift) {
}
if (t === 'build' && GAME.drag) {
const P = piece(), b = aimBlock(), code = pieceCode(P, b);
const list = shift ? blockRect(GAME.drag.bx, GAME.drag.by, b.bx, b.by) : blockLine(GAME.drag.bx, GAME.drag.by, b.bx, b.by, isWall(code) || code === BP_TUBE);
const list = shift ? blockRect(GAME.drag.bx, GAME.drag.by, b.bx, b.by) : blockLine(GAME.drag.bx, GAME.drag.by, b.bx, b.by, isWall(code) || isSlopeBelt(code) || code === BP_TUBE);
const dd = dragDirFor(P, GAME.drag, b);
if (dd >= 0) GAME.pieceDir[P.id] = dd;
const v = pieceV(P), ex = pieceExtra(P);