mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-03-07 14:36:13 +01:00
Working armor application
This commit is contained in:
parent
7036a53c71
commit
514e0260eb
9 changed files with 99 additions and 18 deletions
|
|
@ -43,6 +43,7 @@ CONFIG.Item.dataModels = models.items.config;
|
||||||
|
|
||||||
CONFIG.ActiveEffect.documentClass = documents.DhActiveEffect;
|
CONFIG.ActiveEffect.documentClass = documents.DhActiveEffect;
|
||||||
CONFIG.ActiveEffect.dataModels = models.activeEffects.config;
|
CONFIG.ActiveEffect.dataModels = models.activeEffects.config;
|
||||||
|
CONFIG.ActiveEffect.changeTypes = { ...CONFIG.ActiveEffect.changeTypes, ...models.activeEffects.changeTypes };
|
||||||
|
|
||||||
CONFIG.Combat.documentClass = documents.DhpCombat;
|
CONFIG.Combat.documentClass = documents.DhpCombat;
|
||||||
CONFIG.Combat.dataModels = { base: models.DhCombat };
|
CONFIG.Combat.dataModels = { base: models.DhCombat };
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,13 @@ export default class ArmorSheet extends ItemAttachmentSheet(DHBaseItemSheet) {
|
||||||
...super.PARTS
|
...super.PARTS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_attachPartListeners(partId, htmlElement, options) {
|
||||||
|
super._attachPartListeners(partId, htmlElement, options);
|
||||||
|
|
||||||
|
for (const element of htmlElement.querySelectorAll('.base-score-input'))
|
||||||
|
element.addEventListener('change', this.updateArmorEffect.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
/**@inheritdoc */
|
/**@inheritdoc */
|
||||||
async _preparePartContext(partId, context) {
|
async _preparePartContext(partId, context) {
|
||||||
await super._preparePartContext(partId, context);
|
await super._preparePartContext(partId, context);
|
||||||
|
|
@ -41,12 +48,22 @@ export default class ArmorSheet extends ItemAttachmentSheet(DHBaseItemSheet) {
|
||||||
switch (partId) {
|
switch (partId) {
|
||||||
case 'settings':
|
case 'settings':
|
||||||
context.features = this.document.system.armorFeatures.map(x => x.value);
|
context.features = this.document.system.armorFeatures.map(x => x.value);
|
||||||
|
context.armorScore = this.document.system.armorEffect?.system.armorData?.max;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async updateArmorEffect(event) {
|
||||||
|
const value = Number.parseInt(event.target.value);
|
||||||
|
const armorEffect = this.document.system.armorEffect;
|
||||||
|
if (Number.isNaN(value) || !armorEffect) return;
|
||||||
|
|
||||||
|
await armorEffect.system.updateArmorMax(value);
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback function used by `tagifyElement`.
|
* Callback function used by `tagifyElement`.
|
||||||
* @param {Array<Object>} selectedOptions - The currently selected tag objects.
|
* @param {Array<Object>} selectedOptions - The currently selected tag objects.
|
||||||
|
|
|
||||||
|
|
@ -854,6 +854,11 @@ export const sceneRangeMeasurementSetting = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const activeEffectModes = {
|
export const activeEffectModes = {
|
||||||
|
armor: {
|
||||||
|
id: 'armor',
|
||||||
|
priority: 20,
|
||||||
|
label: 'TYPES.ActiveEffect.armor'
|
||||||
|
},
|
||||||
custom: {
|
custom: {
|
||||||
id: 'custom',
|
id: 'custom',
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
|
|
||||||
|
|
@ -11,3 +11,7 @@ export const config = {
|
||||||
horde: HordeEffect,
|
horde: HordeEffect,
|
||||||
armor: ArmorEffect
|
armor: ArmorEffect
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const changeTypes = {
|
||||||
|
armor: ArmorEffect.armorChangeEffect
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,11 @@ export default class ArmorEffect extends foundry.data.ActiveEffectTypeDataModel
|
||||||
type: new fields.StringField({
|
type: new fields.StringField({
|
||||||
required: true,
|
required: true,
|
||||||
blank: false,
|
blank: false,
|
||||||
choices: CONFIG.DH.GENERAL.activeEffectModes,
|
initial: CONFIG.DH.GENERAL.activeEffectModes.armor.id,
|
||||||
initial: CONFIG.DH.GENERAL.activeEffectModes.add.id,
|
|
||||||
validate: ArmorEffect.#validateType
|
validate: ArmorEffect.#validateType
|
||||||
}),
|
}),
|
||||||
phase: new fields.StringField({ required: true, blank: false, initial: 'initial' }),
|
phase: new fields.StringField({ required: true, blank: false, initial: 'initial' }),
|
||||||
priority: new fields.NumberField(),
|
priority: new fields.NumberField({ integer: true, initial: 20 }),
|
||||||
marked: new fields.NumberField({
|
marked: new fields.NumberField({
|
||||||
required: true,
|
required: true,
|
||||||
integer: true,
|
integer: true,
|
||||||
|
|
@ -34,13 +33,57 @@ export default class ArmorEffect extends foundry.data.ActiveEffectTypeDataModel
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get armorData() {
|
||||||
|
if (this.changes.length !== 1) return { value: 0, max: 0 };
|
||||||
|
return { value: this.changes[0].value, max: this.changes[0].max };
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateArmorMax(newMax) {
|
||||||
|
if (this.changes.length !== 1) return;
|
||||||
|
const newChanges = this.changes.map(change => ({
|
||||||
|
...change,
|
||||||
|
max: newMax,
|
||||||
|
marked: Math.min(change.marked, newMax)
|
||||||
|
}));
|
||||||
|
await this.parent.update({ 'system.changes': newChanges });
|
||||||
|
}
|
||||||
|
|
||||||
static applyChangeField(model, change, field) {
|
static applyChangeField(model, change, field) {
|
||||||
return [model, change, field];
|
return [model, change, field];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static armorChangeEffect = {
|
||||||
|
label: 'Armor',
|
||||||
|
defaultPriortiy: 20,
|
||||||
|
handler: (actor, change, _options, _field, replacementData) => {
|
||||||
|
game.system.api.documents.DhActiveEffect.applyChange(
|
||||||
|
actor,
|
||||||
|
{
|
||||||
|
...change,
|
||||||
|
key: 'system.armorScore.value',
|
||||||
|
type: CONFIG.DH.GENERAL.activeEffectModes.add.id,
|
||||||
|
value: change.value
|
||||||
|
},
|
||||||
|
replacementData
|
||||||
|
);
|
||||||
|
game.system.api.documents.DhActiveEffect.applyChange(
|
||||||
|
actor,
|
||||||
|
{
|
||||||
|
...change,
|
||||||
|
key: 'system.armorScore.max',
|
||||||
|
type: CONFIG.DH.GENERAL.activeEffectModes.add.id,
|
||||||
|
value: change.max
|
||||||
|
},
|
||||||
|
replacementData
|
||||||
|
);
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
render: null
|
||||||
|
};
|
||||||
|
|
||||||
prepareBaseData() {
|
prepareBaseData() {
|
||||||
for (const change of this.changes) {
|
for (const change of this.changes) {
|
||||||
change.key = 'system.armorScore.value';
|
change.key = 'system.armorScore';
|
||||||
change.value = Math.min(change.max - change.marked, change.max);
|
change.value = Math.min(change.max - change.marked, change.max);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -52,13 +95,9 @@ export default class ArmorEffect extends foundry.data.ActiveEffectTypeDataModel
|
||||||
* @throws {Error} An error if the type string is malformed
|
* @throws {Error} An error if the type string is malformed
|
||||||
*/
|
*/
|
||||||
static #validateType(type) {
|
static #validateType(type) {
|
||||||
if (type.length < 3) throw new Error('must be at least three characters long');
|
if (type !== CONFIG.DH.GENERAL.activeEffectModes.armor.id)
|
||||||
if (!/^custom\.-?\d+$/.test(type) && !type.split('.').every(s => /^[a-z0-9]+$/i.test(s))) {
|
throw new Error('An armor effect must have change.type "armor"');
|
||||||
throw new Error(
|
|
||||||
'A change type must either be a sequence of dot-delimited, alpha-numeric substrings or of the form' +
|
|
||||||
' "custom.{number}"'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ export default class DHArmor extends AttachableItem {
|
||||||
...super.defineSchema(),
|
...super.defineSchema(),
|
||||||
tier: new fields.NumberField({ required: true, integer: true, initial: 1, min: 1 }),
|
tier: new fields.NumberField({ required: true, integer: true, initial: 1, min: 1 }),
|
||||||
equipped: new fields.BooleanField({ initial: false }),
|
equipped: new fields.BooleanField({ initial: false }),
|
||||||
baseScore: new fields.NumberField({ integer: true, initial: 0 }),
|
|
||||||
armorFeatures: new fields.ArrayField(
|
armorFeatures: new fields.ArrayField(
|
||||||
new fields.SchemaField({
|
new fields.SchemaField({
|
||||||
value: new fields.StringField({
|
value: new fields.StringField({
|
||||||
|
|
@ -54,6 +53,11 @@ export default class DHArmor extends AttachableItem {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get armorEffect() {
|
||||||
|
/* TODO: make armors only able to have on armor effect, or handle in some other way */
|
||||||
|
return this.parent.effects.find(x => x.type === 'armor');
|
||||||
|
}
|
||||||
|
|
||||||
/**@inheritdoc */
|
/**@inheritdoc */
|
||||||
async getDescriptionData() {
|
async getDescriptionData() {
|
||||||
const baseDescription = this.description;
|
const baseDescription = this.description;
|
||||||
|
|
@ -159,8 +163,9 @@ export default class DHArmor extends AttachableItem {
|
||||||
* @returns {string[]} An array of localized tag strings.
|
* @returns {string[]} An array of localized tag strings.
|
||||||
*/
|
*/
|
||||||
_getTags() {
|
_getTags() {
|
||||||
|
const baseScore = this.armorEffect?.system.armorData?.value;
|
||||||
const tags = [
|
const tags = [
|
||||||
`${game.i18n.localize('DAGGERHEART.ITEMS.Armor.baseScore')}: ${this.baseScore}`,
|
`${game.i18n.localize('DAGGERHEART.ITEMS.Armor.baseScore')}: ${baseScore}`,
|
||||||
`${game.i18n.localize('DAGGERHEART.ITEMS.Armor.baseThresholds.base')}: ${this.baseThresholds.major} / ${this.baseThresholds.severe}`
|
`${game.i18n.localize('DAGGERHEART.ITEMS.Armor.baseThresholds.base')}: ${this.baseThresholds.major} / ${this.baseThresholds.severe}`
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -173,8 +178,10 @@ export default class DHArmor extends AttachableItem {
|
||||||
*/
|
*/
|
||||||
_getLabels() {
|
_getLabels() {
|
||||||
const labels = [];
|
const labels = [];
|
||||||
if (this.baseScore)
|
if (this.armorEffect)
|
||||||
labels.push(`${game.i18n.localize('DAGGERHEART.ITEMS.Armor.baseScore')}: ${this.baseScore}`);
|
labels.push(
|
||||||
|
`${game.i18n.localize('DAGGERHEART.ITEMS.Armor.baseScore')}: ${this.armorEffect.system.armorData?.value}`
|
||||||
|
);
|
||||||
return labels;
|
return labels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then apply the standard suppression rules
|
// Then apply the standard suppression rules
|
||||||
if (['weapon', 'armor'].includes(this.parent?.type)) {
|
if (['weapon', 'armor'].includes(this.parent?.type) && this.transfer) {
|
||||||
return !this.parent.system.equipped;
|
return !this.parent.system.equipped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -992,4 +992,8 @@ export default class DhpActor extends Actor {
|
||||||
|
|
||||||
return allTokens;
|
return allTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
applyActiveEffects(phase) {
|
||||||
|
super.applyActiveEffects(phase);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,12 @@
|
||||||
<legend>{{localize tabs.settings.label}}</legend>
|
<legend>{{localize tabs.settings.label}}</legend>
|
||||||
<span>{{localize "DAGGERHEART.GENERAL.Tiers.singular"}}</span>
|
<span>{{localize "DAGGERHEART.GENERAL.Tiers.singular"}}</span>
|
||||||
{{formField systemFields.tier value=source.system.tier}}
|
{{formField systemFields.tier value=source.system.tier}}
|
||||||
<span>{{localize "DAGGERHEART.ITEMS.Armor.baseScore"}}</span>
|
{{#if this.armorScore includeZero=true}}
|
||||||
{{formField systemFields.baseScore value=source.system.baseScore}}
|
<span>{{localize "DAGGERHEART.ITEMS.Armor.baseScore"}}</span>
|
||||||
|
<div class="form-fields">
|
||||||
|
<input type="text" data-dtype="Number" class="base-score-input" value="{{this.armorScore}}" />
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
<span>{{localize "TYPES.Item.feature"}}</span>
|
<span>{{localize "TYPES.Item.feature"}}</span>
|
||||||
<input type="text" class="features-input" value="{{features}}" />
|
<input type="text" class="features-input" value="{{features}}" />
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue