## 11.2.20 - Le soulagement d'Akarlikarlikar #698

Merged
uberwald merged 7 commits from VincentVk/foundryvtt-reve-de-dragon:v11 into v11 2024-05-13 17:24:52 +02:00
12 changed files with 196 additions and 171 deletions

View File

@ -1,4 +1,14 @@
# 11.2 # 11.2
## 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 alternative fonctionnent avec la validation du 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
- 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
## 11.2.19 - Les hémorroïdes d'Akarlikarlikar ## 11.2.19 - Les hémorroïdes d'Akarlikarlikar
- La validation des jets d'encaissement par le Gardien fonctionne de nouveau - La validation des jets d'encaissement par le Gardien fonctionne de nouveau

View File

@ -347,7 +347,7 @@ export class RdDActor extends RdDBaseActorSang {
const timestamp = game.system.rdd.calendrier.getTimestamp() const timestamp = game.system.rdd.calendrier.getTimestamp()
const blessures = this.filterItems(it => it.system.gravite > 0, TYPES.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(async b => b.recuperationBlessure({
actor: this, actor: this,
timestamp, timestamp,
message, message,
@ -429,7 +429,7 @@ export class RdDActor extends RdDBaseActorSang {
let jetsReve = []; let jetsReve = [];
let dormi = await this.dormirDesHeures(jetsReve, message, heures, options); let dormi = await this.dormirDesHeures(jetsReve, message, heures, options);
if (jetsReve.length > 0) { if (jetsReve.length > 0) {
message.content += `Vous récupérez ${jetsReve.map(it => it < 0 ? '(dragon)' : it).reduce(Misc.joining("+"))} Points de rêve. `; message.content += `Vous récupérez ${jetsReve.map(it => it < 0 ? '0 (réveil)' : it).reduce(Misc.joining("+"))} Points de rêve. `;
} }
if (dormi.etat == 'eveil') { if (dormi.etat == 'eveil') {
await this.reveilReveDeDragon(message, dormi.heures); await this.reveilReveDeDragon(message, dormi.heures);
@ -450,7 +450,6 @@ export class RdDActor extends RdDBaseActorSang {
} }
async reveilReveDeDragon(message, heures) { async reveilReveDeDragon(message, heures) {
message.content += 'Vous êtes réveillé par un Rêve de Dragon.';
const restant = Math.max(this.system.sommeil?.heures - heures, 0) const restant = Math.max(this.system.sommeil?.heures - heures, 0)
if (restant > 0) { if (restant > 0) {
await this.update({ 'system.sommeil': { heures: restant } }); await this.update({ 'system.sommeil': { heures: restant } });
@ -1333,7 +1332,7 @@ export class RdDActor extends RdDBaseActorSang {
} }
await RdDResolutionTable.rollData(ethylismeData.jetVie); await RdDResolutionTable.rollData(ethylismeData.jetVie);
this._appliquerExperienceRollData(ethylismeData.jetVie); this._gererExperience(ethylismeData.jetVie);
RollDataAjustements.calcul(ethylismeData.jetVie, this); RollDataAjustements.calcul(ethylismeData.jetVie, this);
if (ethylismeData.jetVie.rolled.isSuccess) { if (ethylismeData.jetVie.rolled.isSuccess) {
ethylisme.nb_doses++; ethylisme.nb_doses++;
@ -1365,7 +1364,7 @@ export class RdDActor extends RdDBaseActorSang {
finalLevel: Number(ethylisme.value) + Number(this.system.compteurs.moral.value) finalLevel: Number(ethylisme.value) + Number(this.system.compteurs.moral.value)
} }
await RdDResolutionTable.rollData(ethylismeData.jetVolonte); await RdDResolutionTable.rollData(ethylismeData.jetVolonte);
this._appliquerExperienceRollData(ethylismeData.jetVolonte); this._gererExperience(ethylismeData.jetVolonte);
RollDataAjustements.calcul(ethylismeData.jetVolonte, this); RollDataAjustements.calcul(ethylismeData.jetVolonte, this);
} }
} }
@ -1549,7 +1548,7 @@ export class RdDActor extends RdDBaseActorSang {
const content = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-gain-xp.html`, { const content = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-gain-xp.html`, {
actor: this, actor: this,
xpData xpData
}); })
if (hideChatMessage) { if (hideChatMessage) {
ChatUtility.blindMessageToGM({ content: content }); ChatUtility.blindMessageToGM({ content: content });
} }
@ -1779,13 +1778,13 @@ export class RdDActor extends RdDBaseActorSang {
}; };
RollDataAjustements.calcul(rollData, this); RollDataAjustements.calcul(rollData, this);
await RdDResolutionTable.rollData(rollData); await RdDResolutionTable.rollData(rollData);
this._appliquerExperienceRollData(rollData); this._gererExperience(rollData);
await RdDResolutionTable.displayRollData(rollData, this) await RdDResolutionTable.displayRollData(rollData, this)
return rollData.rolled; return rollData.rolled;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_appliquerExperienceRollData(rollData) { _gererExperience(rollData) {
const callback = this.createCallbackExperience(); const callback = this.createCallbackExperience();
if (callback.condition(rollData)) { if (callback.condition(rollData)) {
callback.action(rollData); callback.action(rollData);
@ -2269,7 +2268,7 @@ export class RdDActor extends RdDBaseActorSang {
async _appliquerExperience(rolled, caracName, competence, jetResistance) { async _appliquerExperience(rolled, caracName, competence, jetResistance) {
// Pas d'XP // Pas d'XP
if (!rolled.isPart || rolled.finalLevel >= 0) { if (!rolled.isPart || rolled.finalLevel >= 0) {
return undefined; return []
} }
if (this.checkDesirLancinant()) { if (this.checkDesirLancinant()) {
// Cas de désir lancinant, pas d'expérience sur particulière // Cas de désir lancinant, pas d'expérience sur particulière
@ -2277,7 +2276,7 @@ export class RdDActor extends RdDBaseActorSang {
content: `Vous souffrez au moins d'un Désir Lancinant, vous ne pouvez pas gagner d'expérience sur une Particulière tant que le désir n'est pas assouvi`, content: `Vous souffrez au moins d'un Désir Lancinant, vous ne pouvez pas gagner d'expérience sur une Particulière tant que le désir n'est pas assouvi`,
whisper: ChatMessage.getWhisperRecipients(this.name) whisper: ChatMessage.getWhisperRecipients(this.name)
}); });
return undefined; return []
} }
let xp = Math.abs(rolled.finalLevel); let xp = Math.abs(rolled.finalLevel);
@ -2365,26 +2364,25 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async resetNombresAstraux() { async deleteNombresAstraux() {
const deletions = this.itemTypes['nombreastral'].map(it => it._id); const deletions = this.itemTypes['nombreastral'].map(it => it._id);
await this.deleteEmbeddedDocuments("Item", deletions); await this.deleteEmbeddedDocuments("Item", deletions);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async ajouteNombreAstral(callData) { async ajouteNombreAstral(date, nbAstral, isValid) {
const indexDate = Number.parseInt(callData.date); const indexDate = Number.parseInt(date);
// Ajout du nombre astral // Ajout du nombre astral
const item = { const item = {
name: "Nombre Astral", type: "nombreastral", system: name: "Nombre Astral", type: "nombreastral", system:
{ {
value: callData.nbAstral, value: nbAstral,
istrue: callData.isvalid, istrue: isValid,
jourindex: indexDate, jourindex: indexDate,
jourlabel: RdDTimestamp.formatIndexDate(indexDate) jourlabel: RdDTimestamp.formatIndexDate(indexDate)
} }
}; };
await this.createEmbeddedDocuments("Item", [item]); await this.createEmbeddedDocuments("Item", [item]);
game.system.rdd.calendrier.notifyChangeNombresAstraux();
} }
async supprimerAnciensNombresAstraux() { async supprimerAnciensNombresAstraux() {

View File

@ -421,36 +421,35 @@ export class RdDBaseActorReve extends RdDBaseActor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async encaisser() { await RdDEncaisser.encaisser(this) } async encaisser() { await RdDEncaisser.encaisser(this) }
async encaisserDommagesRemote(rollData, attackerId, show) {
const attacker = game.actors.get(attackerId);
await this.encaisserDommages(rollData, attacker, show)
}
async encaisserDommages(rollData, attacker = undefined, show = undefined) { async encaisserDommages(rollData, attacker = undefined, show = undefined) {
if (attacker && !await attacker.accorder(this, 'avant-encaissement')) { if (attacker && !await attacker.accorder(this, 'avant-encaissement')) {
return; return;
} }
const attackerId = attacker?.id;
if (ReglesOptionnelles.isUsing('validation-encaissement-gr') && !game.user.isGM) {
RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'encaisserDommagesRemote',
args: [rollData, attackerId, show]
});
return;
}
const armure = await this.computeArmure(rollData); const armure = await this.computeArmure(rollData);
if (ReglesOptionnelles.isUsing('validation-encaissement-gr')) { if (ReglesOptionnelles.isUsing('validation-encaissement-gr')){
DialogValidationEncaissement.validerEncaissement(this, rollData, armure, await this.encaisserDommagesValidationGR(rollData, armure, attacker?.id, show);
jet => this.$onEncaissement(jet, show, attacker)); }
}
else { else {
const jet = await RdDUtility.jetEncaissement(rollData, armure, { showDice: SHOW_DICE }); const jet = await RdDUtility.jetEncaissement(rollData, armure, { showDice: SHOW_DICE });
await this.$onEncaissement(jet, show, attacker); await this.$onEncaissement(jet, show, attacker);
} }
} }
async encaisserDommagesValidationGR(rollData, armure, attackerId, show) {
if (!game.user.isGM) {
RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'encaisserDommagesValidationGR',
args: [rollData, armure, attackerId, show]
});
} else {
const attacker = game.actors.get(attackerId);
DialogValidationEncaissement.validerEncaissement(this, rollData, armure,
jet => this.$onEncaissement(jet, show, attacker));
}
}
async $onEncaissement(jet, show, attacker) { async $onEncaissement(jet, show, attacker) {
await this.onAppliquerJetEncaissement(jet, attacker); await this.onAppliquerJetEncaissement(jet, attacker);
await this.$afficherEncaissement(jet, show); await this.$afficherEncaissement(jet, show);

View File

@ -42,13 +42,6 @@ export class RdDBaseActor extends Actor {
switch (sockmsg.msg) { switch (sockmsg.msg) {
case "msg_remote_actor_call": case "msg_remote_actor_call":
return RdDBaseActor.onRemoteActorCall(sockmsg.data, sockmsg.userId); return RdDBaseActor.onRemoteActorCall(sockmsg.data, sockmsg.userId);
case "msg_reset_nombre_astral":
game.user.character.resetNombresAstraux();
game.system.rdd.calendrier.notifyChangeNombresAstraux();
return;
case "msg_refresh_nombre_astral":
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
return;
} }
} }

View File

@ -5,6 +5,7 @@ import { Monnaie } from "./item-monnaie.js";
import { RdDItem, TYPES } from "./item.js"; import { RdDItem, TYPES } from "./item.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js"; import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { RdDRaretes } from "./item/raretes.js"; import { RdDRaretes } from "./item/raretes.js";
import { RdDCalendrier } from "./time/rdd-calendrier.js";
class Migration { class Migration {
get code() { return "sample"; } get code() { return "sample"; }
@ -70,17 +71,17 @@ class _10_0_16_MigrationSortsReserve extends Migration {
get version() { return "10.0.16"; } get version() { return "10.0.16"; }
async migrate() { async migrate() {
await game.actors const actors = game.actors.filter((actor) => actor.type == "personnage" && (actor.system.reve?.reserve?.list?.length ?? 0 > 0))
.filter((actor) => actor.type == "personnage") Promise.all(actors.map(async it => await this.convertirSortsReserveActeur(it)))
.filter((actor) => actor.system.reve?.reserve?.list?.length ?? 0 > 0) }
.forEach(async (actor) => {
const sortsReserve = actor.system.reve.reserve.list.map(this.conversionSortReserve); async convertirSortsReserveActeur(actor) {
console.log(`${LOG_HEAD} Migration des sorts en réserve de ${actor.name}`, sortsReserve); const sortsReserve = actor.system.reve.reserve.list.map(this.conversionSortReserve);
await actor.createEmbeddedDocuments("Item", sortsReserve, { console.log(`${LOG_HEAD} Migration des sorts en réserve de ${actor.name}`, sortsReserve);
renderSheet: false, await actor.createEmbeddedDocuments("Item", sortsReserve, {
}); renderSheet: false,
await actor.update({ 'system.reve.reserve': undefined }) });
}); await actor.update({ 'system.reve.reserve': undefined });
} }
conversionSortReserve(it) { conversionSortReserve(it) {
@ -507,13 +508,28 @@ class _10_7_19_PossessionsEntiteVictime extends Migration {
} }
migratePossession(it) { migratePossession(it) {
return { _id: it.id, return {
_id: it.id,
'system.entite.actorid': it.system.possesseurid, 'system.entite.actorid': it.system.possesseurid,
'system.victime.actorid': it.system.possedeid 'system.victime.actorid': it.system.possedeid
} }
} }
} }
class _11_2_20_MigrationAstrologie extends Migration {
get code() { return "migration-astrologie" }
get version() { return "11.2.20" }
async migrate() {
const nombresAstraux = game.system.rdd.calendrier.getNombresAstraux()
nombresAstraux.forEach(na => {
na.lectures = na.valeursFausses
na.valeursFausses = undefined
})
await game.system.rdd.calendrier.setNombresAstraux(nombresAstraux)
}
}
export class Migrations { export class Migrations {
static getMigrations() { static getMigrations() {
return [ return [
@ -532,6 +548,7 @@ export class Migrations {
new _10_7_0_MigrationBlessures(), new _10_7_0_MigrationBlessures(),
new _10_7_19_CategorieCompetenceCreature(), new _10_7_19_CategorieCompetenceCreature(),
new _10_7_19_PossessionsEntiteVictime(), new _10_7_19_PossessionsEntiteVictime(),
new _11_2_20_MigrationAstrologie(),
]; ];
} }
@ -546,7 +563,10 @@ export class Migrations {
} }
migrate() { migrate() {
const currentVersion = game.settings.get(SYSTEM_RDD, "systemMigrationVersion"); let currentVersion = game.settings.get(SYSTEM_RDD, "systemMigrationVersion")
if (currentVersion.startsWith("v")) {
currentVersion = currentVersion.substring(1)
}
if (isNewerVersion(game.system.version, currentVersion)) { if (isNewerVersion(game.system.version, currentVersion)) {
// if (true) { /* comment previous and uncomment here to test before upgrade */ // if (true) { /* comment previous and uncomment here to test before upgrade */
const migrations = Migrations.getMigrations().filter(m => isNewerVersion(m.version, currentVersion)); const migrations = Migrations.getMigrations().filter(m => isNewerVersion(m.version, currentVersion));
@ -554,7 +574,7 @@ export class Migrations {
migrations.sort((a, b) => this.compareVersions(a, b)); migrations.sort((a, b) => this.compareVersions(a, b));
migrations.forEach(async (m) => { migrations.forEach(async (m) => {
ui.notifications.info( ui.notifications.info(
`Executing migration ${m.code}: version ${currentVersion} is lower than ${m.version}` `${LOG_HEAD} Executing migration ${m.code}: version ${currentVersion} is lower than ${m.version}`
); );
await m.migrate(); await m.migrate();
}); });
@ -562,9 +582,7 @@ export class Migrations {
`Migrations done, version will change to ${game.system.version}` `Migrations done, version will change to ${game.system.version}`
); );
} else { } else {
console.log( console.log(`${LOG_HEAD} No migration needeed, version will change to ${game.system.version}`
LOG_HEAD +
`No migration needeed, version will change to ${game.system.version}`
); );
} }
@ -574,7 +592,7 @@ export class Migrations {
game.system.version game.system.version
); );
} else { } else {
console.log(LOG_HEAD + `No system version changed`); console.log(`${LOG_HEAD} No system version changed`);
} }
} }

View File

@ -18,6 +18,7 @@ import { RdDRaretes } from "./item/raretes.js";
import { RdDEmpoignade } from "./rdd-empoignade.js"; import { RdDEmpoignade } from "./rdd-empoignade.js";
import { ExperienceLog } from "./actor/experience-log.js"; import { ExperienceLog } from "./actor/experience-log.js";
import { RdDCoeur } from "./coeur/rdd-coeur.js"; import { RdDCoeur } from "./coeur/rdd-coeur.js";
import { APP_ASTROLOGIE_REFRESH } from "./sommeil/app-astrologie.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
// This table starts at 0 -> niveau -10 // This table starts at 0 -> niveau -10
@ -549,49 +550,54 @@ export class RdDUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async jetEncaissement(rollData, armure, options = { showDice: HIDE_DICE }) { static async jetEncaissement(rollData, armure, options = { showDice: HIDE_DICE }) {
let formula = "2d10"; const diff = Math.abs(rollData.diffLibre);
let formula = RdDUtility.formuleEncaissement(diff, options)
const roll = await RdDDice.roll(formula, options);
// Chaque dé fait au minmum la difficulté libre RdDUtility.remplaceDeMinParDifficulte(roll, diff, options);
if (ReglesOptionnelles.isUsing('degat-minimum-malus-libre')) {
if (rollData.diffLibre < 0) {
let valeurMin = Math.abs(rollData.diffLibre);
formula += "min" + valeurMin;
}
}
// Chaque dé fait au minmum la difficulté libre
if (ReglesOptionnelles.isUsing('degat-ajout-malus-libre')) {
if (rollData.diffLibre < 0) {
let valeurMin = Math.abs(rollData.diffLibre);
formula += "+" + valeurMin;
}
}
let roll = await RdDDice.roll(formula, options);
// 1 dé fait au minmum la difficulté libre
if (ReglesOptionnelles.isUsing('degat-minimum-malus-libre-simple')) {
if (rollData.diffLibre < 0) {
let valeurMin = Math.abs(rollData.diffLibre);
if (roll.terms[0].results[0].result < valeurMin) {
roll.terms[0].results[0].result = valeurMin;
} else if (roll.terms[0].results[1].result < valeurMin) {
roll.terms[0].results[1].result = valeurMin;
}
roll._total = roll.terms[0].results[0].result + roll.terms[0].results[1].result;
}
}
return await RdDUtility.prepareEncaissement(rollData, roll, armure); return await RdDUtility.prepareEncaissement(rollData, roll, armure);
} }
static remplaceDeMinParDifficulte(roll, diff, options) {
if (!ReglesOptionnelles.isUsing('degat-minimum-malus-libre-simple')) {
return
}
// 1 dé fait au minmum la difficulté libre
const total = options.forceDiceResult?.total;
if (total) {
const reste = Math.max(total - diff, 1)
roll.terms[0].number = reste + diff
}
else {
if (roll.terms[0].results[0].result < diff) {
roll.terms[0].results[0].result = diff;
} else if (roll.terms[0].results[1].result < diff) {
roll.terms[0].results[1].result = diff;
}
roll._total = roll.terms[0].results[0].result + roll.terms[0].results[1].result;
}
}
static formuleEncaissement(diff, options) {
// Chaque dé fait au minimum la difficulté libre
if (ReglesOptionnelles.isUsing('degat-minimum-malus-libre')) {
return `2d10min${diff}`
}
return '2d10'
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async prepareEncaissement(rollData, roll, armure) { static async prepareEncaissement(rollData, roll, armure) {
const jetTotal = roll.total + rollData.dmg.total - armure; // La difficulté d'ataque s'ajoute aux dégâts
let encaissement = RdDUtility._selectEncaissement(jetTotal, rollData.dmg.mortalite); const bonusDegatsDiffLibre = ReglesOptionnelles.isUsing('degat-ajout-malus-libre') ? Math.abs(rollData.diffLibre ?? 0) : 0
let over20 = Math.max(jetTotal - 20, 0); const jetTotal = roll.total + rollData.dmg.total - armure + bonusDegatsDiffLibre
const encaissement = RdDUtility._selectEncaissement(jetTotal, rollData.dmg.mortalite);
const over20 = Math.max(jetTotal - 20, 0);
encaissement.dmg = rollData.dmg; encaissement.dmg = rollData.dmg;
encaissement.dmg.loc = rollData.dmg.loc ?? await RdDUtility.getLocalisation(this.type); encaissement.dmg.loc = rollData.dmg.loc ?? await RdDUtility.getLocalisation(this.type);
encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;'; encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;';
encaissement.dmg.bonusDegatsDiffLibre = bonusDegatsDiffLibre
encaissement.roll = roll; encaissement.roll = roll;
encaissement.armure = armure; encaissement.armure = armure;
encaissement.penetration = rollData.arme?.system.penetration ?? 0; encaissement.penetration = rollData.arme?.system.penetration ?? 0;
@ -620,21 +626,15 @@ export class RdDUtility {
return perte.total; return perte.total;
} }
/* -------------------------------------------- */
static async responseNombreAstral(callData) {
let actor = game.actors.get(callData.id);
actor.ajouteNombreAstral(callData);
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static onSocketMessage(sockmsg) { static onSocketMessage(sockmsg) {
switch (sockmsg.msg) { switch (sockmsg.msg) {
case "msg_gm_chat_message": case "msg_gm_chat_message":
return ChatUtility.handleGMChatMessage(sockmsg.data); return ChatUtility.handleGMChatMessage(sockmsg.data);
case "msg_app_astrologie_refresh":
return Hooks.callAll(APP_ASTROLOGIE_REFRESH);
case "msg_request_nombre_astral": case "msg_request_nombre_astral":
return game.system.rdd.calendrier.requestNombreAstral(sockmsg.data); return game.system.rdd.calendrier.requestNombreAstral(sockmsg.data);
case "msg_response_nombre_astral":
return RdDUtility.responseNombreAstral(sockmsg.data);
case "msg_tmr_move": case "msg_tmr_move":
let actor = game.actors.get(sockmsg.data.actorId); let actor = game.actors.get(sockmsg.data.actorId);
if (actor.isOwner || game.user.isGM) { if (actor.isOwner || game.user.isGM) {

View File

@ -31,7 +31,6 @@ export class AppAstrologie extends Application {
constructor(actor, options = {}) { constructor(actor, options = {}) {
super(options); super(options);
this.actor = actor; this.actor = actor;
this.hookReference = Hooks.on(APP_ASTROLOGIE_REFRESH, () => this.refreshAstrologie());
} }
getData(options) { getData(options) {
@ -85,9 +84,10 @@ export class AppAstrologie extends Application {
const nbAstral = calendrier.getNombreAstral() const nbAstral = calendrier.getNombreAstral()
const heures = RdDTimestamp.heures(); const heures = RdDTimestamp.heures();
return { return {
ajustementsActors:game.actors.filter(actor => actor.isPersonnageJoueur()) ajustementsActors: game.actors.filter(actor => actor.isPersonnageJoueur())
.map(actor => this.getAjustementActor(actor, nbAstral, heures)), .map(actor => this.getAjustementActor(actor, nbAstral, heures)),
nombresAstraux: calendrier.getNombresAstraux().map(na => this.getDetailNombreAstral(na)) nombresAstraux: game.system.rdd.calendrier.getNombresAstraux()
.map(na => this.getDetailNombreAstral(na))
} }
} }
return {} return {}
@ -107,12 +107,15 @@ export class AppAstrologie extends Application {
const detail = foundry.utils.duplicate(nombreAstral); const detail = foundry.utils.duplicate(nombreAstral);
const timestamp = new RdDTimestamp({ indexDate: nombreAstral.index }); const timestamp = new RdDTimestamp({ indexDate: nombreAstral.index });
detail.date = { mois: timestamp.mois, jour: timestamp.jour + 1 }; detail.date = { mois: timestamp.mois, jour: timestamp.jour + 1 };
detail.valeursFausses.forEach(fausse => fausse.actorName = game.actors.get(fausse.actorId).name ?? "Inconnu"); detail.lectures.forEach(lecture => lecture.actorName = game.actors.get(lecture.actorId).name ?? "Inconnu");
return detail; return detail;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
activateListeners(html) { activateListeners(html) {
if (!this.hookReference){
this.hookReference = Hooks.on(APP_ASTROLOGIE_REFRESH, () => this.refreshAstrologie());
}
super.activateListeners(html); super.activateListeners(html);
this.html = html; this.html = html;
this.html.find('select[name="signe-astral"]').change(event => { this.html.find('select[name="signe-astral"]').change(event => {
@ -145,8 +148,7 @@ export class AppAstrologie extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
async onRebuild() { async onRebuild() {
game.system.rdd.calendrier.resetNombresAstraux(); await game.system.rdd.calendrier.resetNombresAstraux();
await game.system.rdd.calendrier.rebuildNombresAstraux(); await game.system.rdd.calendrier.rebuildNombresAstraux();
} }
@ -195,6 +197,8 @@ export class AppAstrologie extends Application {
} }
refreshAstrologie() { refreshAstrologie() {
this.count = (this.count ?? 0)+1
console.log(`Refreshing ${this.count}`);
this.render(true) this.render(true)
} }

View File

@ -51,7 +51,6 @@ export class RdDCalendrier extends Application {
this.timestamp = RdDTimestamp.getWorldTime(); this.timestamp = RdDTimestamp.getWorldTime();
if (Misc.isUniqueConnectedGM()) { // Uniquement si GM if (Misc.isUniqueConnectedGM()) { // Uniquement si GM
RdDTimestamp.setWorldTime(this.timestamp); RdDTimestamp.setWorldTime(this.timestamp);
this.nombresAstraux = this.getNombresAstraux();
this.rebuildNombresAstraux(); // Ensure always up-to-date this.rebuildNombresAstraux(); // Ensure always up-to-date
} }
Hooks.on('updateSetting', async (setting, update, options, id) => this.onUpdateSetting(setting, update, options, id)); Hooks.on('updateSetting', async (setting, update, options, id) => this.onUpdateSetting(setting, update, options, id));
@ -108,7 +107,10 @@ export class RdDCalendrier extends Application {
this.timestamp = RdDTimestamp.getWorldTime(); this.timestamp = RdDTimestamp.getWorldTime();
this.positionAiguilles() this.positionAiguilles()
this.render(false); this.render(false);
Hooks.callAll(APP_ASTROLOGIE_REFRESH); Hooks.callAll(APP_ASTROLOGIE_REFRESH)
}
if (setting.key == SYSTEM_RDD + '.' + "liste-nombre-astral") {
Hooks.callAll(APP_ASTROLOGIE_REFRESH)
} }
} }
@ -167,7 +169,11 @@ export class RdDCalendrier extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
getNombresAstraux() { getNombresAstraux() {
return game.settings.get(SYSTEM_RDD, "liste-nombre-astral") ?? []; return game.settings.get(SYSTEM_RDD, "liste-nombre-astral") ?? []
}
async setNombresAstraux(nombresAstraux) {
await game.settings.set(SYSTEM_RDD, "liste-nombre-astral", nombresAstraux)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -225,20 +231,15 @@ export class RdDCalendrier extends Application {
const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: HIDE_DICE, rollMode: "selfroll" }); const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: HIDE_DICE, rollMode: "selfroll" });
return { return {
nombreAstral: nombreAstral, nombreAstral: nombreAstral,
valeursFausses: [], lectures: [],
index: indexDate index: indexDate
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
resetNombresAstraux() { async resetNombresAstraux() {
this.nombresAstraux = []; await Promise.all(game.actors.filter(it => it.type == "personnage").map(async it => await it.deleteNombresAstraux()))
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", []); await this.setNombresAstraux([])
game.socket.emit(SYSTEM_SOCKET_ID, {
msg: "msg_reset_nombre_astral",
data: {}
});
} }
/** /**
@ -251,39 +252,30 @@ export class RdDCalendrier extends Application {
if (indexDate == undefined) { if (indexDate == undefined) {
indexDate = this.timestamp.indexDate; indexDate = this.timestamp.indexDate;
} }
this.nombresAstraux = this.getNombresAstraux(); const nombresAstraux = this.getNombresAstraux()
let astralData = this.nombresAstraux.find((nombreAstral, i) => nombreAstral.index == indexDate); let astralData = nombresAstraux.find(it => it.index == indexDate);
return astralData?.nombreAstral ?? 0; return astralData?.nombreAstral ?? 0;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rebuildNombresAstraux() { async rebuildNombresAstraux() {
if (Misc.isUniqueConnectedGM()) { if (Misc.isUniqueConnectedGM()) {
let newList = []; const nombresAstraux = this.getNombresAstraux()
let newNombresAstraux = [];
for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) { for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) {
let dayIndex = this.timestamp.indexDate + i; let dayIndex = this.timestamp.indexDate + i;
let na = this.nombresAstraux.find(n => n.index == dayIndex); let na = nombresAstraux.find(it => it.index == dayIndex);
if (na) { if (na) {
newList[i] = na; newNombresAstraux[i] = na;
} else { } else {
newList[i] = await this.ajouterNombreAstral(dayIndex); newNombresAstraux[i] = await this.ajouterNombreAstral(dayIndex);
} }
} }
this.nombresAstraux = newList;
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", newList);
game.actors.filter(it => it.isPersonnage()).forEach(actor => actor.supprimerAnciensNombresAstraux()); game.actors.filter(it => it.isPersonnage()).forEach(actor => actor.supprimerAnciensNombresAstraux());
this.notifyChangeNombresAstraux(); await this.setNombresAstraux(newNombresAstraux);
} }
} }
notifyChangeNombresAstraux() {
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
game.socket.emit(SYSTEM_SOCKET_ID, {
msg: "msg_refresh_nombre_astral",
data: {}
});
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async setNewTimestamp(newTimestamp) { async setNewTimestamp(newTimestamp) {
const oldTimestamp = this.timestamp; const oldTimestamp = this.timestamp;
@ -373,25 +365,22 @@ export class RdDCalendrier extends Application {
request.nbAstral = await RdDDice.rollTotal("1dhr" + request.nbAstral, { request.nbAstral = await RdDDice.rollTotal("1dhr" + request.nbAstral, {
rollMode: "selfroll", showDice: HIDE_DICE rollMode: "selfroll", showDice: HIDE_DICE
}); });
// Mise à jour des nombres astraux du joueur
this.addNbAstralIncorect(request.id, request.date, request.nbAstral);
}
if (Misc.getActiveUser(request.userId)?.isGM) {
RdDUtility.responseNombreAstral(request);
} else {
game.socket.emit(SYSTEM_SOCKET_ID, {
msg: "msg_response_nombre_astral",
data: request
});
} }
// Mise à jour des nombres astraux du joueur
await this.addNbAstralJoueur(actor, request.date, request.nbAstral, request.isValid)
Hooks.callAll(APP_ASTROLOGIE_REFRESH)
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_app_astrologie_refresh", data: {} })
} }
} }
addNbAstralIncorect(actorId, date, nbAstral) { async addNbAstralJoueur(actor, date, nbAstral, isValid) {
const astralData = this.nombresAstraux.find((nombreAstral, i) => nombreAstral.index == date); const nombresAstraux = this.getNombresAstraux()
astralData.valeursFausses.push({ actorId: actorId, nombreAstral: nbAstral }); const astralData = nombresAstraux.find(it => it.index == date)
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", this.nombresAstraux); if (astralData) {
astralData.lectures.push({ actorId: actor.id, nombreAstral: nbAstral });
await this.setNombresAstraux(nombresAstraux);
await actor.ajouteNombreAstral(date, nbAstral, isValid);
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -92,6 +92,8 @@
--background-custom-button-hover: linear-gradient(to bottom, rgb(128, 0, 0) 5%, rgb(62, 1, 1) 100%); --background-custom-button-hover: linear-gradient(to bottom, rgb(128, 0, 0) 5%, rgb(62, 1, 1) 100%);
--background-control-selected: linear-gradient(to bottom, hsla(0, 100%, 25%, 0.5) 5%, hsla(0, 100%, 12%, 0.5) 100%); --background-control-selected: linear-gradient(to bottom, hsla(0, 100%, 25%, 0.5) 5%, hsla(0, 100%, 12%, 0.5) 100%);
--background-tooltip: hsla(60, 12%, 85%, 0.95); --background-tooltip: hsla(60, 12%, 85%, 0.95);
--color-tooltip:hsla(282, 47%, 33%, 0.9);
--color-tooltip-faint:hsla(282, 47%, 66%, 0.5);
--background-error:hsla(16, 100%, 50%, 0.8); --background-error:hsla(16, 100%, 50%, 0.8);
--color-profile-border: hsla(0, 0%, 80%, 0.05); --color-profile-border: hsla(0, 0%, 80%, 0.05);
} }
@ -1943,7 +1945,7 @@ div.calendar-timestamp-edit select.calendar-signe-heure {
padding: 3px; padding: 3px;
} }
aside#tooltip{ aside#tooltip {
background: var(--background-tooltip); background: var(--background-tooltip);
color: var(--color-text-dark-primary); color: var(--color-text-dark-primary);
font-size: 1rem; font-size: 1rem;
@ -1951,6 +1953,15 @@ aside#tooltip{
padding: 0.4rem; padding: 0.4rem;
} }
aside#tooltip span.reference {
color: var(--color-tooltip);
border: 1px solid var(--color-tooltip-faint);
}
aside#tooltip .toolclip p.faint {
color: var(--color-tooltip-faint);
}
.tooltip :is(.ttt-xp,.ttt-levelup) { .tooltip :is(.ttt-xp,.ttt-levelup) {
width: 250px; width: 250px;
background: var(--background-tooltip) !important; background: var(--background-tooltip) !important;

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.2.19", "version": "11.2.20",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.2.19.zip", "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.2.20.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": {

View File

@ -15,33 +15,36 @@
<label class="encaissement-total">{{encaissement.total}}</label> <label class="encaissement-total">{{encaissement.total}}</label>
<div class="tooltiptext ttt-ajustements"> <div class="tooltiptext ttt-ajustements">
<div>Armure: {{encaissement.armure}}</div> <div>Armure: {{encaissement.armure}}</div>
{{#if rollData.dmg.penetration}} {{#if encaissement.dmg.penetration}}
<div>Pénétration: -{{rollData.dmg.penetration}}</div> <div>Pénétration: -{{encaissement.dmg.penetration}}</div>
{{/if}} {{/if}}
<hr> <hr>
{{#if encaissement.dmg.total}} {{#if encaissement.dmg.total}}
<div>+dom encaissement: {{plusMoins rollData.dmg.total}}</div> <div>+dom encaissement: {{plusMoins encaissement.dmg.total}}</div>
{{/if}} {{/if}}
{{#if rollData.dmg.dmgArme}} {{#if encaissement.dmg.dmgArme}}
<div>+dom arme: {{plusMoins rollData.dmg.dmgArme}}</div> <div>+dom arme: {{plusMoins encaissement.dmg.dmgArme}}</div>
{{/if}} {{/if}}
{{#if rollData.dmg.dmgActor}} {{#if encaissement.dmg.dmgActor}}
<div>+dom attaquant: {{plusMoins rollData.dmg.dmgActor}}</div> <div>+dom attaquant: {{plusMoins encaissement.dmg.dmgActor}}</div>
{{/if}} {{/if}}
{{#if rollData.dmg.dmgParticuliere}} {{#if encaissement.dmg.dmgParticuliere}}
<div>+dom particulière: {{plusMoins rollData.dmg.dmgParticuliere}}</div> <div>+dom particulière: {{plusMoins encaissement.dmg.dmgParticuliere}}</div>
{{/if}} {{/if}}
{{#if rollData.dmg.dmgTactique}} {{#if encaissement.dmg.dmgTactique}}
<div>+dom tactique: {{plusMoins rollData.dmg.dmgTactique}}</div> <div>+dom tactique: {{plusMoins encaissement.dmg.dmgTactique}}</div>
{{/if}} {{/if}}
{{#if rollData.dmg.dmgSurprise}} {{#if encaissement.dmg.dmgSurprise}}
<div>+dom surprise: {{plusMoins rollData.dmg.dmgSurprise}}</div> <div>+dom surprise: {{plusMoins encaissement.dmg.dmgSurprise}}</div>
{{/if}}
{{#if encaissement.dmg.bonusDegatsDiffLibre}}
<div>+dom attaque: {{plusMoins encaissement.dmg.bonusDegatsDiffLibre}}</div>
{{/if}} {{/if}}
</div> </div>
</span> </span>
</li> </li>
<li class="flexrow flex-group-left"> <li class="flexrow flex-group-left">
<label>Blessure ({{rollData.dmg.mortalite}})</label> <label>Blessure ({{encaissement.dmg.mortalite}})</label>
<label class="encaissement-blessure">{{encaissement.blessures}}</label> <label class="encaissement-blessure">{{encaissement.blessures}}</label>
</li> </li>
</ul> </ul>

View File

@ -15,8 +15,8 @@
<td class="nombre-astral" data-nombre-astral="{{nba.nombreAstral}}"> <td class="nombre-astral" data-nombre-astral="{{nba.nombreAstral}}">
<ol> <ol>
<b>{{nba.nombreAstral}}</b> <b>{{nba.nombreAstral}}</b>
{{#each nba.valeursFausses as |fausse|}} {{#each nba.lectures as |lecture|}}
<li>{{fausse.actorName}} - {{fausse.nombreAstral}}</li> <li>{{lecture.actorName}} - {{lecture.nombreAstral}}</li>
{{/each}} {{/each}}
</ol> </ol>
</td> </td>