mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-03-07 22:46:12 +01:00
.
This commit is contained in:
parent
514e0260eb
commit
fb9f89fa9d
8 changed files with 127 additions and 57 deletions
|
|
@ -1849,6 +1849,9 @@
|
||||||
"Attachments": {
|
"Attachments": {
|
||||||
"attachHint": "Drop items here to attach them",
|
"attachHint": "Drop items here to attach them",
|
||||||
"transferHint": "If checked, this effect will be applied to any actor that owns this Effect's parent Item. The effect is always applied if this Item is attached to another one."
|
"transferHint": "If checked, this effect will be applied to any actor that owns this Effect's parent Item. The effect is always applied if this Item is attached to another one."
|
||||||
|
},
|
||||||
|
"Armor": {
|
||||||
|
"newArmorEffect": "Armor Effect"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"GENERAL": {
|
"GENERAL": {
|
||||||
|
|
@ -2975,7 +2978,9 @@
|
||||||
"tokenActorMissing": "{name} is missing an Actor",
|
"tokenActorMissing": "{name} is missing an Actor",
|
||||||
"tokenActorsMissing": "[{names}] missing Actors",
|
"tokenActorsMissing": "[{names}] missing Actors",
|
||||||
"domainTouchRequirement": "This domain card requires {nr} {domain} cards in the loadout to be used",
|
"domainTouchRequirement": "This domain card requires {nr} {domain} cards in the loadout to be used",
|
||||||
"knowTheTide": "Know The Tide gained a token"
|
"knowTheTide": "Know The Tide gained a token",
|
||||||
|
"cannotAlterArmorEffectChanges": "You cannot alter the changes length of an armor effect",
|
||||||
|
"cannotAlterArmorEffectType": "You cannot alter the type of armor effect changes"
|
||||||
},
|
},
|
||||||
"Sidebar": {
|
"Sidebar": {
|
||||||
"actorDirectory": {
|
"actorDirectory": {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ export default class ArmorActiveEffectConfig extends HandlebarsApplicationMixin(
|
||||||
closeOnSubmit: false
|
closeOnSubmit: false
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
addEffect: ArmorActiveEffectConfig.#addEffect,
|
|
||||||
finish: ArmorActiveEffectConfig.#finish
|
finish: ArmorActiveEffectConfig.#finish
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -54,11 +53,6 @@ export default class ArmorActiveEffectConfig extends HandlebarsApplicationMixin(
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
static #addEffect() {
|
|
||||||
this.document.update({ 'system.changes': [...this.document.system.changes, {}] });
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
static #finish() {
|
static #finish() {
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ 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;
|
context.armorScore = this.document.system.armorData.max;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
/**
|
||||||
|
* ArmorEffects are ActiveEffects that have a static changes field of length 1. It includes current and maximum armor.
|
||||||
|
* When applied to a character, it adds to their currently marked and maximum armor.
|
||||||
|
*/
|
||||||
export default class ArmorEffect extends foundry.data.ActiveEffectTypeDataModel {
|
export default class ArmorEffect extends foundry.data.ActiveEffectTypeDataModel {
|
||||||
static defineSchema() {
|
static defineSchema() {
|
||||||
const fields = foundry.data.fields;
|
const fields = foundry.data.fields;
|
||||||
|
|
@ -14,7 +18,7 @@ export default class ArmorEffect extends foundry.data.ActiveEffectTypeDataModel
|
||||||
}),
|
}),
|
||||||
phase: new fields.StringField({ required: true, blank: false, initial: 'initial' }),
|
phase: new fields.StringField({ required: true, blank: false, initial: 'initial' }),
|
||||||
priority: new fields.NumberField({ integer: true, initial: 20 }),
|
priority: new fields.NumberField({ integer: true, initial: 20 }),
|
||||||
marked: new fields.NumberField({
|
value: new fields.NumberField({
|
||||||
required: true,
|
required: true,
|
||||||
integer: true,
|
integer: true,
|
||||||
initial: 0,
|
initial: 0,
|
||||||
|
|
@ -28,28 +32,35 @@ export default class ArmorEffect extends foundry.data.ActiveEffectTypeDataModel
|
||||||
min: 1,
|
min: 1,
|
||||||
label: 'DAGGERHEART.GENERAL.max'
|
label: 'DAGGERHEART.GENERAL.max'
|
||||||
})
|
})
|
||||||
})
|
}),
|
||||||
|
{
|
||||||
|
initial: [
|
||||||
|
{
|
||||||
|
type: CONFIG.DH.GENERAL.activeEffectModes.armor.id,
|
||||||
|
phase: 'initial',
|
||||||
|
priority: 20,
|
||||||
|
value: 0,
|
||||||
|
max: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
get armorData() {
|
/* Type Functions */
|
||||||
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;
|
* Validate that an {@link EffectChangeData#type} string is well-formed.
|
||||||
const newChanges = this.changes.map(change => ({
|
* @param {string} type The string to be validated
|
||||||
...change,
|
* @returns {true}
|
||||||
max: newMax,
|
* @throws {Error} An error if the type string is malformed
|
||||||
marked: Math.min(change.marked, newMax)
|
*/
|
||||||
}));
|
static #validateType(type) {
|
||||||
await this.parent.update({ 'system.changes': newChanges });
|
if (type !== CONFIG.DH.GENERAL.activeEffectModes.armor.id)
|
||||||
}
|
throw new Error('An armor effect must have change.type "armor"');
|
||||||
|
|
||||||
static applyChangeField(model, change, field) {
|
return true;
|
||||||
return [model, change, field];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static armorChangeEffect = {
|
static armorChangeEffect = {
|
||||||
|
|
@ -81,23 +92,71 @@ export default class ArmorEffect extends foundry.data.ActiveEffectTypeDataModel
|
||||||
render: null
|
render: null
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Helpers */
|
||||||
|
|
||||||
|
get armorChange() {
|
||||||
|
if (this.changes.length !== 1)
|
||||||
|
throw new Error('Unexpected error. An armor effect should have a changes field of length 1.');
|
||||||
|
return this.changes[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
get armorData() {
|
||||||
|
return { value: this.armorChange.value, max: this.armorChange.max };
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateArmorMax(newMax) {
|
||||||
|
const newChanges = [
|
||||||
|
{
|
||||||
|
...this.armorChange,
|
||||||
|
max: newMax,
|
||||||
|
value: Math.min(this.armorChange.value, newMax)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
await this.parent.update({ 'system.changes': newChanges });
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Overrides */
|
||||||
|
|
||||||
prepareBaseData() {
|
prepareBaseData() {
|
||||||
for (const change of this.changes) {
|
const armorChange = this.armorChange;
|
||||||
change.key = 'system.armorScore';
|
armorChange.key = 'system.armorScore';
|
||||||
change.value = Math.min(change.max - change.marked, change.max);
|
}
|
||||||
|
|
||||||
|
static getDefaultEffectData() {
|
||||||
|
return {
|
||||||
|
type: 'armor',
|
||||||
|
name: game.i18n.localize('DAGGERHEART.EFFECTS.Armor.newArmorEffect'),
|
||||||
|
img: 'icons/equipment/chest/breastplate-helmet-metal.webp'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async _preCreate(data, options, user) {
|
||||||
|
const allowed = await super._preCreate(data, options, user);
|
||||||
|
if (allowed === false) return;
|
||||||
|
|
||||||
|
await this.updateSource({ ...ArmorEffect.getDefaultEffectData(), data });
|
||||||
|
}
|
||||||
|
|
||||||
|
async _preUpdate(changes, options, user) {
|
||||||
|
const allowed = await super._preUpdate(changes, options, user);
|
||||||
|
if (allowed === false) return false;
|
||||||
|
|
||||||
|
if (changes.system?.changes) {
|
||||||
|
const changesChanged = changes.system.changes.length !== this.changes.length;
|
||||||
|
if (changesChanged) {
|
||||||
|
ui.notifications.error(
|
||||||
|
game.i18n.localize('DAGGERHEART.UI.Notifications.cannotAlterArmorEffectChanges')
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
changes.system.changes.length === 1 &&
|
||||||
|
changes.system.changes[0].type !== CONFIG.DH.GENERAL.activeEffectModes.armor.id
|
||||||
|
) {
|
||||||
|
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.cannotAlterArmorEffectType'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate that an {@link EffectChangeData#type} string is well-formed.
|
|
||||||
* @param {string} type The string to be validated
|
|
||||||
* @returns {true}
|
|
||||||
* @throws {Error} An error if the type string is malformed
|
|
||||||
*/
|
|
||||||
static #validateType(type) {
|
|
||||||
if (type !== CONFIG.DH.GENERAL.activeEffectModes.armor.id)
|
|
||||||
throw new Error('An armor effect must have change.type "armor"');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -458,6 +458,11 @@ export default class DhCharacter extends BaseDataActor {
|
||||||
return this.parent.items.find(x => x.type === 'armor' && x.system.equipped);
|
return this.parent.items.find(x => x.type === 'armor' && x.system.equipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: Prep datastructure to be useful when applying automatic armor damage order */
|
||||||
|
get armorEffects() {
|
||||||
|
return Array.from(this.parent.allApplicableEffects());
|
||||||
|
}
|
||||||
|
|
||||||
get activeBeastform() {
|
get activeBeastform() {
|
||||||
return this.parent.effects.find(x => x.type === 'beastform');
|
return this.parent.effects.find(x => x.type === 'beastform');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,10 +54,16 @@ export default class DHArmor extends AttachableItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
get armorEffect() {
|
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');
|
return this.parent.effects.find(x => x.type === 'armor');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get armorData() {
|
||||||
|
const armorEffect = this.armorEffect;
|
||||||
|
if (!armorEffect) return { value: 0, max: 0 };
|
||||||
|
|
||||||
|
return armorEffect.system.armorData;
|
||||||
|
}
|
||||||
|
|
||||||
/**@inheritdoc */
|
/**@inheritdoc */
|
||||||
async getDescriptionData() {
|
async getDescriptionData() {
|
||||||
const baseDescription = this.description;
|
const baseDescription = this.description;
|
||||||
|
|
@ -73,6 +79,17 @@ export default class DHArmor extends AttachableItem {
|
||||||
return { prefix, value: baseDescription, suffix: null };
|
return { prefix, value: baseDescription, suffix: null };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**@inheritdoc */
|
||||||
|
async _onCreate(_data, _options, userId) {
|
||||||
|
if (userId !== game.user.id) return;
|
||||||
|
|
||||||
|
if (!this.parent.effects.some(x => x.type === 'armor')) {
|
||||||
|
this.parent.createEmbeddedDocuments('ActiveEffect', [
|
||||||
|
game.system.api.data.activeEffects.ArmorEffect.getDefaultEffectData()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**@inheritdoc */
|
/**@inheritdoc */
|
||||||
async _preUpdate(changes, options, user) {
|
async _preUpdate(changes, options, user) {
|
||||||
const allowed = await super._preUpdate(changes, options, user);
|
const allowed = await super._preUpdate(changes, options, user);
|
||||||
|
|
@ -163,9 +180,8 @@ 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')}: ${baseScore}`,
|
`${game.i18n.localize('DAGGERHEART.ITEMS.Armor.baseScore')}: ${this.armorData.value}`,
|
||||||
`${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}`
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -177,11 +193,7 @@ export default class DHArmor extends AttachableItem {
|
||||||
* @returns {(string | { value: string, icons: string[] })[]} An array of localized strings and damage label objects.
|
* @returns {(string | { value: string, icons: string[] })[]} An array of localized strings and damage label objects.
|
||||||
*/
|
*/
|
||||||
_getLabels() {
|
_getLabels() {
|
||||||
const labels = [];
|
const labels = [`${game.i18n.localize('DAGGERHEART.ITEMS.Armor.baseScore')}: ${this.armorData.value}`];
|
||||||
if (this.armorEffect)
|
|
||||||
labels.push(
|
|
||||||
`${game.i18n.localize('DAGGERHEART.ITEMS.Armor.baseScore')}: ${this.armorEffect.system.armorData?.value}`
|
|
||||||
);
|
|
||||||
return labels;
|
return labels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -146,18 +146,15 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect {
|
||||||
|
|
||||||
/**@inheritdoc*/
|
/**@inheritdoc*/
|
||||||
static applyChangeField(model, change, field) {
|
static applyChangeField(model, change, field) {
|
||||||
if (this.system?.applyChangeField)
|
|
||||||
super.applyChangeField(...this.system.applyChangeField(model, change, field));
|
|
||||||
|
|
||||||
change.value = Number.isNumeric(change.value)
|
change.value = Number.isNumeric(change.value)
|
||||||
? change.value
|
? change.value
|
||||||
: DhActiveEffect.getChangeValue(model, change, change.effect);
|
: DhActiveEffect.getChangeValue(model, change, change.effect);
|
||||||
super.applyChangeField(model, change, field);
|
super.applyChangeField(model, change, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
_applyLegacy(actor, change, changes) {
|
_applyChangeUnguided(actor, change, changes, options) {
|
||||||
change.value = DhActiveEffect.getChangeValue(actor, change, change.effect);
|
change.value = DhActiveEffect.getChangeValue(actor, change, change.effect);
|
||||||
super._applyLegacy(actor, change, changes);
|
super._applyChangeUnguided(actor, change, changes, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getChangeValue(model, change, effect) {
|
static getChangeValue(model, change, effect) {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
<section class="tab{{#if tab.active}} active{{/if}}" data-group="{{tab.group}}" data-tab="{{tab.id}}">
|
<section class="tab{{#if tab.active}} active{{/if}}" data-group="{{tab.group}}" data-tab="{{tab.id}}">
|
||||||
<button data-action="addEffect">Add Effect</button>
|
|
||||||
|
|
||||||
<div class="armor-effects-container">
|
<div class="armor-effects-container">
|
||||||
{{#each source.system.changes as |change index|}}
|
{{#each source.system.changes as |change index|}}
|
||||||
<div class="armor-effect-container">
|
<div class="armor-effect-container">
|
||||||
{{formGroup @root.systemFields.changes.element.fields.marked name=(concat 'system.changes.' index '.marked') value=change.marked localize=true}}
|
{{formGroup @root.systemFields.changes.element.fields.value name=(concat 'system.changes.' index '.value') value=change.value localize=true}}
|
||||||
{{formGroup @root.systemFields.changes.element.fields.max name=(concat 'system.changes.' index '.max') value=change.max localize=true}}
|
{{formGroup @root.systemFields.changes.element.fields.max name=(concat 'system.changes.' index '.max') value=change.max localize=true}}
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue