feat: gestion des Dés de Totems (influence, instincts, interdits)
Release Creation / build (release) Failing after 1m32s
Release Creation / build (release) Failing after 1m32s
- VermineTotemDice : influence Humain/Adapté (+1D/-1D par domaine, règles p. 121), gains/pertes via Instincts/Interdits avec limites (3D/totem, 5D total) et règles d'échange. - roll.mjs applique l'influence selon le Totem dominant (au lieu de l'ancienne logique basée sur identity.totem). - Dialogue TotemDiceDialog (instinct Humain/autre totem, interdit Humain, acte grave ±2D) + bouton et ligne d'influence sur la fiche personnage. - Dés de Totem gagnés en cas d'échec à l'apprentissage Dé d'Évolution (dés dépensés, garde capacité vide). - Couleur de texte @color-text-light-2 assombrie (#c9e0c0 → #3f9b55) pour la lisibilité dans tous les dialogues. fix: robustesse et visibilité des évolutions - buyEvolutionDialog : n'efface les Dés d'Évolution que si l'item est créé. - Flag mutation éditable sur la fiche item evolution + badge Adaptation/Mutation dans la liste du personnage. - loseDie : applique aussi la limite totale de 5 dés au gain Adapté. - Case "acte grave" conservée entre les rendus du dialogue.
This commit is contained in:
+16
-64
@@ -1,3 +1,5 @@
|
||||
import { VermineTotemDice } from "./totem-dice.mjs";
|
||||
|
||||
export class VermineUtils {
|
||||
/**
|
||||
* Rolls dice with Vermine2047-specific rules.
|
||||
@@ -49,12 +51,12 @@ export class VermineUtils {
|
||||
// Declare variables
|
||||
let formula = "";
|
||||
let modFormula = null;
|
||||
let totemBonus = { human: 0, adapted: 0 };
|
||||
|
||||
// Calculate domain bonuses for totems
|
||||
if (skillCategory) {
|
||||
totemBonus = this._calculateTotemDomainBonuses(skillCategory, actor);
|
||||
}
|
||||
// Influence des Dés de Totems : Bonus/Malus de 1D selon le Totem dominant
|
||||
// et le Domaine de la Compétence (règles p. 121). S'applique même sans
|
||||
// utiliser un Dé de Totem.
|
||||
const influenceMod = this._calculateTotemInfluence(skillCategory, actor);
|
||||
NoD += influenceMod;
|
||||
|
||||
// Apply automatic successes from skill mastery
|
||||
let adjustedDifficulty = difficulty;
|
||||
@@ -65,11 +67,6 @@ export class VermineUtils {
|
||||
const humanDifficulty = adjustedDifficulty;
|
||||
const humanFormula = `(1D10cs>=${humanDifficulty}[human_${safeUserName}]*2)`;
|
||||
|
||||
// Apply domain bonus/malus
|
||||
if (totemBonus.human !== 0) {
|
||||
NoD += totemBonus.human;
|
||||
}
|
||||
|
||||
modFormula = humanFormula;
|
||||
}
|
||||
|
||||
@@ -79,11 +76,6 @@ export class VermineUtils {
|
||||
const adaptedDifficulty = adjustedDifficulty;
|
||||
const adaptedFormula = `(1D10cs>=${adaptedDifficulty}[adapted_${safeUserName}]*2)`;
|
||||
|
||||
// Apply domain bonus/malus
|
||||
if (totemBonus.adapted !== 0) {
|
||||
NoD += totemBonus.adapted;
|
||||
}
|
||||
|
||||
// Build combined formula
|
||||
if (modFormula !== null) {
|
||||
modFormula = `${modFormula}+${adaptedFormula}`;
|
||||
@@ -113,8 +105,8 @@ export class VermineUtils {
|
||||
formula = modFormula !== null ? `${baseFormula}+${modFormula}` : baseFormula;
|
||||
|
||||
// Reconcile the breakdown displayed in chat with the dice actually rolled.
|
||||
// Domain bonuses/malus are only applied when the corresponding totem die
|
||||
// is used, and totem dice replace (not add to) base-pool dice.
|
||||
// L'influence s'applique au pool ; les Dés de Totem remplacent (n'ajoutent
|
||||
// pas) des dés du pool de base.
|
||||
if (poolBreakdown) {
|
||||
// Count totem dice present in the final modifier formula.
|
||||
let totemDice = 0;
|
||||
@@ -122,14 +114,9 @@ export class VermineUtils {
|
||||
if (modFormula.includes("human_")) totemDice += 1;
|
||||
if (modFormula.includes("adapted_")) totemDice += 1;
|
||||
}
|
||||
// Only count the domain bonus of totems actually activated in the roll.
|
||||
const domainBonus = (totems.human ? totemBonus.human : 0)
|
||||
+ (totems.adapted ? totemBonus.adapted : 0);
|
||||
const basePool = poolBreakdown.total;
|
||||
poolBreakdown.totemDice = totemDice;
|
||||
poolBreakdown.domainBonus = domainBonus;
|
||||
poolBreakdown.domainBonus = influenceMod;
|
||||
// Total = nombre réel de dés lancés (NoD réguliers + dés de totem).
|
||||
// Équivaut à basePool + domainBonus sauf si le pool régulier clampe à 0.
|
||||
poolBreakdown.total = NoD + totemDice;
|
||||
}
|
||||
|
||||
@@ -145,7 +132,7 @@ export class VermineUtils {
|
||||
skillCategory: skillCategory,
|
||||
skillLevel: skillLevel,
|
||||
hasSpecialty: hasSpecialty,
|
||||
totemBonuses: { ...totemBonus },
|
||||
totemInfluence: influenceMod,
|
||||
baseNoD: NoD,
|
||||
rerolls: Reroll,
|
||||
selfControl: self_control,
|
||||
@@ -188,47 +175,12 @@ export class VermineUtils {
|
||||
* Calculates domain bonuses/penalties for totems.
|
||||
* @param {string} skillCategory - The skill category
|
||||
* @param {Actor} actor - The actor
|
||||
* @returns {Object} Bonuses for each totem {human: number, adapted: number}
|
||||
* @returns {number} Modificateur d'influence (-1, 0 ou +1)
|
||||
*/
|
||||
static _calculateTotemDomainBonuses(skillCategory, actor) {
|
||||
const bonuses = { human: 0, adapted: 0 };
|
||||
|
||||
// Validate inputs
|
||||
if (!CONFIG.VERMINE?.totemDomains || !actor?.system?.identity?.totem) {
|
||||
return bonuses;
|
||||
}
|
||||
|
||||
const actorTotem = actor.system.identity.totem;
|
||||
|
||||
// Check if actor's totem exists in configuration
|
||||
if (!CONFIG.VERMINE.totemDomains[actorTotem]) {
|
||||
return bonuses;
|
||||
}
|
||||
|
||||
const totemConfig = CONFIG.VERMINE.totemDomains[actorTotem];
|
||||
|
||||
if (!totemConfig?.domains) {
|
||||
return bonuses;
|
||||
}
|
||||
|
||||
// Get actor's preferred skill category
|
||||
const preferredCategory = actor.system.skill_categories?.preferred;
|
||||
|
||||
// Bonus for actor's totem if preferred category is in its domains
|
||||
if (preferredCategory && totemConfig.domains.includes(preferredCategory)) {
|
||||
bonuses[actorTotem] = totemConfig.bonus || 1;
|
||||
}
|
||||
|
||||
// Penalty for opposite totem if preferred category is in its domains
|
||||
const oppositeTotem = CONFIG.VERMINE.totem_opposites?.[actorTotem];
|
||||
if (oppositeTotem && CONFIG.VERMINE.totemDomains[oppositeTotem]) {
|
||||
const oppositeConfig = CONFIG.VERMINE.totemDomains[oppositeTotem];
|
||||
if (preferredCategory && oppositeConfig?.domains?.includes(preferredCategory)) {
|
||||
bonuses[oppositeTotem] = -(oppositeConfig.bonus || 1);
|
||||
}
|
||||
}
|
||||
|
||||
return bonuses;
|
||||
static _calculateTotemInfluence(skillCategory, actor) {
|
||||
// Les Dés de Totems n'existent que sur les personnages.
|
||||
if (actor?.type !== "character" || !skillCategory) return 0;
|
||||
return VermineTotemDice.influenceModifier(actor, skillCategory);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user