From 568b1b4f581be3574ea7129113cb15eb4e6e2b25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Wed, 27 Mar 2024 19:12:29 +0100 Subject: [PATCH 01/25] fix #42 --- lang/en-EN.json | 8 +- lang/fr-FR.json | 8 +- modules/DicePool.js | 6 +- modules/applications/DicePoolBuilder.js | 34 ++++++-- .../actors/WFRP3eCharacterSheet.js | 54 +++++------- modules/documents/WFRP3eItem.js | 39 ++++++++- styles/less/components/character_sheet.less | 36 ++++++++ styles/less/components/dice_pool_builder.less | 1 + .../applications/actors/character-sheet.hbs | 4 +- templates/applications/dice-pool-builder.hbs | 16 ++++ templates/applications/items/skill-sheet.hbs | 33 +++++-- templates/partials/item-armour-row.hbs | 18 +++- templates/partials/item-skill-row.hbs | 86 +++++++++++-------- templates/partials/item-trapping-row.hbs | 4 +- templates/partials/item-weapon-row.hbs | 24 ++++-- 15 files changed, 266 insertions(+), 105 deletions(-) diff --git a/lang/en-EN.json b/lang/en-EN.json index 11709c2..ce84409 100644 --- a/lang/en-EN.json +++ b/lang/en-EN.json @@ -414,6 +414,7 @@ "ROLL.DICEPOOLBUILDER.Hint": "Left click to increase dice, right click to decrease.", "ROLL.DICEPOOLBUILDER.Options": "Options", "ROLL.DICEPOOLBUILDER.RollCheck": "Roll check", + "ROLL.DICEPOOLBUILDER.Specialisations": "Specialisations", "ROLL.DICEPOOLBUILDER.Skill": "Skill", "ROLL.DICEPOOLBUILDER.StartingResults": "Starting results", "ROLL.DICEPOOLBUILDER.Weapon": "Weapon", @@ -455,8 +456,13 @@ "ROLL.UNIVERSAL.MentalBane": "Suffer 1 stress", "ROLL.UNIVERSAL.SigmarsComet": "+1 critical", - "SKILL.Characteristic": "Characteristic", "SKILL.AdvancedSkill": "Advanced Skill", + "SKILL.Characteristic": "Characteristic", + "SKILL.Name": "Name", + "SKILL.SpecialisationList": "Specialisations: {specialisations}", + "SKILL.Specialisations": "Specialisations", + "SKILL.TrainingLevel": "Training Level", + "SKILL.ABBREVIATION.Characteristic": "Char", "TALENT.AvailableSocket": "Available {type} Socket", "TALENT.TakenSocket": "{type} Socket taken by {talent}", diff --git a/lang/fr-FR.json b/lang/fr-FR.json index 40366c2..ee1b116 100644 --- a/lang/fr-FR.json +++ b/lang/fr-FR.json @@ -414,6 +414,7 @@ "ROLL.DICEPOOLBUILDER.Hint": "Clic gauche pour ajouter des dés, clic droit pour en retirer.", "ROLL.DICEPOOLBUILDER.Options": "Options", "ROLL.DICEPOOLBUILDER.RollCheck": "Lancer le test", + "ROLL.DICEPOOLBUILDER.Specialisations": "Spécialisations", "ROLL.DICEPOOLBUILDER.Skill": "Skill", "ROLL.DICEPOOLBUILDER.StartingResults": "Pictogrammes de départ", "ROLL.DICEPOOLBUILDER.Weapon": "Arme", @@ -455,8 +456,13 @@ "ROLL.UNIVERSAL.MentalBane": "Suffer 1 stress", "ROLL.UNIVERSAL.SigmarsComet": "+1 critical", - "SKILL.Characteristic": "Caractéristique", "SKILL.AdvancedSkill": "Compétence Avancée", + "SKILL.Characteristic": "Caractéristique", + "SKILL.Name": "Nom", + "SKILL.SpecialisationList": "Spécialisations : {specialisations}", + "SKILL.Specialisations": "Spécialisations", + "SKILL.TrainingLevel": "Formation", + "SKILL.ABBREVIATION.Characteristic": "Car.", "TALENT.AvailableSocket": "Emplacement {type} libre", "TALENT.TakenSocket": "Emplacement {type} occupé par {talent}", diff --git a/modules/DicePool.js b/modules/DicePool.js index a527d67..fcda63a 100644 --- a/modules/DicePool.js +++ b/modules/DicePool.js @@ -36,6 +36,8 @@ export default class DicePool return creatureDice; }, {}); + this.specialisations = []; + mergeObject(this, options); } @@ -47,7 +49,9 @@ export default class DicePool { return [ this.dice.characteristic + "d" + CharacteristicDie.DENOMINATION, - (this.dice.fortune + this.creatureDice.aggression + this.creatureDice.cunning) + "d" + FortuneDie.DENOMINATION, + (this.dice.fortune + this.specialisations.length + + this.creatureDice.aggression + + this.creatureDice.cunning) + "d" + FortuneDie.DENOMINATION, (this.dice.expertise + this.creatureDice.expertise) + "d" + ExpertiseDie.DENOMINATION, this.dice.conservative + "d" + ConservativeDie.DENOMINATION, this.dice.reckless + "d" + RecklessDie.DENOMINATION, diff --git a/modules/applications/DicePoolBuilder.js b/modules/applications/DicePoolBuilder.js index b542b8c..b3ccca0 100644 --- a/modules/applications/DicePoolBuilder.js +++ b/modules/applications/DicePoolBuilder.js @@ -72,6 +72,16 @@ export default class DicePoolBuilder extends FormApplication return object; }, {}); + data.specialisations = this.object.checkData.actor.itemTypes.skill + .filter(skill => skill.system.specialisations) + .reduce((specialisations, skill) => { + specialisations.push(...skill.system.specialisations + .split(",") + .map(specialisation => specialisation.trim()) + ); + return specialisations; + }, []); + if(this.object.checkData.actor.type === "creature") data.attributes = this.object.checkData.actor.system.attributes; } @@ -131,11 +141,17 @@ export default class DicePoolBuilder extends FormApplication { await super._onChangeInput(event); - setProperty( - this.object, - event.currentTarget.name, - isNaN(event.currentTarget.value) ? event.currentTarget.value : Number(event.currentTarget.value) - ); + let value = []; + for(const element of $(event.delegateTarget).find(`[name="${event.currentTarget.name}"]`)) { + if(element.type === "checkbox") { + if(element.checked) + value.push(element.value); + } + else + value = element.value; + } + + setProperty(this.object, event.currentTarget.name, isNaN(value) ? value : Number(value)); this._updatePreview(); } @@ -351,7 +367,9 @@ export default class DicePoolBuilder extends FormApplication { container.innerHTML = ""; - const totalDice = Object.values(this.object.dice).reduce((accumulator, dice) => accumulator + +dice, 0); + const totalDice = Object.values(this.object.dice).reduce((accumulator, dice) => accumulator + +dice, 0) + + Object.values(this.object.creatureDice).reduce((accumulator, dice) => accumulator + +dice, 0) + + this.object.specialisations.length; // Adjust dice icons' size. let height = 48; @@ -374,7 +392,9 @@ export default class DicePoolBuilder extends FormApplication Object.entries(this.object.dice).forEach((dice, index) => { if(this.object.creatureDice) { if(dice[0] === "fortune") - dice[1] += this.object.creatureDice.aggression + this.object.creatureDice.cunning; + dice[1] += this.object.specialisations.length + + this.object.creatureDice.aggression + + this.object.creatureDice.cunning; else if(dice[0] === "expertise") dice[1] += this.object.creatureDice.expertise; } diff --git a/modules/applications/actors/WFRP3eCharacterSheet.js b/modules/applications/actors/WFRP3eCharacterSheet.js index 48851c8..98e0bd8 100644 --- a/modules/applications/actors/WFRP3eCharacterSheet.js +++ b/modules/applications/actors/WFRP3eCharacterSheet.js @@ -96,7 +96,7 @@ export default class WFRP3eCharacterSheet extends ActorSheet html.find(".flip-link").click(this._onFlipClick.bind(this)); html.find(".item-roll-link").click(this._onItemRoll.bind(this)); - html.find(".item-expand-link").click(this._onItemExpandClick.bind(this)); + html.find(".item.row, .item-expand-link").click(this._onItemExpandClick.bind(this)); html.find(".item-edit-link").click(this._onItemEdit.bind(this)); html.find(".item-delete-link").click(this._onItemDelete.bind(this)); @@ -115,7 +115,6 @@ export default class WFRP3eCharacterSheet extends ActorSheet .contextmenu(this._onRechargeTokenRightClick.bind(this)); html.find(".skill-training-level-input").change(this._onSkillTrainingLevelChange.bind(this)); - html.find(".stance-meter-segment").click(this._onStanceMeterSegmentClick.bind(this)); } /** @@ -175,24 +174,24 @@ export default class WFRP3eCharacterSheet extends ActorSheet }); if(this.actor.system.currentCareer) { - this.actor.system.currentCareer.system.talentSockets.forEach((talentSocket, index) => { + this.actor.system.currentCareer.system.talentSockets.forEach((talentSocketName, index) => { // Find a potential Talent that would be socketed in that Talent Socket. const talent = this.actor.itemTypes.talent.find(talent => talent.system.talentSocket === "career_" + this.actor.system.currentCareer._id + "_" + index); - talentSocketsByType[talentSocket]["career_" + this.actor.system.currentCareer._id + "_" + index] = + talentSocketsByType[talentSocketName]["career_" + this.actor.system.currentCareer._id + "_" + index] = this.actor.system.currentCareer.name + (talent ? " - " + game.i18n.format("TALENT.TakenSocket", { - type: game.i18n.localize(`TALENT.TYPE.${capitalize(talentSocket[0])}`), + type: game.i18n.localize(`TALENT.TYPE.${capitalize(talentSocketName)}`), talent: talent.name }) : " - " + game.i18n.format("TALENT.AvailableSocket", { - type: game.i18n.localize(`TALENT.TYPE.${capitalize(talentSocket[0])}`) + type: game.i18n.localize(`TALENT.TYPE.${capitalize(talentSocketName)}`) })); }); } if(this.actor.system.currentParty) { - this.actor.system.currentParty.system.talentSockets.forEach((talentSocket, index) => { + this.actor.system.currentParty.system.talentSockets.forEach((talentSocketName, index) => { let talent = null; for(const member of this.actor.system.currentParty.memberActors) { @@ -203,15 +202,17 @@ export default class WFRP3eCharacterSheet extends ActorSheet break; } - talentSocketsByType[talentSocket]["party_" + this.actor.system.currentParty._id + "_" + index] = + talentSocketsByType[talentSocketName]["party_" + this.actor.system.currentParty._id + "_" + index] = this.actor.system.currentParty.name + (talent - ? " - " + game.i18n.format("TALENT.TakenSocket", { - type: game.i18n.localize(`TALENT.TYPE.${capitalize(talentSocket[0])}`), + ? " - " + + game.i18n.format("TALENT.TakenSocket", { + type: game.i18n.localize(`TALENT.TYPE.${capitalize(talentSocketName)}`), talent: talent.name }) - : " - " + game.i18n.format("TALENT.AvailableSocket", { - type: game.i18n.localize(`TALENT.TYPE.${capitalize(talentSocket[0])}`) - })); + : " - " + + game.i18n.format("TALENT.AvailableSocket", { + type: game.i18n.localize(`TALENT.TYPE.${capitalize(talentSocketName)}`) + })); }); } @@ -493,8 +494,11 @@ export default class WFRP3eCharacterSheet extends ActorSheet _onItemExpandClick(event) { event.preventDefault(); + event.stopPropagation(); - const itemElement = $(event.currentTarget).parents(".item"); + const itemElement = $(event.currentTarget).hasClass("item") + ? $(event.currentTarget) + : $(event.currentTarget).parents(".item"); const item = this._getItemById(event); if(itemElement.hasClass("expanded")) { @@ -503,20 +507,16 @@ export default class WFRP3eCharacterSheet extends ActorSheet details.slideUp(200, () => details.remove()); - $(event.currentTarget).find(".fas").removeClass("fa-chevron-up").addClass("fa-chevron-down"); + itemElement.find(".item-expand-link .fas").removeClass("fa-chevron-up").addClass("fa-chevron-down"); } else { // Add a div with the item's details below the row. - const detailsElement = $(`
${item.system.description}
`); - - if(item.type === "weapon" && item.system.special) - detailsElement.append(item.system.special); + const detailsElement = $(`
${item.getDetails()}
`); itemElement.append(detailsElement.hide()); detailsElement.slideDown(200); - $(event.currentTarget).find(".fas").removeClass("fa-chevron-down").addClass("fa-chevron-up"); - + itemElement.find(".item-expand-link .fas").removeClass("fa-chevron-down").addClass("fa-chevron-up"); } itemElement.toggleClass("expanded"); @@ -538,16 +538,4 @@ export default class WFRP3eCharacterSheet extends ActorSheet else clickedItem.update({"system.trainingLevel": Number(event.target.value)}); } - - /** - * Performs follow-up operations after clicks on a Stance meter's segment. - * @param {MouseEvent} event - * @private - */ - async _onStanceMeterSegmentClick(event) - { - event.preventDefault(); - - this.actor.update({"system.stance.current": parseInt($(event.currentTarget).find("input")[0].value)}); - } } \ No newline at end of file diff --git a/modules/documents/WFRP3eItem.js b/modules/documents/WFRP3eItem.js index 9ce3ef6..6f8b89e 100644 --- a/modules/documents/WFRP3eItem.js +++ b/modules/documents/WFRP3eItem.js @@ -15,11 +15,12 @@ export default class WFRP3eItem extends Item } /** + * Makes usage of the WFRP3eItem. The result depends on the type of the WFRP3eItem. * @param {Object} [options] */ useItem(options = {}) { - const functionName = `use${capitalize(this.type)}`; + const functionName = `_use${capitalize(this.type)}`; if(this[`${functionName}`]) this[`${functionName}`](options); @@ -29,8 +30,10 @@ export default class WFRP3eItem extends Item /** * @param {Object} [options] + * @returns {Promise} + * @private */ - async useAction(options = {}) + async _useAction(options = {}) { if(!options.face) throw new Error("Knowing which face of the Action to use is needed."); @@ -78,16 +81,20 @@ export default class WFRP3eItem extends Item /** * @param {Object} [options] + * @returns {Promise} + * @private */ - async useSkill(options = {}) + async _useSkill(options = {}) { await CheckHelper.prepareSkillCheck(this.actor, this); } /** * @param {Object} [options] + * @returns {Promise} + * @private */ - async useWeapon(options = {}) + async _useWeapon(options = {}) { const weaponType = CONFIG.WFRP3e.weapon.groups[this.system.group].type; let action = null; @@ -105,6 +112,30 @@ export default class WFRP3eItem extends Item await CheckHelper.prepareActionCheck(this.actor, action, this.actor.getCurrentStanceName(), {weapon: this}); } + /** + * Fetches the details of the WFRP3eItem, depending on its type. + * @returns {*} + */ + getDetails() + { + const functionName = `_get${capitalize(this.type)}Details`; + + if(this[`${functionName}`]) + return this[`${functionName}`](); + else + return this.system.description; + } + + _getSkillDetails() + { + return game.i18n.format("SKILL.SpecialisationList", {specialisations: this.system.specialisations ?? ""}); + } + + _getWeaponDetails() + { + return this.system.description.concat(this.system.special); + } + /** * Adds recharge tokens to an Action equal to its recharge rating. * @param {string} face diff --git a/styles/less/components/character_sheet.less b/styles/less/components/character_sheet.less index 74b261e..da96ced 100644 --- a/styles/less/components/character_sheet.less +++ b/styles/less/components/character_sheet.less @@ -402,6 +402,14 @@ background: #E9E2DB; } + &.skill { + background: #EDE1D1; + + &:nth-of-type(even) { + background: #E1CFB6; + } + } + & .content:first-child { align-items: center; display: flex; @@ -418,6 +426,13 @@ text-align: center; text-shadow: 1px 1px var(--color-shadow-dark); + &.skill { + background: initial; + color: initial; + font-variant-caps: small-caps; + text-shadow: initial; + } + &.title { background: #3F0B0CFF; display: block; @@ -454,6 +469,27 @@ } } + &.skill { + & .buttons { + width: 10%; + } + + & .skill-characteristic { + font-variant-caps: small-caps; + width: 15%; + } + + & .skill-name { + font-variant-caps: small-caps; + text-align: initial; + width: 50%; + } + + & .skill-training-level { + width: 25%; + } + } + &.trapping { & .trapping-name { diff --git a/styles/less/components/dice_pool_builder.less b/styles/less/components/dice_pool_builder.less index f49df6c..ef4e978 100644 --- a/styles/less/components/dice_pool_builder.less +++ b/styles/less/components/dice_pool_builder.less @@ -235,6 +235,7 @@ & .quick-settings { flex: 1 1 200px; + width: 200px; & > label { margin-bottom: 0.5rem; diff --git a/templates/applications/actors/character-sheet.hbs b/templates/applications/actors/character-sheet.hbs index 2ca7afb..24ddd3a 100644 --- a/templates/applications/actors/character-sheet.hbs +++ b/templates/applications/actors/character-sheet.hbs @@ -194,7 +194,7 @@ {{#if (lookup @root.items.talents ty)}}
{{#each (lookup @root.items.talents ty) as |talent ta|}} -
+ {{/if}} + +
+ {{localize "ROLL.DICEPOOLBUILDER.Specialisations"}} + + {{#if specialisations}} + {{#each specialisations}} + + {{/each}} + {{else}} + None + {{/if}} +
{{/if}} \ No newline at end of file diff --git a/templates/applications/items/skill-sheet.hbs b/templates/applications/items/skill-sheet.hbs index 354296e..a5505c5 100644 --- a/templates/applications/items/skill-sheet.hbs +++ b/templates/applications/items/skill-sheet.hbs @@ -1,22 +1,37 @@
-

+ +

+ +

-
- - {{selectOptions characteristics selected=item.system.characteristic labelAttr="name" localize=true}} -
+ + + {{editor item.system.description target="system.description" button=true owner=owner editable=editable}} + + {{#if item.parent}} + + {{/if}}
\ No newline at end of file diff --git a/templates/partials/item-armour-row.hbs b/templates/partials/item-armour-row.hbs index 30a38c9..eb9dace 100644 --- a/templates/partials/item-armour-row.hbs +++ b/templates/partials/item-armour-row.hbs @@ -1,16 +1,26 @@
- {{armour.name}} + + {{armour.name}} + - {{armour.system.defenceValue}} +
+ + + {{armour.system.defenceValue}} +
- {{armour.system.soakValue}} + + {{armour.system.soakValue}} +
- {{armour.system.encumbrance}} + + {{armour.system.encumbrance}} +
diff --git a/templates/partials/item-skill-row.hbs b/templates/partials/item-skill-row.hbs index 2a348cf..299bdbd 100644 --- a/templates/partials/item-skill-row.hbs +++ b/templates/partials/item-skill-row.hbs @@ -1,37 +1,51 @@ - - - {{skill.name}} - - - - {{localize (lookup (lookup @root.characteristics skill.system.characteristic) "abbreviation")}} - - - - - - - - - - - {{#if @root.document.isOwner}} - - - +
+
+ + {{skill.name}} + + + + {{localize (lookup (lookup @root.characteristics skill.system.characteristic) "abbreviation")}} + + + + + + + + + + +
+ + - - {{/if}} - \ No newline at end of file + + + + + + {{#if @root.document.isOwner}} + + + + + + + + {{/if}} +
+
+
\ No newline at end of file diff --git a/templates/partials/item-trapping-row.hbs b/templates/partials/item-trapping-row.hbs index 91c45e9..6946826 100644 --- a/templates/partials/item-trapping-row.hbs +++ b/templates/partials/item-trapping-row.hbs @@ -1,6 +1,8 @@
- {{trapping.name}} + + {{trapping.name}} +
diff --git a/templates/partials/item-weapon-row.hbs b/templates/partials/item-weapon-row.hbs index 331e8a5..3b0e148 100644 --- a/templates/partials/item-weapon-row.hbs +++ b/templates/partials/item-weapon-row.hbs @@ -1,18 +1,26 @@
- {{weapon.name}} + + {{weapon.name}} +
- {{weapon.system.damageRating}} + + {{weapon.system.damageRating}} +
- {{weapon.system.criticalRating}} + + {{weapon.system.criticalRating}} +
- {{localize (lookup @root.weaponRanges weapon.system.range)}} + + {{localize (lookup @root.weaponRanges weapon.system.range)}} +
@@ -28,11 +36,15 @@
- {{localize (lookup (lookup @root.weaponGroups weapon.system.group) "name")}} + + {{localize (lookup (lookup @root.weaponGroups weapon.system.group) "name")}} +
- {{weapon.system.encumbrance}} + + {{weapon.system.encumbrance}} +
From 029d7fe9f2ceef6573dad15923916197b1a4a97f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Wed, 27 Mar 2024 15:32:33 +0100 Subject: [PATCH 02/25] fix #64 --- lang/en-EN.json | 1 + lang/fr-FR.json | 19 ++++---- modules/DicePool.js | 36 ++++++++++---- modules/applications/DicePoolBuilder.js | 51 +++++++++++--------- templates/applications/dice-pool-builder.hbs | 8 +-- 5 files changed, 71 insertions(+), 44 deletions(-) diff --git a/lang/en-EN.json b/lang/en-EN.json index 11709c2..353ceb5 100644 --- a/lang/en-EN.json +++ b/lang/en-EN.json @@ -411,6 +411,7 @@ "ROLL.DICEPOOLBUILDER.DicePool": "Dice Pool", "ROLL.DICEPOOLBUILDER.EncounterType": "Encounter Type", "ROLL.DICEPOOLBUILDER.ExpertiseDice": "Expertise Dice", + "ROLL.DICEPOOLBUILDER.FortunePoints": "Fortune Points", "ROLL.DICEPOOLBUILDER.Hint": "Left click to increase dice, right click to decrease.", "ROLL.DICEPOOLBUILDER.Options": "Options", "ROLL.DICEPOOLBUILDER.RollCheck": "Roll check", diff --git a/lang/fr-FR.json b/lang/fr-FR.json index 40366c2..2e07f4f 100644 --- a/lang/fr-FR.json +++ b/lang/fr-FR.json @@ -395,22 +395,23 @@ "ROLL.AMOUNT.Successes": "{nb} succès", "ROLL.AMOUNT.SigmarsComets": "{nb} comètes de Sigmar", "ROLL.CHALLENGELEVEL.Simple": "Simple", - "ROLL.CHALLENGELEVEL.Easy": "Easy", - "ROLL.CHALLENGELEVEL.Average": "Average", - "ROLL.CHALLENGELEVEL.Hard": "Hard", - "ROLL.CHALLENGELEVEL.Daunting": "Daunting", - "ROLL.CHALLENGELEVEL.Heroic": "Heroic", - "ROLL.DICEPOOLBUILDER.AggressionDice": "Aggression Dice", - "ROLL.DICEPOOLBUILDER.ChallengeLevel": "Challenge Level", + "ROLL.CHALLENGELEVEL.Easy": "Facile", + "ROLL.CHALLENGELEVEL.Average": "Moyen", + "ROLL.CHALLENGELEVEL.Hard": "Difficile", + "ROLL.CHALLENGELEVEL.Daunting": "Intimidant", + "ROLL.CHALLENGELEVEL.Heroic": "Héroïque", + "ROLL.DICEPOOLBUILDER.AggressionDice": "Dés d'Agressivité", + "ROLL.DICEPOOLBUILDER.ChallengeLevel": "Niveau de Défi", "ROLL.DICEPOOLBUILDER.Characteristic": "Caractéristique", "ROLL.DICEPOOLBUILDER.ConvertConservative": "Convertir en dé de prudence", "ROLL.DICEPOOLBUILDER.ConvertReckless": "Convertir en dé de témérité", "ROLL.DICEPOOLBUILDER.ConvertWarning": "Il n'y a pas de dé de {type} à convertir.", "ROLL.DICEPOOLBUILDER.ConvertBackWarning": "Il n'y a plus de dé de {type} à reconvertir.", - "ROLL.DICEPOOLBUILDER.CunningDice": "Cunning Dice", + "ROLL.DICEPOOLBUILDER.CunningDice": "Dés d'Astuce", "ROLL.DICEPOOLBUILDER.DicePool": "Réserve de dés", "ROLL.DICEPOOLBUILDER.EncounterType": "Type de rencontre", - "ROLL.DICEPOOLBUILDER.ExpertiseDice": "Expertise Dice", + "ROLL.DICEPOOLBUILDER.ExpertiseDice": "Dés d'Adresse", + "ROLL.DICEPOOLBUILDER.FortunePoints": "Points de Fortune", "ROLL.DICEPOOLBUILDER.Hint": "Clic gauche pour ajouter des dés, clic droit pour en retirer.", "ROLL.DICEPOOLBUILDER.Options": "Options", "ROLL.DICEPOOLBUILDER.RollCheck": "Lancer le test", diff --git a/modules/DicePool.js b/modules/DicePool.js index a527d67..741dfdf 100644 --- a/modules/DicePool.js +++ b/modules/DicePool.js @@ -36,6 +36,8 @@ export default class DicePool return creatureDice; }, {}); + this.fortunePoints = 0; + mergeObject(this, options); } @@ -47,7 +49,7 @@ export default class DicePool { return [ this.dice.characteristic + "d" + CharacteristicDie.DENOMINATION, - (this.dice.fortune + this.creatureDice.aggression + this.creatureDice.cunning) + "d" + FortuneDie.DENOMINATION, + (this.dice.fortune + this.fortunePoints + this.creatureDice.aggression + this.creatureDice.cunning) + "d" + FortuneDie.DENOMINATION, (this.dice.expertise + this.creatureDice.expertise) + "d" + ExpertiseDie.DENOMINATION, this.dice.conservative + "d" + ConservativeDie.DENOMINATION, this.dice.reckless + "d" + RecklessDie.DENOMINATION, @@ -135,18 +137,34 @@ export default class DicePool if(this.sound) AudioHelper.play({src: this.sound}, true); - if(this.checkData?.actor?.type === "creature") { - const updates = {system: {attributes: {}}}; + if(this.checkData?.actor) { + const actor = this.checkData.actor; + + // Remove the fortune points spent on the check. + if(actor.type === "character" && this.fortunePoints > 0) { + const updates = {"system.fortune.value": Math.max(actor.system.fortune.value - this.fortunePoints, 0)}; - for(const [attributeName, creatureDice] of Object.entries(this.creatureDice)) { - if(creatureDice > 0) { - updates.system.attributes[attributeName] = { - current: this.checkData.actor.system.attributes[attributeName].current - creatureDice - }; + if(this.fortunePoints > actor.system.fortune.value) { + const party = actor.system.currentParty; + party.update({"system.fortunePool": Math.max(party.system.fortunePool - (this.fortunePoints - actor.system.fortune.value), 0)}) } + + actor.update(updates); } + // Remove the attribute dice spent on the check. + else if(actor.type === "creature") { + const updates = {system: {attributes: {}}}; + + for(const [attributeName, creatureDice] of Object.entries(this.creatureDice)) { + if(creatureDice > 0) + updates.system.attributes[attributeName] = { + value: actor.system.attributes[attributeName].value - creatureDice + }; + } - this.checkData.actor.update(updates); + if(Object.keys(updates.system.attributes).length > 0) + actor.update(updates); + } } return roll; diff --git a/modules/applications/DicePoolBuilder.js b/modules/applications/DicePoolBuilder.js index b542b8c..edbcef9 100644 --- a/modules/applications/DicePoolBuilder.js +++ b/modules/applications/DicePoolBuilder.js @@ -61,41 +61,46 @@ export default class DicePoolBuilder extends FormApplication } if(this.object.checkData) { - this.object.checkData.challengeLevel = data.challengeLevel; + const checkData = this.object.checkData; + checkData.challengeLevel = data.challengeLevel; - if(this.object.checkData.actor) { - data.skills = this.object.checkData.actor.itemTypes.skill; + if(checkData.actor) { + const actor = checkData.actor; + data.skills = actor.itemTypes.skill; data.characteristics = Object.entries(CONFIG.WFRP3e.characteristics).reduce((object, characteristic) => { if(characteristic[0] !== "varies") object[characteristic[0]] = characteristic[1].name; return object; }, {}); - if(this.object.checkData.actor.type === "creature") - data.attributes = this.object.checkData.actor.system.attributes; + if(actor.type === "character") + data.maxFortunePoints = actor.system.fortune.value + actor.system.currentParty.system.fortunePool; + else if(actor.type === "creature") + data.attributes = actor.system.attributes; } - if(this.object.checkData.skill) - data.skill = this.object.checkData.skill; + if(checkData.skill) + data.skill = checkData.skill; - if(this.object.checkData.characteristic) - data.characteristic = this.object.checkData.characteristic; + if(checkData.characteristic) + data.characteristic = checkData.characteristic; - if(this.object.checkData.action) { - data.action = this.object.checkData.action + if(checkData.action) { + const action = checkData.action; + data.action = action; - if(["melee", "ranged"].includes(data.action.system.type)) { - data.availableWeapons = data.action.actor.itemTypes.weapon.filter(weapon => { + if(["melee", "ranged"].includes(action.system.type)) { + data.availableWeapons = action.actor.itemTypes.weapon.filter(weapon => { return Object.entries(CONFIG.WFRP3e.weapon.groups).reduce((array, weaponGroup) => { - if(weaponGroup[1].type === data.action.system.type) + if(weaponGroup[1].type === action.system.type) array.push(weaponGroup[0]); return array; }, []).includes(weapon.system.group); }); - data.weapon = this.object.checkData.weapon ?? Object.values(data.availableWeapons)[0]; - this.object.checkData.weapon = Object.values(data.availableWeapons)[0]; + data.weapon = checkData.weapon ?? Object.values(data.availableWeapons)[0]; + checkData.weapon = Object.values(data.availableWeapons)[0]; } } } @@ -351,7 +356,9 @@ export default class DicePoolBuilder extends FormApplication { container.innerHTML = ""; - const totalDice = Object.values(this.object.dice).reduce((accumulator, dice) => accumulator + +dice, 0); + const totalDice = Object.values(this.object.dice).reduce((accumulator, dice) => accumulator + +dice, 0) + + Object.values(this.object.creatureDice).reduce((accumulator, dice) => accumulator + +dice, 0) + + this.object.fortunePoints; // Adjust dice icons' size. let height = 48; @@ -374,7 +381,9 @@ export default class DicePoolBuilder extends FormApplication Object.entries(this.object.dice).forEach((dice, index) => { if(this.object.creatureDice) { if(dice[0] === "fortune") - dice[1] += this.object.creatureDice.aggression + this.object.creatureDice.cunning; + dice[1] += this.object.fortunePoints + + this.object.creatureDice.aggression + + this.object.creatureDice.cunning; else if(dice[0] === "expertise") dice[1] += this.object.creatureDice.expertise; } @@ -472,14 +481,12 @@ export default class DicePoolBuilder extends FormApplication { event.preventDefault(); - const skill = this.object.checkData.actor.itemTypes.skill.find(skill => skill._id === event.currentTarget.value) + const skill = this.object.checkData.actor.itemTypes.skill.find(skill => skill._id === event.currentTarget.value); this.object.checkData.skill = skill; this.object.dice.expertise = skill.system.trainingLevel; - html.find(".characteristic-select") - .val(skill.system.characteristic) - .trigger("change"); + html.find(".characteristic-select").val(skill.system.characteristic).trigger("change"); this._synchronizeInputs(html); } diff --git a/templates/applications/dice-pool-builder.hbs b/templates/applications/dice-pool-builder.hbs index 15844b1..07f9788 100644 --- a/templates/applications/dice-pool-builder.hbs +++ b/templates/applications/dice-pool-builder.hbs @@ -11,7 +11,7 @@ {{#each diceIcons as |die d|}} {{/each}} @@ -27,7 +27,7 @@ {{#if availableWeapons}} From b04cc83a1673a89c79c140c8534a98432f7e8533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Fri, 29 Mar 2024 07:39:21 +0100 Subject: [PATCH 03/25] fix #65 --- lang/en-EN.json | 5 + lang/fr-FR.json | 7 +- styles/less/components/character_sheet.less | 20 +- styles/less/components/condition_card.less | 107 +++++----- styles/less/components/disease_card.less | 187 ++++++++---------- styles/less/components/insanity_card.less | 38 ++-- styles/less/components/miscast_card.less | 123 ++++++------ styles/less/components/mutation_card.less | 187 ++++++++---------- styles/less/components/wound_card.less | 121 ++++++------ .../applications/actors/character-sheet.hbs | 110 +++++++---- 10 files changed, 441 insertions(+), 464 deletions(-) diff --git a/lang/en-EN.json b/lang/en-EN.json index 6204d50..cf67406 100644 --- a/lang/en-EN.json +++ b/lang/en-EN.json @@ -132,11 +132,14 @@ "CHARACTER.Background": "Background", "CHARACTER.Careers": "Careers", "CHARACTER.Characteristics": "Characteristics", + "CHARACTER.Conditions": "Conditions", "CHARACTER.Corruption": "Corruption", + "CHARACTER.CriticalWounds": "Critical Wounds", "CHARACTER.Current": "Current", "CHARACTER.CurrentExperience": "Current Experience", "CHARACTER.Experience": "Experience", "CHARACTER.Fortune": "Fortune", + "CHARACTER.Insanities": "Insanities", "CHARACTER.Maximum": "Maximum", "CHARACTER.Origin": "Origin", "CHARACTER.Skills": "Skills", @@ -145,7 +148,9 @@ "CHARACTER.Threshold": "Threshold", "CHARACTER.TotalExperience": "Total Experience", "CHARACTER.Trappings": "Trappings", + "CHARACTER.Miscasts": "Miscasts", "CHARACTER.Money": "Money", + "CHARACTER.Mutations": "Mutations", "CHARACTER.Weapons": "Weapons", "CHARACTER.Wounds": "Wounds", "CHARACTER.WoundThreshold": "Wound Threshold", diff --git a/lang/fr-FR.json b/lang/fr-FR.json index 9681725..b863b1c 100644 --- a/lang/fr-FR.json +++ b/lang/fr-FR.json @@ -125,18 +125,21 @@ "CAREERSELECTOR.SelectedCareer": "Selected Career:", "CAREERSELECTOR.Title": "Career Selector", - "CHARACTER.Abilities": "Abilities", + "CHARACTER.Abilities": "Aptitudes", "CHARACTER.Actions": "Actions", "CHARACTER.Armours": "Armures", "CHARACTER.Attributes": "Attributs", "CHARACTER.Background": "Historique", "CHARACTER.Careers": "Carrières", "CHARACTER.Characteristics": "Caractéristiques", + "CHARACTER.Conditions": "États", "CHARACTER.Corruption": "Corruption", + "CHARACTER.CriticalWounds": "Blessures Critiques", "CHARACTER.Current": "Actuel", "CHARACTER.CurrentExperience": "Current Experience", "CHARACTER.Experience": "Experience", "CHARACTER.Fortune": "Fortune", + "CHARACTER.Insanities": "Folies", "CHARACTER.Maximum": "Maximum", "CHARACTER.Origin": "Origin", "CHARACTER.Skills": "Compétences", @@ -145,7 +148,9 @@ "CHARACTER.Threshold": "Plafond", "CHARACTER.TotalExperience": "Total Experience", "CHARACTER.Trappings": "Dotations", + "CHARACTER.Miscasts": "Revers Magiques", "CHARACTER.Money": "Argent", + "CHARACTER.Mutations": "Mutations", "CHARACTER.Weapons": "Armes", "CHARACTER.Wounds": "Blessures", "CHARACTER.WoundThreshold": "Plafond de Blessure", diff --git a/styles/less/components/character_sheet.less b/styles/less/components/character_sheet.less index da96ced..e92b4ea 100644 --- a/styles/less/components/character_sheet.less +++ b/styles/less/components/character_sheet.less @@ -22,9 +22,23 @@ overflow: auto; } - & .abilities-tab .character-sheet-abilities { - display: flex; - flex-wrap: wrap; + & .abilities-tab { + overflow: unset; + + & .character-sheet-abilities { + min-height: 0; + } + + & .character-sheet-ability-tabs { + border-bottom: 1px solid #b5b3a4; + display: flex; + flex-flow: row wrap; + justify-content: space-around; + + & > * { + margin: 0 5px; + } + } } & .actions-tab { diff --git a/styles/less/components/condition_card.less b/styles/less/components/condition_card.less index b3ca6f0..252c2c0 100644 --- a/styles/less/components/condition_card.less +++ b/styles/less/components/condition_card.less @@ -1,35 +1,48 @@ -.conditions -{ - & .condition-card - { - position: relative; - width: 255px; - height: 385px; - margin: 0 auto; - padding: 20px; - border-radius: 10px; - background-color: #806050; - text-align: center; +.condition-card { + position: relative; + width: 255px; + height: 385px; + margin: 8px; + padding: 20px; + border-radius: 10px; + background-color: #806050; + text-align: center; - & .condition-card-description - { - text-shadow: 0 0 16px white; - background-color: #b0a0a0; + & .condition-card-description { + text-shadow: 0 0 16px white; + background-color: #b0a0a0; - & p - { - text-align: center; - } + & p { + text-align: center; } + } + + & .condition-card-duration { + padding: 10px 0 20px; + background-color: #c0b0a0; + color: white; + font-size: 14pt; + font-weight: bold; + font-variant-caps: small-caps; + text-shadow: + -1pt -1pt 0 black, + -1pt 0 0 black, + 0 -1pt 0 black, + -1pt 1pt 0 black, + 1pt -1pt 0 black, + 0 1pt 0 black, + 1pt 0 0 black, + 1pt 1pt 0 black, + 0 0 8px black; + } + + & .condition-card-header { + padding: 20px 0; + background: #903030; - & .condition-card-duration - { - padding: 10px 0 20px; - background-color: #c0b0a0; + & .condition-card-name { color: white; - font-size: 14pt; - font-weight: bold; - font-variant-caps: small-caps; + font: small-caps 16pt var(--font-title); text-shadow: -1pt -1pt 0 black, -1pt 0 0 black, @@ -38,41 +51,17 @@ 1pt -1pt 0 black, 0 1pt 0 black, 1pt 0 0 black, - 1pt 1pt 0 black, - 0 0 8px black; - } - - & .condition-card-header - { - padding: 20px 0; - background: #903030; - - & .condition-card-name - { - color: white; - font: small-caps 16pt var(--font-title); - text-shadow: - -1pt -1pt 0 black, - -1pt 0 0 black, - 0 -1pt 0 black, - -1pt 1pt 0 black, - 1pt -1pt 0 black, - 0 1pt 0 black, - 1pt 0 0 black, - 1pt 1pt 0 black; + 1pt 1pt 0 black; - &:hover - { - text-shadow: 0 0 8px var(--color-shadow-primary); - } + &:hover { + text-shadow: 0 0 8px var(--color-shadow-primary); } } + } - & .item-delete-link - { - position: absolute; - bottom: 5px; - right: 10px; - } + & .item-delete-link { + position: absolute; + bottom: 5px; + right: 10px; } } \ No newline at end of file diff --git a/styles/less/components/disease_card.less b/styles/less/components/disease_card.less index c8bc17f..c4e05b2 100644 --- a/styles/less/components/disease_card.less +++ b/styles/less/components/disease_card.less @@ -1,119 +1,104 @@ -.diseases -{ - & .disease-card - { - position: relative; - width: 255px; - height: 385px; - margin: 0 auto; - border: 10px solid #104020; - border-radius: 10px; - text-align: center; - background-color: #e8f0e0; +.disease-card { + position: relative; + width: 255px; + height: 385px; + margin: 8px; + border: 10px solid #104020; + border-radius: 10px; + text-align: center; + background-color: #e8f0e0; - & .disease-card-content - { - padding: 0 5px; + & .disease-card-content { + padding: 0 5px; - & .disease-card-description - { - text-align: left; - margin-left: 0; - padding: 0; - border: 0; - } + & .disease-card-description { + text-align: left; + margin-left: 0; + padding: 0; + border: 0; + } - & .disease-card-severity-rating - { - width: 31px; - height: 31px; - background-color: #405848; - float: left; - color: white; - font: small-caps 20pt var(--font-title); - text-shadow: - -1pt -1pt 0 black, - -1pt 0 0 black, - 0 -1pt 0 black, - -1pt 1pt 0 black, - 1pt -1pt 0 black, - 0 1pt 0 black, - 1pt 0 0 black, - 1pt 1pt 0 black; - } + & .disease-card-severity-rating { + width: 31px; + height: 31px; + background-color: #405848; + float: left; + color: white; + font: small-caps 20pt var(--font-title); + text-shadow: + -1pt -1pt 0 black, + -1pt 0 0 black, + 0 -1pt 0 black, + -1pt 1pt 0 black, + 1pt -1pt 0 black, + 0 1pt 0 black, + 1pt 0 0 black, + 1pt 1pt 0 black; + } - & .disease-card-symptom - { - text-align: left; + & .disease-card-symptom { + text-align: left; - & .symptom-name - { - text-transform: uppercase; + & .symptom-name { + text-transform: uppercase; - &::first-letter - { - font-size: 16pt; - } + &::first-letter { + font-size: 16pt; } } } + } - & .disease-card-header - { - display: flex; - flex-direction: column; - height: 70px; - margin-bottom: 5px; - - & .disease-card-name - { - margin: auto 0; - padding: 0 5px; - color: white; - font: small-caps 16pt var(--font-title); - text-shadow: - -1pt -1pt 0 black, - -1pt 0 0 black, - 0 -1pt 0 black, - -1pt 1pt 0 black, - 1pt -1pt 0 black, - 0 1pt 0 black, - 1pt 0 0 black, - 1pt 1pt 0 black; - vertical-align: middle; + & .disease-card-header { + display: flex; + flex-direction: column; + height: 70px; + margin-bottom: 5px; - &:hover - { - text-shadow: 0 0 8px var(--color-shadow-primary); - } - } + & .disease-card-name { + margin: auto 0; + padding: 0 5px; + color: white; + font: small-caps 16pt var(--font-title); + text-shadow: + -1pt -1pt 0 black, + -1pt 0 0 black, + 0 -1pt 0 black, + -1pt 1pt 0 black, + 1pt -1pt 0 black, + 0 1pt 0 black, + 1pt 0 0 black, + 1pt 1pt 0 black; + vertical-align: middle; - & .disease-card-traits - { - height: 20px; - padding: 3px 5px; - background-color: #383830; - color: white; - font-size: 10pt; - font-style: italic; - font-weight: bold; - text-shadow: - -1pt -1pt 0 black, - -1pt 0 0 black, - 0 -1pt 0 black, - -1pt 1pt 0 black, - 1pt -1pt 0 black, - 0 1pt 0 black, - 1pt 0 0 black, - 1pt 1pt 0 black; + &:hover { + text-shadow: 0 0 8px var(--color-shadow-primary); } } - & .item-delete-link - { - position: absolute; - bottom: 0; - right: 5px; + & .disease-card-traits { + height: 20px; + padding: 3px 5px; + background-color: #383830; + color: white; + font-size: 10pt; + font-style: italic; + font-weight: bold; + text-shadow: + -1pt -1pt 0 black, + -1pt 0 0 black, + 0 -1pt 0 black, + -1pt 1pt 0 black, + 1pt -1pt 0 black, + 0 1pt 0 black, + 1pt 0 0 black, + 1pt 1pt 0 black; } } + + & .item-delete-link { + position: absolute; + bottom: 0; + right: 5px; + } } \ No newline at end of file diff --git a/styles/less/components/insanity_card.less b/styles/less/components/insanity_card.less index 7592e27..9078853 100644 --- a/styles/less/components/insanity_card.less +++ b/styles/less/components/insanity_card.less @@ -1,28 +1,24 @@ -.insanity-card -{ +.insanity-card { position: relative; width: 255px; height: 385px; - margin: 0 auto; + margin: 8px; border: 10px solid #602018; border-radius: 10px; text-align: center; background-color: #d0d8e0; - & .insanity-card-content - { + & .insanity-card-content { padding: 0 5px; - & .insanity-card-description - { + & .insanity-card-description { text-align: left; margin-left: 0; padding: 0; border: 0; } - & .insanity-card-severity-rating - { + & .insanity-card-severity-rating { width: 31px; height: 31px; background-color: #202020; @@ -40,31 +36,26 @@ 1pt 1pt 0 black; } - & .insanity-card-symptom - { + & .insanity-card-symptom { text-align: left; - & .symptom-name - { + & .symptom-name { text-transform: uppercase; - &::first-letter - { + &::first-letter { font-size: 16pt; } } } } - & .insanity-card-header - { + & .insanity-card-header { display: flex; flex-direction: column; height: 70px; margin-bottom: 5px; - & .insanity-card-name - { + & .insanity-card-name { margin: auto 0; padding: 0 5px; color: white; @@ -80,14 +71,12 @@ 1pt 1pt 0 black; vertical-align: middle; - &:hover - { + &:hover { text-shadow: 0 0 8px var(--color-shadow-primary); } } - & .insanity-card-traits - { + & .insanity-card-traits { height: 20px; padding: 3px 5px; background-color: #303030; @@ -107,8 +96,7 @@ } } - & .item-delete-link - { + & .item-delete-link { position: absolute; bottom: 0; right: 5px; diff --git a/styles/less/components/miscast_card.less b/styles/less/components/miscast_card.less index b087c8f..e1d1412 100644 --- a/styles/less/components/miscast_card.less +++ b/styles/less/components/miscast_card.less @@ -1,70 +1,36 @@ -.miscasts -{ - & .miscast-card - { - display: flex; - flex-direction: column; - position: relative; - width: 255px; - height: 385px; - margin: 0 auto; - border: 10px solid #385060; - border-width: 10px 0; - border-radius: 10px; - text-align: center; - background-color: #e8f0f8; +.miscast-card { + display: flex; + flex-direction: column; + position: relative; + width: 255px; + height: 385px; + margin: 8px; + border: 10px solid #385060; + border-width: 10px 0; + border-radius: 10px; + text-align: center; + background-color: #e8f0f8; - & .miscast-card-description - { - flex-grow: 1; - padding: 10px; + & .miscast-card-description { + flex-grow: 1; + padding: 10px; - & p - { - text-align: left; - } + & p { + text-align: left; } + } - & .miscast-card-header - { - display: flex; - flex-direction: column; - height: 50px; - margin-bottom: 5px; - background-color: #e8e8e0; - - & .miscast-card-name - { - margin: auto 0; - color: white; - font: small-caps 16pt var(--font-title); - text-shadow: - -1pt -1pt 0 black, - -1pt 0 0 black, - 0 -1pt 0 black, - -1pt 1pt 0 black, - 1pt -1pt 0 black, - 0 1pt 0 black, - 1pt 0 0 black, - 1pt 1pt 0 black; - - &:hover - { - text-shadow: 0 0 8px var(--color-shadow-primary); - } - } - } + & .miscast-card-header { + display: flex; + flex-direction: column; + height: 50px; + margin-bottom: 5px; + background-color: #e8e8e0; - & .miscast-card-severity-rating - { - position: absolute; - width: 31px; - height: 31px; - bottom: 15px; - right: 15px; - background-color: #703818; + & .miscast-card-name { + margin: auto 0; color: white; - font: small-caps 20pt var(--font-title); + font: small-caps 16pt var(--font-title); text-shadow: -1pt -1pt 0 black, -1pt 0 0 black, @@ -74,13 +40,36 @@ 0 1pt 0 black, 1pt 0 0 black, 1pt 1pt 0 black; - } - & .item-delete-link - { - position: absolute; - bottom: 0; - right: 5px; + &:hover { + text-shadow: 0 0 8px var(--color-shadow-primary); + } } } + + & .miscast-card-severity-rating { + position: absolute; + width: 31px; + height: 31px; + bottom: 15px; + right: 15px; + background-color: #703818; + color: white; + font: small-caps 20pt var(--font-title); + text-shadow: + -1pt -1pt 0 black, + -1pt 0 0 black, + 0 -1pt 0 black, + -1pt 1pt 0 black, + 1pt -1pt 0 black, + 0 1pt 0 black, + 1pt 0 0 black, + 1pt 1pt 0 black; + } + + & .item-delete-link { + position: absolute; + bottom: 0; + right: 5px; + } } \ No newline at end of file diff --git a/styles/less/components/mutation_card.less b/styles/less/components/mutation_card.less index adfbb99..74cce78 100644 --- a/styles/less/components/mutation_card.less +++ b/styles/less/components/mutation_card.less @@ -1,119 +1,104 @@ -.mutations -{ - & .mutation-card - { - position: relative; - width: 255px; - height: 385px; - margin: 0 auto; - border: 10px solid #987060; - border-radius: 10px; - text-align: center; - background-color: #f0e8e0; +.mutation-card { + position: relative; + width: 255px; + height: 385px; + margin: 8px; + border: 10px solid #987060; + border-radius: 10px; + text-align: center; + background-color: #f0e8e0; - & .mutation-card-content - { - padding: 0 5px; + & .mutation-card-content { + padding: 0 5px; - & .mutation-card-description - { - text-align: left; - margin-left: 0; - padding: 0; - border: 0; - } + & .mutation-card-description { + text-align: left; + margin-left: 0; + padding: 0; + border: 0; + } - & .mutation-card-severity-rating - { - width: 31px; - height: 31px; - background-color: #e8e8e8; - float: left; - color: white; - font: small-caps 20pt var(--font-title); - text-shadow: - -1pt -1pt 0 black, - -1pt 0 0 black, - 0 -1pt 0 black, - -1pt 1pt 0 black, - 1pt -1pt 0 black, - 0 1pt 0 black, - 1pt 0 0 black, - 1pt 1pt 0 black; - } + & .mutation-card-severity-rating { + width: 31px; + height: 31px; + background-color: #e8e8e8; + float: left; + color: white; + font: small-caps 20pt var(--font-title); + text-shadow: + -1pt -1pt 0 black, + -1pt 0 0 black, + 0 -1pt 0 black, + -1pt 1pt 0 black, + 1pt -1pt 0 black, + 0 1pt 0 black, + 1pt 0 0 black, + 1pt 1pt 0 black; + } - & .mutation-card-symptom - { - text-align: left; + & .mutation-card-symptom { + text-align: left; - & .symptom-name - { - text-transform: uppercase; + & .symptom-name { + text-transform: uppercase; - &::first-letter - { - font-size: 16pt; - } + &::first-letter { + font-size: 16pt; } } } + } - & .mutation-card-header - { - display: flex; - flex-direction: column; - height: 70px; - margin-bottom: 5px; - - & .mutation-card-name - { - margin: auto 0; - padding: 0 5px; - color: white; - font: small-caps 16pt var(--font-title); - text-shadow: - -1pt -1pt 0 black, - -1pt 0 0 black, - 0 -1pt 0 black, - -1pt 1pt 0 black, - 1pt -1pt 0 black, - 0 1pt 0 black, - 1pt 0 0 black, - 1pt 1pt 0 black; - vertical-align: middle; + & .mutation-card-header { + display: flex; + flex-direction: column; + height: 70px; + margin-bottom: 5px; - &:hover - { - text-shadow: 0 0 8px var(--color-shadow-primary); - } - } + & .mutation-card-name { + margin: auto 0; + padding: 0 5px; + color: white; + font: small-caps 16pt var(--font-title); + text-shadow: + -1pt -1pt 0 black, + -1pt 0 0 black, + 0 -1pt 0 black, + -1pt 1pt 0 black, + 1pt -1pt 0 black, + 0 1pt 0 black, + 1pt 0 0 black, + 1pt 1pt 0 black; + vertical-align: middle; - & .mutation-card-traits - { - height: 20px; - padding: 3px 5px; - background-color: #383830; - color: white; - font-size: 10pt; - font-style: italic; - font-weight: bold; - text-shadow: - -1pt -1pt 0 black, - -1pt 0 0 black, - 0 -1pt 0 black, - -1pt 1pt 0 black, - 1pt -1pt 0 black, - 0 1pt 0 black, - 1pt 0 0 black, - 1pt 1pt 0 black; + &:hover { + text-shadow: 0 0 8px var(--color-shadow-primary); } } - & .item-delete-link - { - position: absolute; - bottom: 0; - right: 5px; + & .mutation-card-traits { + height: 20px; + padding: 3px 5px; + background-color: #383830; + color: white; + font-size: 10pt; + font-style: italic; + font-weight: bold; + text-shadow: + -1pt -1pt 0 black, + -1pt 0 0 black, + 0 -1pt 0 black, + -1pt 1pt 0 black, + 1pt -1pt 0 black, + 0 1pt 0 black, + 1pt 0 0 black, + 1pt 1pt 0 black; } } + + & .item-delete-link { + position: absolute; + bottom: 0; + right: 5px; + } } \ No newline at end of file diff --git a/styles/less/components/wound_card.less b/styles/less/components/wound_card.less index a517754..18515ab 100644 --- a/styles/less/components/wound_card.less +++ b/styles/less/components/wound_card.less @@ -1,69 +1,35 @@ -.wounds -{ - & .wound-card - { - display: flex; - flex-direction: column; - position: relative; - width: 255px; - height: 385px; - margin: 0 auto; - border-radius: 10px; - text-align: center; - background-color: #f4e0c0; +.wound-card { + display: flex; + flex-direction: column; + position: relative; + width: 255px; + height: 385px; + margin: 8px; + border-radius: 10px; + text-align: center; + background-color: #f4e0c0; - & .wound-card-description - { - flex-grow: 1; - padding: 10px; - border: 10px solid #803020; - border-top: 0; + & .wound-card-description { + flex-grow: 1; + padding: 10px; + border: 10px solid #803020; + border-top: 0; - & p - { - text-align: left; - } + & p { + text-align: left; } + } - & .wound-card-header - { - border-bottom: 10px solid #503010; - - & .wound-card-name - { - display: block; - margin: auto 0; - border: 10px solid #2e231f; - background-color: #e0c0b0; - color: white; - font: small-caps 16pt var(--font-title); - text-shadow: - -1pt -1pt 0 black, - -1pt 0 0 black, - 0 -1pt 0 black, - -1pt 1pt 0 black, - 1pt -1pt 0 black, - 0 1pt 0 black, - 1pt 0 0 black, - 1pt 1pt 0 black; - - &:hover - { - text-shadow: 0 0 8px var(--color-shadow-primary); - } - } - } + & .wound-card-header { + border-bottom: 10px solid #503010; - & .wound-card-severity-rating - { - position: absolute; - width: 31px; - height: 31px; - bottom: 15px; - right: 15px; - background-color: #703818; + & .wound-card-name { + display: block; + margin: auto 0; + border: 10px solid #2e231f; + background-color: #e0c0b0; color: white; - font: small-caps 20pt var(--font-title); + font: small-caps 16pt var(--font-title); text-shadow: -1pt -1pt 0 black, -1pt 0 0 black, @@ -73,13 +39,36 @@ 0 1pt 0 black, 1pt 0 0 black, 1pt 1pt 0 black; - } - & .item-delete-link - { - position: absolute; - bottom: 10px; - left: 15px; + &:hover { + text-shadow: 0 0 8px var(--color-shadow-primary); + } } } + + & .wound-card-severity-rating { + position: absolute; + width: 31px; + height: 31px; + bottom: 15px; + right: 15px; + background-color: #703818; + color: white; + font: small-caps 20pt var(--font-title); + text-shadow: + -1pt -1pt 0 black, + -1pt 0 0 black, + 0 -1pt 0 black, + -1pt 1pt 0 black, + 1pt -1pt 0 black, + 0 1pt 0 black, + 1pt 0 0 black, + 1pt 1pt 0 black; + } + + & .item-delete-link { + position: absolute; + bottom: 10px; + left: 15px; + } } \ No newline at end of file diff --git a/templates/applications/actors/character-sheet.hbs b/templates/applications/actors/character-sheet.hbs index 24ddd3a..9abc457 100644 --- a/templates/applications/actors/character-sheet.hbs +++ b/templates/applications/actors/character-sheet.hbs @@ -105,44 +105,6 @@ {{/for}}
- -
-
- {{#each items.conditions as |condition cond|}} - {{>systems/wfrp3e/templates/partials/item-condition-card.hbs condition=condition}} - {{/each}} -
- -
- {{#each items.criticalWounds as |wound wnd|}} - {{>systems/wfrp3e/templates/partials/item-wound-card.hbs wound=wound}} - {{/each}} -
- -
- {{#each items.diseases as |disease dis|}} - {{>systems/wfrp3e/templates/partials/item-disease-card.hbs disease=disease}} - {{/each}} -
- -
- {{#each items.insanities as |insanity ins|}} - {{>systems/wfrp3e/templates/partials/item-insanity-card.hbs insanity=insanity}} - {{/each}} -
- -
- {{#each items.mutations as |mutation mut|}} - {{>systems/wfrp3e/templates/partials/item-mutation-card.hbs mutation=mutation}} - {{/each}} -
- -
- {{#each items.miscasts as |miscast mis|}} - {{>systems/wfrp3e/templates/partials/item-miscast-card.hbs miscast=miscast}} - {{/each}} -
-
@@ -238,10 +200,76 @@
+
+ {{localize "CHARACTER.Abilities"}} + + {{#if items.conditions}} + {{localize "CHARACTER.Conditions"}} + {{/if}} + + {{#if items.criticalWounds}} + {{localize "CHARACTER.CriticalWounds"}} + {{/if}} + + {{#if items.diseases}} + {{localize "CHARACTER.Diseases"}} + {{/if}} + + {{#if items.insanities}} + {{localize "CHARACTER.Insanities"}} + {{/if}} + + {{#if items.mutations}} + {{localize "CHARACTER.Mutations"}} + {{/if}} + + {{#if items.miscasts}} + {{localize "CHARACTER.Miscasts"}} + {{/if}} +
+
- {{#each items.abilities as |ability ab|}} - {{>systems/wfrp3e/templates/partials/item-ability-card.hbs ability=ability}} - {{/each}} +
+ {{#each items.abilities as |ability ab|}} + {{>systems/wfrp3e/templates/partials/item-ability-card.hbs ability=ability}} + {{/each}} +
+ +
+ {{#each items.conditions as |condition cond|}} + {{>systems/wfrp3e/templates/partials/item-condition-card.hbs condition=condition}} + {{/each}} +
+ +
+ {{#each items.criticalWounds as |wound wnd|}} + {{>systems/wfrp3e/templates/partials/item-wound-card.hbs wound=wound}} + {{/each}} +
+ +
+ {{#each items.diseases as |disease dis|}} + {{>systems/wfrp3e/templates/partials/item-disease-card.hbs disease=disease}} + {{/each}} +
+ +
+ {{#each items.insanities as |insanity ins|}} + {{>systems/wfrp3e/templates/partials/item-insanity-card.hbs insanity=insanity}} + {{/each}} +
+ +
+ {{#each items.mutations as |mutation mut|}} + {{>systems/wfrp3e/templates/partials/item-mutation-card.hbs mutation=mutation}} + {{/each}} +
+ +
+ {{#each items.miscasts as |miscast mis|}} + {{>systems/wfrp3e/templates/partials/item-miscast-card.hbs miscast=miscast}} + {{/each}} +
From b60ca33c96ff71fe88bae5ad86b682bbcc3152b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Fri, 29 Mar 2024 07:43:08 +0100 Subject: [PATCH 04/25] Fixing fix #42 --- .../applications/actors/character-sheet.hbs | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/templates/applications/actors/character-sheet.hbs b/templates/applications/actors/character-sheet.hbs index 9abc457..aaded81 100644 --- a/templates/applications/actors/character-sheet.hbs +++ b/templates/applications/actors/character-sheet.hbs @@ -94,14 +94,15 @@
{{#for actor.system.stanceMeter.conservative (increment actor.system.stanceMeter.reckless 1) 1}} - - + + {{/for}}
@@ -110,13 +111,21 @@

{{localize "CHARACTER.Skills"}}

- - - {{#each items.skills as |skill sk|}} - {{>systems/wfrp3e/templates/partials/item-skill-row.hbs skill=skill}} - {{/each}} - -
+
+
+ {{localize "SKILL.Name"}} + + {{localize "SKILL.ABBREVIATION.Characteristic"}} + + {{localize "SKILL.TrainingLevel"}} + + +
+ + {{#each items.skills as |skill sk|}} + {{>systems/wfrp3e/templates/partials/item-skill-row.hbs skill=skill}} + {{/each}} +
From c80081ca37e33a0ac0b0c99e9bfc8a0e5ccce83b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Fri, 29 Mar 2024 09:02:24 +0100 Subject: [PATCH 05/25] fix #67 --- lang/en-EN.json | 2 + lang/fr-FR.json | 4 +- modules/CheckHelper.js | 38 ++++++++++++++--- modules/DicePool.js | 26 +++++++++--- modules/applications/DicePoolBuilder.js | 42 +++++++++++++------ .../actors/WFRP3eCharacterSheet.js | 12 ++++++ .../actors/WFRP3eCreatureSheet.js | 14 +++++++ modules/documents/WFRP3eActor.js | 9 ++++ .../applications/actors/creature-sheet.hbs | 38 +++++++++-------- templates/applications/dice-pool-builder.hbs | 5 ++- templates/partials/characteristic-partial.hbs | 32 +++++++------- 11 files changed, 163 insertions(+), 59 deletions(-) diff --git a/lang/en-EN.json b/lang/en-EN.json index cf67406..e1659a5 100644 --- a/lang/en-EN.json +++ b/lang/en-EN.json @@ -363,12 +363,14 @@ "ROLL.DicePoolBuilder": "Dice Pool Builder", "ROLL.ActionCheckBuilder": "{action} Check Builder", + "ROLL.CharacteristicCheckBuilder": "{characteristic} Check Builder", "ROLL.InitiativeCheckBuilder": "Initiative Check Builder", "ROLL.SkillCheckBuilder": "{skill} Check Builder", "ROLL.AvailableEffects": "Available Effects", "ROLL.DicePool": "Dice pool", "ROLL.FreeCheck": "Free check", "ROLL.ActionCheck": "{action} check", + "ROLL.CharacteristicCheck": "{characteristic} check", "ROLL.CombatEncounterInitiativeCheck": "Combat encounter initiative check", "ROLL.SocialEncounterInitiativeCheck": "Social encounter initiative check", "ROLL.SkillCheck": "{skill} check", diff --git a/lang/fr-FR.json b/lang/fr-FR.json index b863b1c..209d2b7 100644 --- a/lang/fr-FR.json +++ b/lang/fr-FR.json @@ -363,12 +363,14 @@ "ROLL.DicePoolBuilder": "Préparateur de réserve de dés", "ROLL.ActionCheckBuilder": "Préparateur du test de {action}", + "ROLL.CharacteristicCheckBuilder": "Préparateur du test de {characteristic}", "ROLL.InitiativeCheckBuilder": "Préparateur du test d'initiative", "ROLL.SkillCheckBuilder": "Préparateur du test de {skill}", - "ROLL.AvailableEffects": "Effects disponibles", + "ROLL.AvailableEffects": "Effets disponibles", "ROLL.DicePool": "Réserve de dés", "ROLL.FreeCheck": "Test libre", "ROLL.ActionCheck": "Test de {action}", + "ROLL.CharacteristicCheck": "Test de {characteristic}", "ROLL.CombatEncounterInitiativeCheck": "Test d'initiative de rencontre de combat", "ROLL.SocialEncounterInitiativeCheck": "Test d'initiative de rencontre sociale", "ROLL.SkillCheck": "Test de {skill}", diff --git a/modules/CheckHelper.js b/modules/CheckHelper.js index a8d50fc..7db9db9 100644 --- a/modules/CheckHelper.js +++ b/modules/CheckHelper.js @@ -6,10 +6,39 @@ import DicePool from "./DicePool.js"; */ export default class CheckHelper { + /** + * Prepares a Characteristic check then opens the Dice Pool Builder afterwards. + * @param {WFRP3eActor} actor The Character making the check. + * @param {Object} characteristic The Characteristic used for the check. + * @param {Object} [options] + * @param {String} [options.flavor] Some flavor text to add to the Skill check's outcome description. + * @param {String} [options.sound] Some sound to play after the Skill check completion. + * @returns {Promise} + */ + static async prepareCharacteristicCheck(actor, characteristic, {flavor = null, sound = null} = {}) + { + const stance = actor.system.stance.current ?? actor.system.stance; + + await new DicePoolBuilder( + new DicePool({ + dice: { + characteristic: characteristic.rating - Math.abs(stance), + fortune: characteristic.fortune, + conservative: stance < 0 ? Math.abs(stance) : 0, + reckless: stance > 0 ? stance : 0 + } + }, { + checkData: {actor, characteristic}, + flavor, + sound + }) + ).render(true); + } + /** * Prepares a Skill check then opens the Dice Pool Builder afterwards. - * @param {WFRP3eActor} actor The Character using the Action. - * @param {WFRP3eItem} skill The Skill check has been triggered. + * @param {WFRP3eActor} actor The Character making the check. + * @param {WFRP3eItem} skill The Skill used for the check. * @param {Object} [options] * @param {String} [options.flavor] Some flavor text to add to the Skill check's outcome description. * @param {String} [options.sound] Some sound to play after the Skill check completion. @@ -30,8 +59,7 @@ export default class CheckHelper reckless: stance > 0 ? stance : 0 } }, { - name: game.i18n.format("ROLL.SkillCheck", {skill: skill.name}), - checkData: {actor: actor, skill: skill, characteristic: skill.system.characteristic}, + checkData: {actor, skill, characteristic: skill.system.characteristic}, flavor, sound }) @@ -93,7 +121,6 @@ export default class CheckHelper : 0) } }, { - name: game.i18n.format("ROLL.ActionCheck", {action: action.name}), checkData, flavor, sound @@ -123,7 +150,6 @@ export default class CheckHelper reckless: stance > 0 ? stance : 0 } }, { - name: game.i18n.localize("ROLL.InitiativeCheckBuilder"), checkData: {actor: actor, characteristic: characteristic, combat}, flavor, sound diff --git a/modules/DicePool.js b/modules/DicePool.js index 4f430cf..6718683 100644 --- a/modules/DicePool.js +++ b/modules/DicePool.js @@ -6,20 +6,19 @@ import FortuneDie from "./dice/FortuneDie.js"; import MisfortuneDie from "./dice/MisfortuneDie.js"; import RecklessDie from "./dice/RecklessDie.js"; import WFRP3eRoll from "./WFRP3eRoll.js"; +import {capitalize} from "./helpers.js"; /** * DicePool utility helps prepare WFRP3e's special dice pools. - * * @param {Object} [startingPool] * @param {Object} [options] - * @param {String} [options.name] - * @param {Object} [options.data] + * @param {Object} [options.checkData] * @param {String} [options.flavor] * @param {String} [options.sound] */ export default class DicePool { - constructor(startingPool = {}, options = {name: game.i18n.localize("ROLL.FreeCheck"), checkData: null, flavor: null, sound: null}) + constructor(startingPool = {}, options = {checkData: null, flavor: null, sound: null}) { this.dice = Object.keys(CONFIG.WFRP3e.dice).reduce((dice, dieName) => { dice[dieName] = startingPool.dice ? startingPool.dice[dieName] ?? 0 : 0; @@ -66,6 +65,22 @@ export default class DicePool }).join("+"); } + get name() + { + if(this.checkData.combat) + return game.i18n.localize(`ROLL.${capitalize(this.check.combat.tags.encounterType)}EncounterInitiativeCheck`); + else if(this.checkData.action) + return game.i18n.format("ROLL.ActionCheck", {action: this.checkData.action.name}); + else if(this.checkData.skill) + return game.i18n.format("ROLL.SkillCheck", {skill: this.checkData.skill.name}); + else if(this.checkData.characteristic) + return game.i18n.format("ROLL.CharacteristicCheck", { + characteristic: game.i18n.localize(CONFIG.WFRP3e.characteristics[this.checkData.characteristic.name].name) + }); + + return game.i18n.localize("ROLL.FreeCheck"); + } + /** * Adds another DicePool to the current one. * @param {DicePool} [otherDicePool] @@ -123,7 +138,8 @@ export default class DicePool } /** - * + * Rolls the Dice Pool, then shows the results in a Message. + * @returns {Promise<*>} */ async roll() { diff --git a/modules/applications/DicePoolBuilder.js b/modules/applications/DicePoolBuilder.js index 4d412ec..9e10a87 100644 --- a/modules/applications/DicePoolBuilder.js +++ b/modules/applications/DicePoolBuilder.js @@ -11,13 +11,19 @@ export default class DicePoolBuilder extends FormApplication /** @inheritDoc */ get title() { - if(this.checkData) { - if(this.checkData.action) - return game.i18n.format("ROLL.ActionCheckBuilder", {action: this.check.data.action.name}); - else if(this.checkData.skill) - return game.i18n.format("ROLL.SkillCheckBuilder", {skill: this.check.data.skill.name}); - else if(this.checkData.combat) + if(this.object.checkData) { + const checkData = this.object.checkData; + + if(checkData.combat) return game.i18n.localize("ROLL.InitiativeCheckBuilder"); + else if(checkData.action) + return game.i18n.format("ROLL.ActionCheckBuilder", {action: checkData.action.name}); + else if(checkData.skill) + return game.i18n.format("ROLL.SkillCheckBuilder", {skill: checkData.skill.name}); + else if(checkData.characteristic) + return game.i18n.format("ROLL.CharacteristicCheckBuilder", { + characteristic: game.i18n.localize(CONFIG.WFRP3e.characteristics[checkData.characteristic.name].name) + }); } return game.i18n.localize("ROLL.CheckBuilder"); @@ -67,12 +73,13 @@ export default class DicePoolBuilder extends FormApplication if(checkData.actor) { const actor = checkData.actor; - data.skills = actor.itemTypes.skill; + data.actor = actor; data.characteristics = Object.entries(CONFIG.WFRP3e.characteristics).reduce((object, characteristic) => { if(characteristic[0] !== "varies") object[characteristic[0]] = characteristic[1].name; return object; }, {}); + data.skills = actor.itemTypes.skill; if(actor.type === "character") { data.maxFortunePoints = actor.system.fortune.value + actor.system.currentParty.system.fortunePool; @@ -90,6 +97,9 @@ export default class DicePoolBuilder extends FormApplication data.attributes = actor.system.attributes; } + if(checkData.characteristic) + data.characteristic = checkData.characteristic; + if(checkData.skill) data.skill = checkData.skill; @@ -475,13 +485,15 @@ export default class DicePoolBuilder extends FormApplication { event.preventDefault(); - const characteristic = this.object.checkData.actor.system.characteristics[event.currentTarget.value]; + this.object.checkData.characteristic = { + name: event.currentTarget.value, + ...this.object.checkData.actor.system.characteristics[event.currentTarget.value] + }; const stance = this.object.checkData.actor.system.stance.current; - this.object.checkData.skill = event.currentTarget.value; mergeObject(this.object.dice, { - characteristic: characteristic.value - Math.abs(stance), - fortune: characteristic.fortune, + characteristic: this.object.checkData.characteristic.value - Math.abs(stance), + fortune: this.object.checkData.characteristic.fortune, conservative: stance < 0 ? Math.abs(stance) : 0, reckless: stance > 0 ? stance : 0 }); @@ -502,9 +514,13 @@ export default class DicePoolBuilder extends FormApplication const skill = this.object.checkData.actor.itemTypes.skill.find(skill => skill._id === event.currentTarget.value); this.object.checkData.skill = skill; - this.object.dice.expertise = skill.system.trainingLevel; - html.find(".characteristic-select").val(skill.system.characteristic).trigger("change"); + if(skill) { + this.object.dice.expertise = skill.system.trainingLevel; + html.find(".characteristic-select").val(skill.system.characteristic).trigger("change"); + } + else + this.object.dice.expertise = 0; this._synchronizeInputs(html); } diff --git a/modules/applications/actors/WFRP3eCharacterSheet.js b/modules/applications/actors/WFRP3eCharacterSheet.js index 98e0bd8..288a7dd 100644 --- a/modules/applications/actors/WFRP3eCharacterSheet.js +++ b/modules/applications/actors/WFRP3eCharacterSheet.js @@ -87,6 +87,8 @@ export default class WFRP3eCharacterSheet extends ActorSheet html.find(".advance-checkbox").change(this._onAdvanceCheckboxChange.bind(this)); + html.find(".characteristic a").click(this._onCharacteristicLink.bind(this)); + html.find(".current-career-input").click(this._onCurrentCareerInput.bind(this)); html.find(".impairment .token") @@ -263,6 +265,16 @@ export default class WFRP3eCharacterSheet extends ActorSheet } } + /** + * Performs follow-up operations after clicks on a Characteristic link. + * @param {MouseEvent} event + * @private + */ + _onCharacteristicLink(event) + { + this.actor.performCharacteristicCheck(event.currentTarget.dataset.characteristic); + } + /** * Performs follow-up operations after clicks on a Career sheet's current radiobox. * @param {MouseEvent} event diff --git a/modules/applications/actors/WFRP3eCreatureSheet.js b/modules/applications/actors/WFRP3eCreatureSheet.js index 0f48bc6..d7f6dd0 100644 --- a/modules/applications/actors/WFRP3eCreatureSheet.js +++ b/modules/applications/actors/WFRP3eCreatureSheet.js @@ -39,6 +39,8 @@ export default class WFRP3eCreatureSheet extends ActorSheet { super.activateListeners(html); + html.find(".characteristic a").click(this._onCharacteristicLink.bind(this)); + html.find(".creature-sheet-stance") .click(this._onStanceLinkLeftClick.bind(this)) .contextmenu(this._onStanceLinkRightClick.bind(this)); @@ -111,6 +113,16 @@ export default class WFRP3eCreatureSheet extends ActorSheet return this.actor.items.get(event.currentTarget.dataset.itemId ?? $(event.currentTarget).parents(".item").data("itemId")); } + /** + * Performs follow-up operations after clicks on a Characteristic link. + * @param {MouseEvent} event + * @private + */ + _onCharacteristicLink(event) + { + this.actor.performCharacteristicCheck(event.currentTarget.dataset.characteristic); + } + /** * Performs follow-up operations after left-clicks on the stance link. * @param {MouseEvent} event @@ -195,6 +207,8 @@ export default class WFRP3eCreatureSheet extends ActorSheet */ async _onItemLeftClick(event) { + event.stopPropagation(); + const item = this._getItemById(event); const options = {}; const face = $(event.currentTarget).parents(".face").data("face"); diff --git a/modules/documents/WFRP3eActor.js b/modules/documents/WFRP3eActor.js index e7240f2..438ef18 100644 --- a/modules/documents/WFRP3eActor.js +++ b/modules/documents/WFRP3eActor.js @@ -3,6 +3,7 @@ import CareerSelector from "../applications/CareerSelector.js"; import CharacteristicUpgrader from "../applications/CharacteristicUpgrader.js"; import TalentSelector from "../applications/TalentSelector.js"; import TrainingSelector from "../applications/TrainingSelector.js"; +import CheckHelper from "../CheckHelper.js"; import {capitalize} from "../helpers.js"; /** @@ -29,6 +30,14 @@ export default class WFRP3eActor extends Actor super.prepareDerivedData(); } + performCharacteristicCheck(characteristic) + { + CheckHelper.prepareCharacteristicCheck( + this, + {name: characteristic, ...this.system.characteristics[characteristic]} + ); + } + /** * Gets the name of Character's current stance. * @returns {string} diff --git a/templates/applications/actors/creature-sheet.hbs b/templates/applications/actors/creature-sheet.hbs index 1dc5a0b..727c817 100644 --- a/templates/applications/actors/creature-sheet.hbs +++ b/templates/applications/actors/creature-sheet.hbs @@ -26,23 +26,27 @@
{{#each actor.system.characteristics as |characteristic char|}} -
- - {{localize (lookup (lookup @root.characteristics char) "abbreviation")}} - - - - - -
+ {{#with (lookup @root.characteristics char) as |charac|}} + + {{/with}} {{/each}}
diff --git a/templates/applications/dice-pool-builder.hbs b/templates/applications/dice-pool-builder.hbs index ea8bce1..eb7def9 100644 --- a/templates/applications/dice-pool-builder.hbs +++ b/templates/applications/dice-pool-builder.hbs @@ -190,12 +190,13 @@
- {{#if skill}} + {{#if actor}}
@@ -204,7 +205,7 @@ {{localize "ROLL.DICEPOOLBUILDER.Characteristic"}} diff --git a/templates/partials/characteristic-partial.hbs b/templates/partials/characteristic-partial.hbs index b3ae68c..0ef1a89 100644 --- a/templates/partials/characteristic-partial.hbs +++ b/templates/partials/characteristic-partial.hbs @@ -1,17 +1,19 @@ -
- {{localize (lookup (lookup @root.characteristics char) "name")}} +{{#with (lookup @root.characteristics char) as |charac|}} +
+ {{localize charac.name}} -
- - - +
+ + + +
-
\ No newline at end of file +{{/with}} \ No newline at end of file From 55114231f6a05202cbab0dd525f282a08ed02d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:21:19 +0200 Subject: [PATCH 06/25] fix #66 --- modules/CheckHelper.js | 79 +++++- modules/WFRP3eRoll.js | 4 +- .../applications/items/WFRP3eActionSheet.js | 2 +- modules/handlebars.js | 3 +- templates/applications/career-selector.hbs | 2 +- templates/applications/dice-pool-builder.hbs | 14 +- templates/applications/items/action-sheet.hbs | 250 +++++++++--------- templates/partials/action-effects.hbs | 52 ++-- templates/partials/impairment-partial.hbs | 4 +- templates/partials/item-action-card.hbs | 6 +- 10 files changed, 242 insertions(+), 174 deletions(-) diff --git a/modules/CheckHelper.js b/modules/CheckHelper.js index 7db9db9..eb52804 100644 --- a/modules/CheckHelper.js +++ b/modules/CheckHelper.js @@ -210,27 +210,80 @@ export default class CheckHelper /** * Toggles effects from a Roll, depending on the symbols remaining. - * @param chatMessageId The id of the ChatMessage containing the Roll. - * @param symbol The symbol of the effect to toggle. - * @param index The index of the effect to toggle. + * @param {String} chatMessageId The id of the ChatMessage containing the Roll. + * @param {String} symbol The symbol of the effect to toggle. + * @param {Number} index The index of the effect to toggle. */ static toggleEffect(chatMessageId, symbol, index) { const chatMessage = game.messages.get(chatMessageId); const changes = {rolls: chatMessage.rolls}; + const roll = changes.rolls[0]; + const toggledEffect = roll.effects[symbol][index]; + const plural = CONFIG.WFRP3e.symbols[symbol].plural; - if(changes.rolls[0].effects[symbol][index].active === true) - changes.rolls[0].effects[symbol][index].active = false; - else if(changes.rolls[0].remainingSymbols[CONFIG.WFRP3e.symbols[symbol].plural] >= changes.rolls[0].effects[symbol][index].symbolAmount) - changes.rolls[0].effects[symbol][index].active = true; + if(toggledEffect.active === true) + toggledEffect.active = false; + // Delay/Exertion + Bane effects. + else if(["delay", "exertion"].includes(symbol)) { + if(roll.remainingSymbols[plural] > 0) { + if(toggledEffect.symbolAmount > 1) { + if(roll.remainingSymbols.banes >= toggledEffect.symbolAmount - 1) + toggledEffect.active = true; + else + ui.notifications.warn(game.i18n.format("ROLL.NotEnoughSymbolToTriggerEffect", { + symbol: game.i18n.localize(CONFIG.WFRP3e.symbols.bane.name) + })); + } + else + toggledEffect.active = true; + } + else + ui.notifications.warn(game.i18n.format("ROLL.NotEnoughSymbolToTriggerEffect", { + symbol: game.i18n.localize(CONFIG.WFRP3e.symbols[symbol].name) + })); + } + // Sigmar's Comet as Success/Boon. + else if(["success", "boon"].includes(symbol) && (roll.remainingSymbols[plural] + roll.remainingSymbols.sigmarsComets >= toggledEffect.symbolAmount)) + toggledEffect.active = true; + // Default. + else if(roll.remainingSymbols[plural] >= toggledEffect.symbolAmount) + toggledEffect.active = true; else - ui.notifications.warn(game.i18n.format("ROLL.NotEnoughSymbolToTriggerEffect", {symbol: game.i18n.localize(CONFIG.WFRP3e.symbols[symbol].name)})); + ui.notifications.warn(game.i18n.format("ROLL.NotEnoughSymbolToTriggerEffect", { + symbol: game.i18n.localize(CONFIG.WFRP3e.symbols[symbol].name) + })); + + roll.remainingSymbols = {...roll.resultSymbols}; + + // Recalculate remaining symbols for every type. + Object.entries(roll.effects).forEach(effects => { + const symbolName = effects[0]; + const plural = CONFIG.WFRP3e.symbols[symbolName].plural; - changes.rolls[0].remainingSymbols[CONFIG.WFRP3e.symbols[symbol].plural] = changes.rolls[0].effects[symbol].reduce((accumulator, effect) => { - if(effect.active) - accumulator -= effect.symbolAmount; - return accumulator; - }, changes.rolls[0].resultSymbols[CONFIG.WFRP3e.symbols[symbol].plural]); + roll.remainingSymbols[plural] = effects[1].filter(effect => effect.active) + .reduce((remainingSymbols, effect) => { + if(["delay", "exertion"].includes(symbolName)) { + remainingSymbols--; + + if(effect.symbolAmount > 1) + roll.remainingSymbols.banes -= effect.symbolAmount - 1; + } + else if(remainingSymbols < effect.symbolAmount) { + if(["success", "boon"].includes(symbolName) + && (remainingSymbols + roll.remainingSymbols.sigmarsComets >= effect.symbolAmount)) { + roll.remainingSymbols.sigmarsComets += remainingSymbols - effect.symbolAmount; + return 0; + } + + throw new Error(`The remaining number of ${symbolName} cannot be negative.`); + } + else + remainingSymbols -= effect.symbolAmount; + + return remainingSymbols; + }, roll.remainingSymbols[plural]); + }); chatMessage.update(changes); } diff --git a/modules/WFRP3eRoll.js b/modules/WFRP3eRoll.js index 5b0f088..b18f1c6 100644 --- a/modules/WFRP3eRoll.js +++ b/modules/WFRP3eRoll.js @@ -216,9 +216,9 @@ export default class WFRP3eRoll extends Roll user: game.user.id, tooltip: isPrivate ? "" : await this.getTooltip(), total: isPrivate ? "?" : Math.round(this.total * 100) / 100, - action: this.options?.data?.action, + action: this.options?.checkData?.action, effects: this.effects, - face: this.options?.data?.face, + face: this.options?.checkData?.face, hasSpecialDice: this.hasSpecialDice, hasStandardDice: this.hasStandardDice, publicRoll: !isPrivate, diff --git a/modules/applications/items/WFRP3eActionSheet.js b/modules/applications/items/WFRP3eActionSheet.js index 5251629..142b3ee 100644 --- a/modules/applications/items/WFRP3eActionSheet.js +++ b/modules/applications/items/WFRP3eActionSheet.js @@ -5,7 +5,7 @@ export default class WFRP3eActionSheet extends ItemSheet return { ...super.defaultOptions, template: "systems/wfrp3e/templates/applications/items/action-sheet.hbs", - width: 540, + width: 550, height: 680, classes: ["wfrp3e", "sheet", "item", "action"], tabs: [ diff --git a/modules/handlebars.js b/modules/handlebars.js index ddddc16..22c6a03 100644 --- a/modules/handlebars.js +++ b/modules/handlebars.js @@ -4,6 +4,7 @@ export default function() { Hooks.on("init", () => { Handlebars.registerHelper("and", (firstCondition, secondCondition) => firstCondition === true && secondCondition === true); + Handlebars.registerHelper("or", (firstCondition, secondCondition) => firstCondition === true || secondCondition === true); Handlebars.registerHelper("superiorTo", (value, compareValue) => Number(value) > Number(compareValue)); Handlebars.registerHelper("inferiorTo", (value, compareValue) => Number(value) < Number(compareValue)); Handlebars.registerHelper("equalTo", (value, compareValue) => value == compareValue); @@ -13,7 +14,7 @@ export default function() Handlebars.registerHelper("inferiorOrEqualTo", (value, compareValue) => Number(value) <= Number(compareValue)); Handlebars.registerHelper("increment", (value, valueToAdd) => value + parseInt(valueToAdd)); Handlebars.registerHelper("multiply", (value, multiplier) => value * multiplier); - Handlebars.registerHelper("concat", (value, otherValue) => value.toString() + otherValue.toString()); + Handlebars.registerHelper("concat", () => arguments.join()); Handlebars.registerHelper("capitalize", (string) => capitalize(string)); Handlebars.registerHelper("abs", (number) => Math.abs(number)); Handlebars.registerHelper("in", (value, array) => array.includes(value)); diff --git a/templates/applications/career-selector.hbs b/templates/applications/career-selector.hbs index 2fdf0ad..eef2d44 100644 --- a/templates/applications/career-selector.hbs +++ b/templates/applications/career-selector.hbs @@ -7,7 +7,7 @@ {{inferiorTo object.system.rank 2}} {{#unless (and (equalTo ty "advanced") (inferiorTo @root.object.system.rank 2))}} - {{localize (concat (concat "CAREER.SHEET." (capitalize ty)) "Career")}} + {{localize (concat "CAREER.SHEET." (capitalize ty) "Career")}} {{else}} diff --git a/templates/applications/dice-pool-builder.hbs b/templates/applications/dice-pool-builder.hbs index eb7def9..efd7da1 100644 --- a/templates/applications/dice-pool-builder.hbs +++ b/templates/applications/dice-pool-builder.hbs @@ -12,7 +12,7 @@ {{/each}}
@@ -31,7 +31,7 @@ type="number" min="0" max="{{attribute.budget}}" /> -
{{localize (concat (concat "ROLL.DICEPOOLBUILDER." (capitalize attr)) "Dice")}}
+
{{localize (concat "ROLL.DICEPOOLBUILDER." (capitalize attr) "Dice")}}
{{/each}}
@@ -196,8 +196,8 @@ {{localize "ROLL.DICEPOOLBUILDER.Skill"}} @@ -205,7 +205,7 @@ {{localize "ROLL.DICEPOOLBUILDER.Characteristic"}} @@ -213,7 +213,7 @@ {{localize "ROLL.DICEPOOLBUILDER.ChallengeLevel"}} @@ -228,7 +228,7 @@ {{localize "ROLL.DICEPOOLBUILDER.Weapon"}} {{/if}} diff --git a/templates/applications/items/action-sheet.hbs b/templates/applications/items/action-sheet.hbs index a9ef1a5..3a16f1d 100644 --- a/templates/applications/items/action-sheet.hbs +++ b/templates/applications/items/action-sheet.hbs @@ -22,147 +22,149 @@
{{#each @root.stances as |stance st|}} -
- - -
-
-
+
+ - -
+ +
-
- -
- - - -
- - -
- -
-
- - - {{#each @root.symbols as |symbol sym|}} -
- - - - {{#each (lookup (lookup (lookup @root.item.system st) "effects") sym) as |effect ef|}} -
- - - {{editor effect.description - target=(concat (concat (concat (concat (concat (concat "system." st) ".effects.") sym) ".") ef) ".description") - button=true - owner=@root.owner - editable=@root.editable}} - - - - -
- {{/each}} -
- {{/each}} -
- - - - {{editor (lookup (lookup @root.item.system st) "special") target=(concat (concat "system." st) ".special") button=true owner=owner editable=@root.editable}} - - - - - {{editor (lookup (lookup @root.item.system st) "uniqueEffect") target=(concat (concat "system." st) ".uniqueEffect") button=true owner=@root.owner editable=@root.editable}} - +
+ +
+
+ + + {{#each @root.symbols as |symbol sym|}} +
+ + + + {{#each (lookup face.effects sym) as |effect ef|}} +
+ + + {{editor effect.description + target=(concat "system." st ".effects." sym "." ef ".description") + button=true + owner=@root.owner + editable=@root.editable}} + + + + +
+ {{/each}} +
+ {{/each}} +
+ + + + {{editor face.special target=(concat "system." st ".special") button=true owner=owner editable=@root.editable}} + + + + + {{editor face.uniqueEffect target=(concat "system." st ".uniqueEffect") button=true owner=@root.owner editable=@root.editable}} + +
- + {{/with}} {{/each}}
\ No newline at end of file diff --git a/templates/partials/action-effects.hbs b/templates/partials/action-effects.hbs index 1dde5d3..82f8b48 100644 --- a/templates/partials/action-effects.hbs +++ b/templates/partials/action-effects.hbs @@ -3,29 +3,37 @@ - {{#if (lookup (lookup action.system face) 'special')}} - - {{/if}} - - {{#if (lookup (lookup action.system face) 'uniqueEffect')}} - - {{/if}} - - {{#each symbols as |symbol sym|}} - {{#if (lookup ../effects sym)}} - + {{#with (lookup action.system face) as |face|}} + {{#if face.special}} + {{/if}} - {{/each}} + + {{#if face.uniqueEffect}} + + {{/if}} + + {{#each ../symbols as |symbol sym|}} + {{#with (lookup ../../effects sym) as |effects|}} + {{#if effects}} + + {{/if}} + {{/with}} + {{/each}} + {{/with}}
{{{striptags (lookup (lookup action.system face) 'special') 'p'}}}
{{{striptags (lookup (lookup action.system face) 'uniqueEffect') 'p'}}}
- {{#each (lookup ../effects sym) as |effect ef|}} - - {{#for 0 effect.symbolAmount 1}} - - {{/for}} - - {{{striptags effect.description 'p'}}} - - {{/each}} -
{{{striptags face.special 'p'}}}
{{{striptags face.uniqueEffect 'p'}}}
+ {{#each effects as |effect ef|}} + + {{#for 0 effect.symbolAmount 1}} + {{#unless (and (or (sameAs sym "delay") (sameAs sym "exertion")) (superiorTo this 0))}} + + {{else}} + + {{/unless}} + {{/for}} + + {{{striptags effect.description 'p'}}} + + {{/each}} +
\ No newline at end of file diff --git a/templates/partials/impairment-partial.hbs b/templates/partials/impairment-partial.hbs index 46d400b..b2ae862 100644 --- a/templates/partials/impairment-partial.hbs +++ b/templates/partials/impairment-partial.hbs @@ -1,6 +1,6 @@
- - {{localize (concat (concat + + {{localize (concat {{lookup actor.system.impairments impairment}} diff --git a/templates/partials/item-action-card.hbs b/templates/partials/item-action-card.hbs index 63ba9c3..3f8b0b9 100644 --- a/templates/partials/item-action-card.hbs +++ b/templates/partials/item-action-card.hbs @@ -46,7 +46,11 @@ {{#each effects as |effect ef|}}
{{#for 0 effect.symbolAmount 1}} - + {{#unless (and (or (sameAs sym "delay") (sameAs sym "exertion")) (superiorTo this 0))}} + + {{else}} + + {{/unless}} {{/for}} {{{striptags effect.description "p"}}} From 0e0f86d556748e17a396af0c742fc16e3943d051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:25:39 +0200 Subject: [PATCH 07/25] Changing universal effects localization keys --- lang/en-EN.json | 10 +++++----- lang/fr-FR.json | 10 +++++----- modules/CheckHelper.js | 28 ++++++++++++++++++++++------ 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/lang/en-EN.json b/lang/en-EN.json index e1659a5..c7efc7b 100644 --- a/lang/en-EN.json +++ b/lang/en-EN.json @@ -458,11 +458,11 @@ "ROLL.SYMBOL.Exertions": "exertions", "ROLL.SYMBOL.Successes": "successes", "ROLL.SYMBOL.SigmarsComets": "Sigmar's comets", - "ROLL.UNIVERSAL.PhysicalBoon": "Recover 1 fatigue", - "ROLL.UNIVERSAL.MentalBoon": "Recover 1 stress", - "ROLL.UNIVERSAL.PhysicalBane": "Suffer 1 fatigue", - "ROLL.UNIVERSAL.MentalBane": "Suffer 1 stress", - "ROLL.UNIVERSAL.SigmarsComet": "+1 critical", + "ROLL.EFFECT.RecoverFatigue": "Recover 1 fatigue", + "ROLL.EFFECT.RecoverStress": "Recover 1 stress", + "ROLL.EFFECT.SufferFatigue": "Suffer 1 fatigue", + "ROLL.EFFECT.SufferStress": "Suffer 1 stress", + "ROLL.EFFECT.Critical": "+1 critical", "SKILL.AdvancedSkill": "Advanced Skill", "SKILL.Characteristic": "Characteristic", diff --git a/lang/fr-FR.json b/lang/fr-FR.json index 209d2b7..4d83f9f 100644 --- a/lang/fr-FR.json +++ b/lang/fr-FR.json @@ -458,11 +458,11 @@ "ROLL.SYMBOL.Exertions": "efforts", "ROLL.SYMBOL.Successes": "succès", "ROLL.SYMBOL.SigmarsComets": "comètes de Sigmar", - "ROLL.UNIVERSAL.PhysicalBoon": "Recover 1 fatigue", - "ROLL.UNIVERSAL.MentalBoon": "Recover 1 stress", - "ROLL.UNIVERSAL.PhysicalBane": "Suffer 1 fatigue", - "ROLL.UNIVERSAL.MentalBane": "Suffer 1 stress", - "ROLL.UNIVERSAL.SigmarsComet": "+1 critical", + "ROLL.EFFECT.RecoverFatigue": "Recover {amount} fatigue", + "ROLL.EFFECT.RecoverStress": "Recover {amount} stress", + "ROLL.EFFECT.SufferFatigue": "Suffer {amount} fatigue", + "ROLL.EFFECT.SufferStress": "Suffer {amount} stress", + "ROLL.EFFECT.Critical": "+{amount} critical", "SKILL.AdvancedSkill": "Compétence Avancée", "SKILL.Characteristic": "Caractéristique", diff --git a/modules/CheckHelper.js b/modules/CheckHelper.js index eb52804..96d4855 100644 --- a/modules/CheckHelper.js +++ b/modules/CheckHelper.js @@ -170,41 +170,57 @@ export default class CheckHelper /** * Get the universal boon effect. * @param {boolean} isMental Whether the check is based upon a mental characteristic. + * @returns {{symbolAmount: Number, description: String}} */ static getUniversalBoonEffect(isMental) { return isMental ? { symbolAmount: 2, - description: game.i18n.localize("ROLL.UNIVERSAL.MentalBoon") + description: game.i18n.format("ROLL.EFFECT.RecoverFatigue", {amount: 1}) } : { symbolAmount: 2, - description: game.i18n.localize("ROLL.UNIVERSAL.PhysicalBoon") + description: game.i18n.format("ROLL.EFFECT.RecoverStress", {amount: 1}) }; } /** - * Get the universal boon effect. + * Get the universal bane effect. * @param {boolean} isMental Whether the check is based upon a mental characteristic. + * @returns {{symbolAmount: Number, description: String}} */ static getUniversalBaneEffect(isMental) { return isMental ? { symbolAmount: 2, - description: game.i18n.localize("ROLL.UNIVERSAL.MentalBane") + description: game.i18n.format("ROLL.EFFECT.SufferFatigue", {amount: 1}) } : { symbolAmount: 2, - description: game.i18n.localize("ROLL.UNIVERSAL.PhysicalBane") + description: game.i18n.format("ROLL.EFFECT.SufferStress", {amount: 1}) + }; + } + + /** + * Get the weapon's Critical Rating effect. + * @param {WFRP3eItem} weapon + * @returns {{symbolAmount: Number, description: String}} + */ + static getCriticalRatingEffect(weapon) + { + return { + symbolAmount: weapon.system.criticalRating, + description: game.i18n.format("ROLL.EFFECT.Critical", {amount: 1}) }; } /** * Get the universal Sigmar's comet effect. + * @returns {{symbolAmount: Number, description: String}} */ static getUniversalSigmarsCometEffect() { return { symbolAmount: 1, - description: game.i18n.localize("ROLL.UNIVERSAL.SigmarsComet") + description: game.i18n.format("ROLL.EFFECT.Critical", {amount: 1}) }; } From 629731e40ee938dabbb694e2064fc2d4aef122bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:27:43 +0200 Subject: [PATCH 08/25] Adding a Basic trait localization key --- lang/en-EN.json | 1 + lang/fr-FR.json | 1 + modules/applications/ActionSelector.js | 5 +++-- modules/applications/CharacterGenerator.js | 8 +++++--- modules/applications/actors/WFRP3eCharacterSheet.js | 5 +++-- modules/applications/actors/WFRP3eCreatureSheet.js | 5 +++-- 6 files changed, 16 insertions(+), 9 deletions(-) diff --git a/lang/en-EN.json b/lang/en-EN.json index c7efc7b..8bc366a 100644 --- a/lang/en-EN.json +++ b/lang/en-EN.json @@ -35,6 +35,7 @@ "ACTION.EFFECT.SymbolAmount": "Symbol Amount", "ACTION.FACE.Conservative": "Conservative", "ACTION.FACE.Reckless": "Reckless", + "ACTION.TRAITS.Basic": "Base", "ACTION.TYPE.Melee": "Melee", "ACTION.TYPE.Ranged": "Ranged", "ACTION.TYPE.Support": "Support", diff --git a/lang/fr-FR.json b/lang/fr-FR.json index 4d83f9f..319d407 100644 --- a/lang/fr-FR.json +++ b/lang/fr-FR.json @@ -35,6 +35,7 @@ "ACTION.EFFECT.SymbolAmount": "Symbol Amount", "ACTION.FACE.Conservative": "Prudence", "ACTION.FACE.Reckless": "Téméraire", + "ACTION.TRAITS.Basic": "Base", "ACTION.TYPE.Melee": "Mêlée", "ACTION.TYPE.Ranged": "Distance", "ACTION.TYPE.Support": "Support", diff --git a/modules/applications/ActionSelector.js b/modules/applications/ActionSelector.js index f786920..4be08e8 100644 --- a/modules/applications/ActionSelector.js +++ b/modules/applications/ActionSelector.js @@ -87,9 +87,10 @@ export default class ActionSelector extends FormApplication } this.allActions = actions.sort((a, b) => { - if(a.system.conservative.traits.includes("Basic") && !b.system.conservative.traits.includes("Basic")) + const basicTrait = game.i18n.localize("ACTION.TRAITS.Basic"); + if(a.system.conservative.traits.includes(basicTrait) && !b.system.conservative.traits.includes(basicTrait)) return -1; - else if(!a.system.conservative.traits.includes("Basic") && b.system.conservative.traits.includes("Basic")) + else if(!a.system.conservative.traits.includes(basicTrait) && b.system.conservative.traits.includes(basicTrait)) return 1 else if(a.name < b.name) return -1; diff --git a/modules/applications/CharacterGenerator.js b/modules/applications/CharacterGenerator.js index 30c9d8d..d2c1ab7 100644 --- a/modules/applications/CharacterGenerator.js +++ b/modules/applications/CharacterGenerator.js @@ -874,7 +874,8 @@ export default class CharacterGenerator extends FormApplication || (actionType === "blessing" && this.priest) || (actionType === "spell" && this.wizard)) everyActions[actionType] = this.actions.filter(action => { - return action.system.type === actionType && !action.system.conservative.traits.includes("Basic"); + return action.system.type === actionType + && !action.system.conservative.traits.includes(game.i18n.localize("ACTION.TRAITS.Basic")); }); return everyActions; @@ -984,7 +985,8 @@ export default class CharacterGenerator extends FormApplication // Add every Basic Support Actions, except Block, Dodge and Parry if their requirements are not met. this.actions - .filter(action => action.system.type === "support" && action.system.conservative.traits.includes("Basic")) + .filter(action => action.system.type === "support" + && action.system.conservative.traits.includes(game.i18n.localize("ACTION.TRAITS.Basic"))) .forEach(action => { if((action._id === "gevnvkwHS62NBrpf" && this.characteristicRatings.toughness >= 3) || (action._id === "eXHXyTK445ZEARTB" && this.characteristicRatings.agility >= 3) @@ -1001,7 +1003,7 @@ export default class CharacterGenerator extends FormApplication // Add Minor Blessing, Minor Ward, and Blessing of Health to Priests who have acquired Invocation. if(this.chosenTrainingsAndSpecialisations["ekPGMSRCHYlLWWZS"].acquired) this.finalActions.push(...this.actions.filter(action => action.system.type === "blessing" - && action.system.reckless.traits.includes("Basic") + && action.system.reckless.traits.includes(game.i18n.localize("ACTION.TRAITS.Basic")) && action._id !== "b1Zbbl8fybXf8gkI")); } diff --git a/modules/applications/actors/WFRP3eCharacterSheet.js b/modules/applications/actors/WFRP3eCharacterSheet.js index 288a7dd..b3cab91 100644 --- a/modules/applications/actors/WFRP3eCharacterSheet.js +++ b/modules/applications/actors/WFRP3eCharacterSheet.js @@ -127,11 +127,12 @@ export default class WFRP3eCharacterSheet extends ActorSheet */ _buildItemLists(items) { + const basicTrait = game.i18n.localize("ACTION.TRAITS.Basic"); const sortedItems = items.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0); const actions = sortedItems.filter(item => item.type === "action").sort((a, b) => { - if(a.system.conservative.traits.includes("Basic") && !b.system.conservative.traits.includes("Basic")) + if(a.system.conservative.traits.includes(basicTrait) && !b.system.conservative.traits.includes(basicTrait)) return -1; - else if(!a.system.conservative.traits.includes("Basic") && b.system.conservative.traits.includes("Basic")) + else if(!a.system.conservative.traits.includes(basicTrait) && b.system.conservative.traits.includes(basicTrait)) return 1 else return 0; diff --git a/modules/applications/actors/WFRP3eCreatureSheet.js b/modules/applications/actors/WFRP3eCreatureSheet.js index d7f6dd0..044ad25 100644 --- a/modules/applications/actors/WFRP3eCreatureSheet.js +++ b/modules/applications/actors/WFRP3eCreatureSheet.js @@ -67,11 +67,12 @@ export default class WFRP3eCreatureSheet extends ActorSheet */ _buildItemLists(items) { + const basicTrait = game.i18n.localize("ACTION.TRAITS.Basic"); const sortedItems = items.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0); const actions = sortedItems.filter(item => item.type === "action").sort((a, b) => { - if(a.system.conservative.traits.includes("Basic") && !b.system.conservative.traits.includes("Basic")) + if(a.system.conservative.traits.includes(basicTrait) && !b.system.conservative.traits.includes(basicTrait)) return -1; - else if(!a.system.conservative.traits.includes("Basic") && b.system.conservative.traits.includes("Basic")) + else if(!a.system.conservative.traits.includes(basicTrait) && b.system.conservative.traits.includes(basicTrait)) return 1 else return 0; From f884655cb3084e2b6375654b021127dae5d766bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:28:05 +0200 Subject: [PATCH 09/25] Fixing Abilities tab on Character sheets --- modules/applications/actors/WFRP3eCharacterSheet.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/applications/actors/WFRP3eCharacterSheet.js b/modules/applications/actors/WFRP3eCharacterSheet.js index b3cab91..67422b2 100644 --- a/modules/applications/actors/WFRP3eCharacterSheet.js +++ b/modules/applications/actors/WFRP3eCharacterSheet.js @@ -21,7 +21,8 @@ export default class WFRP3eCharacterSheet extends ActorSheet {group: "primary", navSelector: ".primary-tabs", contentSelector: ".character-sheet-body", initial: "characteristics"}, {group: "careers", navSelector: ".character-sheet-career-tabs", contentSelector: ".character-sheet-careers"}, {group: "talents", navSelector: ".character-sheet-talent-tabs", contentSelector: ".character-sheet-talents", initial: "focus"}, - {group: "actions", navSelector: ".character-sheet-action-tabs", contentSelector: ".character-sheet-actions", initial: "melee"} + {group: "actions", navSelector: ".character-sheet-action-tabs", contentSelector: ".character-sheet-actions", initial: "melee"}, + {group: "abilities", navSelector: ".character-sheet-ability-tabs", contentSelector: ".character-sheet-abilities", initial: "ability"} ] }; } From 9c00c53ca9f7a40e7b4a8ac287262a7b014b168b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:28:41 +0200 Subject: [PATCH 10/25] Fixing skill row expansion --- modules/applications/actors/WFRP3eCharacterSheet.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/applications/actors/WFRP3eCharacterSheet.js b/modules/applications/actors/WFRP3eCharacterSheet.js index 67422b2..3b9d19a 100644 --- a/modules/applications/actors/WFRP3eCharacterSheet.js +++ b/modules/applications/actors/WFRP3eCharacterSheet.js @@ -99,7 +99,7 @@ export default class WFRP3eCharacterSheet extends ActorSheet html.find(".flip-link").click(this._onFlipClick.bind(this)); html.find(".item-roll-link").click(this._onItemRoll.bind(this)); - html.find(".item.row, .item-expand-link").click(this._onItemExpandClick.bind(this)); + html.find(".item-expand-link").click(this._onItemExpandClick.bind(this)); html.find(".item-edit-link").click(this._onItemEdit.bind(this)); html.find(".item-delete-link").click(this._onItemDelete.bind(this)); @@ -416,6 +416,8 @@ export default class WFRP3eCharacterSheet extends ActorSheet */ async _onItemLeftClick(event) { + event.stopPropagation(); + const options = {}; const face = $(event.currentTarget).parents(".face").data("face"); From 57048f5c33ae488dd0ef0a6adda50cbd4968d7c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:29:14 +0200 Subject: [PATCH 11/25] Refactoring _onSkillTrainingLevelChange() --- modules/applications/actors/WFRP3eCharacterSheet.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/applications/actors/WFRP3eCharacterSheet.js b/modules/applications/actors/WFRP3eCharacterSheet.js index 3b9d19a..4bee101 100644 --- a/modules/applications/actors/WFRP3eCharacterSheet.js +++ b/modules/applications/actors/WFRP3eCharacterSheet.js @@ -369,7 +369,7 @@ export default class WFRP3eCharacterSheet extends ActorSheet this._getItemById(event).useItem(options); } - /**² + /** * Performs follow-up operations after clicks on an Item edit button. * @param {MouseEvent} event * @private @@ -547,11 +547,11 @@ export default class WFRP3eCharacterSheet extends ActorSheet { event.preventDefault(); - const clickedItem = this.actor.items.get($(event.currentTarget).parents("tr").attr("data-item-id")); + const item = this._getItemById(event); if(event.target.defaultChecked) - clickedItem.update({"system.trainingLevel": Number(event.target.value - 1)}); + item.update({"system.trainingLevel": Number(event.target.value - 1)}); else - clickedItem.update({"system.trainingLevel": Number(event.target.value)}); + item.update({"system.trainingLevel": Number(event.target.value)}); } } \ No newline at end of file From 1fce36399729e10a5ff2ba251a4bc5131c8355a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:30:11 +0200 Subject: [PATCH 12/25] Fixing DicePoolBuilder's _onChangeInput() --- modules/applications/DicePoolBuilder.js | 2 +- modules/applications/sidebar/WFRP3eCombatTracker.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/applications/DicePoolBuilder.js b/modules/applications/DicePoolBuilder.js index 9e10a87..f2017cd 100644 --- a/modules/applications/DicePoolBuilder.js +++ b/modules/applications/DicePoolBuilder.js @@ -166,7 +166,7 @@ export default class DicePoolBuilder extends FormApplication value = element.value; } - setProperty(this.object, event.currentTarget.name, isNaN(value) ? value : Number(value)); + setProperty(this.object, event.currentTarget.name, Array.isArray(value) || isNaN(value) ? value : Number(value)); this._updatePreview(); } diff --git a/modules/applications/sidebar/WFRP3eCombatTracker.js b/modules/applications/sidebar/WFRP3eCombatTracker.js index dec3b3c..d0cefa9 100644 --- a/modules/applications/sidebar/WFRP3eCombatTracker.js +++ b/modules/applications/sidebar/WFRP3eCombatTracker.js @@ -29,8 +29,10 @@ export default class WFRP3eCombatTracker extends CombatTracker { event.preventDefault(); + const value = event.currentTarget.value; const updates = {}; - updates[event.currentTarget.name] = isNaN(event.currentTarget.value) ? event.currentTarget.value : Number(event.currentTarget.value); + + updates[event.currentTarget.name] = Array.isArray(value) || isNaN(value) ? value : Number(value); this.viewed.update(updates); } From d29c083caa9b5b1a6150dee6fa8018869f2758a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:30:53 +0200 Subject: [PATCH 13/25] Fixing Challenge Level select --- modules/applications/DicePoolBuilder.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/applications/DicePoolBuilder.js b/modules/applications/DicePoolBuilder.js index f2017cd..cbc595c 100644 --- a/modules/applications/DicePoolBuilder.js +++ b/modules/applications/DicePoolBuilder.js @@ -468,11 +468,11 @@ export default class DicePoolBuilder extends FormApplication const challengeLevel = CONFIG.WFRP3e.challengeLevels[event.currentTarget.value]; this.object.checkData.challengeLevel = event.currentTarget.value; - this.object.dice.challenge = this.object.checkData.action?.system[this.object.checkData.face].difficultyModifiers.challengeDice ?? 0 + + this.object.dice.challenge = (this.object.checkData.action?.system[this.object.checkData.face].difficultyModifiers.challengeDice ?? 0) + (["melee", "ranged"].includes(this.object.checkData.action?.system.type) ? 1 : 0) + challengeLevel.challengeDice; - this._synchronizeInputs(html, html); + this._synchronizeInputs(html); } /** From 39ab70b96ffe35d95c070ba7f2bdee3e6a64f04b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:31:13 +0200 Subject: [PATCH 14/25] Refactoring _useAction() --- modules/documents/WFRP3eItem.js | 70 ++++++++++++++++----------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/modules/documents/WFRP3eItem.js b/modules/documents/WFRP3eItem.js index 6f8b89e..f31314c 100644 --- a/modules/documents/WFRP3eItem.js +++ b/modules/documents/WFRP3eItem.js @@ -40,43 +40,41 @@ export default class WFRP3eItem extends Item if(this.system.rechargeTokens > 0) ui.notifications.warn(game.i18n.localize("ACTION.Recharging")); - else { - if (CheckHelper.doesRequireNoCheck(this.system[options.face].check)) - await new Dialog({ - title: game.i18n.localize("APPLICATION.TITLE.ActionUsage"), - content: "

" + game.i18n.format("APPLICATION.DESCRIPTION.ActionUsage", {action: this.system[options.face].name}) + "

", - buttons: { - confirm: { - icon: '', - label: game.i18n.localize("Yes"), - callback: async dlg => { - this.exhaustAction(options.face); - - return ChatMessage.create({ - content: await renderTemplate("systems/wfrp3e/templates/partials/action-effects.hbs", { - action: this, - face: options.face, - symbols: CONFIG.WFRP3e.symbols, - effects: this.system[options.face].effects - }), - flavor: game.i18n.format("ACTION.UsageMessage", { - actor: this.actor.name, - action: this.system[options.face].name - }), - speaker: ChatMessage.getSpeaker({actor: this.actor}) - }); - } - }, - cancel: { - icon: '', - label: game.i18n.localize("Cancel") - }, + else if(CheckHelper.doesRequireNoCheck(this.system[options.face].check)) + await new Dialog({ + title: game.i18n.localize("APPLICATION.TITLE.ActionUsage"), + content: "

" + game.i18n.format("APPLICATION.DESCRIPTION.ActionUsage", {action: this.system[options.face].name}) + "

", + buttons: { + confirm: { + icon: '', + label: game.i18n.localize("Yes"), + callback: async dlg => { + this.exhaustAction(options.face); + + return ChatMessage.create({ + content: await renderTemplate("systems/wfrp3e/templates/partials/action-effects.hbs", { + action: this, + face: options.face, + symbols: CONFIG.WFRP3e.symbols, + effects: this.system[options.face].effects + }), + flavor: game.i18n.format("ACTION.UsageMessage", { + actor: this.actor.name, + action: this.system[options.face].name + }), + speaker: ChatMessage.getSpeaker({actor: this.actor}) + }); + } }, - default: "confirm" - }).render(true); - else - await CheckHelper.prepareActionCheck(this.actor, this, options.face); - } + cancel: { + icon: '', + label: game.i18n.localize("Cancel") + }, + }, + default: "confirm" + }).render(true); + else + await CheckHelper.prepareActionCheck(this.actor, this, options.face); } /** From 4c8a93bc464da6f9de46e71c90ed66ab1cbce8c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:33:38 +0200 Subject: [PATCH 15/25] Fixing characteristic object on DicePoolBuilder --- modules/CheckHelper.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/CheckHelper.js b/modules/CheckHelper.js index 96d4855..aa25214 100644 --- a/modules/CheckHelper.js +++ b/modules/CheckHelper.js @@ -59,7 +59,7 @@ export default class CheckHelper reckless: stance > 0 ? stance : 0 } }, { - checkData: {actor, skill, characteristic: skill.system.characteristic}, + checkData: {actor, skill, characteristic: {name: skill.system.characteristic, ...characteristic}}, flavor, sound }) @@ -92,7 +92,7 @@ export default class CheckHelper } const characteristic = actor.system.characteristics[characteristicName]; - const checkData = {actor: actor, action: action, face: face, skill: skill, characteristic: characteristicName}; + const checkData = {actor, action, face, skill, characteristic: {name: characteristicName, ...characteristic}}; let stance = 0; if(actor.type === "character") From 929b58da01a0245dfa7f0a5327e7953e9a5d4107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:34:21 +0200 Subject: [PATCH 16/25] More french localization --- lang/en-EN.json | 1 + lang/fr-FR.json | 107 +++++++++++++++++++++-------------------- modules/CheckHelper.js | 16 +++--- 3 files changed, 65 insertions(+), 59 deletions(-) diff --git a/lang/en-EN.json b/lang/en-EN.json index 8bc366a..121aa7b 100644 --- a/lang/en-EN.json +++ b/lang/en-EN.json @@ -28,6 +28,7 @@ "ACTION.UsageMessage": "uses {action}", "ACTION.MeleeStrike": "Melee Strike", "ACTION.RangedShot": "Ranged Shot", + "ACTION.CHECK.Against": "vs", "ACTION.CHECK.GenerallyNoCheckRequired": "Generally No Check Required", "ACTION.CHECK.NoCheckRequired": "No Check Required", "ACTION.CHECK.TargetDefence": "Target Defence", diff --git a/lang/fr-FR.json b/lang/fr-FR.json index 319d407..0e73b15 100644 --- a/lang/fr-FR.json +++ b/lang/fr-FR.json @@ -17,7 +17,7 @@ "ACTION.Effects": "Effets", "ACTION.MisfortuneDice": "Dés d'Infortune", "ACTION.Name": "Titre", - "ACTION.RechargeRating": "Recharge Rating", + "ACTION.RechargeRating": "Temps de Recharge", "ACTION.RechargeTokens": "Jetons de recharge", "ACTION.Recharging": "Vous ne pouvez pas utiliser une Action en cours de rechargement.", "ACTION.Requirements": "Conditions", @@ -28,11 +28,12 @@ "ACTION.UsageMessage": "utilise {action}", "ACTION.MeleeStrike": "Attaque au corps-à-corps", "ACTION.RangedShot": "Tir à distance", - "ACTION.CHECK.GenerallyNoCheckRequired": "Generally No Check Required", - "ACTION.CHECK.NoCheckRequired": "No Check Required", - "ACTION.CHECK.TargetDefence": "Target Defence", + "ACTION.CHECK.Against": "contre", + "ACTION.CHECK.GenerallyNoCheckRequired": "Généralement Aucun Test Requis", + "ACTION.CHECK.NoCheckRequired": "Aucun Test Requis", + "ACTION.CHECK.TargetDefence": "Défense de la Cible", "ACTION.EFFECT.Description": "Description", - "ACTION.EFFECT.SymbolAmount": "Symbol Amount", + "ACTION.EFFECT.SymbolAmount": "Quantité de symboles", "ACTION.FACE.Conservative": "Prudence", "ACTION.FACE.Reckless": "Téméraire", "ACTION.TRAITS.Basic": "Base", @@ -66,39 +67,39 @@ "ARMOUR.Soak": "Encaissement", "ATTRIBUTE.Aggression": "Agressivité", - "ATTRIBUTE.Cunning": "Ruse", - "ATTRIBUTE.Expertise": "Expertise", - "ATTRIBUTE.ABBREVIATION.Aggression": "A", - "ATTRIBUTE.ABBREVIATION.Cunning": "R", - "ATTRIBUTE.ABBREVIATION.Expertise": "E", + "ATTRIBUTE.Cunning": "Astuce", + "ATTRIBUTE.Expertise": "Adresse", + "ATTRIBUTE.ABBREVIATION.Aggression": "Ag", + "ATTRIBUTE.ABBREVIATION.Cunning": "As", + "ATTRIBUTE.ABBREVIATION.Expertise": "Ad", "CAREER.ActionAdvanceOptions": "Promotions d'Action possibles", "CAREER.AdvancedCareer": "Carrière Avancée", - "CAREER.AdvanceOptions": "Advance Options", - "CAREER.CareerAptitudes": "Career Aptitudes", - "CAREER.CareerCompletionAdvances": "Career Completion Advances", + "CAREER.AdvanceOptions": "Options d'Avancement", + "CAREER.CareerAptitudes": "Aptitudes de Carrière", + "CAREER.CareerCompletionAdvances": "Améliorations de Fin de Carrière", "CAREER.CareerSkills": "Compétences de Carrière", "CAREER.ConservativeAdvanceOptions": "Promotions de Prudence possibles", "CAREER.CurrentCareer": "Carrière en cours", "CAREER.FortuneAdvanceOptions": "Promotions de Fortune possibles", - "CAREER.GeneralCareerAdvances": "General Career Advances", - "CAREER.Header": "Header", + "CAREER.GeneralCareerAdvances": "Améliorations de Carrière", + "CAREER.Header": "En-tête", "CAREER.PrimaryCharacteristics": "Caractéristiques Primaires", - "CAREER.RaceRestrictions": "Race Restrictions", + "CAREER.RaceRestrictions": "Restrictions de Race", "CAREER.SettingInformation": "Description", "CAREER.SkillAdvanceOptions": "Promotions de Compétence possibles", - "CAREER.StartingConservativeSegments": "Starting Conservative Segments", - "CAREER.StartingRecklessSegments": "Starting Reckless Segments", + "CAREER.StartingConservativeSegments": "Segments de Prudence de départ", + "CAREER.StartingRecklessSegments": "Segments de Témérité de départ", "CAREER.Summary": "Résumé", "CAREER.TalentAdvanceOptions": "Promotions Talent possibles", "CAREER.TalentSockets": "Emplacements de Talent", "CAREER.Traits": "Traits", "CAREER.RecklessAdvanceOptions": "Promotions de Témérité possibles", "CAREER.WoundAdvanceOptions": "Promotions de Point de Blessure possibles", - "CAREER.NonCareerAdvances": "Non Career Advances", + "CAREER.NonCareerAdvances": "Améliorations Extracurriculaires", "CAREER.ADVANCE.Action": "Action", "CAREER.ADVANCE.CareerTransition": "Transition de Carrière", - "CAREER.ADVANCE.DedicationBonus": "Bonus de fin de Carrière", + "CAREER.ADVANCE.DedicationBonus": "Bonus de Fin de Carrière", "CAREER.ADVANCE.Open": "Amélioration Libre de Carrière", "CAREER.ADVANCE.Talent": "Talent", "CAREER.ADVANCE.Skill": "Formation ou Spécialisation", @@ -137,17 +138,17 @@ "CHARACTER.Corruption": "Corruption", "CHARACTER.CriticalWounds": "Blessures Critiques", "CHARACTER.Current": "Actuel", - "CHARACTER.CurrentExperience": "Current Experience", + "CHARACTER.CurrentExperience": "Expérience actuelle", "CHARACTER.Experience": "Experience", "CHARACTER.Fortune": "Fortune", "CHARACTER.Insanities": "Folies", "CHARACTER.Maximum": "Maximum", - "CHARACTER.Origin": "Origin", + "CHARACTER.Origin": "Origine", "CHARACTER.Skills": "Compétences", "CHARACTER.Stances": "Attitude", "CHARACTER.Talents": "Talents", "CHARACTER.Threshold": "Plafond", - "CHARACTER.TotalExperience": "Total Experience", + "CHARACTER.TotalExperience": "Experience totale", "CHARACTER.Trappings": "Dotations", "CHARACTER.Miscasts": "Revers Magiques", "CHARACTER.Money": "Argent", @@ -159,7 +160,7 @@ "CHARACTER.IMPAIRMENT.Stress": "Stress", "CHARACTER.IMPAIRMENT.FatigueTokens": "Jetons de Fatigue", "CHARACTER.IMPAIRMENT.StressTokens": "Jetons de Stress", - "CHARACTER.SHEET.NoExperienceLeft": "You have no experience left.", + "CHARACTER.SHEET.NoExperienceLeft": "Vous n'avez pas d'expérience à dépenser.", "CHARACTERGENERATOR.Actions": "Action Cards", "CHARACTERGENERATOR.Acquired": "Acquired", @@ -238,18 +239,18 @@ "CONDITION.DURATION.Lingering": "Prolongée", "CREATURE.Actions": "Actions", - "CREATURE.Category": "Category", - "CREATURE.DamageRating": "Damage Rating", - "CREATURE.DefenceValue": "Defence Value", - "CREATURE.Details": "Details", - "CREATURE.SoakValue": "Soak Value", - "CREATURE.Stance": "Stance", - "CREATURE.ThreatRating": "Threat Rating", - "CREATURE.WoundsThreshold": "Wounds Threshold", - "CREATURE.WoundsValue": "Wounds Value", - "CREATURE.ABBREVIATION.DamageRating": "DR", - "CREATURE.ABBREVIATION.DefenceValue": "Defence", - "CREATURE.ABBREVIATION.SoakValue": "Soak", + "CREATURE.Category": "Catégorie", + "CREATURE.DamageRating": "Niveaux de Dégâts", + "CREATURE.DefenceValue": "Valeur de Défense", + "CREATURE.Details": "Détails", + "CREATURE.SoakValue": "Valeur d'Encaissement", + "CREATURE.Stance": "Attitude", + "CREATURE.ThreatRating": "Niveau de Menace", + "CREATURE.WoundsThreshold": "Plafond de Blessure", + "CREATURE.WoundsValue": "Points de Blessures", + "CREATURE.ABBREVIATION.DamageRating": "ND", + "CREATURE.ABBREVIATION.DefenceValue": "Défence", + "CREATURE.ABBREVIATION.SoakValue": "Encaissement", "CRITICALWOUND.SeverityRating": "Niveau de Gravité", @@ -308,9 +309,9 @@ "ITEM.TypeWeapon": "Arme", "MONEY.Value": "Valeur", - "MONEY.Brass": "Brass", - "MONEY.Silver": "Silver", - "MONEY.Gold": "Gold", + "MONEY.Brass": "Cuivre", + "MONEY.Silver": "Argent", + "MONEY.Gold": "Or", "MONEY.ABBREVIATION.BrassCoins": "c", "MONEY.ABBREVIATION.SilverShillings": "a", "MONEY.ABBREVIATION.GoldCrowns": "o", @@ -528,7 +529,7 @@ "WEAPON.Group": "Groupe", "WEAPON.Qualities": "Attributs", "WEAPON.Range": "Portée", - "WEAPON.Rating": "Rating", + "WEAPON.Rating": "Niveau", "WEAPON.ABBREVIATION.CriticalRating": "NC", "WEAPON.ABBREVIATION.DamageRating": "ND", "WEAPON.GROUP.Blackpowder": "Poudre Noire", @@ -545,19 +546,19 @@ "WEAPON.GROUP.Staff": "Bâton", "WEAPON.GROUP.Thrown": "Jet", "WEAPON.GROUP.Unarmed": "Mains Nues", - "WEAPON.QUALITY.Attuned": "Attuned" , - "WEAPON.QUALITY.Blast": "Blast", - "WEAPON.QUALITY.Defensive": "Defensive", - "WEAPON.QUALITY.Entangling": "Entangling", - "WEAPON.QUALITY.Fast": "Fast", - "WEAPON.QUALITY.Pierce": "Pierce", - "WEAPON.QUALITY.Reload": "Reload", - "WEAPON.QUALITY.Slow": "Slow", - "WEAPON.QUALITY.Thrown": "Thrown", - "WEAPON.QUALITY.TwoHanded": "Two-Handed", - "WEAPON.QUALITY.Unreliable": "Unreliable", - "WEAPON.QUALITY.Vicious": "Vicious", - "WEAPON.QUALITY.Special": "Spécial", + "WEAPON.QUALITY.Attuned": "Harmonisé" , + "WEAPON.QUALITY.Blast": "Déflagration", + "WEAPON.QUALITY.Defensive": "Défensive", + "WEAPON.QUALITY.Entangling": "Paralysante", + "WEAPON.QUALITY.Fast": "Rapide", + "WEAPON.QUALITY.Pierce": "Perforante", + "WEAPON.QUALITY.Reload": "Rechargement", + "WEAPON.QUALITY.Slow": "Lente", + "WEAPON.QUALITY.Thrown": "Jet", + "WEAPON.QUALITY.TwoHanded": "Lourde", + "WEAPON.QUALITY.Unreliable": "Peu Fiable", + "WEAPON.QUALITY.Vicious": "Haineuse", + "WEAPON.QUALITY.Special": "Spéciale", "WEAPON.RANGE.Close": "Proche", "WEAPON.RANGE.Medium": "Moyenne", "WEAPON.RANGE.Long": "Longue", diff --git a/modules/CheckHelper.js b/modules/CheckHelper.js index aa25214..181ecce 100644 --- a/modules/CheckHelper.js +++ b/modules/CheckHelper.js @@ -1,5 +1,5 @@ -import DicePoolBuilder from "./applications/DicePoolBuilder.js"; import DicePool from "./DicePool.js"; +import DicePoolBuilder from "./applications/DicePoolBuilder.js"; /** * The CheckHelper provides methods to prepare checks. @@ -79,9 +79,13 @@ export default class CheckHelper */ static async prepareActionCheck(actor, action, face, {weapon = null, flavor = null, sound = null} = {}) { - const match = action.system[face].check.match(new RegExp(/(([\w\s]+) \((\w+)\))( vs\.? ([\w\s]+))?/)); - let skill = actor.itemTypes.skill[0] ?? null; - let characteristicName = skill ? skill.system.characteristic : "Strength"; + const match = action.system[face].check.match(new RegExp( + "(([\\p{L}\\s]+) \\((\\p{L}+)\\))( " + + game.i18n.localize("ACTION.CHECK.Against") + + "\\.? ([\\p{L}\\s]+))?", "u") + ); + let skill = null; + let characteristicName = skill?.system.characteristic ?? "Strength"; if(match) { skill = actor.itemTypes.skill.find((skill) => skill.name === match[2]) ?? skill; @@ -96,9 +100,9 @@ export default class CheckHelper let stance = 0; if(actor.type === "character") - stance = actor.system.stance.current + stance = actor.system.stance.current; else if(actor.type === "creature") - stance = actor.system.stance + stance = actor.system.stance; if(weapon) checkData.weapon = weapon; From 4c0804e3d602632e1d578fc683181717cc8e7182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:36:37 +0200 Subject: [PATCH 17/25] Removing Skill sheet height --- modules/applications/items/WFRP3eSkillSheet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/applications/items/WFRP3eSkillSheet.js b/modules/applications/items/WFRP3eSkillSheet.js index 8cbd477..987d505 100644 --- a/modules/applications/items/WFRP3eSkillSheet.js +++ b/modules/applications/items/WFRP3eSkillSheet.js @@ -6,7 +6,7 @@ export default class WFRP3eSkillSheet extends ItemSheet ...super.defaultOptions, template: "systems/wfrp3e/templates/applications/items/skill-sheet.hbs", //width: 530, - height: 340, + //height: 340, classes: ["wfrp3e", "sheet", "item", "skill"] }; } From da207f19acf3aaea9b9b69d88320aa55a988dc6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:37:09 +0200 Subject: [PATCH 18/25] Fixing DicePool's fortune dice calculation --- modules/DicePool.js | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/DicePool.js b/modules/DicePool.js index 6718683..5c5f10c 100644 --- a/modules/DicePool.js +++ b/modules/DicePool.js @@ -49,7 +49,6 @@ export default class DicePool { return [ this.dice.characteristic + "d" + CharacteristicDie.DENOMINATION, - (this.dice.fortune+ this.creatureDice.aggression + this.creatureDice.cunning) + "d" + FortuneDie.DENOMINATION, (this.dice.fortune + this.fortunePoints + this.specialisations.length + this.creatureDice.aggression From 8033b38fde213e58139916c8a9ca13161496db65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:37:26 +0200 Subject: [PATCH 19/25] Refactoring DicePool's naming --- modules/DicePool.js | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/modules/DicePool.js b/modules/DicePool.js index 5c5f10c..a1ef39f 100644 --- a/modules/DicePool.js +++ b/modules/DicePool.js @@ -66,16 +66,20 @@ export default class DicePool get name() { - if(this.checkData.combat) - return game.i18n.localize(`ROLL.${capitalize(this.check.combat.tags.encounterType)}EncounterInitiativeCheck`); - else if(this.checkData.action) - return game.i18n.format("ROLL.ActionCheck", {action: this.checkData.action.name}); - else if(this.checkData.skill) - return game.i18n.format("ROLL.SkillCheck", {skill: this.checkData.skill.name}); - else if(this.checkData.characteristic) - return game.i18n.format("ROLL.CharacteristicCheck", { - characteristic: game.i18n.localize(CONFIG.WFRP3e.characteristics[this.checkData.characteristic.name].name) - }); + if(this.checkData) { + const checkData = this.checkData; + + if(checkData.combat) + return game.i18n.localize(`ROLL.${capitalize(checkData.combat.tags.encounterType)}EncounterInitiativeCheck`); + else if(checkData.action) + return game.i18n.format("ROLL.ActionCheck", {action: checkData.action.name}); + else if(checkData.skill) + return game.i18n.format("ROLL.SkillCheck", {skill: checkData.skill.name}); + else if(checkData.characteristic) + return game.i18n.format("ROLL.CharacteristicCheck", { + characteristic: game.i18n.localize(CONFIG.WFRP3e.characteristics[checkData.characteristic.name].name) + }); + } return game.i18n.localize("ROLL.FreeCheck"); } From 8459db63eed15a4d449c0a2531faabfe7c7cb111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:37:38 +0200 Subject: [PATCH 20/25] Refactoring WFRP3eRoll's constructor --- modules/WFRP3eRoll.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/WFRP3eRoll.js b/modules/WFRP3eRoll.js index b18f1c6..56af018 100644 --- a/modules/WFRP3eRoll.js +++ b/modules/WFRP3eRoll.js @@ -23,8 +23,9 @@ export default class WFRP3eRoll extends Roll }, {}); if(this.options.checkData?.action) { + const checkData = this.options.checkData; this.effects = { - ...Object.entries(this.options.checkData.action.system[this.options.checkData.face].effects) + ...Object.entries(checkData.action.system[checkData.face].effects) .reduce((object, effectArray) => { object[effectArray[0]] = effectArray[1].reduce((array, effect) => { effect.active = false; @@ -34,11 +35,13 @@ export default class WFRP3eRoll extends Roll return object; }, {}) }; - this.effects.boon.push(CheckHelper.getUniversalBoonEffect(CONFIG.WFRP3e.characteristics[this.options.checkData.characteristic].type === "mental")); - this.effects.bane.push(CheckHelper.getUniversalBaneEffect(CONFIG.WFRP3e.characteristics[this.options.checkData.characteristic].type === "mental")); + this.effects.boon.push(CheckHelper.getUniversalBoonEffect(CONFIG.WFRP3e.characteristics[checkData.characteristic.name].type === "mental")); + this.effects.bane.push(CheckHelper.getUniversalBaneEffect(CONFIG.WFRP3e.characteristics[checkData.characteristic.name].type === "mental")); - if(["melee", "ranged"].includes(this.options.checkData.action.system.type)) + if(["melee", "ranged"].includes(checkData.action.system.type)) { + this.effects.boon.push(CheckHelper.getCriticalRatingEffect(checkData.weapon)); this.effects.sigmarsComet.push(CheckHelper.getUniversalSigmarsCometEffect()); + } } } From 11e41f3b611ec4e1d143c5a0f2da8e19dee647b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:38:00 +0200 Subject: [PATCH 21/25] Fixing Assess The Situation Defence trait --- packs/source/items/Assess_The_Situation_qQrjbMZeH4WjniK6.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packs/source/items/Assess_The_Situation_qQrjbMZeH4WjniK6.json b/packs/source/items/Assess_The_Situation_qQrjbMZeH4WjniK6.json index 3b3ffdd..51742e2 100644 --- a/packs/source/items/Assess_The_Situation_qQrjbMZeH4WjniK6.json +++ b/packs/source/items/Assess_The_Situation_qQrjbMZeH4WjniK6.json @@ -18,7 +18,7 @@ "name": "Assess The Situation", "art": "systems/wfrp3e/assets/images/actions/assess_the_situation.jpg", "type": "support", - "traits": "Basic, Defense", + "traits": "Basic, Defence", "rechargeRating": 2, "difficultyModifiers": { "challengeDice": 0, @@ -59,7 +59,7 @@ "name": "Assess The Situation", "art": "systems/wfrp3e/assets/images/actions/assess_the_situation.jpg", "type": "support", - "traits": "Basic, Defense", + "traits": "Basic, Defence", "rechargeRating": 2, "difficultyModifiers": { "challengeDice": 0, From 6ad2a60e7952c9a606307a5117a042ad4979d24c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:38:17 +0200 Subject: [PATCH 22/25] Fixing Action card's title style --- styles/less/components/action_card.less | 1 + 1 file changed, 1 insertion(+) diff --git a/styles/less/components/action_card.less b/styles/less/components/action_card.less index 1babc4b..cfb117e 100644 --- a/styles/less/components/action_card.less +++ b/styles/less/components/action_card.less @@ -128,6 +128,7 @@ & .action-card-name { font: small-caps 16pt @font-title; grid-area: action-card-name; + line-height: 16pt; margin: auto; text-align: center; text-shadow: From af13d4bc4c3aeb561c7491039c0ac706ef93aa88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:38:40 +0200 Subject: [PATCH 23/25] Fixing Character Sheet skill list's width --- styles/less/components/character_sheet.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles/less/components/character_sheet.less b/styles/less/components/character_sheet.less index e92b4ea..2410563 100644 --- a/styles/less/components/character_sheet.less +++ b/styles/less/components/character_sheet.less @@ -244,7 +244,7 @@ } & .skills { - flex: 1 1 auto; + flex: 1 1 370px; overflow: auto; & .skill-row { From 0d3ddf7b8339cba71415e154f1edf28641c6ce36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:39:03 +0200 Subject: [PATCH 24/25] Fixing DicePoolBuilder Specialisation select --- styles/less/components/dice_pool_builder.less | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/styles/less/components/dice_pool_builder.less b/styles/less/components/dice_pool_builder.less index ef4e978..7bebf79 100644 --- a/styles/less/components/dice_pool_builder.less +++ b/styles/less/components/dice_pool_builder.less @@ -234,16 +234,22 @@ } & .quick-settings { + display: flex; flex: 1 1 200px; + flex-direction: column; + gap: 0.25rem; width: 200px; - & > label { - margin-bottom: 0.5rem; + & > label > * { + display: block; + width: 100%; + } - & > * { - display: block; - width: 100%; - } + & .specialisations { + border: 1px solid var(--color-border-light-primary); + display: flex; + flex-direction: column; + padding: 0.25rem; } } } From e2290727d6113afbc38c4ad6eb61c975cc4a58cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soup=C3=A9?= Date: Mon, 1 Apr 2024 22:39:28 +0200 Subject: [PATCH 25/25] Improving Actor sheet tooltips --- templates/applications/actors/character-sheet.hbs | 6 +++--- templates/applications/actors/creature-sheet.hbs | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/templates/applications/actors/character-sheet.hbs b/templates/applications/actors/character-sheet.hbs index aaded81..c1f30ca 100644 --- a/templates/applications/actors/character-sheet.hbs +++ b/templates/applications/actors/character-sheet.hbs @@ -1,6 +1,6 @@
- + {{actor.name}}
diff --git a/templates/applications/actors/creature-sheet.hbs b/templates/applications/actors/creature-sheet.hbs index 727c817..983a2fa 100644 --- a/templates/applications/actors/creature-sheet.hbs +++ b/templates/applications/actors/creature-sheet.hbs @@ -51,14 +51,14 @@
- + {{actor.name}}