Merge pull request '## v11.0.26 - le crépuscule de Khrachtchoum' (#673) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11

Reviewed-on: #673
This commit is contained in:
uberwald 2023-10-24 07:07:01 +02:00
commit 85f8a716d4
16 changed files with 223 additions and 109 deletions

View File

@ -1,4 +1,22 @@
# v11.0 # v11.0
## v11.0.26 - le crépuscule de Khrachtchoum
- gestion correcte des TMRs
- les TMRs ne sont jamais minimisées (par le système) quand le haut-rêvant est en demi-rêve
- lorsqu'une fenêtre liée aux demi-rêve est affichée, cliquer sur les TMRs n'a pas d'effet
- les lancers de sorts et lectures de signes sont affichées en premier plan
- Les effets qui ouvrent une fenêtre sont bien affichés en premier plan
- en cas de rencontre suivie de maîtrises/conquêtes, les fenêtres s'enchaînent
- Le drag&drop vers la barre de macro est corrigé
- pour les créatures, possibilités d'avoir les attaques ou autres compétences
- pour les personnages, les macros sont créées:
- pour les compétences
- pour le corps à corps, trois macros sont créées: compétence, pugilat, empoignade
- pour les armes
- deux macros sont créées pour les armes à 1/2 mains
- deux macros sont créées pour les armes de mélée et lancer
- 4 macros si votre arbalête se lance, tire, et se manie à 1 ou 2 mains...
- les jets de compétences d'attaque des créatures fonctionnent de nouveau
## v11.0.25 - la vision du rêve de Khrachtchoum ## v11.0.25 - la vision du rêve de Khrachtchoum
- Les TMRs restent affichées tant que le Haut-rêvant est en demi-rêve - Les TMRs restent affichées tant que le Haut-rêvant est en demi-rêve

View File

@ -81,9 +81,12 @@ export class RdDActorSheet extends RdDBaseActorSheet {
}); });
// toujours avoir une liste d'armes (pour mettre esquive et corps à corps) // toujours avoir une liste d'armes (pour mettre esquive et corps à corps)
formData.combat = duplicate(formData.armes ?? []); const actor = this.actor;
formData.combat = duplicate(formData.armes);
RdDItemArme.computeNiveauArmes(formData.combat, formData.competences); RdDItemArme.computeNiveauArmes(formData.combat, formData.competences);
RdDItemArme.ajoutCorpsACorps(formData.combat, formData.competences, formData.system.carac); formData.combat.push(RdDItemArme.mainsNues(actor));
formData.combat.push(RdDItemArme.empoignade(actor));
formData.esquives = this.actor.getCompetences("Esquive"); formData.esquives = this.actor.getCompetences("Esquive");
formData.combat = RdDCombatManager.listActionsArmes(formData.combat, formData.competences, formData.system.carac); formData.combat = RdDCombatManager.listActionsArmes(formData.combat, formData.competences, formData.system.carac);
formData.empoignades = this.actor.getEmpoignades(); formData.empoignades = this.actor.getEmpoignades();

View File

