11.2.21 - Le questionnement d'Akarlikarlikar #699

Merged
uberwald merged 6 commits from VincentVk/foundryvtt-reve-de-dragon:v11 into v11 2024-05-27 07:17:11 +02:00
20 changed files with 107 additions and 78 deletions

View File

@ -1,11 +1,16 @@
# 11.2
## 11.2.20 - Le soulagement d'Akarlikarlikar
## 11.2.21 - Le questionnement d'Akarlikarlikar
- Une confirmation spécifique est demandée pour monter dans les terres médianes en cas de rencontre en attente
- L'expérience en caractéristique sur les jets de chance et rêve actuels est mise dans la caractéristique correspondante
- Les effets s'appliquent correctement sur les créatures
- La date et l'heure (draconiques) sont affichées dans les messages du tchat
- L'option 'ajout de la difficulté d'attaque à l'encaissement est affichée comme un modificateur d'encaissement
- Les options d'encaissement alternative fonctionnent avec la validation du gardien
## 11.2.20 - Le soulagement d'Akarlikarlikar
- L'option "ajout de la difficulté d'attaque à l'encaissement" est affichée comme un modificateur d'encaissement
- Les options d'encaissement alternatives fonctionnent avec la validation de l'encaissement par le gardien
- La fenêtre d'astrologie du gardien affiche toutes les heures lues par un personnage
- Si aucune expérience n'est gagnée, les autres effets à appliquer (comme la récupération de seuil après avoir vaincu un rêve de Dragon) s'appliquent normalement
- Les tooltips de Foundry sont maintenant lisibles
- Les tooltips de Foundry sont lisibles
- On n'accorde plus les entités de cauchemar deux fois quand le gardien valide les encaissements
- Les messages de récupération de rêve en cas de Rêve de Dragon sont clarifiés

View File

