mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-17 07:36:26 +01:00
Fixed translation of TrackedAttributeChoices
This commit is contained in:
parent
a768b1dfdb
commit
ad9a72d494
18 changed files with 410 additions and 91 deletions
|
|
@ -61,6 +61,14 @@ Hooks.once('init', () => {
|
||||||
CONFIG.Dice.rolls = [...CONFIG.Dice.rolls, ...[DHRoll, DualityRoll, D20Roll, DamageRoll]];
|
CONFIG.Dice.rolls = [...CONFIG.Dice.rolls, ...[DHRoll, DualityRoll, D20Roll, DamageRoll]];
|
||||||
CONFIG.MeasuredTemplate.objectClass = placeables.DhMeasuredTemplate;
|
CONFIG.MeasuredTemplate.objectClass = placeables.DhMeasuredTemplate;
|
||||||
|
|
||||||
|
const { DocumentSheetConfig } = foundry.applications.apps;
|
||||||
|
CONFIG.Token.documentClass = documents.DhToken;
|
||||||
|
CONFIG.Token.prototypeSheetClass = applications.sheetConfigs.DhPrototypeTokenConfig;
|
||||||
|
DocumentSheetConfig.unregisterSheet(TokenDocument, 'core', foundry.applications.sheets.TokenConfig);
|
||||||
|
DocumentSheetConfig.registerSheet(TokenDocument, 'dnd5e', applications.sheetConfigs.DhTokenConfig, {
|
||||||
|
makeDefault: true
|
||||||
|
});
|
||||||
|
|
||||||
CONFIG.Item.documentClass = documents.DHItem;
|
CONFIG.Item.documentClass = documents.DHItem;
|
||||||
|
|
||||||
//Registering the Item DataModel
|
//Registering the Item DataModel
|
||||||
|
|
@ -98,12 +106,12 @@ Hooks.once('init', () => {
|
||||||
CONFIG.ActiveEffect.documentClass = documents.DhActiveEffect;
|
CONFIG.ActiveEffect.documentClass = documents.DhActiveEffect;
|
||||||
CONFIG.ActiveEffect.dataModels = models.activeEffects.config;
|
CONFIG.ActiveEffect.dataModels = models.activeEffects.config;
|
||||||
|
|
||||||
foundry.applications.apps.DocumentSheetConfig.unregisterSheet(
|
DocumentSheetConfig.unregisterSheet(
|
||||||
CONFIG.ActiveEffect.documentClass,
|
CONFIG.ActiveEffect.documentClass,
|
||||||
'core',
|
'core',
|
||||||
foundry.applications.sheets.ActiveEffectConfig
|
foundry.applications.sheets.ActiveEffectConfig
|
||||||
);
|
);
|
||||||
foundry.applications.apps.DocumentSheetConfig.registerSheet(
|
DocumentSheetConfig.registerSheet(
|
||||||
CONFIG.ActiveEffect.documentClass,
|
CONFIG.ActiveEffect.documentClass,
|
||||||
SYSTEM.id,
|
SYSTEM.id,
|
||||||
applications.sheetConfigs.ActiveEffectConfig,
|
applications.sheetConfigs.ActiveEffectConfig,
|
||||||
|
|
|
||||||
41
lang/en.json
41
lang/en.json
|
|
@ -1011,23 +1011,36 @@
|
||||||
"severe": "Severe",
|
"severe": "Severe",
|
||||||
"major": "Major",
|
"major": "Major",
|
||||||
"minor": "Minor",
|
"minor": "Minor",
|
||||||
"none": "None"
|
"none": "None",
|
||||||
|
"allDamage": "All Damage",
|
||||||
|
"physicalDamage": "Physical Damage",
|
||||||
|
"magicalDamage": "Magical Damage",
|
||||||
|
"primaryDamageBonus": "Primary Weapon Damage",
|
||||||
|
"primaryDamageDice": "Primary Weapon Extra Dice"
|
||||||
},
|
},
|
||||||
"DamageResistance": {
|
"DamageResistance": {
|
||||||
"none": "None",
|
"none": "None",
|
||||||
"resistance": "Resistance",
|
"resistance": "Resistance",
|
||||||
"immunity": "Immunity"
|
"immunity": "Immunity",
|
||||||
|
"physicalReduction": "Physical Damage Reduction",
|
||||||
|
"magicalReduction": "Magical Damage Reduction"
|
||||||
},
|
},
|
||||||
"DamageThresholds": {
|
"DamageThresholds": {
|
||||||
"title": "Damage Thresholds",
|
"title": "Damage Thresholds",
|
||||||
"minor": "Minor",
|
"minor": "Minor",
|
||||||
"major": "Major",
|
"major": "Major",
|
||||||
"severe": "Severe"
|
"severe": "Severe",
|
||||||
|
"majorThreshold": "Major Damage Threshold",
|
||||||
|
"severeThreshold": "Severe Damage Threshold"
|
||||||
},
|
},
|
||||||
"Dice": {
|
"Dice": {
|
||||||
"single": "Die",
|
"single": "Die",
|
||||||
"plural": "Dice"
|
"plural": "Dice"
|
||||||
},
|
},
|
||||||
|
"Difficulty": {
|
||||||
|
"all": "Difficulty: all",
|
||||||
|
"reaction": "Difficulty: reaction"
|
||||||
|
},
|
||||||
"Disadvantage": {
|
"Disadvantage": {
|
||||||
"full": "Disadvantage",
|
"full": "Disadvantage",
|
||||||
"short": "Dis"
|
"short": "Dis"
|
||||||
|
|
@ -1093,6 +1106,25 @@
|
||||||
"single": "Resource",
|
"single": "Resource",
|
||||||
"plural": "Resources"
|
"plural": "Resources"
|
||||||
},
|
},
|
||||||
|
"Roll": {
|
||||||
|
"attack": "Attack Roll",
|
||||||
|
"primaryWeaponAttack": "Primary Weapon Attack Roll",
|
||||||
|
"spellcast": "Spellcast Roll",
|
||||||
|
"action": "Action Roll",
|
||||||
|
"hopeOrFear": "Hope Or Fear Roll"
|
||||||
|
},
|
||||||
|
"Rules": {
|
||||||
|
"damageReduction": {
|
||||||
|
"increasePerArmorMark": "Armor Block Per Mark",
|
||||||
|
"maxArmorMarkedBonus": "Max Armor Used",
|
||||||
|
"maxArmorMarkedStress": "Max Armor Used With Stress",
|
||||||
|
"stress": {
|
||||||
|
"severe": "Stress Damage Reduction: Severe",
|
||||||
|
"major": "Stress Damage Reduction: Major",
|
||||||
|
"minor": "Stress Damage Reduction: Minor"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Tabs": {
|
"Tabs": {
|
||||||
"details": "Details",
|
"details": "Details",
|
||||||
"attack": "Attack",
|
"attack": "Attack",
|
||||||
|
|
@ -1137,6 +1169,7 @@
|
||||||
"single": "Trait",
|
"single": "Trait",
|
||||||
"plural": "Traits"
|
"plural": "Traits"
|
||||||
},
|
},
|
||||||
|
"armorScore": "Armor Score",
|
||||||
"activeEffects": "Active Effects",
|
"activeEffects": "Active Effects",
|
||||||
"attack": "Attack",
|
"attack": "Attack",
|
||||||
"basics": "Basics",
|
"basics": "Basics",
|
||||||
|
|
@ -1155,6 +1188,7 @@
|
||||||
"features": "Features",
|
"features": "Features",
|
||||||
"hitPoints": "Hit Points",
|
"hitPoints": "Hit Points",
|
||||||
"hope": "Hope",
|
"hope": "Hope",
|
||||||
|
"hordeHp": "Horde HP",
|
||||||
"inactiveEffects": "Inactive Effects",
|
"inactiveEffects": "Inactive Effects",
|
||||||
"inventory": "Inventory",
|
"inventory": "Inventory",
|
||||||
"level": "Level",
|
"level": "Level",
|
||||||
|
|
@ -1162,6 +1196,7 @@
|
||||||
"modifier": "Modifier",
|
"modifier": "Modifier",
|
||||||
"multiclass": "Multiclass",
|
"multiclass": "Multiclass",
|
||||||
"none": "None",
|
"none": "None",
|
||||||
|
"proficiency": "Proficiency",
|
||||||
"quantity": "Quantity",
|
"quantity": "Quantity",
|
||||||
"range": "Range",
|
"range": "Range",
|
||||||
"recovery": "Recovery",
|
"recovery": "Recovery",
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,5 @@ export { default as AdversarySettings } from './adversary-settings.mjs';
|
||||||
export { default as CompanionSettings } from './companion-settings.mjs';
|
export { default as CompanionSettings } from './companion-settings.mjs';
|
||||||
export { default as EnvironmentSettings } from './environment-settings.mjs';
|
export { default as EnvironmentSettings } from './environment-settings.mjs';
|
||||||
export { default as ActiveEffectConfig } from './activeEffectConfig.mjs';
|
export { default as ActiveEffectConfig } from './activeEffectConfig.mjs';
|
||||||
|
export { default as DhTokenConfig } from './token-config.mjs';
|
||||||
|
export { default as DhPrototypeTokenConfig } from './prototype-token-config.mjs';
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,44 @@
|
||||||
|
import autocomplete from 'autocompleter';
|
||||||
|
|
||||||
export default class DhActiveEffectConfig extends foundry.applications.sheets.ActiveEffectConfig {
|
export default class DhActiveEffectConfig extends foundry.applications.sheets.ActiveEffectConfig {
|
||||||
|
constructor(options) {
|
||||||
|
super(options);
|
||||||
|
|
||||||
|
const ignoredActorKeys = ['config', 'DhEnvironment'];
|
||||||
|
const actorAttributes = Object.keys(game.system.api.models.actors).reduce((acc, key) => {
|
||||||
|
if (!ignoredActorKeys.includes(key)) {
|
||||||
|
const model = game.system.api.models.actors[key];
|
||||||
|
const attributes = CONFIG.Token.documentClass.getTrackedAttributes(model);
|
||||||
|
acc[game.i18n.localize(model.metadata.label)] = CONFIG.Token.documentClass.getTrackedAttributeChoices(
|
||||||
|
attributes,
|
||||||
|
model
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
console.log(actorAttributes);
|
||||||
|
|
||||||
|
// const allowedItemKeys = ['DHArmor'];
|
||||||
|
// const itemAttributes = Object.keys(game.system.api.models.items).reduce((acc, key) => {
|
||||||
|
// if(allowedItemKeys.includes(key)) {
|
||||||
|
// const model = game.system.api.models.items[key];
|
||||||
|
// acc[game.i18n.localize(model.metadata.label)] = CONFIG.Token.documentClass.getTrackedAttributes(model);
|
||||||
|
// }
|
||||||
|
// return acc;
|
||||||
|
// }, {});
|
||||||
|
|
||||||
|
// this.selectChoices = [
|
||||||
|
// ...Object.keys(actorAttributes).flatMap(name => {
|
||||||
|
// const attribute = actorAttributes[name];
|
||||||
|
// return { group: name, label: attribute, value: attribute };
|
||||||
|
// }),
|
||||||
|
// ...Object.keys(itemAttributes).flatMap(name => {
|
||||||
|
// const attribute = itemAttributes[name];
|
||||||
|
// return { group: name, label: attribute, value: attribute };
|
||||||
|
// })
|
||||||
|
// ];
|
||||||
|
}
|
||||||
|
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
classes: ['daggerheart', 'sheet', 'dh-style']
|
classes: ['daggerheart', 'sheet', 'dh-style']
|
||||||
};
|
};
|
||||||
|
|
@ -27,36 +67,61 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_attachPartListeners(partId, htmlElement, options) {
|
||||||
|
super._attachPartListeners(partId, htmlElement, options);
|
||||||
|
const selectChoices = this.selectChoices;
|
||||||
|
|
||||||
|
htmlElement.querySelectorAll('.effect-change-input').forEach(element => {
|
||||||
|
autocomplete({
|
||||||
|
input: element,
|
||||||
|
fetch: function (text, update) {
|
||||||
|
if (!text) {
|
||||||
|
update(selectChoices);
|
||||||
|
} else {
|
||||||
|
text = text.toLowerCase();
|
||||||
|
var suggestions = selectChoices.filter(n => n.label.toLowerCase().includes(text));
|
||||||
|
update(suggestions);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render: function (item, search) {
|
||||||
|
const label = game.i18n.localize(item.label);
|
||||||
|
const matchIndex = label.toLowerCase().indexOf(search);
|
||||||
|
|
||||||
|
const base = document.createElement('div');
|
||||||
|
base.textContent = label.slice(0, matchIndex);
|
||||||
|
|
||||||
|
const matchText = document.createElement('div');
|
||||||
|
matchText.textContent = label.slice(matchIndex, matchIndex + search.length);
|
||||||
|
matchText.classList.add('matched');
|
||||||
|
|
||||||
|
const after = document.createElement('div');
|
||||||
|
after.textContent = label.slice(matchIndex + search.length, label.length);
|
||||||
|
|
||||||
|
base.insertAdjacentElement('beforeend', matchText);
|
||||||
|
base.insertAdjacentElement('beforeend', after);
|
||||||
|
return base;
|
||||||
|
},
|
||||||
|
renderGroup: function (label) {
|
||||||
|
const itemElement = document.createElement('div');
|
||||||
|
itemElement.textContent = game.i18n.localize(label);
|
||||||
|
return itemElement;
|
||||||
|
},
|
||||||
|
onSelect: function (item) {
|
||||||
|
element.value = item.value;
|
||||||
|
},
|
||||||
|
click: e => e.fetch(),
|
||||||
|
minLength: 0
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async _preparePartContext(partId, context) {
|
async _preparePartContext(partId, context) {
|
||||||
const partContext = await super._preparePartContext(partId, context);
|
const partContext = await super._preparePartContext(partId, context);
|
||||||
switch (partId) {
|
switch (partId) {
|
||||||
case 'changes':
|
case 'changes':
|
||||||
const fieldPaths = [];
|
|
||||||
const validFieldPath = fieldPath => this.validFieldPath(fieldPath, this.#unapplicablePaths);
|
|
||||||
context.document.parent.system.schema.apply(function () {
|
|
||||||
if (!(this instanceof foundry.data.fields.SchemaField)) {
|
|
||||||
if (validFieldPath(this.fieldPath)) {
|
|
||||||
fieldPaths.push(this.fieldPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
context.fieldPaths = fieldPaths;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return partContext;
|
return partContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
#unapplicablePaths = ['story', 'pronouns', 'description'];
|
|
||||||
validFieldPath(fieldPath, unapplicablePaths) {
|
|
||||||
const splitPath = fieldPath.split('.');
|
|
||||||
if (splitPath.length > 1 && unapplicablePaths.includes(splitPath[1])) return false;
|
|
||||||
|
|
||||||
/* The current value of a resource should not be modified */
|
|
||||||
if (new RegExp(/resources.*\.value/).exec(fieldPath)) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
export default class DhPrototypeTokenConfig extends foundry.applications.sheets.PrototypeTokenConfig {
|
||||||
|
/** @inheritDoc */
|
||||||
|
async _prepareResourcesTab() {
|
||||||
|
const token = this.token;
|
||||||
|
const usesTrackableAttributes = !foundry.utils.isEmpty(CONFIG.Actor.trackableAttributes);
|
||||||
|
const attributeSource =
|
||||||
|
this.actor?.system instanceof foundry.abstract.DataModel && usesTrackableAttributes
|
||||||
|
? this.actor?.type
|
||||||
|
: this.actor?.system;
|
||||||
|
const TokenDocument = foundry.utils.getDocumentClass('Token');
|
||||||
|
const attributes = TokenDocument.getTrackedAttributes(attributeSource);
|
||||||
|
return {
|
||||||
|
barAttributes: TokenDocument.getTrackedAttributeChoices(attributes, attributeSource),
|
||||||
|
bar1: token.getBarAttribute?.('bar1'),
|
||||||
|
bar2: token.getBarAttribute?.('bar2'),
|
||||||
|
turnMarkerModes: DhPrototypeTokenConfig.TURN_MARKER_MODES,
|
||||||
|
turnMarkerAnimations: CONFIG.Combat.settings.turnMarkerAnimations
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
20
module/applications/sheets-configs/token-config.mjs
Normal file
20
module/applications/sheets-configs/token-config.mjs
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
export default class DhTokenConfig extends foundry.applications.sheets.TokenConfig {
|
||||||
|
/** @inheritDoc */
|
||||||
|
async _prepareResourcesTab() {
|
||||||
|
const token = this.token;
|
||||||
|
const usesTrackableAttributes = !foundry.utils.isEmpty(CONFIG.Actor.trackableAttributes);
|
||||||
|
const attributeSource =
|
||||||
|
this.actor?.system instanceof foundry.abstract.DataModel && usesTrackableAttributes
|
||||||
|
? this.actor?.type
|
||||||
|
: this.actor?.system;
|
||||||
|
const TokenDocument = foundry.utils.getDocumentClass('Token');
|
||||||
|
const attributes = TokenDocument.getTrackedAttributes(attributeSource);
|
||||||
|
return {
|
||||||
|
barAttributes: TokenDocument.getTrackedAttributeChoices(attributes, attributeSource),
|
||||||
|
bar1: token.getBarAttribute?.('bar1'),
|
||||||
|
bar2: token.getBarAttribute?.('bar2'),
|
||||||
|
turnMarkerModes: DhTokenConfig.TURN_MARKER_MODES,
|
||||||
|
turnMarkerAnimations: CONFIG.Combat.settings.turnMarkerAnimations
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,9 +2,9 @@ import DHAdversarySettings from '../../applications/sheets-configs/adversary-set
|
||||||
import ActionField from '../fields/actionField.mjs';
|
import ActionField from '../fields/actionField.mjs';
|
||||||
import BaseDataActor from './base.mjs';
|
import BaseDataActor from './base.mjs';
|
||||||
|
|
||||||
const resourceField = () =>
|
const resourceField = label =>
|
||||||
new foundry.data.fields.SchemaField({
|
new foundry.data.fields.SchemaField({
|
||||||
value: new foundry.data.fields.NumberField({ initial: 0, integer: true }),
|
value: new foundry.data.fields.NumberField({ initial: 0, integer: true, label }),
|
||||||
max: new foundry.data.fields.NumberField({ initial: 0, integer: true }),
|
max: new foundry.data.fields.NumberField({ initial: 0, integer: true }),
|
||||||
isReversed: new foundry.data.fields.BooleanField({ initial: true })
|
isReversed: new foundry.data.fields.BooleanField({ initial: true })
|
||||||
});
|
});
|
||||||
|
|
@ -37,14 +37,29 @@ export default class DhpAdversary extends BaseDataActor {
|
||||||
motivesAndTactics: new fields.StringField(),
|
motivesAndTactics: new fields.StringField(),
|
||||||
notes: new fields.HTMLField(),
|
notes: new fields.HTMLField(),
|
||||||
difficulty: new fields.NumberField({ required: true, initial: 1, integer: true }),
|
difficulty: new fields.NumberField({ required: true, initial: 1, integer: true }),
|
||||||
hordeHp: new fields.NumberField({ required: true, initial: 1, integer: true }),
|
hordeHp: new fields.NumberField({
|
||||||
|
required: true,
|
||||||
|
initial: 1,
|
||||||
|
integer: true,
|
||||||
|
label: 'DAGGERHEART.GENERAL.hordeHp'
|
||||||
|
}),
|
||||||
damageThresholds: new fields.SchemaField({
|
damageThresholds: new fields.SchemaField({
|
||||||
major: new fields.NumberField({ required: true, initial: 0, integer: true }),
|
major: new fields.NumberField({
|
||||||
severe: new fields.NumberField({ required: true, initial: 0, integer: true })
|
required: true,
|
||||||
|
initial: 0,
|
||||||
|
integer: true,
|
||||||
|
label: 'DAGGERHEART.GENERAL.DamageThresholds.majorThreshold'
|
||||||
|
}),
|
||||||
|
severe: new fields.NumberField({
|
||||||
|
required: true,
|
||||||
|
initial: 0,
|
||||||
|
integer: true,
|
||||||
|
label: 'DAGGERHEART.GENERAL.DamageThresholds.severeThreshold'
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
resources: new fields.SchemaField({
|
resources: new fields.SchemaField({
|
||||||
hitPoints: resourceField(),
|
hitPoints: resourceField('DAGGERHEART.GENERAL.hitPoints'),
|
||||||
stress: resourceField()
|
stress: resourceField('DAGGERHEART.GENERAL.stress')
|
||||||
}),
|
}),
|
||||||
attack: new ActionField({
|
attack: new ActionField({
|
||||||
initial: {
|
initial: {
|
||||||
|
|
@ -81,8 +96,16 @@ export default class DhpAdversary extends BaseDataActor {
|
||||||
),
|
),
|
||||||
bonuses: new fields.SchemaField({
|
bonuses: new fields.SchemaField({
|
||||||
difficulty: new fields.SchemaField({
|
difficulty: new fields.SchemaField({
|
||||||
all: new fields.NumberField({ integer: true, initial: 0 }),
|
all: new fields.NumberField({
|
||||||
reaction: new fields.NumberField({ integer: true, initial: 0 })
|
integer: true,
|
||||||
|
initial: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Difficulty.all'
|
||||||
|
}),
|
||||||
|
reaction: new fields.NumberField({
|
||||||
|
integer: true,
|
||||||
|
initial: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Difficulty.reaction'
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import DHBaseActorSettings from '../../applications/sheets/api/actor-setting.mjs';
|
import DHBaseActorSettings from '../../applications/sheets/api/actor-setting.mjs';
|
||||||
|
|
||||||
const resistanceField = () =>
|
const resistanceField = reductionLabel =>
|
||||||
new foundry.data.fields.SchemaField({
|
new foundry.data.fields.SchemaField({
|
||||||
resistance: new foundry.data.fields.BooleanField({ initial: false }),
|
resistance: new foundry.data.fields.BooleanField({ initial: false }),
|
||||||
immunity: 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 })
|
reduction: new foundry.data.fields.NumberField({ integer: true, initial: 0, label: reductionLabel })
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -40,8 +40,8 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel {
|
||||||
if (this.metadata.isNPC) schema.description = new fields.HTMLField({ required: true, nullable: true });
|
if (this.metadata.isNPC) schema.description = new fields.HTMLField({ required: true, nullable: true });
|
||||||
if (this.metadata.hasResistances)
|
if (this.metadata.hasResistances)
|
||||||
schema.resistance = new fields.SchemaField({
|
schema.resistance = new fields.SchemaField({
|
||||||
physical: resistanceField(),
|
physical: resistanceField('DAGGERHEART.GENERAL.DamageResistance.physicalReduction'),
|
||||||
magical: resistanceField()
|
magical: resistanceField('DAGGERHEART.GENERAL.DamageResistance.magicalReduction')
|
||||||
});
|
});
|
||||||
return schema;
|
return schema;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,26 +3,28 @@ import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs';
|
||||||
import DhLevelData from '../levelData.mjs';
|
import DhLevelData from '../levelData.mjs';
|
||||||
import BaseDataActor from './base.mjs';
|
import BaseDataActor from './base.mjs';
|
||||||
|
|
||||||
const attributeField = () =>
|
const attributeField = label =>
|
||||||
new foundry.data.fields.SchemaField({
|
new foundry.data.fields.SchemaField({
|
||||||
value: new foundry.data.fields.NumberField({ initial: 0, integer: true }),
|
value: new foundry.data.fields.NumberField({ initial: 0, integer: true, label: label }),
|
||||||
tierMarked: new foundry.data.fields.BooleanField({ initial: false })
|
tierMarked: new foundry.data.fields.BooleanField({ initial: false })
|
||||||
});
|
});
|
||||||
|
|
||||||
const resourceField = (max, reverse = false) =>
|
const resourceField = (max, label, reverse = false) =>
|
||||||
new foundry.data.fields.SchemaField({
|
new foundry.data.fields.SchemaField({
|
||||||
value: new foundry.data.fields.NumberField({ initial: 0, integer: true }),
|
value: new foundry.data.fields.NumberField({ initial: 0, integer: true, label: label }),
|
||||||
max: new foundry.data.fields.NumberField({ initial: max, integer: true }),
|
max: new foundry.data.fields.NumberField({ initial: max, integer: true }),
|
||||||
isReversed: new foundry.data.fields.BooleanField({ initial: reverse })
|
isReversed: new foundry.data.fields.BooleanField({ initial: reverse })
|
||||||
});
|
});
|
||||||
|
|
||||||
const stressDamageReductionRule = () =>
|
const stressDamageReductionRule = label =>
|
||||||
new foundry.data.fields.SchemaField({
|
new foundry.data.fields.SchemaField({
|
||||||
enabled: new foundry.data.fields.BooleanField({ required: true, initial: false }),
|
enabled: new foundry.data.fields.BooleanField({ required: true, initial: false }),
|
||||||
cost: new foundry.data.fields.NumberField({ integer: true })
|
cost: new foundry.data.fields.NumberField({ integer: true, label })
|
||||||
});
|
});
|
||||||
|
|
||||||
export default class DhCharacter extends BaseDataActor {
|
export default class DhCharacter extends BaseDataActor {
|
||||||
|
static LOCALIZATION_PREFIXES = ['DAGGERHEART.ACTORS.Character'];
|
||||||
|
|
||||||
static get metadata() {
|
static get metadata() {
|
||||||
return foundry.utils.mergeObject(super.metadata, {
|
return foundry.utils.mergeObject(super.metadata, {
|
||||||
label: 'TYPES.Actor.character',
|
label: 'TYPES.Actor.character',
|
||||||
|
|
@ -37,24 +39,36 @@ export default class DhCharacter extends BaseDataActor {
|
||||||
return {
|
return {
|
||||||
...super.defineSchema(),
|
...super.defineSchema(),
|
||||||
resources: new fields.SchemaField({
|
resources: new fields.SchemaField({
|
||||||
hitPoints: resourceField(0, true),
|
hitPoints: resourceField(0, 'DAGGERHEART.GENERAL.hitPoints', true),
|
||||||
stress: resourceField(6, true),
|
stress: resourceField(6, 'DAGGERHEART.GENERAL.stress', true),
|
||||||
hope: resourceField(6)
|
hope: resourceField(6, 'DAGGERHEART.GENERAL.hope')
|
||||||
}),
|
}),
|
||||||
traits: new fields.SchemaField({
|
traits: new fields.SchemaField({
|
||||||
agility: attributeField(),
|
agility: attributeField('DAGGERHEART.CONFIG.Traits.agility.name'),
|
||||||
strength: attributeField(),
|
strength: attributeField('DAGGERHEART.CONFIG.Traits.strength.name'),
|
||||||
finesse: attributeField(),
|
finesse: attributeField('DAGGERHEART.CONFIG.Traits.finesse.name'),
|
||||||
instinct: attributeField(),
|
instinct: attributeField('DAGGERHEART.CONFIG.Traits.instinct.name'),
|
||||||
presence: attributeField(),
|
presence: attributeField('DAGGERHEART.CONFIG.Traits.presence.name'),
|
||||||
knowledge: attributeField()
|
knowledge: attributeField('DAGGERHEART.CONFIG.Traits.knowledge.name')
|
||||||
}),
|
}),
|
||||||
proficiency: new fields.NumberField({ initial: 1, integer: true }),
|
proficiency: new fields.NumberField({
|
||||||
evasion: new fields.NumberField({ initial: 0, integer: true }),
|
initial: 1,
|
||||||
armorScore: new fields.NumberField({ integer: true, initial: 0 }),
|
integer: true,
|
||||||
|
label: 'DAGGERHEART.GENERAL.proficiency'
|
||||||
|
}),
|
||||||
|
evasion: new fields.NumberField({ initial: 0, integer: true, label: 'DAGGERHEART.GENERAL.evasion' }),
|
||||||
|
armorScore: new fields.NumberField({ integer: true, initial: 0, label: 'DAGGERHEART.GENERAL.armorScore' }),
|
||||||
damageThresholds: new fields.SchemaField({
|
damageThresholds: new fields.SchemaField({
|
||||||
severe: new fields.NumberField({ integer: true, initial: 0 }),
|
severe: new fields.NumberField({
|
||||||
major: new fields.NumberField({ integer: true, initial: 0 })
|
integer: true,
|
||||||
|
initial: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.DamageThresholds.majorThreshold'
|
||||||
|
}),
|
||||||
|
major: new fields.NumberField({
|
||||||
|
integer: true,
|
||||||
|
initial: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.DamageThresholds.severeThreshold'
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
experiences: new fields.TypedObjectField(
|
experiences: new fields.TypedObjectField(
|
||||||
new fields.SchemaField({
|
new fields.SchemaField({
|
||||||
|
|
@ -94,21 +108,59 @@ export default class DhCharacter extends BaseDataActor {
|
||||||
levelData: new fields.EmbeddedDataField(DhLevelData),
|
levelData: new fields.EmbeddedDataField(DhLevelData),
|
||||||
bonuses: new fields.SchemaField({
|
bonuses: new fields.SchemaField({
|
||||||
roll: new fields.SchemaField({
|
roll: new fields.SchemaField({
|
||||||
attack: new fields.NumberField({ integer: true, initial: 0 }),
|
attack: new fields.NumberField({
|
||||||
primaryWeapon: new fields.SchemaField({
|
integer: true,
|
||||||
attack: new fields.NumberField({ integer: true, initial: 0 })
|
initial: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Roll.attack'
|
||||||
}),
|
}),
|
||||||
spellcast: new fields.NumberField({ integer: true, initial: 0 }),
|
primaryWeapon: new fields.SchemaField({
|
||||||
action: new fields.NumberField({ integer: true, initial: 0 }),
|
attack: new fields.NumberField({
|
||||||
hopeOrFear: new fields.NumberField({ integer: true, initial: 0 })
|
integer: true,
|
||||||
|
initial: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Roll.primaryWeaponAttack'
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
spellcast: new fields.NumberField({
|
||||||
|
integer: true,
|
||||||
|
initial: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Roll.spellcast'
|
||||||
|
}),
|
||||||
|
action: new fields.NumberField({
|
||||||
|
integer: true,
|
||||||
|
initial: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Roll.action'
|
||||||
|
}),
|
||||||
|
hopeOrFear: new fields.NumberField({
|
||||||
|
integer: true,
|
||||||
|
initial: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Roll.hopeOrFear'
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
damage: new fields.SchemaField({
|
damage: new fields.SchemaField({
|
||||||
all: new fields.NumberField({ integer: true, initial: 0 }),
|
all: new fields.NumberField({
|
||||||
physical: new fields.NumberField({ integer: true, initial: 0 }),
|
integer: true,
|
||||||
magic: new fields.NumberField({ integer: true, initial: 0 }),
|
initial: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Damage.allDamage'
|
||||||
|
}),
|
||||||
|
physical: new fields.NumberField({
|
||||||
|
integer: true,
|
||||||
|
initial: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Damage.physicalDamage'
|
||||||
|
}),
|
||||||
|
magic: new fields.NumberField({
|
||||||
|
integer: true,
|
||||||
|
initial: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Damage.magicalDamage'
|
||||||
|
}),
|
||||||
primaryWeapon: new fields.SchemaField({
|
primaryWeapon: new fields.SchemaField({
|
||||||
bonus: new fields.NumberField({ integer: true }),
|
bonus: new fields.NumberField({
|
||||||
extraDice: new fields.NumberField({ integer: true })
|
integer: true,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Damage.primaryDamageBonus'
|
||||||
|
}),
|
||||||
|
extraDice: new fields.NumberField({
|
||||||
|
integer: true,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Damage.primaryDamageDice'
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
|
|
@ -117,25 +169,32 @@ export default class DhCharacter extends BaseDataActor {
|
||||||
damageReduction: new fields.SchemaField({
|
damageReduction: new fields.SchemaField({
|
||||||
maxArmorMarked: new fields.SchemaField({
|
maxArmorMarked: new fields.SchemaField({
|
||||||
value: new fields.NumberField({ required: true, integer: true, initial: 1 }),
|
value: new fields.NumberField({ required: true, integer: true, initial: 1 }),
|
||||||
bonus: new fields.NumberField({ required: true, integer: true, initial: 0 }),
|
bonus: new fields.NumberField({
|
||||||
stressExtra: new fields.NumberField({ required: true, integer: true, initial: 0 })
|
required: true,
|
||||||
|
integer: true,
|
||||||
|
initial: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.maxArmorMarkedBonus'
|
||||||
|
}),
|
||||||
|
stressExtra: new fields.NumberField({
|
||||||
|
required: true,
|
||||||
|
integer: true,
|
||||||
|
initial: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.maxArmorMarkedStress'
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
stressDamageReduction: new fields.SchemaField({
|
stressDamageReduction: new fields.SchemaField({
|
||||||
severe: stressDamageReductionRule(),
|
severe: stressDamageReductionRule('DAGGERHEART.GENERAL.Rules.damageReduction.stress.severe'),
|
||||||
major: stressDamageReductionRule(),
|
major: stressDamageReductionRule('DAGGERHEART.GENERAL.Rules.damageReduction.stress.major'),
|
||||||
minor: stressDamageReductionRule()
|
minor: stressDamageReductionRule('DAGGERHEART.GENERAL.Rules.damageReduction.stress.minor')
|
||||||
|
}),
|
||||||
|
increasePerArmorMark: new fields.NumberField({
|
||||||
|
integer: true,
|
||||||
|
initial: 1,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.increasePerArmorMark'
|
||||||
}),
|
}),
|
||||||
increasePerArmorMark: new fields.NumberField({ integer: true, initial: 1 }),
|
|
||||||
magical: new fields.BooleanField({ initial: false }),
|
magical: new fields.BooleanField({ initial: false }),
|
||||||
physical: new fields.BooleanField({ initial: false })
|
physical: new fields.BooleanField({ initial: false })
|
||||||
}),
|
}),
|
||||||
strangePatterns: new fields.NumberField({
|
|
||||||
integer: true,
|
|
||||||
min: 1,
|
|
||||||
max: 12,
|
|
||||||
nullable: true,
|
|
||||||
initial: null
|
|
||||||
}),
|
|
||||||
weapon: new fields.SchemaField({
|
weapon: new fields.SchemaField({
|
||||||
/* Unimplemented
|
/* Unimplemented
|
||||||
-> Should remove the lowest damage dice from weapon damage
|
-> Should remove the lowest damage dice from weapon damage
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,15 @@ export default class DhCompanion extends BaseDataActor {
|
||||||
max: new fields.NumberField({ initial: 3, integer: true }),
|
max: new fields.NumberField({ initial: 3, integer: true }),
|
||||||
isReversed: new foundry.data.fields.BooleanField({ initial: true })
|
isReversed: new foundry.data.fields.BooleanField({ initial: true })
|
||||||
}),
|
}),
|
||||||
hope: new fields.NumberField({ initial: 0, integer: true })
|
hope: new fields.NumberField({ initial: 0, integer: true, label: 'DAGGERHEART.GENERAL.hope' })
|
||||||
|
}),
|
||||||
|
evasion: new fields.NumberField({
|
||||||
|
required: true,
|
||||||
|
min: 1,
|
||||||
|
initial: 10,
|
||||||
|
integer: true,
|
||||||
|
label: 'DAGGERHEART.GENERAL.evasion'
|
||||||
}),
|
}),
|
||||||
evasion: new fields.NumberField({ required: true, min: 1, initial: 10, integer: true }),
|
|
||||||
experiences: new fields.TypedObjectField(
|
experiences: new fields.TypedObjectField(
|
||||||
new fields.SchemaField({
|
new fields.SchemaField({
|
||||||
name: new fields.StringField({}),
|
name: new fields.StringField({}),
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,5 @@ export { default as DHItem } from './item.mjs';
|
||||||
export { default as DhpCombat } from './combat.mjs';
|
export { default as DhpCombat } from './combat.mjs';
|
||||||
export { default as DhActiveEffect } from './activeEffect.mjs';
|
export { default as DhActiveEffect } from './activeEffect.mjs';
|
||||||
export { default as DhChatMessage } from './chatMessage.mjs';
|
export { default as DhChatMessage } from './chatMessage.mjs';
|
||||||
|
export { default as DhToken } from './token.mjs';
|
||||||
export { default as DhTooltipManager } from './tooltipManager.mjs';
|
export { default as DhTooltipManager } from './tooltipManager.mjs';
|
||||||
|
|
|
||||||
33
module/documents/token.mjs
Normal file
33
module/documents/token.mjs
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
export default class DHToken extends TokenDocument {
|
||||||
|
/**
|
||||||
|
* Inspect the Actor data model and identify the set of attributes which could be used for a Token Bar.
|
||||||
|
* @param {object} attributes The tracked attributes which can be chosen from
|
||||||
|
* @returns {object} A nested object of attribute choices to display
|
||||||
|
*/
|
||||||
|
static getTrackedAttributeChoices(attributes, model) {
|
||||||
|
attributes = attributes || this.getTrackedAttributes();
|
||||||
|
const barGroup = game.i18n.localize('TOKEN.BarAttributes');
|
||||||
|
const valueGroup = game.i18n.localize('TOKEN.BarValues');
|
||||||
|
|
||||||
|
const bars = attributes.bar.map(v => {
|
||||||
|
const a = v.join('.');
|
||||||
|
const modelLabel = model ? game.i18n.localize(model.schema.getField(`${a}.value`).label) : null;
|
||||||
|
return { group: barGroup, value: a, label: modelLabel ? modelLabel : a };
|
||||||
|
});
|
||||||
|
bars.sort((a, b) => a.label.compare(b.label));
|
||||||
|
|
||||||
|
const invalidAttributes = ['gold', 'levelData', 'rules.damageReduction.maxArmorMarked.value'];
|
||||||
|
const values = attributes.value.reduce((acc, v) => {
|
||||||
|
const a = v.join('.');
|
||||||
|
if (invalidAttributes.some(x => a.startsWith(x))) return acc;
|
||||||
|
|
||||||
|
const modelLabel = model ? game.i18n.localize(model.schema.getField(a).label) : null;
|
||||||
|
acc.push({ group: valueGroup, value: a, label: modelLabel ? modelLabel : a });
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
values.sort((a, b) => a.label.compare(b.label));
|
||||||
|
|
||||||
|
return bars.concat(values);
|
||||||
|
}
|
||||||
|
}
|
||||||
6
package-lock.json
generated
6
package-lock.json
generated
|
|
@ -6,6 +6,7 @@
|
||||||
"": {
|
"": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@yaireo/tagify": "^4.17.9",
|
"@yaireo/tagify": "^4.17.9",
|
||||||
|
"autocompleter": "^9.3.2",
|
||||||
"gulp": "^5.0.0",
|
"gulp": "^5.0.0",
|
||||||
"gulp-less": "^5.0.0",
|
"gulp-less": "^5.0.0",
|
||||||
"rollup": "^4.40.0"
|
"rollup": "^4.40.0"
|
||||||
|
|
@ -608,6 +609,11 @@
|
||||||
"node": ">= 10.13.0"
|
"node": ">= 10.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/autocompleter": {
|
||||||
|
"version": "9.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/autocompleter/-/autocompleter-9.3.2.tgz",
|
||||||
|
"integrity": "sha512-rLbf2TLGOD7y+gOS36ksrZdIsvoHa2KXc2A7503w+NBRPrcF73zzFeYBxEcV/iMPjaBH3jFhNIYObZ7zt1fkCQ=="
|
||||||
|
},
|
||||||
"node_modules/available-typed-arrays": {
|
"node_modules/available-typed-arrays": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@yaireo/tagify": "^4.17.9",
|
"@yaireo/tagify": "^4.17.9",
|
||||||
|
"autocompleter": "^9.3.2",
|
||||||
"gulp": "^5.0.0",
|
"gulp": "^5.0.0",
|
||||||
"gulp-less": "^5.0.0",
|
"gulp-less": "^5.0.0",
|
||||||
"rollup": "^4.40.0"
|
"rollup": "^4.40.0"
|
||||||
|
|
|
||||||
39
styles/less/ux/autocomplete/autocomplete.less
Normal file
39
styles/less/ux/autocomplete/autocomplete.less
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
.theme-light .autocomplete {
|
||||||
|
background-image: url('../assets/parchments/dh-parchment-dark.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete {
|
||||||
|
padding: 2px;
|
||||||
|
border-width: 0 1px 1px 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: light-dark(@dark-blue, @beige);
|
||||||
|
border-radius: 6px;
|
||||||
|
color: light-dark(@beige, @dark);
|
||||||
|
background-image: url('../assets/parchments/dh-parchment-light.png');
|
||||||
|
z-index: 200;
|
||||||
|
|
||||||
|
.group {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
padding-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div[role='option'] {
|
||||||
|
font-size: 14;
|
||||||
|
padding-left: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: light-dark(@beige-50, @dark-blue);
|
||||||
|
color: light-dark(@dark, @beige);
|
||||||
|
}
|
||||||
|
|
||||||
|
.matched {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
@import './tooltip/tooltip.less';
|
@import './tooltip/tooltip.less';
|
||||||
|
@import './autocomplete/autocomplete.less';
|
||||||
|
|
|
||||||
|
|
@ -264,7 +264,7 @@
|
||||||
"applyEffect": {}
|
"applyEffect": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"primaryTokenAttribute": "resources.health",
|
"primaryTokenAttribute": "resources.hitPoints",
|
||||||
"secondaryTokenAttribute": "resources.stress",
|
"secondaryTokenAttribute": "resources.stress",
|
||||||
"url": "https://your/hosted/system/repo/",
|
"url": "https://your/hosted/system/repo/",
|
||||||
"manifest": "https://your/hosted/system/repo/system.json",
|
"manifest": "https://your/hosted/system/repo/system.json",
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,12 @@
|
||||||
{{#with ../fields.changes.element.fields as |changeFields|}}
|
{{#with ../fields.changes.element.fields as |changeFields|}}
|
||||||
<li data-index="{{i}}">
|
<li data-index="{{i}}">
|
||||||
<div class="key">
|
<div class="key">
|
||||||
<input type="text" name="{{concat "changes." i ".key"}}" value="{{change.key}}" list="change-fields" />
|
<input type="text" class="effect-change-input" name="{{concat "changes." i ".key"}}" value="{{change.key}}" />
|
||||||
<datalist id="change-fields">
|
{{!-- <datalist id="change-fields">
|
||||||
{{#each @root.fieldPaths}}
|
{{#each @root.fieldPaths}}
|
||||||
<option value="{{this}}">{{this}}</option>
|
<option value="{{this}}">{{this}}</option>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</datalist>
|
</datalist> --}}
|
||||||
</div>
|
</div>
|
||||||
<div class="mode">
|
<div class="mode">
|
||||||
{{formInput changeFields.mode name=(concat "changes." i ".mode") value=change.mode choices=@root.modes}}
|
{{formInput changeFields.mode name=(concat "changes." i ".mode") value=change.mode choices=@root.modes}}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue