Resultat impari sur D20 dans messages et corrections diverses

This commit is contained in:
2026-03-10 21:37:20 +01:00
parent e7a6c15bf7
commit 6b909b192b
42 changed files with 52 additions and 39 deletions

View File

@@ -43,6 +43,7 @@
"MNBL.disarm": "Disarm", "MNBL.disarm": "Disarm",
"MNBL.doubleD20": "Double d20 (1 Shard Point)", "MNBL.doubleD20": "Double d20 (1 Shard Point)",
"MNBL.dramaticfailure": "Dramatic Failure", "MNBL.dramaticfailure": "Dramatic Failure",
"MNBL.oddresult": "Odd result — the die counts as 0",
"MNBL.duration": "Duration", "MNBL.duration": "Duration",
"MNBL.easy": "Easy (5)", "MNBL.easy": "Easy (5)",
"MNBL.eclat": "Shard", "MNBL.eclat": "Shard",

View File

@@ -161,6 +161,7 @@
"MNBL.failure": "Echec", "MNBL.failure": "Echec",
"MNBL.heroicsuccess": "Succés Héroïque", "MNBL.heroicsuccess": "Succés Héroïque",
"MNBL.dramaticfailure": "Echec Dramatique", "MNBL.dramaticfailure": "Echec Dramatique",
"MNBL.oddresult": "Résultat impair — le dé compte pour 0",
"MNBL.attackmountbonus": "Attaquant monté vs def. au sol (+5)", "MNBL.attackmountbonus": "Attaquant monté vs def. au sol (+5)",
"MNBL.targetdefense": "Défense adversaire", "MNBL.targetdefense": "Défense adversaire",

View File

@@ -132,7 +132,7 @@ export default class MournbladeItemSheet extends HandlebarsApplicationMixin(foun
payload: chatData, payload: chatData,
}) })
const html = await renderTemplate('systems/fvtt-mournblade/templates/post-item.hbs', chatData) const html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-mournblade/templates/post-item.hbs', chatData)
const chatOptions = { const chatOptions = {
user: game.user.id, user: game.user.id,
content: html, content: html,

View File

@@ -11,7 +11,22 @@ export default class CompetenceDataModel extends foundry.abstract.TypeDataModel
attribut2: new fields.StringField({ initial: "" }), attribut2: new fields.StringField({ initial: "" }),
attribut3: new fields.StringField({ initial: "" }), attribut3: new fields.StringField({ initial: "" }),
doublebonus: new fields.BooleanField({ initial: false }), doublebonus: new fields.BooleanField({ initial: false }),
predilections: new fields.ArrayField(new fields.StringField(), { initial: [] }) predilections: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({ initial: "" }),
used: new fields.BooleanField({ initial: false })
}),
{ initial: [] }
)
}; };
} }
static migrateData(source) {
if (Array.isArray(source.predilections)) {
source.predilections = source.predilections.map(pred =>
typeof pred === "string" ? { name: pred, used: false } : pred
);
}
return super.migrateData(source);
}
} }

View File

