Various fixes

This commit is contained in:
WBHarry 2025-07-27 13:06:26 +02:00
parent 5cd9075732
commit e55809f988
16 changed files with 152 additions and 74 deletions

View file

@ -196,9 +196,9 @@ Hooks.on('chatMessage', (_, message) => {
const traitValue = rollCommand.trait?.toLowerCase();
const advantage = rollCommand.advantage
? CONFIG.DH.ACTIONS.advandtageState.advantage.value
? CONFIG.DH.ACTIONS.advantageState.advantage.value
: rollCommand.disadvantage
? CONFIG.DH.ACTIONS.advandtageState.disadvantage.value
? CONFIG.DH.ACTIONS.advantageState.disadvantage.value
: undefined;
const difficulty = rollCommand.difficulty;

View file

@ -28,26 +28,6 @@
},
"DAGGERHEART": {
"ACTIONS": {
"Config": {
"beastform": {
"exact": "Beastform Max Tier",
"exactHint": "The Character's Tier is used if empty",
"label": "Beastform"
},
"displayInChat": "Display in chat"
},
"Settings": {
"attackBonus": "Attack Bonus",
"attackName": "Attack Name",
"includeBase": { "label": "Include Item Damage" },
"multiplier": "Multiplier",
"resultBased": {
"label": "Formula based on Hope/Fear result."
},
"applyTo": {
"label": "Targeted Resource"
}
},
"TYPES": {
"attack": {
"name": "Attack",
@ -77,6 +57,35 @@
"name": "Summon",
"tooltip": "Create tokens in the scene."
}
},
"Config": {
"beastform": {
"exact": "Beastform Max Tier",
"exactHint": "The Character's Tier is used if empty",
"label": "Beastform"
},
"displayInChat": "Display in chat"
},
"RollField": {
"diceRolling": {
"compare": "Should be",
"dice": "Dice Type",
"flatMultiplier": "Flat Multiplier",
"multiplier": "Dice Number",
"threshold": "Threshold"
}
},
"Settings": {
"attackBonus": "Attack Bonus",
"attackName": "Attack Name",
"includeBase": { "label": "Include Item Damage" },
"multiplier": "Multiplier",
"resultBased": {
"label": "Formula based on Hope/Fear result."
},
"applyTo": {
"label": "Targeted Resource"
}
}
},
"ACTORS": {
@ -1107,10 +1116,30 @@
},
"DamageResistance": {
"none": "None",
"resistance": "Resistance",
"immunity": "Immunity",
"physicalReduction": "Physical Damage Reduction",
"magicalReduction": "Magical Damage Reduction"
"physicalResistance": {
"label": "Damage Resistance: Physical",
"hint": "Physical Damage is halved if this is set to 1"
},
"magicalResistance": {
"label": "Damage Resistance: Magical",
"hint": "Magical Damage is halved if this is set to 1"
},
"physicalImmunity": {
"label": "Damage Immunity: Physical",
"hint": "Immune to Physical Damage if this is set to 1"
},
"magicalImmunity": {
"label": "Damage Immunity: Magical",
"hint": "Immune to Magical Damage if this is set to 1"
},
"physicalReduction": {
"label": "Damage Reduction: Physical",
"hint": "Physical Damage is reduced by the amount set here"
},
"magicalReduction": {
"label": "Damage Reduction: Magical",
"hint": "Magical Damage is reduced by the amount set here"
}
},
"DamageThresholds": {
"title": "Damage Thresholds",

View file

@ -249,12 +249,20 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
const target = event.target.closest('fieldset.drop-section');
const item = await fromUuid(data.uuid);
if (item?.type === 'feature') {
await this.document.update({
'system.features': [...this.document.system.features, { type: target.dataset.type, item }].map(x => ({
...x,
item: x.item?.uuid
}))
});
if (target.dataset.type) {
await this.document.update({
'system.features': [...this.document.system.features, { type: target.dataset.type, item }].map(
x => ({
...x,
item: x.item?.uuid
})
)
});
} else {
await this.document.update({
'system.features': [...this.document.system.features, item].map(x => x.uuid)
});
}
}
}
}

View file

@ -66,8 +66,8 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
super.close(options);
}
async getActor(id) {
return await fromUuid(id);
async getActor(uuid) {
return await foundry.utils.fromUuid(uuid);
}
getAction(actor, itemId, actionId) {

View file

@ -108,7 +108,7 @@ export const diceCompare = {
}
};
export const advandtageState = {
export const advantageState = {
disadvantage: {
label: 'DAGGERHEART.GENERAL.Disadvantage.full',
value: -1

View file

@ -164,7 +164,8 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
title: this.item.name,
source: {
item: this.item._id,
action: this._id
action: this._id,
actor: this.actor.uuid
},
dialog: {},
type: this.type,
@ -191,7 +192,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
difficulty: this.roll?.difficulty,
formula: this.roll.getFormula(),
bonus: this.roll.bonus,
advantage: CONFIG.DH.ACTIONS.advandtageState[this.roll.advState].value
advantage: CONFIG.DH.ACTIONS.advantageState[this.roll.advState].value
};
if (this.roll?.type === 'diceSet') roll.lite = true;
@ -256,6 +257,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
/* EFFECTS */
async applyEffects(event, data, targets) {
targets ??= data.system.targets;
const force = true; /* Where should this come from? */
if (!this.effects?.length || !targets.length) return;
let effects = this.effects;
targets.forEach(async token => {

View file

@ -1,10 +1,23 @@
import DHBaseActorSettings from '../../applications/sheets/api/actor-setting.mjs';
const resistanceField = reductionLabel =>
const resistanceField = (resistanceLabel, immunityLabel, reductionLabel) =>
new foundry.data.fields.SchemaField({
resistance: new foundry.data.fields.BooleanField({ initial: false }),
immunity: new foundry.data.fields.BooleanField({ initial: false }),
reduction: new foundry.data.fields.NumberField({ integer: true, initial: 0, label: reductionLabel })
resistance: new foundry.data.fields.BooleanField({
initial: false,
label: `${resistanceLabel}.label`,
hint: `${resistanceLabel}.hint`
}),
immunity: new foundry.data.fields.BooleanField({
initial: false,
label: `${immunityLabel}.label`,
hint: `${immunityLabel}.hint`
}),
reduction: new foundry.data.fields.NumberField({
integer: true,
initial: 0,
label: `${reductionLabel}.label`,
hint: `${reductionLabel}.hint`
})
});
/**
@ -40,8 +53,16 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel {
if (this.metadata.isNPC) schema.description = new fields.HTMLField({ required: true, nullable: true });
if (this.metadata.hasResistances)
schema.resistance = new fields.SchemaField({
physical: resistanceField('DAGGERHEART.GENERAL.DamageResistance.physicalReduction'),
magical: resistanceField('DAGGERHEART.GENERAL.DamageResistance.magicalReduction')
physical: resistanceField(
'DAGGERHEART.GENERAL.DamageResistance.physicalResistance',
'DAGGERHEART.GENERAL.DamageResistance.physicalImmunity',
'DAGGERHEART.GENERAL.DamageResistance.physicalReduction'
),
magical: resistanceField(
'DAGGERHEART.GENERAL.DamageResistance.magicalResistance',
'DAGGERHEART.GENERAL.DamageResistance.magicalImmunity',
'DAGGERHEART.GENERAL.DamageResistance.magicalReduction'
)
});
return schema;
}

View file

@ -45,12 +45,12 @@ export default class DhCharacter extends BaseDataActor {
severe: new fields.NumberField({
integer: true,
initial: 0,
label: 'DAGGERHEART.GENERAL.DamageThresholds.majorThreshold'
label: 'DAGGERHEART.GENERAL.DamageThresholds.severeThreshold'
}),
major: new fields.NumberField({
integer: true,
initial: 0,
label: 'DAGGERHEART.GENERAL.DamageThresholds.severeThreshold'
label: 'DAGGERHEART.GENERAL.DamageThresholds.majorThreshold'
})
}),
experiences: new fields.TypedObjectField(

View file

@ -8,25 +8,38 @@ export class DHActionRollData extends foundry.abstract.DataModel {
trait: new fields.StringField({ nullable: true, initial: null, choices: CONFIG.DH.ACTOR.abilities }),
difficulty: new fields.NumberField({ nullable: true, initial: null, integer: true, min: 0 }),
bonus: new fields.NumberField({ nullable: true, initial: null, integer: true }),
advState: new fields.StringField({ choices: CONFIG.DH.ACTIONS.advandtageState, initial: 'neutral' }),
advState: new fields.StringField({
choices: CONFIG.DH.ACTIONS.advantageState,
initial: CONFIG.DH.ACTIONS.advantageState.neutral.label
}),
diceRolling: new fields.SchemaField({
multiplier: new fields.StringField({
choices: CONFIG.DH.GENERAL.diceSetNumbers,
initial: 'prof',
label: 'Dice Number'
initial: CONFIG.DH.GENERAL.diceSetNumbers.prof,
label: 'DAGGERHEART.ACTIONS.RollField.diceRolling.multiplier'
}),
flatMultiplier: new fields.NumberField({
nullable: true,
initial: 1,
label: 'DAGGERHEART.ACTIONS.RollField.diceRolling.flatMultiplier'
}),
flatMultiplier: new fields.NumberField({ nullable: true, initial: 1, label: 'Flat Multiplier' }),
dice: new fields.StringField({
choices: CONFIG.DH.GENERAL.diceTypes,
initial: 'd6',
label: 'Dice Type'
initial: CONFIG.DH.GENERAL.diceTypes.d6,
label: 'DAGGERHEART.ACTIONS.RollField.diceRolling.dice'
}),
compare: new fields.StringField({
choices: CONFIG.DH.ACTIONS.diceCompare,
initial: 'above',
label: 'Should be'
nullable: true,
initial: null,
label: 'DAGGERHEART.ACTIONS.RollField.diceRolling.compare'
}),
treshold: new fields.NumberField({ initial: 1, integer: true, min: 1, label: 'Treshold' })
treshold: new fields.NumberField({
integer: true,
nullable: true,
initial: null,
label: 'DAGGERHEART.ACTIONS.RollField.diceRolling.threshold'
})
}),
useDefault: new fields.BooleanField({ initial: false })
};
@ -41,7 +54,11 @@ export class DHActionRollData extends foundry.abstract.DataModel {
this.diceRolling.multiplier === 'flat'
? this.diceRolling.flatMultiplier
: `@${this.diceRolling.multiplier}`;
formula = `${multiplier}${this.diceRolling.dice}cs${CONFIG.DH.ACTIONS.diceCompare[this.diceRolling.compare].operator}${this.diceRolling.treshold}`;
if (this.diceRolling.compare && this.diceRolling.threshold) {
formula = `${multiplier}${this.diceRolling.dice}cs${CONFIG.DH.ACTIONS.diceCompare[this.diceRolling.compare].operator}${this.diceRolling.treshold}`;
} else {
formula = `${multiplier}${this.diceRolling.dice}`;
}
break;
default:
formula = '';

View file

@ -1,5 +1,4 @@
import AttachableItem from './attachableItem.mjs';
import { ActionsField } from '../fields/actionField.mjs';
import { armorFeatures } from '../../config/itemConfig.mjs';
export default class DHArmor extends AttachableItem {

View file

@ -152,12 +152,14 @@ export default class DHBeastform extends BaseDataItem {
_onCreate(_data, _options, userId) {
if (userId !== game.user.id) return;
this.parent.createEmbeddedDocuments('ActiveEffect', [
{
type: 'beastform',
name: game.i18n.localize('DAGGERHEART.ITEMS.Beastform.beastformEffect'),
img: 'icons/creatures/abilities/paw-print-pair-purple.webp'
}
]);
if (!this.parent.effects.find(x => x.type === 'beastform')) {
this.parent.createEmbeddedDocuments('ActiveEffect', [
{
type: 'beastform',
name: game.i18n.localize('DAGGERHEART.ITEMS.Beastform.beastformEffect'),
img: 'icons/creatures/abilities/paw-print-pair-purple.webp'
}
]);
}
}
}

View file

@ -22,14 +22,14 @@ function getDualityMessage(roll) {
: game.i18n.localize('DAGGERHEART.GENERAL.duality');
const advantage = roll.advantage
? CONFIG.DH.ACTIONS.advandtageState.advantage.value
? CONFIG.DH.ACTIONS.advantageState.advantage.value
: roll.disadvantage
? CONFIG.DH.ACTIONS.advandtageState.disadvantage.value
? CONFIG.DH.ACTIONS.advantageState.disadvantage.value
: undefined;
const advantageLabel =
advantage === CONFIG.DH.ACTIONS.advandtageState.advantage.value
advantage === CONFIG.DH.ACTIONS.advantageState.advantage.value
? 'Advantage'
: advantage === CONFIG.DH.ACTIONS.advandtageState.disadvantage.value
: advantage === CONFIG.DH.ACTIONS.advantageState.disadvantage.value
? 'Disadvantage'
: undefined;

View file

@ -271,14 +271,14 @@ export function addLinkedItemsDiff(changedItems, currentItems, options) {
newItems
.difference(prevItems)
.map(item => item?.item ?? item)
.filter(x => (typeof x === 'object' ? x.item : x))
.filter(x => (typeof x === 'object' ? x?.item : x))
);
options.toUnlink = Array.from(
prevItems
.difference(newItems)
.map(item => item?.item?.uuid ?? item?.uuid ?? item)
.filter(x => (typeof x === 'object' ? x.item : x))
.filter(x => (typeof x === 'object' ? x?.item : x))
);
}
}

View file

@ -11,9 +11,9 @@
{{#if (eq source.type "diceSet")}}
<div class="nest-inputs">
{{formField fields.diceRolling.fields.multiplier name="roll.diceRolling.multiplier" value=source.diceRolling.multiplier localize=true}}
{{#if (eq source.diceRolling.multiplier 'flat')}}{{formField fields.diceRolling.fields.flatMultiplier value=source.diceRolling.flatMultiplier name="roll.diceRolling.flatMultiplier" }}{{/if}}
{{formField fields.diceRolling.fields.dice name="roll.diceRolling.dice" value=source.diceRolling.dice}}
{{formField fields.diceRolling.fields.compare name="roll.diceRolling.compare" value=source.diceRolling.compare localize=true}}
{{#if (eq source.diceRolling.multiplier 'flat')}}{{formField fields.diceRolling.fields.flatMultiplier value=source.diceRolling.flatMultiplier name="roll.diceRolling.flatMultiplier" localize=true }}{{/if}}
{{formField fields.diceRolling.fields.dice name="roll.diceRolling.dice" value=source.diceRolling.dice localize=true}}
{{formField fields.diceRolling.fields.compare name="roll.diceRolling.compare" value=source.diceRolling.compare localize=true blank=""}}
{{formField fields.diceRolling.fields.treshold name="roll.diceRolling.treshold" value=source.diceRolling.treshold localize=true}}
</div>
{{else}}

View file

@ -22,7 +22,7 @@ Parameters:
- showActions {boolean} : If true show feature's actions.
--}}
<fieldset class="{{#if isGlassy}}glassy{{/if}}">
<fieldset class="{{#if isGlassy}}glassy{{/if}} drop-section">
<legend>
{{localize title}}
{{#if canCreate}}

View file

@ -189,7 +189,7 @@
{{/if}}
{{/if}}
{{#if hasEffect}}
<button class="duality-action{{#if (or hasDamage hasHealing)}} duality-action-effect{{/if}}" data-value="{{roll.total}}"><span>{{localize "DAGGERHEART.UI.Chat.attackRoll.applyEffect"}}</span></button>
<button class="duality-action-effect" data-value="{{roll.total}}"><span>{{localize "DAGGERHEART.UI.Chat.attackRoll.applyEffect"}}</span></button>
{{/if}}
<div class="duality-result">
<div>{{roll.total}}