diff --git a/module/actor.js b/module/actor.js index 9faf2b56..914aa630 100644 --- a/module/actor.js +++ b/module/actor.js @@ -47,11 +47,12 @@ import { RdDRollResult } from "./rdd-roll-result.js"; import { RdDInitiative } from "./initiative.mjs"; import RollDialog from "./roll/roll-dialog.mjs"; import { OptionsAvancees, ROLL_DIALOG_V2, ROLL_DIALOG_V2_TEST } from "./settings/options-avancees.js"; -import { ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION } from "./roll/roll-constants.mjs"; +import { ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION, ROLL_TYPE_SORT } from "./roll/roll-constants.mjs"; import { PART_TACHE } from "./roll/roll-part-tache.mjs"; import { PART_COMP } from "./roll/roll-part-comp.mjs"; import { PART_OEUVRE } from "./roll/roll-part-oeuvre.mjs"; import { PART_CUISINE } from "./roll/roll-part-cuisine.mjs"; +import { PART_SORT } from "./roll/roll-part-sort.mjs"; export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre'] @@ -741,12 +742,7 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ async sortMisEnReserve(sort, draconic, coord, ptreve) { - await this.createEmbeddedDocuments("Item", [{ - type: ITEM_TYPES.sortreserve, - name: sort.name, - img: sort.img, - system: { sortid: sort._id, draconic: (draconic?.name ?? sort.system.draconic), ptreve: ptreve, coord: coord, heurecible: 'Vaisseau' } - }], + await this.createEmbeddedDocuments("Item", [RdDItemSort.prepareSortEnReserve(sort, draconic, ptreve, coord)], { renderSheet: false }); this.tmrApp.updateTokens(); } @@ -1712,15 +1708,18 @@ export class RdDActor extends RdDBaseActorSang { ui.notifications.error("Une queue ou un souffle vous empèche de lancer de sort!") return } + if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { + return await this.rollUnSortV2(); + } // Duplication car les pts de reve sont modifiés dans le sort! let sorts = foundry.utils.duplicate(this.itemTypes[ITEM_TYPES.sort].filter(it => RdDItemSort.isSortOnCoord(it, coord))) if (sorts.length == 0) { ui.notifications.info(`Aucun sort disponible en ${TMRUtility.getTMR(coord).label} !`); - return; + return } - const draconicList = this.computeDraconicAndSortIndex(sorts); - const reve = foundry.utils.duplicate(this.system.carac.reve); + const draconicList = this.computeDraconicAndSortIndex(sorts) + const reve = foundry.utils.duplicate(this.system.carac.reve) const dialog = await this.openRollDialog({ name: 'lancer-un-sort', @@ -1743,6 +1742,27 @@ export class RdDActor extends RdDBaseActorSang { this.tmrApp?.setTMRPendingAction(dialog); } + async rollUnSortV2() { + const rollData = { + ids: { actorId: this.id }, + type: { allowed: [ROLL_TYPE_SORT], current: ROLL_TYPE_SORT } + }; + const dialog = await RollDialog.create(rollData, { + callbacks: [roll => { + this.tmrApp?.restoreTMRAfterAction(); + if (roll.closeTMR) { + this.tmrApp?.close(); + this.tmrApp = undefined; + } + } ], + onRollDone: RollDialog.onRollDoneClose, + onClose: () => { + this.tmrApp?.restoreTMRAfterAction(); + } + }); + this.tmrApp?.setTMRPendingAction(dialog); + } + /* -------------------------------------------- */ isMauvaiseRencontre() { // Gestion queue/souffle 'Mauvaise Rencontre en Perpective' let addMsg = ""; @@ -1814,11 +1834,7 @@ export class RdDActor extends RdDBaseActorSang { } else { console.log('lancement de sort', rollData.selectedSort) - const precedents = rollData.selectedSort.system.lancements ?? [] - const lancements = [...precedents, { - timestamp: game.system.rdd.calendrier.getTimestamp(), - reve: rollData.selectedSort.system.ptreve_reel - }] + const lancements = RdDItemSort.prepareSortAddLancement(rollData.selectedSort, rollData.selectedSort.system.ptreve_reel) await this.updateEmbeddedDocuments('Item', [{ _id: rollData.selectedSort._id, 'system.lancements': lancements }] ) @@ -2121,18 +2137,19 @@ export class RdDActor extends RdDBaseActorSang { async rollLireSigneDraconique(coord) { if (!this.isHautRevant()) { ui.notifications.info("Seul un haut rêvant peut lire un signe draconique!"); - return; + return } - let signes = this._getSignesDraconiques(coord); + let signes = this._getSignesDraconiques(coord) if (signes.length == 0) { - ui.notifications.info(`Aucun signe draconiques en ${coord} !`); - return; + ui.notifications.info(`Aucun signe draconiques en ${coord} !`) + return } + let draconicList = this.getDraconics() .map(draconic => { - let draconicLecture = foundry.utils.duplicate(draconic); - draconicLecture.system.defaut_carac = "intellect"; - return draconicLecture; + let draconicLecture = foundry.utils.duplicate(draconic) + draconicLecture.system.defaut_carac = "intellect" + return draconicLecture }); const intellect = this.system.carac.intellect; diff --git a/module/item-sort.js b/module/item-sort.js index ec4f5cdd..0dd015d0 100644 --- a/module/item-sort.js +++ b/module/item-sort.js @@ -148,10 +148,17 @@ export class RdDItemSort extends Item { /* -------------------------------------------- */ static incrementBonusCase(actor, sort, coord) { + let bonuscase = RdDItemSort.calculBonuscase(sort, coord) + + actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': bonuscase }]); + } + + + static calculBonuscase(sort, coord) { if (TMRUtility.isFleuve(coord)) { - coord = FLEUVE_COORD; + coord = FLEUVE_COORD } - let list = RdDItemSort.stringToBonuscases(sort.system.bonuscase); + let list = RdDItemSort.stringToBonuscases(sort.system.bonuscase) const existing = list.find(it => it.case == coord) const bonus = Number(existing?.bonus ?? 0) + 1 if (existing) { @@ -160,11 +167,9 @@ export class RdDItemSort extends Item { else { list.push({ case: coord, bonus: 1 }) } - - actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': RdDItemSort.bonuscasesToString(list) }]); + return RdDItemSort.bonuscasesToString(list) } - /* -------------------------------------------- */ static getCaseBonus(sort, coord) { const search = TMRUtility.isFleuve(coord) @@ -189,4 +194,22 @@ export class RdDItemSort extends Item { .map(it => it.split(':')) .map(it => { return { case: it[0], bonus: it[1] } }); } + + static prepareSortEnReserve(sort, draconic, ptreve, coord) { + return { + type: ITEM_TYPES.sortreserve, + name: sort.name, + img: sort.img, + system: { sortid: sort._id, draconic: (draconic?.name ?? sort.system.draconic), ptreve: ptreve, coord: coord, heurecible: 'Vaisseau' } + }; + } + + static prepareSortAddLancement(sort, reveSort) { + const precedents = sort.system.lancements ?? [] + const lancements = [...precedents, { + timestamp: game.system.rdd.calendrier.getTimestamp(), + reve: reveSort + }] + return lancements + } } \ No newline at end of file diff --git a/module/roll/roll-dialog.mjs b/module/roll/roll-dialog.mjs index 1c368137..deffa22a 100644 --- a/module/roll/roll-dialog.mjs +++ b/module/roll/roll-dialog.mjs @@ -173,6 +173,8 @@ const ROLL_PARTS = [ /* -------------------------------------------- */ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2) { + static onCloseDoNothing() { + } static onRollDoneDoNothing(dialog) { dialog.render() } @@ -181,7 +183,6 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2 dialog.close() } - static init() { } @@ -236,6 +237,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2 static async create(rollData, rollOptions = {}) { const rollDialog = new RollDialog(rollData, rollOptions) rollDialog.render(true) + return rollDialog } static get PARTS() { @@ -322,7 +324,8 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2 ...(rollOptions.callbacks ?? []) ], customChatMessage: rollOptions.customChatMessage, - onRollDone: rollOptions.onRollDone ?? RollDialog.onRollDoneDoNothing + onRollDone: rollOptions.onRollDone ?? RollDialog.onRollDoneDoNothing, + onClose: rollOptions.onClose ?? RollDialog.onCloseDoNothing } this.chatRollResult = new ChatRollResult(); this.selectType() @@ -440,6 +443,13 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2 return ALL_ROLL_TYPES.find(m => m.code == this.rollData.type.current) } + async close(options){ + if (this.rollOptions.onClose){ + this.rollOptions.onClose() + } + return await super.close(options) + } + async roll() { const roll = RollDialog.saveParts(this.rollData) diff --git a/module/roll/roll-part-sort.mjs b/module/roll/roll-part-sort.mjs index 181af63d..ac7627a4 100644 --- a/module/roll/roll-part-sort.mjs +++ b/module/roll/roll-part-sort.mjs @@ -22,9 +22,27 @@ export class RollPartSort extends RollPartSelect { isValid(rollData) { return rollData.active.actor.isPersonnage() && rollData.active.actor.isHautRevant() } visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_SORT) } + restore(rollData) { + const saved = this.getSaved(rollData) + this.setCurrent(rollData, { + key: saved.key, + isReserve: saved.isReserve, + ptreve: saved.ptreve + }) + } + + store(rollData, targetData) { + const current = this.getCurrent(rollData) + this.setSaved(targetData, { + key: current.key, + isReserve: current.isReserve, + ptreve: current.ptreve + }) + } + loadRefs(rollData) { const refs = this.getRefs(rollData) - const coord = rollData.active.actor.system.reve.tmrpos.coord + const coord = this.getCoord(rollData) const draconics = rollData.active.actor.getDraconics() const sorts = rollData.active.actor.itemTypes[ITEM_TYPES.sort] .map(s => RollPartSort.$extractSort(s, coord, draconics)) @@ -33,7 +51,7 @@ export class RollPartSort extends RollPartSelect { { coord: coord, tmr: TMRUtility.getTMR(coord), - reve: rollData.active.actor.system.reve.reve.value, + reve: this.getReveActuel(rollData), draconics: draconics, all: sorts, sorts: sorts.filter(it => RdDItemSort.isSortOnCoord(it.sort, coord)) @@ -41,10 +59,18 @@ export class RollPartSort extends RollPartSelect { { inplace: true } ) if (refs.sorts.length > 0) { - this.$selectSort(rollData) + this.$selectSort(rollData, this.getSaved(rollData)) } } + getReveActuel(rollData) { + return rollData.active.actor.system.reve.reve.value + } + + getCoord(rollData) { + return rollData.active.actor.system.reve.tmrpos.coord + } + choices(refs) { return refs.sorts } static $extractSort(sort, coord, draconics) { @@ -56,11 +82,12 @@ export class RollPartSort extends RollPartSelect { value: isDiffVariable ? -7 : parseInt(sort.system.difficulte), ptreve: isReveVariable ? 1 : sort.system.ptreve, caseTMR: RdDItemSort.getCaseTMR(sort), + bonusCase: RdDItemSort.getCaseBonus(sort, coord), isDiffVariable: isDiffVariable, isReveVariable: isReveVariable, isReserve: false, sort: sort, - draconics: RdDItemSort.getDraconicsSort(draconics, sort).map(it => it.name) + draconics: RdDItemSort.getDraconicsSort(draconics, sort).map(it => it.name), } } @@ -68,25 +95,27 @@ export class RollPartSort extends RollPartSelect { const current = this.getCurrent(rollData) if (current) { const reserve = current.isReserve ? - [{ label: `Mise en réserve en ${current.coord}` }] : [] + [{ label: `Mise en réserve en ${this.getCoord(rollData)}` }] : [] const bonusCase = current.bonusCase ? [{ label: `Bonus case +${current.bonusCase}%` }] : [] return [ { label: current.label, diff: current.value }, - { label: `r${current.ptreve}` }, ...bonusCase, + { label: `Rêve ${current.ptreve}` }, ...reserve ] } return [] } - $selectSort(rollData, key) { - const previous = this.getCurrent(rollData) - const current = this.selectByKey(rollData, key, -7) - if (current.key != previous.key) { } - current.bonusCase = RdDItemSort.getCaseBonus(current.sort, - rollData.active.actor.system.reve.tmrpos.coord) + $selectSort(rollData, values) { + const current = this.selectByKey(rollData, values.key) + if (values.ptreve) { + current.ptreve = values.ptreve + } + if (values.isReserve != undefined) { + current.isReserve = values.isReserve + } } async _onRender(rollDialog, context, options) { @@ -99,7 +128,7 @@ export class RollPartSort extends RollPartSelect { selectSort.addEventListener("change", e => { const selectOptions = e.currentTarget.options const index = selectOptions.selectedIndex - this.$selectSort(rollDialog.rollData, selectOptions[index]?.value) + this.$selectSort(rollDialog.rollData, { key: selectOptions[index]?.value }) rollDialog.render() }) diff --git a/module/roll/roll-type-sort.mjs b/module/roll/roll-type-sort.mjs index 728b3e3e..88164496 100644 --- a/module/roll/roll-type-sort.mjs +++ b/module/roll/roll-type-sort.mjs @@ -1,4 +1,9 @@ +import { RdDItemCompetence } from "../item-competence.js" +import { RdDItemSort } from "../item-sort.js" +import { RdDResolutionTable } from "../rdd-resolution-table.js" import { DIFF, ROLL_TYPE_SORT } from "./roll-constants.mjs" +import { PART_COMP } from "./roll-part-comp.mjs" +import { PART_SORT } from "./roll-part-sort.mjs" import { RollType } from "./roll-type.mjs" export class RollTypeSort extends RollType { @@ -11,4 +16,69 @@ export class RollTypeSort extends RollType { onSelect(rollData) { this.setDiffType(rollData, DIFF.AUCUN) } + + getResult(rollData, impacts) { + const rolled = rollData.rolled + const actor = rollData.active.actor + const coord = actor.system.reve.tmrpos.coord + const reveActuel = parseInt(actor.system.reve.reve.value) + const draconic = rollData.current[PART_COMP].comp + + const current = rollData.current[PART_SORT] + const sort = current.sort + const isReserve = current.isReserve + const reveSort = current.ptreve + const isThanatos = RdDItemCompetence.isThanatos(draconic) + + actor.tmrApp?.restoreTMRAfterAction() + + current.depenseReve = reveSort + if (isThanatos) { // Si Thanatos + impacts.addActorUpdate("system.reve.reve.thanatosused", true) + } + + if (rolled.isSuccess) { // Réussite du sort ! + if (rolled.isPart) { + current.depenseReve = Math.max(Math.floor(current.depenseReve / 2), 1) + } + if (isReserve) { + current.depenseReve++ + } + + if (reveActuel > current.depenseReve) { + // Incrémenter/gére le bonus de case + impacts.addUpdate('Item', sort, 'system.bonuscase', RdDItemSort.calculBonuscase(sort, coord)) + + if (isReserve) { + impacts.addCreated('Item', RdDItemSort.prepareSortEnReserve(sort, draconic, reveSort, coord)) + } + else { + rollData.closeTMR = true + if (sort.system.isrituel) { + impacts.addUpdate('Item', sort, 'system.lancements', RdDItemSort.prepareSortAddLancement(sort, reveSort)) + } + } + } + else { + current.depenseReve = 0; + rollData.show.reveInsuffisant = true + foundry.utils.mergeObject(rollData.rolled, RdDResolutionTable.getResultat("echec"), { overwrite: true }) + } + } else { + rollData.closeTMR = true + if (rolled.isETotal) { // Echec total ! + current.depenseReve = Math.min(reveActuel, Math.floor(current.depenseReve * 1.5)) + // TODO: mise en réserve d'un échec total... + } else { + current.depenseReve = 0 + } + } + + impacts.addActorDelta("system.reve.reve.value", - Math.min(current.depenseReve, reveActuel)) + + if (current.depenseReve >= reveActuel) { // 0 points de reve + rollData.show.zeroReve = true + } + } + } \ No newline at end of file diff --git a/templates/roll/result/chat-sort.hbs b/templates/roll/result/chat-sort.hbs index e69de29b..e862cd9d 100644 --- a/templates/roll/result/chat-sort.hbs +++ b/templates/roll/result/chat-sort.hbs @@ -0,0 +1,47 @@ +
+ {{#if rolled.isETotal}}Echec TOTAL + {{else if rolled.isEchec}}Echec + {{else}}Réussite{{/if}} + du {{#if current.sort.sort.system.isrituel}}rituel{{else}}sort{{/if}}, + {{#if rolled.isSuccess}} + le sort est {{#if current.sort.isReserve}}mis en réserve{{else}}lancé{{/if}} + avec {{current.sort.ptreve}} point{{~#if (gt current.sort.ptreve 1)}}s{{/if}} de rêve en {{caseTmr-label refs.sort.coord}} ({{refs.sort.coord}}). + {{/if}} +
++ {{#if (eq current.sort.depenseReve 0)}}Pas de dépense de rêve + {{else if (eq current.sort.depenseReve 1)}}1 point de rêve a été dépensé + {{else}}{{current.sort.depenseReve}} points de rêve ont été dépensés + {{~/if}}. + {{#if show.reveInsuffisant}}Pas assez de rêve!{{/if}} +
+ + {{> "systems/foundryvtt-reve-de-dragon/templates/chat-description.hbs" current.sort.sort.system}} +