diff --git a/assets/icons/adresse.webp b/assets/icons/adresse.webp new file mode 100644 index 0000000..e36b964 Binary files /dev/null and b/assets/icons/adresse.webp differ diff --git a/assets/icons/bonneaventure.webp b/assets/icons/bonneaventure.webp new file mode 100644 index 0000000..a32ad80 Binary files /dev/null and b/assets/icons/bonneaventure.webp differ diff --git a/assets/icons/clairvoyance.webp b/assets/icons/clairvoyance.webp new file mode 100644 index 0000000..196810e Binary files /dev/null and b/assets/icons/clairvoyance.webp differ diff --git a/assets/icons/eclat.webp b/assets/icons/eclat.webp new file mode 100644 index 0000000..fdb1c0b Binary files /dev/null and b/assets/icons/eclat.webp differ diff --git a/assets/icons/presence.webp b/assets/icons/presence.webp new file mode 100644 index 0000000..4f2a4ad Binary files /dev/null and b/assets/icons/presence.webp differ diff --git a/assets/icons/puissance.webp b/assets/icons/puissance.webp new file mode 100644 index 0000000..e537971 Binary files /dev/null and b/assets/icons/puissance.webp differ diff --git a/assets/icons/trempe.webp b/assets/icons/trempe.webp new file mode 100644 index 0000000..e2371df Binary files /dev/null and b/assets/icons/trempe.webp differ diff --git a/modules/mournblade-actor-sheet.js b/modules/mournblade-actor-sheet.js index a77e980..311c6ac 100644 --- a/modules/mournblade-actor-sheet.js +++ b/modules/mournblade-actor-sheet.js @@ -43,6 +43,7 @@ export class MournbladeActorSheet extends ActorSheet { skills: duplicate(this.actor.getSkills()), weapons: duplicate(this.actor.getWeapons()), armors: duplicate(this.actor.getArmors()), + alignement: this.actor.getAlignement(), //equipments: duplicate(this.actor.getEquipments()), options: this.options, owner: this.document.isOwner, diff --git a/modules/mournblade-actor.js b/modules/mournblade-actor.js index 3b80c4e..3516082 100644 --- a/modules/mournblade-actor.js +++ b/modules/mournblade-actor.js @@ -46,18 +46,18 @@ export class MournbladeActor extends Actor { /* -------------------------------------------- */ getWeapons() { - return this.data.items.filter(item => item.type == "arme" ) + return this.data.items.filter(item => item.type == "arme") } /* -------------------------------------------- */ getArmors() { - return this.data.items.filter(item => item.type == "protection" ) + return this.data.items.filter(item => item.type == "protection") } /* -------------------------------------------- */ getSkills() { let comp = [] - for( let item of this.data.items) { + for (let item of this.data.items) { item = duplicate(item) - if ( item.type == "competence") { + if (item.type == "competence") { item.data.attribut1total = item.data.niveau + (this.data.data.attributs[item.data.attribut1]?.value || 0) item.data.attribut2total = item.data.niveau + (this.data.data.attributs[item.data.attribut2]?.value || 0) item.data.attribut3total = item.data.niveau + (this.data.data.attributs[item.data.attribut3]?.value || 0) @@ -69,12 +69,17 @@ export class MournbladeActor extends Actor { item.data.attribut1label = this.data.data.attributs[item.data.attribut1]?.label || "" item.data.attribut2label = this.data.data.attributs[item.data.attribut2]?.label || "" item.data.attribut3label = this.data.data.attributs[item.data.attribut3]?.label || "" - comp.push( item ) - } + comp.push(item) + } } return comp } - + + /* -------------------------------------------- */ + getAlignement() { + return (this.data.data.balance.loi > this.data.data.balance.chaos) ? "loyal" : "chaotique" + } + /* -------------------------------------------- */ prepareBaseData() { } @@ -119,7 +124,7 @@ export class MournbladeActor extends Actor { /* -------------------------------------------- */ editItemField(itemId, itemType, itemField, dataType, value) { - let item= this.data.items.find(item => item.id == itemId) + let item = this.data.items.find(item => item.id == itemId) if (item) { console.log("Item ", item, itemField, dataType, value) if (dataType.toLowerCase() == "number") { @@ -128,10 +133,39 @@ export class MournbladeActor extends Actor { value = String(value) } let update = { _id: item.id, [`data.${itemField}`]: value }; - this.updateEmbeddedDocuments( "Item", [update]) + this.updateEmbeddedDocuments("Item", [update]) } } + /* -------------------------------------------- */ + getBonneAventure() { + return this.data.data.bonneaventure.actuelle + } + + /* -------------------------------------------- */ + changeBonneAventure(value) { + let newBA = this.data.data.bonneaventure.actuelle + newBA += value + this.update({ 'data.bonneaventure.actuelle': newBA }) + } + + /* -------------------------------------------- */ + getEclat() { + return this.data.data.eclat.value + } + + /* -------------------------------------------- */ + changeEclat(value) { + let newE = this.data.data.eclat.value + newE += value + this.update({ 'data.eclat.value': newE }) + } + + /* -------------------------------------------- */ + canEclatDoubleD20( ) { + return ( this.getAlignement() == "loyal" && this.data.data.eclat.value> 0) + } + /* -------------------------------------------- */ compareName(a, b) { if (a.name < b.name) { @@ -198,13 +232,17 @@ export class MournbladeActor extends Actor { rollData.actorImg = this.img rollData.actorId = this.id rollData.img = this.img - + rollData.canEclatDoubleD20 = this.canEclatDoubleD20() + rollData.doubleD20 = false + if (attrKey) { rollData.attrKey = attrKey + rollData.actionImg = "systems/fvtt-mournblade/assets/icons/" + this.data.data.attributs[attrKey].labelnorm + ".webp" rollData.attr = duplicate(this.data.data.attributs[attrKey]) } if (compId) { rollData.competence = duplicate(this.data.items.get(compId) || {}) + rollData.actionImg = rollData.competence.img } return rollData } diff --git a/modules/mournblade-roll-dialog.js b/modules/mournblade-roll-dialog.js index a396ff0..b32ec97 100644 --- a/modules/mournblade-roll-dialog.js +++ b/modules/mournblade-roll-dialog.js @@ -63,6 +63,8 @@ export class MournbladeRollDialog extends Dialog { html.find('#difficulte').change(async (event) => { this.rollData.difficulte = Number(event.currentTarget.value) }) - + html.find('#doubleD20').change(async (event) => { + this.rollData.doubleD20 = event.currentTarget.checked + }) } } \ No newline at end of file diff --git a/modules/mournblade-utility.js b/modules/mournblade-utility.js index 87b58dd..b25b5d6 100644 --- a/modules/mournblade-utility.js +++ b/modules/mournblade-utility.js @@ -8,10 +8,12 @@ export class MournbladeUtility { /* -------------------------------------------- */ static async init() { - Hooks.on('renderChatLog', (log, html, data) => MournbladeUtility.chatListeners(html)); + Hooks.on('renderChatLog', (log, html, data) => MournbladeUtility.chatListeners(html)) + Hooks.on("getChatLogEntryContext", (html, options) => MournbladeUtility.chatRollMenu(html, options)) + Hooks.on("getCombatTrackerEntryContext", (html, options) => { MournbladeUtility.pushInitiativeOptions(html, options); - }); + }) Hooks.on("dropCanvasData", (canvas, data) => { MournbladeUtility.dropItemOnToken(canvas, data) }); @@ -49,14 +51,14 @@ export class MournbladeUtility { static getModificateurOptions() { let opt = [] for (let i = -15; i <= 15; i++) { - opt.push( `` ) + opt.push(``) } return opt.concat("\n") } /* -------------------------------------------- */ static getAttributs() { - return { adr: "Adresse", pui: "Puissance", cla: "Clairvoyance", pre: "Présence", tre: "Trempe"} + return { adr: "Adresse", pui: "Puissance", cla: "Clairvoyance", pre: "Présence", tre: "Trempe" } } /* -------------------------------------------- */ static pushInitiativeOptions(html, options) { @@ -101,9 +103,9 @@ export class MournbladeUtility { static async preloadHandlebarsTemplates() { const templatePaths = [ - 'systems/fvtt-mournblade/templates/editor-notes-gm.html', - 'systems/fvtt-mournblade/templates/partial-item-description.html', - 'systems/fvtt-mournblade/templates/partial-list-niveau.html' + 'systems/fvtt-mournblade/templates/editor-notes-gm.html', + 'systems/fvtt-mournblade/templates/partial-item-description.html', + 'systems/fvtt-mournblade/templates/partial-list-niveau.html' ] return loadTemplates(templatePaths); } @@ -193,7 +195,7 @@ export class MournbladeUtility { } /* -------------------------------------------- */ static saveRollData(rollData) { - game.socket.emit("system.Mournblade-rpg", { + game.socket.emit("system.fvtt-mournblade", { name: "msg_update_roll", data: rollData }); // Notify all other clients of the roll this.updateRollData(rollData); @@ -260,51 +262,77 @@ export class MournbladeUtility { } } + /* -------------------------------------------- */ + static computeResult(rollData) { + if (rollData.mainDice == "1d20") { + let diceValue = rollData.roll.terms[0].results[0].result + diceValue *= (rollData.doubleD20) ? 2 : 1 + //console.log("PAIR/IMP", diceValue) + if (diceValue % 2 == 1) { + //console.log("PAIR/IMP2", diceValue) + rollData.finalResult -= rollData.roll.terms[0].results[0].result // Substract value + if (diceValue == 1 || diceValue == 11) { + rollData.isDramatique = true + rollData.isSuccess = false + } + } + } + + if (rollData.difficulte > 0 && !rollData.isDramatique) { + rollData.isSuccess = (rollData.roll.finalResult >= rollData.difficulte) + rollData.isHeroique = ((rollData.roll.finalResult - rollData.difficulte) >= 10) + rollData.isDramatique = ((rollData.roll.finalResult - rollData.difficulte) <= -10) + } + } + /* -------------------------------------------- */ static async rollMournblade(rollData) { rollData.diceFormula = rollData.mainDice - if (rollData.competence) { + if ( rollData.doubleD20) { // Multiply result ! + rollData.diceFormula += "*2" + if (!rollData.isReroll) { + let actor = game.actors.get(rollData.actorId) + actor.changeEclat(-1) + } + } + if (rollData.competence) { let compmod = (rollData.competence.data.niveau == 0) ? -3 : 0 rollData.diceFormula += `+${rollData.attr.value}+${rollData.competence.data.niveau}+${rollData.modificateur}+${compmod}` } else { rollData.diceFormula += `+${rollData.attr.value}*2+${rollData.modificateur}` } - let myRoll = rollData.roll - if (!myRoll) { // New rolls only of no rerolls - myRoll = new Roll(rollData.diceFormula).roll({ async: false }); - console.log("ROLL : ", rollData.diceFormula) - await this.showDiceSoNice(myRoll, game.settings.get("core", "rollMode")); - rollData.roll = myRoll - } + let myRoll = new Roll(rollData.diceFormula).roll({ async: false }) + await this.showDiceSoNice(myRoll, game.settings.get("core", "rollMode")); + rollData.roll = myRoll console.log(">>>> ", myRoll) rollData.finalResult = myRoll.total - if ( rollData.mainDice == "1d20") { - let diceValue = myRoll.terms[0].results[0].result - console.log("PAIR/IMP", diceValue) - if ( diceValue % 2 == 1) { - console.log("PAIR/IMP2", diceValue) - rollData.finalResult -= myRoll.terms[0].results[0].result // Substract value - if (diceValue == 1 || diceValue == 11) { - rollData.isDramatique = true - rollData.isSuccess = false - } - } - } - - if (rollData.difficulte > 0 && !rollData.isDramatique) { - rollData.isSuccess = (myRoll.finalResult >= rollData.difficulte) - rollData.isHeroique = ((myRoll.finalResult - rollData.difficulte) >= 10) - rollData.isDramatique = ((myRoll.finalResult - rollData.difficulte) <= -10) - } + this.computeResult( rollData) + this.createChatWithRollMode(rollData.alias, { content: await renderTemplate(`systems/fvtt-mournblade/templates/chat-generic-result.html`, rollData) - }); + }, rollData) + + } + + /* -------------------------------------------- */ + static async bonusRollMournblade(rollData) { + rollData.bonusFormula = rollData.addedBonus + + let bonusRoll = new Roll(rollData.bonusFormula).roll({async: false}) + await this.showDiceSoNice(bonusRoll, game.settings.get("core", "rollMode")); + rollData.bonusRoll = bonusRoll + + rollData.finalResult += rollData.bonusRoll.total + + this.computeResult( rollData) + + this.createChatWithRollMode(rollData.alias, { + content: await renderTemplate(`systems/fvtt-mournblade/templates/chat-generic-result.html`, rollData) + }, rollData) - // And save the roll - this.saveRollData(rollData); } /* -------------------------------------------- */ @@ -364,7 +392,7 @@ export class MournbladeUtility { } /* -------------------------------------------- */ - static createChatMessage(name, rollMode, chatOptions) { + static async createChatMessage(name, rollMode, chatOptions, rollData = undefined) { switch (rollMode) { case "blindroll": // GM only if (!game.user.isGM) { @@ -381,8 +409,10 @@ export class MournbladeUtility { chatOptions.whisper = this.getWhisperRecipients(rollMode, name); break; } - chatOptions.alias = chatOptions.alias || name; - ChatMessage.create(chatOptions); + chatOptions.alias = chatOptions.alias || name + let msg = await ChatMessage.create(chatOptions) + console.log("=======>", rollData) + msg.setFlag("world", "mournblade-roll", rollData) } /* -------------------------------------------- */ @@ -390,7 +420,7 @@ export class MournbladeUtility { let rollData = { rollId: randomID(16), rollMode: game.settings.get("core", "rollMode"), - modificateursOptions : this.getModificateurOptions(), + modificateursOptions: this.getModificateurOptions(), difficulte: 0, modificateur: 0, } @@ -413,8 +443,119 @@ export class MournbladeUtility { } /* -------------------------------------------- */ - static createChatWithRollMode(name, chatOptions) { - this.createChatMessage(name, game.settings.get("core", "rollMode"), chatOptions); + static createChatWithRollMode(name, chatOptions, rollData = undefined) { + this.createChatMessage(name, game.settings.get("core", "rollMode"), chatOptions, rollData) + } + + /* -------------------------------------------- */ + static applyBonneAventureRoll(li, changed, addedBonus) { + let msgId = li.data("message-id") + let msg = game.messages.get(msgId) + if (msg) { + let rollData = msg.getFlag("world", "mournblade-roll") + let actor = game.actors.get(rollData.actorId) + actor.changeBonneAventure( changed ) + rollData.isReroll = true + rollData.textBonus = "Bonus de Points d'Aventure" + if (addedBonus == "reroll") { + MournbladeUtility.rollMournblade(rollData) + } else { + rollData.addedBonus = addedBonus + MournbladeUtility.bonusRollMournblade(rollData) + } + } + } + + /* -------------------------------------------- */ + static applyEclatRoll(li, changed, addedBonus) { + let msgId = li.data("message-id") + let msg = game.messages.get(msgId) + if (msg) { + let rollData = msg.getFlag("world", "mournblade-roll") + let actor = game.actors.get(rollData.actorId) + actor.changeEclat( changed ) + rollData.isReroll = true + rollData.textBonus = "Bonus d'Eclat" + rollData.addedBonus = addedBonus + MournbladeUtility.bonusRollMournblade(rollData) + } + } + + /* -------------------------------------------- */ + static chatRollMenu(html, options) { + let canApply = li => canvas.tokens.controlled.length && li.find(".mournblade-roll").length + let canApplyBALoyal = function (li) { + let message = game.messages.get(li.attr("data-message-id")) + let rollData = message.getFlag("world", "mournblade-roll") + let actor = game.actors.get(rollData.actorId) + return ( !rollData.isReroll && actor.getBonneAventure() > 0 && actor.getAlignement() == "loyal") + } + let canApplyPELoyal = function (li) { + let message = game.messages.get(li.attr("data-message-id")) + let rollData = message.getFlag("world", "mournblade-roll") + let actor = game.actors.get(rollData.actorId) + return ( !rollData.isReroll && actor.getEclat() > 0 && actor.getAlignement() == "loyal") + } + let canApplyBAChaotique = function (li) { + let message = game.messages.get(li.attr("data-message-id")) + let rollData = message.getFlag("world", "mournblade-roll") + let actor = game.actors.get(rollData.actorId) + return ( !rollData.isReroll && actor.getBonneAventure() > 0 && actor.getAlignement() == "chaotique") + } + let canApplyBAChaotique3 = function (li) { + let message = game.messages.get(li.attr("data-message-id")) + let rollData = message.getFlag("world", "mournblade-roll") + let actor = game.actors.get(rollData.actorId) + return ( !rollData.isReroll && actor.getBonneAventure() > 2 && actor.getAlignement() == "chaotique") + } + let canApplyPEChaotique = function (li) { + let message = game.messages.get(li.attr("data-message-id")) + let rollData = message.getFlag("world", "mournblade-roll") + let actor = game.actors.get(rollData.actorId) + return ( !rollData.isReroll && actor.getEclat() > 0 && actor.getAlignement() == "chaotique") + } + + options.push( + { + name: "Ajouer +3 (1 point de Bonne Aventure)", + icon: "", + condition: canApply && canApplyBALoyal, + callback: li => MournbladeUtility.applyBonneAventureRoll(li, -1, "+3") + } + ) + options.push( + { + name: "Ajouer +1d6 (1 point de Bonne Aventure)", + icon: "", + condition: canApply && canApplyBAChaotique, + callback: li => MournbladeUtility.applyBonneAventureRoll(li, -1, "+1d6") + } + ) + options.push( + { + name: "Relancer le dé (3 points de Bonne Aventure)", + icon: "", + condition: canApply && canApplyBAChaotique3, + callback: li => MournbladeUtility.applyBonneAventureRoll(li, -3, "reroll") + } + ) + options.push( + { + name: "Ajouter +10 (1 Point d'Eclat)", + icon: "", + condition: canApply && canApplyPELoyal, + callback: li => MournbladeUtility.applyEclatRoll(li, -1, "+10") + } + ) + options.push( + { + name: "Ajouter +1d20(1 Point d'Eclat)", + icon: "", + condition: canApply && canApplyPEChaotique, + callback: li => MournbladeUtility.applyEclatRoll(li, -1, "+1d20") + } + ) + return options } /* -------------------------------------------- */ diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index ddbac92..065bc43 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -48,13 +48,37 @@ +