fix: Correct critical bugs and complete Creature/Group DataModel implementation

- Fix TypeError: controls.find is not a function in hooks.mjs
- Fix undefined 'npc' variable in applications.mjs
- Fix CONFIG.VERMINE.model undefined by checking game.system.template existence
- Fix TypeError: html.find(...).forEach is not a function in roll.mjs
- Fix Cannot set properties of undefined (setting 'initial') in actor.mjs
- Fix Cannot read properties of undefined (reading 'difficulty') in actor.mjs
- Fix ActiveEffect application phase 'initial' already completed by adding combatStatus to base template
- Fix Missing helper: 'select' in roll-dialog.hbs (removed invalid Handlebars select block)
- Add SIZE_LEVELS labels to creatureSizeLevels config
- Add SIZE_LEVELS translations to fr.json
- Add combatStatus to base actor template
- Convert all .html templates to .hbs for Foundry v14 compatibility
- Update item-sheet.mjs to use .hbs extension
- Update handlebars-manager.mjs to use .hbs for all partials

Complete Vermine2047 Creature and Group sheet implementation:
- Creature: Pattern, Size, Role, Pack with computed values
- Group: Totem, Reserve, Morale, Objectives, Members management
- All templates functional with proper styling

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
2026-06-04 20:58:22 +02:00
parent f9f07cbc7e
commit 30d6f71fc7
43 changed files with 19225 additions and 609 deletions
+17 -10
View File
@@ -79,7 +79,7 @@ export class ActorPicker extends Application {
if (type == 'members') {
actorsList = characters;
} else if (type == 'relations') {
actorsList = npc;//[...npc, ...characters];
actorsList = npcs;//[...npcs, ...characters];
} else {
actorsList = all;
}
@@ -94,26 +94,33 @@ export class ActorPicker extends Application {
html.find('.actor').click(async (event) => {
const actorId = $(event.target).parent('div').data('actor-id');
const type = $(this.linkEl).data('type');
if (!actorId) return;
let actorsList = [];
if (type == 'members') {
actorsList = this.actor.system.members;
actorsList = foundry.utils.duplicate(this.actor.system.members || []);
} else if (type == 'encounters') {
actorsList = this.actor.system.encounters;
actorsList = foundry.utils.duplicate(this.actor.system.encounters || []);
}
if (!Array.isArray(actorsList)) {
actorsList = [];
}
actorsList.push(actorId);
if (type == 'members') {
actorsList = this.actor.system.members;
this.actor.update({ 'system.members': actorsList });
} else if (type == 'encounters') {
this.actor.update({ 'system.encounters': actorsList });
// Add actor if not already present
if (!actorsList.includes(actorId)) {
actorsList.push(actorId);
}
if (type == 'members') {
await this.actor.update({ 'system.members': actorsList });
} else if (type == 'encounters') {
await this.actor.update({ 'system.encounters': actorsList });
}
this.close();
});
}
+74 -3
View File
@@ -179,9 +179,9 @@ VERMINE.creaturePatternLevels = {
* Creature Size Levels configuration
*/
VERMINE.creatureSizeLevels = {
1: { "attack": 2, "vigor": 1, "minorWound": 0, "majorWound": 0, "deadlyWound": 1 },
2: { "attack": 3, "vigor": 2, "minorWound": 0, "majorWound": 1, "deadlyWound": 1 },
3: { "attack": 4, "vigor": 3, "minorWound": 1, "majorWound": 1, "deadlyWound": 1 }
1: { "label": "SIZE_LEVELS.small", "attack": 2, "vigor": 1, "minorWound": 0, "majorWound": 0, "deadlyWound": 1 },
2: { "label": "SIZE_LEVELS.medium", "attack": 3, "vigor": 2, "minorWound": 0, "majorWound": 1, "deadlyWound": 1 },
3: { "label": "SIZE_LEVELS.large", "attack": 4, "vigor": 3, "minorWound": 1, "majorWound": 1, "deadlyWound": 1 }
}
/**
@@ -394,3 +394,74 @@ VERMINE.combatStatus = {
passif: 9
}
/**
* Group Morale Levels configuration
* Rules: p. 68-69 - Group Reserve and Morale
*/
VERMINE.groupMoraleLevels = {
"high": {
"label": "VERMINE.morale_high",
"description": "7D+ - Moral élevé, groupe déterminé",
"minDice": 7
},
"normal": {
"label": "VERMINE.morale_normal",
"description": "3-6D - Moral normal",
"minDice": 3,
"maxDice": 6
},
"low": {
"label": "VERMINE.morale_low",
"description": "1-2D - Moral bas, groupe hésitant",
"minDice": 1,
"maxDice": 2
},
"crisis": {
"label": "VERMINE.morale_crisis",
"description": "0D - Crise, groupe au bord de l'effondrement",
"minDice": 0,
"maxDice": 0
}
}
/**
* Group Reserve configuration
* The reserve is shared among all group members and can be used with vote
*/
VERMINE.groupReserve = {
"min": 0,
"max": 10,
"description": "Réserve de dés partagée par le groupe (p. 68-69)"
}
/**
* Group Level configuration (1-10)
*/
VERMINE.groupLevels = {
1: { "label": "Niveau 1 - Débutant" },
2: { "label": "Niveau 2 - Initié" },
3: { "label": "Niveau 3 - Expérimenté" },
4: { "label": "Niveau 4 - Confirmé" },
5: { "label": "Niveau 5 - Vétéran" },
6: { "label": "Niveau 6 - Élite" },
7: { "label": "Niveau 7 - Légendaire" },
8: { "label": "Niveau 8 - Mythique" },
9: { "label": "Niveau 9 - Hérotique" },
10: { "label": "Niveau 10 - Légende" }
}
/**
* Totem Instincts and Prohibitions effects
* Rules: p. 68-69 - Instincts give +3D/+5D, Prohibitions give -3D/-5D
*/
VERMINE.totemEffects = {
"instinct": {
"minor": "+3D",
"major": "+5D"
},
"prohibition": {
"minor": "-3D",
"major": "-5D"
}
}
+3 -3
View File
@@ -39,11 +39,11 @@ export const preloadHandlebarsTemplates = async function () {
"systems/vermine2047/templates/dialogs/roll-dialog.hbs",
//items partials
"systems/vermine2047/templates/item/partials/damages.html",
"systems/vermine2047/templates/item/partials/traits.html",
"systems/vermine2047/templates/item/partials/damages.hbs",
"systems/vermine2047/templates/item/partials/traits.hbs",
"systems/vermine2047/templates/item/partials/header.hbs",
"systems/vermine2047/templates/item/partials/physicalItems.hbs",
"systems/vermine2047/templates/item/chatCards/parts/base.html",
"systems/vermine2047/templates/item/chatCards/parts/base.hbs",
]);
+12 -10
View File
@@ -88,16 +88,18 @@ export const registerHooks = function () {
});
Hooks.on('getSceneControlButtons', async (controls) => {
console.log;
controls.find((c) => c.name === 'token').tools.push({
name: 'Dice Roller',
title: game.i18n.localize("VERMINE.RollTool"),
icon: 'fas fa-dice-d10',
button: true,
onClick() {
RollDialog.create().then(d => d.render(true));
}
});
const tokenControls = controls.token;
if (tokenControls && tokenControls.tools) {
tokenControls.tools.push({
name: 'Dice Roller',
title: game.i18n.localize("VERMINE.RollTool"),
icon: 'fas fa-dice-d10',
button: true,
onClick() {
RollDialog.create().then(d => d.render(true));
}
});
}
});
/* -------------------------------------------- */
+4 -4
View File
@@ -370,13 +370,13 @@ export class VermineUtils {
// Enable/disable rerolls based on count
if (!rerollCount || parseInt(rerollCount, 10) < 1) {
// Disable rerolls for all dice
html.find('.die').forEach(die => {
die.classList.remove("rerollable");
html.find('.die').each(function() {
this.classList.remove("rerollable");
});
} else {
// Enable rerolls for all dice
html.find('.die').forEach(die => {
die.classList.add("rerollable");
html.find('.die').each(function() {
this.classList.add("rerollable");
});
}