From 4c4f75f30b80538100a67a1ac028e4fbf1da721c Mon Sep 17 00:00:00 2001 From: r0ms Date: Sat, 28 Feb 2026 21:03:39 +0100 Subject: [PATCH 01/11] feat(bae): wip, not working great --- css/torgeternity.css | 34 +++++++ module/config.js | 52 ++++++++++ module/data/active-effect.js | 66 ++++++++++++- .../active-effect/torgActiveEffect.js | 94 ++++++++++++++++++- .../sheets/torgeternityActiveEffectConfig.js | 49 +++++++++- system.json | 4 +- templates/active_effects/torg_changes.hbs | 63 +++++++++++++ .../torg_effects.hbs} | 0 8 files changed, 351 insertions(+), 11 deletions(-) create mode 100644 templates/active_effects/torg_changes.hbs rename templates/{active-effect-torg.hbs => active_effects/torg_effects.hbs} (100%) diff --git a/css/torgeternity.css b/css/torgeternity.css index 9d44179b5..e7eefc63f 100644 --- a/css/torgeternity.css +++ b/css/torgeternity.css @@ -4763,4 +4763,38 @@ aside.carry-type-menu { background: #444; } } +} + +.torgeternity-active-effects.changes { + .scrollable { + display: flex; + flex-direction: column; + gap: 8px; /* Breathing room between rows */ + padding: 0; + margin: 0; + list-style: none; + align-items: flex-start; + } + + .change-row { + display: flex; + align-items: center; + gap: 10px; + } + + .change-row select { + flex: 8; + height:2rem; + } + + .change-row .value-input { + flex: 1; + height:2rem; + } + + .change-button { + border: 1px solid; + margin-top: 12px; + padding: 16px 12px; + } } \ No newline at end of file diff --git a/module/config.js b/module/config.js index fb73f3a27..0d99f6194 100644 --- a/module/config.js +++ b/module/config.js @@ -315,6 +315,50 @@ export function initConfig() { faith: 'torgeternity.powerSkills.faith', }; + torgeternity.interactionSkills = { + intimidation: 'torgeternity.skills.intimidation', + maneuver: 'torgeternity.skills.maneuver', + taunt: 'torgeternity.skills.taunt', + trick: 'torgeternity.skills.trick', + } + + torgeternity.combatSkills = { + dodge: 'torgeternity.skills.dodge', + energyWeapons: 'torgeternity.skills.energyWeapons', + fireCombat: 'torgeternity.skills.fireCombat', + heavyWeapons: 'torgeternity.skills.heavyWeapons', + meleeWeapons: 'torgeternity.skills.meleeWeapons', + missileWeapons: 'torgeternity.skills.missileWeapons', + unarmedCombat: 'torgeternity.skills.unarmedCombat', + } + + torgeternity.vehiclesSkills = { + airVehicles: 'torgeternity.skills.airVehicles', + beastRiding: 'torgeternity.skills.beastRiding', + landVehicles: 'torgeternity.skills.landVehicles', + waterVehicles: 'torgeternity.skills.waterVehicles', + } + + torgeternity.otherSkills = { + computers: 'torgeternity.skills.computers', + evidenceAnalysis: 'torgeternity.skills.evidenceAnalysis', + find: 'torgeternity.skills.find', + firstAid: 'torgeternity.skills.firstAid', + language: 'torgeternity.skills.language', + lockpicking: 'torgeternity.skills.lockpicking', + medicine: 'torgeternity.skills.medicine', + persuasion: 'torgeternity.skills.persuasion', + profession: 'torgeternity.skills.profession', + reality: 'torgeternity.skills.reality', + scholar: 'torgeternity.skills.scholar', + science: 'torgeternity.skills.science', + stealth: 'torgeternity.skills.stealth', + streetwise: 'torgeternity.skills.streetwise', + survival: 'torgeternity.skills.survival', + tracking: 'torgeternity.skills.tracking', + willpower: 'torgeternity.skills.willpower', + } + torgeternity.clearances = { alpha: 'torgeternity.clearances.alpha', beta: 'torgeternity.clearances.beta', @@ -376,6 +420,7 @@ export function initConfig() { willpower: 'torgeternity.skills.willpower', }; + torgeternity.concentrationSkills = [ // Spells 'alteration', @@ -632,6 +677,13 @@ export function initConfig() { ...Object.entries(torgeternity.rangedWeaponTraits).reduce((acc, ent) => { acc[ent[0]] = { label: ent[1], group: 'torgeternity.traitGroup.ranged' }; return acc }, {}), } + torgeternity.allSkillsGrouped = { + ...Object.entries(torgeternity.combatSkills).reduce((acc, ent) => { acc[ent[0]] = { label: ent[1], group: 'torgeternity.skillGroup.power' }; return acc }, {}), + ...Object.entries(torgeternity.powerSkills).reduce((acc, ent) => { acc[ent[0]] = { label: ent[1], group: 'torgeternity.skillGroup.combat' }; return acc }, {}), + ...Object.entries(torgeternity.vehiclesSkills).reduce((acc, ent) => { acc[ent[0]] = { label: ent[1], group: 'torgeternity.skillGroup.vehicle' }; return acc }, {}), + ...Object.entries(torgeternity.otherSkills).reduce((acc, ent) => { acc[ent[0]] = { label: ent[1], group: 'torgeternity.skillGroup.other' }; return acc }, {}), + } + torgeternity.specificItemTraits = { // ammunition diff --git a/module/data/active-effect.js b/module/data/active-effect.js index 02655f825..12125c408 100644 --- a/module/data/active-effect.js +++ b/module/data/active-effect.js @@ -2,6 +2,40 @@ import { newTraitsField } from './item/baseItemData.js'; const fields = foundry.data.fields; +const toFieldSchema = (choiceList) => new fields.ArrayField( + new fields.SchemaField({ + key: new fields.StringField({ + //required: true, + choices: choiceList, + initial: "" , + blank:true, + nullable:true + }), + value: new fields.StringField({ initial: "0", blank: true }), + mode: new fields.NumberField({ + initial: CONST.ACTIVE_EFFECT_MODES.ADD, + integer: true + }), + priority: new fields.NumberField({ initial: null, nullable: true }) + }) +); + + +const setSkillsSchema = () => new fields.SetField( + new fields.StringField({ + blank: false, + choices: CONFIG.torgeternity.allSkillsGrouped, + textSearch: true, + trim: true, + }), + { + nullable: false, + required: true, + label: "Skills favoured", + initial: undefined + }); + + /** * Addtional fields for TorgEternity ActiveEffect * @@ -9,13 +43,18 @@ const fields = foundry.data.fields; * @param {Boolean} transferOnOutcome Apply this effect to the target of the attack if the attack test has this specific outcome. * @param {SetField(StringField)} applyIfTrait Apply this effect to the item if the owning actor has one of these traits. * @param {SetField(StringField)} applyVsTrait Apply this effect to the item if the target has one of these traits. + * @param {SetField(StringField)} skillsFavor Wether a skill is favor by this active effect */ export class TorgActiveEffectData extends (foundry.data.ActiveEffectTypeDataModel ?? foundry.abstract.TypeDataModel) { // Foundry 14 - change base class to foundry.data.ActiveEffectTypeDataModel static LOCALIZATION_PREFIXES = ["torgeternity.activeEffect"]; - static defineSchema() { + const skillAddChoices = Object.fromEntries(Object.entries(CONFIG.torgeternity.skills).map(([k,v]) => [(v+'.adds').replace('torgeternity', 'system'), v])) + //const skillFavChoices = Object.fromEntries(Object.entries(CONFIG.torgeternity.skills).map(([k,v]) => [(v).replace('torgeternity', 'system'), v])) + const attributesAddsChoices = Object.fromEntries(Object.entries(CONFIG.torgeternity.attributeTypes).map(([k,v]) => [(v+'.value').replace('torgeternity', 'system'), v])) + const attributesFavChoices = Object.fromEntries(Object.entries(CONFIG.torgeternity.attributeTypes).map(([k,v]) => [(v+'.isFav').replace('torgeternity', 'system'), v])) + const schema = (game.release.generation >= 14) ? foundry.data.ActiveEffectTypeDataModel.defineSchema() : {}; Object.assign(schema, { @@ -30,7 +69,14 @@ export class TorgActiveEffectData extends (foundry.data.ActiveEffectTypeDataMode applyIfAttackTrait: newTraitsField(), applyIfDefendTrait: newTraitsField(), combatToggle: new fields.BooleanField({ initial: false, }), + skillsAdds: toFieldSchema(skillAddChoices), + attributesAdds: toFieldSchema(attributesAddsChoices), + skillsFavor: setSkillsSchema(), + attributesFavor: toFieldSchema(attributesFavChoices), + defensesChanges: toFieldSchema(CONFIG.torgeternity.defenses), + otherChanges: toFieldSchema(["system.possibilityPerAct"]), }) + //console.log("schema", schema) return schema; } @@ -46,6 +92,22 @@ export class TorgActiveEffectData extends (foundry.data.ActiveEffectTypeDataMode */ get isSuppressed() { // Don't apply the AE to the owning actor if it is being transferred on an attack - return (this.transferOnAttack || this.transferOnOutcome); + return this.system && (this.system.transferOnAttack || this.system.transferOnOutcome); + } + + async _preUpdate(changed, options, user) { + console.log("[Data] PreUpdate") + const result = await super._preUpdate(changed, options, user); + // Check if our SetField 'favoredSkills' is being updated + if ( "skillsFavor" in (changed.system || {}) ) { + const newSkillSet = changed.system.skillsFavor; // This is an Array or Set in v13 + const effectChanges = Array.from(newSkillSet).map(skillId => ({ + key: `system.skills.${skillId}.isFav`, + value: 'true', + mode: CONST.ACTIVE_EFFECT_MODES.OVERRIDE + })); + changed.changes = [...changed.changes, ...effectChanges] + } + return result; } } \ No newline at end of file diff --git a/module/documents/active-effect/torgActiveEffect.js b/module/documents/active-effect/torgActiveEffect.js index 5ad42d40a..a8c074eab 100644 --- a/module/documents/active-effect/torgActiveEffect.js +++ b/module/documents/active-effect/torgActiveEffect.js @@ -58,7 +58,6 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { } } } - // Replace flags if (source.flags?.torgeternity?.transferOnAttack !== undefined) { source.system.transferOnAttack = source.flags.torgeternity.transferOnAttack; @@ -69,6 +68,63 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { delete source.flags.torgeternity.testOutcome; } + if(!source.changes){ + source.changes = [] + } + if(source.system.skillsFavor){ + source.system.skillsFavor.forEach((sf) => { + source.changes.push({ + key:'system.skills.'+sf+'.isFav', + value: 'true', + mode: CONST.ACTIVE_EFFECT_MODES.OVERRIDE + }) + }) + } + const changesPerType = source.changes?.reduce((changesPerType, change) => { + // if(change.key.includes('skills') && change.key.includes('isFav')){ + // changesPerType.skillsFavor.push(change.key.replace('system.skills.', '').replace('.isFav', '')) + // return changesPerType + // } + if(change.key.includes('attributes') && change.key.includes('isFav')){ + changesPerType.attributesFavor.push(change) + return changesPerType + } + if(change.key.includes('skills') && !change.key.includes('isFav')){ + changesPerType.skillsAdds.push(change) + return changesPerType + } + if(change.key.includes('attributes')){ + changesPerType.attributesAdds.push(change) + return changesPerType + } + if(change.key.includes('defenses')){ + changesPerType.defensesChanges.push(change) + return changesPerType + } + if(change.key.includes('other')){ + changesPerType.otherChanges.push(change) + return changesPerType + } + return changesPerType + }, { + skillsAdds:[], + skillsFavor:[], + attributesAdds:[], + attributesFavor:[], + defensesChanges:[], + otherChanges:[] + }) + if(!source.system){ + source.system = {} + } + source.system.skillsAdds = changesPerType.skillsAdds ?? [] + source.system.skillsFavor = source.system.skillsFavor ?? [] + source.system.attributesAdds = changesPerType.attributesAdds ?? [] + source.system.attributesFavor = changesPerType.attributesFavor ?? [] + source.system.defensesChanges = changesPerType.defensesChanges ?? [] + source.system.otherChanges = changesPerType.otherChanges ?? [] + console.log("[Document] Data Migration") + console.log(source) return super.migrateData(source); } @@ -84,26 +140,56 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { } /** - * Return if this effect modifies the target of the test rather than the owner of the AE. + * Should this effect be transferred to the target on a successful attack? + * @param {TestResult} result + * @param {Array | undefined} attackTraits array of traits on the actor performing the test + * @param {Array | undefined} defendTraits array of traits on the target of the test + */ + appliesToTest(result, attackTraits, defendTraits) { + return (!this.disabled && + (this.system.transferOnAttack && result >= TestResult.STANDARD) || (this.system.transferOnOutcome === result)) && + testTraits(this.system.applyIfAttackTrait, attackTraits) && + testTraits(this.system.applyIfDefendTrait, defendTraits); + } + + /** + * Return if this effect has at least one change which is not merely changing the test. * @type {boolean} */ get modifiesTarget() { return !this.disabled && - (this.system.transferOnAttack || this.system.transferOnOutcome); + (this.system.transferOnAttack || this.system.transferOnOutcome) && + (this.changes.find(change => !change.key.startsWith('test.')) || this.statuses.length !== 0); } static blank; /** - * Return a copy of this object with the various "attack" traits cleared. + * Return a copy of this object with the various "attack" traits cleared, + * and any 'test.*' changes removed from it. */ copyForTarget() { if (!this.blank) this.blank = new TorgActiveEffect({ name: "blank" }); let fx = this.toObject(); + fx.changes = fx.changes.filter(change => !change.key.startsWith('test.')); return Object.assign(fx, { disabled: false, system: this.blank.system, origin: this.parent.uuid, }); } +} + +/** + * Return true if testTraits contains at least one of the entries in actualTraits + * @param {Set} testTraits + * @param {Array} actualTraits + */ +function testTraits(testTraits, actualTraits) { + if (!testTraits?.size) return true; + if (!actualTraits?.length) return false; + for (const trait of testTraits) { + if (actualTraits.includes(trait)) return true; + } + return false; } \ No newline at end of file diff --git a/module/sheets/torgeternityActiveEffectConfig.js b/module/sheets/torgeternityActiveEffectConfig.js index cc164a818..27b11ad35 100644 --- a/module/sheets/torgeternityActiveEffectConfig.js +++ b/module/sheets/torgeternityActiveEffectConfig.js @@ -5,9 +5,10 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. header: { template: "templates/sheets/active-effect/header.hbs" }, tabs: { template: "templates/generic/tab-navigation.hbs" }, details: { template: "templates/sheets/active-effect/details.hbs", scrollable: [""] }, - torg: { template: "systems/torgeternity/templates/active-effect-torg.hbs", scrollable: [""] }, + torg: { template: "systems/torgeternity_dev/templates/active_effects/torg_effects.hbs", scrollable: [""] }, duration: { template: "templates/sheets/active-effect/duration.hbs" }, changes: { template: "templates/sheets/active-effect/changes.hbs", scrollable: ["ol[data-changes]"] }, + torgChanges: { template: "systems/torgeternity_dev/templates/active_effects/torg_changes.hbs", scrollable: ["ol[data-changes]"] }, footer: { template: "templates/generic/form-footer.hbs" } }; @@ -18,18 +19,60 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. { id: "details", icon: "fa-solid fa-book" }, { id: "torg", icon: "fa-solid fa-swords" }, { id: "duration", icon: "fa-solid fa-clock" }, - { id: "changes", icon: "fa-solid fa-gears" } + { id: "changes", icon: "fa-solid fa-gears" }, + { id: "torgChanges", icon: "fa-solid fa-warning" }, ], initial: "details", labelPrefix: "EFFECT.TABS" }, }; + /** @override **/ + /** @inheritDoc */ + static DEFAULT_OPTIONS = { + classes: ["active-effect-config"], + window: { + contentClasses: ["standard-form"], + icon: "fa-solid fa-person-rays" + }, + position: {width: 800}, + form: {closeOnSubmit: false}, + actions: { + addSkillChange: this.#onAddSkillChange, + deleSkillChange: this.#onDeleteSkillChange + } + }; + async _preparePartContext(partId, context) { const partContext = await super._preparePartContext(partId, context); - if (partId === 'torg') { + if (partId === 'torg' || partId === 'torgChanges') { partContext.systemFields = this.document.system.schema.fields; } return partContext; } + + /* ----------------------------------------- */ + + /** + * Add a new skill change to the skill changes array + * @this {ActiveEffectConfig} + * @type {ApplicationClickAction} + */ + static async #onAddSkillChange() { + const submitData = this._processFormData(null, this.form, new FormDataExtended(this.form)); + const changes = Object.values(submitData.system.skillsAdds ?? {}); + changes.push({key: "system.skills.airVehicles.adds", value:0}); // Push the default value + return this.submit({updateData: {changes}}); + } + + /* ----------------------------------------- */ + + /** + * Delete a change from the skills changes array. + * @this {ActiveEffectConfig} + * @type {ApplicationClickAction} + */ + static async #onDeleteSkillChange(event) { + // TODO + } } \ No newline at end of file diff --git a/system.json b/system.json index c7be34332..d7912eb7a 100644 --- a/system.json +++ b/system.json @@ -1,6 +1,6 @@ { - "id": "torgeternity", - "title": "Torg Eternity", + "id": "torgeternity_dev", + "title": "Torg Eternity (DEV)", "description": "Torg Eternity System for Foundry VTT", "authors": [ { diff --git a/templates/active_effects/torg_changes.hbs b/templates/active_effects/torg_changes.hbs new file mode 100644 index 000000000..0f574ec74 --- /dev/null +++ b/templates/active_effects/torg_changes.hbs @@ -0,0 +1,63 @@ +
+ +
+ Change on Skills adds: +
    + {{#each source.system.skillsAdds as |changeSkillAdd i|}} + {{#with ../systemFields.skillsAdds as |skillAddsChanges|}} +
  1. + + + +
  2. + {{/with}} + {{/each}} +
+ +
+
+ {{formGroup systemFields.skillsFavor value=souce.system.skillsFavor rootId=rootId localize=true name="system.skillsFavor"}} +
+{{!-- +
+ Change on attribute adds: +
    + {{#each source.system.attributesAdds as |changeAttributeAdd i|}} + {{#with ../systemFields.attributesAdds as |attributesAddsChanges|}} +
  1. +
    + +
    + Value : {{changeAttributeAdd.value}} +
  2. + {{/with}} + {{/each}} +
+ +
+
+ Change on attribute favor +
    + {{#each source.system.attributesFavor as |changeAttributeFavor i|}} + {{#with ../systemFields.attributesFavor as |attributesFavorChanges|}} +
  1. +
    + +
    + Value : {{changeAttributeFavor.value}} +
  2. + {{/with}} + {{/each}} +
+ + +
--}} +
\ No newline at end of file diff --git a/templates/active-effect-torg.hbs b/templates/active_effects/torg_effects.hbs similarity index 100% rename from templates/active-effect-torg.hbs rename to templates/active_effects/torg_effects.hbs From 16fbf3b3ea5cd89ed1e4ca05ffd831251423becd Mon Sep 17 00:00:00 2001 From: r0ms Date: Sun, 1 Mar 2026 16:42:03 +0100 Subject: [PATCH 02/11] fix: almost working --- lang/de.json | 3 +- lang/en.json | 3 +- lang/es.json | 3 +- lang/fr.json | 3 +- module/config.js | 8 +- module/data/active-effect.js | 32 ++----- .../active-effect/torgActiveEffect.js | 96 +++++++++++-------- .../sheets/torgeternityActiveEffectConfig.js | 51 ++++++---- templates/active_effects/torg_changes.hbs | 9 +- 9 files changed, 118 insertions(+), 90 deletions(-) diff --git a/lang/de.json b/lang/de.json index 6a7ced5c1..d52aac720 100644 --- a/lang/de.json +++ b/lang/de.json @@ -5,7 +5,8 @@ }, "EFFECT": { "TABS": { - "torg": "Torg Eternity" + "torg": "Torg Eternity", + "torgChanges": "Changes" } }, "CHAT": { diff --git a/lang/en.json b/lang/en.json index 7fc5f529d..31535b7fd 100644 --- a/lang/en.json +++ b/lang/en.json @@ -5,7 +5,8 @@ }, "EFFECT": { "TABS": { - "torg": "Torg Eternity" + "torg": "Torg Eternity", + "torgChanges": "Changes" } }, "TYPES": { diff --git a/lang/es.json b/lang/es.json index 727e18bb9..f21275bdd 100644 --- a/lang/es.json +++ b/lang/es.json @@ -5,7 +5,8 @@ }, "EFFECT": { "TABS": { - "torg": "Torg Eternity" + "torg": "Torg Eternity", + "torgChanges": "Changes" } }, "CHAT": { diff --git a/lang/fr.json b/lang/fr.json index 74388e747..30877c691 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -5,7 +5,8 @@ }, "EFFECT": { "TABS": { - "torg": "Torg Eternity" + "torg": "Torg Eternity", + "torgChanges": "Changes" } }, "CHAT": { diff --git a/module/config.js b/module/config.js index 0d99f6194..666980d7e 100644 --- a/module/config.js +++ b/module/config.js @@ -678,10 +678,10 @@ export function initConfig() { } torgeternity.allSkillsGrouped = { - ...Object.entries(torgeternity.combatSkills).reduce((acc, ent) => { acc[ent[0]] = { label: ent[1], group: 'torgeternity.skillGroup.power' }; return acc }, {}), - ...Object.entries(torgeternity.powerSkills).reduce((acc, ent) => { acc[ent[0]] = { label: ent[1], group: 'torgeternity.skillGroup.combat' }; return acc }, {}), - ...Object.entries(torgeternity.vehiclesSkills).reduce((acc, ent) => { acc[ent[0]] = { label: ent[1], group: 'torgeternity.skillGroup.vehicle' }; return acc }, {}), - ...Object.entries(torgeternity.otherSkills).reduce((acc, ent) => { acc[ent[0]] = { label: ent[1], group: 'torgeternity.skillGroup.other' }; return acc }, {}), + ...Object.entries(torgeternity.combatSkills).reduce((acc, ent) => { acc['skillFavor.'+ent[0]] = { label: ent[1], group: 'torgeternity.skillGroup.combat' }; return acc }, {}), + ...Object.entries(torgeternity.powerSkills).reduce((acc, ent) => { acc['skillFavor.'+ent[0]] = { label: ent[1], group: 'torgeternity.skillGroup.power' }; return acc }, {}), + ...Object.entries(torgeternity.vehiclesSkills).reduce((acc, ent) => { acc['skillFavor.'+ent[0]] = { label: ent[1], group: 'torgeternity.skillGroup.vehicle' }; return acc }, {}), + ...Object.entries(torgeternity.otherSkills).reduce((acc, ent) => { acc['skillFavor.'+ent[0]] = { label: ent[1], group: 'torgeternity.skillGroup.other' }; return acc }, {}), } diff --git a/module/data/active-effect.js b/module/data/active-effect.js index 12125c408..a24d3fa3b 100644 --- a/module/data/active-effect.js +++ b/module/data/active-effect.js @@ -5,11 +5,10 @@ const fields = foundry.data.fields; const toFieldSchema = (choiceList) => new fields.ArrayField( new fields.SchemaField({ key: new fields.StringField({ - //required: true, choices: choiceList, - initial: "" , - blank:true, - nullable:true + initial: "", + blank:false, + nullable:false }), value: new fields.StringField({ initial: "0", blank: true }), mode: new fields.NumberField({ @@ -51,7 +50,6 @@ export class TorgActiveEffectData extends (foundry.data.ActiveEffectTypeDataMode static LOCALIZATION_PREFIXES = ["torgeternity.activeEffect"]; static defineSchema() { const skillAddChoices = Object.fromEntries(Object.entries(CONFIG.torgeternity.skills).map(([k,v]) => [(v+'.adds').replace('torgeternity', 'system'), v])) - //const skillFavChoices = Object.fromEntries(Object.entries(CONFIG.torgeternity.skills).map(([k,v]) => [(v).replace('torgeternity', 'system'), v])) const attributesAddsChoices = Object.fromEntries(Object.entries(CONFIG.torgeternity.attributeTypes).map(([k,v]) => [(v+'.value').replace('torgeternity', 'system'), v])) const attributesFavChoices = Object.fromEntries(Object.entries(CONFIG.torgeternity.attributeTypes).map(([k,v]) => [(v+'.isFav').replace('torgeternity', 'system'), v])) @@ -70,13 +68,12 @@ export class TorgActiveEffectData extends (foundry.data.ActiveEffectTypeDataMode applyIfDefendTrait: newTraitsField(), combatToggle: new fields.BooleanField({ initial: false, }), skillsAdds: toFieldSchema(skillAddChoices), - attributesAdds: toFieldSchema(attributesAddsChoices), + // attributesAdds: toFieldSchema(attributesAddsChoices), skillsFavor: setSkillsSchema(), - attributesFavor: toFieldSchema(attributesFavChoices), - defensesChanges: toFieldSchema(CONFIG.torgeternity.defenses), - otherChanges: toFieldSchema(["system.possibilityPerAct"]), + // attributesFavor: toFieldSchema(attributesFavChoices), + // defensesChanges: toFieldSchema(CONFIG.torgeternity.defenses), + // otherChanges: toFieldSchema(["system.possibilityPerAct"]), }) - //console.log("schema", schema) return schema; } @@ -95,19 +92,4 @@ export class TorgActiveEffectData extends (foundry.data.ActiveEffectTypeDataMode return this.system && (this.system.transferOnAttack || this.system.transferOnOutcome); } - async _preUpdate(changed, options, user) { - console.log("[Data] PreUpdate") - const result = await super._preUpdate(changed, options, user); - // Check if our SetField 'favoredSkills' is being updated - if ( "skillsFavor" in (changed.system || {}) ) { - const newSkillSet = changed.system.skillsFavor; // This is an Array or Set in v13 - const effectChanges = Array.from(newSkillSet).map(skillId => ({ - key: `system.skills.${skillId}.isFav`, - value: 'true', - mode: CONST.ACTIVE_EFFECT_MODES.OVERRIDE - })); - changed.changes = [...changed.changes, ...effectChanges] - } - return result; - } } \ No newline at end of file diff --git a/module/documents/active-effect/torgActiveEffect.js b/module/documents/active-effect/torgActiveEffect.js index a8c074eab..78fba68d5 100644 --- a/module/documents/active-effect/torgActiveEffect.js +++ b/module/documents/active-effect/torgActiveEffect.js @@ -11,6 +11,7 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { * @returns {object} the migrated data object */ static migrateData(source) { + console.log("Migrating Data", source) if (Object.hasOwn(source, 'changes')) { const migrationDictionary = { // SK and Threat attribute modifiers @@ -68,63 +69,82 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { delete source.flags.torgeternity.testOutcome; } + // Reassign system attributes, attribute, defenses and others to comprehensible foundry changes if(!source.changes){ source.changes = [] } - if(source.system.skillsFavor){ + if(!source.system){ + source.system = {} + } + if(source.system?.skillsFavor){ + const changesToUpdate = source.changes.filter((c) => (c.key.includes('skills') && c.key.includes('.isFav')) ? false : true) source.system.skillsFavor.forEach((sf) => { - source.changes.push({ - key:'system.skills.'+sf+'.isFav', - value: 'true', - mode: CONST.ACTIVE_EFFECT_MODES.OVERRIDE - }) + const changeAlreadyExists = changesToUpdate.find(c => c.key.includes(sf)) + if(!changeAlreadyExists){ + changesToUpdate.push({ + key:'system.skills.'+sf.replace('skillFavor.', '')+'.isFav', + value: 'true', + mode: CONST.ACTIVE_EFFECT_MODES.OVERRIDE + }) + } + }) + source.changes = changesToUpdate + } + + if(source.system?.skillsAdds){ + const changesToUpdate = source.changes.filter((c) => (c.key.includes('skills') && !c.key.includes('.isFav')) ? false : true) + source.system.skillsAdds.forEach((sa) => { + const changeExists = changesToUpdate.find((c) => c.key === sa.key) + if(!changeExists){ + changesToUpdate.push(sa) + } }) + source.changes = changesToUpdate } + + // Reassign changes to system skills, attribute, defenses and other to ensure + // backward compatibility const changesPerType = source.changes?.reduce((changesPerType, change) => { - // if(change.key.includes('skills') && change.key.includes('isFav')){ - // changesPerType.skillsFavor.push(change.key.replace('system.skills.', '').replace('.isFav', '')) - // return changesPerType - // } - if(change.key.includes('attributes') && change.key.includes('isFav')){ - changesPerType.attributesFavor.push(change) + if(change.key.includes('skills') && change.key.includes('isFav')){ + changesPerType.skillsFavor.push(change.key.replace('system.skills.', 'skillFavor.').replace('.isFav', '')) return changesPerType } + // if(change.key.includes('attributes') && change.key.includes('isFav')){ + // changesPerType.attributesFavor.push(change) + // return changesPerType + // } if(change.key.includes('skills') && !change.key.includes('isFav')){ changesPerType.skillsAdds.push(change) return changesPerType } - if(change.key.includes('attributes')){ - changesPerType.attributesAdds.push(change) - return changesPerType - } - if(change.key.includes('defenses')){ - changesPerType.defensesChanges.push(change) - return changesPerType - } - if(change.key.includes('other')){ - changesPerType.otherChanges.push(change) - return changesPerType - } + // } + // if(change.key.includes('attributes')){ + // changesPerType.attributesAdds.push(change) + // return changesPerType + // } + // if(change.key.includes('defenses')){ + // changesPerType.defensesChanges.push(change) + // return changesPerType + // } + // if(change.key.includes('other')){ + // changesPerType.otherChanges.push(change) + // return changesPerType + // } return changesPerType }, { skillsAdds:[], skillsFavor:[], - attributesAdds:[], - attributesFavor:[], - defensesChanges:[], - otherChanges:[] + // attributesAdds:[], + // attributesFavor:[], + // defensesChanges:[], + // otherChanges:[] }) - if(!source.system){ - source.system = {} - } source.system.skillsAdds = changesPerType.skillsAdds ?? [] - source.system.skillsFavor = source.system.skillsFavor ?? [] - source.system.attributesAdds = changesPerType.attributesAdds ?? [] - source.system.attributesFavor = changesPerType.attributesFavor ?? [] - source.system.defensesChanges = changesPerType.defensesChanges ?? [] - source.system.otherChanges = changesPerType.otherChanges ?? [] - console.log("[Document] Data Migration") - console.log(source) + source.system.skillsFavor = changesPerType.skillsFavor ?? [] + // source.system.attributesAdds = changesPerType.attributesAdds ?? [] + // source.system.attributesFavor = changesPerType.attributesFavor ?? [] + // source.system.defensesChanges = changesPerType.defensesChanges ?? [] + // source.system.otherChanges = changesPerType.otherChanges ?? [] return super.migrateData(source); } diff --git a/module/sheets/torgeternityActiveEffectConfig.js b/module/sheets/torgeternityActiveEffectConfig.js index 27b11ad35..58952b062 100644 --- a/module/sheets/torgeternityActiveEffectConfig.js +++ b/module/sheets/torgeternityActiveEffectConfig.js @@ -20,9 +20,9 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. { id: "torg", icon: "fa-solid fa-swords" }, { id: "duration", icon: "fa-solid fa-clock" }, { id: "changes", icon: "fa-solid fa-gears" }, - { id: "torgChanges", icon: "fa-solid fa-warning" }, + { id: "torgChanges", icon: "fa-solid fa-gears" }, ], - initial: "details", + initial: "torgChanges", labelPrefix: "EFFECT.TABS" }, }; @@ -35,11 +35,14 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. contentClasses: ["standard-form"], icon: "fa-solid fa-person-rays" }, - position: {width: 800}, - form: {closeOnSubmit: false}, + position: {width: 560}, + form: { + closeOnSubmit: false, + submitOnChange: true, + }, actions: { - addSkillChange: this.#onAddSkillChange, - deleSkillChange: this.#onDeleteSkillChange + addSkillAddsChange: this.#onAddSkillAddsChange, + deleteSkillAddsChange: this.#onDeleteSkillAddsChange } }; @@ -50,29 +53,45 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. } return partContext; } - - /* ----------------------------------------- */ - + /* ----------------------------------------- */ /** * Add a new skill change to the skill changes array * @this {ActiveEffectConfig} * @type {ApplicationClickAction} */ - static async #onAddSkillChange() { + static async #onAddSkillAddsChange() { const submitData = this._processFormData(null, this.form, new FormDataExtended(this.form)); - const changes = Object.values(submitData.system.skillsAdds ?? {}); - changes.push({key: "system.skills.airVehicles.adds", value:0}); // Push the default value - return this.submit({updateData: {changes}}); + const wholeChange = Object.values(submitData.system) + const skillAddsChanges = Object.values(submitData.system.skillsAdds || {}); + skillAddsChanges.push({key: "system.skills.dodge.adds", value: 0 }); // Push a default value otherwise recounciliation will skip it. + return this.submit({updateData: { + system: { + ...wholeChange, + skillsAdds : skillAddsChanges + } + } + }) } /* ----------------------------------------- */ - /** * Delete a change from the skills changes array. * @this {ActiveEffectConfig} * @type {ApplicationClickAction} */ - static async #onDeleteSkillChange(event) { - // TODO + static async #onDeleteSkillAddsChange(event) { + const submitData = this._processFormData(null, this.form, new FormDataExtended(this.form)); + const wholeChange = Object.values(submitData.system) + const changes = Object.values(submitData.system.skillsAdds); + const row = event.target.closest("li"); + const index = Number(row.dataset.skillAddsIndex) || 0; + changes.splice(index, 1); + return this.submit({updateData: { + system: { + ...wholeChange, + skillsAdds: changes + } + } + }); } } \ No newline at end of file diff --git a/templates/active_effects/torg_changes.hbs b/templates/active_effects/torg_changes.hbs index 0f574ec74..b8c5934b4 100644 --- a/templates/active_effects/torg_changes.hbs +++ b/templates/active_effects/torg_changes.hbs @@ -5,20 +5,23 @@
    {{#each source.system.skillsAdds as |changeSkillAdd i|}} {{#with ../systemFields.skillsAdds as |skillAddsChanges|}} -
  1. +
  2. +
    + +
  3. {{/with}} {{/each}}
- +
- {{formGroup systemFields.skillsFavor value=souce.system.skillsFavor rootId=rootId localize=true name="system.skillsFavor"}} + {{formGroup systemFields.skillsFavor value=source.system.skillsFavor rootId=rootId localize=true name="system.skillsFavor"}}
{{!--
From 9d10e90f9a3e0ed463d0ff6b0d0f4b6fc2d4a93a Mon Sep 17 00:00:00 2001 From: r0ms Date: Sun, 1 Mar 2026 18:00:50 +0100 Subject: [PATCH 03/11] fix: working now. added attributes --- module/config.js | 8 ++ module/data/active-effect.js | 26 ++++- .../active-effect/torgActiveEffect.js | 106 ++++++++++++------ module/documents/item/torgeternityItem.js | 1 + .../sheets/torgeternityActiveEffectConfig.js | 46 +++++++- templates/active_effects/torg_changes.hbs | 49 +++----- 6 files changed, 162 insertions(+), 74 deletions(-) diff --git a/module/config.js b/module/config.js index 666980d7e..8a8ee901d 100644 --- a/module/config.js +++ b/module/config.js @@ -684,6 +684,14 @@ export function initConfig() { ...Object.entries(torgeternity.otherSkills).reduce((acc, ent) => { acc['skillFavor.'+ent[0]] = { label: ent[1], group: 'torgeternity.skillGroup.other' }; return acc }, {}), } + torgeternity.attributesFavorAndLabel = { + "attrFavor.charisma": {label: 'torgeternity.attributes.charisma'}, + "attrFavor.dexterity": {label: 'torgeternity.attributes.dexterity'}, + "attrFavor.mind": {label: 'torgeternity.attributes.mind'}, + "attrFavor.spirit": {label: 'torgeternity.attributes.spirit'}, + "attrFavor.strength": {label: 'torgeternity.attributes.strength'}, + } + torgeternity.specificItemTraits = { // ammunition diff --git a/module/data/active-effect.js b/module/data/active-effect.js index a24d3fa3b..8bb56405b 100644 --- a/module/data/active-effect.js +++ b/module/data/active-effect.js @@ -33,6 +33,19 @@ const setSkillsSchema = () => new fields.SetField( label: "Skills favoured", initial: undefined }); + + const attributeSetSchema = () => new fields.SetField( + new fields.StringField({ + blank: false, + choices: CONFIG.torgeternity.attributesFavorAndLabel, + textSearch: true, + trim: true}), + { + nullable: false, + required: true, + label: "Attributes favoured", + initial: undefined + }) /** @@ -68,11 +81,11 @@ export class TorgActiveEffectData extends (foundry.data.ActiveEffectTypeDataMode applyIfDefendTrait: newTraitsField(), combatToggle: new fields.BooleanField({ initial: false, }), skillsAdds: toFieldSchema(skillAddChoices), - // attributesAdds: toFieldSchema(attributesAddsChoices), + attributesAdds: toFieldSchema(attributesAddsChoices), skillsFavor: setSkillsSchema(), - // attributesFavor: toFieldSchema(attributesFavChoices), - // defensesChanges: toFieldSchema(CONFIG.torgeternity.defenses), - // otherChanges: toFieldSchema(["system.possibilityPerAct"]), + attributesFavor: attributeSetSchema(), + defensesChanges: toFieldSchema(CONFIG.torgeternity.defenses), + otherChanges: toFieldSchema(["system.possibilityPerAct"]), }) return schema; } @@ -80,7 +93,10 @@ export class TorgActiveEffectData extends (foundry.data.ActiveEffectTypeDataMode static migrateData(source) { if (source.applyIfAttackTrait) source.applyIfAttackTrait = source.applyIfAttackTrait.map(t => (t === 'supernnaturalEvil') ? 'supernaturalEvil' : t) if (source.applyIfDefendTrait) source.applyIfDefendTrait = source.applyIfDefendTrait.map(t => (t === 'supernnaturalEvil') ? 'supernaturalEvil' : t) - return super.migrateData(source); + console.log("before AE migrate by foundry", source) + const migrated = super.migrateData(source); + console.log("After migrate by foundry", migrated) + return migrated } /** diff --git a/module/documents/active-effect/torgActiveEffect.js b/module/documents/active-effect/torgActiveEffect.js index 78fba68d5..b296ef27b 100644 --- a/module/documents/active-effect/torgActiveEffect.js +++ b/module/documents/active-effect/torgActiveEffect.js @@ -58,7 +58,7 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { change.value = change.value.toLowerCase(); } } - } + } // Replace flags if (source.flags?.torgeternity?.transferOnAttack !== undefined) { source.system.transferOnAttack = source.flags.torgeternity.transferOnAttack; @@ -68,15 +68,17 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { source.system.transferOnOutcome = source.flags.torgeternity.testOutcome; delete source.flags.torgeternity.testOutcome; } - - // Reassign system attributes, attribute, defenses and others to comprehensible foundry changes + // No changes made to systemField or changes, we can safely return the + // parent migration + if(!source.system && !source.changes){ + return super.migrateData(source) + } + // Changes made on systemField or Changes, if no changes, let's init it if(!source.changes){ source.changes = [] } - if(!source.system){ - source.system = {} - } - if(source.system?.skillsFavor){ + // Reassign system attributes, attribute, defenses and others to comprehensible foundry changes + if(source.system?.skillsFavor && source.changes !== undefined){ const changesToUpdate = source.changes.filter((c) => (c.key.includes('skills') && c.key.includes('.isFav')) ? false : true) source.system.skillsFavor.forEach((sf) => { const changeAlreadyExists = changesToUpdate.find(c => c.key.includes(sf)) @@ -91,7 +93,7 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { source.changes = changesToUpdate } - if(source.system?.skillsAdds){ + if(source.system?.skillsAdds && source.changes !== undefined){ const changesToUpdate = source.changes.filter((c) => (c.key.includes('skills') && !c.key.includes('.isFav')) ? false : true) source.system.skillsAdds.forEach((sa) => { const changeExists = changesToUpdate.find((c) => c.key === sa.key) @@ -102,49 +104,81 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { source.changes = changesToUpdate } + if(source.system?.attributesFavor && source.changes !== undefined){ + const changesToUpdate = source.changes.filter((c) => (c.key.includes('attributes') && c.key.includes('.isFav')) ? false : true) + source.system.attributesFavor.forEach((af) => { + const changeAlreadyExists = changesToUpdate.find(c => c.key.includes(af)) + if(!changeAlreadyExists){ + changesToUpdate.push({ + key:'system.attributes.'+af.replace('attrFavor.', '')+'.isFav', + value: 'true', + mode: CONST.ACTIVE_EFFECT_MODES.OVERRIDE + }) + } + }) + source.changes = changesToUpdate + } + + if(source.system?.attributesAdds && source.changes !== undefined){ + const changesToUpdate = source.changes.filter((c) => (c.key.includes('attributes') && !c.key.includes('.isFav')) ? false : true) + source.system.attributesAdds.forEach((aa) => { + const changeExists = changesToUpdate.find((c) => c.key === aa.key) + if(!changeExists){ + changesToUpdate.push(aa) + } + }) + source.changes = changesToUpdate + } + // Reassign changes to system skills, attribute, defenses and other to ensure - // backward compatibility + // backward compatibility an UI stay compatible + if(source.changes !== undefined){ const changesPerType = source.changes?.reduce((changesPerType, change) => { if(change.key.includes('skills') && change.key.includes('isFav')){ changesPerType.skillsFavor.push(change.key.replace('system.skills.', 'skillFavor.').replace('.isFav', '')) return changesPerType } - // if(change.key.includes('attributes') && change.key.includes('isFav')){ - // changesPerType.attributesFavor.push(change) - // return changesPerType - // } + if(change.key.includes('attributes') && change.key.includes('isFav')){ + changesPerType.attributesFavor.push(change.key.replace('system.attributes.', 'attrFavor.').replace('.isFav', '')) + return changesPerType + } if(change.key.includes('skills') && !change.key.includes('isFav')){ changesPerType.skillsAdds.push(change) return changesPerType } - // } - // if(change.key.includes('attributes')){ - // changesPerType.attributesAdds.push(change) - // return changesPerType - // } - // if(change.key.includes('defenses')){ - // changesPerType.defensesChanges.push(change) - // return changesPerType - // } - // if(change.key.includes('other')){ - // changesPerType.otherChanges.push(change) - // return changesPerType - // } + if(change.key.includes('attributes') && !change.key.includes('isFav')){ + changesPerType.attributesAdds.push(change) + return changesPerType + } + if(change.key.includes('defenses')){ + changesPerType.defensesChanges.push(change) + return changesPerType + } + if(change.key.includes('other')){ + changesPerType.otherChanges.push(change) + return changesPerType + } return changesPerType }, { skillsAdds:[], skillsFavor:[], - // attributesAdds:[], - // attributesFavor:[], - // defensesChanges:[], - // otherChanges:[] + attributesAdds:[], + attributesFavor:[], + defensesChanges:[], + otherChanges:[] }) - source.system.skillsAdds = changesPerType.skillsAdds ?? [] - source.system.skillsFavor = changesPerType.skillsFavor ?? [] - // source.system.attributesAdds = changesPerType.attributesAdds ?? [] - // source.system.attributesFavor = changesPerType.attributesFavor ?? [] - // source.system.defensesChanges = changesPerType.defensesChanges ?? [] - // source.system.otherChanges = changesPerType.otherChanges ?? [] + // Reassign for UI + source.system = { + ...(source.system ??{}), // Keep other fields change not manage by migration (attackTraits, etc.) + skillsAdds : changesPerType.skillsAdds ?? [], + skillsFavor : changesPerType.skillsFavor ?? [], + attributesAdds : changesPerType.attributesAdds ?? [], + attributesFavor : changesPerType.attributesFavor ?? [], + defensesChanges : changesPerType.defensesChanges ?? [], + otherChanges : changesPerType.otherChanges ?? [], + } + + } return super.migrateData(source); } diff --git a/module/documents/item/torgeternityItem.js b/module/documents/item/torgeternityItem.js index 68be57f57..9cbc435f0 100644 --- a/module/documents/item/torgeternityItem.js +++ b/module/documents/item/torgeternityItem.js @@ -102,6 +102,7 @@ export default class TorgeternityItem extends foundry.documents.Item { source.system.gunnerFixedSkill = parseInt(source.system.gunner.skillValue); delete source.system.gunner; } + console.log("before item migration", source) return super.migrateData(source); } diff --git a/module/sheets/torgeternityActiveEffectConfig.js b/module/sheets/torgeternityActiveEffectConfig.js index 58952b062..31261004c 100644 --- a/module/sheets/torgeternityActiveEffectConfig.js +++ b/module/sheets/torgeternityActiveEffectConfig.js @@ -42,7 +42,9 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. }, actions: { addSkillAddsChange: this.#onAddSkillAddsChange, - deleteSkillAddsChange: this.#onDeleteSkillAddsChange + deleteSkillAddsChange: this.#onDeleteSkillAddsChange, + addAttributesChange: this.#onAddAttributeChange, + deleteAttributesChange: this.#onDeleteAttributesChange } }; @@ -94,4 +96,46 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. } }); } + + /* ----------------------------------------- */ + /** + * Add a new skill change to the skill changes array + * @this {ActiveEffectConfig} + * @type {ApplicationClickAction} + */ + static async #onAddAttributeChange() { + const submitData = this._processFormData(null, this.form, new FormDataExtended(this.form)); + const wholeChange = Object.values(submitData.system) + const attributesAddsChanges = Object.values(submitData.system.attributesAdds || {}); + attributesAddsChanges.push({key: "system.attributes.strength.value", value: 0 }); // Push a default value otherwise recounciliation will skip it. + return this.submit({updateData: { + system: { + ...wholeChange, + attributesAdds : attributesAddsChanges + } + } + }) + } + + /* ----------------------------------------- */ + /** + * Delete a change from the skills changes array. + * @this {ActiveEffectConfig} + * @type {ApplicationClickAction} + */ + static async #onDeleteAttributesChange(event) { + const submitData = this._processFormData(null, this.form, new FormDataExtended(this.form)); + const wholeChange = Object.values(submitData.system) + const changes = Object.values(submitData.system.attributesAdds); + const row = event.target.closest("li"); + const index = Number(row.dataset.attributesAddsIndex) || 0; + changes.splice(index, 1); + return this.submit({updateData: { + system: { + ...wholeChange, + attributesAdds: changes + } + } + }); + } } \ No newline at end of file diff --git a/templates/active_effects/torg_changes.hbs b/templates/active_effects/torg_changes.hbs index b8c5934b4..1a7a1a140 100644 --- a/templates/active_effects/torg_changes.hbs +++ b/templates/active_effects/torg_changes.hbs @@ -23,44 +23,29 @@
{{formGroup systemFields.skillsFavor value=source.system.skillsFavor rootId=rootId localize=true name="system.skillsFavor"}}
-{{!--
- Change on attribute adds: -
    - {{#each source.system.attributesAdds as |changeAttributeAdd i|}} - {{#with ../systemFields.attributesAdds as |attributesAddsChanges|}} -
  1. -
    - + Change on Attribute Value: +
      + {{#each source.system.attributesAdds as |changeAttrAdds i|}} + {{#with ../systemFields.attributesAdds as |attributesChanges|}} +
    1. + + + +
      +
      - Value : {{changeAttributeAdd.value}}
    2. {{/with}} {{/each}}
    - +
    - Change on attribute favor -
      - {{#each source.system.attributesFavor as |changeAttributeFavor i|}} - {{#with ../systemFields.attributesFavor as |attributesFavorChanges|}} -
    1. -
      - -
      - Value : {{changeAttributeFavor.value}} -
    2. - {{/with}} - {{/each}} -
    - - -
    --}} + {{formGroup systemFields.attributesFavor value=source.system.attributesFavor rootId=rootId localize=true + name="system.attributesFavor"}} +
\ No newline at end of file From 9c452b0b66871c6423702381a8101b023f7f4fd9 Mon Sep 17 00:00:00 2001 From: r0ms Date: Sun, 1 Mar 2026 19:49:55 +0100 Subject: [PATCH 04/11] fix: some style and allow multiple input of the same skill / attr --- css/torgeternity.css | 34 +++- module/data/active-effect.js | 150 ++++++++++-------- .../active-effect/torgActiveEffect.js | 9 +- module/documents/item/torgeternityItem.js | 1 - .../sheets/torgeternityActiveEffectConfig.js | 96 ++++++++--- templates/active_effects/torg_changes.hbs | 17 +- 6 files changed, 205 insertions(+), 102 deletions(-) diff --git a/css/torgeternity.css b/css/torgeternity.css index e7eefc63f..26524641b 100644 --- a/css/torgeternity.css +++ b/css/torgeternity.css @@ -4765,6 +4765,14 @@ aside.carry-type-menu { } } +.torgeternity-active-effects.scrollable{ + --scroll-margin: 0.75rem; + margin-right: calc(-1 * var(--scroll-margin)); + padding-right: var(--scroll-margin); + overflow: hidden auto; + scrollbar-gutter: stable; +} + .torgeternity-active-effects.changes { .scrollable { display: flex; @@ -4780,10 +4788,11 @@ aside.carry-type-menu { display: flex; align-items: center; gap: 10px; + width: 100%; } .change-row select { - flex: 8; + flex: 9; height:2rem; } @@ -4794,7 +4803,28 @@ aside.carry-type-menu { .change-button { border: 1px solid; - margin-top: 12px; + margin: 1rem 0; padding: 16px 12px; } + + .torgchange-section{ + border: 1px solid; + padding: 0.5rem; + border-radius: 0.5rem; + margin: 0.5rem 0; + + h3 { + transform: translate(0, -1rem); + background: var(--color-cool-5); + display: block; + width: auto; + padding: 0 0.8rem; + display: inline-block; + } + + h4{ + color: var(--color-form-label); + margin: -1rem 0 0 0; + } + } } \ No newline at end of file diff --git a/module/data/active-effect.js b/module/data/active-effect.js index 8bb56405b..291f98a48 100644 --- a/module/data/active-effect.js +++ b/module/data/active-effect.js @@ -1,51 +1,65 @@ -import { newTraitsField } from './item/baseItemData.js'; +import { + newTraitsField +} from './item/baseItemData.js'; const fields = foundry.data.fields; const toFieldSchema = (choiceList) => new fields.ArrayField( new fields.SchemaField({ - key: new fields.StringField({ - choices: choiceList, + _id: new fields.StringField({ + initial: foundry.utils.randomID(), + blank: true, + nullable: true, + }), + key: new fields.StringField({ + choices: choiceList, initial: "", - blank:false, - nullable:false + blank: true, + nullable: false + }), + value: new fields.StringField({ + initial: "0", + blank: true }), - value: new fields.StringField({ initial: "0", blank: true }), - mode: new fields.NumberField({ - initial: CONST.ACTIVE_EFFECT_MODES.ADD, - integer: true + mode: new fields.NumberField({ + initial: CONST.ACTIVE_EFFECT_MODES.ADD, + integer: true }), - priority: new fields.NumberField({ initial: null, nullable: true }) + priority: new fields.NumberField({ + initial: null, + nullable: true + }) }) ); -const setSkillsSchema = () => new fields.SetField( - new fields.StringField({ - blank: false, - choices: CONFIG.torgeternity.allSkillsGrouped, - textSearch: true, - trim: true, - }), - { - nullable: false, - required: true, - label: "Skills favoured", - initial: undefined - }); - - const attributeSetSchema = () => new fields.SetField( - new fields.StringField({ - blank: false, - choices: CONFIG.torgeternity.attributesFavorAndLabel, - textSearch: true, - trim: true}), - { - nullable: false, - required: true, - label: "Attributes favoured", - initial: undefined - }) +const setSkillsSchema = () => new fields.SetField( + new fields.StringField({ + blank: false, + choices: CONFIG.torgeternity.allSkillsGrouped, + textSearch: true, + trim: true, + }), { + nullable: false, + required: true, + label: "Skills favoured", + initial: undefined + } +); + +const attributeSetSchema = () => new fields.SetField( + new fields.StringField({ + blank: false, + choices: CONFIG.torgeternity.attributesFavorAndLabel, + textSearch: true, + trim: true + }), { + nullable: false, + required: true, + label: "Attributes favoured", + initial: undefined + } +) /** @@ -57,45 +71,51 @@ const setSkillsSchema = () => new fields.SetField( * @param {SetField(StringField)} applyVsTrait Apply this effect to the item if the target has one of these traits. * @param {SetField(StringField)} skillsFavor Wether a skill is favor by this active effect */ -export class TorgActiveEffectData extends (foundry.data.ActiveEffectTypeDataModel ?? foundry.abstract.TypeDataModel) { +export class TorgActiveEffectData extends(foundry.data.ActiveEffectTypeDataModel ?? foundry.abstract.TypeDataModel) { // Foundry 14 - change base class to foundry.data.ActiveEffectTypeDataModel static LOCALIZATION_PREFIXES = ["torgeternity.activeEffect"]; static defineSchema() { - const skillAddChoices = Object.fromEntries(Object.entries(CONFIG.torgeternity.skills).map(([k,v]) => [(v+'.adds').replace('torgeternity', 'system'), v])) - const attributesAddsChoices = Object.fromEntries(Object.entries(CONFIG.torgeternity.attributeTypes).map(([k,v]) => [(v+'.value').replace('torgeternity', 'system'), v])) - const attributesFavChoices = Object.fromEntries(Object.entries(CONFIG.torgeternity.attributeTypes).map(([k,v]) => [(v+'.isFav').replace('torgeternity', 'system'), v])) + const skillAddChoices = Object.fromEntries(Object.entries(CONFIG.torgeternity.skills).map(([k, v]) => [(v + + '.adds').replace('torgeternity', 'system'), v])) + + const attributesAddsChoices = Object.fromEntries(Object.entries(CONFIG.torgeternity.attributeTypes).map(([k, + v + ]) => [(v + '.value').replace('torgeternity', 'system'), v])) const schema = (game.release.generation >= 14) ? foundry.data.ActiveEffectTypeDataModel.defineSchema() : {}; - Object.assign(schema, - { - // ...foundry.data.ActiveEffectTypeDataModel.defineSchema(), // Foundry 14+ - transferOnAttack: new fields.BooleanField({ initial: false, }), - transferOnOutcome: new fields.NumberField({ - choices: CONFIG.torgeternity.testOutcomeLabel, - initial: null, - integer: true, - nullable: true, - }), - applyIfAttackTrait: newTraitsField(), - applyIfDefendTrait: newTraitsField(), - combatToggle: new fields.BooleanField({ initial: false, }), - skillsAdds: toFieldSchema(skillAddChoices), - attributesAdds: toFieldSchema(attributesAddsChoices), - skillsFavor: setSkillsSchema(), - attributesFavor: attributeSetSchema(), - defensesChanges: toFieldSchema(CONFIG.torgeternity.defenses), - otherChanges: toFieldSchema(["system.possibilityPerAct"]), - }) + Object.assign(schema, { + // ...foundry.data.ActiveEffectTypeDataModel.defineSchema(), // Foundry 14+ + transferOnAttack: new fields.BooleanField({ + initial: false, + }), + transferOnOutcome: new fields.NumberField({ + choices: CONFIG.torgeternity.testOutcomeLabel, + initial: null, + integer: true, + nullable: true, + }), + applyIfAttackTrait: newTraitsField(), + applyIfDefendTrait: newTraitsField(), + combatToggle: new fields.BooleanField({ + initial: false, + }), + skillsAdds: toFieldSchema(skillAddChoices), + attributesAdds: toFieldSchema(attributesAddsChoices), + skillsFavor: setSkillsSchema(), + attributesFavor: attributeSetSchema(), + defensesChanges: toFieldSchema(CONFIG.torgeternity.defenses), + otherChanges: toFieldSchema(["system.possibilityPerAct"]), + }) return schema; } static migrateData(source) { - if (source.applyIfAttackTrait) source.applyIfAttackTrait = source.applyIfAttackTrait.map(t => (t === 'supernnaturalEvil') ? 'supernaturalEvil' : t) - if (source.applyIfDefendTrait) source.applyIfDefendTrait = source.applyIfDefendTrait.map(t => (t === 'supernnaturalEvil') ? 'supernaturalEvil' : t) - console.log("before AE migrate by foundry", source) + if (source.applyIfAttackTrait) source.applyIfAttackTrait = source.applyIfAttackTrait.map(t => (t === + 'supernnaturalEvil') ? 'supernaturalEvil' : t) + if (source.applyIfDefendTrait) source.applyIfDefendTrait = source.applyIfDefendTrait.map(t => (t === + 'supernnaturalEvil') ? 'supernaturalEvil' : t) const migrated = super.migrateData(source); - console.log("After migrate by foundry", migrated) return migrated } @@ -108,4 +128,4 @@ export class TorgActiveEffectData extends (foundry.data.ActiveEffectTypeDataMode return this.system && (this.system.transferOnAttack || this.system.transferOnOutcome); } -} \ No newline at end of file +} diff --git a/module/documents/active-effect/torgActiveEffect.js b/module/documents/active-effect/torgActiveEffect.js index b296ef27b..dff0e118a 100644 --- a/module/documents/active-effect/torgActiveEffect.js +++ b/module/documents/active-effect/torgActiveEffect.js @@ -11,7 +11,6 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { * @returns {object} the migrated data object */ static migrateData(source) { - console.log("Migrating Data", source) if (Object.hasOwn(source, 'changes')) { const migrationDictionary = { // SK and Threat attribute modifiers @@ -96,9 +95,9 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { if(source.system?.skillsAdds && source.changes !== undefined){ const changesToUpdate = source.changes.filter((c) => (c.key.includes('skills') && !c.key.includes('.isFav')) ? false : true) source.system.skillsAdds.forEach((sa) => { - const changeExists = changesToUpdate.find((c) => c.key === sa.key) + const changeExists = changesToUpdate.find((c) => c._id === sa._id) if(!changeExists){ - changesToUpdate.push(sa) + changesToUpdate.push({...sa, _id: foundry.utils.randomID()}) } }) source.changes = changesToUpdate @@ -122,9 +121,9 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { if(source.system?.attributesAdds && source.changes !== undefined){ const changesToUpdate = source.changes.filter((c) => (c.key.includes('attributes') && !c.key.includes('.isFav')) ? false : true) source.system.attributesAdds.forEach((aa) => { - const changeExists = changesToUpdate.find((c) => c.key === aa.key) + const changeExists = changesToUpdate.find((c) => c._id === aa._id) if(!changeExists){ - changesToUpdate.push(aa) + changesToUpdate.push({...aa, _id: foundry.utils.randomID()}) } }) source.changes = changesToUpdate diff --git a/module/documents/item/torgeternityItem.js b/module/documents/item/torgeternityItem.js index 9cbc435f0..68be57f57 100644 --- a/module/documents/item/torgeternityItem.js +++ b/module/documents/item/torgeternityItem.js @@ -102,7 +102,6 @@ export default class TorgeternityItem extends foundry.documents.Item { source.system.gunnerFixedSkill = parseInt(source.system.gunner.skillValue); delete source.system.gunner; } - console.log("before item migration", source) return super.migrateData(source); } diff --git a/module/sheets/torgeternityActiveEffectConfig.js b/module/sheets/torgeternityActiveEffectConfig.js index 31261004c..3b8bd15e6 100644 --- a/module/sheets/torgeternityActiveEffectConfig.js +++ b/module/sheets/torgeternityActiveEffectConfig.js @@ -2,25 +2,59 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. /** @override */ static PARTS = { - header: { template: "templates/sheets/active-effect/header.hbs" }, - tabs: { template: "templates/generic/tab-navigation.hbs" }, - details: { template: "templates/sheets/active-effect/details.hbs", scrollable: [""] }, - torg: { template: "systems/torgeternity_dev/templates/active_effects/torg_effects.hbs", scrollable: [""] }, - duration: { template: "templates/sheets/active-effect/duration.hbs" }, - changes: { template: "templates/sheets/active-effect/changes.hbs", scrollable: ["ol[data-changes]"] }, - torgChanges: { template: "systems/torgeternity_dev/templates/active_effects/torg_changes.hbs", scrollable: ["ol[data-changes]"] }, - footer: { template: "templates/generic/form-footer.hbs" } + header: { + template: "templates/sheets/active-effect/header.hbs" + }, + tabs: { + template: "templates/generic/tab-navigation.hbs" + }, + details: { + template: "templates/sheets/active-effect/details.hbs", + scrollable: [""] + }, + torg: { + template: "systems/torgeternity_dev/templates/active_effects/torg_effects.hbs", + scrollable: [""] + }, + duration: { + template: "templates/sheets/active-effect/duration.hbs" + }, + changes: { + template: "templates/sheets/active-effect/changes.hbs", + scrollable: ["ol[data-changes]"] + }, + torgChanges: { + template: "systems/torgeternity_dev/templates/active_effects/torg_changes.hbs", + scrollable: ["ol[data-changes]"] + }, + footer: { + template: "templates/generic/form-footer.hbs" + } }; /** @override */ static TABS = { sheet: { - tabs: [ - { id: "details", icon: "fa-solid fa-book" }, - { id: "torg", icon: "fa-solid fa-swords" }, - { id: "duration", icon: "fa-solid fa-clock" }, - { id: "changes", icon: "fa-solid fa-gears" }, - { id: "torgChanges", icon: "fa-solid fa-gears" }, + tabs: [{ + id: "details", + icon: "fa-solid fa-book" + }, + { + id: "torg", + icon: "fa-solid fa-swords" + }, + { + id: "duration", + icon: "fa-solid fa-clock" + }, + { + id: "changes", + icon: "fa-solid fa-gears" + }, + { + id: "torgChanges", + icon: "fa-solid fa-gears" + }, ], initial: "torgChanges", labelPrefix: "EFFECT.TABS" @@ -35,7 +69,9 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. contentClasses: ["standard-form"], icon: "fa-solid fa-person-rays" }, - position: {width: 560}, + position: { + width: 560 + }, form: { closeOnSubmit: false, submitOnChange: true, @@ -65,11 +101,16 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. const submitData = this._processFormData(null, this.form, new FormDataExtended(this.form)); const wholeChange = Object.values(submitData.system) const skillAddsChanges = Object.values(submitData.system.skillsAdds || {}); - skillAddsChanges.push({key: "system.skills.dodge.adds", value: 0 }); // Push a default value otherwise recounciliation will skip it. - return this.submit({updateData: { + skillAddsChanges.push({ + key: "system.skills.airVehicles.adds", + value: 0, + _id: foundry.utils.randomID() + }); // Push a default value otherwise recounciliation will skip it. + return this.submit({ + updateData: { system: { ...wholeChange, - skillsAdds : skillAddsChanges + skillsAdds: skillAddsChanges } } }) @@ -88,7 +129,8 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. const row = event.target.closest("li"); const index = Number(row.dataset.skillAddsIndex) || 0; changes.splice(index, 1); - return this.submit({updateData: { + return this.submit({ + updateData: { system: { ...wholeChange, skillsAdds: changes @@ -107,11 +149,16 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. const submitData = this._processFormData(null, this.form, new FormDataExtended(this.form)); const wholeChange = Object.values(submitData.system) const attributesAddsChanges = Object.values(submitData.system.attributesAdds || {}); - attributesAddsChanges.push({key: "system.attributes.strength.value", value: 0 }); // Push a default value otherwise recounciliation will skip it. - return this.submit({updateData: { + attributesAddsChanges.push({ + key: "system.attributes.charisma.value", + value: 0, + _id: foundry.utils.randomID() + }); // Push a default value otherwise recounciliation will skip it. + return this.submit({ + updateData: { system: { ...wholeChange, - attributesAdds : attributesAddsChanges + attributesAdds: attributesAddsChanges } } }) @@ -130,7 +177,8 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. const row = event.target.closest("li"); const index = Number(row.dataset.attributesAddsIndex) || 0; changes.splice(index, 1); - return this.submit({updateData: { + return this.submit({ + updateData: { system: { ...wholeChange, attributesAdds: changes @@ -138,4 +186,4 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. } }); } -} \ No newline at end of file +} diff --git a/templates/active_effects/torg_changes.hbs b/templates/active_effects/torg_changes.hbs index 1a7a1a140..cc601878a 100644 --- a/templates/active_effects/torg_changes.hbs +++ b/templates/active_effects/torg_changes.hbs @@ -1,11 +1,13 @@ -
- +
+
+

Skills:

- Change on Skills adds: +

Change on Skills adds:

    {{#each source.system.skillsAdds as |changeSkillAdd i|}} {{#with ../systemFields.skillsAdds as |skillAddsChanges|}}
  1. + @@ -23,12 +25,16 @@
    {{formGroup systemFields.skillsFavor value=source.system.skillsFavor rootId=rootId localize=true name="system.skillsFavor"}}
    +
+
+

Attributes:

- Change on Attribute Value: +

Change on Attribute Value:

    {{#each source.system.attributesAdds as |changeAttrAdds i|}} {{#with ../systemFields.attributesAdds as |attributesChanges|}}
  1. + @@ -42,10 +48,11 @@ {{/with}} {{/each}}
- +
{{formGroup systemFields.attributesFavor value=source.system.attributesFavor rootId=rootId localize=true name="system.attributesFavor"}}
+
\ No newline at end of file From 708872d6d90ea1baef0deee910a0808305f198c3 Mon Sep 17 00:00:00 2001 From: r0ms Date: Sun, 1 Mar 2026 19:58:40 +0100 Subject: [PATCH 05/11] fix: remove temporary old change template. Update translations --- lang/de.json | 6 ++++++ lang/en.json | 6 ++++++ lang/fr.json | 6 ++++++ .../sheets/torgeternityActiveEffectConfig.js | 18 +++++++++--------- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/lang/de.json b/lang/de.json index d52aac720..4836a57ae 100644 --- a/lang/de.json +++ b/lang/de.json @@ -1178,6 +1178,12 @@ "additionalDamage": "+ Schaden", "bonusDice": "BW im Voraus würfeln" }, + "skillGroup": { + "combat": "Kampf", + "power": "Kräfte", + "vehicle": "Fahrzeuge", + "other": "Sonstiges" + }, "sizes": { "large": "Groß", "normal": "Durchschnittlich", diff --git a/lang/en.json b/lang/en.json index 31535b7fd..4f42a3d37 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1172,6 +1172,12 @@ "additionalDamage": "Additional damage preset", "bonusDice": "Rolled Bonus-Dice in advance" }, + "skillGroup": { + "combat": "Combat", + "power": "Power", + "vehicle": "Vehicles", + "other": "Other" + }, "sizes": { "large": "Large", "normal": "Normal", diff --git a/lang/fr.json b/lang/fr.json index 30877c691..b17c6d588 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -1178,6 +1178,12 @@ "additionalDamage": "Dommages additionels", "bonusDice": "DB lancés par avance" }, + "skillGroup": { + "combat": "Combat", + "power": "Pouvoirs", + "vehicle": "Véhicules", + "other": "Autres" + }, "sizes": { "large": "Grande", "normal": "Normale", diff --git a/module/sheets/torgeternityActiveEffectConfig.js b/module/sheets/torgeternityActiveEffectConfig.js index 3b8bd15e6..04d1cfe97 100644 --- a/module/sheets/torgeternityActiveEffectConfig.js +++ b/module/sheets/torgeternityActiveEffectConfig.js @@ -19,10 +19,10 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. duration: { template: "templates/sheets/active-effect/duration.hbs" }, - changes: { - template: "templates/sheets/active-effect/changes.hbs", - scrollable: ["ol[data-changes]"] - }, + // changes: { + // template: "templates/sheets/active-effect/changes.hbs", + // scrollable: ["ol[data-changes]"] + // }, torgChanges: { template: "systems/torgeternity_dev/templates/active_effects/torg_changes.hbs", scrollable: ["ol[data-changes]"] @@ -47,16 +47,16 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. id: "duration", icon: "fa-solid fa-clock" }, - { - id: "changes", - icon: "fa-solid fa-gears" - }, + // { + // id: "changes", + // icon: "fa-solid fa-gears" + // }, { id: "torgChanges", icon: "fa-solid fa-gears" }, ], - initial: "torgChanges", + initial: "details", labelPrefix: "EFFECT.TABS" }, }; From 5529f9b9d41298fbe7426aa84142f5e96e2a7d05 Mon Sep 17 00:00:00 2001 From: r0ms Date: Sun, 1 Mar 2026 20:02:57 +0100 Subject: [PATCH 06/11] fix: rollback beautifier changes --- module/data/active-effect.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/module/data/active-effect.js b/module/data/active-effect.js index 291f98a48..ab5db0790 100644 --- a/module/data/active-effect.js +++ b/module/data/active-effect.js @@ -71,7 +71,7 @@ const attributeSetSchema = () => new fields.SetField( * @param {SetField(StringField)} applyVsTrait Apply this effect to the item if the target has one of these traits. * @param {SetField(StringField)} skillsFavor Wether a skill is favor by this active effect */ -export class TorgActiveEffectData extends(foundry.data.ActiveEffectTypeDataModel ?? foundry.abstract.TypeDataModel) { +export class TorgActiveEffectData extends (foundry.data.ActiveEffectTypeDataModel ?? foundry.abstract.TypeDataModel) { // Foundry 14 - change base class to foundry.data.ActiveEffectTypeDataModel static LOCALIZATION_PREFIXES = ["torgeternity.activeEffect"]; @@ -111,10 +111,8 @@ export class TorgActiveEffectData extends(foundry.data.ActiveEffectTypeDataModel } static migrateData(source) { - if (source.applyIfAttackTrait) source.applyIfAttackTrait = source.applyIfAttackTrait.map(t => (t === - 'supernnaturalEvil') ? 'supernaturalEvil' : t) - if (source.applyIfDefendTrait) source.applyIfDefendTrait = source.applyIfDefendTrait.map(t => (t === - 'supernnaturalEvil') ? 'supernaturalEvil' : t) + if (source.applyIfAttackTrait) source.applyIfAttackTrait = source.applyIfAttackTrait.map(t => (t === 'supernnaturalEvil') ? 'supernaturalEvil' : t) + if (source.applyIfDefendTrait) source.applyIfDefendTrait = source.applyIfDefendTrait.map(t => (t === 'supernnaturalEvil') ? 'supernaturalEvil' : t) const migrated = super.migrateData(source); return migrated } @@ -127,5 +125,4 @@ export class TorgActiveEffectData extends(foundry.data.ActiveEffectTypeDataModel // Don't apply the AE to the owning actor if it is being transferred on an attack return this.system && (this.system.transferOnAttack || this.system.transferOnOutcome); } - } From 0b657a6d889535bfd9abcb525fd7000ede567b0a Mon Sep 17 00:00:00 2001 From: r0ms Date: Mon, 2 Mar 2026 14:30:43 +0100 Subject: [PATCH 07/11] feat(bae): add denfeses modifier and fix data not populated on migrate at start --- lang/de.json | 11 ++++ lang/en.json | 11 ++++ lang/fr.json | 11 ++++ module/config.js | 12 ++++ module/data/active-effect.js | 31 +++++++++- .../active-effect/torgActiveEffect.js | 21 ++++++- module/documents/actor/torgeternityActor.js | 3 + .../sheets/torgeternityActiveEffectConfig.js | 57 ++++++++++++++++++- templates/active_effects/torg_changes.hbs | 31 ++++++++++ 9 files changed, 182 insertions(+), 6 deletions(-) diff --git a/lang/de.json b/lang/de.json index 4836a57ae..698ac1e16 100644 --- a/lang/de.json +++ b/lang/de.json @@ -335,6 +335,17 @@ "sub": "Das Opfer erhält sofort eine letzte, dramatische Aktion, bevor es abtritt. Verwundungsmalusse werden hierbei ignoriert." } }, + "defenses": { + "dodge": "Ausweichen", + "meleeWeapons": "Nahkampfwaffe", + "unarmedCombat": "Waffenloser Kampf", + "intimidation": "Einschüchtern", + "maneuver": "Manövrieren", + "taunt": "Verspotten", + "trick": "Tricksen", + "armor": "Rüstung", + "toughness": "Robustheit" + }, "dialogPrompts": { "cardPooled": "Im Aktionenpool?", "cosmDeckDialogLabel": "Ziehe", diff --git a/lang/en.json b/lang/en.json index 60ba4c648..087ea17db 100644 --- a/lang/en.json +++ b/lang/en.json @@ -329,6 +329,17 @@ "sub": "You get one final, dramatic action before expiring (ignoring wound penalties)" } }, + "defenses": { + "dodge": "Dodge", + "meleeWeapons": "Melee Weapons", + "unarmedCombat": "Unarmed Combat", + "intimidation": "Intimidation", + "maneuver": "Maneuver", + "taunt": "Taunt", + "trick": "Trick", + "armor": "Armor", + "toughness": "Toughness" + }, "dialogPrompts": { "cardPooled": "In Pool?", "cosmDeckDialogLabel": "Draw", diff --git a/lang/fr.json b/lang/fr.json index b17c6d588..7785afa06 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -335,6 +335,17 @@ "sub": "Vous pouvez effectuer une dernière action dramatique avant d’expirer. Vous ignorez les malus des Blessures pour ce dernier effort héroïque." } }, + "defenses": { + "dodge": "Esquive", + "meleeWeapons": "Défense en mélée", + "unarmedCombat": "Défense à mains nues", + "intimidation": "Intimidation", + "maneuver": "Manœuvre", + "taunt": "Provocation", + "trick": "Ruse", + "armor": "Armure", + "toughness": "Résistance" + }, "dialogPrompts": { "cardPooled": "Réserve d'action", "cosmDeckDialogLabel": "Piocher", diff --git a/module/config.js b/module/config.js index 8a8ee901d..f69ebda2c 100644 --- a/module/config.js +++ b/module/config.js @@ -692,6 +692,18 @@ export function initConfig() { "attrFavor.strength": {label: 'torgeternity.attributes.strength'}, } + torgeternity.defensesModAndLabel = { + "defenses.dodge.mod": {label: 'torgeternity.defenses.dodge'}, + "defenses.meleeWeapons.mod": {label: 'torgeternity.defenses.meleeWeapons'}, + "defenses.unarmedCombat.mod": {label: 'torgeternity.defenses.unarmedCombat'}, + "defenses.intimidation.mod": {label: 'torgeternity.defenses.intimidation'}, + "defenses.maneuver.mod": {label: 'torgeternity.defenses.maneuver'}, + "defenses.taunt.mod": {label: 'torgeternity.defenses.taunt'}, + "defenses.trick.mod": {label: 'torgeternity.defenses.trick'}, + "defenses.armor": {label: 'torgeternity.defenses.armor'}, + "defenses.toughness": {label: 'torgeternity.defenses.toughness'}, + } + torgeternity.specificItemTraits = { // ammunition diff --git a/module/data/active-effect.js b/module/data/active-effect.js index ab5db0790..be62e7ecd 100644 --- a/module/data/active-effect.js +++ b/module/data/active-effect.js @@ -61,6 +61,35 @@ const attributeSetSchema = () => new fields.SetField( } ) +const defensesModSchema = () => new fields.ArrayField( + new fields.SchemaField({ + _id: new fields.StringField({ + initial: foundry.utils.randomID(), + blank: true, + nullable: true, + }), + key: new fields.StringField({ + choices: CONFIG.torgeternity.defensesModAndLabel, + initial: "", + blank: true, + nullable: false + }), + value: new fields.StringField({ + initial: "0", + blank: true + }), + mode: new fields.NumberField({ + initial: CONST.ACTIVE_EFFECT_MODES.ADD, + integer: true + }), + priority: new fields.NumberField({ + initial: null, + nullable: true + }) + }) +); + + /** * Addtional fields for TorgEternity ActiveEffect @@ -104,7 +133,7 @@ export class TorgActiveEffectData extends (foundry.data.ActiveEffectTypeDataMode attributesAdds: toFieldSchema(attributesAddsChoices), skillsFavor: setSkillsSchema(), attributesFavor: attributeSetSchema(), - defensesChanges: toFieldSchema(CONFIG.torgeternity.defenses), + defensesChanges: defensesModSchema(), otherChanges: toFieldSchema(["system.possibilityPerAct"]), }) return schema; diff --git a/module/documents/active-effect/torgActiveEffect.js b/module/documents/active-effect/torgActiveEffect.js index dff0e118a..c6f24c29e 100644 --- a/module/documents/active-effect/torgActiveEffect.js +++ b/module/documents/active-effect/torgActiveEffect.js @@ -11,6 +11,7 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { * @returns {object} the migrated data object */ static migrateData(source) { + console.log("Migrating Data", source) if (Object.hasOwn(source, 'changes')) { const migrationDictionary = { // SK and Threat attribute modifiers @@ -57,6 +58,10 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { change.value = change.value.toLowerCase(); } } + // Assign to each changes a randomID as the default schema for those doesn't yield one + for(const change of source.changes){ + change._id = foundry.utils.randomID() + } } // Replace flags if (source.flags?.torgeternity?.transferOnAttack !== undefined) { @@ -85,7 +90,8 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { changesToUpdate.push({ key:'system.skills.'+sf.replace('skillFavor.', '')+'.isFav', value: 'true', - mode: CONST.ACTIVE_EFFECT_MODES.OVERRIDE + mode: CONST.ACTIVE_EFFECT_MODES.OVERRIDE, + _id: foundry.utils.randomID() }) } }) @@ -111,7 +117,8 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { changesToUpdate.push({ key:'system.attributes.'+af.replace('attrFavor.', '')+'.isFav', value: 'true', - mode: CONST.ACTIVE_EFFECT_MODES.OVERRIDE + mode: CONST.ACTIVE_EFFECT_MODES.OVERRIDE, + _id: foundry.utils.randomID() }) } }) @@ -129,6 +136,16 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { source.changes = changesToUpdate } + if(source.system?.defensesChanges && source.changes !== undefined){ + const changesToUpdate = source.changes.filter((c) => (c.key.includes('defenses')) ? false : true) + source.system.defensesChanges.forEach((dc) => { + const changeExists = changesToUpdate.find((c) => c._id === dc._id) + if(!changeExists){ + changesToUpdate.push({...dc, _id: foundry.utils.randomID()}) + } + }) + source.changes = changesToUpdate + } // Reassign changes to system skills, attribute, defenses and other to ensure // backward compatibility an UI stay compatible if(source.changes !== undefined){ diff --git a/module/documents/actor/torgeternityActor.js b/module/documents/actor/torgeternityActor.js index 46c8f3dc8..7d80e65cd 100644 --- a/module/documents/actor/torgeternityActor.js +++ b/module/documents/actor/torgeternityActor.js @@ -117,7 +117,10 @@ export default class TorgeternityActor extends foundry.documents.Actor { * @inheritdoc */ prepareDerivedData() { + console.log("applied effect (prior derived)", this.appliedEffects) super.prepareDerivedData(); + console.log("applied effect (after derived)", this.appliedEffects) + // Here Effects are applied, whatever follow cannot be directly affected by Effects // apply status effects (note that base values of 0 might have been modified by Active Effects) diff --git a/module/sheets/torgeternityActiveEffectConfig.js b/module/sheets/torgeternityActiveEffectConfig.js index 04d1cfe97..ab43d2031 100644 --- a/module/sheets/torgeternityActiveEffectConfig.js +++ b/module/sheets/torgeternityActiveEffectConfig.js @@ -80,7 +80,9 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. addSkillAddsChange: this.#onAddSkillAddsChange, deleteSkillAddsChange: this.#onDeleteSkillAddsChange, addAttributesChange: this.#onAddAttributeChange, - deleteAttributesChange: this.#onDeleteAttributesChange + deleteAttributesChange: this.#onDeleteAttributesChange, + addDefensesMod: this.#onAddDefensesMod, + deleteDefenseMod: this.#onDeleteDenfensesMod, } }; @@ -141,7 +143,7 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. /* ----------------------------------------- */ /** - * Add a new skill change to the skill changes array + * Add a new Attribute change to the attributes changes array * @this {ActiveEffectConfig} * @type {ApplicationClickAction} */ @@ -166,7 +168,7 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. /* ----------------------------------------- */ /** - * Delete a change from the skills changes array. + * Delete a change from the attrributes changes array. * @this {ActiveEffectConfig} * @type {ApplicationClickAction} */ @@ -186,4 +188,53 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. } }); } + +/* ----------------------------------------- */ + /** + * Add a new defenses modifier to the defenses changes array + * @this {ActiveEffectConfig} + * @type {ApplicationClickAction} + */ + static async #onAddDefensesMod() { + const submitData = this._processFormData(null, this.form, new FormDataExtended(this.form)); + const wholeChange = Object.values(submitData.system) + const defensesModChanges = Object.values(submitData.system.defensesChanges || {}); + defensesModChanges.push({ + key: "defenses.dodge.mod", + value: 0, + _id: foundry.utils.randomID() + }); // Push a default value otherwise recounciliation will skip it. + console.log(defensesModChanges) + return this.submit({ + updateData: { + system: { + ...wholeChange, + defensesChanges: defensesModChanges + } + } + }) + } + + /* ----------------------------------------- */ + /** + * Delete a change from the defenses mod array + * @this {ActiveEffectConfig} + * @type {ApplicationClickAction} + */ + static async #onDeleteDenfensesMod(event) { + const submitData = this._processFormData(null, this.form, new FormDataExtended(this.form)); + const wholeChange = Object.values(submitData.system) + const changes = Object.values(submitData.system.defensesChanges); + const row = event.target.closest("li"); + const index = Number(row.dataset.defensesModIndex) || 0; + changes.splice(index, 1); + return this.submit({ + updateData: { + system: { + ...wholeChange, + defensesChanges: changes + } + } + }); + } } diff --git a/templates/active_effects/torg_changes.hbs b/templates/active_effects/torg_changes.hbs index cc601878a..602e1d8f9 100644 --- a/templates/active_effects/torg_changes.hbs +++ b/templates/active_effects/torg_changes.hbs @@ -1,4 +1,5 @@
+{{!-- Skills --}}

Skills:

@@ -26,6 +27,8 @@ {{formGroup systemFields.skillsFavor value=source.system.skillsFavor rootId=rootId localize=true name="system.skillsFavor"}}
+ +{{!-- Attributes --}}

Attributes:

@@ -55,4 +58,32 @@ name="system.attributesFavor"}}
+ +{{!-- Defenses --}} +
+

Defenses:

+
+

Change a defense value:

+
    + {{#each source.system.defensesChanges as |changeDefensesMod i|}} + {{#with ../systemFields.defensesChanges as |defensesMod|}} +
  1. + + + + +
    + +
    +
  2. + {{/with}} + {{/each}} +
+ +
+
\ No newline at end of file From a7d65d2ffe4a922bfc0c73ef18a6f9334f1ba28c Mon Sep 17 00:00:00 2001 From: r0ms Date: Mon, 2 Mar 2026 16:00:42 +0100 Subject: [PATCH 08/11] feat(bae): add elemental defenses --- css/torgeternity.css | 2 +- lang/de.json | 16 ++- lang/en.json | 16 ++- lang/fr.json | 16 ++- module/config.js | 13 ++ module/data/active-effect.js | 38 +++++- .../active-effect/torgActiveEffect.js | 113 ++++++++++-------- .../sheets/torgeternityActiveEffectConfig.js | 82 ++++++++++--- templates/active_effects/torg_changes.hbs | 23 +++- 9 files changed, 243 insertions(+), 76 deletions(-) diff --git a/css/torgeternity.css b/css/torgeternity.css index 3146a83e4..715d4b714 100644 --- a/css/torgeternity.css +++ b/css/torgeternity.css @@ -4847,7 +4847,7 @@ aside.carry-type-menu { h4{ color: var(--color-form-label); - margin: -1rem 0 0 0; + margin: 12px 0; } } } \ No newline at end of file diff --git a/lang/de.json b/lang/de.json index 698ac1e16..a4fb3b26f 100644 --- a/lang/de.json +++ b/lang/de.json @@ -6,7 +6,7 @@ "EFFECT": { "TABS": { "torg": "Torg Eternity", - "torgChanges": "Changes" + "torgChanges": "Torg Changes" } }, "CHAT": { @@ -344,7 +344,19 @@ "taunt": "Verspotten", "trick": "Tricksen", "armor": "Rüstung", - "toughness": "Robustheit" + "toughness": "Robustheit", + "damageTraits" : { + "energyArmor": "Rüstung gegen Energieschaden", + "energyDefense": "Resistenz gegen Energieschaden", + "fireArmor": "Rüstung gegen Feuerschaden", + "fireDefense": "Resistenz gegen Feuerschaden", + "forceArmor": "Rüstung gegen Kraftschaden", + "forceDefense": "Resistenz gegen Kraftschaden", + "iceArmor": "Rüstung gegen Eisschaden", + "iceDefense": "Resistenz gegen Eisschaden", + "lightningArmor": "Rüstung gegen Blitzschaden", + "lightningDefense": "Resistenz gegen Blitzschaden" + } }, "dialogPrompts": { "cardPooled": "Im Aktionenpool?", diff --git a/lang/en.json b/lang/en.json index 087ea17db..4a34d0fd5 100644 --- a/lang/en.json +++ b/lang/en.json @@ -6,7 +6,7 @@ "EFFECT": { "TABS": { "torg": "Torg Eternity", - "torgChanges": "Changes" + "torgChanges": "Torg Changes" } }, "TYPES": { @@ -338,7 +338,19 @@ "taunt": "Taunt", "trick": "Trick", "armor": "Armor", - "toughness": "Toughness" + "toughness": "Toughness", + "damageTraits" : { + "energyArmor": "Armor against Energy Damage", + "energyDefense": "Toughness against Energy Dame", + "fireArmor": "Armor against Fire Damage", + "fireDefense": "Toughness against Fire Damage", + "forceArmor": "Armor against Force Damage", + "forceDefense": "Toughness against Force Damage", + "iceArmor": "Armor against Ice Damage", + "iceDefense": "Toughness against Ice Damage", + "lightningArmor": "Armor against Lightning Damage", + "lightningDefense": "Toughness against Lightning Damage" + } }, "dialogPrompts": { "cardPooled": "In Pool?", diff --git a/lang/fr.json b/lang/fr.json index 7785afa06..132f022a5 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -6,7 +6,7 @@ "EFFECT": { "TABS": { "torg": "Torg Eternity", - "torgChanges": "Changes" + "torgChanges": "Torg Changes" } }, "CHAT": { @@ -344,7 +344,19 @@ "taunt": "Provocation", "trick": "Ruse", "armor": "Armure", - "toughness": "Résistance" + "toughness": "Résistance", + "damageTraits" : { + "energyArmor": "Armure contre Arme à Énergie", + "energyDefense": "Résistance contre Arme à Énergie", + "fireArmor": "Armure contre Feu", + "fireDefense": "Résistance au Feu", + "forceArmor": "Armure contre les dégâts de Force", + "forceDefense": "Réistance au dégât de Force", + "iceArmor": "Armure contre le Froid", + "iceDefense": "Résistance au Froid", + "lightningArmor": "Armure contre l'Électricité", + "lightningDefense": "Résistance aux dégât Électrique" + } }, "dialogPrompts": { "cardPooled": "Réserve d'action", diff --git a/module/config.js b/module/config.js index f69ebda2c..5c1347117 100644 --- a/module/config.js +++ b/module/config.js @@ -704,6 +704,19 @@ export function initConfig() { "defenses.toughness": {label: 'torgeternity.defenses.toughness'}, } + torgeternity.defensesAgainstElementAndLabel = { + "defenses.damageTraits.energyArmor" : {label: 'torgeternity.defenses.damageTraits.energyArmor'}, + "defenses.damageTraits.energyDefense" : {label: 'torgeternity.defenses.damageTraits.energyDefense'}, + "defenses.damageTraits.fireArmor" : {label: 'torgeternity.defenses.damageTraits.fireArmor'}, + "defenses.damageTraits.fireDefense" : {label: 'torgeternity.defenses.damageTraits.fireDefense'}, + "defenses.damageTraits.forceArmor" : {label: 'torgeternity.defenses.damageTraits.forceArmor'}, + "defenses.damageTraits.forceDefense" : {label: 'torgeternity.defenses.damageTraits.forceDefense'}, + "defenses.damageTraits.iceArmor" : {label: 'torgeternity.defenses.damageTraits.iceArmor'}, + "defenses.damageTraits.iceDefense" : {label: 'torgeternity.defenses.damageTraits.iceDefense'}, + "defenses.damageTraits.lightningArmor" : {label: 'torgeternity.defenses.damageTraits.lightningArmor'}, + "defenses.damageTraits.lightningDefense" : {label: 'torgeternity.defenses.damageTraits.lightningDefense'}, + } + torgeternity.specificItemTraits = { // ammunition diff --git a/module/data/active-effect.js b/module/data/active-effect.js index be62e7ecd..8f647d32b 100644 --- a/module/data/active-effect.js +++ b/module/data/active-effect.js @@ -89,6 +89,34 @@ const defensesModSchema = () => new fields.ArrayField( }) ); +const elementalDefensesModSchema = () => new fields.ArrayField( + new fields.SchemaField({ + _id: new fields.StringField({ + initial: foundry.utils.randomID(), + blank: true, + nullable: true, + }), + key: new fields.StringField({ + choices: CONFIG.torgeternity.defensesAgainstElementAndLabel, + initial: "", + blank: true, + nullable: false + }), + value: new fields.StringField({ + initial: "0", + blank: true + }), + mode: new fields.NumberField({ + initial: CONST.ACTIVE_EFFECT_MODES.ADD, + integer: true + }), + priority: new fields.NumberField({ + initial: null, + nullable: true + }) + }) +); + /** @@ -105,12 +133,11 @@ export class TorgActiveEffectData extends (foundry.data.ActiveEffectTypeDataMode static LOCALIZATION_PREFIXES = ["torgeternity.activeEffect"]; static defineSchema() { - const skillAddChoices = Object.fromEntries(Object.entries(CONFIG.torgeternity.skills).map(([k, v]) => [(v + - '.adds').replace('torgeternity', 'system'), v])) + const skillAddChoices = Object.fromEntries(Object.entries(CONFIG.torgeternity.skills) + .map(([k, v]) => [(v + '.adds').replace('torgeternity', 'system'), v])) - const attributesAddsChoices = Object.fromEntries(Object.entries(CONFIG.torgeternity.attributeTypes).map(([k, - v - ]) => [(v + '.value').replace('torgeternity', 'system'), v])) + const attributesAddsChoices = Object.fromEntries(Object.entries(CONFIG.torgeternity.attributeTypes) + .map(([k,v]) => [(v + '.value').replace('torgeternity', 'system'), v])) const schema = (game.release.generation >= 14) ? foundry.data.ActiveEffectTypeDataModel.defineSchema() : {}; Object.assign(schema, { @@ -134,6 +161,7 @@ export class TorgActiveEffectData extends (foundry.data.ActiveEffectTypeDataMode skillsFavor: setSkillsSchema(), attributesFavor: attributeSetSchema(), defensesChanges: defensesModSchema(), + elementalDefenses: elementalDefensesModSchema(), otherChanges: toFieldSchema(["system.possibilityPerAct"]), }) return schema; diff --git a/module/documents/active-effect/torgActiveEffect.js b/module/documents/active-effect/torgActiveEffect.js index c6f24c29e..3f1dd412f 100644 --- a/module/documents/active-effect/torgActiveEffect.js +++ b/module/documents/active-effect/torgActiveEffect.js @@ -1,4 +1,5 @@ import { TestResult } from '../../torgchecks.js'; +import { torgeternity as config} from '../../config.js'; /** * Extend the basic ActiveEffect model with migrations and TORG specific handling @@ -72,6 +73,7 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { source.system.transferOnOutcome = source.flags.torgeternity.testOutcome; delete source.flags.torgeternity.testOutcome; } + // No changes made to systemField or changes, we can safely return the // parent migration if(!source.system && !source.changes){ @@ -110,12 +112,12 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { } if(source.system?.attributesFavor && source.changes !== undefined){ - const changesToUpdate = source.changes.filter((c) => (c.key.includes('attributes') && c.key.includes('.isFav')) ? false : true) + const changesToUpdate = source.changes.filter((c) => (c.key.includes('attributes') && c.key.includes('IsFav')) ? false : true) source.system.attributesFavor.forEach((af) => { const changeAlreadyExists = changesToUpdate.find(c => c.key.includes(af)) if(!changeAlreadyExists){ changesToUpdate.push({ - key:'system.attributes.'+af.replace('attrFavor.', '')+'.isFav', + key:'system.attributes.'+af.replace('attrFavor.', '')+'IsFav', value: 'true', mode: CONST.ACTIVE_EFFECT_MODES.OVERRIDE, _id: foundry.utils.randomID() @@ -126,7 +128,7 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { } if(source.system?.attributesAdds && source.changes !== undefined){ - const changesToUpdate = source.changes.filter((c) => (c.key.includes('attributes') && !c.key.includes('.isFav')) ? false : true) + const changesToUpdate = source.changes.filter((c) => (c.key.includes('attributes') && !c.key.includes('IsFav')) ? false : true) source.system.attributesAdds.forEach((aa) => { const changeExists = changesToUpdate.find((c) => c._id === aa._id) if(!changeExists){ @@ -137,7 +139,7 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { } if(source.system?.defensesChanges && source.changes !== undefined){ - const changesToUpdate = source.changes.filter((c) => (c.key.includes('defenses')) ? false : true) + const changesToUpdate = source.changes.filter((c) => (c.key.includes('defenses') && !c.key.includes('damageTraits')) ? false : true) source.system.defensesChanges.forEach((dc) => { const changeExists = changesToUpdate.find((c) => c._id === dc._id) if(!changeExists){ @@ -146,54 +148,71 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { }) source.changes = changesToUpdate } + + if(source.system?.elementalDefenses && source.changes !== undefined){ + const changesToUpdate = source.changes.filter((c) => (c.key.includes('defenses') && c.key.includes('damageTraits')) ? false : true) + source.system.elementalDefenses.forEach((ed) => { + const changeExists = changesToUpdate.find((c) => c._id === ed._id) + if(!changeExists){ + changesToUpdate.push({...ed, _id: foundry.utils.randomID()}) + } + }) + source.changes = changesToUpdate + } // Reassign changes to system skills, attribute, defenses and other to ensure // backward compatibility an UI stay compatible if(source.changes !== undefined){ - const changesPerType = source.changes?.reduce((changesPerType, change) => { - if(change.key.includes('skills') && change.key.includes('isFav')){ - changesPerType.skillsFavor.push(change.key.replace('system.skills.', 'skillFavor.').replace('.isFav', '')) - return changesPerType - } - if(change.key.includes('attributes') && change.key.includes('isFav')){ - changesPerType.attributesFavor.push(change.key.replace('system.attributes.', 'attrFavor.').replace('.isFav', '')) - return changesPerType - } - if(change.key.includes('skills') && !change.key.includes('isFav')){ - changesPerType.skillsAdds.push(change) - return changesPerType - } - if(change.key.includes('attributes') && !change.key.includes('isFav')){ - changesPerType.attributesAdds.push(change) - return changesPerType - } - if(change.key.includes('defenses')){ - changesPerType.defensesChanges.push(change) - return changesPerType - } - if(change.key.includes('other')){ - changesPerType.otherChanges.push(change) + const changesPerType = source.changes?.reduce((changesPerType, change) => { + if(change.key.includes('skills') && change.key.includes('isFav')){ + changesPerType.skillsFavor.push(change.key.replace('system.skills.', 'skillFavor.').replace('.isFav', '')) + return changesPerType + } + if(change.key.includes('attributes') && change.key.includes('IsFav')){ + changesPerType.attributesFavor.push(change.key.replace('system.attributes.', 'attrFavor.').replace('IsFav', '')) + console.log(changesPerType) + return changesPerType + } + if(change.key.includes('skills') && !change.key.includes('isFav')){ + changesPerType.skillsAdds.push(change) + return changesPerType + } + if(change.key.includes('attributes') && !change.key.includes('IsFav')){ + changesPerType.attributesAdds.push(change) + return changesPerType + } + if(change.key.includes('defenses') && !change.key.includes('damageTraits')){ + changesPerType.defensesChanges.push(change) + return changesPerType + } + if(change.key.includes('defenses') && change.key.includes('damageTraits')){ + changesPerType.elementalDefenses.push(change) + return changesPerType + } + if(change.key.includes('other')){ + changesPerType.otherChanges.push(change) + return changesPerType + } return changesPerType + }, { + skillsAdds:[], + skillsFavor:[], + attributesAdds:[], + attributesFavor:[], + defensesChanges:[], + elementalDefenses:[], + otherChanges:[] + }) + // Reassign for UI + source.system = { + ...(source.system ??{}), // Keep other fields change not manage by migration (attackTraits, etc.) + skillsAdds : changesPerType.skillsAdds ?? [], + skillsFavor : changesPerType.skillsFavor ?? [], + attributesAdds : changesPerType.attributesAdds ?? [], + attributesFavor : changesPerType.attributesFavor ?? [], + defensesChanges : changesPerType.defensesChanges ?? [], + elementalDefenses: changesPerType.elementalDefenses ?? [], + otherChanges : changesPerType.otherChanges ?? [], } - return changesPerType - }, { - skillsAdds:[], - skillsFavor:[], - attributesAdds:[], - attributesFavor:[], - defensesChanges:[], - otherChanges:[] - }) - // Reassign for UI - source.system = { - ...(source.system ??{}), // Keep other fields change not manage by migration (attackTraits, etc.) - skillsAdds : changesPerType.skillsAdds ?? [], - skillsFavor : changesPerType.skillsFavor ?? [], - attributesAdds : changesPerType.attributesAdds ?? [], - attributesFavor : changesPerType.attributesFavor ?? [], - defensesChanges : changesPerType.defensesChanges ?? [], - otherChanges : changesPerType.otherChanges ?? [], - } - } return super.migrateData(source); } diff --git a/module/sheets/torgeternityActiveEffectConfig.js b/module/sheets/torgeternityActiveEffectConfig.js index ab43d2031..7b5fb3560 100644 --- a/module/sheets/torgeternityActiveEffectConfig.js +++ b/module/sheets/torgeternityActiveEffectConfig.js @@ -19,19 +19,19 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. duration: { template: "templates/sheets/active-effect/duration.hbs" }, - // changes: { - // template: "templates/sheets/active-effect/changes.hbs", - // scrollable: ["ol[data-changes]"] - // }, + changes: { + template: "templates/sheets/active-effect/changes.hbs", + scrollable: ["ol[data-changes]"] + }, torgChanges: { template: "systems/torgeternity_dev/templates/active_effects/torg_changes.hbs", - scrollable: ["ol[data-changes]"] }, footer: { template: "templates/generic/form-footer.hbs" } }; + /** @override */ static TABS = { sheet: { @@ -47,14 +47,14 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. id: "duration", icon: "fa-solid fa-clock" }, - // { - // id: "changes", - // icon: "fa-solid fa-gears" - // }, { - id: "torgChanges", - icon: "fa-solid fa-gears" + id: "changes", + icon: "fa-solid fa-gear" }, + { + id: "torgChanges", + icon: "fa-solid fa-gear" + } ], initial: "details", labelPrefix: "EFFECT.TABS" @@ -70,11 +70,11 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. icon: "fa-solid fa-person-rays" }, position: { - width: 560 + width: 600 // bigger to avoid breaking tabs }, form: { - closeOnSubmit: false, - submitOnChange: true, + closeOnSubmit: true, + submitOnChange: false, }, actions: { addSkillAddsChange: this.#onAddSkillAddsChange, @@ -82,7 +82,9 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. addAttributesChange: this.#onAddAttributeChange, deleteAttributesChange: this.#onDeleteAttributesChange, addDefensesMod: this.#onAddDefensesMod, - deleteDefenseMod: this.#onDeleteDenfensesMod, + deleteDefenseMod: this.#onDeleteDefensesMod, + addElemDefenses: this.#onAddElemDefensesMod, + deleteElemDefense: this.#onDeleteElemDefensesMod } }; @@ -221,7 +223,7 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. * @this {ActiveEffectConfig} * @type {ApplicationClickAction} */ - static async #onDeleteDenfensesMod(event) { + static async #onDeleteDefensesMod(event) { const submitData = this._processFormData(null, this.form, new FormDataExtended(this.form)); const wholeChange = Object.values(submitData.system) const changes = Object.values(submitData.system.defensesChanges); @@ -237,4 +239,52 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. } }); } + + /* ----------------------------------------- */ + /** + * Add a new elemental defenses modifier to the elemental defense changes array + * @this {ActiveEffectConfig} + * @type {ApplicationClickAction} + */ + static async #onAddElemDefensesMod() { + const submitData = this._processFormData(null, this.form, new FormDataExtended(this.form)); + const wholeChange = Object.values(submitData.system) + const elementalDefensesChanges = Object.values(submitData.system.elementalDefenses || {}); + elementalDefensesChanges.push({ + key: "defenses.damageTraits.energyArmor", + value: 0, + _id: foundry.utils.randomID() + }); // Push a default value otherwise recounciliation will skip it. + return this.submit({ + updateData: { + system: { + ...wholeChange, + elementalDefenses: elementalDefensesChanges + } + } + }) + } + + /* ----------------------------------------- */ + /** + * Delete a change from the defenses mod array + * @this {ActiveEffectConfig} + * @type {ApplicationClickAction} + */ + static async #onDeleteElemDefensesMod(event) { + const submitData = this._processFormData(null, this.form, new FormDataExtended(this.form)); + const wholeChange = Object.values(submitData.system) + const changes = Object.values(submitData.system.elementalDefenses); + const row = event.target.closest("li"); + const index = Number(row.dataset.elementalDefenses) || 0; + changes.splice(index, 1); + return this.submit({ + updateData: { + system: { + ...wholeChange, + elementalDefenses: changes + } + } + }); + } } diff --git a/templates/active_effects/torg_changes.hbs b/templates/active_effects/torg_changes.hbs index 602e1d8f9..2e3f55e48 100644 --- a/templates/active_effects/torg_changes.hbs +++ b/templates/active_effects/torg_changes.hbs @@ -83,7 +83,28 @@ {{/with}} {{/each}} - + + +

Add armor or toughness against elements:

+
    + {{#each source.system.elementalDefenses as |changeElementalDef i|}} + {{#with ../systemFields.elementalDefenses as |eleDefensesMod|}} +
  1. + + + + +
    + +
    +
  2. + {{/with}} + {{/each}} +
+
\ No newline at end of file From 15a0934bfb07784816eddb8a600a65658045beaa Mon Sep 17 00:00:00 2001 From: r0ms Date: Mon, 2 Mar 2026 19:27:37 +0100 Subject: [PATCH 09/11] feat(bae): add others changes (missing cosms and vehicles for now) --- lang/de.json | 7 +++ lang/en.json | 7 +++ lang/fr.json | 7 +++ module/config.js | 27 ++++++++++ module/data/active-effect.js | 30 ++++++++++- .../active-effect/torgActiveEffect.js | 26 ++++++++-- .../sheets/torgeternityActiveEffectConfig.js | 52 ++++++++++++++++++- templates/active_effects/torg_changes.hbs | 30 +++++++++++ 8 files changed, 180 insertions(+), 6 deletions(-) diff --git a/lang/de.json b/lang/de.json index a4fb3b26f..7fbf2b833 100644 --- a/lang/de.json +++ b/lang/de.json @@ -688,6 +688,13 @@ "reachedMaximumAttr": "Du hast das Attributsmaximum, dass dein Volk vorgibt, erreicht. Eine weitere Erhöhung ist nicht möglich.", "clipEmpty": "Diese Munition ist leer und kann nicht zum Nachladen verwendet werden." }, + "otherActiveEffectsChanges": { + "movement": "Movement", + "health": "Heatlh", + "damageAndTest": "Damages and Test", + "axiomsAndReality": "Axioms and Reality", + "others": "Others" + }, "packs": { "basicRules": "torgeternity.system-de-basisregeln", "decks": "torgeternity.system-de-grundkarten" diff --git a/lang/en.json b/lang/en.json index 4a34d0fd5..418bedfc1 100644 --- a/lang/en.json +++ b/lang/en.json @@ -682,6 +682,13 @@ "reachedMaximumAttr": "You have reached the attribute maximum specified by your race. A further increase is not possible.", "clipEmpty": "This ammunition is empty and cannot be used for reloading." }, + "otherActiveEffectsChanges": { + "movement": "Movement", + "health": "Heatlh", + "damageAndTest": "Damages and Test", + "axiomsAndReality": "Axioms and Reality", + "others": "Others" + }, "packs": { "basicRules": "torgeternity.basic-rules", "decks": "torgeternity.core-card-set" diff --git a/lang/fr.json b/lang/fr.json index 132f022a5..4ab6f5474 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -688,6 +688,13 @@ "reachedMaximumAttr": "Tu as atteint le maximum d'attributs que ton peuple a défini. Une augmentation supplémentaire n'est pas possible.", "clipEmpty": "Ces munitions sont vides et ne peuvent pas être utilisées pour recharger." }, + "otherActiveEffectsChanges": { + "movement": "Déplacement", + "health": "Santé", + "damageAndTest": "Dégât et Tests", + "axiomsAndReality": "Axiomes and Réalité", + "others": "Autres" + }, "packs": { "basicRules": "torgeternity.basic-rules-fr", "decks": "torgeternity.core-card-set-fr" diff --git a/module/config.js b/module/config.js index 5c1347117..9744ba71d 100644 --- a/module/config.js +++ b/module/config.js @@ -717,6 +717,33 @@ export function initConfig() { "defenses.damageTraits.lightningDefense" : {label: 'torgeternity.defenses.damageTraits.lightningDefense'}, } + torgeternity.otherChangesGroupedWithLabels = { + //Movement + "system.other.moveMod" : {label : "Move", group:"torgeternity.otherActiveEffectsChanges.movement"}, + "system.other.runMod" : {label : "Run", group:"torgeternity.otherActiveEffectsChanges.movement"}, + //Health + "fatigue": {label :"Fatigue", group:"torgeternity.otherActiveEffectsChanges.health"}, + "system.shock.max": {label :"Schock Max", group:"torgeternity.otherActiveEffectsChanges.health"}, + "system.wounds.max": {label :"Wounds Max", group:"torgeternity.otherActiveEffectsChanges.health"}, + //Damage and Tests + "system.unarmedDamageMod" : {label:"Unarmed Damage", group:"torgeternity.otherActiveEffectsChanges.damageAndTest"}, + "test.damage" : {label:"Test Damage", group:"torgeternity.otherActiveEffectsChanges.damageAndTest"}, + "test.weaponAP" : {label:"Weapon Armor Piercing", group:"torgeternity.otherActiveEffectsChanges.damageAndTest"}, + "test.wounds" : {label:"Test Wounds", group:"torgeternity.otherActiveEffectsChanges.damageAndTest"}, + "test.shock" : {label:"Test Schock", group:"torgeternity.otherActiveEffectsChanges.damageAndTest"}, + //Axioms and Reality + "system.axioms.magic": {label:"Magic Axiom", group:"torgeternity.otherActiveEffectsChanges.axiomsAndReality"}, + "system.axioms.social": {label:"Social Axiom", group:"torgeternity.otherActiveEffectsChanges.axiomsAndReality"}, + "system.axioms.spirit": {label:"Spirit Axiom", group:"torgeternity.otherActiveEffectsChanges.axiomsAndReality"}, + "system.axioms.tech": {label:"Tech Axiom", group:"torgeternity.otherActiveEffectsChanges.axiomsAndReality"}, + "system.other.possibilities.perAct": {label:"Possibilities per act", group:"torgeternity.otherActiveEffectsChanges.axiomsAndReality"}, + //Others + "system.other.maxDex":{label:"Max Dexterity", group:"torgeternity.otherActiveEffectsChanges.others"}, + "system.other.minStr":{label:"Min Strength", group:"torgeternity.otherActiveEffectsChanges.others"}, + "targetModifiers.darkness": {label:"Darkness Modifier", group:"torgeternity.otherActiveEffectsChanges.others"} + } + + torgeternity.specificItemTraits = { // ammunition diff --git a/module/data/active-effect.js b/module/data/active-effect.js index 8f647d32b..ea42700f3 100644 --- a/module/data/active-effect.js +++ b/module/data/active-effect.js @@ -117,6 +117,34 @@ const elementalDefensesModSchema = () => new fields.ArrayField( }) ); +const otherActiveEffectsChangesSchema = () => new fields.ArrayField( + new fields.SchemaField({ + _id: new fields.StringField({ + initial: foundry.utils.randomID(), + blank: true, + nullable: true, + }), + key: new fields.StringField({ + choices: CONFIG.torgeternity.otherChangesGroupedWithLabels, + initial: "", + blank: true, + nullable: false + }), + value: new fields.StringField({ + initial: "0", + blank: true + }), + mode: new fields.NumberField({ + initial: CONST.ACTIVE_EFFECT_MODES.ADD, + integer: true + }), + priority: new fields.NumberField({ + initial: null, + nullable: true + }) + }) +); + /** @@ -162,7 +190,7 @@ export class TorgActiveEffectData extends (foundry.data.ActiveEffectTypeDataMode attributesFavor: attributeSetSchema(), defensesChanges: defensesModSchema(), elementalDefenses: elementalDefensesModSchema(), - otherChanges: toFieldSchema(["system.possibilityPerAct"]), + otherChanges: otherActiveEffectsChangesSchema(), }) return schema; } diff --git a/module/documents/active-effect/torgActiveEffect.js b/module/documents/active-effect/torgActiveEffect.js index 3f1dd412f..0ac23c6df 100644 --- a/module/documents/active-effect/torgActiveEffect.js +++ b/module/documents/active-effect/torgActiveEffect.js @@ -1,6 +1,16 @@ import { TestResult } from '../../torgchecks.js'; import { torgeternity as config} from '../../config.js'; +const OTHER_AE_KEY_FRAGMENTS = [ +"system.other", +"fatigue", +"system.shock", +"system.wounds", +"test", +"system.axioms", +"targetModifiers", +] + /** * Extend the basic ActiveEffect model with migrations and TORG specific handling */ @@ -159,6 +169,17 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { }) source.changes = changesToUpdate } + + if(source.system?.otherChanges && source.changes !== undefined){ + const changesToUpdate = source.changes.filter((c) => (OTHER_AE_KEY_FRAGMENTS.some(otherKey => c.key.includes(otherKey))) ? false : true) + source.system.otherChanges.forEach((ed) => { + const changeExists = changesToUpdate.find((c) => c._id === ed._id) + if(!changeExists){ + changesToUpdate.push({...ed, _id: foundry.utils.randomID()}) + } + }) + source.changes = changesToUpdate + } // Reassign changes to system skills, attribute, defenses and other to ensure // backward compatibility an UI stay compatible if(source.changes !== undefined){ @@ -169,7 +190,6 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { } if(change.key.includes('attributes') && change.key.includes('IsFav')){ changesPerType.attributesFavor.push(change.key.replace('system.attributes.', 'attrFavor.').replace('IsFav', '')) - console.log(changesPerType) return changesPerType } if(change.key.includes('skills') && !change.key.includes('isFav')){ @@ -188,11 +208,8 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { changesPerType.elementalDefenses.push(change) return changesPerType } - if(change.key.includes('other')){ changesPerType.otherChanges.push(change) return changesPerType - } - return changesPerType }, { skillsAdds:[], skillsFavor:[], @@ -202,6 +219,7 @@ export default class TorgActiveEffect extends foundry.documents.ActiveEffect { elementalDefenses:[], otherChanges:[] }) + console.log(source) // Reassign for UI source.system = { ...(source.system ??{}), // Keep other fields change not manage by migration (attackTraits, etc.) diff --git a/module/sheets/torgeternityActiveEffectConfig.js b/module/sheets/torgeternityActiveEffectConfig.js index 7b5fb3560..74af102e7 100644 --- a/module/sheets/torgeternityActiveEffectConfig.js +++ b/module/sheets/torgeternityActiveEffectConfig.js @@ -84,7 +84,9 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. addDefensesMod: this.#onAddDefensesMod, deleteDefenseMod: this.#onDeleteDefensesMod, addElemDefenses: this.#onAddElemDefensesMod, - deleteElemDefense: this.#onDeleteElemDefensesMod + deleteElemDefense: this.#onDeleteElemDefensesMod, + deleteOtherChange: this.#onDeleteOtherChange, + addOtherChange: this.#onAddOtherChange, } }; @@ -287,4 +289,52 @@ export default class TorgActiveEffectConfig extends foundry.applications.sheets. } }); } + + /* ----------------------------------------- */ + /** + * Add a new elemental defenses modifier to the elemental defense changes array + * @this {ActiveEffectConfig} + * @type {ApplicationClickAction} + */ + static async #onAddOtherChange() { + const submitData = this._processFormData(null, this.form, new FormDataExtended(this.form)); + const wholeChange = Object.values(submitData.system) + const otherChanges = Object.values(submitData.system.otherChanges || {}); + otherChanges.push({ + key: "system.other.moveMod", + value: 0, + _id: foundry.utils.randomID() + }); // Push a default value otherwise recounciliation will skip it. + return this.submit({ + updateData: { + system: { + ...wholeChange, + otherChanges: otherChanges + } + } + }) + } + + /* ----------------------------------------- */ + /** + * Delete a change from the defenses mod array + * @this {ActiveEffectConfig} + * @type {ApplicationClickAction} + */ + static async #onDeleteOtherChange(event) { + const submitData = this._processFormData(null, this.form, new FormDataExtended(this.form)); + const wholeChange = Object.values(submitData.system) + const changes = Object.values(submitData.system.otherChanges); + const row = event.target.closest("li"); + const index = Number(row.dataset.otherChanges) || 0; + changes.splice(index, 1); + return this.submit({ + updateData: { + system: { + ...wholeChange, + otherChanges: changes + } + } + }); + } } diff --git a/templates/active_effects/torg_changes.hbs b/templates/active_effects/torg_changes.hbs index 2e3f55e48..8d1118d22 100644 --- a/templates/active_effects/torg_changes.hbs +++ b/templates/active_effects/torg_changes.hbs @@ -1,3 +1,4 @@ +{{!-- TODO: Split to parts! --}}
{{!-- Skills --}}
@@ -107,4 +108,33 @@
+ +{{!-- Others --}} +
+

Others:

+

Here lies what cannot be regrouped easily such as tests modifier, health modifier, axioms etc.

+
+

Change on Attribute Value:

+
    + {{#each source.system.otherChanges as |otherChange i|}} + {{#with ../systemFields.otherChanges as |otherChangesField|}} +
  1. + + + + +
    + +
    +
  2. + {{/with}} + {{/each}} +
+ +
+
\ No newline at end of file From 079fa63d23322b7f16d88cc570a1a1fd84bacd1c Mon Sep 17 00:00:00 2001 From: r0ms Date: Tue, 3 Mar 2026 19:08:14 +0100 Subject: [PATCH 10/11] feat(i18n): add localization --- lang/de.json | 46 ++++++++++++++++++++++- lang/en.json | 46 ++++++++++++++++++++++- lang/fr.json | 46 ++++++++++++++++++++++- module/data/active-effect.js | 4 +- templates/active_effects/torg_changes.hbs | 33 ++++++++-------- 5 files changed, 155 insertions(+), 20 deletions(-) diff --git a/lang/de.json b/lang/de.json index 7fbf2b833..43b1f11a2 100644 --- a/lang/de.json +++ b/lang/de.json @@ -1206,7 +1206,51 @@ "backlash2Tooltip": "1 Schock anwenden", "backlash3Tooltip": "Sehr Angeschlagen anwenden", "additionalDamage": "+ Schaden", - "bonusDice": "BW im Voraus würfeln" + "bonusDice": "BW im Voraus würfeln", + "activeEffect": { + "skills": { + "title": "Fertigkeiten", + "description": "Wenn du Fertigkeitsboni ändern oder sie als bevorzugt markieren möchtest.", + "skillAdds": { + "label": "Fertigkeitsboni:", + "cta": "+ Fertigkeitsbonus hinzufügen" + }, + "skillsFavour": { + "label": "Bevorzugte Fertigkeiten:" + } + }, + "attributes": { + "title": "Attribute", + "description": "Wenn du Attributswerte ändern oder sie als bevorzugt markieren möchtest.", + "attributesValue": { + "label": "Attributswerte:", + "cta": "+ Attributswert-Änderung hinzufügen" + }, + "attributesFavor": { + "label": "Bevorzugte Attribute:" + } + }, + "defenses": { + "title": "Verteidigung", + "description": "Wenn du Rüstungs- oder Widerstandswerte global oder gegen bestimmte Elemente ändern möchtest.", + "defensesMod": { + "label": "Verteidigungsmodifikator", + "cta": "+ Verteidigungsmodifikator hinzufügen" + }, + "elements": { + "label": "Elementare Verteidigung", + "cta": "+ Elementaren Verteidigungsmodifikator hinzufügen" + } + }, + "other": { + "title": "Sonstiges", + "description": "Sonstige Änderungen, die nicht kategorisiert werden können, wie Möglichkeiten, Axiome, Gesundheit, Bewegung usw. Diese wurden hier zusammengefasst.", + "otherChanges": { + "label": "Sonstige Änderung", + "cta": "+ Sonstige Änderung hinzufügen" + } + } + } }, "skillGroup": { "combat": "Kampf", diff --git a/lang/en.json b/lang/en.json index 418bedfc1..1999d6905 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1200,7 +1200,51 @@ "backlash2Tooltip": "Apply 1 shock", "backlash3Tooltip": "Apply Very Stymied", "additionalDamage": "Additional damage preset", - "bonusDice": "Rolled Bonus-Dice in advance" + "bonusDice": "Rolled Bonus-Dice in advance", + "activeEffect": { + "skills": { + "title": "Skills", + "description": "If you want to modify adds to skills or make them favored.", + "skillAdds": { + "label": "Skills adds:", + "cta": "+ Add a skill adds change" + }, + "skillsFavour": { + "label": "Skills Favored:" + } + }, + "attributes": { + "title": "Attributes", + "description": "If you want to modify attributes value or make them favored.", + "attributesValue": { + "label": "Attributes values:", + "cta": "+ Add an attribute value change" + }, + "attributesFavor": { + "label": "Attributes Favored:" + } + }, + "defenses": { + "title": "Defenses", + "description": "If you want to modify Armor or Toughness modifier globally or against certain elements", + "defensesMod": { + "label": "Defenses modifier", + "cta": "+ Add a Defense modifier" + }, + "elements": { + "label": "Elemental defense", + "cta": "+ Add an Elemental defense modifier" + } + }, + "other": { + "title": "Miscellaneous", + "description": "Other changes cannot be categorized such as Possibilities, Axiom, Health, Movement, etc. Those have been regrouped here.", + "otherChanges": { + "label": "Other change", + "cta": "+ Add a Miscellaneous change" + } + } + } }, "skillGroup": { "combat": "Combat", diff --git a/lang/fr.json b/lang/fr.json index 4ab6f5474..0be0f99d0 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -1206,7 +1206,51 @@ "backlash2Tooltip": "Appliquer 1 Choc", "backlash3Tooltip": "Appliquer Très Déstabilisé", "additionalDamage": "Dommages additionels", - "bonusDice": "DB lancés par avance" + "bonusDice": "DB lancés par avance", + "activeEffect": { + "skills": { + "title": "Compétences", + "description": "Pour augmenter ou diminuer le rang d'une ou plusieurs compétences ou les rendre favorisées.", + "skillAdds": { + "label": "Rand de compétence:", + "cta": "+ Ajouter une modification de rang" + }, + "skillsFavour": { + "label": "Compétences favorisées:" + } + }, + "attributes": { + "title": "Attributes", + "description": "Pour augmenter ou diminuer la valeur d'un ou plusieurs attributs ou les rendre favorisés", + "attributesValue": { + "label": "Valeur d'attribut :", + "cta": "+ Ajouter une modification de valeur" + }, + "attributesFavor": { + "label": "Attributs favorisés:" + } + }, + "defenses": { + "title": "Défenses", + "description": "Pour augmenter ou dominuer les différents modificateur de défenses ainsi que les résistances aux éléments", + "defensesMod": { + "label": "Modificateur de défense", + "cta": "+ Ajouter un modificateur de défense" + }, + "elements": { + "label": "Défense Élémentaire", + "cta": "+ Ajouter un modificateur de défense élémentaire" + } + }, + "other": { + "title": "Divers", + "description": "Toutes les modifications ne peuvent pas être regroupée (Possibilités, Axiomes, Mouvement, Dégâts) et ont été regroupée ci-dessous", + "otherChanges": { + "label": "Autre modification", + "cta": "+ Ajouter une modification diverse" + } + } + } }, "skillGroup": { "combat": "Combat", diff --git a/module/data/active-effect.js b/module/data/active-effect.js index ea42700f3..7d50cfa4b 100644 --- a/module/data/active-effect.js +++ b/module/data/active-effect.js @@ -42,7 +42,7 @@ const setSkillsSchema = () => new fields.SetField( }), { nullable: false, required: true, - label: "Skills favoured", + label: "torgeternity.sheet.activeEffect.skills.skillsFavour.label", initial: undefined } ); @@ -56,7 +56,7 @@ const attributeSetSchema = () => new fields.SetField( }), { nullable: false, required: true, - label: "Attributes favoured", + label: "torgeternity.sheet.activeEffect.attributes.attributesFavor.label", initial: undefined } ) diff --git a/templates/active_effects/torg_changes.hbs b/templates/active_effects/torg_changes.hbs index 8d1118d22..60cd7efd8 100644 --- a/templates/active_effects/torg_changes.hbs +++ b/templates/active_effects/torg_changes.hbs @@ -2,9 +2,10 @@
{{!-- Skills --}}
-

Skills:

+

{{localize "torgeternity.sheetLabels.activeEffect.skills.title"}}

+

{{localize "torgeternity.sheetLabels.activeEffect.skills.description"}}

-

Change on Skills adds:

+

{{localize "torgeternity.sheetLabels.activeEffect.skills.skillAdds.label"}}

    {{#each source.system.skillsAdds as |changeSkillAdd i|}} {{#with ../systemFields.skillsAdds as |skillAddsChanges|}} @@ -22,7 +23,7 @@ {{/with}} {{/each}}
- +
{{formGroup systemFields.skillsFavor value=source.system.skillsFavor rootId=rootId localize=true name="system.skillsFavor"}} @@ -31,9 +32,10 @@ {{!-- Attributes --}}
-

Attributes:

+

{{localize "torgeternity.sheetLabels.activeEffect.attributes.title"}}

+

{{localize "torgeternity.sheetLabels.activeEffect.attributes.description"}}

-

Change on Attribute Value:

+

{{localize "torgeternity.sheetLabels.activeEffect.attributes.attributesValue.label"}}

    {{#each source.system.attributesAdds as |changeAttrAdds i|}} {{#with ../systemFields.attributesAdds as |attributesChanges|}} @@ -52,7 +54,7 @@ {{/with}} {{/each}}
- +
{{formGroup systemFields.attributesFavor value=source.system.attributesFavor rootId=rootId localize=true @@ -62,9 +64,10 @@ {{!-- Defenses --}}
-

Defenses:

+

{{localize "torgeternity.sheetLabels.activeEffect.defenses.title"}}

+

{{localize "torgeternity.sheetLabels.activeEffect.defenses.description"}}

-

Change a defense value:

+

{{localize "torgeternity.sheetLabels.activeEffect.defenses.defensesMod.label"}}

    {{#each source.system.defensesChanges as |changeDefensesMod i|}} {{#with ../systemFields.defensesChanges as |defensesMod|}} @@ -84,9 +87,9 @@ {{/with}} {{/each}}
- + -

Add armor or toughness against elements:

+

{{localize "torgeternity.sheetLabels.activeEffect.defenses.elements.label"}}

    {{#each source.system.elementalDefenses as |changeElementalDef i|}} {{#with ../systemFields.elementalDefenses as |eleDefensesMod|}} @@ -105,16 +108,16 @@ {{/with}} {{/each}}
- +
{{!-- Others --}}
-

Others:

-

Here lies what cannot be regrouped easily such as tests modifier, health modifier, axioms etc.

+

{{localize "torgeternity.sheetLabels.activeEffect.other.title"}}

+

{{localize "torgeternity.sheetLabels.activeEffect.other.description"}}

-

Change on Attribute Value:

+

{{localize "torgeternity.sheetLabels.activeEffect.other.otherChanges.label"}}

    {{#each source.system.otherChanges as |otherChange i|}} {{#with ../systemFields.otherChanges as |otherChangesField|}} @@ -134,7 +137,7 @@ {{/with}} {{/each}}
- +
\ No newline at end of file From 4069b2a9ba482fb0738ed5395ba2fdae9f4cdb39 Mon Sep 17 00:00:00 2001 From: r0ms Date: Tue, 3 Mar 2026 19:16:19 +0100 Subject: [PATCH 11/11] fix(i18n): fix label for favor skill and favor attributes --- lang/de.json | 6 ++++++ lang/en.json | 6 ++++++ lang/fr.json | 6 ++++++ module/data/active-effect.js | 2 -- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lang/de.json b/lang/de.json index 43b1f11a2..b5ea58069 100644 --- a/lang/de.json +++ b/lang/de.json @@ -54,6 +54,12 @@ "applyIfDefendTrait": { "label": "Anwenden bei Verteidiger-Eigenschaft", "hint": "Effekt wird nur angewendet, wenn der angegriffene Token (das Ziel) einen der angegebenen Eigenschaften besitzt." + }, + "skillsFavour": { + "label": "Bevorzugte Fertigkeiten:" + }, + "attributesFavor": { + "label": "Bevorzugte Attribute:" } } }, diff --git a/lang/en.json b/lang/en.json index 1999d6905..f94a32ee6 100644 --- a/lang/en.json +++ b/lang/en.json @@ -48,6 +48,12 @@ "applyIfDefendTrait": { "label": "Apply If Defend Trait", "hint": "Apply the effect only if the attacked token (the target) has one of these traits" + }, + "skillsFavor":{ + "label": "Skills Favored:" + }, + "attributesFavor": { + "label": "Attributes Favored:" } } }, diff --git a/lang/fr.json b/lang/fr.json index 0be0f99d0..cd4af5ea2 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -54,6 +54,12 @@ "applyIfDefendTrait": { "label": "Appliquer le trait de défense", "hint": "Appliquer l'Effet uniquement si le Token attaqué (la cible) possède l'un de ces traits" + }, + "skillsFavor":{ + "label": "Compétences favorisées:" + }, + "attributesFavor": { + "label": "Attributs favorisés:" } } }, diff --git a/module/data/active-effect.js b/module/data/active-effect.js index 7d50cfa4b..d22af78fb 100644 --- a/module/data/active-effect.js +++ b/module/data/active-effect.js @@ -42,7 +42,6 @@ const setSkillsSchema = () => new fields.SetField( }), { nullable: false, required: true, - label: "torgeternity.sheet.activeEffect.skills.skillsFavour.label", initial: undefined } ); @@ -56,7 +55,6 @@ const attributeSetSchema = () => new fields.SetField( }), { nullable: false, required: true, - label: "torgeternity.sheet.activeEffect.attributes.attributesFavor.label", initial: undefined } )