@ -16,7 +16,6 @@ import { RdDItem } from "./item.js";
import { RdDItemBlessure } from "./item/blessure.js";
import { RdDEmpoignade } from "./rdd-empoignade.js";
import { RdDBaseActorSangSheet } from "./actor/base-actor-sang-sheet.js";
import { ChatUtility } from "./chat-utility.js";
import { RdDCoeur } from "./coeur/rdd-coeur.js";
/* -------------------------------------------- */
@ -43,7 +42,6 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
{
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
effects: this.actor.effects.map(e => foundry.utils.deepClone(e)),
limited: this.actor.limited,
owner: this.actor.isOwner,
biographie: await TextEditor.enrichHTML(this.actor.system.biographie, { async: true }),

View File

@ -991,25 +991,33 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
buildTMRInnaccessible() {
const tmrInnaccessibles = this.filterItems(it => Draconique.isCaseTMR(it) &&
EffetsDraconiques.isInnaccessible(it));
return tmrInnaccessibles.map(it => it.system.coord);
return this.items[TYPES.casetmr]
.filter(it => EffetsDraconiques.isInnaccessible(it))
.map(it => it.system.coord)
}
/* -------------------------------------------- */
getTMRRencontres() {
return this.itemTypes['rencontre'];
getRencontresTMR() {
return this.itemTypes[TYPES.rencontre];
}
/* -------------------------------------------- */
async deleteTMRRencontreAtPosition() {
const demiReve = this.getDemiReve()
let rencontreIds = this.items.filter(it => it.type == 'rencontre' && it.system.coord == demiReve).map(it => it.id);
async deleteRencontreTMRAtPosition() {
const rencontreIds = this.itemTypes[TYPES.rencontre].filter(this.filterRencontreTMRDemiReve()).map(it => it.id)
if (rencontreIds.length > 0) {
await this.deleteEmbeddedDocuments('Item', rencontreIds);
await this.deleteEmbeddedDocuments('Item', rencontreIds)
}
}
getRencontreTMREnAttente() {
return this.itemTypes[TYPES.rencontre].find(this.filterRencontreTMRDemiReve())
}
filterRencontreTMRDemiReve() {
const position = this.getDemiReve()
return it => it.system.coord == position
}
/* -------------------------------------------- */
async addTMRRencontre(currentRencontre) {
const toCreate = currentRencontre.toObject();
@ -2353,6 +2361,8 @@ export class RdDActor extends RdDBaseActorSang {
static _getComposantsCaracDerivee(caracName) {
switch (Grammar.toLowerCaseNoAccent(caracName)) {
case 'reve-actuel': case 'reve actuel': return ['reve']
case 'chance-actuelle': case 'chance actuelle': return ['chance']
case 'vie': return ['constitution']
case 'tir': return ['vue', 'dexterite']
case 'lancer': return ['force', 'dexterite', 'vue']
@ -2423,22 +2433,29 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
async displayTMR(mode = "normal") {
if (this.tmrApp) {
ui.notifications.warn("Vous êtes déja dans les TMR....");
this.tmrApp.forceTMRDisplay();
ui.notifications.warn("Vous êtes déja dans les TMR....")
this.tmrApp.forceTMRDisplay()
return
}
if (mode != 'visu' && this.getEffect(STATUSES.StatusDemiReve)) {
ui.notifications.warn("Le joueur ou le MJ est déja dans les Terres Médianes avec ce personnage ! Visualisation uniquement");
ui.notifications.warn("Les personnage est déjà dans les Terres Médianes, elles s'affichent en visualisation")
mode = "visu"; // bascule le mode en visu automatiquement
}
if (mode == 'visu') {
await this._doDisplayTMR(mode)
}
else {
const rencontre = this.getRencontreTMREnAttente();
const settingConfirmer = rencontre ? "confirmation-tmr-rencontre" : "confirmation-tmr";
const messageRencontre = rencontre ? `<p>Vous devrez combattre ${rencontre.system.genre == 'f' ? 'la' : 'le'} ${rencontre.name} de ${rencontre.system.force} points de Rêve</p>` : '';
RdDConfirm.confirmer({
bypass: mode == 'visu',
settingConfirmer: "confirmation-tmr",
content: `<p>Voulez vous monter dans les TMR en mode ${mode}?</p>`,
settingConfirmer: settingConfirmer,
content: `<p>Voulez vous monter dans les TMR en mode ${mode}?</p>` + messageRencontre,
title: 'Confirmer la montée dans les TMR',
buttonLabel: 'Monter dans les TMR',
onAction: async () => await this._doDisplayTMR(mode)
});
})
}
}
async _doDisplayTMR(mode) {
@ -2967,9 +2984,6 @@ export class RdDActor extends RdDBaseActorSang {
}
}
/* -------------------------------------------- */
isEffectAllowed(effectId) { return true }
/* -------------------------------------------- */
async onPreUpdateItem(item, change, options, id) {
if (item.isCompetencePersonnage() && item.system.defaut_carac && item.system.xp) {

View File

@ -180,7 +180,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
}
/* -------------------------------------------- */
isEffectAllowed(effectId) { return true }
isEffectAllowed(effectId) { return false }
getEffects(filter = e => true) {
return this.getEmbeddedCollection("ActiveEffect").filter(filter);

View File

@ -269,6 +269,8 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
return this.getEffect(STATUSES.StatusStunned);
}
isEffectAllowed(effectId) { return true }
/* -------------------------------------------- */
async computeEtatGeneral() { this.system.compteurs.etat.value = this.malusVie() + this.malusFatigue() + this.malusEthylisme() }
getEtatGeneral(options = { ethylisme: false }) { return this.system.compteurs.etat.value }

View File

@ -37,7 +37,8 @@ export class RdDBaseActorSheet extends ActorSheet {
system: this.actor.system,
description: await TextEditor.enrichHTML(this.actor.system.description, { async: true }),
notesmj: await TextEditor.enrichHTML(this.actor.system.notesmj, { async: true }),
options: RdDSheetUtility.mergeDocumentRights(this.options, this.actor, this.isEditable)
options: RdDSheetUtility.mergeDocumentRights(this.options, this.actor, this.isEditable),
effects: this.actor.effects
}
RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);

View File

@ -8,7 +8,6 @@ import { RdDAudio } from "../rdd-audio.js";
import { RdDConfirm } from "../rdd-confirm.js";
import { RdDUtility } from "../rdd-utility.js";
import { SystemCompendiums } from "../settings/system-compendiums.js";
import { APP_ASTROLOGIE_REFRESH } from "../sommeil/app-astrologie.js";
export class RdDBaseActor extends Actor {
@ -16,7 +15,7 @@ export class RdDBaseActor extends Actor {
return Object.entries(carac)
.filter(it => Grammar.equalsInsensitive(it[1].label, name))
.map(it => it[0])
.find(it => it);
.find(it => it)
}
static $findCaracByName(carac, name) {
const caracList = Object.entries(carac);

View File

@ -33,10 +33,6 @@ export class RdDCreature extends RdDBaseActorSang {
}
}
isEffectAllowed(effectId) {
return [STATUSES.StatusComma].includes(effectId);
}
isEntiteAccordee(attacker) {
if (this.isEntite([ENTITE_INCARNE])) {
let resonnance = this.system.sante.resonnance

View File

@ -1,5 +1,6 @@
import { Misc } from "./misc.js";
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js";
/**
@ -163,4 +164,17 @@ export class ChatUtility {
return game.messages.get(chatMessageId);
}
static async onRenderChatMessage(chatMessage, html, data) {
const rddTimestamp = chatMessage.getFlag(SYSTEM_RDD, 'rdd-timestamp')
if (rddTimestamp) {
const timestamp = new RdDTimestamp(rddTimestamp);
const timestampData = timestamp.toCalendrier();
const dateHeure = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/common/date-heure.hbs', timestampData);
html.find('header.message-header .message-sender').after(dateHeure)
}
}
static async onCreateChatMessage(chatMessage, options, id) {
await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp());
}
}

View File

@ -177,7 +177,7 @@ export class RdDItem extends Item {
constructor(docData, context = {}) {
if (!context.rdd?.ready) {
mergeObject(context, { rdd: { ready: true } });
foundry.utils.mergeObject(context, { rdd: { ready: true } });
const ItemConstructor = game.system.rdd.itemClasses[docData.type];
if (ItemConstructor) {
if (!docData.img) {

View File

@ -4,11 +4,6 @@ import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
export class RdDConfirm {
/* -------------------------------------------- */
static confirmer(options, autresActions) {
options.bypass = options.bypass || !(options.settingConfirmer == undefined || ReglesOptionnelles.isUsing(options.settingConfirmer));
if (options.bypass) {
options.onAction();
}
else {
let buttons = {
"action": RdDConfirm._createButtonAction(options),
"cancel": RdDConfirm._createButtonCancel()
@ -27,7 +22,6 @@ export class RdDConfirm {
};
new Dialog(dialogDetails, { width: 150 * Object.keys(buttons).length }).render(true);
}
}
static _createButtonCancel() {
return { icon: '<i class="fas fa-times"></i>', label: "Annuler" };

View File

@ -212,7 +212,7 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
loadRencontres() {
this.rencontresExistantes = this.actor.getTMRRencontres();
this.rencontresExistantes = this.actor.getRencontresTMR();
}
/* -------------------------------------------- */
@ -382,7 +382,7 @@ export class RdDTMRDialog extends Dialog {
async refouler() {
console.log("-> refouler", this.currentRencontre);
await this.actor.ajouterRefoulement(this.currentRencontre.system.refoulement, `${this.currentRencontre.system.genre == 'f' ? 'une' : 'un'} ${this.currentRencontre.name}`);
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary
await this.actor.deleteRencontreTMRAtPosition()
this.updateTokens();
this.updateValuesDisplay();
this.nettoyerRencontre();
@ -392,7 +392,7 @@ export class RdDTMRDialog extends Dialog {
async ignorerRencontre() {
console.log("-> ignorer", this.currentRencontre);
this._tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name);
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary
await this.actor.deleteRencontreTMRAtPosition()
this.updateTokens();
this.updateValuesDisplay();
this.nettoyerRencontre();
@ -446,7 +446,7 @@ export class RdDTMRDialog extends Dialog {
async maitriserRencontre() {
console.log("-> maitriser", this.currentRencontre);
await this.actor.deleteTMRRencontreAtPosition();
await this.actor.deleteRencontreTMRAtPosition()
this.updateTokens();
let rencontreData = {

View File

@ -99,8 +99,9 @@ export class RdDUtility {
static afficheContenu = {}
/* -------------------------------------------- */
static async init() {
Hooks.on("renderChatMessage", async (app, html, msg) => RdDUtility.onRenderChatMessage(app, html, msg));
Hooks.on('renderChatLog', (log, html, chatLog) => RdDUtility.chatListeners(html));
Hooks.on("renderChatMessage", async (app, html, msg) => await ChatUtility.onRenderChatMessage(app, html, msg))
Hooks.on("createChatMessage", async (chatMessage, options, id) => await ChatUtility.onCreateChatMessage(chatMessage, options, id))
Hooks.on('renderChatLog', (log, html, chatLog) => RdDUtility.chatListeners(html))
}
/* -------------------------------------------- */
@ -206,6 +207,7 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/voyage/fatigue-actor.hbs',
'systems/foundryvtt-reve-de-dragon/templates/voyage/option-vitesse-fatigue.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/timestamp.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/date-heure.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/periodicite.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/enum-duree.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/compendium-link.hbs',
@ -890,10 +892,4 @@ export class RdDUtility {
}
}
/*-------------------------------------------- */
static async onRenderChatMessage(app, html, msg) {
// TODO
//console.log(app, html, msg);
}
}

View File

@ -26,6 +26,7 @@ const listeReglesOptionnelles = [
{ group: 'Confirmations', name: 'confirmer-combat-sans-cible', descr: "Confirmer avant une attaque sans cible", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-tmr', descr: "Confirmer pour monter dans les TMR", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-tmr-rencontre', descr: "Confirmer pour monter dans les TMR avec rencontre en attente", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-refouler', descr: "Confirmer avant de refouler", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-vider', descr: "Confirmer pour vider l'équipement", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-supprimer-lien-acteur', descr: "Confirmer pour détacher un animal/suivant/véhicule", scope: "client"},

View File

@ -18,8 +18,8 @@ const rddStatusEffects = [
{ rdd: true, id: STATUSES.StatusStunned, label: 'EFFECT.StatusStunned', icon: 'icons/svg/stoned.svg', "duration.rounds": 1 },
{ rdd: true, id: STATUSES.StatusBleeding, label: 'EFFECT.StatusBleeding', icon: 'icons/svg/blood.svg' },
{ rdd: true, id: STATUSES.StatusProne, label: 'EFFECT.StatusProne', icon: 'icons/svg/falling.svg' },
{ rdd: true, id: STATUSES.StatusGrappling, tint: '#33cc33', label: 'EFFECT.StatusGrappling', icon: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.svg' },
{ rdd: true, id: STATUSES.StatusGrappled, tint: '#ff9900', label: 'EFFECT.StatusGrappled', icon: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.svg' },
{ rdd: true, id: STATUSES.StatusGrappling, tint: '#33cc33', label: 'EFFECT.StatusGrappling', icon: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.webp' },
{ rdd: true, id: STATUSES.StatusGrappled, tint: '#ff9900', label: 'EFFECT.StatusGrappled', icon: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.webp' },
{ rdd: true, id: STATUSES.StatusRestrained, label: 'EFFECT.StatusRestrained', icon: 'icons/svg/net.svg' },
{ rdd: true, id: STATUSES.StatusUnconscious, label: 'EFFECT.StatusUnconscious', icon: 'icons/svg/unconscious.svg' },
{ rdd: true, id: STATUSES.StatusBlind, label: 'EFFECT.StatusBlind', icon: 'icons/svg/blind.svg' },
@ -65,7 +65,7 @@ export class StatusEffects extends FormApplication {
static valeurSurprise(effect, isCombat) {
if (statusSurpriseTotale.intersects(effect.statuses)) {
return 2;
return 2
}
if (statusDemiSurprise.intersects(effect.statuses)) {
return 1
@ -110,7 +110,7 @@ export class StatusEffects extends FormApplication {
static get defaultOptions() {
const options = super.defaultOptions;
mergeObject(options, {
foundry.utils.mergeObject(options, {
id: "status-effects",
template: "systems/foundryvtt-reve-de-dragon/templates/settings/status-effects.html",
height: 800,

View File

@ -231,6 +231,7 @@ export class RdDTimestamp {
get annee() { return Math.floor(this.indexDate / RDD_JOURS_PAR_AN) }
get mois() { return Math.floor(Misc.modulo(this.indexDate, RDD_JOURS_PAR_AN) / RDD_JOURS_PAR_MOIS) }
get nomMois() { return Math.floor(Misc.modulo(this.indexDate, RDD_JOURS_PAR_AN) / RDD_JOURS_PAR_MOIS) }
get jour() { return Misc.modulo(Misc.modulo(this.indexDate, RDD_JOURS_PAR_AN), RDD_JOURS_PAR_MOIS) }
get heure() { return Math.floor(this.indexMinute / RDD_MINUTES_PAR_HEURES) }
get minute() { return Misc.modulo(this.indexMinute, RDD_MINUTES_PAR_HEURES) }

View File

@ -16,7 +16,7 @@ export class Rencontre extends Draconique {
return pixiTMR.sprite(this.code(), {
zIndex: tmrTokenZIndex.rencontre,
decallage: pixiTMR.sizes.decallage(0, 0),
taille: () => pixiTMR.sizes.twoThird,
taille: () => pixiTMR.sizes.full,
})
}
}

View File

@ -1527,6 +1527,11 @@ div.control-icon.token-hud-icon {
font-size: 1rem;
}
.chat-message header.message-header .heure-rdd {
font-size: 0.7rem;
flex-grow: 3;
}
.chat-message.whisper {
background: rgba(220,220,210,0.75);
border: 2px solid #545469;

View File

@ -1,8 +1,8 @@
{
"id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon",
"version": "11.2.20",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.2.20.zip",
"version": "11.2.21",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.2.21.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,3 @@
<span class="message-metadata heure-rdd">
{{this.jourDuMois}} {{this.mois.label}} - {{timestamp-imgSigne this.heure}}
</span>