diff --git a/daggerheart.mjs b/daggerheart.mjs index 05b57ac9..1987ec12 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -420,7 +420,10 @@ const updateActorsRangeDependentEffects = async token => { // Get required distance and special case 5 feet to test adjacency const required = rangeMeasurement[range]; const reverse = type === CONFIG.DH.GENERAL.rangeInclusion.outsideRange.id; - const inRange = userTarget.distanceTo(token.object) <= required; + const inRange = + required === 5 + ? userTarget.isAdjacentWith(token.object) + : userTarget.distanceTo(token.object) <= required; if (reverse ? inRange : !inRange) { enabledEffect = false; break; diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index 449880fb..49f7dcf0 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -431,18 +431,18 @@ export default function DHApplicationMixin(Base) { { name: 'disableEffect', icon: 'fa-solid fa-lightbulb', - condition: element => { - const target = element.closest('[data-item-uuid]'); - return !target.dataset.disabled && target.dataset.itemType !== 'beastform'; + condition: target => { + const doc = getDocFromElementSync(target); + return doc && !doc.disabled && doc.type !== 'beastform'; }, callback: async target => (await getDocFromElement(target)).update({ disabled: true }) }, { name: 'enableEffect', icon: 'fa-regular fa-lightbulb', - condition: element => { - const target = element.closest('[data-item-uuid]'); - return target.dataset.disabled && target.dataset.itemType !== 'beastform'; + condition: target => { + const doc = getDocFromElementSync(target); + return doc && doc.disabled && doc.type !== 'beastform'; }, callback: async target => (await getDocFromElement(target)).update({ disabled: false }) } @@ -536,9 +536,9 @@ export default function DHApplicationMixin(Base) { options.push({ name: 'CONTROLS.CommonDelete', icon: 'fa-solid fa-trash', - condition: element => { - const target = element.closest('[data-item-uuid]'); - return target.dataset.itemType !== 'beastform'; + condition: target => { + const doc = getDocFromElementSync(target); + return doc && doc.type !== 'beastform'; }, callback: async (target, event) => { const doc = await getDocFromElement(target); diff --git a/module/canvas/placeables/token.mjs b/module/canvas/placeables/token.mjs index 148466c1..068f21e1 100644 --- a/module/canvas/placeables/token.mjs +++ b/module/canvas/placeables/token.mjs @@ -54,58 +54,30 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token { if (this === target) return 0; const originPoint = this.center; - const targetPoint = target.center; - const thisBounds = this.bounds; - const targetBounds = target.bounds; - const adjacencyBuffer = canvas.grid.distance * 1.75; // handles diagonals with one square elevation difference - - // Figure out the elevation difference. - // This intends to return "grid distance" for adjacent ones, so we add that number if not overlapping. - const sizePerUnit = canvas.grid.size / canvas.grid.distance; - const thisHeight = Math.max(thisBounds.width, thisBounds.height) / sizePerUnit; - const targetHeight = Math.max(targetBounds.width, targetBounds.height) / sizePerUnit; - const thisElevation = [this.document.elevation, this.document.elevation + thisHeight]; - const targetElevation = [target.document.elevation, target.document.elevation + targetHeight]; - const isSameAltitude = - thisElevation[0] < targetElevation[1] && // bottom of this must be at or below the top of target - thisElevation[1] > targetElevation[0]; // top of this must be at or above the bottom of target - const [lower, higher] = [targetElevation, thisElevation].sort((a, b) => a[1] - b[1]); - const elevation = isSameAltitude ? 0 : higher[0] - lower[1] + canvas.grid.distance; + const destinationPoint = target.center; // Compute for gridless. This version returns circular edge to edge + grid distance, // so that tokens that are touching return 5. if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) { const boundsCorrection = canvas.grid.distance / canvas.grid.size; - const originRadius = (thisBounds.width * boundsCorrection) / 2; - const targetRadius = (targetBounds.width * boundsCorrection) / 2; - const measuredDistance = canvas.grid.measurePath([ - { ...originPoint, elevation: 0 }, - { ...targetPoint, elevation } - ]).distance; - const distance = Math.floor(measuredDistance - originRadius - targetRadius + canvas.grid.distance); - return Math.min(distance, distance > adjacencyBuffer ? Infinity : canvas.grid.distance); + const originRadius = (this.bounds.width * boundsCorrection) / 2; + const targetRadius = (target.bounds.width * boundsCorrection) / 2; + const distance = canvas.grid.measurePath([originPoint, destinationPoint]).distance; + return Math.floor(distance - originRadius - targetRadius + canvas.grid.distance); } // Compute what the closest grid space of each token is, then compute that distance - const originEdge = this.#getEdgeBoundary(thisBounds, originPoint, targetPoint); - const targetEdge = this.#getEdgeBoundary(targetBounds, originPoint, targetPoint); - const adjustedOriginPoint = originEdge - ? canvas.grid.getTopLeftPoint({ - x: originEdge.x + Math.sign(originPoint.x - originEdge.x), - y: originEdge.y + Math.sign(originPoint.y - originEdge.y) - }) - : originPoint; - const adjustDestinationPoint = targetEdge - ? canvas.grid.getTopLeftPoint({ - x: targetEdge.x + Math.sign(targetPoint.x - targetEdge.x), - y: targetEdge.y + Math.sign(targetPoint.y - targetEdge.y) - }) - : targetPoint; - const distance = canvas.grid.measurePath([ - { ...adjustedOriginPoint, elevation: 0 }, - { ...adjustDestinationPoint, elevation } - ]).distance; - return Math.min(distance, distance > adjacencyBuffer ? Infinity : canvas.grid.distance); + const originEdge = this.#getEdgeBoundary(this.bounds, originPoint, destinationPoint); + const targetEdge = this.#getEdgeBoundary(target.bounds, originPoint, destinationPoint); + const adjustedOriginPoint = canvas.grid.getTopLeftPoint({ + x: originEdge.x + Math.sign(originPoint.x - originEdge.x), + y: originEdge.y + Math.sign(originPoint.y - originEdge.y) + }); + const adjustDestinationPoint = canvas.grid.getTopLeftPoint({ + x: targetEdge.x + Math.sign(destinationPoint.x - targetEdge.x), + y: targetEdge.y + Math.sign(destinationPoint.y - targetEdge.y) + }); + return canvas.grid.measurePath([adjustedOriginPoint, adjustDestinationPoint]).distance; } _onHoverIn(event, options) { @@ -131,7 +103,8 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token { // Determine the actual range const ranges = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.variantRules).rangeMeasurement; - const distanceResult = DhMeasuredTemplate.getRangeLabels(originToken.distanceTo(this), ranges); + const distanceNum = originToken.distanceTo(this); + const distanceResult = DhMeasuredTemplate.getRangeLabels(distanceNum, ranges); const distanceLabel = `${distanceResult.distance} ${distanceResult.units}`.trim(); // Create the element @@ -183,6 +156,11 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token { return null; } + /** Tests if the token is at least adjacent with another, with some leeway for diagonals */ + isAdjacentWith(token) { + return this.distanceTo(token) <= canvas.grid.distance * 1.5; + } + /** @inheritDoc */ _drawBar(number, bar, data) { const val = Number(data.value); diff --git a/module/data/actor/adversary.mjs b/module/data/actor/adversary.mjs index 0a446c15..78964720 100644 --- a/module/data/actor/adversary.mjs +++ b/module/data/actor/adversary.mjs @@ -190,10 +190,6 @@ export default class DhpAdversary extends DhCreature { } } - prepareDerivedData() { - this.attack.roll.isStandardAttack = true; - } - _getTags() { const tags = [ game.i18n.localize(`DAGGERHEART.GENERAL.Tiers.${this.tier}`), diff --git a/module/data/fields/action/damageField.mjs b/module/data/fields/action/damageField.mjs index 6439344b..efad726c 100644 --- a/module/data/fields/action/damageField.mjs +++ b/module/data/fields/action/damageField.mjs @@ -165,8 +165,7 @@ export default class DamageField extends fields.SchemaField { if (data.hasRoll && part.resultBased && data.roll.result.duality === -1) return part.valueAlt; const isAdversary = this.actor.type === 'adversary'; - const isHorde = this.actor.system.type === CONFIG.DH.ACTOR.adversaryTypes.horde.id; - if (isAdversary && isHorde && this.roll?.isStandardAttack) { + if (isAdversary && this.actor.system.type === CONFIG.DH.ACTOR.adversaryTypes.horde.id) { const hasHordeDamage = this.actor.effects.find(x => x.type === 'horde'); if (hasHordeDamage && !hasHordeDamage.disabled) return part.valueAlt; } diff --git a/templates/sheets/global/partials/inventory-fieldset-items-V2.hbs b/templates/sheets/global/partials/inventory-fieldset-items-V2.hbs index 0a3275d0..d2534a5a 100644 --- a/templates/sheets/global/partials/inventory-fieldset-items-V2.hbs +++ b/templates/sheets/global/partials/inventory-fieldset-items-V2.hbs @@ -56,7 +56,6 @@ Parameters: {{> 'daggerheart.inventory-item' item=item type=../type - disabledEffect=../disabledEffect actorType=../actorType hideControls=../hideControls hideContextMenu=../hideContextMenu diff --git a/templates/sheets/global/partials/inventory-item-V2.hbs b/templates/sheets/global/partials/inventory-item-V2.hbs index fec215a0..76e13a5c 100644 --- a/templates/sheets/global/partials/inventory-item-V2.hbs +++ b/templates/sheets/global/partials/inventory-item-V2.hbs @@ -17,12 +17,8 @@ Parameters: - showActions {boolean} : If true show feature's actions. --}} -