mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-03-07 14:36:13 +01:00
Compare commits
10 commits
cad3f533ad
...
c7431d16a7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7431d16a7 | ||
|
|
5413730108 | ||
|
|
d96e72505a | ||
|
|
f9f252c7a6 | ||
|
|
78012be6e4 | ||
|
|
4ad8b960b5 | ||
|
|
f7e4c5346e | ||
|
|
44131d21a6 | ||
|
|
202e624a06 | ||
|
|
5e7201bfe9 |
19 changed files with 328 additions and 45 deletions
59
lang/en.json
59
lang/en.json
|
|
@ -192,6 +192,9 @@
|
|||
},
|
||||
"age": "Age",
|
||||
"backgroundQuestions": "Backgrounds",
|
||||
"burden": {
|
||||
"ignore": { "label": "Burden: Ignore", "hint": "Ignore burden rules" }
|
||||
},
|
||||
"companionFeatures": "Companion Features",
|
||||
"connections": "Connections",
|
||||
"contextMenu": {
|
||||
|
|
@ -214,6 +217,12 @@
|
|||
"maxEvasionBonus": "Max Evasion Increase",
|
||||
"maxHPBonus": "Max HP Increase",
|
||||
"pronouns": "Pronouns",
|
||||
"roll": {
|
||||
"guaranteedCritical": {
|
||||
"label": "Guaranteed Critical",
|
||||
"hint": "Set to 1 to always roll a critical"
|
||||
}
|
||||
},
|
||||
"story": {
|
||||
"backgroundTitle": "Background",
|
||||
"characteristics": "Characteristics",
|
||||
|
|
@ -446,6 +455,10 @@
|
|||
"description": "Describe how you are preparing for the next day's adventure, then gain a Hope. If you choose to Prepare with one or more members of your party, you may each take two Hope.",
|
||||
"name": "Prepare"
|
||||
},
|
||||
"prepareWithFriends": {
|
||||
"description": "Describe how you are preparing for the next day's adventure, then gain a Hope. If you choose to Prepare with one or more members of your party, you may each take two Hope.",
|
||||
"name": "Prepare (with Friends)"
|
||||
},
|
||||
"repairArmor": {
|
||||
"description": "Describe how you spend time repairing your armor and clear all of its Armor Slots. You may also do this to an ally's armor instead.",
|
||||
"name": "Repair Armor"
|
||||
|
|
@ -477,6 +490,10 @@
|
|||
"prepare": {
|
||||
"name": "Prepare",
|
||||
"description": "Describe how you prepare yourself for the path ahead, then gain a Hope. If you choose to Prepare with one or more members of your party, you each gain 2 Hope."
|
||||
},
|
||||
"prepareWithFriends": {
|
||||
"name": "Prepare (with Friends)",
|
||||
"description": "Describe how you prepare yourself for the path ahead, then gain a Hope. If you choose to Prepare with one or more members of your party, you each gain 2 Hope."
|
||||
}
|
||||
},
|
||||
"refreshable": {
|
||||
|
|
@ -1840,6 +1857,16 @@
|
|||
"singular": "Adversary",
|
||||
"plural": "Adversaries"
|
||||
},
|
||||
"Attack": {
|
||||
"hpDamageMultiplier": {
|
||||
"label": "HP Damage Multiplier",
|
||||
"hint": "Multiply any damage you deal by this number"
|
||||
},
|
||||
"hpDamageTakenMultiplier": {
|
||||
"label": "HP Damage Taken Multiplier",
|
||||
"hint": "Multiply any damage dealt to you by this number"
|
||||
}
|
||||
},
|
||||
"Bonuses": {
|
||||
"rest": {
|
||||
"downtimeAction": "Downtime Action",
|
||||
|
|
@ -2024,16 +2051,40 @@
|
|||
"reaction": "Reaction Roll"
|
||||
},
|
||||
"Rules": {
|
||||
"conditionImmunities": {
|
||||
"hidden": "Condition Immunity: Hidden",
|
||||
"restrained": "Condition Immunity: Restrained",
|
||||
"vulnerable": "Condition Immunity: Vulnerable"
|
||||
},
|
||||
"damageReduction": {
|
||||
"disabledArmor": { "label": "Disabled Armorslots" },
|
||||
"increasePerArmorMark": {
|
||||
"label": "Damage Reduction per Armor Slot",
|
||||
"hint": "A used armor slot normally reduces damage by one step. This value increases the number of steps damage is reduced by."
|
||||
},
|
||||
"magical": {
|
||||
"label": "Daamge Reduction: Only Magical",
|
||||
"hint": "Armor can only be used to reduce magical damage"
|
||||
},
|
||||
"maxArmorMarkedBonus": "Max Armor Used",
|
||||
"maxArmorMarkedStress": {
|
||||
"label": "Max Armor Used With Stress",
|
||||
"hint": "If this value is set you can use up to that much stress to spend additional Armor Marks beyond your normal maximum."
|
||||
},
|
||||
"reduceSeverity": {
|
||||
"magical": {
|
||||
"label": "Reduce Damage Severity: Magical",
|
||||
"hint": "Lowers any magical damage received by the set amount of severity degrees"
|
||||
},
|
||||
"physical": {
|
||||
"label": "Reduce Damage Severity: Physical",
|
||||
"hint": "Lowers any physical damage received by the set amount of severity degrees"
|
||||
}
|
||||
},
|
||||
"physical": {
|
||||
"label": "Damage Reduction: Only Physical",
|
||||
"hint": "Armor can only be used to reduce physical damage"
|
||||
},
|
||||
"stress": {
|
||||
"any": {
|
||||
"label": "Stress Damage Reduction: Any",
|
||||
|
|
@ -2051,6 +2102,12 @@
|
|||
"label": "Stress Damage Reduction: Minor",
|
||||
"hint": "The cost in stress you can pay to reduce minor damage to none."
|
||||
}
|
||||
},
|
||||
"thresholdImmunities": {
|
||||
"minor": {
|
||||
"label": "Threshold Immunities: Minor",
|
||||
"hint": "Automatically ignores minor damage"
|
||||
}
|
||||
}
|
||||
},
|
||||
"attack": {
|
||||
|
|
@ -2556,6 +2613,8 @@
|
|||
"resetMovesTitle": "Reset {type} Downtime Moves",
|
||||
"resetItemFeaturesTitle": "Reset {type}",
|
||||
"resetMovesText": "Are you sure you want to reset?",
|
||||
"deleteItemTitle": "Delete Homebrew Item",
|
||||
"deleteItemText": "Are you sure you want to delete the item?",
|
||||
"FIELDS": {
|
||||
"maxFear": { "label": "Max Fear" },
|
||||
"maxHope": { "label": "Max Hope" },
|
||||
|
|
|
|||
|
|
@ -103,6 +103,12 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
? { id: this.selected.adversaryType, ...this.settings.adversaryTypes[this.selected.adversaryType] }
|
||||
: null;
|
||||
break;
|
||||
case 'downtime':
|
||||
context.restOptions = {
|
||||
shortRest: CONFIG.DH.GENERAL.defaultRestOptions.shortRest(),
|
||||
longRest: CONFIG.DH.GENERAL.defaultRestOptions.longRest()
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
return context;
|
||||
|
|
@ -225,6 +231,15 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
}
|
||||
|
||||
static async removeItem(_, target) {
|
||||
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||
window: {
|
||||
title: game.i18n.localize(`DAGGERHEART.SETTINGS.Homebrew.deleteItemTitle`)
|
||||
},
|
||||
content: game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.deleteItemText')
|
||||
});
|
||||
|
||||
if (!confirmed) return;
|
||||
|
||||
const { type, id } = target.dataset;
|
||||
const isDowntime = ['shortRest', 'longRest'].includes(type);
|
||||
const path = isDowntime ? `restMoves.${type}.moves` : `itemFeatures.${type}`;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,24 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac
|
|||
super(options);
|
||||
|
||||
const ignoredActorKeys = ['config', 'DhEnvironment', 'DhParty'];
|
||||
|
||||
const getAllLeaves = (root, group, parentPath = '') => {
|
||||
const leaves = [];
|
||||
const rootKey = `${parentPath ? `${parentPath}.` : ''}${root.name}`;
|
||||
for (const field of Object.values(root.fields)) {
|
||||
if (field instanceof foundry.data.fields.SchemaField)
|
||||
leaves.push(...getAllLeaves(field, group, rootKey));
|
||||
else
|
||||
leaves.push({
|
||||
value: `${rootKey}.${field.name}`,
|
||||
label: game.i18n.localize(field.label),
|
||||
hint: game.i18n.localize(field.hint),
|
||||
group
|
||||
});
|
||||
}
|
||||
|
||||
return leaves;
|
||||
};
|
||||
this.changeChoices = Object.keys(game.system.api.models.actors).reduce((acc, key) => {
|
||||
if (ignoredActorKeys.includes(key)) return acc;
|
||||
|
||||
|
|
@ -30,7 +48,10 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac
|
|||
return { value: joined, label: getLabel(joined), group };
|
||||
});
|
||||
|
||||
acc.push(...bars, ...values);
|
||||
const bonuses = getAllLeaves(model.schema.fields.bonuses, group);
|
||||
const rules = getAllLeaves(model.schema.fields.rules, group);
|
||||
|
||||
acc.push(...bars, ...values, ...rules, ...bonuses);
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
|
|
|||
|
|
@ -433,7 +433,7 @@ export default function DHApplicationMixin(Base) {
|
|||
icon: 'fa-solid fa-lightbulb',
|
||||
condition: target => {
|
||||
const doc = getDocFromElementSync(target);
|
||||
return doc && !doc.disabled;
|
||||
return doc && !doc.disabled && doc.type !== 'beastform';
|
||||
},
|
||||
callback: async target => (await getDocFromElement(target)).update({ disabled: true })
|
||||
},
|
||||
|
|
@ -442,7 +442,7 @@ export default function DHApplicationMixin(Base) {
|
|||
icon: 'fa-regular fa-lightbulb',
|
||||
condition: target => {
|
||||
const doc = getDocFromElementSync(target);
|
||||
return doc && doc.disabled;
|
||||
return doc && doc.disabled && doc.type !== 'beastform';
|
||||
},
|
||||
callback: async target => (await getDocFromElement(target)).update({ disabled: false })
|
||||
}
|
||||
|
|
@ -536,6 +536,10 @@ export default function DHApplicationMixin(Base) {
|
|||
options.push({
|
||||
name: 'CONTROLS.CommonDelete',
|
||||
icon: 'fa-solid fa-trash',
|
||||
condition: target => {
|
||||
const doc = getDocFromElementSync(target);
|
||||
return doc && doc.type !== 'beastform';
|
||||
},
|
||||
callback: async (target, event) => {
|
||||
const doc = await getDocFromElement(target);
|
||||
if (event.shiftKey) return doc.delete();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
export default function ItemAttachmentSheet(Base) {
|
||||
return class extends Base {
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
dragDrop: [
|
||||
...(super.DEFAULT_OPTIONS.dragDrop || []),
|
||||
{ dragSelector: null, dropSelector: '.attachments-section' }
|
||||
|
|
|
|||
|
|
@ -331,7 +331,56 @@ export const defaultRestOptions = {
|
|||
icon: 'fa-solid fa-dumbbell',
|
||||
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
||||
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.prepare.description'),
|
||||
actions: {},
|
||||
actions: {
|
||||
prepare: {
|
||||
type: 'healing',
|
||||
systemPath: 'restMoves.shortRest.moves.prepare.actions',
|
||||
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.prepare.name'),
|
||||
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
||||
actionType: 'action',
|
||||
chatDisplay: false,
|
||||
target: {
|
||||
type: 'self'
|
||||
},
|
||||
damage: {
|
||||
parts: [
|
||||
{
|
||||
applyTo: healingTypes.hope.id,
|
||||
value: {
|
||||
custom: {
|
||||
enabled: true,
|
||||
formula: '1'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
prepareWithFriends: {
|
||||
type: 'healing',
|
||||
systemPath: 'restMoves.shortRest.moves.prepare.actions',
|
||||
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.prepareWithFriends.name'),
|
||||
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
||||
actionType: 'action',
|
||||
chatDisplay: false,
|
||||
target: {
|
||||
type: 'self'
|
||||
},
|
||||
damage: {
|
||||
parts: [
|
||||
{
|
||||
applyTo: healingTypes.hope.id,
|
||||
value: {
|
||||
custom: {
|
||||
enabled: true,
|
||||
formula: '2'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
effects: []
|
||||
}
|
||||
}),
|
||||
|
|
@ -446,7 +495,56 @@ export const defaultRestOptions = {
|
|||
icon: 'fa-solid fa-dumbbell',
|
||||
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
||||
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.prepare.description'),
|
||||
actions: {},
|
||||
actions: {
|
||||
prepare: {
|
||||
type: 'healing',
|
||||
systemPath: 'restMoves.longRest.moves.prepare.actions',
|
||||
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.prepare.name'),
|
||||
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
||||
actionType: 'action',
|
||||
chatDisplay: false,
|
||||
target: {
|
||||
type: 'self'
|
||||
},
|
||||
damage: {
|
||||
parts: [
|
||||
{
|
||||
applyTo: healingTypes.hope.id,
|
||||
value: {
|
||||
custom: {
|
||||
enabled: true,
|
||||
formula: '1'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
prepareWithFriends: {
|
||||
type: 'healing',
|
||||
systemPath: 'restMoves.longRest.moves.prepare.actions',
|
||||
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.prepareWithFriends.name'),
|
||||
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
||||
actionType: 'action',
|
||||
chatDisplay: false,
|
||||
target: {
|
||||
type: 'self'
|
||||
},
|
||||
damage: {
|
||||
parts: [
|
||||
{
|
||||
applyTo: healingTypes.hope.id,
|
||||
value: {
|
||||
custom: {
|
||||
enabled: true,
|
||||
formula: '2'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
effects: []
|
||||
},
|
||||
workOnAProject: {
|
||||
|
|
|
|||
|
|
@ -29,17 +29,40 @@ const resistanceField = (resistanceLabel, immunityLabel, reductionLabel) =>
|
|||
/* Common rules applying to Characters and Adversaries */
|
||||
export const commonActorRules = (extendedData = { damageReduction: {}, attack: { damage: {} } }) => ({
|
||||
conditionImmunities: new fields.SchemaField({
|
||||
hidden: new fields.BooleanField({ initial: false }),
|
||||
restrained: new fields.BooleanField({ initial: false }),
|
||||
vulnerable: new fields.BooleanField({ initial: false })
|
||||
hidden: new fields.BooleanField({
|
||||
initial: false,
|
||||
label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.hidden'
|
||||
}),
|
||||
restrained: new fields.BooleanField({
|
||||
initial: false,
|
||||
label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.restrained'
|
||||
}),
|
||||
vulnerable: new fields.BooleanField({
|
||||
initial: false,
|
||||
label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.vulnerable'
|
||||
})
|
||||
}),
|
||||
damageReduction: new fields.SchemaField({
|
||||
thresholdImmunities: new fields.SchemaField({
|
||||
minor: new fields.BooleanField({ initial: false })
|
||||
minor: new fields.BooleanField({
|
||||
initial: false,
|
||||
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.thresholdImmunities.minor.label',
|
||||
hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.thresholdImmunities.minor.hint'
|
||||
})
|
||||
}),
|
||||
reduceSeverity: new fields.SchemaField({
|
||||
magical: new fields.NumberField({ initial: 0, min: 0 }),
|
||||
physical: new fields.NumberField({ initial: 0, min: 0 })
|
||||
magical: new fields.NumberField({
|
||||
initial: 0,
|
||||
min: 0,
|
||||
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.reduceSeverity.magical.label',
|
||||
hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.reduceSeverity.magical.hint'
|
||||
}),
|
||||
physical: new fields.NumberField({
|
||||
initial: 0,
|
||||
min: 0,
|
||||
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.reduceSeverity.physical.label',
|
||||
hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.reduceSeverity.physical.hint'
|
||||
})
|
||||
}),
|
||||
...(extendedData.damageReduction ?? {})
|
||||
}),
|
||||
|
|
@ -49,12 +72,16 @@ export const commonActorRules = (extendedData = { damageReduction: {}, attack: {
|
|||
hpDamageMultiplier: new fields.NumberField({
|
||||
required: true,
|
||||
nullable: false,
|
||||
initial: 1
|
||||
initial: 1,
|
||||
label: 'DAGGERHEART.GENERAL.Attack.hpDamageMultiplier.label',
|
||||
hint: 'DAGGERHEART.GENERAL.Attack.hpDamageMultiplier.hint'
|
||||
}),
|
||||
hpDamageTakenMultiplier: new fields.NumberField({
|
||||
required: true,
|
||||
nullable: false,
|
||||
initial: 1
|
||||
initial: 1,
|
||||
label: 'DAGGERHEART.GENERAL.Attack.hpDamageTakenMultiplier.label',
|
||||
hint: 'DAGGERHEART.GENERAL.Attack.hpDamageTakenMultiplier.hint'
|
||||
}),
|
||||
...(extendedData.attack?.damage ?? {})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -225,8 +225,16 @@ export default class DhCharacter extends BaseDataActor {
|
|||
rules: new fields.SchemaField({
|
||||
...commonActorRules({
|
||||
damageReduction: {
|
||||
magical: new fields.BooleanField({ initial: false }),
|
||||
physical: new fields.BooleanField({ initial: false }),
|
||||
magical: new fields.BooleanField({
|
||||
initial: false,
|
||||
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.magical.label',
|
||||
hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.magical.hint'
|
||||
}),
|
||||
physical: new fields.BooleanField({
|
||||
initial: false,
|
||||
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.physical.label',
|
||||
hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.physical.hint'
|
||||
}),
|
||||
maxArmorMarked: new fields.SchemaField({
|
||||
value: new fields.NumberField({
|
||||
required: true,
|
||||
|
|
@ -256,7 +264,10 @@ export default class DhCharacter extends BaseDataActor {
|
|||
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.increasePerArmorMark.label',
|
||||
hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.increasePerArmorMark.hint'
|
||||
}),
|
||||
disabledArmor: new fields.BooleanField({ intial: false })
|
||||
disabledArmor: new fields.BooleanField({
|
||||
intial: false,
|
||||
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.disabledArmor.label'
|
||||
})
|
||||
},
|
||||
attack: {
|
||||
damage: {
|
||||
|
|
@ -304,12 +315,14 @@ export default class DhCharacter extends BaseDataActor {
|
|||
label: 'DAGGERHEART.ACTORS.Character.defaultFearDice'
|
||||
})
|
||||
}),
|
||||
runeWard: new fields.BooleanField({ initial: false }),
|
||||
burden: new fields.SchemaField({
|
||||
ignore: new fields.BooleanField()
|
||||
ignore: new fields.BooleanField({ label: 'DAGGERHEART.ACTORS.Character.burden.ignore.label' })
|
||||
}),
|
||||
roll: new fields.SchemaField({
|
||||
guaranteedCritical: new fields.BooleanField()
|
||||
guaranteedCritical: new fields.BooleanField({
|
||||
label: 'DAGGERHEART.ACTORS.Character.roll.guaranteedCritical.label',
|
||||
hint: 'DAGGERHEART.ACTORS.Character.roll.guaranteedCritical.hint'
|
||||
})
|
||||
})
|
||||
})
|
||||
};
|
||||
|
|
|
|||
|
|
@ -53,9 +53,18 @@ export default class DhCompanion extends BaseDataActor {
|
|||
),
|
||||
rules: new fields.SchemaField({
|
||||
conditionImmunities: new fields.SchemaField({
|
||||
hidden: new fields.BooleanField({ initial: false }),
|
||||
restrained: new fields.BooleanField({ initial: false }),
|
||||
vulnerable: new fields.BooleanField({ initial: false })
|
||||
hidden: new fields.BooleanField({
|
||||
initial: false,
|
||||
label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.hidden'
|
||||
}),
|
||||
restrained: new fields.BooleanField({
|
||||
initial: false,
|
||||
label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.restrained'
|
||||
}),
|
||||
vulnerable: new fields.BooleanField({
|
||||
initial: false,
|
||||
label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.vulnerable'
|
||||
})
|
||||
})
|
||||
}),
|
||||
attack: new ActionField({
|
||||
|
|
|
|||
|
|
@ -109,8 +109,8 @@ export default class DamageField extends fields.SchemaField {
|
|||
);
|
||||
else {
|
||||
const configDamage = foundry.utils.deepClone(config.damage);
|
||||
const hpDamageMultiplier = config.actionActor?.system.rules.attack.damage.hpDamageMultiplier ?? 1;
|
||||
const hpDamageTakenMultiplier = actor.system.rules.attack.damage.hpDamageTakenMultiplier;
|
||||
const hpDamageMultiplier = config.actionActor?.system.rules?.attack?.damage?.hpDamageMultiplier ?? 1;
|
||||
const hpDamageTakenMultiplier = actor.system.rules?.attack?.damage?.hpDamageTakenMultiplier;
|
||||
if (configDamage.hitPoints) {
|
||||
for (const part of configDamage.hitPoints.parts) {
|
||||
part.total = Math.ceil(part.total * hpDamageMultiplier * hpDamageTakenMultiplier);
|
||||
|
|
|
|||
|
|
@ -253,4 +253,20 @@ export default class DHBeastform extends BaseDataItem {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
_onCreate(_data, _options, userId) {
|
||||
if (!this.actor && game.user.id === userId) {
|
||||
const hasBeastformEffect = this.parent.effects.some(x => x.type === 'beastform');
|
||||
if (!hasBeastformEffect)
|
||||
this.parent.createEmbeddedDocuments('ActiveEffect', [
|
||||
{
|
||||
type: 'beastform',
|
||||
name: game.i18n.localize('DAGGERHEART.ITEMS.Beastform.beastformEffect'),
|
||||
img: 'icons/creatures/abilities/paw-print-pair-purple.webp'
|
||||
}
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,14 +61,15 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect {
|
|||
update.img = 'icons/magic/life/heart-cross-blue.webp';
|
||||
}
|
||||
|
||||
const statuses = Object.keys(data.statuses ?? {});
|
||||
const immuneStatuses =
|
||||
data.statuses?.filter(
|
||||
statuses.filter(
|
||||
status =>
|
||||
this.parent.system.rules?.conditionImmunities &&
|
||||
this.parent.system.rules.conditionImmunities[status]
|
||||
) ?? [];
|
||||
if (immuneStatuses.length > 0) {
|
||||
update.statuses = data.statuses.filter(x => !immuneStatuses.includes(x));
|
||||
update.statuses = statuses.filter(x => !immuneStatuses.includes(x));
|
||||
const conditions = CONFIG.DH.GENERAL.conditions();
|
||||
const scrollingTexts = immuneStatuses.map(status => ({
|
||||
text: game.i18n.format('DAGGERHEART.ACTIVEEFFECT.immuneStatusText', {
|
||||
|
|
|
|||
|
|
@ -170,7 +170,8 @@
|
|||
"value": 1,
|
||||
"recovery": "shortRest",
|
||||
"max": "1",
|
||||
"icon": ""
|
||||
"icon": "",
|
||||
"progression": "decreasing"
|
||||
},
|
||||
"attribution": {
|
||||
"source": "Daggerheart SRD",
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@
|
|||
|
||||
.dialog-header-inner {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
|
|
@ -45,6 +47,29 @@
|
|||
}
|
||||
}
|
||||
|
||||
.reaction-chip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 5px;
|
||||
width: fit-content;
|
||||
gap: 5px;
|
||||
cursor: pointer;
|
||||
padding: 5px;
|
||||
background: light-dark(@dark-blue-10, @golden-10);
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
|
||||
.label {
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: var(--font-size-14);
|
||||
line-height: 17px;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: light-dark(@dark-blue-40, @golden-40);
|
||||
}
|
||||
}
|
||||
|
||||
.tag-team-controller {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
|||
|
|
@ -1,17 +1,12 @@
|
|||
<header class="dialog-header">
|
||||
<div class="dialog-header-inner">
|
||||
<h1>
|
||||
{{#if reactionOverride}}
|
||||
{{localize "DAGGERHEART.CONFIG.FeatureForm.reaction"}}
|
||||
{{else}}
|
||||
{{ifThen rollConfig.headerTitle rollConfig.headerTitle rollConfig.title}}
|
||||
{{/if}}
|
||||
{{#if showReaction}}
|
||||
<button class="reaction-roll-controller {{#if reactionOverride}}active{{/if}}" data-action="toggleReaction" data-tooltip-text="{{localize "DAGGERHEART.GENERAL.reactionRoll"}}">
|
||||
<i class="fa-solid fa-reply"></i>
|
||||
</button>
|
||||
{{/if}}
|
||||
</h1>
|
||||
<h1>{{ifThen rollConfig.headerTitle rollConfig.headerTitle rollConfig.title}}</h1>
|
||||
{{#if showReaction}}
|
||||
<div class="reaction-chip {{#if reactionOverride}}selected{{/if}}" data-action="toggleReaction">
|
||||
<span><i class="{{ifThen reactionOverride "fa-solid" "fa-regular"}} fa-circle"></i></span>
|
||||
<span class="label">{{localize "DAGGERHEART.GENERAL.reactionRoll"}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if (and @root.hasRoll @root.activeTagTeamRoll)}}
|
||||
<div class="tag-team-controller {{#if @root.tagTeamSelected}}selected{{/if}}" data-action="toggleTagTeamRoll">
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@
|
|||
{{#if name}}
|
||||
<div class="experience-chip {{#if (includes ../selectedExperiences id)}}selected{{/if}}" data-action="selectExperience" data-key="{{id}}" data-tooltip="{{this.description}}">
|
||||
<span><i class="{{ifThen (includes ../selectedExperiences id) "fa-solid" "fa-regular"}} fa-circle"></i></span>
|
||||
<span class="label">{{name}} +{{value}}</span>
|
||||
<span class="label">{{name}} {{numberFormat value sign=true}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@
|
|||
{{#each document.system.experiences as |experience id|}}
|
||||
<div class="experience-row" data-tooltip-text="{{experience.description}}">
|
||||
<span class="experience-value">
|
||||
+{{experience.value}}
|
||||
{{numberFormat experience.value sign=true}}
|
||||
</span>
|
||||
<span class="experience-name">{{experience.name}}</span>
|
||||
<div class="controls">
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ Parameters:
|
|||
data-tooltip="DAGGERHEART.UI.Tooltip.{{ifThen item.system.inVault 'sendToLoadout' 'sendToVault' }}">
|
||||
<i class="fa-solid {{ifThen item.system.inVault 'fa-arrow-up' 'fa-arrow-down'}}"></i>
|
||||
</a>
|
||||
{{else if (eq type 'effect')}}
|
||||
{{else if (and (eq type 'effect') (not (eq item.type 'beastform')))}}
|
||||
<a data-action="toggleEffect"
|
||||
data-tooltip="DAGGERHEART.UI.Tooltip.{{ifThen item.disabled 'enableEffect' 'disableEffect' }}">
|
||||
<i class="{{ifThen item.disabled 'fa-solid fa-toggle-off' 'fa-solid fa-toggle-on'}}"></i>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ const foundryPath = process.env.FOUNDRY_MAIN_PATH || '../../../../FoundryDev/mai
|
|||
const dataPath = process.env.FOUNDRY_DATA_PATH || '../../../';
|
||||
|
||||
// Run the original command with proper environment
|
||||
const args = ['rollup -c --watch', `node "${foundryPath}" --dataPath="${dataPath}" --noupnp`, 'gulp'];
|
||||
const args = ['rollup -c --watch', `node "\"${foundryPath}\"" --dataPath="${dataPath}" --noupnp`, 'gulp'];
|
||||
|
||||
spawn('npx', ['concurrently', ...args.map(arg => `"${arg}"`)], {
|
||||
stdio: 'inherit',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue