Ready for release
Release Creation / build (release) Successful in 43s

This commit is contained in:
2026-06-12 20:53:44 +02:00
parent efe37b8a96
commit a53c7ace53
98 changed files with 1171 additions and 289 deletions
+89 -3
View File
@@ -1,5 +1,6 @@
import { formatCredits } from './tradeHelper.js';
import { createNpcActor, generateClientMission, generateEncounter, generateQuickNpc } from './npcHelper.js';
import { createNpcActor, generateClientMission, generateEncounter, generateQuickNpc, formatSigned } from './npcHelper.js';
import { generateAllyEnemy } from './allyEnemyGenerator.js';
import { NPC_RELATIONS } from './data/npcTables.js';
import { generateAndCreateTravellerNpc } from './travellerNpcGenerator.js';
import { generateRandomName } from './data/travellerNpcGenerator.js';
@@ -68,6 +69,13 @@ export class NpcDialog extends HandlebarsApplicationMixin(ApplicationV2) {
actorName: '',
openCreatedActor: DEFAULT_OPTIONS.openCreatedActor,
},
ae: {
relation: options.relation ?? 'contact',
includeSpecial: true,
createActor: false,
actorName: '',
openCreatedActor: true,
},
};
}
@@ -138,6 +146,12 @@ export class NpcDialog extends HandlebarsApplicationMixin(ApplicationV2) {
await this._handleTravellerNpc();
});
html.find('[data-action="generate-ally-enemy"]').on('click', async (event) => {
event.preventDefault();
this._readForm(html);
await this._handleAllyEnemy();
});
html.find('[data-action="randomize-name"]').on('click', (event) => {
event.preventDefault();
this._randomizeTravellerName(html);
@@ -205,6 +219,13 @@ export class NpcDialog extends HandlebarsApplicationMixin(ApplicationV2) {
this._formData.encounter.context = html.find('[name="encounter.context"]').val();
this._formData.encounter.includeFollowUp = html.find('[name="encounter.includeFollowUp"]').is(':checked');
// Données pour l'onglet Alliés/Ennemis
this._formData.ae.relation = html.find('[name="ae.relation"]').val();
this._formData.ae.includeSpecial = html.find('[name="ae.includeSpecial"]').is(':checked');
this._formData.ae.createActor = html.find('[name="ae.createActor"]').is(':checked');
this._formData.ae.actorName = html.find('[name="ae.actorName"]').val();
this._formData.ae.openCreatedActor = html.find('[name="ae.openCreatedActor"]').is(':checked');
// Données pour l'onglet PNJ Détaillé (Traveller)
this._formData.traveller.citizenCategory = html.find('[name="traveller.citizenCategory"]').val();
this._formData.traveller.experience = html.find('[name="traveller.experience"]').val();
@@ -281,6 +302,60 @@ export class NpcDialog extends HandlebarsApplicationMixin(ApplicationV2) {
}
}
async _handleAllyEnemy() {
const button = $(this.element).find('[data-action="generate-ally-enemy"]');
const originalLabel = button.html();
try {
button.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Génération...');
const result = await generateAllyEnemy(this._formData.ae.relation, {
includeSpecial: this._formData.ae.includeSpecial,
});
if (result.success) {
if (this._formData.ae.createActor) {
const ae = this._formData.ae;
const actorName = ae.actorName?.trim() || `PNJ — ${result.relation.label}`;
const baseActorSystem = game.system?.id === 'mgt2e'
? await (await import('./travellerNpcGenerator.js')).getMgt2eBaseActorSystem()
: null;
const actorData = {
name: actorName,
type: 'npc',
img: 'systems/mgt2e/icons/cargo/passenger-middle.svg',
system: {
settings: foundry.utils.mergeObject(foundry.utils.deepClone(baseActorSystem?.settings ?? {}), {
hideUntrained: true, lockCharacteristics: true,
}),
sophont: foundry.utils.mergeObject(foundry.utils.deepClone(baseActorSystem?.sophont ?? {}), {
age: 18, homeworld: '', profession: result.relation.label,
}),
characteristics: foundry.utils.deepClone(baseActorSystem?.characteristics ?? {}),
hits: foundry.utils.deepClone(baseActorSystem?.hits ?? {}),
skills: foundry.utils.deepClone(baseActorSystem?.skills ?? {}),
},
flags: {
[MODULE_ID]: { generatedAllyEnemy: { relation: result.relation.key } },
},
};
const actor = await Actor.create(actorData, { renderSheet: false });
result.createdActor = { id: actor.id, name: actor.name };
if (ae.openCreatedActor) actor.sheet?.render(true);
ui.notifications.info(`Fiche PNJ créée : ${actor.name}`);
}
await this._postToChatResult(result);
} else {
ui.notifications.error('Erreur lors de la génération de la relation');
}
} catch (error) {
console.error(`${MODULE_ID} | Erreur AE:`, error);
ui.notifications.error(`Erreur: ${error.message}`);
} finally {
button.prop('disabled', false).html(originalLabel);
}
}
_randomizeTravellerName(html) {
const name = generateRandomName(this._formData.traveller.gender);
html.find('[name="traveller.firstName"]').val(name.firstName);
@@ -295,13 +370,15 @@ export class NpcDialog extends HandlebarsApplicationMixin(ApplicationV2) {
async _postToChatResult(data) {
registerHandlebarsHelpers();
// Déterminer quel template utiliser en fonction du type de données
let template = `modules/${MODULE_ID}/templates/npc-result.hbs`;
let resultType = 'npc-result';
if (data.type === 'traveller-npc' || data?.flags?.[MODULE_ID]?.type === 'traveller-npc-result') {
template = `modules/${MODULE_ID}/templates/traveller-npc-result.hbs`;
resultType = 'traveller-npc-result';
} else if (data.type === 'ally-enemy') {
template = `modules/${MODULE_ID}/templates/ally-enemy-result.hbs`;
resultType = 'ally-enemy-result';
}
const html = await foundry.applications.handlebars.renderTemplate(template, data);
@@ -369,4 +446,13 @@ function registerHandlebarsHelpers() {
if (!obj || !key) return '';
return obj[key] !== undefined ? obj[key] : '';
});
const RELATION_LABELS = Object.entries(NPC_RELATIONS).reduce((acc, [key, val]) => {
acc[key] = val.label;
return acc;
}, {});
Handlebars.registerHelper('lookupRelationKey', (key) => RELATION_LABELS[key] || key);
Handlebars.registerHelper('formatSigned', (value) => formatSigned(value));
}