From dcc450db63c46c9519219d6dee7c5acef0240cb9 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Thu, 18 Mar 2021 23:46:49 +0100 Subject: [PATCH 1/9] Fix tooltip rencontre dans les TMR --- module/tmr/rencontre.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/tmr/rencontre.js b/module/tmr/rencontre.js index 6bce1a6e..119a6c68 100644 --- a/module/tmr/rencontre.js +++ b/module/tmr/rencontre.js @@ -13,7 +13,7 @@ export class Rencontre extends Draconique { async onActorCreateOwned(actor, item) { } code() { return 'rencontre' } - tooltip(linkData) { return `${linkData.name} de force ${linkData.force}` } + tooltip(linkData) { return `${linkData.rencontre.name} de force ${linkData.rencontre.force}` } img() { return 'systems/foundryvtt-reve-de-dragon/icons/heures/hd06.svg' } createSprite(pixiTMR) { From 17d863482daa2885c4cb52aa6856c8057ce27539 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Thu, 18 Mar 2021 23:55:26 +0100 Subject: [PATCH 2/9] simplification/organisation RdDActorSheet.getData --- module/actor-sheet.js | 56 ++++++++++++-------------------------- module/actor.js | 6 ++-- module/item-arme.js | 32 +++++++++++++++++----- module/item-competence.js | 6 +++- templates/actor-sheet.html | 15 +++++----- 5 files changed, 58 insertions(+), 57 deletions(-) diff --git a/module/actor-sheet.js b/module/actor-sheet.js index a9fcc32e..29170dc2 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -62,9 +62,6 @@ export class RdDActorSheet extends ActorSheet { if (this.actor.data.type == 'creature') return formData; // Shortcut - // toujours avoir une liste d'armes (pour mettre esquive et corps à corps) - formData.itemsByType.arme = formData.itemsByType.arme ?? []; - formData.competenceByCategory = Misc.classify(formData.data.competences, item => item.data.categorie); formData.calc = { @@ -93,38 +90,15 @@ export class RdDActorSheet extends ActorSheet { }); - // Force empty arme, at least for Esquive - if (formData.itemsByType.arme == undefined) formData.itemsByType.arme = []; - for (const arme of formData.itemsByType.arme) { - arme.data.niveau = 0; // Per default, TODO to be fixed - for (const melee of formData.competenceByCategory.melee) { - if (melee.name == arme.data.competence) - arme.data.niveau = melee.data.niveau - } - for (const tir of formData.competenceByCategory.tir) { - if (tir.name == arme.data.competence) - arme.data.niveau = tir.data.niveau - } - for (const lancer of formData.competenceByCategory.lancer) { - if (lancer.name == arme.data.competence) - arme.data.niveau = lancer.data.niveau - } - } - - // To avoid armour and so on... - formData.data.combat = duplicate(RdDUtility.checkNull(formData.itemsByType['arme'])); + // toujours avoir une liste d'armes (pour mettre esquive et corps à corps) + formData.data.combat = duplicate(formData.itemsByType.arme ?? []); + RdDItemArme.computeNiveauArmes(formData.data.combat, formData.data.competences); + RdDItemArme.ajoutCorpsACorps(formData.data.combat, formData.data.competences, formData.data.carac ); + formData.esquive = RdDItemCompetence.getEsquive(formData.data.competences); formData.data.combat = RdDCombatManager.finalizeArmeList(formData.data.combat, formData.itemsByType.competence, formData.data.carac); - formData.esquive = { name: "Esquive", niveau: formData.competenceByCategory?.melee.find(it => it.name == 'Esquive')?.data.niveau ?? -6 }; - let corpsACorps = formData.competenceByCategory?.melee.find(it => it.name == 'Corps à corps'); - if (corpsACorps) { - let cc_init = RdDCombatManager.calculInitiative(corpsACorps.data.niveau, formData.data.carac['melee'].value); - formData.data.combat.push(RdDItemArme.mainsNues({ niveau: corpsACorps.data.niveau, initiative: cc_init })); - } - this.armesList = duplicate(formData.data.combat); - formData.data.carac.taille.isTaille = true; // To avoid button link; - formData.data.blessures.resume = this.actor.computeResumeBlessure(formData.data.blessures); + this.armesList = formData.data.combat; // Mise à jour de l'encombrement total et du prix de l'équipement @@ -140,14 +114,18 @@ export class RdDActorSheet extends ActorSheet { html: "" + RdDUtility.makeHTMLfatigueMatrix(formData.data.sante.fatigue.value, formData.data.sante.endurance.max).html() + "
" } - RdDUtility.filterItemsPerTypeForSheet(formData); - formData.data.sortReserve = formData.data.reve.reserve.list; - formData.data.rencontres = duplicate(formData.data.reve.rencontre.list); - formData.data.caseSpeciales = formData.itemsByType['casetmr']; + formData.hautreve = { + sortsReserve: formData.data.reve.reserve.list, + rencontres: duplicate(formData.data.reve.rencontre.list), + casesTmr: formData.itemsByType.casetmr + } + RdDUtility.buildArbreDeConteneur(this, formData); - formData.data.vehiculesList = this.actor.buildVehiculesList(); - formData.data.monturesList = this.actor.buildMonturesList(); - formData.data.suivantsList = this.actor.buildSuivantsList(); + formData.subacteurs = { + vehicules: this.actor.listeVehicules(), + montures: this.actor.listeMontures(), + suivants: this.actor.listeSuivants() + } return formData; } diff --git a/module/actor.js b/module/actor.js index 8b046d36..30a01d16 100644 --- a/module/actor.js +++ b/module/actor.js @@ -3007,7 +3007,7 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - buildVehiculesList() { + listeVehicules() { return this._buildActorLinksList( this.data.data.subacteurs?.vehicules ?? [], vehicle => { @@ -3019,12 +3019,12 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - buildSuivantsList() { + listeSuivants() { return this._buildActorLinksList(this.data.data.subacteurs?.suivants ?? []); } /* -------------------------------------------- */ - buildMonturesList() { + listeMontures() { return this._buildActorLinksList(this.data.data.subacteurs?.montures ?? []); } diff --git a/module/item-arme.js b/module/item-arme.js index fa3428a5..0d6ea65d 100644 --- a/module/item-arme.js +++ b/module/item-arme.js @@ -1,4 +1,5 @@ import { RdDItemCompetenceCreature } from "./item-competencecreature.js" +import { RdDCombatManager } from "./rdd-combat.js"; const nomCategorieParade = { "sans-armes": "Sans arme / armes naturelles", @@ -30,6 +31,17 @@ export class RdDItemArme extends Item { return RdDItemArme.mainsNues(); } + static computeNiveauArmes(armes, competences) { + for (const arme of armes) { + arme.data.niveau = RdDItemArme.niveauCompetenceArme(arme, competences); + } + } + + static niveauCompetenceArme(arme, competences) { + const compArme = competences.find(it => it.name == arme.data.competence); + return compArme?.data.niveau ?? -8; + } + /* -------------------------------------------- */ static getNomCategorieParade(arme) { const categorie = arme?.data ? RdDItemArme.getCategorieParade(arme) : arme; @@ -38,7 +50,7 @@ export class RdDItemArme extends Item { /* -------------------------------------------- */ static needArmeResist(armeAttaque, armeParade) { - if (!armeAttaque || !armeParade){ + if (!armeAttaque || !armeParade) { return false; } // Epées parant une arme de bois (cf. page 115 ), une résistance est nécessaire @@ -54,7 +66,7 @@ export class RdDItemArme extends Item { return arme.data.categorie_parade; } // pour compatibilité avec des personnages existants - if (arme.type == 'competencecreature' || arme.data.categorie == 'creature' ) { + if (arme.type == 'competencecreature' || arme.data.categorie == 'creature') { return arme.data.categorie_parade || (arme.data.isparade ? 'sans-armes' : ''); } if (!arme.type.match(/arme|competencecreature/)) { @@ -86,7 +98,7 @@ export class RdDItemArme extends Item { /* -------------------------------------------- */ static needParadeSignificative(armeAttaque, armeParade) { - if (!armeAttaque || !armeParade){ + if (!armeAttaque || !armeParade) { return false; } // categories d'armes à la parade (cf. page 115 ) @@ -145,10 +157,16 @@ export class RdDItemArme extends Item { } static isArmeUtilisable(item) { - return item.type == 'arme' && item.data.equipe && (item.data.resistance > 0 || item.data.portee_courte>0); + return item.type == 'arme' && item.data.equipe && (item.data.resistance > 0 || item.data.portee_courte > 0); } - static mainsNues(actorData={}) { + static ajoutCorpsACorps(armes, competences, carac) { + let corpsACorps = competences.find(it => it.name == 'Corps à corps') ?? { data: { niveau: -6 } }; + let init = RdDCombatManager.calculInitiative(corpsACorps.data.niveau, carac['melee'].value); + armes.push(RdDItemArme.mainsNues({ niveau: corpsACorps.data.niveau, initiative: init })); + } + + static mainsNues(actorData = {}) { const mainsNues = { name: 'Mains nues', data: { @@ -163,8 +181,8 @@ export class RdDItemArme extends Item { } }; if (actorData) { - mergeObject( mainsNues.data, actorData, {overwrite:false}); + mergeObject(mainsNues.data, actorData, { overwrite: false }); } return mainsNues } -} +} diff --git a/module/item-competence.js b/module/item-competence.js index 2f947f17..c7be84c7 100644 --- a/module/item-competence.js +++ b/module/item-competence.js @@ -56,11 +56,15 @@ export class RdDItemCompetence extends Item { return categorieCompetences[category].label; } + static getEsquive(competences) { + return { name: 'Esquive', niveau: RdDItemCompetence.findCompetence(competences, 'Esquive')?.data.niveau ?? -6 }; + } + /* -------------------------------------------- */ static isCompetenceArme(competence) { switch (competence.data.categorie) { case 'melee': - return competence.name.toLowerCase() != 'esquive'; + return competence.name != 'Esquive'; case 'tir': case 'lancer': return true; diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index 84b0b5a8..056359c8 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -541,6 +541,7 @@ {{!-- hautreve Tab --}} + {{log 'Haut reve' hautreve}}

Haut rêve:

@@ -599,7 +600,7 @@

Sorts en Réserve:

    - {{#each data.sortReserve as |reserve key|}} + {{#each hautreve.sortsReserve as |reserve key|}}
  • {{reserve.sort.name}} - {{reserve.coord}}
  • @@ -625,7 +626,7 @@

    Cases Spéciales:

      - {{#each data.caseSpeciales as |casetmr key|}} + {{#each hautreve.casesTmr as |casetmr key|}}
    • {{casetmr.name}}
      @@ -639,9 +640,9 @@

      Rencontres présentes:

        - {{#each data.rencontres as |rencontre key|}} + {{#each hautreve.rencontres as |rencontre key|}}
      • - {{rencontre.rencontre.name}} - {{rencontre.coord}} ({{rencontre.rencontre.date}} - {{rencontre.rencontre.heure}}) + {{rencontre.rencontre.name}} - {{rencontre.coord}} {{#if rencontre.rencontre.date}}({{rencontre.rencontre.date}} - {{rencontre.rencontre.heure}}){{/if}}
        @@ -760,7 +761,7 @@

        Montures

          - {{#each data.monturesList as |monture id|}} + {{#each subacteurs.montures as |monture id|}}
        • {{monture.name}} @@ -773,7 +774,7 @@

          Véhicules

            - {{#each data.vehiculesList as |vehicule id|}} + {{#each subacteurs.vehicules as |vehicule id|}}
          • {{vehicule.name}} @@ -788,7 +789,7 @@

            Suivants

              - {{#each data.suivantsList as |suivant id|}} + {{#each subacteurs.suivants as |suivant id|}}
            • {{suivant.name}} From e71c03abb0f4698eaefde1866ffe6cbf2f4e2b1d Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Thu, 18 Mar 2021 23:55:59 +0100 Subject: [PATCH 3/9] Fix erreur en cas d'attaque sans cible --- module/actor.js | 2 +- module/rdd-combat.js | 26 ++++++++++++++++---------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/module/actor.js b/module/actor.js index 30a01d16..659a971d 100644 --- a/module/actor.js +++ b/module/actor.js @@ -2546,7 +2546,7 @@ export class RdDActor extends Actor { let competence = this.getCompetence(compName); if (arme || armeName || (competence.type == 'competencecreature' && competence.data.iscombat)) { - RdDCombat.createUsingTarget(this).attaque(competence, arme); + RdDCombat.createUsingTarget(this)?.attaque(competence, arme); } else { this.rollCompetence(competence.name); } diff --git a/module/rdd-combat.js b/module/rdd-combat.js index db85f5c1..e668de44 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -413,9 +413,11 @@ export class RdDCombat { ? "Vous devez choisir une seule cible à attaquer!" : "Vous devez choisir une cible à attaquer!"); } - const defender = target?.actor; - const defenderTokenId = target?.data._id; - return this.create(attacker, defender, defenderTokenId, target) + else { + const defender = target?.actor; + const defenderTokenId = target?.data._id; + return this.create(attacker, defender, defenderTokenId, target) + } } /* -------------------------------------------- */ @@ -500,11 +502,13 @@ export class RdDCombat { } if ((game.user.isGM && !defenderToken.actor.hasPlayerOwner) || (defenderToken.actor.hasPlayerOwner && (game.user.character._id == defenderToken.actor.data._id))) { const rddCombat = RdDCombat.createForAttackerAndDefender(msg.attackerId, msg.defenderTokenId); - const defenderRoll = msg.defenderRoll; - RdDCombat._storeAttaque(msg.attackerId, defenderRoll.attackerRoll); - RdDCombat._storeDefense(defenderRoll); - rddCombat.removeChatMessageActionsPasseArme(defenderRoll.passeArme); - rddCombat._chatMessageDefense(msg.paramChatDefense); + if (rddCombat) { + const defenderRoll = msg.defenderRoll; + RdDCombat._storeAttaque(msg.attackerId, defenderRoll.attackerRoll); + RdDCombat._storeDefense(defenderRoll); + rddCombat.removeChatMessageActionsPasseArme(defenderRoll.passeArme); + rddCombat._chatMessageDefense(msg.paramChatDefense); + } } } } @@ -533,9 +537,11 @@ export class RdDCombat { const rddCombat = RdDCombat.createForAttackerAndDefender( event.currentTarget.attributes['data-attackerId']?.value, event.currentTarget.attributes['data-defenderTokenId']?.value); + if (rddCombat) { - rddCombat.onEvent(button, event); - event.preventDefault(); + rddCombat.onEvent(button, event); + event.preventDefault(); + } }); } html.on("click", '#chat-jet-vie', event => { From 944dd103d26c4cfa0567e1febcb1bf9a36e41a61 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 28 Feb 2021 01:40:32 +0100 Subject: [PATCH 4/9] =?UTF-8?q?Ajout=20commande=20id=C3=A9e=20fixe/d=C3=A9?= =?UTF-8?q?sir=20lancinant?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- module/rdd-commands.js | 2 ++ module/rdd-rolltables.js | 12 ++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/module/rdd-commands.js b/module/rdd-commands.js index 317b62bf..dddfdb2c 100644 --- a/module/rdd-commands.js +++ b/module/rdd-commands.js @@ -24,6 +24,8 @@ export class RdDCommands { rddCommands.registerCommand({ path: ["/aide"], func: (content, msg, params) => rddCommands.help(msg), descr: "Affiche l'aide pour toutes les commandes" }); rddCommands.registerCommand({ path: ["/help"], func: (content, msg, params) => rddCommands.help(msg), descr: "Affiche l'aide pour toutes les commandes" }); rddCommands.registerCommand({ path: ["/table", "queues"], func: (content, msg, params) => RdDRollTables.getQueue(true), descr: "Tire une Queue de Dragon" }); + rddCommands.registerCommand({ path: ["/table", "ideefixe"], func: (content, msg, params) => RdDRollTables.getIdeeFixe(true), descr: "Tire une Idée fixe" }); + rddCommands.registerCommand({ path: ["/table", "desir"], func: (content, msg, params) => RdDRollTables.getDesirLancinant(true), descr: "Tire un Désir Lancinant" }); rddCommands.registerCommand({ path: ["/table", "ombre"], func: (content, msg, params) => RdDRollTables.getOmbre(true), descr: "Tire une Ombre de Dragon" }); rddCommands.registerCommand({ path: ["/table", "tetehr"], func: (content, msg, params) => RdDRollTables.getTeteHR(true), descr: "Tire une Tête de Dragon pour Hauts Revants" }); rddCommands.registerCommand({ path: ["/table", "tete"], func: (content, msg, params) => RdDRollTables.getTete(true), descr: "Tire une Tête de Dragon" }); diff --git a/module/rdd-rolltables.js b/module/rdd-rolltables.js index 957c130a..74d06152 100644 --- a/module/rdd-rolltables.js +++ b/module/rdd-rolltables.js @@ -48,14 +48,22 @@ export class RdDRollTables { static async getQueue(toChat = false) { let queue = await RdDRollTables.drawItemFromRollTable("Queues de dragon", toChat); if (queue.name.toLowerCase().includes('lancinant') ) { - queue = await RdDRollTables.drawItemFromRollTable("Désirs lancinants", toChat); + return await RdDRollTables.getDesirLancinant(toChat); } if (queue.name.toLowerCase().includes('fixe') ) { - queue = await RdDRollTables.drawItemFromRollTable("Idées fixes", toChat); + return await RdDRollTables.getIdeeFixe(toChat); } return queue; } + static async getDesirLancinant(toChat = false) { + return await RdDRollTables.drawItemFromRollTable("Désirs lancinants", toChat); + } + + static async getIdeeFixe(toChat = false) { + return await RdDRollTables.drawItemFromRollTable("Idées fixes", toChat); + } + /* -------------------------------------------- */ static async getTeteHR(toChat = false) { return await RdDRollTables.drawItemFromRollTable("Têtes de Dragon pour haut-rêvants", toChat); From 3f4d52487df0c3d245ece94f054847b5f2e556bc Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 28 Feb 2021 01:50:15 +0100 Subject: [PATCH 5/9] =?UTF-8?q?Refactor:=20extrait=20m=C3=A9thodes=20commu?= =?UTF-8?q?nes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - suppression de casetmr lors de visite/conquete - suppression de toutes les cases TMRs liées - notification lors de suppression d'une casetmr pour enlever la queue # Conflicts: # module/actor.js --- module/actor.js | 10 ++++++++++ module/rdd-tmr-dialog.js | 20 ++++++++++--------- module/tmr/conquete.js | 7 ------- module/tmr/desorientation.js | 10 ---------- module/tmr/draconique.js | 36 +++++++++++++++++++++++++---------- module/tmr/fermeture-cites.js | 7 ------- module/tmr/pelerinage.js | 9 --------- 7 files changed, 47 insertions(+), 52 deletions(-) diff --git a/module/actor.js b/module/actor.js index 659a971d..0f497714 100644 --- a/module/actor.js +++ b/module/actor.js @@ -3205,6 +3205,9 @@ export class RdDActor extends Actor { case 'souffle': await this.onDeleteOwnedDraconique(item, options, id); break; + case 'casetmr': + await this.onDeleteOwnedCaseTmr(item, options, id); + break; } } @@ -3226,6 +3229,13 @@ export class RdDActor extends Actor { } } + async onDeleteOwnedCaseTmr(item, options, id) { + let draconique = Draconique.all().find(it => it.isCase(item)); + if (draconique) { + draconique.onActorDeleteCaseTmr(this, item) + } + } + notifyGestionTeteSouffleQueue(item, manualMessage = true) { ChatMessage.create({ whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), diff --git a/module/rdd-tmr-dialog.js b/module/rdd-tmr-dialog.js index a3bcff7e..ecbc3caf 100644 --- a/module/rdd-tmr-dialog.js +++ b/module/rdd-tmr-dialog.js @@ -558,8 +558,10 @@ export class RdDTMRDialog extends Dialog { await this._conquerir(tmr, { difficulte: -9, action: 'Conquérir la cité', - onConqueteReussie: r => EffetsDraconiques.fermetureCites.onConquete(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), - onConqueteEchec: r => this.close(), + onConqueteReussie: r => EffetsDraconiques.fermetureCites.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), + onConqueteEchec: r => { + this.close() + }, canClose: false }); } @@ -576,8 +578,8 @@ export class RdDTMRDialog extends Dialog { await this._conquerir(tmr, { difficulte: -7, action: 'Conquérir', - onConqueteReussie: r => EffetsDraconiques.conquete.onConquete(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), - onConqueteEchec: r => { }, + onConqueteReussie: r => EffetsDraconiques.conquete.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), + onConqueteEchec: r => this.close(), canClose: false }); } @@ -639,8 +641,8 @@ export class RdDTMRDialog extends Dialog { dialog.render(true); } - async validerPelerinage(tmr) { - await EffetsDraconiques.pelerinage.onFinPelerinage(this.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)); + async validerVisite(tmr) { + await EffetsDraconiques.pelerinage.onVisiteSupprimer(this.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)); } @@ -836,17 +838,17 @@ export class RdDTMRDialog extends Dialog { await this.manageCaseHumide(tmr); await this.conquerirCiteFermee(tmr); await this.conquerirTMR(tmr); - await this.validerPelerinage(tmr); + await this.validerVisite(tmr); await this.declencheSortEnReserve(tmr.coord); await this.actor.checkSoufflePeage(tmr); } } - + /* -------------------------------------------- */ async forceDemiRevePositionView() { this._updateDemiReve(); } - + /* -------------------------------------------- */ async forceDemiRevePosition(coord) { await this.actor.updateCoordTMR(coord); diff --git a/module/tmr/conquete.js b/module/tmr/conquete.js index 92d665c4..550c6427 100644 --- a/module/tmr/conquete.js +++ b/module/tmr/conquete.js @@ -35,11 +35,4 @@ export class Conquete extends Draconique { await this.createCaseTmr(actor, 'Conquête: ' + conquete.label, conquete, queue._id); } - async onConquete(actor, tmr, onRemoveToken) { - let existants = actor.data.items.filter(it => this.isCase(it, tmr.coord)); - for (let casetmr of existants) { - await actor.deleteOwnedItem(casetmr.data.sourceid); - onRemoveToken(tmr, casetmr); - } - } } diff --git a/module/tmr/desorientation.js b/module/tmr/desorientation.js index f2dad665..1dcec96a 100644 --- a/module/tmr/desorientation.js +++ b/module/tmr/desorientation.js @@ -24,10 +24,6 @@ export class Desorientation extends Draconique { return Object.keys(TMRType).filter(it => !dejaDesorientes.includes(it)); } - async onActorDeleteOwned(actor, souffle) { - await this._supprimerCasesTmr(actor, souffle); - } - code() { return 'desorientation' } tooltip(linkData) { return `Désorientation, cette case n'existe plus !` } img() { return 'icons/svg/explosion.svg' } @@ -51,11 +47,5 @@ export class Desorientation extends Draconique { } } - async _supprimerCasesTmr(actor, souffle) { - let caseTmrs = actor.data.items.filter(it => it.data.sourceId == souffle._id); - for (let casetmr of caseTmrs) { - await actor.deleteOwnedItem(casetmr._id); - } - } } diff --git a/module/tmr/draconique.js b/module/tmr/draconique.js index 9af391ec..bbbac5fe 100644 --- a/module/tmr/draconique.js +++ b/module/tmr/draconique.js @@ -7,8 +7,7 @@ const registeredEffects = [ /** * Définition des informations d'une "draconique" (queue, ombre, tête, souffle) qui influence les TMR */ -export class Draconique -{ +export class Draconique { static isCaseTMR(element) { return element.type == 'casetmr'; } static isQueueDragon(element) { return element.type == 'queue' || element.type == 'ombre'; } static isSouffleDragon(element) { return element.type == 'souffle'; } @@ -28,6 +27,7 @@ export class Draconique static all() { return Object.values(registeredEffects); } + static get(code) { return registeredEffects[code]; } @@ -56,10 +56,11 @@ export class Draconique } async onActorDeleteOwned(actor, item) { - let caseTmrs = actor.data.items.filter(it => this.isCase(it) && it.data.sourceid == item._id); - for (let casetmr of caseTmrs) { - await actor.deleteOwnedItem(casetmr._id); - } + this.deleteCasesTmr(actor, item); + return false; + } + + async onActorDeleteCaseTmr(actor, casetmr) { return false; } /** @@ -72,7 +73,7 @@ export class Draconique * @returns un tooltip à afficher au dessus du token */ tooltip(linkData) { return undefined } - + /** * @param {*} img l'url du fichier image à utiliser pour le token. Si indéfini (et si createSprite n'est pas surchargé), * un disque est utilisé. @@ -102,7 +103,7 @@ export class Draconique if (this.img()) { return pixiTMR.sprite(this.code()); } - else{ + else { return pixiTMR.circle() } } @@ -120,11 +121,26 @@ export class Draconique return list.find(c => this.isCase(c, coord)); } - async createCaseTmr(actor, label, tmr, sourceId=undefined) { + async createCaseTmr(actor, label, tmr, sourceId = undefined) { await actor.createOwnedItem({ name: label, type: 'casetmr', img: this.img(), _id: randomID(16), - data: { coord: tmr.coord, specific: this.code(), sourceid:sourceId } + data: { coord: tmr.coord, specific: this.code(), sourceid: sourceId } }); } + async deleteCasesTmr(actor, draconique) { + let caseTmrs = actor.data.items.filter(it => this.isCase(it) && it.data.sourceid == draconique._id); + for (let casetmr of caseTmrs) { + await actor.deleteOwnedItem(casetmr._id); + } + } + + async onVisiteSupprimer(actor, tmr, onRemoveToken) { + let existants = actor.data.items.filter(it => this.isCase(it, tmr.coord)); + for (let casetmr of existants) { + await actor.deleteOwnedItem(casetmr._id); + onRemoveToken(tmr, casetmr); + } + } + } \ No newline at end of file diff --git a/module/tmr/fermeture-cites.js b/module/tmr/fermeture-cites.js index 6a8602d3..8d695ae6 100644 --- a/module/tmr/fermeture-cites.js +++ b/module/tmr/fermeture-cites.js @@ -35,11 +35,4 @@ export class FermetureCites extends Draconique { await this.createCaseTmr(actor, 'Fermeture: ' + tmr.label, tmr, souffle._id); } } - - async onConquete(actor, tmr, onRemoveToken) { - const citeFermee = actor.data.items.find(it => this.isCase(it, tmr.coord)); - await actor.deleteOwnedItem(citeFermee._id); - onRemoveToken(tmr, citeFermee); - } - } diff --git a/module/tmr/pelerinage.js b/module/tmr/pelerinage.js index 76cc2fe9..d9ba19c5 100644 --- a/module/tmr/pelerinage.js +++ b/module/tmr/pelerinage.js @@ -30,13 +30,4 @@ export class Pelerinage extends Draconique { decallage: tmrConstants.right }); } - - async onFinPelerinage(actor, tmr, onRemoveToken) { - const pelerinages = actor.data.items.filter(it => this.isCase(it, tmr.coord)); - for (let p of pelerinages){ - await actor.deleteOwnedItem(p.data.sourceid); - onRemoveToken(tmr, p); - } - } - } From bbd38bd6183c6dc345716c59d7939854be8aba27 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 28 Feb 2021 01:50:46 +0100 Subject: [PATCH 6/9] =?UTF-8?q?Extrait=20m=C3=A9thode=20Actor.getDemiReve?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- module/actor.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/module/actor.js b/module/actor.js index 0f497714..9df2bd1c 100644 --- a/module/actor.js +++ b/module/actor.js @@ -311,6 +311,9 @@ export class RdDActor extends Actor { } return duplicate(list[0]); } + getDemiReve() { + return this.data.data.reve.tmrpos.coord; + } /* -------------------------------------------- */ async deleteSortReserve(sortReserve) { let reserve = duplicate(this.data.data.reve.reserve); @@ -1193,7 +1196,7 @@ export class RdDActor extends Actor { //console.log("List", rencontres, len); let newTable = []; for (i = 0; i < len; i++) { - if (rencontres.list[i].coord != this.data.data.reve.tmrpos.coord) + if (rencontres.list[i].coord != this.getDemiReve()) newTable.push(rencontres.list[i]); } if (newTable.length != len) { @@ -1210,7 +1213,7 @@ export class RdDActor extends Actor { let i = 0; let already = false; for (i = 0; i < len; i++) { - if (rencontres.list[i].coord == this.data.data.reve.tmrpos.coord) + if (rencontres.list[i].coord == this.getDemiReve()) already = true; } if (!already) { @@ -1232,9 +1235,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async updateCoordTMR(coord) { - let tmrPos = duplicate(this.data.data.reve.tmrpos); - tmrPos.coord = coord; - await this.update({ "data.reve.tmrpos": tmrPos }); + await this.update({ "data.reve.tmrpos.coord": coord }); } /* -------------------------------------------- */ From 34e12cd7015196c553dd615aad415432b6416ab5 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 28 Feb 2021 01:52:58 +0100 Subject: [PATCH 7/9] Suppression de queues TMR finies --- module/tmr/conquete.js | 4 ++++ module/tmr/draconique.js | 1 - module/tmr/pelerinage.js | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/module/tmr/conquete.js b/module/tmr/conquete.js index 550c6427..ba7dffeb 100644 --- a/module/tmr/conquete.js +++ b/module/tmr/conquete.js @@ -35,4 +35,8 @@ export class Conquete extends Draconique { await this.createCaseTmr(actor, 'Conquête: ' + conquete.label, conquete, queue._id); } + async onActorDeleteCaseTmr(actor, casetmr) { + await actor.deleteOwnedItem(casetmr.data.sourceid); + } + } diff --git a/module/tmr/draconique.js b/module/tmr/draconique.js index bbbac5fe..f6b88794 100644 --- a/module/tmr/draconique.js +++ b/module/tmr/draconique.js @@ -142,5 +142,4 @@ export class Draconique { onRemoveToken(tmr, casetmr); } } - } \ No newline at end of file diff --git a/module/tmr/pelerinage.js b/module/tmr/pelerinage.js index d9ba19c5..ec9e4010 100644 --- a/module/tmr/pelerinage.js +++ b/module/tmr/pelerinage.js @@ -30,4 +30,9 @@ export class Pelerinage extends Draconique { decallage: tmrConstants.right }); } + + async onActorDeleteCaseTmr(actor, casetmr) { + await actor.deleteOwnedItem(casetmr.data.sourceid); + } + } From 50c336cda745e8e776a1d3bfc12c2590e1ffd4e3 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 28 Feb 2021 01:54:19 +0100 Subject: [PATCH 8/9] Ajout de souffle dans certains cas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - conquete de cité échouée --- module/rdd-tmr-dialog.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/module/rdd-tmr-dialog.js b/module/rdd-tmr-dialog.js index ecbc3caf..4f876aa2 100644 --- a/module/rdd-tmr-dialog.js +++ b/module/rdd-tmr-dialog.js @@ -498,9 +498,7 @@ export class RdDTMRDialog extends Dialog { } async _resultatMaitriseCaseHumide(rollData) { - if (rollData.rolled.isETotal) { - rollData.souffle = await this.actor.ajouterSouffle({ chat: false }); - } + await this.souffleSiEchecTotal(rollData); this.toclose = rollData.rolled.isEchec; if (rollData.rolled.isSuccess && rollData.double) { rollData.previous = { rolled: rollData.rolled, ajustements: rollData.ajustements }; @@ -518,6 +516,12 @@ export class RdDTMRDialog extends Dialog { } } + async souffleSiEchecTotal(rollData) { + if (rollData.rolled.isETotal) { + rollData.souffle = await this.actor.ajouterSouffle({ chat: false }); + } + } + /* -------------------------------------------- */ isCaseHumide(tmr) { if (!(TMRUtility.isCaseHumide(tmr) || this.isCaseHumideAdditionelle(tmr))) { @@ -560,6 +564,7 @@ export class RdDTMRDialog extends Dialog { action: 'Conquérir la cité', onConqueteReussie: r => EffetsDraconiques.fermetureCites.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), onConqueteEchec: r => { + this.souffleSiEchecTotal(rollData); this.close() }, canClose: false From c509e23513742a1f8ce726db4a3de125e962c948 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 28 Feb 2021 01:56:17 +0100 Subject: [PATCH 9/9] =?UTF-8?q?Ajout=20P=C3=A9riple=20&=20urgence=20dracon?= =?UTF-8?q?ique?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Conflicts: # module/tmr-utility.js --- module/actor.js | 20 ---------- module/rdd-tmr-dialog.js | 37 ++++++++++++++----- module/tmr-utility.js | 36 ++++++++++++++---- module/tmr/effets-draconiques.js | 25 +++++++++++-- module/tmr/periple.js | 44 ++++++++++++++++++++++ module/tmr/urgence-draconique.js | 55 ++++++++++++++++++++++++++++ templates/casetmr-specific-list.html | 21 ++++++----- 7 files changed, 186 insertions(+), 52 deletions(-) create mode 100644 module/tmr/periple.js create mode 100644 module/tmr/urgence-draconique.js diff --git a/module/actor.js b/module/actor.js index 9df2bd1c..ee1e39af 100644 --- a/module/actor.js +++ b/module/actor.js @@ -1163,26 +1163,6 @@ export class RdDActor extends Actor { return tmrInnaccessibles.map(it => it.data.coord); } - /* -------------------------------------------- */ - displayTMRQueueSouffleInformation() { - let messages = []; - for (let item of this.data.items) { - if (EffetsDraconiques.isUrgenceDraconique(item)) { - messages.push("Vous souffrez d'une Urgence Draconique : " + item.data.description); - } - if (EffetsDraconiques.isPeriple(item)) { - messages.push("Vous souffrez du Souffle Périple. Vous devez gérer manuellement le détail du Périple.
              " + item.data.description); - } - } - - if (messages.length > 0) { - ChatMessage.create({ - whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), - content: "RAPPEL !
              " + messages.join('
              ') - }); - } - } - /* -------------------------------------------- */ getTMRRencontres() { return this.data.data.reve.rencontre; diff --git a/module/rdd-tmr-dialog.js b/module/rdd-tmr-dialog.js index 4f876aa2..cbc1aafe 100644 --- a/module/rdd-tmr-dialog.js +++ b/module/rdd-tmr-dialog.js @@ -108,6 +108,11 @@ export class RdDTMRDialog extends Dialog { this._createTokens(); } + removeToken(tmr, casetmr) { + this._removeTokens(t => t.coordTMR() == tmr.coord && t.caseSpeciale?._id == casetmr._id); + this.updateTokens() + } + /* -------------------------------------------- */ _getTokensCasesTmr() { return this.casesSpeciales.map(c => this._tokenCaseSpeciale(c)).filter(token => token); @@ -142,7 +147,7 @@ export class RdDTMRDialog extends Dialog { async activateListeners(html) { super.activateListeners(html); - document.getElementById("tmrrow1").insertCell(1).append(this.pixiApp.view); + document.getElementById("tmrrow1").insertCell(0).append(this.pixiApp.view); if (this.viewOnly) { html.find('#lancer-sort').remove(); @@ -168,7 +173,6 @@ export class RdDTMRDialog extends Dialog { let tmr = TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord); await this.manageRencontre(tmr, () => { this.postRencontre(tmr); - this.actor.displayTMRQueueSouffleInformation(); }); } @@ -571,10 +575,20 @@ export class RdDTMRDialog extends Dialog { }); } } - - removeToken(tmr, casetmr) { - this._removeTokens(t => t.coordTMR() == tmr.coord && t.caseSpeciale?._id == casetmr._id); - this.updateTokens() + /* -------------------------------------------- */ + async purifierPeriple(tmr) { + if (EffetsDraconiques.periple.find(this.casesSpeciales, tmr.coord)) { + await this._conquerir(tmr, { + difficulte: EffetsDraconiques.periple.getDifficulte(tmr), + action: 'Purifier ' + TMRUtility.getTMRDescr(tmr.coord), + onConqueteReussie: r => EffetsDraconiques.periple.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), + onConqueteEchec: r => { + this.souffleSiEchecTotal(rollData); + this.close() + }, + canClose: false + }); + } } /* -------------------------------------------- */ @@ -648,6 +662,7 @@ export class RdDTMRDialog extends Dialog { async validerVisite(tmr) { await EffetsDraconiques.pelerinage.onVisiteSupprimer(this.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)); + await EffetsDraconiques.urgenceDraconique.onVisiteSupprimer(this.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)); } @@ -656,11 +671,12 @@ export class RdDTMRDialog extends Dialog { let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coord); if (sortReserveList.length > 0) { - if (EffetsDraconiques.isSortImpossible(this.actor)) { + if (EffetsDraconiques.isSortReserveImpossible(this.actor)) { ui.notifications.error("Une queue ou un souffle vous empèche de déclencher de sort!"); return; } - if (EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coord)) { + if (!EffetsDraconiques.isUrgenceDraconique(this.actor) && + (EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coord))) { let msg = "Vous êtes sur une case avec un Sort en Réserve. Grâce à votre Tête Reserve en Sécurité ou Réserve Exensible, vous pouvez contrôler le déclenchement. Cliquez si vous souhaitez le déclencher :
                "; for (let sortReserve of sortReserveList) { msg += "
              • " + sortReserve.sort.name + "
              • "; @@ -670,9 +686,9 @@ export class RdDTMRDialog extends Dialog { content: msg, whisper: ChatMessage.getWhisperRecipients(game.user.name) }); - } else { - await this.processSortReserve(sortReserveList[0]); + return; } + await this.processSortReserve(sortReserveList[0]); } } @@ -842,6 +858,7 @@ export class RdDTMRDialog extends Dialog { if (!(this.viewOnly || this.currentRencontre)) { await this.manageCaseHumide(tmr); await this.conquerirCiteFermee(tmr); + await this.purifierPeriple(tmr); await this.conquerirTMR(tmr); await this.validerVisite(tmr); await this.declencheSortEnReserve(tmr.coord); diff --git a/module/tmr-utility.js b/module/tmr-utility.js index aa0358ef..74863674 100644 --- a/module/tmr-utility.js +++ b/module/tmr-utility.js @@ -210,8 +210,8 @@ const TMRMapping = { export const TMRType = { cite: { name: "cité", genre: "f" }, - sanctuaire: { name: "sanctuaire" }, - plaines: { name: "plaines", genre: "p" }, + sanctuaire: { name: "sanctuaire", genre: 'm' }, + plaines: { name: "plaines", genre: "fp" }, pont: { name: "pont", genre: "m" }, collines: { name: "collines", genre: "p" }, foret: { name: "forêt", genre: "f" }, @@ -332,7 +332,12 @@ export class TMRUtility { } static getTMRLabel(coord) { - return TMRMapping[coord]?.label ?? (coord+": case inconnue"); + return TMRMapping[coord]?.label ?? (coord + ": case inconnue"); + } + + static getTMRDescr(coord) { + const tmr = TMRMapping[coord]; + return Grammar.articleDetermine(tmr.genre) + ' ' + tmr.label; } static isCaseHumide(tmr) { @@ -384,7 +389,7 @@ export class TMRUtility { currentPos.x = currentPos.x + direction.x; currentPos.y = currentPos.y + direction.y; if (this._checkTMRCoord(currentPos.x, currentPos.y)) { // Sortie de carte ! Ré-insertion aléatoire - coord = TMRUtility.getTMR(TMRUtility.convertToTMRCoord(currentPos)); + coord = TMRUtility.getTMR(TMRUtility.convertToTMRCoord(currentPos)); } else { coord = await actor.reinsertionAleatoire('Sortie de carte'); } @@ -435,7 +440,7 @@ export class TMRUtility { return reserveList.filter(it => TMRUtility.getTMR(it.coord).type == 'fleuve'); } // Reserve sur un case "normale" - return reserveList.filter(it => it.coord == coord); + return reserveList.filter(it => it.coord == coord); } /* -------------------------------------------- */ @@ -450,9 +455,8 @@ export class TMRUtility { for (let dy = -portee; dy <= portee; dy++) { // Loop thru lines const currentPos = { x: centerPos.x + dx, y: centerPos.y + dy }; if (this._checkTMRCoord(currentPos.x, currentPos.y)) { // Coordinate is valie - let posPicNow = this.computeRealPictureCoordinates(currentPos, tmrConstants); - let dist = Math.sqrt(Math.pow(posPicNow.x - posPic.x, 2) + Math.pow(posPicNow.y - posPic.y, 2)) / tmrConstants.cellw; - if (dist < portee + 0.5) { + let dist = this.distancePosTMR(centerPos, currentPos); + if (dist <= portee) { caseList.push(this.convertToTMRCoord(currentPos)); // Inside the area } } @@ -460,5 +464,21 @@ export class TMRUtility { } return caseList; } + + static distanceTMR(coord1, coord2) { + let pos1 = this.convertToCellPos(coord1); + let pos2 = this.convertToCellPos(coord2); + return this.distancePosTMR(pos1, pos2); + } + + static distancePosTMR(pos1, pos2) { + const dx = pos2.x - pos1.x; + const dy = pos2.y - pos1.y; + const abs_dx = Math.abs(dx); + const abs_dy = Math.abs(dy); + const distance = Math.sign(dx) == Math.sign(dy) ? Math.max(abs_dx, abs_dy) : (abs_dx + abs_dy); + return distance; + } + } diff --git a/module/tmr/effets-draconiques.js b/module/tmr/effets-draconiques.js index ab8bdc3d..6eefe7f3 100644 --- a/module/tmr/effets-draconiques.js +++ b/module/tmr/effets-draconiques.js @@ -14,6 +14,8 @@ import { PresentCites } from "./present-cites.js"; import { Desorientation } from "./desorientation.js"; import { Conquete } from "./conquete.js"; import { Pelerinage } from "./pelerinage.js"; +import { Periple } from "./periple.js"; +import { UrgenceDraconique } from "./urgence-draconique.js"; export class EffetsDraconiques { @@ -32,6 +34,8 @@ export class EffetsDraconiques { static desorientation = new Desorientation(); static conquete = new Conquete(); static pelerinage = new Pelerinage(); + static periple = new Periple(); + static urgenceDraconique = new UrgenceDraconique(); static init() { Draconique.register(EffetsDraconiques.carteTmr); @@ -49,6 +53,8 @@ export class EffetsDraconiques { Draconique.register(EffetsDraconiques.desorientation); Draconique.register(EffetsDraconiques.conquete); Draconique.register(EffetsDraconiques.pelerinage); + Draconique.register(EffetsDraconiques.periple); + Draconique.register(EffetsDraconiques.urgenceDraconique); } /* -------------------------------------------- */ @@ -112,8 +118,7 @@ export class EffetsDraconiques { } static isPeriple(element) { - // TODO - return EffetsDraconiques.isMatching(element, it => Draconique.isSouffleDragon(it) && ir.name.toLowerCase() == 'périple'); + return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.periple.match(it)); } static isDesorientation(element) { @@ -122,7 +127,19 @@ export class EffetsDraconiques { /* -------------------------------------------- */ static isSortImpossible(element) { - return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.conquete.match(it) || EffetsDraconiques.pelerinage.match(it)); + return EffetsDraconiques.isMatching(element, it => + EffetsDraconiques.conquete.match(it) || + EffetsDraconiques.periple.match(it) || + EffetsDraconiques.urgenceDraconique.match(it) || + EffetsDraconiques.pelerinage.match(it) + ); + } + static isSortReserveImpossible(element) { + return EffetsDraconiques.isMatching(element, it => + EffetsDraconiques.conquete.match(it) || + EffetsDraconiques.periple.match(it) || + EffetsDraconiques.pelerinage.match(it) + ); } static isConquete(element) { @@ -138,7 +155,7 @@ export class EffetsDraconiques { } static isUrgenceDraconique(element) { - return EffetsDraconiques.isMatching(element, it => Draconique.isQueueDragon(it) && it.name.toLowerCase() == 'urgence draconique'); + return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.urgenceDraconique.match(it)); } /* -------------------------------------------- */ diff --git a/module/tmr/periple.js b/module/tmr/periple.js new file mode 100644 index 00000000..feba1a2b --- /dev/null +++ b/module/tmr/periple.js @@ -0,0 +1,44 @@ +import { Grammar } from "../grammar.js"; +import { tmrColors, tmrConstants, tmrTokenZIndex, TMRUtility } from "../tmr-utility.js"; +import { Draconique } from "./draconique.js"; + +export class Periple extends Draconique { + + constructor() { + super(); + } + + type() { return 'souffle' } + match(item) { return Draconique.isSouffleDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('periple'); } + manualMessage() { return false } + + async onActorCreateOwned(actor, souffle) { + let terrain = new Roll("1d2").evaluate().total == 1 ? 'sanctuaire' : 'necropole'; + let tmrs = TMRUtility.getListTMR(terrain); + for (let tmr of tmrs) { + await this.createCaseTmr(actor, 'Périple: ' + tmr.label, tmr, souffle._id); + } + } + + + code() { return 'periple' } + tooltip(linkData) { return `Votre Périple passe par ${this.tmrDescr(linkData)}` } + img() { return 'icons/svg/acid.svg' } + + createSprite(pixiTMR) { + return pixiTMR.sprite(this.code(), { + zIndex: tmrTokenZIndex.conquete, + alpha: 1, + color: tmrColors.souffle, + taille: tmrConstants.twoThird, + decallage: tmrConstants.right + }); + } + getDifficulte(tmr) { + switch (tmr.type) { + case 'sanctuaire': return -3; + case 'necropole': return -5; + } + return 0; + } +} \ No newline at end of file diff --git a/module/tmr/urgence-draconique.js b/module/tmr/urgence-draconique.js new file mode 100644 index 00000000..8af5c992 --- /dev/null +++ b/module/tmr/urgence-draconique.js @@ -0,0 +1,55 @@ +import { ChatUtility } from "../chat-utility.js"; +import { Grammar } from "../grammar.js"; +import { Misc } from "../misc.js"; +import { RdDRollTables } from "../rdd-rolltables.js"; +import { tmrColors, tmrConstants, tmrTokenZIndex, TMRUtility } from "../tmr-utility.js"; +import { Draconique } from "./draconique.js"; + +export class UrgenceDraconique extends Draconique { + + constructor() { + super(); + } + + type() { return 'queue' } + match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('urgence draconique'); } + manualMessage() { return false } + async onActorCreateOwned(actor, queue) { + let coordSortsReserve = (actor.data.data.reve.reserve?.list.map(it => it.coord)) ?? []; + if (coordSortsReserve.length == 0) { + // La queue se transforme en idée fixe + let ideeFixe = await RdDRollTables.getIdeeFixe(); + ChatMessage.create({ + whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), + content: `En l'absence de sorts en réserve, l'urgence draconique de ${actor.name} se transforme en ${queue.name}` + }); + await actor.createOwnedItem(ideeFixe); + await actor.deleteOwnedItem(queue._id); + return; + } + else { + let demiReve = actor.getDemiReve(); + coordSortsReserve.sort((a, b) => TMRUtility.distanceTMR(a, demiReve) - TMRUtility.distanceTMR(b, demiReve)); + let tmr = TMRUtility.getTMR(coordSortsReserve[0]); + await this.createCaseTmr(actor, 'Urgence draconique: ' + tmr.label, tmr, queue._id); + } + } + + async onActorDeleteCaseTmr(actor, casetmr) { + await actor.deleteOwnedItem(casetmr.data.sourceid); + } + + code() { return 'urgence' } + tooltip(linkData) { return `Urgence draconique!` } + img() { return 'icons/svg/hazard.svg' } + + createSprite(pixiTMR) { + return pixiTMR.sprite(this.code(), + { + zIndex: tmrTokenZIndex.conquete, + color: tmrColors.queues, + taille: tmrConstants.full, + decallage: { x: 2, y: 0 } + }); + } +} diff --git a/templates/casetmr-specific-list.html b/templates/casetmr-specific-list.html index 48be5d5b..136f1f6d 100644 --- a/templates/casetmr-specific-list.html +++ b/templates/casetmr-specific-list.html @@ -1,12 +1,13 @@ + + + + + + + + + + - - - - - - - - - - +