Compare commits

..

21 Commits

Author SHA1 Message Date
e6592f8333 Merge pull request 'v11.0.28 - les fractures de Khrachtchoum' (#675) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#675
2023-10-30 22:34:39 +01:00
42567e7ca0 Amélioration de fenêtre de jets
- indication du type de dégâts
- affichage du moral avant l'icone d'appel au moral
- meilleur alignement des différentes options
2023-10-30 21:33:38 +01:00
9d1fe6d8fd Version 11.0.28 2023-10-30 19:47:08 +01:00
f5bd0f32f4 Fix: affichage de la gravité des blessures
Le type de blessure est indiqué dans le résumé d'encaissement
2023-10-30 19:42:56 +01:00
fad29f9652 Jet de vie par les propriétaires
Les messages de tour sont séparés en deux:
- un message pour tout le monde disant de qui c'est le tour
- un message pour les propriétaires du token pour les informations
  de santé (jets de vie à faire, ...)

Seul les propriétaires peuvent déclencher les jets de vie
2023-10-30 19:40:21 +01:00
9d51631d5c Merge pull request 'v11.0.27' (#674) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#674
2023-10-25 00:02:40 +02:00
d1b73e7658 Version 11.0.27 2023-10-24 22:51:45 +02:00
54158ee10d Fix disparition du tooltip dans les TMR
Passage den eventMode static permet de ne pas faire disparaître le
tooltip.
2023-10-24 22:44:51 +02:00
e089bdf9c8 Surencombrement seulement sur actions physiques
CF p70
2023-10-24 22:32:49 +02:00
41ab593059 Fix: fabrication de potion depuis l'herbe
La fabrication ne marchait plus
2023-10-24 22:24:54 +02:00
42ad4c5b26 Fix Restauration TMR si minimisée
Lors d'une action dans les TMRs, si la fenêtre est minimisée,
on la réaffiche
2023-10-24 22:16:49 +02:00
85f8a716d4 Merge pull request '## v11.0.26 - le crépuscule de Khrachtchoum' (#673) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#673
2023-10-24 07:07:01 +02:00
47f305d865 Les attaques de créatures fonctionnent de nouveau 2023-10-24 00:50:16 +02:00
407b4f82d9 Version 11.0.26 2023-10-24 00:43:16 +02:00
c950f568fd Fix: les TMRs sont en arrière plan 2023-10-24 00:30:00 +02:00
0ed90f6177 Macros pour le corps à corps
Cas particulier car 3 utilisations possibles, et pas d'armes
2023-10-23 23:48:07 +02:00
b74fc27079 Minor cleanup 2023-10-23 23:38:34 +02:00
a65d4511c5 Fix Macros de combat et corps à corps
- gestion des armes à 1/2 mains depuis les armes / le combat
- gestion correcte des compétences d'attaques de créatures
- message pour les macros de compétence d'arme
2023-10-23 23:29:02 +02:00
e61417c44e Merge pull request '## v11.0.25 - la vision du rêve de Khrachtchoum' (#672) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#672
2023-10-22 21:40:42 +02:00
8ca725bd38 Version 11.0.25 2023-10-22 16:17:53 +02:00
441a5965c7 Fix TMR minimize/maximize
Au lieu de minimiser les TMRs, les actions dans les TMRs sont bloquées
tant qu'une action liée au TMRs est en cours.
2023-10-22 16:17:37 +02:00
26 changed files with 419 additions and 204 deletions

View File

@@ -1,4 +1,42 @@
# v11.0
## v11.0.28 - les fractures de Khrachtchoum
- La gravité de la blessure est affichée dans le résumé de l'encaissement
- Lors du changement d'acteur pendant le round
- le message annonçant le joueur dont c'est le tour ne contient plus d'informations de santé
- un message avec les informations de santé est envoyé au Gardienn et au propriétaire du token.acteur
- le jet de vie est bien fait par le token si besoin
- seul les propriétaires peuvent faire les jets de vie
- Amélioration de la fenêtre de jets
- le type de dégâts pour les attaques est toujours affiché
- le moral est indiqué avant l'icone d'appel au moral
## v11.0.27 - Khrachtchoum le méticuleux
- le tooltip dans les TMR reste visible si on ne bouge pas la souris
- le surencombrement n'affecte QUE les actions physiques
- on peut de nouveau fabriquer une potion depuis la fenêtre d'édition de l'herbe
- si les TMR sont minimisées alors qu'une action est requise, elles sont bien réaffichées lorsque l'action est faite
## 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
- Les TMRs restent affichées tant que le Haut-rêvant est en demi-rêve
## v11.0.24 - les couleurs de Khrachtchoum
- nouvelle carte des TMRs

View File

@@ -81,9 +81,12 @@ export class RdDActorSheet extends RdDBaseActorSheet {
});
// 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.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.combat = RdDCombatManager.listActionsArmes(formData.combat, formData.competences, formData.system.carac);
formData.empoignades = this.actor.getEmpoignades();

View File

@@ -232,12 +232,21 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
getCompetence(idOrName, options = {}) {
if (idOrName instanceof Item) {
return idOrName.isCompetence() ? idOrName : undefined
}
return RdDItemCompetence.findCompetence(this.items, idOrName, options)
}
getCompetences(name) {
return RdDItemCompetence.findCompetences(this.items, name)
}
getCompetenceCorpsACorps(options = {}) {
return this.getCompetence("Corps à corps", options)
}
getCompetencesEsquive() {
return this.getCompetences("esquive")
}
/* -------------------------------------------- */
getTache(id) {
return this.findItemLike(id, 'tache');
@@ -288,13 +297,13 @@ export class RdDActor extends RdDBaseActor {
}
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() {
return this.items.filter(it => it.type == TYPES.possession);
return this.itemTypes[TYPES.possession];
}
getEmpoignades() {
return this.items.filter(it => it.type == TYPES.empoignade);
return this.itemTypes[TYPES.empoignade];
}
getDemiReve() {
return this.system.reve.tmrpos.coord;
@@ -369,7 +378,7 @@ export class RdDActor extends RdDBaseActor {
async _openRollDialog({ name, label, template, rollData, callbackAction }) {
const dialog = await RdDRoll.create(this, rollData,
{ html: template },
{ html: template, close: html => { this.tmrApp?.restoreTMRAfterAction() } },
{
name: name,
label: label,
@@ -380,6 +389,7 @@ export class RdDActor extends RdDBaseActor {
]
});
dialog.render(true);
return dialog
}
@@ -545,7 +555,7 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
async _recuperationBlessures(message, isMaladeEmpoisonne) {
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({
actor: this,
@@ -559,7 +569,7 @@ export class RdDActor extends RdDBaseActor {
}
async supprimerBlessures(filterToDelete) {
const toDelete = this.filterItems(filterToDelete, 'blessure')
const toDelete = this.filterItems(filterToDelete, TYPES.blessure)
.map(it => it.id);
await this.deleteEmbeddedDocuments('Item', toDelete);
}
@@ -567,7 +577,7 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
async _recupererVie(message, isMaladeEmpoisonne) {
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) {
return
}
@@ -846,7 +856,7 @@ export class RdDActor extends RdDBaseActor {
system: { sortid: sort._id, draconic: (draconic?.name ?? sort.system.draconic), ptreve: ptreve, coord: coord, heurecible: 'Vaisseau' }
}],
{ renderSheet: false });
this.currentTMR.updateTokens();
this.tmrApp.updateTokens();
}
/* -------------------------------------------- */
@@ -2138,12 +2148,11 @@ export class RdDActor extends RdDBaseActor {
ui.notifications.info(`Aucun sort disponible en ${TMRUtility.getTMR(coord).label} !`);
return;
}
if (this.currentTMR) this.currentTMR.minimize(); // Hide
const draconicList = this.computeDraconicAndSortIndex(sorts);
const reve = duplicate(this.system.carac.reve);
await this._openRollDialog({
const dialog = await this._openRollDialog({
name: 'lancer-un-sort',
label: 'Lancer un sort',
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.html',
@@ -2159,8 +2168,12 @@ export class RdDActor extends RdDBaseActor {
diffLibre: RdDItemSort.getDifficulte(sorts[0], -7), // Per default at startup
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);
}
/* -------------------------------------------- */
@@ -2251,17 +2264,11 @@ export class RdDActor extends RdDBaseActor {
reveActuel = Math.max(reveActuel - rollData.depenseReve, 0);
await this.update({ "system.reve.reve.value": reveActuel });
if (rollData.isSortReserve) {
this.currentTMR.maximize(); // Re-display TMR
} else {
this.currentTMR.close(); // Close TMR !
}
// Final chat message
await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-sort.html');
if (reveActuel == 0) { // 0 points de reve
ChatMessage.create({ content: this.name + " est réduit à 0 Points de Rêve, et tombe endormi !" });
closeTMR = true;
}
}
@@ -2336,16 +2343,14 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
async rollCompetence(idOrName, options = { tryTarget: true }) {
RdDEmpoignade.checkEmpoignadeEnCours(this)
let rollData = {
carac: this.system.carac,
competence: this.getCompetence(idOrName)
}
if (rollData.competence.type == TYPES.competencecreature) {
const arme = RdDItemCompetenceCreature.armeCreature(rollData.competence)
const competence = this.getCompetence(idOrName);
let rollData = { carac: this.system.carac, competence: competence }
if (competence.type == TYPES.competencecreature) {
const arme = RdDItemCompetenceCreature.armeCreature(competence)
if (arme && options.tryTarget && Targets.hasTargets()) {
Targets.selectOneToken(target => {
if (arme.action == "possession") {
RdDPossession.onAttaquePossession(target, this, rollData.competence)
RdDPossession.onAttaquePossession(target, this, competence)
}
else {
RdDCombat.rddCombatTarget(target, this).attaque(competence, arme)
@@ -2359,7 +2364,7 @@ export class RdDActor extends RdDBaseActor {
await this._openRollDialog({
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',
rollData: rollData,
callbackAction: r => this.$onRollCompetence(r, options)
@@ -2723,8 +2728,6 @@ export class RdDActor extends RdDBaseActor {
ui.notifications.info(`Aucun signe draconiques en ${coord} !`);
return;
}
if (this.currentTMR) this.currentTMR.minimize(); // Hide
let draconicList = this.getDraconicList()
.map(draconic => {
let draconicLecture = duplicate(draconic);
@@ -2747,7 +2750,7 @@ export class RdDActor extends RdDBaseActor {
const dialog = await RdDRoll.create(this, rollData,
{
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-signedraconique.html',
close: html => { this.currentTMR.maximize() } // Re-display TMR
close: html => { this.tmrApp?.restoreTMRAfterAction() }
},
{
name: 'lire-signe-draconique',
@@ -2759,6 +2762,7 @@ export class RdDActor extends RdDBaseActor {
}
);
dialog.render(true);
this.tmrApp?.setTMRPendingAction(dialog);
}
/* -------------------------------------------- */
@@ -2777,7 +2781,7 @@ export class RdDActor extends RdDBaseActor {
}
await this.deleteEmbeddedDocuments("Item", [rollData.signe._id]);
await RdDResolutionTable.displayRollData(rollData, this.name, 'chat-resultat-lecture-signedraconique.html');
this.currentTMR.close();
this.tmrApp.close();
}
/* -------------------------------------------- */
@@ -3012,8 +3016,8 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
refreshTMRView() {
if (this.currentTMR) {
this.currentTMR.externalRefresh();
if (this.tmrApp) {
this.tmrApp.externalRefresh();
}
}
@@ -3021,6 +3025,7 @@ export class RdDActor extends RdDBaseActor {
async displayTMR(mode = "normal") {
if (this.tmrApp) {
ui.notifications.warn("Vous êtes déja dans les TMR....");
this.tmrApp.forceTMRDisplay();
return
}
if (mode != 'visu' && this.getEffect(STATUSES.StatusDemiReve)) {
@@ -3066,29 +3071,40 @@ export class RdDActor extends RdDBaseActor {
hasPlayerOwner: this.hasPlayerOwner
}
this.currentTMR = await RdDTMRDialog.create(this, tmrFormData);
this.currentTMR.render(true);
this.tmrApp = await RdDTMRDialog.create(this, tmrFormData);
this.tmrApp.render(true);
}
/* -------------------------------------------- */
getArmeCompetence(arme, competenceName) {
let comp = arme.system[competenceName]
if (!comp || comp.name == "") {
comp = arme.system[competenceName]
getCompetenceArme(arme, competenceName) {
switch (arme.type) {
case TYPES.competencecreature:
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 == "") {
comp = arme.system[competenceName]
}
return comp
return undefined
}
/* -------------------------------------------- */
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()) {
RdDConfirm.confirmer({
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
</p>`,
title: 'Ne pas utiliser les automatisation de combat',

View File

@@ -20,14 +20,14 @@ const nomCategorieParade = {
export class RdDItemArme extends Item {
static isArme(item) {
return RdDItemCompetenceCreature.getCategorieAttaque(item) || item.type == 'arme';
return RdDItemCompetenceCreature.getCategorieAttaque(item) || item.type == TYPES.arme;
}
/* -------------------------------------------- */
static getArme(arme) {
switch (arme ? arme.type : '') {
case 'arme': return arme;
case 'competencecreature':
case TYPES.arme: return arme;
case TYPES.competencecreature:
return RdDItemCompetenceCreature.armeCreature(arme);
}
return RdDItemArme.mainsNues();
@@ -68,14 +68,14 @@ export class RdDItemArme extends Item {
return armeData.system.categorie_parade;
}
// 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' : '');
}
if (!armeData.type.match(/arme|competencecreature/)) {
return '';
}
if (armeData.system.competence == undefined) {
return 'competencecreature';
return TYPES.competencecreature;
}
let compname = armeData.system.competence.toLowerCase();
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;
}
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) {
return arme.type == 'arme' && arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0);
}
static ajoutCorpsACorps(armes, competences, carac) {
let corpsACorps = competences.find(it => it.name == 'Corps à corps') ?? { system: { niveau: -6 } };
let init = RdDCombatManager.calculInitiative(corpsACorps.system.niveau, carac['melee'].value);
armes.push(RdDItemArme.mainsNues({ niveau: corpsACorps.system.niveau, initiative: init }));
armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.system.niveau, initiative: init }));
static ajoutCorpsACorps(armes, actor) {
armes.push(RdDItemArme.mainsNues(actor));
armes.push(RdDItemArme.empoignade(actor));
}
static corpsACorps(mainsNuesActor) {
const corpsACorps = {
static corpsACorps(actor) {
let competence = actor?.getCompetenceCorpsACorps() ?? { system: { niveau: -6 } };
let melee = actor? actor.system.carac['melee'].value : 0
return {
_id: competence?.id,
name: 'Corps à corps',
type: TYPES.arme,
img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp',
system: {
initiative: RdDCombatManager.calculInitiative(competence.system.niveau, melee),
equipe: true,
rapide: true,
force: 0,
@@ -181,23 +191,22 @@ export class RdDItemArme extends Item {
dommagesReels: 0,
mortalite: 'non-mortel',
competence: 'Corps à corps',
deuxmains: true,
categorie_parade: 'sans-armes'
}
};
mergeObject(corpsACorps.system, mainsNuesActor ?? {}, { overwrite: false });
return corpsACorps;
}
}
static mainsNues(mainsNuesActor) {
const mainsNues = RdDItemArme.corpsACorps(mainsNuesActor)
static mainsNues(actor) {
const mainsNues = RdDItemArme.corpsACorps(actor)
mainsNues.name = 'Mains nues'
mainsNues.system.cac = 'pugilat'
mainsNues.system.baseInit = 4
return mainsNues;
}
static empoignade(mainsNuesActor) {
const empoignade = RdDItemArme.corpsACorps(mainsNuesActor)
static empoignade(actor) {
const empoignade = RdDItemArme.corpsACorps(actor)
empoignade.name = 'Empoignade'
empoignade.system.cac = 'empoignade'
empoignade.system.baseInit = 3

View File

@@ -79,10 +79,9 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */
static isCompetenceArme(competence) {
if (competence.isCompetence()) {
if (competence.isCompetence() && !competence.isCorpsACorps() && !competence.isEsquive()) {
switch (competence.system.categorie) {
case 'melee':
return !Grammar.toLowerCaseNoAccent(competence.name).includes('esquive');
case 'tir':
case 'lancer':
return true;
@@ -93,10 +92,10 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */
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) {
return RdDItemCompetence.isCompetenceArme(competence) && competence.name.toLowerCase().includes("2 main");
return competence.isCompetenceArme() && competence.name.toLowerCase().includes("2 main");
}
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";
const categories = {

View File

@@ -113,7 +113,7 @@ export class RdDItemSheet extends ItemSheet {
formData.competences = competences;
}
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)) {
formData.competences = competences.filter(it => RdDItemCompetence.isDraconic(it));
@@ -195,7 +195,7 @@ export class RdDItemSheet extends ItemSheet {
this.html.find('.creer-tache-livre').click((event) => this._getEventActor(event).creerTacheDepuisLivre(this.item));
this.html.find('.consommer-potion').click((event) => this._getEventActor(event).consommerPotion(this.item, this.getActionRenderItem()));
this.html.find('.creer-potion-base').click((event) => this._getEventActor(event).dialogFabriquerPotion(this.item));
this.html.find('.creer-potion-base').click((event) => this._getEventActor(event).actionHerbe(this.item));
this.html.find('.alchimie-tache a').click((event) => {
let actor = this._getEventActor(event);

View File

@@ -220,6 +220,32 @@ export class RdDItem extends Item {
isService() { return this.type == TYPES.service; }
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" }
isTemporel() { return typesObjetsTemporels.includes(this.type) }
isOeuvre() { return typesObjetsOeuvres.includes(this.type) }

View File

@@ -171,8 +171,7 @@ export class RdDCombatManager extends Combat {
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)");
}
if ((arme.system.unemain && arme.system.competence) ||
(arme.system.competence.toLowerCase().includes("corps à corps"))) {
if (arme.system.unemain && arme.system.competence) {
actions.push(RdDCombatManager.$prepareAttaqueArme({
arme: arme,
infoMain: "(1 main)",
@@ -187,7 +186,7 @@ export class RdDCombatManager extends Combat {
arme: arme,
infoMain: "(2 mains)",
dommagesReel: Number(tableauDommages[1]),
competence: arme.system.competence.replace(" 1 main", " 2 mains"),
competence: RdDItemArme.competence2Mains(arme),
carac: carac,
competences: competences
}));
@@ -258,11 +257,10 @@ export class RdDCombatManager extends Combat {
actions = RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']);
} else if (actor.isPersonnage()) {
// 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 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);
if (actor.system.attributs.hautrevant.value) {
@@ -450,7 +448,7 @@ export class RdDCombat {
if (Misc.isUniqueConnectedGM()) {
let turn = combat.turns.find(t => t.token?.id == combat.current.tokenId);
if (turn?.actor) {
RdDCombat.displayActorCombatStatus(combat, turn.actor);
RdDCombat.displayActorCombatStatus(combat, turn.actor, turn.token.id);
// TODO Playaudio for player??
}
}
@@ -514,8 +512,12 @@ export class RdDCombat {
/* -------------------------------------------- */
static _callJetDeVie(event) {
let actorId = event.currentTarget.attributes['data-actorId'].value;
let actor = game.actors.get(actorId);
actor.jetVie();
let tokenId = event.currentTarget.attributes['data-tokenId'].value;
let token = canvas.tokens.placeables.find(t => t.id == tokenId)
const actor = token?.actor ?? game.actors.get(actorId);
if (actor?.isOwner) {
actor.jetVie();
}
}
/* -------------------------------------------- */
@@ -541,7 +543,7 @@ export class RdDCombat {
}
});
}
html.on("click", '#chat-jet-vie', event => {
html.on("click", 'a.chat-jet-vie', event => {
event.preventDefault();
RdDCombat._callJetDeVie(event);
});
@@ -885,8 +887,8 @@ export class RdDCombat {
}
// # utilisation esquive
const corpsACorps = this.defender.getCompetence("Corps à corps", { onMessage: it => console.info(it, this.defender) });
const esquives = duplicate(this.defender.getCompetences("esquive", { onMessage: it => console.info(it, this.defender) }))
const corpsACorps = this.defender.getCompetenceCorpsACorps({ 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);
const paramChatDefense = {
@@ -1294,7 +1296,7 @@ export class RdDCombat {
}
/* -------------------------------------------- */
static async displayActorCombatStatus(combat, actor) {
static async displayActorCombatStatus(combat, actor, tokenId) {
let formData = {
combatId: combat._id,
alias: actor.name,
@@ -1303,12 +1305,18 @@ export class RdDCombat {
blessuresStatus: actor.computeResumeBlessure(),
SConst: actor.getSConst(),
actorId: actor.id,
tokenId: tokenId,
isGrave: actor.countBlessures(it => it.isGrave()) > 0,
isCritique: actor.countBlessures(it => it.isCritique()) > 0
}
ChatUtility.createChatWithRollMode(actor.name, {
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html`, formData)
await ChatMessage.create({
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-acteur.hbs`, formData),
alias: actor.name
});
await ChatMessage.create({
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-sante.hbs`, formData),
whisper: ChatUtility.getWhisperRecipientsAndGMs(actor.name),
alias: actor.name
});
}
}
}

View File

@@ -181,7 +181,7 @@ export class RdDEmpoignade {
let rollData = {
mode, empoignade, attacker, defender,
isEmpoignade: true,
competence: attacker.getCompetence("Corps à corps"),
competence: attacker.getCompetenceCorpsACorps(),
selectedCarac: attacker.system.carac.melee,
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
}
@@ -210,7 +210,7 @@ export class RdDEmpoignade {
mode: "immobilise",
empoignade, attacker, defender,
isEmpoignade: true,
competence: attacker.getCompetence("Corps à corps")
competence: attacker.getCompetenceCorpsACorps()
}
const msg = await ChatMessage.create({
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";
export class RdDHotbar {
static async createItemMacro(item, slot, armeCompetence = undefined) {
let command = `game.system.rdd.RdDHotbar.rollMacro("${item.name}", "${item.type}"` + ((armeCompetence) ? `, "${armeCompetence}");` : `);`);
let macro = game.macros.contents.find(m => (m.name === item.name) && (m.command === command));
const itemName = item.name;
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) {
macro = await Macro.create({
name: item.name,
name: macroName,
type: "script",
img: item.img,
command: command
@@ -16,29 +20,55 @@ export class RdDHotbar {
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) {
switch (item?.type ?? "") {
switch (item?.type ?? '') {
case TYPES.arme:
{
// Les armes peuvent avoir plusieurs usages
if (item.system.competence != "") {
await this.createItemMacro(item, slot, "competence")
slot++
if (item.system.competence != '') {
if (item.system.unemain) {
await this.createItemMacro(item, slot++, 'unemain')
}
if (item.system.deuxmains) {
await this.createItemMacro(item, slot++, 'deuxmains')
}
}
if (item.system.lancer != "") {
await this.createItemMacro(item, slot, "lancer")
slot++
if (item.system.lancer != '') {
await this.createItemMacro(item, slot++, 'lancer')
}
if (item.system.tir != "") {
await this.createItemMacro(item, slot, "lancer")
slot++
if (item.system.tir != '') {
await this.createItemMacro(item, slot++, 'lancer')
}
}
return
case TYPES.competence:
case TYPES.competencecreature:
const categorie = RdDItemCompetenceCreature.getCategorieAttaque(item) ?? 'competence';
await this.createItemMacro(item, slot, categorie)
return
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
}
}
@@ -51,14 +81,13 @@ export class RdDHotbar {
*/
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
if (documentData.type == "Item") {
if (documentData.type == 'Item') {
const item = fromUuidSync(documentData.uuid) ?? this.actor.items.get(documentData.uuid)
console.log("DROP", documentData, item)
switch (item?.type ?? "")
{
console.log('DROP', documentData, item)
switch (item?.type) {
case TYPES.arme:
case TYPES.competence:
case TYPES.competencecreature:
@@ -72,7 +101,7 @@ export class RdDHotbar {
}
/** Roll macro */
static rollMacro(itemName, itemType, competenceName) {
static rollMacro(itemName, itemType, categorieArme = 'competence') {
const speaker = ChatMessage.getSpeaker();
let actor;
if (speaker.token) actor = game.actors.tokens[speaker.token];
@@ -88,10 +117,22 @@ export class RdDHotbar {
// Trigger the item roll
switch (item.type) {
case TYPES.arme:
return actor.rollArme(item, competenceName);
return actor.rollArme(item, categorieArme);
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:
return actor.rollCompetence(itemName);
return item.system.iscombat && !item.system.isparade
? actor.rollArme(item, categorieArme)
: actor.rollCompetence(item);
}
}

View File

@@ -22,7 +22,7 @@ export class RdDRoll extends Dialog {
const html = await renderTemplate(dialogConfig.html, rollData);
let options = { classes: ["rdd-roll-dialog"], width: 600, height: 'fit-content', 'z-index': 99999, close: html => {} };
let options = { classes: ["rdd-roll-dialog"], width: 650, height: 'fit-content', 'z-index': 99999, close: html => {} };
if (dialogConfig.close) {
options.close = dialogConfig.close;
}
@@ -50,8 +50,6 @@ export class RdDRoll extends Dialog {
encTotal: true
},
isMalusEncombrementTotal: RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
malusArmureValue: actor.getMalusArmure(),
surencMalusValue: actor.computeMalusSurEncombrement(),
encTotal: actor.getEncTotal(),
ajustementAstrologique: actor.ajustementAstrologique(),
surprise: actor.getSurprise(false),
@@ -187,7 +185,7 @@ export class RdDRoll extends Dialog {
console.log("RdDRollSelectDialog - Cout reve", ptreve);
this.updateRollResult(html);
});
this.html.find("[name='mortalite']").change((event) => {
this.html.find("input.check-mortalite").change((event) => {
this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel";
this.updateRollResult(html);
});
@@ -291,34 +289,31 @@ export class RdDRoll extends Dialog {
/* -------------------------------------------- */
async updateRollResult(html) {
let rollData = this.rollData;
const rollData = this.rollData;
rollData.dmg = rollData.attackerRoll?.dmg ?? RdDBonus.dmg(rollData, this.actor.getBonusDegat())
rollData.caracValue = parseInt(rollData.selectedCarac.value)
rollData.mortalite = rollData.attackerRoll?.dmg.mortalite ?? rollData.dmg.mortalite ?? rollData.mortalite ?? 'mortel';
rollData.dmg.mortalite = rollData.dmg.mortalite ?? 'mortel';
rollData.use.appelAuMoral = this.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac);
let dmgText = Misc.toSignedString(rollData.dmg.total);
switch (rollData.mortalite) {
case 'non-mortel': dmgText = `(${dmgText}) non-mortel`; break;
case 'empoignade': dmgText = `empoignade`; break;
}
RollDataAjustements.calcul(rollData, this.actor);
const resolutionTable = await RdDResolutionTable.buildHTMLTable(RdDResolutionTable.subTable(rollData.caracValue, rollData.finalLevel))
const adjustements = await this.buildAjustements(rollData);
HtmlUtility.showControlWhen(this.html.find(".use-encTotal"), rollData.ajustements.encTotal.visible && RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac));
HtmlUtility.showControlWhen(this.html.find(".use-surenc"), rollData.ajustements.surenc.visible && RdDCarac.isActionPhysique(rollData.selectedCarac));
HtmlUtility.showControlWhen(this.html.find(".utilisation-moral"), rollData.use.appelAuMoral);
HtmlUtility.showControlWhen(this.html.find(".divAppelAuMoral"), rollData.use.appelAuMoral);
HtmlUtility.showControlWhen(this.html.find(".diffMoral"), rollData.ajustements.moralTotal.used);
// HtmlUtility.showControlWhen(this.html.find(".diffMoral"), rollData.ajustements.moral.used);
// Mise à jour valeurs
this.html.find(".dialog-roll-title").text(this._getTitle(rollData));
this.html.find("[name='mortalite']").prop('checked', rollData.mortalite == 'non-mortel');
this.html.find(".dmg-arme-actor").text(dmgText);
this.html.find("input.check-mortalite").prop('checked', rollData.dmg.mortalite == 'non-mortel');
this.html.find("label.dmg-arme-actor").text(rollData.dmg.mortalite == 'empoignade'? 'empoignade': Misc.toSignedString(rollData.dmg.total) );
this.html.find("label.arme-mortalite").text(rollData.dmg.mortalite);
// this.html.find("[name='dmg-arme-actor']").text(rollData.dmg.mortalite == 'empoignade'? 'empoignade': Misc.toSignedString(rollData.dmg.total) );
// this.html.find("[name='arme-mortalite']").text(rollData.dmg.mortalite);
this.html.find("div.placeholder-ajustements").empty().append(adjustements);
this.html.find("div.placeholder-resolution").empty().append(resolutionTable)
}
@@ -336,16 +331,19 @@ export class RdDRoll extends Dialog {
return carac;
}
const compName = rollData.competence.name;
if (rollData.draconicList && rollData.selectedSort) {
return compName + " - " + rollData.selectedSort.name;
}
// If a weapon is there, add it in the title
const niveau = Misc.toSignedString(rollData.competence.system.niveau)
if (compName == carac) {
// cas des créatures
return carac + " Niveau " + niveau
return `${carac} Niveau ${niveau}`
}
const armeTitle = (rollData.arme) ? " (" + rollData.arme.name + ") " : "";
return carac + "/" + compName + armeTitle + " Niveau " + niveau
if (rollData.draconicList && rollData.selectedSort) {
// cas de lancer de sort
return `${rollData.competence.name} Niveau ${niveau} ${rollData.selectedSort.name}`
}
if (rollData.arme && rollData.arme.name != compName) {
// ajouter l'arme au titre si son nom n'est pas la compétence
return `${carac} / ${compName} (${rollData.arme.name}) Niveau ${niveau}`
}
return `${carac} / ${compName} Niveau ${niveau}`
}
}

View File

@@ -2,7 +2,6 @@ import { SHOW_DICE } from "./constants.js";
import { RollDataAjustements } from "./rolldata-ajustements.js";
import { RdDUtility } from "./rdd-utility.js";
import { TMRUtility } from "./tmr-utility.js";
import { tmrConstants } from "./tmr-constants.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { RdDTMRRencontreDialog } from "./rdd-tmr-rencontre-dialog.js";
import { ChatUtility } from "./chat-utility.js";
@@ -39,7 +38,9 @@ export class RdDTMRDialog extends Dialog {
title: "Terres Médianes de Rêve",
content: html,
buttons: {
closeButton: { label: "Fermer", callback: html => this.close(html) }
closeButton: {
label: "Fermer", callback: html => this.close()
}
},
default: "closeButton"
}
@@ -63,6 +64,7 @@ export class RdDTMRDialog extends Dialog {
this.rencontreState = 'aucune';
this.pixiApp = new PIXI.Application({ width: 720, height: 860 });
this.pixiTMR = new PixiTMR(this, this.pixiApp);
this.subdialog = undefined
this.callbacksOnAnimate = [];
if (!this.viewOnly) {
@@ -73,6 +75,31 @@ export class RdDTMRDialog extends Dialog {
this.pixiTMR.load((loader, resources) => this.createPixiSprites());
}
async forceTMRDisplay() {
this.bringToTop();
if (this.subdialog) {
this.subdialog.bringToTop();
}
}
async restoreTMRAfterAction() {
this.subdialog = undefined
await this.maximize();
this.bringToTop();
}
forceTMRContinueAction() {
ui.notifications.warn('Vous devez finir votre action avant de continuer dans les TMR');
this.subdialog.bringToTop();
return;
}
setTMRPendingAction(dialog) {
this.subdialog = dialog
if (dialog instanceof Application) {
dialog.bringToTop();
}
}
isDemiReveCache() {
return !game.user.isGM && this.actor.isTMRCache();
}
@@ -174,6 +201,9 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async moveFromKey(move) {
if (this.subdialog) {
return this.forceTMRContinueAction();
}
let oddq = TMRUtility.coordTMRToOddq(this._getActorCoord());
if (move == 'top') oddq.row -= 1;
@@ -198,7 +228,9 @@ export class RdDTMRDialog extends Dialog {
super.activateListeners(html);
this.html = html;
document.getElementById("tmrrow1").insertCell(0).append(this.pixiApp.view);
document.getElementsByClassName("tmr-row")
.item(0)
.insertCell(0).append(this.pixiApp.view);
if (this.viewOnly) {
this.html.find('.lancer-sort').remove();
@@ -209,6 +241,10 @@ export class RdDTMRDialog extends Dialog {
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionnelles.isUsing("appliquer-fatigue"));
HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getActorCoord()));
this.html.find('tr.tmr-row *').click((event) => {
this.subdialog?.bringToTop();
});
// Roll Sort
this.html.find('.lancer-sort').click((event) => {
this.actor.rollUnSort(this._getActorCoord());
@@ -230,7 +266,6 @@ export class RdDTMRDialog extends Dialog {
this.cumulFatigue += this.fatigueParCase;
}
await this.actor.reveActuelIncDec(reveCout);
// Le reste...
this.updateValuesDisplay();
let tmr = TMRUtility.getTMR(this._getActorCoord());
@@ -270,6 +305,10 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async close() {
if (this.subdialog) {
return this.forceTMRContinueAction()
}
this.descenteTMR = true;
if (this.actor.tmrApp) {
this.actor.tmrApp = undefined; // Cleanup reference
@@ -292,6 +331,7 @@ export class RdDTMRDialog extends Dialog {
switch (action) {
case 'derober':
await this.derober();
this.restoreTMRAfterAction();
return;
case 'refouler':
await this.refouler();
@@ -304,6 +344,7 @@ export class RdDTMRDialog extends Dialog {
break;
}
await this.postRencontre(tmr);
this.restoreTMRAfterAction();
}
async derober() {
@@ -359,7 +400,6 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
checkQuitterTMR() {
if (this.actor.isDead()) {
this._tellToGM("Vous êtes mort : vous quittez les Terres médianes !");
this.close();
@@ -530,8 +570,9 @@ export class RdDTMRDialog extends Dialog {
await this.maitriserRencontre();
}
else {
let dialog = new RdDTMRRencontreDialog(this, this.currentRencontre, tmr);
const dialog = new RdDTMRRencontreDialog(this.actor, this.currentRencontre, tmr);
dialog.render(true);
this.setTMRPendingAction(dialog);
}
}
else {
@@ -543,9 +584,12 @@ export class RdDTMRDialog extends Dialog {
_presentCite(tmr) {
const presentCite = this.casesSpeciales.find(c => EffetsDraconiques.presentCites.isCase(c, tmr.coord));
if (presentCite) {
this.minimize();
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;
}
@@ -571,8 +615,6 @@ export class RdDTMRDialog extends Dialog {
presentCite: presentCite
};
await this._tentativeMaitrise(rencontreData);
this.maximize();
this.postRencontre(tmr);
}
@@ -586,7 +628,10 @@ export class RdDTMRDialog extends Dialog {
? TMRUtility.getTMRType(tmr.coord) + " ??"
: tmr.label + " (" + tmr.coord + ")");
const fakeDialogRencontre = { bringToTop: () => { } };
this.setTMRPendingAction(fakeDialogRencontre)
let myRoll = await RdDDice.rollTotal("1dt", { showDice: SHOW_DICE });
this.restoreTMRAfterAction()
if (myRoll == 7) {
this._tellToUser(myRoll + ": Rencontre en " + locTMR);
return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
@@ -776,22 +821,22 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async _maitriserTMR(rollData, callbackMaitrise) {
this.minimize(); // Hide
rollData.isTMRCache = rollData.actor.isTMRCache();
const dialog = await RdDRoll.create(this.actor, rollData,
{
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html',
close: html => { this.maximize(); } // Re-display TMR
},
{
name: rollData.maitrise.verbe, label: rollData.maitrise.action,
callbacks: [
this.actor.createCallbackExperience(),
{ action: r => { this.restoreTMRAfterAction() } },
{ action: callbackMaitrise }
]
}
);
dialog.render(true);
this.setTMRPendingAction(dialog);
}
/* -------------------------------------------- */
@@ -861,7 +906,8 @@ export class RdDTMRDialog extends Dialog {
nettoyerRencontre() {
if (!this.currentRencontre) return; // Sanity check
if (this.currentRencontre.graphics) {
for (let drawRect of this.currentRencontre.graphics) { // Suppression des dessins des zones possibles
for (let drawRect of this.currentRencontre.graphics) {
// Suppression des dessins des zones possibles
this.pixiApp.stage.removeChild(drawRect);
}
}
@@ -894,8 +940,8 @@ export class RdDTMRDialog extends Dialog {
}
/* -------------------------------------------- */
isConnaissanceFleuve(currentTMR, nextTMR) {
return TMRUtility.getTMR(currentTMR).type == 'fleuve' &&
isConnaissanceFleuve(tmrApp, nextTMR) {
return TMRUtility.getTMR(tmrApp).type == 'fleuve' &&
TMRUtility.getTMR(nextTMR).type == 'fleuve' &&
EffetsDraconiques.isConnaissanceFleuve(this.actor);
}
@@ -905,6 +951,9 @@ export class RdDTMRDialog extends Dialog {
if (this.viewOnly) {
return;
}
if (this.subdialog) {
return this.forceTMRContinueAction()
}
let clickOddq = TMRUtility.computeEventOddq(event);
let currentOddq = TMRUtility.coordTMRToOddq(this._getActorCoord());
@@ -971,9 +1020,11 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async _messagerDemiReve(targetCoord) {
/*
TODO: si la case a un sort en réserve, lancer ce sort.
TODO:
Si la case a un sort en réserve, lancer ce sort.
Si la case est le demi-rêve, ne pas lancer de sort.
Si un lancement de sort est en cours, trouver un moyen de réafficher cette fenêtre si on essaie de lancer un sort (ou bloquer le lancer de sort)
Si un lancement de sort est en cours, trouver un moyen de réafficher cette fenêtre
si on essaie de lancer un sort (ou bloquer le lancer de sort)
*/
this.notifierResonanceSigneDraconique(targetCoord);
await this.actor.rollUnSort(targetCoord);
@@ -990,6 +1041,9 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async _deplacerDemiReve(targetCoord, deplacementType) {
if (this.subdialog) {
return this.forceTMRContinueAction()
}
if (this.currentRencontre != 'normal') {
this.nettoyerRencontre();
}
@@ -1039,6 +1093,10 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async positionnerDemiReve(coord) {
if (this.subdialog) {
return this.forceTMRContinueAction()
}
await this.actor.updateCoordTMR(coord);
this.forceDemiRevePositionView();
let tmr = TMRUtility.getTMR(coord);

View File

@@ -2,7 +2,7 @@
export class RdDTMRRencontreDialog extends Dialog {
/* -------------------------------------------- */
constructor(tmrApp, rencontre, tmr) {
constructor(actor, rencontre, tmr) {
const dialogConf = {
title: "Rencontre en TMR!",
content: "Vous rencontrez un " + rencontre.name + " de force " + rencontre.system.force + "<br>",
@@ -28,23 +28,30 @@ export class RdDTMRRencontreDialog extends Dialog {
this.toClose = false;
this.tmr = tmr;
this.tmrApp = tmrApp;
this.actor = actor;
this.rencontre = rencontre;
this.tmrApp.minimize();
}
async onButtonAction(action) {
this.toClose = true;
this.tmrApp.onActionRencontre(action, this.tmr, this.rencontre)
await this.actor.tmrApp?.restoreTMRAfterAction();
this.actor.tmrApp?.onActionRencontre(action, this.tmr, this.rencontre)
}
/* -------------------------------------------- */
close() {
if (this.toClose) {
this.tmrApp.maximize();
return super.close();
async close() {
if (this.actor.tmrApp){
if (this.toClose) {
return await super.close();
}
else {
ui.notifications.info("Vous devez résoudre la rencontre.");
return this.actor.tmrApp.forceTMRContinueAction();
}
}
else {
return await super.close();
}
ui.notifications.info("Vous devez résoudre la rencontre.");
}
}

View File

@@ -245,7 +245,8 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/chat-description.html',
'systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html',
'systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.html',
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html',
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-acteur.hbs',
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-sante.hbs',
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.html',
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html',
'systems/foundryvtt-reve-de-dragon/templates/chat-potionenchantee-chateaudormant.html',

View File

@@ -69,8 +69,8 @@ export const referenceAjustements = {
getValue: (rollData, actor) => -actor.getEncTotal()
},
surenc: {
isVisible: (rollData, actor) => actor.isSurenc(),
isUsed: (rollData, actor) => rollData.use?.surenc,
isVisible: (rollData, actor) => RdDCarac.isActionPhysique(rollData.selectedCarac) && actor.isSurenc(),
isUsed: (rollData, actor) => rollData.use?.surenc && RdDCarac.isActionPhysique(rollData.selectedCarac),
getLabel: (rollData, actor) => 'Sur-encombrement',
getValue: (rollData, actor) => actor.computeMalusSurEncombrement()
},

View File

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

View File

@@ -378,6 +378,9 @@ export class TMRUtility {
// /* -------------------------------------------- */
static computeEventPosition(event) {
if (!event.nativeEvent.target.getBoundingClientRect) {
return { x: 0, y: 0 }
}
const canvasRect = event.nativeEvent.target.getBoundingClientRect();
return {
x: event.nativeEvent.clientX - canvasRect.left,
@@ -389,7 +392,7 @@ export class TMRUtility {
static computeEventOddq(event) {
var { x, y } = TMRUtility.computeEventPosition(event);
return TMRUtility.computeOddq(x, y);
}
}
static computeOddq(x, y) {
const col = Math.floor(x / tmrConstants.cellw); // [From 0 -> 12]

View File

@@ -81,7 +81,7 @@ export class PixiTMR {
sprite.tooltip = new PIXI.Text('', tooltipStyle);
sprite.tooltip.zIndex = tmrTokenZIndex.tooltip;
sprite.isOver = false;
sprite.eventMode = 'dynamic'; // PIXI 7 To be checked
sprite.eventMode = 'static';
sprite
.on('pointermove', event => this.onPointerMove(event, sprite, computeTooltip))
.on('pointerdown', event => this.onClickBackground(event))

View File

@@ -49,12 +49,13 @@ export class PresentCites extends Draconique {
const presents = await game.system.rdd.rencontresTMR.getPresentsCite()
const buttons = {};
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",
content: `La ${this.tmrLabel(casetmr)} vous offre un présent, faites votre choix`,
buttons: buttons
});
d.render(true);
dialog.render(true);
return dialog
}
async ouvrirLePresent(actor, casetmr) {

View File

@@ -1,8 +1,8 @@
{
"id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon",
"version": "11.0.24",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.0.24.zip",
"version": "11.0.28",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.0.28.zip",
"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",
"compatibility": {

View File

@@ -0,0 +1 @@
<h4>C'est au tour de {{alias}} !</h4>

View File

@@ -1,4 +1,4 @@
<h4>C'est au tour de {{alias}} !</h4>
<h4>Résumé de santé pour {{alias}}</h4>
<div data-combatid="{{combatId}}" data-combatmessage="actor-turn-summary">{{blessuresStatus}}</div>
<div>Son état général est de : {{etatGeneral}} {{#if isSonne}} et est <strong>sonné</strong>{{/if}}</div>
{{#if isGrave}}
@@ -6,5 +6,7 @@
{{/if}}
{{#if isCritique}}
<div>{{alias}} souffre d'une <strong>Blessure Critique</strong> : faites un
<a id="chat-jet-vie" class="chat-card-button" data-actorId="{{actorId}}">Jet de Vie.<a></div>
<a class="chat-card-button chat-jet-vie"
data-tokenId="{{tokenId}}"
data-actorId="{{actorId}}">Jet de Vie.<a></div>
{{/if}}

View File

@@ -26,7 +26,7 @@
{{#if (eq dmg.mortalite 'entiteincarnee')}}subit le coup
{{else if mort}}vient de mourir
{{else if blessure}}
{{#if (gt blessure.system.gravite 0)}}subit une blessure {{blessure.system.labelGravite}}
{{#if (gt blessure.system.gravite 0)}}subit une blessure {{blessure.system.label}}
{{else}}subit une contusion
{{~/if~}}
{{else}}s'en sort sans une égratignure

View File

@@ -1,13 +1,29 @@
<form class="skill-roll-dialog">
<img class="chat-icon" src="{{competence.img}}" alt="{{competence.name}}"/>
<h2 class="dialog-roll-title"></h2>
<div class="grid grid-2col">
<div class="flex-group-left">
<img class="chat-icon" src="{{competence.img}}" alt="{{competence.name}}"/>
<div class="flexrow">
<label>Caractéristique</label>
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-select-carac.html"}}
<span>
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-select-carac.html"}}
</span>
</div>
{{#if targetToken}}
<div class="flexrow">
<label>Cible:</label>
<label>
<img class="sheet-competence-img" src="{{targetToken.img}}" title="{{targetToken.name}}" />
{{targetToken.name}}
</label>
</div>
{{/if}}
{{#if ajustements.attaqueDefenseurSurpris.used}}
<div class="flexrow">
<label>{{ajustements.attaqueDefenseurSurpris.label}}</label>
</div>
{{/if}}
{{#if arme}}
{{#if attackerRoll}}
{{#if attackerRoll.tactique}}
@@ -27,41 +43,28 @@
<div class="tooltiptext ttt-ajustements">
<div>
<strong>Charge</strong> : Les longueurs d'armes n'interviennent pas dans la charge, il faut gérer une initiative aléatoire dans ce cas.
<br><strong>Feinte</strong> : Vous devez avoir l'initative sur votre adversaire et y renoncer.
<br>
<strong>Feinte</strong> : Vous devez avoir l'initative sur votre adversaire et y renoncer.
</div>
</div>
</span>
</div>
{{/if}}
{{#if targetToken}}
<div class="flexrow">
Cible: {{targetToken.name}}
<img class="sheet-competence-img" src="{{targetToken.img}}" title="{{targetToken.name}}" />
</div>
{{/if}}
{{#if ajustements.attaqueDefenseurSurpris.used}}
<div class="flexrow">
<label>{{ajustements.attaqueDefenseurSurpris.label}}</label>
</div>
{{/if}}
{{#unless attackerRoll}}
<div class="flexrow">
<label>D&eacute;gats:</label>
{{#if (eq arme.system.mortalite 'non-mortel')}}
<label class="dmg-arme-actor"></label>
{{else if (eq arme.system.mortalite 'empoignade')}}
{{#if (eq arme.system.mortalite 'empoignade')}}
<label>Empoignade</label>
{{else}}
<span>
<input class="attribute-value" type="checkbox" name="motalite" {{#unless (eq mortalite 'mortel')}}checked{{/unless}} />
<label class="dmg-arme-actor"></label>
{{#unless (eq arme.system.mortalite 'non-mortel')}}
<input class="attribute-value check-mortalite" type="checkbox" name="mortalite" {{#unless (eq mortalite 'mortel')}}checked{{/unless}} />
{{/unless}}
<label class="dmg-arme-actor" name="dmg-arme-actor"></label> (<label class="arme-mortalite" name="arme-mortalite"></label>)
</span>
{{/if}}
</div>
{{/unless}}
{{/if}}
{{/if}}
<div class="flexrow"></div>
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-surenc.html"}}
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-enctotal.html"}}
</div>
@@ -75,6 +78,7 @@
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffCondition.html"}}
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-forcer.html"}}
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-moral.html"}}
<div class="flexrow"></div>
<div class="placeholder-ajustements" class="flexrow"></div>
</div>
</div>

View File

@@ -1,6 +1,7 @@
<form class="tmr-dialog">
<h2 class="comptmrdialog" id="tmrDialogTitle" style="visibility: hidden;"></h2>
<table>
<tr id="tmrrow1">
<tr class="tmr-row">
<td>
{{#if (eq mode "visu")}}
<div class="flex-group-center">
@@ -52,6 +53,5 @@
</td>
</tr>
</table>
</form>