@@ -18,6 +18,12 @@ export class MournbladeActor extends Actor {
// Calculate derived attributes // Calculate derived attributes
const data = this.system; const data = this.system;
if (this.type == 'personnage') {
// Compute base health and max soul from attributes (derived, no DB write needed)
data.sante.base = data.sante.bonus + (data.attributs.pui.value + data.attributs.tre.value) * 2 + 5;
data.ame.fullmax = (data.attributs.cla.value + data.attributs.tre.value) * data.biodata.amemultiplier + 5;
}
// Calculate total health // Calculate total health
data.sante.total = data.sante.base + data.sante.bonus; data.sante.total = data.sante.base + data.sante.bonus;
@@ -32,7 +38,7 @@ export class MournbladeActor extends Actor {
} }
prepareDerivedData() { prepareDerivedData() {
this.prepareData(); super.prepareDerivedData();
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -299,25 +305,6 @@ export class MournbladeActor extends Actor {
return combat return combat
} }
/* -------------------------------------------- */
prepareDerivedData() {
if (this.type == 'personnage') {
let newSante = this.system.sante.bonus + (this.system.attributs.pui.value + this.system.attributs.tre.value) * 2 + 5
if (this.system.sante.base != newSante && this._id) {
// Only update if the actor already exists (has an _id)
this.update({ 'system.sante.base': newSante })
}
let newAme = (this.system.attributs.cla.value + this.system.attributs.tre.value) * this.system.biodata.amemultiplier + 5
if (this.system.ame.fullmax != newAme && this._id) {
// Only update if the actor already exists (has an _id)
this.update({ 'system.ame.fullmax': newAme })
}
}
super.prepareDerivedData()
}
/* -------------------------------------------- */ /* -------------------------------------------- */
_preUpdate(changed, options, user) { _preUpdate(changed, options, user) {
@@ -583,8 +570,8 @@ export class MournbladeActor extends Actor {
this.update({ 'system.ressources': ressources }) this.update({ 'system.ressources': ressources })
ChatMessage.create({ ChatMessage.create({
content: "L'utilisation de la capacité/arme a dépensé " + arme.system.nbressources + " ressources.", content: "L'utilisation de la capacité/arme a dépensé " + arme.system.nbressources + " ressources.",
whisper: game.user._id, whisper: game.user.id,
user: game.user._id user: game.user.id
}); });
} else { } else {
ui.notifications.warn("Points de ressources insuffisants.") ui.notifications.warn("Points de ressources insuffisants.")
@@ -735,7 +722,7 @@ export class MournbladeActor extends Actor {
let arme = this.items.get(armeId) let arme = this.items.get(armeId)
if (arme) { if (arme) {
MournbladeUtility.createChatWithRollMode("GM", { MournbladeUtility.createChatWithRollMode("GM", {
content: await renderTemplate(`systems/fvtt-mournblade/templates/chat-display-description.hbs`, arme) content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-mournblade/templates/chat-display-description.hbs`, arme)
}, arme) }, arme)
this.depenseRessources(arme) this.depenseRessources(arme)
} }
@@ -751,7 +738,7 @@ export class MournbladeActor extends Actor {
arme = this.prepareBouclier(arme) arme = this.prepareBouclier(arme)
} }
//Unused rollData.degatsFormula = arme.system.totalDegats //Unused rollData.degatsFormula = arme.system.totalDegats
let roll = await new Roll(arme.system.totalDegats).roll() let roll = await new Roll(arme.system.totalDegats).evaluate()
await MournbladeUtility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); await MournbladeUtility.showDiceSoNice(roll, game.settings.get("core", "rollMode"));
let rollData = { let rollData = {
degatsFormula:arme.system.totalDegats, degatsFormula:arme.system.totalDegats,

View File

@@ -10,7 +10,7 @@ export class MournbladeCombat extends Combat {
const c = this.combatants.get(ids[cId]); const c = this.combatants.get(ids[cId]);
let id = c._id || c.id; let id = c._id || c.id;
let initBonus = c.actor ? c.actor.getInitiativeScore() : 0 let initBonus = c.actor ? c.actor.getInitiativeScore() : 0
let roll = new Roll("1d10 + "+initBonus).roll({ async: false}) let roll = await new Roll("1d10 + "+initBonus).evaluate()
await MournbladeUtility.showDiceSoNice(roll, game.settings.get("core", "rollMode")) await MournbladeUtility.showDiceSoNice(roll, game.settings.get("core", "rollMode"))
//console.log("Init bonus", initBonus, roll.total) //console.log("Init bonus", initBonus, roll.total)
await this.updateEmbeddedDocuments("Combatant", [ { _id: id, initiative: roll.total } ]); await this.updateEmbeddedDocuments("Combatant", [ { _id: id, initiative: roll.total } ]);

View File

@@ -89,7 +89,7 @@ export class MournbladeCommands {
if (command && command.func) { if (command && command.func) {
const result = command.func(content, msg, params); const result = command.func(content, msg, params);
if (result == false) { if (result == false) {
RdDCommands._chatAnswer(msg, command.descr); MournbladeCommands._chatAnswer(msg, command.descr);
} }
return true; return true;
} }
@@ -98,8 +98,8 @@ export class MournbladeCommands {
/* -------------------------------------------- */ /* -------------------------------------------- */
async createChar(msg) { async createChar(msg) {
game.system.Mournblade.creator = new MournbladeActorCreate(); game.system.mournblade.creator = new MournbladeActorCreate();
game.system.Mournblade.creator.start(); game.system.mournblade.creator.start();
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@@ -106,7 +106,7 @@ export class MournbladeItemSheet extends foundry.appv1.sheets.ItemSheet {
payload: chatData, payload: chatData,
}); });
renderTemplate('systems/fvtt-mournblade/templates/post-item.hbs', chatData).then(html => { foundry.applications.handlebars.renderTemplate('systems/fvtt-mournblade/templates/post-item.hbs', chatData).then(html => {
let chatOptions = MournbladeUtility.chatDataSetup(html); let chatOptions = MournbladeUtility.chatDataSetup(html);
ChatMessage.create(chatOptions) ChatMessage.create(chatOptions)
}); });

View File

@@ -44,7 +44,7 @@ Hooks.once("init", async function () {
}; };
/* -------------------------------------------- */ /* -------------------------------------------- */
game.socket.on("system.fvtt-mournblade-rpg", data => { game.socket.on("system.fvtt-mournblade", data => {
MournbladeUtility.onSocketMesssage(data); MournbladeUtility.onSocketMesssage(data);
}); });
@@ -119,7 +119,7 @@ Hooks.once("init", async function () {
/* -------------------------------------------- */ /* -------------------------------------------- */
async function welcomeMessage() { async function welcomeMessage() {
const templateData = {}; const templateData = {};
const html = await renderTemplate("systems/fvtt-mournblade/templates/chat-welcome-message.hbs", templateData); const html = await foundry.applications.handlebars.renderTemplate("systems/fvtt-mournblade/templates/chat-welcome-message.hbs", templateData);
ChatMessage.create({ ChatMessage.create({
user: game.user.id, user: game.user.id,
@@ -154,14 +154,14 @@ Hooks.once("ready", function () {
ui.notifications.info("Attention ! Aucun personnage n'est relié au joueur !"); ui.notifications.info("Attention ! Aucun personnage n'est relié au joueur !");
ChatMessage.create({ ChatMessage.create({
content: "<b>ATTENTION</b> Le joueur " + game.user.name + " n'est relié à aucun personnage !", content: "<b>ATTENTION</b> Le joueur " + game.user.name + " n'est relié à aucun personnage !",
user: game.user._id user: game.user.id
}); });
} }
if (!game.user.isGM && game.user.character && !game.user.character.prototypeToken.actorLink) { if (!game.user.isGM && game.user.character && !game.user.character.prototypeToken.actorLink) {
ui.notifications.info("Le token de du joueur n'est pas connecté à l'acteur !"); ui.notifications.info("Le token de du joueur n'est pas connecté à l'acteur !");
ChatMessage.create({ ChatMessage.create({
content: "<b>ATTENTION</b> Le token du joueur " + game.user.name + " n'est pas connecté à l'acteur !", content: "<b>ATTENTION</b> Le token du joueur " + game.user.name + " n'est pas connecté à l'acteur !",
user: game.user._id user: game.user.id
}); });
} }

View File

@@ -154,7 +154,7 @@ export class MournbladeUtility {
if (game.user.isGM) { if (game.user.isGM) {
MournbladeUtility.applyDegatsFromAttaque(rollData) MournbladeUtility.applyDegatsFromAttaque(rollData)
} else { } else {
game.socket.emit("system.fvtt-mournblade", { name: "msg_apply_damage", data: { rolLData: rollData } }) game.socket.emit("system.fvtt-mournblade", { name: "msg_apply_damage", data: { rollData: rollData } })
} }
}) })
} }
@@ -294,6 +294,7 @@ export class MournbladeUtility {
if (diceValue % 2 == 1) { if (diceValue % 2 == 1) {
//console.log("PAIR/IMP2", diceValue) //console.log("PAIR/IMP2", diceValue)
rollData.finalResult -= rollData.roll.terms[0].results[0].result // Substract value rollData.finalResult -= rollData.roll.terms[0].results[0].result // Substract value
rollData.isImpair = true
if (diceValue == 1 || diceValue == 11) { if (diceValue == 1 || diceValue == 11) {
rollData.isDramatique = true rollData.isDramatique = true
rollData.isSuccess = false rollData.isSuccess = false
@@ -312,6 +313,7 @@ export class MournbladeUtility {
rollData.isDramatique = ((rollData.finalResult - rollData.difficulte) <= -10) rollData.isDramatique = ((rollData.finalResult - rollData.difficulte) <= -10)
rollData.isPureSuccess = (rollData.isSuccess && !rollData.isHeroique) rollData.isPureSuccess = (rollData.isSuccess && !rollData.isHeroique)
} }
rollData.isEchec = !rollData.isSuccess
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -608,7 +610,7 @@ export class MournbladeUtility {
chatGM.whisper = this.getUsers(user => user.isGM); chatGM.whisper = this.getUsers(user => user.isGM);
chatGM.content = "Blinde message of " + game.user.name + "<br>" + chatOptions.content; chatGM.content = "Blinde message of " + game.user.name + "<br>" + chatOptions.content;
console.log("blindMessageToGM", chatGM); console.log("blindMessageToGM", chatGM);
game.socket.emit("system.fvtt-weapons-of-the-gods", { msg: "msg_gm_chat_message", data: chatGM }); game.socket.emit("system.fvtt-mournblade", { msg: "msg_gm_chat_message", data: chatGM });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -682,7 +684,7 @@ export class MournbladeUtility {
let target = MournbladeUtility.getTarget() let target = MournbladeUtility.getTarget()
if (target) { if (target) {
rollData.defenderTokenId = target.id rollData.defenderTokenId = target.id
let defender = game.canvas.tokens.get(rollData.defenderTokenId).actor let defender = game.canvas.tokens.get(rollData.defenderTokenId)?.actor
rollData.defenderCombatValues = defender.getCombatValues() rollData.defenderCombatValues = defender.getCombatValues()
rollData.defender = defender.toObject() // Simpler rollData.defender = defender.toObject() // Simpler
rollData.defenderDefense = defender.getBestDefenseValue() rollData.defenderDefense = defender.getBestDefenseValue()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -698,7 +698,7 @@
</li> </li>
<li class="flexrow item"> <li class="flexrow item">
<label class="label-name">{{localize "MNBL.exp"}}</label> <label class="label-name">{{localize "MNBL.exp"}}</label>
<input type="number" class="" name="system.experience" {{#if isPlayMode}}disabled{{/if}} value="{{system.experience}}" data-dtype="Number" /> <input type="number" class="" name="system.experience.value" {{#if isPlayMode}}disabled{{/if}} value="{{system.experience.value}}" data-dtype="Number" />
</li> </li>
</ul> </ul>
</div> </div>

View File

@@ -64,6 +64,13 @@
{{/if}} {{/if}}
</div> </div>
{{!-- Résultat impair --}}
{{#if isImpair}}
<div class="result-warning">
<i class="fas fa-circle-half-stroke"></i> {{localize "MNBL.oddresult"}}
</div>
{{/if}}
{{!-- Détails du jet --}} {{!-- Détails du jet --}}
<div class="result-details"> <div class="result-details">
<div class="details-section"> <div class="details-section">