@ -232,12 +232,21 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */ /* -------------------------------------------- */
getCompetence(idOrName, options = {}) { getCompetence(idOrName, options = {}) {
if (idOrName instanceof Item) {
return idOrName.isCompetence() ? idOrName : undefined
}
return RdDItemCompetence.findCompetence(this.items, idOrName, options) return RdDItemCompetence.findCompetence(this.items, idOrName, options)
} }
getCompetences(name) { getCompetences(name) {
return RdDItemCompetence.findCompetences(this.items, name) return RdDItemCompetence.findCompetences(this.items, name)
} }
getCompetenceCorpsACorps(options = {}) {
return this.getCompetence("Corps à corps", options)
}
getCompetencesEsquive() {
return this.getCompetences("esquive")
}
/* -------------------------------------------- */ /* -------------------------------------------- */
getTache(id) { getTache(id) {
return this.findItemLike(id, 'tache'); return this.findItemLike(id, 'tache');
@ -288,13 +297,13 @@ export class RdDActor extends RdDBaseActor {
} }
getPossession(possessionId) { getPossession(possessionId) {
return this.items.find(it => it.type == TYPES.possession && it.system.possessionid == possessionId); return this.itemTypes[TYPES.possession].find(it => it.system.possessionid == possessionId);
} }
getPossessions() { getPossessions() {
return this.items.filter(it => it.type == TYPES.possession); return this.itemTypes[TYPES.possession];
} }
getEmpoignades() { getEmpoignades() {
return this.items.filter(it => it.type == TYPES.empoignade); return this.itemTypes[TYPES.empoignade];
} }
getDemiReve() { getDemiReve() {
return this.system.reve.tmrpos.coord; return this.system.reve.tmrpos.coord;
@ -546,7 +555,7 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async _recuperationBlessures(message, isMaladeEmpoisonne) { async _recuperationBlessures(message, isMaladeEmpoisonne) {
const timestamp = game.system.rdd.calendrier.getTimestamp() const timestamp = game.system.rdd.calendrier.getTimestamp()
const blessures = this.filterItems(it => it.system.gravite > 0, 'blessure').sort(Misc.ascending(it => it.system.gravite)) const blessures = this.filterItems(it => it.system.gravite > 0, TYPES.blessure).sort(Misc.ascending(it => it.system.gravite))
await Promise.all(blessures.map(b => b.recuperationBlessure({ await Promise.all(blessures.map(b => b.recuperationBlessure({
actor: this, actor: this,
@ -560,7 +569,7 @@ export class RdDActor extends RdDBaseActor {
} }
async supprimerBlessures(filterToDelete) { async supprimerBlessures(filterToDelete) {
const toDelete = this.filterItems(filterToDelete, 'blessure') const toDelete = this.filterItems(filterToDelete, TYPES.blessure)
.map(it => it.id); .map(it => it.id);
await this.deleteEmbeddedDocuments('Item', toDelete); await this.deleteEmbeddedDocuments('Item', toDelete);
} }
@ -568,7 +577,7 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async _recupererVie(message, isMaladeEmpoisonne) { async _recupererVie(message, isMaladeEmpoisonne) {
const tData = this.system const tData = this.system
let blessures = this.filterItems(it => it.system.gravite > 0, 'blessure'); let blessures = this.filterItems(it => it.system.gravite > 0, TYPES.blessure);
if (blessures.length > 0) { if (blessures.length > 0) {
return return
} }
@ -2139,7 +2148,6 @@ export class RdDActor extends RdDBaseActor {
ui.notifications.info(`Aucun sort disponible en ${TMRUtility.getTMR(coord).label} !`); ui.notifications.info(`Aucun sort disponible en ${TMRUtility.getTMR(coord).label} !`);
return; return;
} }
const draconicList = this.computeDraconicAndSortIndex(sorts); const draconicList = this.computeDraconicAndSortIndex(sorts);
const reve = duplicate(this.system.carac.reve); const reve = duplicate(this.system.carac.reve);
@ -2160,7 +2168,10 @@ export class RdDActor extends RdDBaseActor {
diffLibre: RdDItemSort.getDifficulte(sorts[0], -7), // Per default at startup diffLibre: RdDItemSort.getDifficulte(sorts[0], -7), // Per default at startup
coutreve: Array(30).fill().map((item, index) => 1 + index), coutreve: Array(30).fill().map((item, index) => 1 + index),
}, },
callbackAction: r => this._rollUnSortResult(r) callbackAction: async r => {
await this._rollUnSortResult(r);
if (!r.isSortReserve) this.tmrApp?.close();
}
}); });
this.tmrApp?.setTMRPendingAction(dialog); this.tmrApp?.setTMRPendingAction(dialog);
} }
@ -2253,17 +2264,11 @@ export class RdDActor extends RdDBaseActor {
reveActuel = Math.max(reveActuel - rollData.depenseReve, 0); reveActuel = Math.max(reveActuel - rollData.depenseReve, 0);
await this.update({ "system.reve.reve.value": reveActuel }); await this.update({ "system.reve.reve.value": reveActuel });
if (rollData.isSortReserve) {
this.tmrApp.maximize(); // Re-display TMR
} else {
this.tmrApp.close(); // Close TMR !
}
// Final chat message // Final chat message
await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-sort.html'); await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-sort.html');
if (reveActuel == 0) { // 0 points de reve if (reveActuel == 0) { // 0 points de reve
ChatMessage.create({ content: this.name + " est réduit à 0 Points de Rêve, et tombe endormi !" }); ChatMessage.create({ content: this.name + " est réduit à 0 Points de Rêve, et tombe endormi !" });
closeTMR = true;
} }
} }
@ -2338,16 +2343,14 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollCompetence(idOrName, options = { tryTarget: true }) { async rollCompetence(idOrName, options = { tryTarget: true }) {
RdDEmpoignade.checkEmpoignadeEnCours(this) RdDEmpoignade.checkEmpoignadeEnCours(this)
let rollData = { const competence = this.getCompetence(idOrName);
carac: this.system.carac, let rollData = { carac: this.system.carac, competence: competence }
competence: this.getCompetence(idOrName) if (competence.type == TYPES.competencecreature) {
} const arme = RdDItemCompetenceCreature.armeCreature(competence)
if (rollData.competence.type == TYPES.competencecreature) {
const arme = RdDItemCompetenceCreature.armeCreature(rollData.competence)
if (arme && options.tryTarget && Targets.hasTargets()) { if (arme && options.tryTarget && Targets.hasTargets()) {
Targets.selectOneToken(target => { Targets.selectOneToken(target => {
if (arme.action == "possession") { if (arme.action == "possession") {
RdDPossession.onAttaquePossession(target, this, rollData.competence) RdDPossession.onAttaquePossession(target, this, competence)
} }
else { else {
RdDCombat.rddCombatTarget(target, this).attaque(competence, arme) RdDCombat.rddCombatTarget(target, this).attaque(competence, arme)
@ -2361,7 +2364,7 @@ export class RdDActor extends RdDBaseActor {
await this._openRollDialog({ await this._openRollDialog({
name: 'jet-competence', name: 'jet-competence',
label: 'Jet ' + Grammar.apostrophe('de', rollData.competence.name), label: 'Jet ' + Grammar.apostrophe('de', competence.name),
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html', template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html',
rollData: rollData, rollData: rollData,
callbackAction: r => this.$onRollCompetence(r, options) callbackAction: r => this.$onRollCompetence(r, options)
@ -3073,24 +3076,35 @@ export class RdDActor extends RdDBaseActor {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
getArmeCompetence(arme, competenceName) { getCompetenceArme(arme, competenceName) {
let comp = arme.system[competenceName] switch (arme.type) {
if (!comp || comp.name == "") { case TYPES.competencecreature:
comp = arme.system[competenceName] return arme.name
case TYPES.arme:
switch (competenceName) {
case 'competence': return arme.system.competence;
case 'unemain': return RdDItemArme.competence1Mains(arme);
case 'deuxmains': return RdDItemArme.competence2Mains(arme);
case 'tir': return arme.system.tir;
case 'lancer': return arme.system.lancer;
}
} }
if ( !comp || comp.name == "") { return undefined
comp = arme.system[competenceName]
}
return comp
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
rollArme(arme, competenceName = "competence") { /**
let compToUse = this.getArmeCompetence(arme, competenceName) *
* @param {*} arme item d'arme/compétence de créature
* @param {*} categorieArme catégorie d'attaque à utiliser: competence (== melee), lancer, tir; naturelle, possession
* @returns
*/
rollArme(arme, categorieArme = "competence") {
let compToUse = this.getCompetenceArme(arme, categorieArme)
if (!Targets.hasTargets()) { if (!Targets.hasTargets()) {
RdDConfirm.confirmer({ RdDConfirm.confirmer({
settingConfirmer: "confirmer-combat-sans-cible", settingConfirmer: "confirmer-combat-sans-cible",
content: `<p>Voulez vous faire un jet de compétence ${competenceName} sans choisir de cible valide? content: `<p>Voulez vous faire un jet de ${compToUse} sans choisir de cible valide?
<br>Tous les jets de combats devront être gérés à la main <br>Tous les jets de combats devront être gérés à la main
</p>`, </p>`,
title: 'Ne pas utiliser les automatisation de combat', title: 'Ne pas utiliser les automatisation de combat',

View File

@ -20,14 +20,14 @@ const nomCategorieParade = {
export class RdDItemArme extends Item { export class RdDItemArme extends Item {
static isArme(item) { static isArme(item) {
return RdDItemCompetenceCreature.getCategorieAttaque(item) || item.type == 'arme'; return RdDItemCompetenceCreature.getCategorieAttaque(item) || item.type == TYPES.arme;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getArme(arme) { static getArme(arme) {
switch (arme ? arme.type : '') { switch (arme ? arme.type : '') {
case 'arme': return arme; case TYPES.arme: return arme;
case 'competencecreature': case TYPES.competencecreature:
return RdDItemCompetenceCreature.armeCreature(arme); return RdDItemCompetenceCreature.armeCreature(arme);
} }
return RdDItemArme.mainsNues(); return RdDItemArme.mainsNues();
@ -68,14 +68,14 @@ export class RdDItemArme extends Item {
return armeData.system.categorie_parade; return armeData.system.categorie_parade;
} }
// pour compatibilité avec des personnages existants // pour compatibilité avec des personnages existants
if (armeData.type == 'competencecreature' || armeData.system.categorie == 'creature') { if (armeData.type == TYPES.competencecreature || armeData.system.categorie == 'creature') {
return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : ''); return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : '');
} }
if (!armeData.type.match(/arme|competencecreature/)) { if (!armeData.type.match(/arme|competencecreature/)) {
return ''; return '';
} }
if (armeData.system.competence == undefined) { if (armeData.system.competence == undefined) {
return 'competencecreature'; return TYPES.competencecreature;
} }
let compname = armeData.system.competence.toLowerCase(); let compname = armeData.system.competence.toLowerCase();
if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) return ''; if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) return '';
@ -157,23 +157,33 @@ export class RdDItemArme extends Item {
} }
return armeData; return armeData;
} }
static competence2Mains(arme) {
return arme.system.competence.replace(" 1 main", " 2 mains");
}
static competence1Mains(arme) {
return arme.system.competence.replace(" 2 mains", " 1 main");
}
static isArmeUtilisable(arme) { static isArmeUtilisable(arme) {
return arme.type == 'arme' && arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0); return arme.type == 'arme' && arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0);
} }
static ajoutCorpsACorps(armes, competences, carac) { static ajoutCorpsACorps(armes, actor) {
let corpsACorps = competences.find(it => it.name == 'Corps à corps') ?? { system: { niveau: -6 } }; armes.push(RdDItemArme.mainsNues(actor));
let init = RdDCombatManager.calculInitiative(corpsACorps.system.niveau, carac['melee'].value); armes.push(RdDItemArme.empoignade(actor));
armes.push(RdDItemArme.mainsNues({ niveau: corpsACorps.system.niveau, initiative: init }));
armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.system.niveau, initiative: init }));
} }
static corpsACorps(mainsNuesActor) { static corpsACorps(actor) {
const corpsACorps = { let competence = actor?.getCompetenceCorpsACorps() ?? { system: { niveau: -6 } };
let melee = actor? actor.system.carac['melee'].value : 0
return {
_id: competence?.id,
name: 'Corps à corps', name: 'Corps à corps',
type: TYPES.arme,
img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp', img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp',
system: { system: {
initiative: RdDCombatManager.calculInitiative(competence.system.niveau, melee),
equipe: true, equipe: true,
rapide: true, rapide: true,
force: 0, force: 0,
@ -181,23 +191,22 @@ export class RdDItemArme extends Item {
dommagesReels: 0, dommagesReels: 0,
mortalite: 'non-mortel', mortalite: 'non-mortel',
competence: 'Corps à corps', competence: 'Corps à corps',
deuxmains: true,
categorie_parade: 'sans-armes' categorie_parade: 'sans-armes'
} }
}; }
mergeObject(corpsACorps.system, mainsNuesActor ?? {}, { overwrite: false });
return corpsACorps;
} }
static mainsNues(mainsNuesActor) { static mainsNues(actor) {
const mainsNues = RdDItemArme.corpsACorps(mainsNuesActor) const mainsNues = RdDItemArme.corpsACorps(actor)
mainsNues.name = 'Mains nues' mainsNues.name = 'Mains nues'
mainsNues.system.cac = 'pugilat' mainsNues.system.cac = 'pugilat'
mainsNues.system.baseInit = 4 mainsNues.system.baseInit = 4
return mainsNues; return mainsNues;
} }
static empoignade(mainsNuesActor) { static empoignade(actor) {
const empoignade = RdDItemArme.corpsACorps(mainsNuesActor) const empoignade = RdDItemArme.corpsACorps(actor)
empoignade.name = 'Empoignade' empoignade.name = 'Empoignade'
empoignade.system.cac = 'empoignade' empoignade.system.cac = 'empoignade'
empoignade.system.baseInit = 3 empoignade.system.baseInit = 3

View File

@ -79,10 +79,9 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isCompetenceArme(competence) { static isCompetenceArme(competence) {
if (competence.isCompetence()) { if (competence.isCompetence() && !competence.isCorpsACorps() && !competence.isEsquive()) {
switch (competence.system.categorie) { switch (competence.system.categorie) {
case 'melee': case 'melee':
return !Grammar.toLowerCaseNoAccent(competence.name).includes('esquive');
case 'tir': case 'tir':
case 'lancer': case 'lancer':
return true; return true;
@ -93,10 +92,10 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isArmeUneMain(competence) { static isArmeUneMain(competence) {
return RdDItemCompetence.isCompetenceArme(competence) && competence.name.toLowerCase().includes("1 main"); return competence.isCompetenceArme() && competence.name.toLowerCase().includes("1 main");
} }
static isArme2Main(competence) { static isArme2Main(competence) {
return RdDItemCompetence.isCompetenceArme(competence) && competence.name.toLowerCase().includes("2 main"); return competence.isCompetenceArme() && competence.name.toLowerCase().includes("2 main");
} }
static isThanatos(competence) { static isThanatos(competence) {

View File

@ -1,5 +1,5 @@
import { RdDItem, TYPES } from "./item.js"; import { TYPES } from "./item.js";
import { RdDCombatManager } from "./rdd-combat.js"; import { RdDCombatManager } from "./rdd-combat.js";
const categories = { const categories = {

View File

@ -113,7 +113,7 @@ export class RdDItemSheet extends ItemSheet {
formData.competences = competences; formData.competences = competences;
} }
if (this.item.type == 'arme') { if (this.item.type == 'arme') {
formData.competences = competences.filter(it => RdDItemCompetence.isCompetenceArme(it)) formData.competences = competences.filter(it => it.isCompetenceArme())
} }
if (['sort', 'sortreserve'].includes(this.item.type)) { if (['sort', 'sortreserve'].includes(this.item.type)) {
formData.competences = competences.filter(it => RdDItemCompetence.isDraconic(it)); formData.competences = competences.filter(it => RdDItemCompetence.isDraconic(it));

View File

@ -220,6 +220,32 @@ export class RdDItem extends Item {
isService() { return this.type == TYPES.service; } isService() { return this.type == TYPES.service; }
isCompetence() { return typesObjetsCompetence.includes(this.type) } isCompetence() { return typesObjetsCompetence.includes(this.type) }
isEsquive() {
return (this.isCompetence()
&& this.system.categorie == 'melee'
&& Grammar.includesLowerCaseNoAccent(this.name, 'Esquive'));
}
isCorpsACorps() {
return (this.isCompetence()
&& this.system.categorie == 'melee'
&& Grammar.includesLowerCaseNoAccent(this.name, 'Corps à Corps'));
}
isCompetenceArme() {
if (this.isCompetence()) {
switch (this.system.categorie) {
case 'melee':
return !this.isCorpsACorps() && !this.isEsquive()
case 'tir':
case 'lancer':
return true;
}
}
return false;
}
isCompetencePossession() { return TYPES.competencecreature == this.type && this.system.categorie == "possession" } isCompetencePossession() { return TYPES.competencecreature == this.type && this.system.categorie == "possession" }
isTemporel() { return typesObjetsTemporels.includes(this.type) } isTemporel() { return typesObjetsTemporels.includes(this.type) }
isOeuvre() { return typesObjetsOeuvres.includes(this.type) } isOeuvre() { return typesObjetsOeuvres.includes(this.type) }

View File

@ -75,7 +75,7 @@ export class RdDCombatManager extends Combat {
} }
} }
} }
/************************************************************************************/ /************************************************************************************/
async rollInitiative(ids, formula = undefined, messageOptions = {}) { async rollInitiative(ids, formula = undefined, messageOptions = {}) {
console.log(`${game.system.title} | Combat.rollInitiative()`, ids, formula, messageOptions); console.log(`${game.system.title} | Combat.rollInitiative()`, ids, formula, messageOptions);
@ -171,8 +171,7 @@ export class RdDCombatManager extends Combat {
if (arme.system.unemain && arme.system.deuxmains && !dommages.includes("/")) { if (arme.system.unemain && arme.system.deuxmains && !dommages.includes("/")) {
ui.notifications.info("Les dommages de l'arme à 1/2 mains " + arme.name + " ne sont pas corrects (ie sous la forme X/Y)"); ui.notifications.info("Les dommages de l'arme à 1/2 mains " + arme.name + " ne sont pas corrects (ie sous la forme X/Y)");
} }
if ((arme.system.unemain && arme.system.competence) || if (arme.system.unemain && arme.system.competence) {
(arme.system.competence.toLowerCase().includes("corps à corps"))) {
actions.push(RdDCombatManager.$prepareAttaqueArme({ actions.push(RdDCombatManager.$prepareAttaqueArme({
arme: arme, arme: arme,
infoMain: "(1 main)", infoMain: "(1 main)",
@ -187,7 +186,7 @@ export class RdDCombatManager extends Combat {
arme: arme, arme: arme,
infoMain: "(2 mains)", infoMain: "(2 mains)",
dommagesReel: Number(tableauDommages[1]), dommagesReel: Number(tableauDommages[1]),
competence: arme.system.competence.replace(" 1 main", " 2 mains"), competence: RdDItemArme.competence2Mains(arme),
carac: carac, carac: carac,
competences: competences competences: competences
})); }));
@ -258,11 +257,10 @@ export class RdDCombatManager extends Combat {
actions = RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']); actions = RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']);
} else if (actor.isPersonnage()) { } else if (actor.isPersonnage()) {
// Recupération des items 'arme' // Recupération des items 'arme'
const armes = actor.itemTypes['arme'].filter(it => RdDItemArme.isArmeUtilisable(it))
.concat(RdDItemArme.empoignade())
.concat(RdDItemArme.mainsNues());
const competences = actor.itemTypes['competence']; const competences = actor.itemTypes['competence'];
const armes = actor.itemTypes['arme'].filter(it => RdDItemArme.isArmeUtilisable(it))
.concat(RdDItemArme.empoignade(actor))
.concat(RdDItemArme.mainsNues(actor));
actions = RdDCombatManager.listActionsArmes(armes, competences, actor.system.carac); actions = RdDCombatManager.listActionsArmes(armes, competences, actor.system.carac);
if (actor.system.attributs.hautrevant.value) { if (actor.system.attributs.hautrevant.value) {
@ -885,8 +883,8 @@ export class RdDCombat {
} }
// # utilisation esquive // # utilisation esquive
const corpsACorps = this.defender.getCompetence("Corps à corps", { onMessage: it => console.info(it, this.defender) }); const corpsACorps = this.defender.getCompetenceCorpsACorps({ onMessage: it => console.info(it, this.defender) });
const esquives = duplicate(this.defender.getCompetences("esquive", { onMessage: it => console.info(it, this.defender) })) const esquives = duplicate(this.defender.getCompetencesEsquive())
esquives.forEach(e => e.system.nbUsage = e?._id ? this.defender.getItemUse(e._id) : 0); esquives.forEach(e => e.system.nbUsage = e?._id ? this.defender.getItemUse(e._id) : 0);
const paramChatDefense = { const paramChatDefense = {

View File

@ -181,7 +181,7 @@ export class RdDEmpoignade {
let rollData = { let rollData = {
mode, empoignade, attacker, defender, mode, empoignade, attacker, defender,
isEmpoignade: true, isEmpoignade: true,
competence: attacker.getCompetence("Corps à corps"), competence: attacker.getCompetenceCorpsACorps(),
selectedCarac: attacker.system.carac.melee, selectedCarac: attacker.system.carac.melee,
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender) malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
} }
@ -210,7 +210,7 @@ export class RdDEmpoignade {
mode: "immobilise", mode: "immobilise",
empoignade, attacker, defender, empoignade, attacker, defender,
isEmpoignade: true, isEmpoignade: true,
competence: attacker.getCompetence("Corps à corps") competence: attacker.getCompetenceCorpsACorps()
} }
const msg = await ChatMessage.create({ const msg = await ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(attacker.name), whisper: ChatUtility.getWhisperRecipientsAndGMs(attacker.name),

View File

@ -1,13 +1,17 @@
import { RdDItemArme } from "./item-arme.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { TYPES } from "./item.js"; import { TYPES } from "./item.js";
export class RdDHotbar { export class RdDHotbar {
static async createItemMacro(item, slot, armeCompetence = undefined) { static async createItemMacro(item, slot, armeCompetence = undefined) {
let command = `game.system.rdd.RdDHotbar.rollMacro("${item.name}", "${item.type}"` + ((armeCompetence) ? `, "${armeCompetence}");` : `);`); const itemName = item.name;
let macro = game.macros.contents.find(m => (m.name === item.name) && (m.command === command)); let macroName = itemName + RdDHotbar.$macroNameSuffix(armeCompetence);
let command = `game.system.rdd.RdDHotbar.rollMacro("${itemName}", "${item.type}", "${armeCompetence}");`
let macro = game.macros.contents.find(m => (m.name === itemName) && (m.command === command));
if (!macro) { if (!macro) {
macro = await Macro.create({ macro = await Macro.create({
name: item.name, name: macroName,
type: "script", type: "script",
img: item.img, img: item.img,
command: command command: command
@ -16,29 +20,55 @@ export class RdDHotbar {
await game.user.assignHotbarMacro(macro, slot); await game.user.assignHotbarMacro(macro, slot);
} }
static $macroNameSuffix(armeCompetence) {
switch (armeCompetence) {
case 'unemain': return ' (1 main)';
case 'deuxmains': return ' (2 main)';
case 'tir': return ' (tir)';
case 'lancer': return ' (lancer)';
case 'pugilat': return ' (pugilat)';
case 'empoignade': return ' (empoignade)';
}
return ''
}
static async addToHotbar(item, slot) { static async addToHotbar(item, slot) {
switch (item?.type ?? "") { switch (item?.type ?? '') {
case TYPES.arme: case TYPES.arme:
{ {
// Les armes peuvent avoir plusieurs usages // Les armes peuvent avoir plusieurs usages
if (item.system.competence != "") { if (item.system.competence != '') {
await this.createItemMacro(item, slot, "competence") if (item.system.unemain) {
slot++ await this.createItemMacro(item, slot++, 'unemain')
}
if (item.system.deuxmains) {
await this.createItemMacro(item, slot++, 'deuxmains')
}
} }
if (item.system.lancer != "") { if (item.system.lancer != '') {
await this.createItemMacro(item, slot, "lancer") await this.createItemMacro(item, slot++, 'lancer')
slot++
} }
if (item.system.tir != "") { if (item.system.tir != '') {
await this.createItemMacro(item, slot, "lancer") await this.createItemMacro(item, slot++, 'lancer')
slot++
} }
} }
return return
case TYPES.competence:
case TYPES.competencecreature: case TYPES.competencecreature:
const categorie = RdDItemCompetenceCreature.getCategorieAttaque(item) ?? 'competence';
await this.createItemMacro(item, slot, categorie)
return
default: default:
await this.createItemMacro(item, slot) case TYPES.competence:
await this.createItemMacro(item, slot++, 'competence')
if (item.isCorpsACorps()) {
await this.createItemMacro(item, slot++, 'pugilat')
await this.createItemMacro(item, slot++, 'empoignade')
}
if (item.isCompetenceArme()) {
ui.notifications.info(`${item.name} est une compétence d'arme, la macro n'est pas liée à un arme.<br>
Créez la macro depuis l'arme ou l'onglet combat pour garder les automatisations de combat.`);
}
return return
} }
} }
@ -51,14 +81,13 @@ export class RdDHotbar {
*/ */
static initDropbar() { static initDropbar() {
Hooks.on("hotbarDrop", (bar, documentData, slot) => { Hooks.on('hotbarDrop', (bar, documentData, slot) => {
// Create item macro if rollable item - weapon, spell, prayer, trait, or skill // Create item macro if rollable item - weapon, spell, prayer, trait, or skill
if (documentData.type == "Item") { if (documentData.type == 'Item') {
const item = fromUuidSync(documentData.uuid) ?? this.actor.items.get(documentData.uuid) const item = fromUuidSync(documentData.uuid) ?? this.actor.items.get(documentData.uuid)
console.log("DROP", documentData, item) console.log('DROP', documentData, item)
switch (item?.type ?? "") switch (item?.type) {
{
case TYPES.arme: case TYPES.arme:
case TYPES.competence: case TYPES.competence:
case TYPES.competencecreature: case TYPES.competencecreature:
@ -72,7 +101,7 @@ export class RdDHotbar {
} }
/** Roll macro */ /** Roll macro */
static rollMacro(itemName, itemType, competenceName) { static rollMacro(itemName, itemType, categorieArme = 'competence') {
const speaker = ChatMessage.getSpeaker(); const speaker = ChatMessage.getSpeaker();
let actor; let actor;
if (speaker.token) actor = game.actors.tokens[speaker.token]; if (speaker.token) actor = game.actors.tokens[speaker.token];
@ -88,10 +117,22 @@ export class RdDHotbar {
// Trigger the item roll // Trigger the item roll
switch (item.type) { switch (item.type) {
case TYPES.arme: case TYPES.arme:
return actor.rollArme(item, competenceName); return actor.rollArme(item, categorieArme);
case TYPES.competence: case TYPES.competence:
if (item.isCorpsACorps()) {
switch (categorieArme) {
case 'pugilat':
return actor.rollArme(RdDItemArme.mainsNues(actor), 'competence');
case 'empoignade':
return actor.rollArme(RdDItemArme.empoignade(actor), 'competence');
}
}
return actor.rollCompetence(item);
case TYPES.competencecreature: case TYPES.competencecreature:
return actor.rollCompetence(itemName); return item.system.iscombat && !item.system.isparade
? actor.rollArme(item, categorieArme)
: actor.rollCompetence(item);
} }
} }

View File

@ -39,7 +39,8 @@ export class RdDTMRDialog extends Dialog {
content: html, content: html,
buttons: { buttons: {
closeButton: { closeButton: {
label: "Fermer", callback: html => this.close() } label: "Fermer", callback: html => this.close()
}
}, },
default: "closeButton" default: "closeButton"
} }
@ -93,6 +94,9 @@ export class RdDTMRDialog extends Dialog {
setTMRPendingAction(dialog) { setTMRPendingAction(dialog) {
this.subdialog = dialog this.subdialog = dialog
if (dialog instanceof Application) {
dialog.bringToTop();
}
} }
isDemiReveCache() { isDemiReveCache() {
@ -579,9 +583,12 @@ export class RdDTMRDialog extends Dialog {
_presentCite(tmr) { _presentCite(tmr) {
const presentCite = this.casesSpeciales.find(c => EffetsDraconiques.presentCites.isCase(c, tmr.coord)); const presentCite = this.casesSpeciales.find(c => EffetsDraconiques.presentCites.isCase(c, tmr.coord));
if (presentCite) { if (presentCite) {
this.minimize();
const caseData = presentCite; const caseData = presentCite;
EffetsDraconiques.presentCites.choisirUnPresent(caseData, (present => this._utiliserPresentCite(presentCite, present, tmr))); const dialog = EffetsDraconiques.presentCites.choisirUnPresent(caseData, present => {
this._utiliserPresentCite(presentCite, present, tmr)
this.restoreTMRAfterAction();
});
this.setTMRPendingAction(dialog);
} }
return presentCite; return presentCite;
} }
@ -607,8 +614,6 @@ export class RdDTMRDialog extends Dialog {
presentCite: presentCite presentCite: presentCite
}; };
await this._tentativeMaitrise(rencontreData); await this._tentativeMaitrise(rencontreData);
this.maximize();
this.postRencontre(tmr); this.postRencontre(tmr);
} }
@ -815,22 +820,22 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
async _maitriserTMR(rollData, callbackMaitrise) { async _maitriserTMR(rollData, callbackMaitrise) {
this.minimize(); // Hide
rollData.isTMRCache = rollData.actor.isTMRCache(); rollData.isTMRCache = rollData.actor.isTMRCache();
const dialog = await RdDRoll.create(this.actor, rollData, const dialog = await RdDRoll.create(this.actor, rollData,
{ {
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html', html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html',
close: html => { this.restoreTMRAfterAction(); }
}, },
{ {
name: rollData.maitrise.verbe, label: rollData.maitrise.action, name: rollData.maitrise.verbe, label: rollData.maitrise.action,
callbacks: [ callbacks: [
this.actor.createCallbackExperience(), this.actor.createCallbackExperience(),
{ action: r => { this.restoreTMRAfterAction() } },
{ action: callbackMaitrise } { action: callbackMaitrise }
] ]
} }
); );
dialog.render(true); dialog.render(true);
this.setTMRPendingAction(dialog);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -34,6 +34,7 @@ export class RdDTMRRencontreDialog extends Dialog {
async onButtonAction(action) { async onButtonAction(action) {
this.toClose = true; this.toClose = true;
await this.actor.tmrApp?.restoreTMRAfterAction();
this.actor.tmrApp?.onActionRencontre(action, this.tmr, this.rencontre) this.actor.tmrApp?.onActionRencontre(action, this.tmr, this.rencontre)
} }
@ -41,7 +42,6 @@ export class RdDTMRRencontreDialog extends Dialog {
async close() { async close() {
if (this.actor.tmrApp){ if (this.actor.tmrApp){
if (this.toClose) { if (this.toClose) {
this.actor.tmrApp?.restoreTMRAfterAction();
return await super.close(); return await super.close();
} }
else { else {

View File

@ -364,7 +364,7 @@ export class RdDCalendrier extends Application {
if (request.rolled.isSuccess) { if (request.rolled.isSuccess) {
if (request.rolled.isPart) { if (request.rolled.isPart) {
// Gestion expérience (si existante) // Gestion expérience (si existante)
request.competence = actor.getCompetence("astrologie") request.competence = actor.getCompetence('Astrologie')
request.selectedCarac = actor.system.carac["vue"]; request.selectedCarac = actor.system.carac["vue"];
actor.appliquerAjoutExperience(request, 'hide'); actor.appliquerAjoutExperience(request, 'hide');
} }

View File

@ -49,12 +49,13 @@ export class PresentCites extends Draconique {
const presents = await game.system.rdd.rencontresTMR.getPresentsCite() const presents = await game.system.rdd.rencontresTMR.getPresentsCite()
const buttons = {}; const buttons = {};
presents.forEach(r => buttons['present'+r.id] = { icon: '<i class="fas fa-check"></i>', label: r.name, callback: async () => onChoixPresent(r) }); presents.forEach(r => buttons['present'+r.id] = { icon: '<i class="fas fa-check"></i>', label: r.name, callback: async () => onChoixPresent(r) });
let d = new Dialog({ let dialog = new Dialog({
title: "Présent des cités", title: "Présent des cités",
content: `La ${this.tmrLabel(casetmr)} vous offre un présent, faites votre choix`, content: `La ${this.tmrLabel(casetmr)} vous offre un présent, faites votre choix`,
buttons: buttons buttons: buttons
}); });
d.render(true); dialog.render(true);
return dialog
} }
async ouvrirLePresent(actor, casetmr) { async ouvrirLePresent(actor, casetmr) {

View File

@ -1,8 +1,8 @@
{ {
"id": "foundryvtt-reve-de-dragon", "id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon", "title": "Rêve de Dragon",
"version": "11.0.25", "version": "11.0.26",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.0.25.zip", "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.0.26.zip",
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json", "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json",
"changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md", "changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md",
"compatibility": { "compatibility": {