From 10f43ad920d39df1d1ec59f0795968a1137b78b3 Mon Sep 17 00:00:00 2001 From: emna9 Date: Tue, 28 Jan 2025 14:22:52 +0100 Subject: [PATCH 01/12] test --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cd4cf4155..e78de06a5 100755 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![OpenCollective Badge](https://opencollective.com/ancientbeast/tiers/badge.svg)](https://opencollective.com/AncientBeast) [![Discord](https://img.shields.io/discord/154868963132571649?logo=discord&label=Discord&color=5865F2)](https://discord.gg/CtqBsnF85z) - +o ![1vs1 Dark Forest](https://raw.github.com/FreezingMoon/AncientBeast-Website/master/multimedia/screenshots/v0.3%20Dark%20Forest.jpg) **"We all die. The goal isn't to live forever. The goal is to create something that will."** _Chuck Palahniuk_ From 91fe77b9f59810c1f792b7450c2f3a6983c83039 Mon Sep 17 00:00:00 2001 From: emna9 Date: Wed, 2 Apr 2025 22:15:00 +0100 Subject: [PATCH 02/12] updated Scavenger.js --- src/abilities/Scavenger.js | 205 +++++++++++++++++++++---------------- 1 file changed, 119 insertions(+), 86 deletions(-) mode change 100755 => 100644 src/abilities/Scavenger.js diff --git a/src/abilities/Scavenger.js b/src/abilities/Scavenger.js old mode 100755 new mode 100644 index 6f3ae01b4..7931dc587 --- a/src/abilities/Scavenger.js +++ b/src/abilities/Scavenger.js @@ -4,7 +4,6 @@ import { Team } from '../utility/team'; import * as matrices from '../utility/matrices'; import * as arrayUtils from '../utility/arrayUtils'; import { Effect } from '../effect'; - function getEscortUsableHexes(G, crea, trg) { const trgIsInfront = G.grid.getHexMap( @@ -13,23 +12,40 @@ function getEscortUsableHexes(G, crea, trg) { 0, false, matrices.inlinefront2hex, - )[0].creature == trg; + )[0].creature === trg; + + const dir = trgIsInfront ? -1 : 1; + const creaSize = crea.size; + const trgSize = trg.size; + + const blockStartX = trgIsInfront ? trg.x : crea.x; + const blockEndX = blockStartX + creaSize + trgSize - 1; const distance = crea.remainingMove; - const size = crea.size + trg.size; - const x = trgIsInfront ? crea.x + trg.size : crea.x; - - const usableHexes = G.grid - .getFlyingRange(x, crea.y, distance, size, [crea.id, trg.id]) - .filter(function (item) { - return ( - crea.y == item.y && (trgIsInfront ? item.x < x : item.x > x - crea.size - trg.size + 1) - ); - }); - - return { size, trgIsInfront, usableHexes }; + + let usableHexes = []; + + for (let shift = 1; shift <= distance; shift++) { + const hoveredBlockStartX = blockStartX + (shift * dir); + + let blockFits = true; + for (let i = 0; i < creaSize + trgSize; i++) { + const xToCheck = hoveredBlockStartX + i; + if (!G.grid.hexExists({ x: xToCheck, y: crea.y })) { + blockFits = false; + break; + } + } + + if (blockFits) { + usableHexes.push(G.grid.hexes[crea.y][hoveredBlockStartX]); + } + } + + return { usableHexes, trgIsInfront, creaSize, trgSize, dir, blockStartX }; } + /** Creates the abilities * @param {Object} G the game object * @return {void} @@ -203,55 +219,69 @@ export default (G) => { query: function () { const ability = this; const crea = this.creature; - + + // Retrieve creatures adjacent to Scavenger in a line (front and back) const hexes = crea.getHexMap(matrices.inlinefrontnback2hex); const trg = hexes[0].creature || hexes[1].creature; - + + // Get data to determine usable hexes, block size, and whether target is in front const { size, trgIsInfront, usableHexes } = getEscortUsableHexes(G, crea, trg); - + + console.log("[QUERY] usableHexes initially calculated:", usableHexes); + console.log("[QUERY] Block size (Scavenger + Target):", size); + console.log("[QUERY] Target is in front of Scavenger:", trgIsInfront); + const select = (hex) => { - for (let i = 0; i < trg.hexagons.length; i++) { - G.grid.cleanHex(trg.hexagons[i]); - trg.hexagons[i].displayVisualState('dashed'); - } - for (let i = 0; i < crea.hexagons.length; i++) { - G.grid.cleanHex(crea.hexagons[i]); - crea.hexagons[i].overlayVisualState('hover h_player' + crea.team); - } - for (let i = 0; i < size; i++) { - if (!G.grid.hexExists({ y: hex.y, x: hex.x - i })) { - continue; + const { trgIsInfront, creaSize, trgSize, dir, blockStartX } = getEscortUsableHexes(G, crea, trg); + + [...trg.hexagons, ...crea.hexagons].forEach(h => { + G.grid.cleanHex(h); + h.displayVisualState('dashed'); + }); + + const hoveredBlockStartX = hex.x; + const shift = hoveredBlockStartX - blockStartX; + + for (let i = 0; i < trgSize; i++) { + const targetX = trg.x + shift; + if (G.grid.hexExists({ x: targetX + i, y: trg.y })) { + const targetHex = G.grid.hexes[trg.y][targetX + i]; + targetHex.overlayVisualState('active creature player' + trg.team); + targetHex.displayVisualState('creature player' + trg.team); } - const h = G.grid.hexes[hex.y][hex.x - i]; - let color; - if (trgIsInfront) { - color = i < trg.size ? trg.team : crea.team; - } else { - color = i > 1 ? trg.team : crea.team; + } + + for (let i = 0; i < creaSize; i++) { + const creaX = crea.x + shift; + if (G.grid.hexExists({ x: creaX + i, y: crea.y })) { + const creaHex = G.grid.hexes[crea.y][creaX + i]; + creaHex.overlayVisualState('active creature player' + crea.team); + creaHex.displayVisualState('creature player' + crea.team); } - G.grid.cleanHex(h); - h.overlayVisualState('active creature player' + color); - h.displayVisualState('creature player' + color); - - const creatureData = G.retrieveCreatureStats(crea.type); - const targetData = G.retrieveCreatureStats(trg.type); - const creaPos = trgIsInfront ? { x: hex.pos.x - trg.size, y: hex.pos.y } : hex.pos; - const trgPos = trgIsInfront - ? { x: hex.pos.x, y: hex.pos.y } - : { x: hex.pos.x - 2, y: hex.pos.y }; - - G.grid.previewCreature(creaPos, creatureData, crea.player); - G.grid.previewCreature(trgPos, targetData, trg.player, true); } + + const trgPreviewGridPos = { x: trg.x + shift, y: trg.y }; + const creaPreviewGridPos = { x: crea.x + shift, y: crea.y }; + + console.log("[FIXED SELECT] Preview Target (grid):", trgPreviewGridPos); + console.log("[FIXED SELECT] Preview Scavenger (grid):", creaPreviewGridPos); + + G.grid.previewCreature(trgPreviewGridPos, G.retrieveCreatureStats(trg.type), trg.player, true); + G.grid.previewCreature(creaPreviewGridPos, G.retrieveCreatureStats(crea.type), crea.player); }; - + + + + + + // Execute hex query with hover and confirm functionality G.grid.queryHexes({ fnOnConfirm: function () { G.grid.fadeOutTempCreature(); G.grid.fadeOutTempCreature(G.grid.secondary_overlay); ability.animation(...arguments); - }, // fnOnConfirm - fnOnSelect: select, // fnOnSelect, + }, + fnOnSelect: select, team: this._targetTeam, id: [crea.id, trg.id], size: size, @@ -262,7 +292,7 @@ export default (G) => { trgIsInfront: trgIsInfront, }, callbackAfterQueryHexes: () => { - console.log('cleaning'); + console.log('cleaning after query'); for (let i = 0; i < trg.hexagons.length; i++) { G.grid.cleanHex(trg.hexagons[i]); trg.hexagons[i].displayVisualState('dashed'); @@ -271,56 +301,59 @@ export default (G) => { fillHexOnHover: false, }); }, + + // activate() : activate: function (hex, args) { const ability = this; ability.end(); G.Phaser.camera.shake(0.01, 66, true, G.Phaser.camera.SHAKE_HORIZONTAL, true); - + const crea = this.creature; - const trg = G.creatures[args.trg]; - - const trgIF = args.trgIsInfront; - - const creaDest = G.grid.hexes[hex.y][trgIF ? hex.x - trg.size : hex.x]; - const trgDest = G.grid.hexes[hex.y][trgIF ? hex.x : hex.x - crea.size]; - - // Determine distance - let distance = 0; - let k = 0; - const start = G.grid.hexes[crea.y][crea.x]; - while (!distance) { - k++; - - if (arrayUtils.findPos(start.adjacentHex(k), creaDest)) { - distance = k; - } - } - - // Substract from movement points - crea.remainingMove -= distance * trg.size; - - crea.moveTo(creaDest, { + const { blockStartX } = getEscortUsableHexes(G, crea, trg); + + const hoveredBlockStartX = hex.x; + const finalShift = hoveredBlockStartX - blockStartX; + + const creaDestX = crea.x + finalShift; + const trgDestX = trg.x + finalShift; + + const creaDest = G.grid.hexes[crea.y][creaDestX]; + const trgDest = G.grid.hexes[trg.y][trgDestX]; + + console.log('[FIXED ACTIVATE] Shift:', finalShift); + + crea.remainingMove -= Math.abs(finalShift); + + trg.moveTo(trgDest, { animation: 'fly', - callback: function () { - trg.updateHex(); - }, + callback: () => crea.updateHex(), ignoreMovementPoint: true, }); - - trg.moveTo(trgDest, { + + crea.moveTo(creaDest, { animation: 'fly', - callback: function () { - ability.creature.updateHex(); - ability.creature.queryMove(); + callback: () => { + trg.updateHex(); + crea.queryMove(); }, - ignoreFacing: true, ignoreMovementPoint: true, overrideSpeed: crea.animation.walk_speed, }); - }, + } + + + + + + + + + + + }, // Fourth Ability: Deadly Toxin @@ -418,4 +451,4 @@ export default (G) => { }, }, ]; -}; +}; \ No newline at end of file From 234e8b8606432fe036f697fb7ca13e6ef0155242 Mon Sep 17 00:00:00 2001 From: emna9 Date: Wed, 2 Apr 2025 23:28:38 +0100 Subject: [PATCH 03/12] updated the first function to handle both directions --- src/abilities/Scavenger.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/abilities/Scavenger.js b/src/abilities/Scavenger.js index 7931dc587..541cb6300 100644 --- a/src/abilities/Scavenger.js +++ b/src/abilities/Scavenger.js @@ -27,20 +27,23 @@ function getEscortUsableHexes(G, crea, trg) { for (let shift = 1; shift <= distance; shift++) { const hoveredBlockStartX = blockStartX + (shift * dir); - + let blockFits = true; + for (let i = 0; i < creaSize + trgSize; i++) { - const xToCheck = hoveredBlockStartX + i; + const xToCheck = hoveredBlockStartX + (i * dir); // ← clearly fixed here + if (!G.grid.hexExists({ x: xToCheck, y: crea.y })) { blockFits = false; break; } } - + if (blockFits) { usableHexes.push(G.grid.hexes[crea.y][hoveredBlockStartX]); } } + return { usableHexes, trgIsInfront, creaSize, trgSize, dir, blockStartX }; } From cd24236615522b21fdd5a960556067ba6085efb8 Mon Sep 17 00:00:00 2001 From: emna9 Date: Thu, 3 Apr 2025 00:24:14 +0100 Subject: [PATCH 04/12] test avaiable tiles --- src/abilities/Scavenger.js | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/abilities/Scavenger.js b/src/abilities/Scavenger.js index 541cb6300..7da02f7b7 100644 --- a/src/abilities/Scavenger.js +++ b/src/abilities/Scavenger.js @@ -19,36 +19,45 @@ function getEscortUsableHexes(G, crea, trg) { const trgSize = trg.size; const blockStartX = trgIsInfront ? trg.x : crea.x; - const blockEndX = blockStartX + creaSize + trgSize - 1; + const totalBlockSize = creaSize + trgSize; const distance = crea.remainingMove; + const usableHexes = []; - let usableHexes = []; - + // Loop through each potential tile in range clearly for (let shift = 1; shift <= distance; shift++) { - const hoveredBlockStartX = blockStartX + (shift * dir); - + const hoveredBlockStartX = blockStartX + shift * dir; + let blockFits = true; - - for (let i = 0; i < creaSize + trgSize; i++) { - const xToCheck = hoveredBlockStartX + (i * dir); // ← clearly fixed here - + for (let i = 0; i < totalBlockSize; i++) { + const xToCheck = hoveredBlockStartX + i * dir; + + // Clearly ensure the hex exists if (!G.grid.hexExists({ x: xToCheck, y: crea.y })) { blockFits = false; break; } + + const hexToCheck = G.grid.hexes[crea.y][xToCheck]; + + // Clearly ensure hex is unoccupied or occupied by current block creatures only + if (hexToCheck.creature && ![crea.id, trg.id].includes(hexToCheck.creature.id)) { + blockFits = false; + break; + } } - + + // If clearly fits, add as usable if (blockFits) { usableHexes.push(G.grid.hexes[crea.y][hoveredBlockStartX]); } } - return { usableHexes, trgIsInfront, creaSize, trgSize, dir, blockStartX }; } + /** Creates the abilities * @param {Object} G the game object * @return {void} From e0391f37a7be82544802ce4c73119269601fc934 Mon Sep 17 00:00:00 2001 From: emna9 Date: Thu, 3 Apr 2025 03:00:16 +0100 Subject: [PATCH 05/12] tested on overlapping but still.. --- src/abilities/Scavenger.js | 90 +++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/abilities/Scavenger.js b/src/abilities/Scavenger.js index 7da02f7b7..0de37b5d6 100644 --- a/src/abilities/Scavenger.js +++ b/src/abilities/Scavenger.js @@ -4,57 +4,57 @@ import { Team } from '../utility/team'; import * as matrices from '../utility/matrices'; import * as arrayUtils from '../utility/arrayUtils'; import { Effect } from '../effect'; -function getEscortUsableHexes(G, crea, trg) { - const trgIsInfront = - G.grid.getHexMap( - crea.x - matrices.inlinefront2hex.origin[0], - crea.y - matrices.inlinefront2hex.origin[1], - 0, - false, - matrices.inlinefront2hex, - )[0].creature === trg; - - const dir = trgIsInfront ? -1 : 1; - const creaSize = crea.size; - const trgSize = trg.size; - - const blockStartX = trgIsInfront ? trg.x : crea.x; - const totalBlockSize = creaSize + trgSize; - - const distance = crea.remainingMove; - const usableHexes = []; - - // Loop through each potential tile in range clearly - for (let shift = 1; shift <= distance; shift++) { - const hoveredBlockStartX = blockStartX + shift * dir; - - let blockFits = true; - for (let i = 0; i < totalBlockSize; i++) { - const xToCheck = hoveredBlockStartX + i * dir; - - // Clearly ensure the hex exists - if (!G.grid.hexExists({ x: xToCheck, y: crea.y })) { - blockFits = false; - break; - } + function getEscortUsableHexes(G, crea, trg) { + const trgIsInfront = + G.grid.getHexMap( + crea.x - matrices.inlinefront2hex.origin[0], + crea.y - matrices.inlinefront2hex.origin[1], + 0, + false, + matrices.inlinefront2hex, + )[0].creature === trg; + + const dir = trgIsInfront ? -1 : 1; + const creaSize = crea.size; + const trgSize = trg.size; + + const blockStartX = trgIsInfront ? trg.x : crea.x; + const totalBlockSize = creaSize + trgSize; + + const distance = crea.remainingMove; + const usableHexes = []; + + // Loop through each potential tile in range clearly + for (let shift = 1; shift <= distance; shift++) { + const hoveredBlockStartX = blockStartX + shift * dir; + + let blockFits = true; + for (let i = 0; i < totalBlockSize; i++) { + const xToCheck = hoveredBlockStartX + i * dir; + + // Clearly ensure the hex exists + if (!G.grid.hexExists({ x: xToCheck, y: crea.y })) { + blockFits = false; + break; + } - const hexToCheck = G.grid.hexes[crea.y][xToCheck]; + const hexToCheck = G.grid.hexes[crea.y][xToCheck]; - // Clearly ensure hex is unoccupied or occupied by current block creatures only - if (hexToCheck.creature && ![crea.id, trg.id].includes(hexToCheck.creature.id)) { - blockFits = false; - break; + // Clearly ensure hex is unoccupied or occupied by current block creatures only + if (hexToCheck.creature && ![crea.id, trg.id].includes(hexToCheck.creature.id)) { + blockFits = false; + break; + } } - } - // If clearly fits, add as usable - if (blockFits) { - usableHexes.push(G.grid.hexes[crea.y][hoveredBlockStartX]); + // If clearly fits, add as usable + if (blockFits) { + usableHexes.push(G.grid.hexes[crea.y][hoveredBlockStartX]); + } } - } - return { usableHexes, trgIsInfront, creaSize, trgSize, dir, blockStartX }; -} + return { usableHexes, trgIsInfront, creaSize, trgSize, dir, blockStartX }; + } From e58d0d2fad1f003e2db4c35feb4d710cdd6ca73e Mon Sep 17 00:00:00 2001 From: emna9 Date: Sat, 5 Apr 2025 15:12:01 +0100 Subject: [PATCH 06/12] test --- src/abilities/Scavenger.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/abilities/Scavenger.js b/src/abilities/Scavenger.js index 0de37b5d6..186756cbe 100644 --- a/src/abilities/Scavenger.js +++ b/src/abilities/Scavenger.js @@ -250,7 +250,6 @@ export default (G) => { G.grid.cleanHex(h); h.displayVisualState('dashed'); }); - const hoveredBlockStartX = hex.x; const shift = hoveredBlockStartX - blockStartX; From 4c438656621981d8e225f1442ef13fd47f419cda Mon Sep 17 00:00:00 2001 From: emna9 Date: Tue, 8 Apr 2025 00:33:22 +0100 Subject: [PATCH 07/12] test --- src/abilities/Scavenger.js | 125 ++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 49 deletions(-) diff --git a/src/abilities/Scavenger.js b/src/abilities/Scavenger.js index 186756cbe..36c2ff612 100644 --- a/src/abilities/Scavenger.js +++ b/src/abilities/Scavenger.js @@ -4,58 +4,65 @@ import { Team } from '../utility/team'; import * as matrices from '../utility/matrices'; import * as arrayUtils from '../utility/arrayUtils'; import { Effect } from '../effect'; - function getEscortUsableHexes(G, crea, trg) { - const trgIsInfront = - G.grid.getHexMap( - crea.x - matrices.inlinefront2hex.origin[0], - crea.y - matrices.inlinefront2hex.origin[1], - 0, - false, - matrices.inlinefront2hex, - )[0].creature === trg; - - const dir = trgIsInfront ? -1 : 1; - const creaSize = crea.size; - const trgSize = trg.size; - - const blockStartX = trgIsInfront ? trg.x : crea.x; - const totalBlockSize = creaSize + trgSize; - - const distance = crea.remainingMove; - const usableHexes = []; - - // Loop through each potential tile in range clearly - for (let shift = 1; shift <= distance; shift++) { - const hoveredBlockStartX = blockStartX + shift * dir; - - let blockFits = true; - for (let i = 0; i < totalBlockSize; i++) { - const xToCheck = hoveredBlockStartX + i * dir; - - // Clearly ensure the hex exists - if (!G.grid.hexExists({ x: xToCheck, y: crea.y })) { - blockFits = false; - break; - } +function getEscortUsableHexes(G, crea, trg) { + const trgIsInfront = + G.grid.getHexMap( + crea.x - matrices.inlinefront2hex.origin[0], + crea.y - matrices.inlinefront2hex.origin[1], + 0, + false, + matrices.inlinefront2hex, + )[0].creature === trg; + + const dir = trgIsInfront ? -1 : 1; + const creaSize = crea.size; + const trgSize = trg.size; + const totalBlockSize = creaSize + trgSize; + const blockStartX = trgIsInfront ? trg.x : crea.x; + + const distance = crea.remainingMove; + const usableHexes = []; + + // 1. Collect ALL hexes currently occupied by any OTHER creature + const reservedHexes = new Set(); + for (const row of G.grid.hexes) { + for (const hex of row) { + if (hex.creature && ![crea.id, trg.id].includes(hex.creature.id)) { + reservedHexes.add(`${hex.x},${hex.y}`); + } + } + } - const hexToCheck = G.grid.hexes[crea.y][xToCheck]; + // 2. Try shifts of 1, 2, ..., movement range + for (let shift = 1; shift <= distance; shift++) { + const hoveredBlockStartX = blockStartX + shift * dir; + let blockFits = true; - // Clearly ensure hex is unoccupied or occupied by current block creatures only - if (hexToCheck.creature && ![crea.id, trg.id].includes(hexToCheck.creature.id)) { - blockFits = false; - break; - } + // Check full block (target first, then scavenger) + for (let i = 0; i < totalBlockSize; i++) { + const x = hoveredBlockStartX + i * dir; + const y = crea.y; + + if (!G.grid.hexExists({ x, y })) { + blockFits = false; + break; } - // If clearly fits, add as usable - if (blockFits) { - usableHexes.push(G.grid.hexes[crea.y][hoveredBlockStartX]); + if (reservedHexes.has(`${x},${y}`)) { + blockFits = false; + break; } } - return { usableHexes, trgIsInfront, creaSize, trgSize, dir, blockStartX }; + if (blockFits) { + usableHexes.push(G.grid.hexes[crea.y][hoveredBlockStartX]); + } } + return { usableHexes, trgIsInfront, creaSize, trgSize, dir, blockStartX }; +} + + /** Creates the abilities @@ -323,32 +330,51 @@ export default (G) => { const crea = this.creature; const trg = G.creatures[args.trg]; - const { blockStartX } = getEscortUsableHexes(G, crea, trg); + + const { + blockStartX, + dir + } = getEscortUsableHexes(G, crea, trg); // Original logic preserved const hoveredBlockStartX = hex.x; - const finalShift = hoveredBlockStartX - blockStartX; + // 👇 Compute how many hexes to shift + const finalShift = (hoveredBlockStartX - blockStartX); + + // 🔁 Apply shift to each hex const creaDestX = crea.x + finalShift; const trgDestX = trg.x + finalShift; const creaDest = G.grid.hexes[crea.y][creaDestX]; const trgDest = G.grid.hexes[trg.y][trgDestX]; - console.log('[FIXED ACTIVATE] Shift:', finalShift); + console.log('[ACTIVATE]', { + finalShift, + creaDestX, + trgDestX, + blockStartX, + dir, + hoveredBlockStartX, + }); + // ➖ Update move points crea.remainingMove -= Math.abs(finalShift); + // ✅ Move target first (important) trg.moveTo(trgDest, { animation: 'fly', - callback: () => crea.updateHex(), + callback: () => { + trg.updateHex(); // Update grid state + }, ignoreMovementPoint: true, }); + // ✅ Move Scavenger crea.moveTo(creaDest, { animation: 'fly', callback: () => { - trg.updateHex(); - crea.queryMove(); + crea.updateHex(); // Update grid + crea.queryMove(); // Let player move again }, ignoreMovementPoint: true, overrideSpeed: crea.animation.walk_speed, @@ -362,6 +388,7 @@ export default (G) => { + From 5dea3da60cc776d1001d74b4e8cf54cdd668120d Mon Sep 17 00:00:00 2001 From: emna9 Date: Wed, 9 Apr 2025 02:00:03 +0100 Subject: [PATCH 08/12] test --- src/abilities/Scavenger.js | 153 ++++++++++++++++++++----------------- 1 file changed, 84 insertions(+), 69 deletions(-) diff --git a/src/abilities/Scavenger.js b/src/abilities/Scavenger.js index 36c2ff612..9790f8dd7 100644 --- a/src/abilities/Scavenger.js +++ b/src/abilities/Scavenger.js @@ -5,62 +5,75 @@ import * as matrices from '../utility/matrices'; import * as arrayUtils from '../utility/arrayUtils'; import { Effect } from '../effect'; function getEscortUsableHexes(G, crea, trg) { - const trgIsInfront = - G.grid.getHexMap( - crea.x - matrices.inlinefront2hex.origin[0], - crea.y - matrices.inlinefront2hex.origin[1], - 0, - false, - matrices.inlinefront2hex, - )[0].creature === trg; - - const dir = trgIsInfront ? -1 : 1; - const creaSize = crea.size; - const trgSize = trg.size; - const totalBlockSize = creaSize + trgSize; - const blockStartX = trgIsInfront ? trg.x : crea.x; - - const distance = crea.remainingMove; - const usableHexes = []; - - // 1. Collect ALL hexes currently occupied by any OTHER creature - const reservedHexes = new Set(); - for (const row of G.grid.hexes) { - for (const hex of row) { - if (hex.creature && ![crea.id, trg.id].includes(hex.creature.id)) { - reservedHexes.add(`${hex.x},${hex.y}`); - } - } - } - - // 2. Try shifts of 1, 2, ..., movement range - for (let shift = 1; shift <= distance; shift++) { - const hoveredBlockStartX = blockStartX + shift * dir; - let blockFits = true; - - // Check full block (target first, then scavenger) - for (let i = 0; i < totalBlockSize; i++) { - const x = hoveredBlockStartX + i * dir; - const y = crea.y; - - if (!G.grid.hexExists({ x, y })) { - blockFits = false; - break; - } - - if (reservedHexes.has(`${x},${y}`)) { - blockFits = false; - break; - } - } + const trgIsInfront = + G.grid.getHexMap( + crea.x - matrices.inlinefront2hex.origin[0], + crea.y - matrices.inlinefront2hex.origin[1], + 0, + false, + matrices.inlinefront2hex, + )[0].creature === trg; + + const dir = trgIsInfront ? -1 : 1; // Direction of movement + const creaSize = crea.size; + const trgSize = trg.size; + const totalBlockSize = creaSize + trgSize; + const blockStartX = trgIsInfront ? trg.x : crea.x; + + const distance = crea.remainingMove; + const usableHexes = []; + + console.log(`Direction: ${dir}, Block Start X: ${blockStartX}, Remaining Move: ${distance}`); + + // 1. Collect all hexes occupied by any other creatures + const reservedHexes = new Set(); + for (const row of G.grid.hexes) { + for (const hex of row) { + if (hex.creature && ![crea.id, trg.id].includes(hex.creature.id)) { + reservedHexes.add(`${hex.x},${hex.y}`); + } + } + } + + // 2. Try shifts of 1, 2, ..., movement range + for (let shift = 1; shift <= distance; shift++) { + const hoveredBlockStartX = blockStartX + shift * dir; + console.log(`[SHIFT] Trying Shift: ${shift}, Hovered Start X: ${hoveredBlockStartX}`); + + let blockFits = true; + + // Check full block (target first, then scavenger) + for (let i = 0; i < totalBlockSize; i++) { + const x = hoveredBlockStartX + i * dir; + const y = crea.y; + + // Check if hex exists and if it's occupied by another creature + if (!G.grid.hexExists({ x, y })) { + blockFits = false; + break; + } + + if (reservedHexes.has(`${x},${y}`)) { + blockFits = false; + break; + } + } + + // If the block fits, push it to usable hexes + if (blockFits) { + console.log(`[VALID BLOCK] Usable Hex at X: ${hoveredBlockStartX}`); + usableHexes.push(G.grid.hexes[crea.y][hoveredBlockStartX]); + } else { + console.log(`[INVALID BLOCK] Block does not fit at X: ${hoveredBlockStartX}`); + } + } + + console.log("Final Usable Hexes: ", usableHexes); + + return { usableHexes, trgIsInfront, creaSize, trgSize, dir, blockStartX }; +} - if (blockFits) { - usableHexes.push(G.grid.hexes[crea.y][hoveredBlockStartX]); - } - } - return { usableHexes, trgIsInfront, creaSize, trgSize, dir, blockStartX }; -} @@ -238,28 +251,33 @@ export default (G) => { query: function () { const ability = this; const crea = this.creature; - + // Retrieve creatures adjacent to Scavenger in a line (front and back) const hexes = crea.getHexMap(matrices.inlinefrontnback2hex); const trg = hexes[0].creature || hexes[1].creature; - + // Get data to determine usable hexes, block size, and whether target is in front const { size, trgIsInfront, usableHexes } = getEscortUsableHexes(G, crea, trg); console.log("[QUERY] usableHexes initially calculated:", usableHexes); console.log("[QUERY] Block size (Scavenger + Target):", size); console.log("[QUERY] Target is in front of Scavenger:", trgIsInfront); - + const select = (hex) => { + console.log(`[SELECT] Hovered Hex: ${hex.x}, ${hex.y}`); + const { trgIsInfront, creaSize, trgSize, dir, blockStartX } = getEscortUsableHexes(G, crea, trg); - - [...trg.hexagons, ...crea.hexagons].forEach(h => { + + [ ...trg.hexagons, ...crea.hexagons ].forEach(h => { G.grid.cleanHex(h); h.displayVisualState('dashed'); }); + const hoveredBlockStartX = hex.x; const shift = hoveredBlockStartX - blockStartX; - + + console.log(`[SELECT] Calculated Shift: ${shift}`); + for (let i = 0; i < trgSize; i++) { const targetX = trg.x + shift; if (G.grid.hexExists({ x: targetX + i, y: trg.y })) { @@ -268,7 +286,7 @@ export default (G) => { targetHex.displayVisualState('creature player' + trg.team); } } - + for (let i = 0; i < creaSize; i++) { const creaX = crea.x + shift; if (G.grid.hexExists({ x: creaX + i, y: crea.y })) { @@ -277,21 +295,17 @@ export default (G) => { creaHex.displayVisualState('creature player' + crea.team); } } - + const trgPreviewGridPos = { x: trg.x + shift, y: trg.y }; const creaPreviewGridPos = { x: crea.x + shift, y: crea.y }; - + console.log("[FIXED SELECT] Preview Target (grid):", trgPreviewGridPos); console.log("[FIXED SELECT] Preview Scavenger (grid):", creaPreviewGridPos); - + G.grid.previewCreature(trgPreviewGridPos, G.retrieveCreatureStats(trg.type), trg.player, true); G.grid.previewCreature(creaPreviewGridPos, G.retrieveCreatureStats(crea.type), crea.player); }; - - - - // Execute hex query with hover and confirm functionality G.grid.queryHexes({ fnOnConfirm: function () { @@ -320,6 +334,7 @@ export default (G) => { }); }, + // activate() : @@ -489,4 +504,4 @@ export default (G) => { }, }, ]; -}; \ No newline at end of file +}; \ No newline at end of file From 53396febea35deaf0d73858da2284d63c1ba88c4 Mon Sep 17 00:00:00 2001 From: emna9 Date: Wed, 16 Apr 2025 02:27:05 +0100 Subject: [PATCH 09/12] initial commit --- src/abilities/Scavenger.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/abilities/Scavenger.js b/src/abilities/Scavenger.js index 9790f8dd7..25f1dc3ec 100644 --- a/src/abilities/Scavenger.js +++ b/src/abilities/Scavenger.js @@ -14,7 +14,7 @@ function getEscortUsableHexes(G, crea, trg) { matrices.inlinefront2hex, )[0].creature === trg; - const dir = trgIsInfront ? -1 : 1; // Direction of movement + const dir = trgIsInfront ? -1 : 1; const creaSize = crea.size; const trgSize = trg.size; const totalBlockSize = creaSize + trgSize; @@ -35,7 +35,6 @@ function getEscortUsableHexes(G, crea, trg) { } } - // 2. Try shifts of 1, 2, ..., movement range for (let shift = 1; shift <= distance; shift++) { const hoveredBlockStartX = blockStartX + shift * dir; console.log(`[SHIFT] Trying Shift: ${shift}, Hovered Start X: ${hoveredBlockStartX}`); @@ -349,14 +348,14 @@ export default (G) => { const { blockStartX, dir - } = getEscortUsableHexes(G, crea, trg); // Original logic preserved + } = getEscortUsableHexes(G, crea, trg); const hoveredBlockStartX = hex.x; - // 👇 Compute how many hexes to shift + // Compute how many hexes to shift const finalShift = (hoveredBlockStartX - blockStartX); - // 🔁 Apply shift to each hex + // Apply shift to each hex const creaDestX = crea.x + finalShift; const trgDestX = trg.x + finalShift; @@ -372,24 +371,22 @@ export default (G) => { hoveredBlockStartX, }); - // ➖ Update move points crea.remainingMove -= Math.abs(finalShift); - // ✅ Move target first (important) trg.moveTo(trgDest, { animation: 'fly', callback: () => { - trg.updateHex(); // Update grid state + trg.updateHex(); }, ignoreMovementPoint: true, }); - // ✅ Move Scavenger + // Move Scavenger crea.moveTo(creaDest, { animation: 'fly', callback: () => { - crea.updateHex(); // Update grid - crea.queryMove(); // Let player move again + crea.updateHex(); + crea.queryMove(); }, ignoreMovementPoint: true, overrideSpeed: crea.animation.walk_speed, From 30c73fb241ec37a1593d6ef54329004e7fcfc9db Mon Sep 17 00:00:00 2001 From: emna9 Date: Wed, 16 Apr 2025 02:29:03 +0100 Subject: [PATCH 10/12] fixed 1 tilr movement --- src/abilities/Scavenger.js | 1279 ++++++++++++++++++++++-------------- 1 file changed, 791 insertions(+), 488 deletions(-) diff --git a/src/abilities/Scavenger.js b/src/abilities/Scavenger.js index 25f1dc3ec..ebad9027f 100644 --- a/src/abilities/Scavenger.js +++ b/src/abilities/Scavenger.js @@ -1,504 +1,807 @@ import * as $j from 'jquery'; + import { Damage } from '../damage'; + import { Team } from '../utility/team'; + import * as matrices from '../utility/matrices'; + import * as arrayUtils from '../utility/arrayUtils'; + import { Effect } from '../effect'; + function getEscortUsableHexes(G, crea, trg) { - const trgIsInfront = - G.grid.getHexMap( - crea.x - matrices.inlinefront2hex.origin[0], - crea.y - matrices.inlinefront2hex.origin[1], - 0, - false, - matrices.inlinefront2hex, - )[0].creature === trg; - - const dir = trgIsInfront ? -1 : 1; - const creaSize = crea.size; - const trgSize = trg.size; - const totalBlockSize = creaSize + trgSize; - const blockStartX = trgIsInfront ? trg.x : crea.x; - - const distance = crea.remainingMove; - const usableHexes = []; - - console.log(`Direction: ${dir}, Block Start X: ${blockStartX}, Remaining Move: ${distance}`); - - // 1. Collect all hexes occupied by any other creatures - const reservedHexes = new Set(); - for (const row of G.grid.hexes) { - for (const hex of row) { - if (hex.creature && ![crea.id, trg.id].includes(hex.creature.id)) { - reservedHexes.add(`${hex.x},${hex.y}`); - } - } - } - - for (let shift = 1; shift <= distance; shift++) { - const hoveredBlockStartX = blockStartX + shift * dir; - console.log(`[SHIFT] Trying Shift: ${shift}, Hovered Start X: ${hoveredBlockStartX}`); - - let blockFits = true; - - // Check full block (target first, then scavenger) - for (let i = 0; i < totalBlockSize; i++) { - const x = hoveredBlockStartX + i * dir; - const y = crea.y; - - // Check if hex exists and if it's occupied by another creature - if (!G.grid.hexExists({ x, y })) { - blockFits = false; - break; - } - - if (reservedHexes.has(`${x},${y}`)) { - blockFits = false; - break; - } - } - - // If the block fits, push it to usable hexes - if (blockFits) { - console.log(`[VALID BLOCK] Usable Hex at X: ${hoveredBlockStartX}`); - usableHexes.push(G.grid.hexes[crea.y][hoveredBlockStartX]); - } else { - console.log(`[INVALID BLOCK] Block does not fit at X: ${hoveredBlockStartX}`); - } - } - - console.log("Final Usable Hexes: ", usableHexes); - - return { usableHexes, trgIsInfront, creaSize, trgSize, dir, blockStartX }; + +const trgIsInfront = + +G.grid.getHexMap( + +crea.x - matrices.inlinefront2hex.origin[0], + +crea.y - matrices.inlinefront2hex.origin[1], + +0, + +false, + +matrices.inlinefront2hex, + +)[0].creature === trg; + +const dir = trgIsInfront ? -1 : 1; + +const creaSize = crea.size; + +const trgSize = trg.size; + +const totalBlockSize = creaSize + trgSize; + +const blockStartX = trgIsInfront ? trg.x : crea.x; + +const distance = crea.remainingMove; + +const usableHexes = []; + +console.log(`Direction: ${dir}, Block Start X: ${blockStartX}, Remaining Move: ${distance}`); + +// 1. Collect all hexes occupied by any other creatures + +const reservedHexes = new Set(); + +for (const row of G.grid.hexes) { + +for (const hex of row) { + +if (hex.creature && ![crea.id, trg.id].includes(hex.creature.id)) { + +reservedHexes.add(`${hex.x},${hex.y}`); + +} + +} + +} + +for (let shift = 1; shift <= distance; shift++) { + +const hoveredBlockStartX = blockStartX + shift * dir; + +console.log(`[SHIFT] Trying Shift: ${shift}, Hovered Start X: ${hoveredBlockStartX}`); + +let blockFits = true; + +// Check full block (target first, then scavenger) + +for (let i = 0; i < totalBlockSize; i++) { + +const x = hoveredBlockStartX + i * dir; + +const y = crea.y; + +// Check if hex exists and if it's occupied by another creature + +if (!G.grid.hexExists({ x, y })) { + +blockFits = false; + +break; + +} + +if (reservedHexes.has(`${x},${y}`)) { + +blockFits = false; + +break; + +} + } +// If the block fits, push it to usable hexes +if (blockFits) { +console.log(`[VALID BLOCK] Usable Hex at X: ${hoveredBlockStartX}`); +usableHexes.push(G.grid.hexes[crea.y][hoveredBlockStartX]); +} else { + +console.log(`[INVALID BLOCK] Block does not fit at X: ${hoveredBlockStartX}`); + +} + +} + +console.log("Final Usable Hexes: ", usableHexes); + +return { usableHexes, trgIsInfront, creaSize, trgSize, dir, blockStartX }; + +} /** Creates the abilities - * @param {Object} G the game object - * @return {void} - */ + +* @param {Object} G the game object + +* @return {void} + +*/ + export default (G) => { - /* - * - * Scavenger abilities - * - */ - G.abilities[44] = [ - // First Ability: Wing Feathers - { - /** - * Provides custom movement type given whether the ability is upgraded or not. - * Movement type is "hover" unless this ability is upgraded, then it's "flying" - * @return {string} movement type, "hover" or "flying" - */ - movementType: function () { - return 'flying'; - }, - - // Type : Can be "onQuery", "onStartPhase", "onDamage" - trigger: '', - - // require() : - require: function () { - return true; - }, - - // activate() : - activate: function () {}, - }, - - // Second Ability: Slicing Pounce - { - // Type : Can be "onQuery", "onStartPhase", "onDamage" - trigger: 'onQuery', - - _targetTeam: Team.Enemy, - - // require() : - require: function () { - if (!this.testRequirements()) { - return false; - } - - if ( - !this.atLeastOneTarget(this.creature.getHexMap(matrices.frontnback2hex), { - team: this._targetTeam, - }) - ) { - return false; - } - return true; - }, - - // query() : - query: function () { - const ability = this; - - G.grid.queryCreature({ - fnOnConfirm: function () { - ability.animation(...arguments); - }, - team: this._targetTeam, - id: this.creature.id, - flipped: this.creature.player.flipped, - hexes: this.creature.getHexMap(matrices.frontnback2hex), - }); - }, - - // activate() : - activate: function (target) { - const ability = this; - ability.end(); - G.Phaser.camera.shake(0.01, 70, true, G.Phaser.camera.SHAKE_HORIZONTAL, true); - - // If upgraded, hits will debuff target with -1 offense - if (this.isUpgraded()) { - const effect = new Effect( - 'Slicing Pounce', - ability.creature, - target, - 'onDamage', - { - alterations: { - offense: -1, - }, - }, - G, - ); - target.addEffect(effect); - G.log('%CreatureName' + target.id + "%'s offense is lowered by 1"); - } - - const damage = new Damage( - ability.creature, // Attacker - ability.damages, // Damage Type - 1, // Area - [], // Effects - G, - ); - - target.takeDamage(damage); - }, - }, - - // Third Ability: Escort Service - { - // Type : Can be "onQuery", "onStartPhase", "onDamage" - trigger: 'onQuery', - - _targetTeam: Team.Both, - - // require() : - require: function () { - if (!this.testRequirements()) { - return false; - } - - const ability = this; - const crea = this.creature; - - let hexes = crea.getHexMap(matrices.inlinefrontnback2hex); - - if (hexes.length < 2) { - // At the border of the map - return false; - } - - if (hexes[0].creature && hexes[1].creature) { - // Sandwiched - return false; - } - - // Cannot escort large (size > 2) creatures unless ability is upgraded - hexes = hexes.filter(function (hex) { - if (!hex.creature) { - return false; - } - - return hex.creature.size < 3 || ability.isUpgraded(); - }); - - if ( - !this.atLeastOneTarget(hexes, { - team: this._targetTeam, - }) - ) { - return false; - } - - const trg = hexes[0].creature || hexes[1].creature; - - if (!trg.stats.moveable) { - this.message = 'Target is not moveable.'; - return false; - } - - const { usableHexes } = getEscortUsableHexes(G, crea, trg); - - if (!usableHexes.length) { - this.message = 'Not enough movement points.'; - return false; - } - - return true; - }, - - query: function () { - const ability = this; - const crea = this.creature; - - // Retrieve creatures adjacent to Scavenger in a line (front and back) - const hexes = crea.getHexMap(matrices.inlinefrontnback2hex); - const trg = hexes[0].creature || hexes[1].creature; - - // Get data to determine usable hexes, block size, and whether target is in front - const { size, trgIsInfront, usableHexes } = getEscortUsableHexes(G, crea, trg); - - console.log("[QUERY] usableHexes initially calculated:", usableHexes); - console.log("[QUERY] Block size (Scavenger + Target):", size); - console.log("[QUERY] Target is in front of Scavenger:", trgIsInfront); - - const select = (hex) => { - console.log(`[SELECT] Hovered Hex: ${hex.x}, ${hex.y}`); - - const { trgIsInfront, creaSize, trgSize, dir, blockStartX } = getEscortUsableHexes(G, crea, trg); - - [ ...trg.hexagons, ...crea.hexagons ].forEach(h => { - G.grid.cleanHex(h); - h.displayVisualState('dashed'); - }); - - const hoveredBlockStartX = hex.x; - const shift = hoveredBlockStartX - blockStartX; - - console.log(`[SELECT] Calculated Shift: ${shift}`); - - for (let i = 0; i < trgSize; i++) { - const targetX = trg.x + shift; - if (G.grid.hexExists({ x: targetX + i, y: trg.y })) { - const targetHex = G.grid.hexes[trg.y][targetX + i]; - targetHex.overlayVisualState('active creature player' + trg.team); - targetHex.displayVisualState('creature player' + trg.team); - } - } - - for (let i = 0; i < creaSize; i++) { - const creaX = crea.x + shift; - if (G.grid.hexExists({ x: creaX + i, y: crea.y })) { - const creaHex = G.grid.hexes[crea.y][creaX + i]; - creaHex.overlayVisualState('active creature player' + crea.team); - creaHex.displayVisualState('creature player' + crea.team); - } - } - - const trgPreviewGridPos = { x: trg.x + shift, y: trg.y }; - const creaPreviewGridPos = { x: crea.x + shift, y: crea.y }; - - console.log("[FIXED SELECT] Preview Target (grid):", trgPreviewGridPos); - console.log("[FIXED SELECT] Preview Scavenger (grid):", creaPreviewGridPos); - - G.grid.previewCreature(trgPreviewGridPos, G.retrieveCreatureStats(trg.type), trg.player, true); - G.grid.previewCreature(creaPreviewGridPos, G.retrieveCreatureStats(crea.type), crea.player); - }; - - // Execute hex query with hover and confirm functionality - G.grid.queryHexes({ - fnOnConfirm: function () { - G.grid.fadeOutTempCreature(); - G.grid.fadeOutTempCreature(G.grid.secondary_overlay); - ability.animation(...arguments); - }, - fnOnSelect: select, - team: this._targetTeam, - id: [crea.id, trg.id], - size: size, - flipped: crea.player.flipped, - hexes: usableHexes, - args: { - trg: trg.id, - trgIsInfront: trgIsInfront, - }, - callbackAfterQueryHexes: () => { - console.log('cleaning after query'); - for (let i = 0; i < trg.hexagons.length; i++) { - G.grid.cleanHex(trg.hexagons[i]); - trg.hexagons[i].displayVisualState('dashed'); - } - }, - fillHexOnHover: false, - }); - }, - - - - - // activate() : - activate: function (hex, args) { - const ability = this; - ability.end(); - G.Phaser.camera.shake(0.01, 66, true, G.Phaser.camera.SHAKE_HORIZONTAL, true); - - const crea = this.creature; - const trg = G.creatures[args.trg]; - - const { - blockStartX, - dir - } = getEscortUsableHexes(G, crea, trg); - - const hoveredBlockStartX = hex.x; - - // Compute how many hexes to shift - const finalShift = (hoveredBlockStartX - blockStartX); - - // Apply shift to each hex - const creaDestX = crea.x + finalShift; - const trgDestX = trg.x + finalShift; - - const creaDest = G.grid.hexes[crea.y][creaDestX]; - const trgDest = G.grid.hexes[trg.y][trgDestX]; - - console.log('[ACTIVATE]', { - finalShift, - creaDestX, - trgDestX, - blockStartX, - dir, - hoveredBlockStartX, - }); - - crea.remainingMove -= Math.abs(finalShift); - - trg.moveTo(trgDest, { - animation: 'fly', - callback: () => { - trg.updateHex(); - }, - ignoreMovementPoint: true, - }); - - // Move Scavenger - crea.moveTo(creaDest, { - animation: 'fly', - callback: () => { - crea.updateHex(); - crea.queryMove(); - }, - ignoreMovementPoint: true, - overrideSpeed: crea.animation.walk_speed, - }); - } - - - - - - - - - - - - - }, - - // Fourth Ability: Deadly Toxin - { - // Type : Can be "onQuery", "onStartPhase", "onDamage" - trigger: 'onQuery', - - _targetTeam: Team.Enemy, - - // require() : - require: function () { - if (!this.testRequirements()) { - return false; - } - - if ( - !this.atLeastOneTarget(this.creature.getHexMap(matrices.frontnback2hex), { - team: this._targetTeam, - }) - ) { - return false; - } - return true; - }, - - // query() : - query: function () { - const ability = this; - - G.grid.queryCreature({ - fnOnConfirm: function () { - ability.animation(...arguments); - }, - team: this._targetTeam, - id: this.creature.id, - flipped: this.creature.player.flipped, - hexes: this.creature.getHexMap(matrices.frontnback2hex), - }); - }, - - // activate() : - activate: function (target) { - const ability = this; - ability.end(); - G.Phaser.camera.shake(0.01, 100, true, G.Phaser.camera.SHAKE_HORIZONTAL, true); - - // Don't perform poison damage unless upgraded - const damages = $j.extend({}, ability.damages); - if (!this.isUpgraded()) { - delete damages.poison; - } - - const damage = new Damage( - ability.creature, // Attacker - damages, // Damage Type - 1, // Area - [], // Effects - G, - ); - - const result = target.takeDamage(damage); - - if (result.damageObj.status !== 'Shielded') { - // Add poison damage debuff - const effect = new Effect( - this.title, - this.creature, - target, - 'onStartPhase', - { - stackable: false, - effectFn: function (eff, creature) { - G.log('%CreatureName' + creature.id + '% is affected by ' + ability.title); - creature.takeDamage( - new Damage( - eff.owner, - { - poison: ability.damages.poison, - }, - 1, - [], - G, - ), - { isFromTrap: true }, - ); - }, - }, - G, - ); - - target.replaceEffect(effect); - - G.log('%CreatureName' + target.id + '% is poisoned by ' + this.title); - } - }, - }, - ]; -}; \ No newline at end of file + +/* + +* + +* Scavenger abilities + +* + +*/ + +G.abilities[44] = [ + +// First Ability: Wing Feathers + +{ + +/** + +* Provides custom movement type given whether the ability is upgraded or not. + +* Movement type is "hover" unless this ability is upgraded, then it's "flying" + +* @return {string} movement type, "hover" or "flying" + +*/ + +movementType: function () { + +return 'flying'; + +}, + +// Type : Can be "onQuery", "onStartPhase", "onDamage" + +trigger: '', + +// require() : + +require: function () { + +return true; + +}, + +// activate() : + +activate: function () {}, + +}, + +// Second Ability: Slicing Pounce + +{ + +// Type : Can be "onQuery", "onStartPhase", "onDamage" + +trigger: 'onQuery', + +_targetTeam: Team.Enemy, + +// require() : + +require: function () { + +if (!this.testRequirements()) { + +return false; + +} + +if ( + +!this.atLeastOneTarget(this.creature.getHexMap(matrices.frontnback2hex), { + +team: this._targetTeam, + +}) + +) { + +return false; + +} + +return true; + +}, + +// query() : + +query: function () { + +const ability = this; + +G.grid.queryCreature({ + +fnOnConfirm: function () { + +ability.animation(...arguments); + +}, + +team: this._targetTeam, + +id: this.creature.id, + +flipped: this.creature.player.flipped, + +hexes: this.creature.getHexMap(matrices.frontnback2hex), + +}); + +}, + +// activate() : + +activate: function (target) { + +const ability = this; + +ability.end(); + +G.Phaser.camera.shake(0.01, 70, true, G.Phaser.camera.SHAKE_HORIZONTAL, true); + +// If upgraded, hits will debuff target with -1 offense + +if (this.isUpgraded()) { + +const effect = new Effect( + +'Slicing Pounce', + +ability.creature, + +target, + +'onDamage', + +{ + +alterations: { + +offense: -1, + +}, + +}, + +G, + +); + +target.addEffect(effect); + +G.log('%CreatureName' + target.id + "%'s offense is lowered by 1"); + +} + +const damage = new Damage( + +ability.creature, // Attacker + +ability.damages, // Damage Type + +1, // Area + +[], // Effects + +G, + +); + +target.takeDamage(damage); + +}, + +}, + +// Third Ability: Escort Service + +{ + +// Type : Can be "onQuery", "onStartPhase", "onDamage" + +trigger: 'onQuery', + +_targetTeam: Team.Both, + +// require() : + +require: function () { + +if (!this.testRequirements()) { + +return false; + +} + +const ability = this; + +const crea = this.creature; + +let hexes = crea.getHexMap(matrices.inlinefrontnback2hex); + +if (hexes.length < 2) { + +// At the border of the map + +return false; + +} + +if (hexes[0].creature && hexes[1].creature) { + +// Sandwiched + +return false; + +} + +// Cannot escort large (size > 2) creatures unless ability is upgraded + +hexes = hexes.filter(function (hex) { + +if (!hex.creature) { + +return false; + +} + +return hex.creature.size < 3 || ability.isUpgraded(); + +}); + +if ( + +!this.atLeastOneTarget(hexes, { + +team: this._targetTeam, + +}) + +) { + +return false; + +} + +const trg = hexes[0].creature || hexes[1].creature; + +if (!trg.stats.moveable) { + +this.message = 'Target is not moveable.'; + +return false; + +} + +const { usableHexes } = getEscortUsableHexes(G, crea, trg); + +if (!usableHexes.length) { + +this.message = 'Not enough movement points.'; + +return false; + +} + +return true; + +}, + +query: function () { + +const ability = this; + +const crea = this.creature; + +// Retrieve creatures adjacent to Scavenger in a line (front and back) + +const hexes = crea.getHexMap(matrices.inlinefrontnback2hex); + +const trg = hexes[0].creature || hexes[1].creature; + +// Get data to determine usable hexes, block size, and whether target is in front + +const { size, trgIsInfront, usableHexes } = getEscortUsableHexes(G, crea, trg); + +console.log("[QUERY] usableHexes initially calculated:", usableHexes); + +console.log("[QUERY] Block size (Scavenger + Target):", size); + +console.log("[QUERY] Target is in front of Scavenger:", trgIsInfront); + +const select = (hex) => { + +console.log(`[SELECT] Hovered Hex: ${hex.x}, ${hex.y}`); + +const { trgIsInfront, creaSize, trgSize, dir, blockStartX } = getEscortUsableHexes(G, crea, trg); + +[ ...trg.hexagons, ...crea.hexagons ].forEach(h => { + +G.grid.cleanHex(h); + +h.displayVisualState('dashed'); + +}); + +const hoveredBlockStartX = hex.x; + +const shift = hoveredBlockStartX - blockStartX; + +console.log(`[SELECT] Calculated Shift: ${shift}`); + +for (let i = 0; i < trgSize; i++) { + +const targetX = trg.x + shift; + +if (G.grid.hexExists({ x: targetX + i, y: trg.y })) { + +const targetHex = G.grid.hexes[trg.y][targetX + i]; + +targetHex.overlayVisualState('active creature player' + trg.team); + +targetHex.displayVisualState('creature player' + trg.team); + +} + +} + +for (let i = 0; i < creaSize; i++) { + +const creaX = crea.x + shift; + +if (G.grid.hexExists({ x: creaX + i, y: crea.y })) { + +const creaHex = G.grid.hexes[crea.y][creaX + i]; + +creaHex.overlayVisualState('active creature player' + crea.team); + +creaHex.displayVisualState('creature player' + crea.team); + +} + +} + +const trgPreviewGridPos = { x: trg.x + shift, y: trg.y }; + +const creaPreviewGridPos = { x: crea.x + shift, y: crea.y }; + +console.log("[FIXED SELECT] Preview Target (grid):", trgPreviewGridPos); + +console.log("[FIXED SELECT] Preview Scavenger (grid):", creaPreviewGridPos); + +G.grid.previewCreature(trgPreviewGridPos, G.retrieveCreatureStats(trg.type), trg.player, true); + +G.grid.previewCreature(creaPreviewGridPos, G.retrieveCreatureStats(crea.type), crea.player); + +}; + +// Execute hex query with hover and confirm functionality + +G.grid.queryHexes({ + +fnOnConfirm: function () { + +G.grid.fadeOutTempCreature(); + +G.grid.fadeOutTempCreature(G.grid.secondary_overlay); + +ability.animation(...arguments); + +}, + +fnOnSelect: select, + +team: this._targetTeam, + +id: [crea.id, trg.id], + +size: size, + +flipped: crea.player.flipped, + +hexes: usableHexes, + +args: { + +trg: trg.id, + +trgIsInfront: trgIsInfront, + +}, + +callbackAfterQueryHexes: () => { + +console.log('cleaning after query'); + +for (let i = 0; i < trg.hexagons.length; i++) { + +G.grid.cleanHex(trg.hexagons[i]); + +trg.hexagons[i].displayVisualState('dashed'); + +} + +}, + +fillHexOnHover: false, + +}); + +}, + +// activate() : + +activate: function (hex, args) { + +const ability = this; + +ability.end(); + +G.Phaser.camera.shake(0.01, 66, true, G.Phaser.camera.SHAKE_HORIZONTAL, true); + +const crea = this.creature; + +const trg = G.creatures[args.trg]; + +const { + +blockStartX, + +dir + +} = getEscortUsableHexes(G, crea, trg); + +const hoveredBlockStartX = hex.x; + +// Compute how many hexes to shift + +const finalShift = (hoveredBlockStartX - blockStartX); + +// Apply shift to each hex + +const creaDestX = crea.x + finalShift; + +const trgDestX = trg.x + finalShift; + +const creaDest = G.grid.hexes[crea.y][creaDestX]; + +const trgDest = G.grid.hexes[trg.y][trgDestX]; + +console.log('[ACTIVATE]', { + +finalShift, + +creaDestX, + +trgDestX, + +blockStartX, + +dir, + +hoveredBlockStartX, + +}); + +crea.remainingMove -= Math.abs(finalShift); + +trg.moveTo(trgDest, { + +animation: 'fly', + +callback: () => { + +trg.updateHex(); + +}, + +ignoreMovementPoint: true, + +}); + +// Move Scavenger + +crea.moveTo(creaDest, { + +animation: 'fly', + +callback: () => { + +crea.updateHex(); + +crea.queryMove(); + +}, + +ignoreMovementPoint: true, + +overrideSpeed: crea.animation.walk_speed, + +}); + +} + +}, + +// Fourth Ability: Deadly Toxin + +{ + +// Type : Can be "onQuery", "onStartPhase", "onDamage" + +trigger: 'onQuery', + +_targetTeam: Team.Enemy, + +// require() : + +require: function () { + +if (!this.testRequirements()) { + +return false; + +} + +if ( + +!this.atLeastOneTarget(this.creature.getHexMap(matrices.frontnback2hex), { + +team: this._targetTeam, + +}) + +) { + +return false; + +} + +return true; + +}, + +// query() : + +query: function () { + +const ability = this; + +G.grid.queryCreature({ + +fnOnConfirm: function () { + +ability.animation(...arguments); + +}, + +team: this._targetTeam, + +id: this.creature.id, + +flipped: this.creature.player.flipped, + +hexes: this.creature.getHexMap(matrices.frontnback2hex), + +}); + +}, + +// activate() : + +activate: function (target) { + +const ability = this; + +ability.end(); + +G.Phaser.camera.shake(0.01, 100, true, G.Phaser.camera.SHAKE_HORIZONTAL, true); + +// Don't perform poison damage unless upgraded + +const damages = $j.extend({}, ability.damages); + +if (!this.isUpgraded()) { + +delete damages.poison; + +} + +const damage = new Damage( + +ability.creature, // Attacker + +damages, // Damage Type + +1, // Area + +[], // Effects + +G, + +); + +const result = target.takeDamage(damage); + +if (result.damageObj.status !== 'Shielded') { + +// Add poison damage debuff + +const effect = new Effect( + +this.title, + +this.creature, + +target, + +'onStartPhase', + +{ + +stackable: false, + +effectFn: function (eff, creature) { + +G.log('%CreatureName' + creature.id + '% is affected by ' + ability.title); + +creature.takeDamage( + +new Damage( + +eff.owner, + +{ + +poison: ability.damages.poison, + +}, + +1, + +[], + +G, + +), + +{ isFromTrap: true }, + +); + +}, + +}, + +G, + +); + +target.replaceEffect(effect); + +G.log('%CreatureName' + target.id + '% is poisoned by ' + this.title); + +} + +}, + +}, + +]; + +}; \ No newline at end of file From fd97651a6aa847310cd61fa3ff258822b73856bb Mon Sep 17 00:00:00 2001 From: emna9 Date: Wed, 16 Apr 2025 02:36:36 +0100 Subject: [PATCH 11/12] test --- src/abilities/Scavenger.js | 1259 +++++++++++++----------------------- 1 file changed, 462 insertions(+), 797 deletions(-) diff --git a/src/abilities/Scavenger.js b/src/abilities/Scavenger.js index ebad9027f..87130ed0b 100644 --- a/src/abilities/Scavenger.js +++ b/src/abilities/Scavenger.js @@ -1,807 +1,472 @@ import * as $j from 'jquery'; - import { Damage } from '../damage'; - import { Team } from '../utility/team'; - import * as matrices from '../utility/matrices'; - import * as arrayUtils from '../utility/arrayUtils'; - import { Effect } from '../effect'; - function getEscortUsableHexes(G, crea, trg) { - -const trgIsInfront = - -G.grid.getHexMap( - -crea.x - matrices.inlinefront2hex.origin[0], - -crea.y - matrices.inlinefront2hex.origin[1], - -0, - -false, - -matrices.inlinefront2hex, - -)[0].creature === trg; - -const dir = trgIsInfront ? -1 : 1; - -const creaSize = crea.size; - -const trgSize = trg.size; - -const totalBlockSize = creaSize + trgSize; - -const blockStartX = trgIsInfront ? trg.x : crea.x; - -const distance = crea.remainingMove; - -const usableHexes = []; - -console.log(`Direction: ${dir}, Block Start X: ${blockStartX}, Remaining Move: ${distance}`); - -// 1. Collect all hexes occupied by any other creatures - -const reservedHexes = new Set(); - -for (const row of G.grid.hexes) { - -for (const hex of row) { - -if (hex.creature && ![crea.id, trg.id].includes(hex.creature.id)) { - -reservedHexes.add(`${hex.x},${hex.y}`); - -} - -} - -} - -for (let shift = 1; shift <= distance; shift++) { - -const hoveredBlockStartX = blockStartX + shift * dir; - -console.log(`[SHIFT] Trying Shift: ${shift}, Hovered Start X: ${hoveredBlockStartX}`); - -let blockFits = true; - -// Check full block (target first, then scavenger) - -for (let i = 0; i < totalBlockSize; i++) { - -const x = hoveredBlockStartX + i * dir; - -const y = crea.y; - -// Check if hex exists and if it's occupied by another creature - -if (!G.grid.hexExists({ x, y })) { - -blockFits = false; - -break; - -} - -if (reservedHexes.has(`${x},${y}`)) { - -blockFits = false; - -break; - -} - + const trgIsInfront = + G.grid.getHexMap( + crea.x - matrices.inlinefront2hex.origin[0], + crea.y - matrices.inlinefront2hex.origin[1], + 0, + false, + matrices.inlinefront2hex, + )[0].creature === trg; + + const dir = trgIsInfront ? -1 : 1; // Direction of movement + const creaSize = crea.size; + const trgSize = trg.size; + const totalBlockSize = creaSize + trgSize; + const blockStartX = trgIsInfront ? trg.x : crea.x; + + const distance = crea.remainingMove; + const usableHexes = []; + + console.log(`Direction: ${dir}, Block Start X: ${blockStartX}, Remaining Move: ${distance}`); + + // 1. Collect all hexes occupied by any other creatures + const reservedHexes = new Set(); + for (const row of G.grid.hexes) { + for (const hex of row) { + if (hex.creature && ![crea.id, trg.id].includes(hex.creature.id)) { + reservedHexes.add(`${hex.x},${hex.y}`); + } + } + } + + for (let shift = 1; shift <= distance; shift++) { + const hoveredBlockStartX = blockStartX + shift * dir; + console.log(`[SHIFT] Trying Shift: ${shift}, Hovered Start X: ${hoveredBlockStartX}`); + + let blockFits = true; + + // Check full block (target first, then scavenger) + for (let i = 0; i < totalBlockSize; i++) { + const x = hoveredBlockStartX + i * dir; + const y = crea.y; + + // Check if hex exists and if it's occupied by another creature + if (!G.grid.hexExists({ x, y })) { + blockFits = false; + break; + } + + if (reservedHexes.has(`${x},${y}`)) { + blockFits = false; + break; + } + } + + // If the block fits, push it to usable hexes + if (blockFits) { + usableHexes.push(G.grid.hexes[crea.y][hoveredBlockStartX]); + } else { + console.log(`[INVALID BLOCK] Block does not fit at X: ${hoveredBlockStartX}`); + } + } + + console.log("Final Usable Hexes: ", usableHexes); + + return { usableHexes, trgIsInfront, creaSize, trgSize, dir, blockStartX }; } - -// If the block fits, push it to usable hexes - -if (blockFits) { - -console.log(`[VALID BLOCK] Usable Hex at X: ${hoveredBlockStartX}`); - -usableHexes.push(G.grid.hexes[crea.y][hoveredBlockStartX]); - -} else { - -console.log(`[INVALID BLOCK] Block does not fit at X: ${hoveredBlockStartX}`); - -} - -} - -console.log("Final Usable Hexes: ", usableHexes); - -return { usableHexes, trgIsInfront, creaSize, trgSize, dir, blockStartX }; - -} - /** Creates the abilities - -* @param {Object} G the game object - -* @return {void} - -*/ - + * @param {Object} G the game object + * @return {void} + */ export default (G) => { - -/* - -* - -* Scavenger abilities - -* - -*/ - -G.abilities[44] = [ - -// First Ability: Wing Feathers - -{ - -/** - -* Provides custom movement type given whether the ability is upgraded or not. - -* Movement type is "hover" unless this ability is upgraded, then it's "flying" - -* @return {string} movement type, "hover" or "flying" - -*/ - -movementType: function () { - -return 'flying'; - -}, - -// Type : Can be "onQuery", "onStartPhase", "onDamage" - -trigger: '', - -// require() : - -require: function () { - -return true; - -}, - -// activate() : - -activate: function () {}, - -}, - -// Second Ability: Slicing Pounce - -{ - -// Type : Can be "onQuery", "onStartPhase", "onDamage" - -trigger: 'onQuery', - -_targetTeam: Team.Enemy, - -// require() : - -require: function () { - -if (!this.testRequirements()) { - -return false; - -} - -if ( - -!this.atLeastOneTarget(this.creature.getHexMap(matrices.frontnback2hex), { - -team: this._targetTeam, - -}) - -) { - -return false; - -} - -return true; - -}, - -// query() : - -query: function () { - -const ability = this; - -G.grid.queryCreature({ - -fnOnConfirm: function () { - -ability.animation(...arguments); - -}, - -team: this._targetTeam, - -id: this.creature.id, - -flipped: this.creature.player.flipped, - -hexes: this.creature.getHexMap(matrices.frontnback2hex), - -}); - -}, - -// activate() : - -activate: function (target) { - -const ability = this; - -ability.end(); - -G.Phaser.camera.shake(0.01, 70, true, G.Phaser.camera.SHAKE_HORIZONTAL, true); - -// If upgraded, hits will debuff target with -1 offense - -if (this.isUpgraded()) { - -const effect = new Effect( - -'Slicing Pounce', - -ability.creature, - -target, - -'onDamage', - -{ - -alterations: { - -offense: -1, - -}, - -}, - -G, - -); - -target.addEffect(effect); - -G.log('%CreatureName' + target.id + "%'s offense is lowered by 1"); - -} - -const damage = new Damage( - -ability.creature, // Attacker - -ability.damages, // Damage Type - -1, // Area - -[], // Effects - -G, - -); - -target.takeDamage(damage); - -}, - -}, - -// Third Ability: Escort Service - -{ - -// Type : Can be "onQuery", "onStartPhase", "onDamage" - -trigger: 'onQuery', - -_targetTeam: Team.Both, - -// require() : - -require: function () { - -if (!this.testRequirements()) { - -return false; - -} - -const ability = this; - -const crea = this.creature; - -let hexes = crea.getHexMap(matrices.inlinefrontnback2hex); - -if (hexes.length < 2) { - -// At the border of the map - -return false; - -} - -if (hexes[0].creature && hexes[1].creature) { - -// Sandwiched - -return false; - -} - -// Cannot escort large (size > 2) creatures unless ability is upgraded - -hexes = hexes.filter(function (hex) { - -if (!hex.creature) { - -return false; - -} - -return hex.creature.size < 3 || ability.isUpgraded(); - -}); - -if ( - -!this.atLeastOneTarget(hexes, { - -team: this._targetTeam, - -}) - -) { - -return false; - -} - -const trg = hexes[0].creature || hexes[1].creature; - -if (!trg.stats.moveable) { - -this.message = 'Target is not moveable.'; - -return false; - -} - -const { usableHexes } = getEscortUsableHexes(G, crea, trg); - -if (!usableHexes.length) { - -this.message = 'Not enough movement points.'; - -return false; - -} - -return true; - -}, - -query: function () { - -const ability = this; - -const crea = this.creature; - -// Retrieve creatures adjacent to Scavenger in a line (front and back) - -const hexes = crea.getHexMap(matrices.inlinefrontnback2hex); - -const trg = hexes[0].creature || hexes[1].creature; - -// Get data to determine usable hexes, block size, and whether target is in front - -const { size, trgIsInfront, usableHexes } = getEscortUsableHexes(G, crea, trg); - -console.log("[QUERY] usableHexes initially calculated:", usableHexes); - -console.log("[QUERY] Block size (Scavenger + Target):", size); - -console.log("[QUERY] Target is in front of Scavenger:", trgIsInfront); - -const select = (hex) => { - -console.log(`[SELECT] Hovered Hex: ${hex.x}, ${hex.y}`); - -const { trgIsInfront, creaSize, trgSize, dir, blockStartX } = getEscortUsableHexes(G, crea, trg); - -[ ...trg.hexagons, ...crea.hexagons ].forEach(h => { - -G.grid.cleanHex(h); - -h.displayVisualState('dashed'); - -}); - -const hoveredBlockStartX = hex.x; - -const shift = hoveredBlockStartX - blockStartX; - -console.log(`[SELECT] Calculated Shift: ${shift}`); - -for (let i = 0; i < trgSize; i++) { - -const targetX = trg.x + shift; - -if (G.grid.hexExists({ x: targetX + i, y: trg.y })) { - -const targetHex = G.grid.hexes[trg.y][targetX + i]; - -targetHex.overlayVisualState('active creature player' + trg.team); - -targetHex.displayVisualState('creature player' + trg.team); - -} - -} - -for (let i = 0; i < creaSize; i++) { - -const creaX = crea.x + shift; - -if (G.grid.hexExists({ x: creaX + i, y: crea.y })) { - -const creaHex = G.grid.hexes[crea.y][creaX + i]; - -creaHex.overlayVisualState('active creature player' + crea.team); - -creaHex.displayVisualState('creature player' + crea.team); - -} - -} - -const trgPreviewGridPos = { x: trg.x + shift, y: trg.y }; - -const creaPreviewGridPos = { x: crea.x + shift, y: crea.y }; - -console.log("[FIXED SELECT] Preview Target (grid):", trgPreviewGridPos); - -console.log("[FIXED SELECT] Preview Scavenger (grid):", creaPreviewGridPos); - -G.grid.previewCreature(trgPreviewGridPos, G.retrieveCreatureStats(trg.type), trg.player, true); - -G.grid.previewCreature(creaPreviewGridPos, G.retrieveCreatureStats(crea.type), crea.player); - -}; - -// Execute hex query with hover and confirm functionality - -G.grid.queryHexes({ - -fnOnConfirm: function () { - -G.grid.fadeOutTempCreature(); - -G.grid.fadeOutTempCreature(G.grid.secondary_overlay); - -ability.animation(...arguments); - -}, - -fnOnSelect: select, - -team: this._targetTeam, - -id: [crea.id, trg.id], - -size: size, - -flipped: crea.player.flipped, - -hexes: usableHexes, - -args: { - -trg: trg.id, - -trgIsInfront: trgIsInfront, - -}, - -callbackAfterQueryHexes: () => { - -console.log('cleaning after query'); - -for (let i = 0; i < trg.hexagons.length; i++) { - -G.grid.cleanHex(trg.hexagons[i]); - -trg.hexagons[i].displayVisualState('dashed'); - -} - -}, - -fillHexOnHover: false, - -}); - -}, - -// activate() : - -activate: function (hex, args) { - -const ability = this; - -ability.end(); - -G.Phaser.camera.shake(0.01, 66, true, G.Phaser.camera.SHAKE_HORIZONTAL, true); - -const crea = this.creature; - -const trg = G.creatures[args.trg]; - -const { - -blockStartX, - -dir - -} = getEscortUsableHexes(G, crea, trg); - -const hoveredBlockStartX = hex.x; - -// Compute how many hexes to shift - -const finalShift = (hoveredBlockStartX - blockStartX); - -// Apply shift to each hex - -const creaDestX = crea.x + finalShift; - -const trgDestX = trg.x + finalShift; - -const creaDest = G.grid.hexes[crea.y][creaDestX]; - -const trgDest = G.grid.hexes[trg.y][trgDestX]; - -console.log('[ACTIVATE]', { - -finalShift, - -creaDestX, - -trgDestX, - -blockStartX, - -dir, - -hoveredBlockStartX, - -}); - -crea.remainingMove -= Math.abs(finalShift); - -trg.moveTo(trgDest, { - -animation: 'fly', - -callback: () => { - -trg.updateHex(); - -}, - -ignoreMovementPoint: true, - -}); - -// Move Scavenger - -crea.moveTo(creaDest, { - -animation: 'fly', - -callback: () => { - -crea.updateHex(); - -crea.queryMove(); - -}, - -ignoreMovementPoint: true, - -overrideSpeed: crea.animation.walk_speed, - -}); - -} - -}, - -// Fourth Ability: Deadly Toxin - -{ - -// Type : Can be "onQuery", "onStartPhase", "onDamage" - -trigger: 'onQuery', - -_targetTeam: Team.Enemy, - -// require() : - -require: function () { - -if (!this.testRequirements()) { - -return false; - -} - -if ( - -!this.atLeastOneTarget(this.creature.getHexMap(matrices.frontnback2hex), { - -team: this._targetTeam, - -}) - -) { - -return false; - -} - -return true; - -}, - -// query() : - -query: function () { - -const ability = this; - -G.grid.queryCreature({ - -fnOnConfirm: function () { - -ability.animation(...arguments); - -}, - -team: this._targetTeam, - -id: this.creature.id, - -flipped: this.creature.player.flipped, - -hexes: this.creature.getHexMap(matrices.frontnback2hex), - -}); - -}, - -// activate() : - -activate: function (target) { - -const ability = this; - -ability.end(); - -G.Phaser.camera.shake(0.01, 100, true, G.Phaser.camera.SHAKE_HORIZONTAL, true); - -// Don't perform poison damage unless upgraded - -const damages = $j.extend({}, ability.damages); - -if (!this.isUpgraded()) { - -delete damages.poison; - -} - -const damage = new Damage( - -ability.creature, // Attacker - -damages, // Damage Type - -1, // Area - -[], // Effects - -G, - -); - -const result = target.takeDamage(damage); - -if (result.damageObj.status !== 'Shielded') { - -// Add poison damage debuff - -const effect = new Effect( - -this.title, - -this.creature, - -target, - -'onStartPhase', - -{ - -stackable: false, - -effectFn: function (eff, creature) { - -G.log('%CreatureName' + creature.id + '% is affected by ' + ability.title); - -creature.takeDamage( - -new Damage( - -eff.owner, - -{ - -poison: ability.damages.poison, - -}, - -1, - -[], - -G, - -), - -{ isFromTrap: true }, - -); - -}, - -}, - -G, - -); - -target.replaceEffect(effect); - -G.log('%CreatureName' + target.id + '% is poisoned by ' + this.title); - -} - -}, - -}, - -]; - -}; \ No newline at end of file + /* + * + * Scavenger abilities + * + */ + G.abilities[44] = [ + // First Ability: Wing Feathers + { + /** + * Provides custom movement type given whether the ability is upgraded or not. + * Movement type is "hover" unless this ability is upgraded, then it's "flying" + * @return {string} movement type, "hover" or "flying" + */ + movementType: function () { + return 'flying'; + }, + + // Type : Can be "onQuery", "onStartPhase", "onDamage" + trigger: '', + + // require() : + require: function () { + return true; + }, + + // activate() : + activate: function () {}, + }, + + // Second Ability: Slicing Pounce + { + // Type : Can be "onQuery", "onStartPhase", "onDamage" + trigger: 'onQuery', + + _targetTeam: Team.Enemy, + + // require() : + require: function () { + if (!this.testRequirements()) { + return false; + } + + if ( + !this.atLeastOneTarget(this.creature.getHexMap(matrices.frontnback2hex), { + team: this._targetTeam, + }) + ) { + return false; + } + return true; + }, + + // query() : + query: function () { + const ability = this; + + G.grid.queryCreature({ + fnOnConfirm: function () { + ability.animation(...arguments); + }, + team: this._targetTeam, + id: this.creature.id, + flipped: this.creature.player.flipped, + hexes: this.creature.getHexMap(matrices.frontnback2hex), + }); + }, + + // activate() : + activate: function (target) { + const ability = this; + ability.end(); + G.Phaser.camera.shake(0.01, 70, true, G.Phaser.camera.SHAKE_HORIZONTAL, true); + + // If upgraded, hits will debuff target with -1 offense + if (this.isUpgraded()) { + const effect = new Effect( + 'Slicing Pounce', + ability.creature, + target, + 'onDamage', + { + alterations: { + offense: -1, + }, + }, + G, + ); + target.addEffect(effect); + G.log('%CreatureName' + target.id + "%'s offense is lowered by 1"); + } + + const damage = new Damage( + ability.creature, // Attacker + ability.damages, // Damage Type + 1, // Area + [], // Effects + G, + ); + + target.takeDamage(damage); + }, + }, + + // Third Ability: Escort Service + { + // Type : Can be "onQuery", "onStartPhase", "onDamage" + trigger: 'onQuery', + + _targetTeam: Team.Both, + + // require() : + require: function () { + if (!this.testRequirements()) { + return false; + } + + const ability = this; + const crea = this.creature; + + let hexes = crea.getHexMap(matrices.inlinefrontnback2hex); + + if (hexes.length < 2) { + // At the border of the map + return false; + } + + if (hexes[0].creature && hexes[1].creature) { + // Sandwiched + return false; + } + + // Cannot escort large (size > 2) creatures unless ability is upgraded + hexes = hexes.filter(function (hex) { + if (!hex.creature) { + return false; + } + + return hex.creature.size < 3 || ability.isUpgraded(); + }); + + if ( + !this.atLeastOneTarget(hexes, { + team: this._targetTeam, + }) + ) { + return false; + } + + const trg = hexes[0].creature || hexes[1].creature; + + if (!trg.stats.moveable) { + this.message = 'Target is not moveable.'; + return false; + } + + const { usableHexes } = getEscortUsableHexes(G, crea, trg); + + if (!usableHexes.length) { + this.message = 'Not enough movement points.'; + return false; + } + + return true; + }, + + query: function () { + const ability = this; + const crea = this.creature; + + // Retrieve creatures adjacent to Scavenger in a line (front and back) + const hexes = crea.getHexMap(matrices.inlinefrontnback2hex); + const trg = hexes[0].creature || hexes[1].creature; + + // Get data to determine usable hexes, block size, and whether target is in front + const { size, trgIsInfront, usableHexes } = getEscortUsableHexes(G, crea, trg); + const select = (hex) => { + console.log(`[SELECT] Hovered Hex: ${hex.x}, ${hex.y}`); + + const { trgIsInfront, creaSize, trgSize, dir, blockStartX } = getEscortUsableHexes(G, crea, trg); + + [ ...trg.hexagons, ...crea.hexagons ].forEach(h => { + G.grid.cleanHex(h); + h.displayVisualState('dashed'); + }); + + const hoveredBlockStartX = hex.x; + const shift = hoveredBlockStartX - blockStartX; + + console.log(`[SELECT] Calculated Shift: ${shift}`); + + for (let i = 0; i < trgSize; i++) { + const targetX = trg.x + shift; + if (G.grid.hexExists({ x: targetX + i, y: trg.y })) { + const targetHex = G.grid.hexes[trg.y][targetX + i]; + targetHex.overlayVisualState('active creature player' + trg.team); + targetHex.displayVisualState('creature player' + trg.team); + } + } + + for (let i = 0; i < creaSize; i++) { + const creaX = crea.x + shift; + if (G.grid.hexExists({ x: creaX + i, y: crea.y })) { + const creaHex = G.grid.hexes[crea.y][creaX + i]; + creaHex.overlayVisualState('active creature player' + crea.team); + creaHex.displayVisualState('creature player' + crea.team); + } + } + + const trgPreviewGridPos = { x: trg.x + shift, y: trg.y }; + const creaPreviewGridPos = { x: crea.x + shift, y: crea.y } + G.grid.previewCreature(trgPreviewGridPos, G.retrieveCreatureStats(trg.type), trg.player, true); + G.grid.previewCreature(creaPreviewGridPos, G.retrieveCreatureStats(crea.type), crea.player); + }; + + // Execute hex query with hover and confirm functionality + G.grid.queryHexes({ + fnOnConfirm: function () { + G.grid.fadeOutTempCreature(); + G.grid.fadeOutTempCreature(G.grid.secondary_overlay); + ability.animation(...arguments); + }, + fnOnSelect: select, + team: this._targetTeam, + id: [crea.id, trg.id], + size: size, + flipped: crea.player.flipped, + hexes: usableHexes, + args: { + trg: trg.id, + trgIsInfront: trgIsInfront, + }, + callbackAfterQueryHexes: () => { + console.log('cleaning after query'); + for (let i = 0; i < trg.hexagons.length; i++) { + G.grid.cleanHex(trg.hexagons[i]); + trg.hexagons[i].displayVisualState('dashed'); + } + }, + fillHexOnHover: false, + }); + }, + // activate() : + activate: function (hex, args) { + const ability = this; + ability.end(); + G.Phaser.camera.shake(0.01, 66, true, G.Phaser.camera.SHAKE_HORIZONTAL, true); + + const crea = this.creature; + const trg = G.creatures[args.trg]; + + const { + blockStartX, + dir + } = getEscortUsableHexes(G, crea, trg); + + const hoveredBlockStartX = hex.x; + + //Compute how many hexes to shift + const finalShift = (hoveredBlockStartX - blockStartX); + + //Apply shift to each hex + const creaDestX = crea.x + finalShift; + const trgDestX = trg.x + finalShift; + + const creaDest = G.grid.hexes[crea.y][creaDestX]; + const trgDest = G.grid.hexes[trg.y][trgDestX]; + + console.log('[ACTIVATE]', { + finalShift, + creaDestX, + trgDestX, + blockStartX, + dir, + hoveredBlockStartX, + }); + + //Update move points + crea.remainingMove -= Math.abs(finalShift); + trg.moveTo(trgDest, { + animation: 'fly', + callback: () => { + trg.updateHex(); + }, + ignoreMovementPoint: true, + }); + + //Move Scavenger + crea.moveTo(creaDest, { + animation: 'fly', + callback: () => { + crea.updateHex(); + crea.queryMove(); + }, + ignoreMovementPoint: true, + overrideSpeed: crea.animation.walk_speed, + }); + } + }, + + // Fourth Ability: Deadly Toxin + { + // Type : Can be "onQuery", "onStartPhase", "onDamage" + trigger: 'onQuery', + + _targetTeam: Team.Enemy, + + // require() : + require: function () { + if (!this.testRequirements()) { + return false; + } + + if ( + !this.atLeastOneTarget(this.creature.getHexMap(matrices.frontnback2hex), { + team: this._targetTeam, + }) + ) { + return false; + } + return true; + }, + + // query() : + query: function () { + const ability = this; + + G.grid.queryCreature({ + fnOnConfirm: function () { + ability.animation(...arguments); + }, + team: this._targetTeam, + id: this.creature.id, + flipped: this.creature.player.flipped, + hexes: this.creature.getHexMap(matrices.frontnback2hex), + }); + }, + + // activate() : + activate: function (target) { + const ability = this; + ability.end(); + G.Phaser.camera.shake(0.01, 100, true, G.Phaser.camera.SHAKE_HORIZONTAL, true); + + // Don't perform poison damage unless upgraded + const damages = $j.extend({}, ability.damages); + if (!this.isUpgraded()) { + delete damages.poison; + } + + const damage = new Damage( + ability.creature, // Attacker + damages, // Damage Type + 1, // Area + [], // Effects + G, + ); + + const result = target.takeDamage(damage); + + if (result.damageObj.status !== 'Shielded') { + // Add poison damage debuff + const effect = new Effect( + this.title, + this.creature, + target, + 'onStartPhase', + { + stackable: false, + effectFn: function (eff, creature) { + G.log('%CreatureName' + creature.id + '% is affected by ' + ability.title); + creature.takeDamage( + new Damage( + eff.owner, + { + poison: ability.damages.poison, + }, + 1, + [], + G, + ), + { isFromTrap: true }, + ); + }, + }, + G, + ); + + target.replaceEffect(effect); + + G.log('%CreatureName' + target.id + '% is poisoned by ' + this.title); + } + }, + }, + ]; +}; \ No newline at end of file From 47dd21a776311c5ad123095981ed949e9550eea7 Mon Sep 17 00:00:00 2001 From: emna9 Date: Wed, 16 Apr 2025 03:13:50 +0100 Subject: [PATCH 12/12] cleanup --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 71794564c..5d2e29328 100755 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![OpenCollective Badge](https://opencollective.com/ancientbeast/tiers/badge.svg)](https://opencollective.com/AncientBeast) [![Discord](https://img.shields.io/discord/154868963132571649?logo=discord&label=Discord&color=5865F2)](https://discord.gg/CtqBsnF85z) -o + ![1vs1 Dark Forest](https://raw.github.com/FreezingMoon/AncientBeast-Website/master/multimedia/screenshots/v0.3%20Dark%20Forest.jpg) **"We all die. The goal isn't to live forever. The goal is to create something that will."** _Chuck Palahniuk_