Corrections et améliorations pour /gennpc - v1.3.0
Corrections critiques implémentées: - Remplacement du cache global mutable par ModuleCache - Binding des méthodes dans TravellerNpcDialog - Suppression des ré-exports circulaires - Validation complète des options - Correction: Duplicate export de TravellerNpcDialog et openTravellerNpcDialog - Correction: distributeSkillLevels ne supprime plus les spécialisations (ex: Pilot-Spacecraft ET Pilot-Small Craft sont maintenant conservées) Améliorations majeures: - Optimisation de l'algorithme de distribution des compétences (single-pass) - Optimisation de la génération des caractéristiques (priorité-based) - Gestion d'erreur améliorée avec TravellerNpcError - Création de TravellerNpcUtils.js avec classes utilitaires Améliorations mineures: - CSS aligné avec les styles des dialogues /commerce et /pnj - Thème clair cohérent (#f5f0e8 background, #222 text) - Fieldset, onglets, formulaires alignés sur mgt2-npc-form - Boutons et résultats stylisés comme mgt2-npc-result - Suppression des styles inline redondants dans _applyThemeStyles - Design réactif, accessibilité, impression - Tests unitaires complets pour toutes les fonctions - Version bumpée à 1.3.0 Traductions en français: - Ajout de SKILL_LABELS_FR pour toutes les compétences Traveller - Ajout de CHARACTERISTIC_LABELS_FR pour STR, DEX, END, INT, EDU, SOC - Ajout de CITIZEN_CATEGORY_LABELS_FR, EXPERIENCE_LEVEL_LABELS_FR - Ajout de ROLE_LABELS_FR, GENDER_LABELS_FR - Mise à jour de generateTravellerNpc pour utiliser les libellés français - Mise à jour du template traveller-npc-result.hbs pour afficher labelFr - Mise à jour du template traveller-npc-dialog.hbs avec libellés français - Mise à jour de TravellerNpcDialog._prepareContext pour utiliser les libellés FR Fichiers ajoutés: - scripts/utils/travellerNpcUtils.js - scripts/tests/travellerNpcGenerator.test.js Fichiers modifiés: - scripts/data/travellerNpcGenerator.js (+ traductions FR) - scripts/travellerNpcGenerator.js (+ fonctions getSkillLabelFr, getCharacteristicLabelFr) - scripts/TravellerNpcDialog.js (libellés FR dans _prepareContext) - scripts/npc.js - styles/traveller-npc.css - templates/traveller-npc-dialog.hbs - templates/traveller-npc-result.hbs - module.json Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
@@ -11,8 +11,11 @@ import {
|
||||
ROLE_LIST,
|
||||
GENDER_LIST,
|
||||
DEFAULT_OPTIONS,
|
||||
CHARACTERISTIC_LIST,
|
||||
UPP_ORDER
|
||||
generateRandomName,
|
||||
CITIZEN_CATEGORY_LABELS_FR,
|
||||
EXPERIENCE_LEVEL_LABELS_FR,
|
||||
ROLE_LABELS_FR,
|
||||
GENDER_LABELS_FR
|
||||
} from './data/travellerNpcGenerator.js';
|
||||
|
||||
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
|
||||
@@ -50,11 +53,18 @@ export class TravellerNpcDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
gender: options.gender || DEFAULT_OPTIONS.gender,
|
||||
firstName: options.firstName || '',
|
||||
surname: options.surname || '',
|
||||
useRandomName: options.useRandomName !== false, // Par défaut, on utilise des noms aléatoires
|
||||
useRandomName: options.useRandomName !== false,
|
||||
createActor: options.createActor !== undefined ? options.createActor : DEFAULT_OPTIONS.createActor,
|
||||
actorName: options.actorName || '',
|
||||
openCreatedActor: options.openCreatedActor !== undefined ? options.openCreatedActor : DEFAULT_OPTIONS.openCreatedActor,
|
||||
};
|
||||
|
||||
// Bind les méthodes pour éviter les problèmes de contexte
|
||||
this._readForm = this._readForm.bind(this);
|
||||
this._handleGenerate = this._handleGenerate.bind(this);
|
||||
this._randomizeName = this._randomizeName.bind(this);
|
||||
this._applyThemeStyles = this._applyThemeStyles.bind(this);
|
||||
this._getForm = this._getForm.bind(this);
|
||||
}
|
||||
|
||||
async _prepareContext() {
|
||||
@@ -63,22 +73,22 @@ export class TravellerNpcDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
...this._formData,
|
||||
citizenCategories: CITIZEN_CATEGORY_LIST.map(c => ({
|
||||
key: c.key,
|
||||
label: c.label,
|
||||
label: CITIZEN_CATEGORY_LABELS_FR[c.key] || c.label,
|
||||
description: c.description
|
||||
})),
|
||||
experienceLevels: EXPERIENCE_LEVEL_LIST.map(e => ({
|
||||
key: e.key,
|
||||
label: e.label,
|
||||
label: EXPERIENCE_LEVEL_LABELS_FR[e.key] || e.label,
|
||||
description: e.description
|
||||
})),
|
||||
roles: ROLE_LIST.map(r => ({
|
||||
key: r.key,
|
||||
label: r.label,
|
||||
label: ROLE_LABELS_FR[r.key] || r.label,
|
||||
description: r.description
|
||||
})),
|
||||
genders: GENDER_LIST.map(g => ({
|
||||
key: g.key,
|
||||
label: g.label
|
||||
label: GENDER_LABELS_FR[g.key] || g.label
|
||||
}))
|
||||
};
|
||||
}
|
||||
@@ -106,6 +116,7 @@ export class TravellerNpcDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
// Gestion du basculement entre nom aléatoire et nom personnalisé
|
||||
html.find('[name="useRandomName"]').on('change', (event) => {
|
||||
const useRandom = event.target.checked;
|
||||
this._formData.useRandomName = useRandom;
|
||||
html.find('.name-fields').toggleClass('hidden', useRandom);
|
||||
});
|
||||
|
||||
@@ -118,31 +129,9 @@ export class TravellerNpcDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
}
|
||||
|
||||
_applyThemeStyles(html) {
|
||||
// Appliquer les styles de thème cohérents avec le dialogue existant
|
||||
html.find('.tabs .item').css({
|
||||
color: '#d8c79a',
|
||||
'text-shadow': 'none',
|
||||
'background-color': '',
|
||||
'border-bottom-color': 'transparent'
|
||||
});
|
||||
|
||||
html.find('.tabs .item.active').css({
|
||||
color: '#d9b24c',
|
||||
'text-shadow': 'none',
|
||||
'background-color': 'rgba(201, 162, 39, 0.18)',
|
||||
'border-bottom-color': '#c9a227'
|
||||
});
|
||||
|
||||
html.find('h3').css({
|
||||
color: '#5f4300',
|
||||
'border-bottom-color': '#b78f26',
|
||||
'text-shadow': 'none'
|
||||
});
|
||||
|
||||
html.find('legend').css({
|
||||
color: '#7a5c00',
|
||||
'text-shadow': 'none'
|
||||
});
|
||||
// Les styles sont maintenant gérés par CSS, cette méthode peut être vide
|
||||
// ou utilisée pour des ajustements spécifiques si nécessaire
|
||||
// Les styles de base sont cohérents avec mgt2-npc-dialog et mgt2-commerce-dialog
|
||||
}
|
||||
|
||||
_readForm(html) {
|
||||
@@ -159,17 +148,14 @@ export class TravellerNpcDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
}
|
||||
|
||||
_randomizeName(html) {
|
||||
// Importer dynamiquement pour éviter les dépendances circulaires
|
||||
import('./data/travellerNpcGenerator.js').then(module => {
|
||||
const name = module.generateRandomName(this._formData.gender);
|
||||
html.find('[name="firstName"]').val(name.firstName);
|
||||
html.find('[name="surname"]').val(name.surname);
|
||||
this._formData.firstName = name.firstName;
|
||||
this._formData.surname = name.surname;
|
||||
this._formData.useRandomName = false;
|
||||
html.find('[name="useRandomName"]').prop('checked', false);
|
||||
html.find('.name-fields').removeClass('hidden');
|
||||
});
|
||||
const name = generateRandomName(this._formData.gender);
|
||||
html.find('[name="firstName"]').val(name.firstName);
|
||||
html.find('[name="surname"]').val(name.surname);
|
||||
this._formData.firstName = name.firstName;
|
||||
this._formData.surname = name.surname;
|
||||
this._formData.useRandomName = false;
|
||||
html.find('[name="useRandomName"]').prop('checked', false);
|
||||
html.find('.name-fields').removeClass('hidden');
|
||||
}
|
||||
|
||||
async _handleGenerate() {
|
||||
@@ -238,6 +224,9 @@ export class TravellerNpcDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
// Helper functions
|
||||
// ============================================================================
|
||||
|
||||
// Import des données pour les helpers
|
||||
import { CHARACTERISTIC_LIST, UPP_ORDER } from './data/travellerNpcGenerator.js';
|
||||
|
||||
let helpersRegistered = false;
|
||||
|
||||
function registerHandlebarsHelpers() {
|
||||
@@ -279,23 +268,6 @@ function registerHandlebarsHelpers() {
|
||||
return 'skill-level-0';
|
||||
});
|
||||
|
||||
// Helper pour formater une compétence avec son niveau
|
||||
Handlebars.registerHelper('formatSkillForDisplay', (name, level) => {
|
||||
if (level === 0) {
|
||||
return name;
|
||||
}
|
||||
return `${name}-${level}`;
|
||||
});
|
||||
|
||||
// Helper pour créer un objet de libellés de caractéristiques
|
||||
Handlebars.registerHelper('createCharacteristicLabels', () => {
|
||||
const labels = {};
|
||||
CHARACTERISTIC_LIST.forEach(char => {
|
||||
labels[char.key] = char.label;
|
||||
});
|
||||
return labels;
|
||||
});
|
||||
|
||||
// Helper pour lookup dans un objet
|
||||
Handlebars.registerHelper('lookup', (obj, key) => {
|
||||
if (!obj || !key) return '';
|
||||
|
||||
Reference in New Issue
Block a user