mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-03-07 06:26:13 +01:00
Compare commits
3 commits
340abbc98c
...
e79ccd34e9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e79ccd34e9 | ||
|
|
4324c3abf2 | ||
|
|
1b09b44d6c |
8 changed files with 81 additions and 51 deletions
|
|
@ -420,10 +420,7 @@ const updateActorsRangeDependentEffects = async token => {
|
||||||
// Get required distance and special case 5 feet to test adjacency
|
// Get required distance and special case 5 feet to test adjacency
|
||||||
const required = rangeMeasurement[range];
|
const required = rangeMeasurement[range];
|
||||||
const reverse = type === CONFIG.DH.GENERAL.rangeInclusion.outsideRange.id;
|
const reverse = type === CONFIG.DH.GENERAL.rangeInclusion.outsideRange.id;
|
||||||
const inRange =
|
const inRange = userTarget.distanceTo(token.object) <= required;
|
||||||
required === 5
|
|
||||||
? userTarget.isAdjacentWith(token.object)
|
|
||||||
: userTarget.distanceTo(token.object) <= required;
|
|
||||||
if (reverse ? inRange : !inRange) {
|
if (reverse ? inRange : !inRange) {
|
||||||
enabledEffect = false;
|
enabledEffect = false;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -431,18 +431,18 @@ export default function DHApplicationMixin(Base) {
|
||||||
{
|
{
|
||||||
name: 'disableEffect',
|
name: 'disableEffect',
|
||||||
icon: 'fa-solid fa-lightbulb',
|
icon: 'fa-solid fa-lightbulb',
|
||||||
condition: target => {
|
condition: element => {
|
||||||
const doc = getDocFromElementSync(target);
|
const target = element.closest('[data-item-uuid]');
|
||||||
return doc && !doc.disabled && doc.type !== 'beastform';
|
return !target.dataset.disabled && target.dataset.itemType !== 'beastform';
|
||||||
},
|
},
|
||||||
callback: async target => (await getDocFromElement(target)).update({ disabled: true })
|
callback: async target => (await getDocFromElement(target)).update({ disabled: true })
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'enableEffect',
|
name: 'enableEffect',
|
||||||
icon: 'fa-regular fa-lightbulb',
|
icon: 'fa-regular fa-lightbulb',
|
||||||
condition: target => {
|
condition: element => {
|
||||||
const doc = getDocFromElementSync(target);
|
const target = element.closest('[data-item-uuid]');
|
||||||
return doc && doc.disabled && doc.type !== 'beastform';
|
return target.dataset.disabled && target.dataset.itemType !== 'beastform';
|
||||||
},
|
},
|
||||||
callback: async target => (await getDocFromElement(target)).update({ disabled: false })
|
callback: async target => (await getDocFromElement(target)).update({ disabled: false })
|
||||||
}
|
}
|
||||||
|
|
@ -536,9 +536,9 @@ export default function DHApplicationMixin(Base) {
|
||||||
options.push({
|
options.push({
|
||||||
name: 'CONTROLS.CommonDelete',
|
name: 'CONTROLS.CommonDelete',
|
||||||
icon: 'fa-solid fa-trash',
|
icon: 'fa-solid fa-trash',
|
||||||
condition: target => {
|
condition: element => {
|
||||||
const doc = getDocFromElementSync(target);
|
const target = element.closest('[data-item-uuid]');
|
||||||
return doc && doc.type !== 'beastform';
|
return target.dataset.itemType !== 'beastform';
|
||||||
},
|
},
|
||||||
callback: async (target, event) => {
|
callback: async (target, event) => {
|
||||||
const doc = await getDocFromElement(target);
|
const doc = await getDocFromElement(target);
|
||||||
|
|
|
||||||
|
|
@ -54,30 +54,58 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
if (this === target) return 0;
|
if (this === target) return 0;
|
||||||
|
|
||||||
const originPoint = this.center;
|
const originPoint = this.center;
|
||||||
const destinationPoint = target.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;
|
||||||
|
|
||||||
// Compute for gridless. This version returns circular edge to edge + grid distance,
|
// Compute for gridless. This version returns circular edge to edge + grid distance,
|
||||||
// so that tokens that are touching return 5.
|
// so that tokens that are touching return 5.
|
||||||
if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) {
|
if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) {
|
||||||
const boundsCorrection = canvas.grid.distance / canvas.grid.size;
|
const boundsCorrection = canvas.grid.distance / canvas.grid.size;
|
||||||
const originRadius = (this.bounds.width * boundsCorrection) / 2;
|
const originRadius = (thisBounds.width * boundsCorrection) / 2;
|
||||||
const targetRadius = (target.bounds.width * boundsCorrection) / 2;
|
const targetRadius = (targetBounds.width * boundsCorrection) / 2;
|
||||||
const distance = canvas.grid.measurePath([originPoint, destinationPoint]).distance;
|
const measuredDistance = canvas.grid.measurePath([
|
||||||
return Math.floor(distance - originRadius - targetRadius + canvas.grid.distance);
|
{ ...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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute what the closest grid space of each token is, then compute that distance
|
// Compute what the closest grid space of each token is, then compute that distance
|
||||||
const originEdge = this.#getEdgeBoundary(this.bounds, originPoint, destinationPoint);
|
const originEdge = this.#getEdgeBoundary(thisBounds, originPoint, targetPoint);
|
||||||
const targetEdge = this.#getEdgeBoundary(target.bounds, originPoint, destinationPoint);
|
const targetEdge = this.#getEdgeBoundary(targetBounds, originPoint, targetPoint);
|
||||||
const adjustedOriginPoint = canvas.grid.getTopLeftPoint({
|
const adjustedOriginPoint = originEdge
|
||||||
x: originEdge.x + Math.sign(originPoint.x - originEdge.x),
|
? canvas.grid.getTopLeftPoint({
|
||||||
y: originEdge.y + Math.sign(originPoint.y - originEdge.y)
|
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),
|
: originPoint;
|
||||||
y: targetEdge.y + Math.sign(destinationPoint.y - targetEdge.y)
|
const adjustDestinationPoint = targetEdge
|
||||||
});
|
? canvas.grid.getTopLeftPoint({
|
||||||
return canvas.grid.measurePath([adjustedOriginPoint, adjustDestinationPoint]).distance;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onHoverIn(event, options) {
|
_onHoverIn(event, options) {
|
||||||
|
|
@ -103,8 +131,7 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
|
|
||||||
// Determine the actual range
|
// Determine the actual range
|
||||||
const ranges = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.variantRules).rangeMeasurement;
|
const ranges = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.variantRules).rangeMeasurement;
|
||||||
const distanceNum = originToken.distanceTo(this);
|
const distanceResult = DhMeasuredTemplate.getRangeLabels(originToken.distanceTo(this), ranges);
|
||||||
const distanceResult = DhMeasuredTemplate.getRangeLabels(distanceNum, ranges);
|
|
||||||
const distanceLabel = `${distanceResult.distance} ${distanceResult.units}`.trim();
|
const distanceLabel = `${distanceResult.distance} ${distanceResult.units}`.trim();
|
||||||
|
|
||||||
// Create the element
|
// Create the element
|
||||||
|
|
@ -156,11 +183,6 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
return null;
|
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 */
|
/** @inheritDoc */
|
||||||
_drawBar(number, bar, data) {
|
_drawBar(number, bar, data) {
|
||||||
const val = Number(data.value);
|
const val = Number(data.value);
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,10 @@ export default class DhpAdversary extends DhCreature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prepareDerivedData() {
|
||||||
|
this.attack.roll.isStandardAttack = true;
|
||||||
|
}
|
||||||
|
|
||||||
_getTags() {
|
_getTags() {
|
||||||
const tags = [
|
const tags = [
|
||||||
game.i18n.localize(`DAGGERHEART.GENERAL.Tiers.${this.tier}`),
|
game.i18n.localize(`DAGGERHEART.GENERAL.Tiers.${this.tier}`),
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,8 @@ export default class DamageField extends fields.SchemaField {
|
||||||
if (data.hasRoll && part.resultBased && data.roll.result.duality === -1) return part.valueAlt;
|
if (data.hasRoll && part.resultBased && data.roll.result.duality === -1) return part.valueAlt;
|
||||||
|
|
||||||
const isAdversary = this.actor.type === 'adversary';
|
const isAdversary = this.actor.type === 'adversary';
|
||||||
if (isAdversary && this.actor.system.type === CONFIG.DH.ACTOR.adversaryTypes.horde.id) {
|
const isHorde = this.actor.system.type === CONFIG.DH.ACTOR.adversaryTypes.horde.id;
|
||||||
|
if (isAdversary && isHorde && this.roll?.isStandardAttack) {
|
||||||
const hasHordeDamage = this.actor.effects.find(x => x.type === 'horde');
|
const hasHordeDamage = this.actor.effects.find(x => x.type === 'horde');
|
||||||
if (hasHordeDamage && !hasHordeDamage.disabled) return part.valueAlt;
|
if (hasHordeDamage && !hasHordeDamage.disabled) return part.valueAlt;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ Parameters:
|
||||||
{{> 'daggerheart.inventory-item'
|
{{> 'daggerheart.inventory-item'
|
||||||
item=item
|
item=item
|
||||||
type=../type
|
type=../type
|
||||||
|
disabledEffect=../disabledEffect
|
||||||
actorType=../actorType
|
actorType=../actorType
|
||||||
hideControls=../hideControls
|
hideControls=../hideControls
|
||||||
hideContextMenu=../hideContextMenu
|
hideContextMenu=../hideContextMenu
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,12 @@ Parameters:
|
||||||
- showActions {boolean} : If true show feature's actions.
|
- showActions {boolean} : If true show feature's actions.
|
||||||
--}}
|
--}}
|
||||||
|
|
||||||
<li class="inventory-item" data-item-id="{{item.id}}" {{#if (or (eq type 'action' ) (eq type 'attack' ))}}
|
<li class="inventory-item" data-item-id="{{item.id}}"
|
||||||
data-action-id="{{item.id}}" {{/if}} data-item-uuid="{{item.uuid}}" data-type="{{type}}" data-no-compendium-edit="{{noCompendiumEdit}}">
|
{{#if (or (eq type 'action' ) (eq type 'attack' ))}}data-action-id="{{item.id}}" {{/if}}
|
||||||
|
{{#if disabledEffect}}data-disabled="true"{{/if}}
|
||||||
|
data-type="{{type}}" data-item-type="{{item.type}}"
|
||||||
|
data-item-uuid="{{item.uuid}}" data-no-compendium-edit="{{noCompendiumEdit}}"
|
||||||
|
>
|
||||||
<div class="inventory-item-header {{#if hideContextMenu}}padded{{/if}}" {{#unless noExtensible}}data-action="toggleExtended" {{/unless}}>
|
<div class="inventory-item-header {{#if hideContextMenu}}padded{{/if}}" {{#unless noExtensible}}data-action="toggleExtended" {{/unless}}>
|
||||||
{{!-- Image --}}
|
{{!-- Image --}}
|
||||||
<div class="img-portait" data-action='{{ifThen (or (hasProperty item "use") (eq type "attack")) "useItem" (ifThen
|
<div class="img-portait" data-action='{{ifThen (or (hasProperty item "use") (eq type "attack")) "useItem" (ifThen
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,21 @@
|
||||||
data-group='{{tabs.effects.group}}'>
|
data-group='{{tabs.effects.group}}'>
|
||||||
|
|
||||||
{{> 'daggerheart.inventory-items'
|
{{> 'daggerheart.inventory-items'
|
||||||
title='DAGGERHEART.GENERAL.activeEffects'
|
title='DAGGERHEART.GENERAL.activeEffects'
|
||||||
type='effect'
|
type='effect'
|
||||||
isGlassy=true
|
isGlassy=true
|
||||||
collection=effects.actives
|
collection=effects.actives
|
||||||
canCreate=true
|
canCreate=true
|
||||||
hideResources=true
|
hideResources=true
|
||||||
}}
|
}}
|
||||||
|
|
||||||
{{> 'daggerheart.inventory-items'
|
{{> 'daggerheart.inventory-items'
|
||||||
title='DAGGERHEART.GENERAL.inactiveEffects'
|
title='DAGGERHEART.GENERAL.inactiveEffects'
|
||||||
type='effect'
|
type='effect'
|
||||||
isGlassy=true
|
disabledEffect=true
|
||||||
collection=effects.inactives
|
isGlassy=true
|
||||||
canCreate=true
|
collection=effects.inactives
|
||||||
hideResources=true
|
canCreate=true
|
||||||
|
hideResources=true
|
||||||
}}
|
}}
|
||||||
</section>
|
</section>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue