Compare commits

...

16 Commits

Author SHA1 Message Date
9ff68884ce Merge pull request 'v11.1.6 - Les dissections de Werther de Zloth' (#682) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#682
2023-11-12 22:15:26 +01:00
09986115b8 Version 11.1.6 2023-11-12 21:18:52 +01:00
511ee5f241 Fix: encaissement joueur à valider par MJ 2023-11-12 21:18:07 +01:00
306d7c2150 Fix: délai de guérison après rétrogradation
Lorsqu'une blessure critique/grave rétrograde naturellement, le délai
avant le jet de récupération suivant est correctement augmenté.
2023-11-12 21:17:38 +01:00
5624bb1bf3 Merge pull request 'Fix: ajout de compétences aux créatures' (#681) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#681
2023-11-12 16:35:40 +01:00
b588c5f7f8 Fix: ajout de compétences aux créatures 2023-11-12 15:06:58 +01:00
6de34178b3 Sync version 2023-11-12 00:35:51 +01:00
0c90fba346 Merge pull request 'Préparation 11.1.5' (#680) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#680
2023-11-12 00:35:06 +01:00
f43b7ac651 Préparation Changelog 11.1.5 2023-11-12 00:33:25 +01:00
ac436bbb25 Fix: Recevoir une queue annulait l'insomnie 2023-11-12 00:24:42 +01:00
9093eadb23 Fix: urgence draconique 2023-11-12 00:22:29 +01:00
5821fc611f Fix: case pour trou noir 2023-11-11 22:33:51 +01:00
381242c8d0 Fix: le jet de vie indique la mort
Jusque là, le 20 indiquait la mort, mais ne diminuait pas la vie
en dessous de - SConst

Désormais:
- la vie passe à -SConst - 1 sur 20 au jet de vie
- Le message indique que le personnage est mort si sa vie est
  inférieure à -SConst
- le jet de vie n'est pas fait si le personnage est déjà mort
2023-11-11 21:30:25 +01:00
3ca33e85b7 Fix case pour réserve extensible 2023-11-11 21:30:02 +01:00
01399e922a Suppression de certains warnings 2023-11-11 20:38:16 +01:00
c6afb8d445 Fix demande defense 2023-11-11 20:23:07 +01:00
16 changed files with 92 additions and 53 deletions

View File

@@ -1,5 +1,24 @@
# v11.0
## v11.1.3 - Werther de Zloth l'Onirique
## v11.1.6 - Les dissections de Werther de Zloth
- Fix: on peut de nouveau donner des compétences aux créatures
- Fix: le délai de guérison d'une blessure rétrogradée est correctement appliqué
- Fix: l'encaissement à valider par le MJ fonctionne de nouveau
## v11.1.5 - Werther de Zloth l'Onirique
- Fixes:
- la demande de défense ne marchait plus
- la tête réserve extensible crée bien une case de réserve extensible (à modifier)
- le souffle trou noir ajoute bien une case de trou noir
- la queue urgence draconique ne se transforme plus en idée fixe s'il y a des sorts en réserve
- l'ajout d'une nouvelle queue ne supprime plus l'insomnie
- Amélioration des jets de vie
- un 1 sur le jet de vie est une réussite même si le personnage est dans le coma
- le temps avant le prochain jet est calculé et affiché
- un 20 sur le jet de vie signifie la mort immédiate
- si on dépasse le S.Const, le personnage est bien indiqué comme mort
- pas de jets de vie pour les morts
## v11.1.4 - Werther de Zloth l'Onirique
- Ajout du facteur de significative à côté du pourcentage dans le résultat des jets de dés pour rappeler que le pourcentage n'est pas diviasé
- Fix: dans les TMRs, les tooltips affichent bien les informations de tous les effets sur la case
- Fix: la fatigue et l'éthylisme sont de nouveau pris en compte dans le calcul de l'éthylisme

View File

@@ -348,7 +348,7 @@ export class RdDActorSheet extends RdDBaseActorReveSheet {
});
this.html.find('.jet-vie').click(async event => {
this.actor.jetVie();
this.actor.jetDeVie();
});
this.html.find('.jet-endurance').click(async event => {
await this.jetEndurance();

View File

@@ -256,7 +256,7 @@ export class RdDActor extends RdDBaseActorSang {
const isMaladeEmpoisonne = maladiesPoisons.length > 0;
this._messageRecuperationMaladiePoisons(maladiesPoisons, message);
await this._recuperationBlessures(message, isMaladeEmpoisonne);
await this._recupererBlessures(message, isMaladeEmpoisonne);
await this._recupererVie(message, isMaladeEmpoisonne);
}
@@ -323,7 +323,9 @@ export class RdDActor extends RdDBaseActorSang {
}
async setInfoSommeilInsomnie() {
await this.update({ 'system.sommeil.insomnie': EffetsDraconiques.isSujetInsomnie(this) });
if (EffetsDraconiques.isSujetInsomnie(this)) {
await this.update({ 'system.sommeil.insomnie': true });
}
}
async setInfoSommeilMoral(situationMoral) {
@@ -365,7 +367,7 @@ export class RdDActor extends RdDBaseActorSang {
}
/* -------------------------------------------- */
async _recuperationBlessures(message, isMaladeEmpoisonne) {
async _recupererBlessures(message, isMaladeEmpoisonne) {
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))
@@ -659,7 +661,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
async sortMisEnReserve(sort, draconic, coord, ptreve) {
await this.createEmbeddedDocuments("Item", [{
type: 'sortreserve',
type: TYPES.sortreserve,
name: sort.name,
img: sort.img,
system: { sortid: sort._id, draconic: (draconic?.name ?? sort.system.draconic), ptreve: ptreve, coord: coord, heurecible: 'Vaisseau' }

View File

@@ -427,7 +427,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'appliquerEncaissement',
method: 'encaisserDommages',
args: [rollData, show, attackerId]
});
return;

View File

@@ -60,13 +60,21 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
return this.system.sante.vie.value < -this.getSConst()
}
nbBlessuresLegeres() {
return this.itemTypes[TYPES.blessure].filter(it => it.isLegere()).length;
}
nbBlessuresGraves() {
return this.itemTypes[TYPES.blessure].filter(it => it.isGrave()).length;
}
nbBlessuresCritiques() {
return this.itemTypes[TYPES.blessure].filter(it => it.isCritique()).length;
}
/* -------------------------------------------- */
computeResumeBlessure() {
const blessures = this.filterItems(it => it.system.gravite > 0, 'blessure')
const nbLegeres = blessures.filter(it => it.isLegere()).length;
const nbGraves = blessures.filter(it => it.isGrave()).length;
const nbCritiques = blessures.filter(it => it.isCritique()).length;
const nbLegeres = this.nbBlessuresLegeres()
const nbGraves = this.nbBlessuresGraves()
const nbCritiques = this.nbBlessuresCritiques()
if (nbLegeres + nbGraves + nbCritiques == 0) {
return "Aucune blessure";
@@ -206,26 +214,36 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
}
/* -------------------------------------------- */
async jetVie() {
let roll = await RdDDice.roll("1d20");
let msgText = "Jet de Vie : " + roll.total + " / " + this.system.sante.vie.value + "<br>";
if (roll.total <= this.system.sante.vie.value) {
msgText += "Jet réussi, pas de perte de point de vie (prochain jet dans 1 round pour 1 critique, SC minutes pour une grave)";
if (roll.total == 1) {
msgText += "La durée entre 2 jets de vie est multipliée par 20 (20 rounds pour une critique, SCx20 minutes pour une grave)";
}
} else {
msgText += "Jet échoué, vous perdez 1 point de vie";
await this.santeIncDec("vie", -1);
if (roll.total == 20) {
msgText += "Votre personnage est mort !!!!!";
}
async jetDeVie() {
if (this.isDead()) {
ChatMessage.create({ content: `Jet de Vie: ${this.name} est déjà mort, ce n'est pas la peine d'en rajouter !!!!!`, whisper: ChatMessage.getWhisperRecipients(this.name) });
return
}
const message = {
content: msgText,
whisper: ChatMessage.getWhisperRecipients(this.name)
};
ChatMessage.create(message);
const jetDeVie = await RdDDice.roll("1d20");
const sConst = this.getSConst();
const vie = this.system.sante.vie.value;
const isCritique = this.nbBlessuresCritiques() > 0;
const isGrave = this.nbBlessuresGraves();
const isEchecTotal = jetDeVie.total == 20;
const isSuccess = jetDeVie.total == 1 || jetDeVie.total <= vie;
const perte = isSuccess ? 0 : 1 + (isEchecTotal ? vie + sConst : 0)
const prochainJet = (jetDeVie.total == 1 && vie > 0 ? 20 : 1) * (isCritique ? 1 : isGrave > 0 ? sConst : 0)
let msgText = `Jet de Vie: <strong>${jetDeVie.total} / ${vie}</strong>`
if (isSuccess) {
msgText += "<br>Réussi, pas de perte de point de vie."
} else {
msgText += `<br>Echoué, perte ${perte} point de vie`;
await this.santeIncDec("vie", -perte);
}
if (this.isDead()) {
msgText += `<br><strong>${this.name} est mort !!!!</strong>`;
}
else if (prochainJet > 0) {
msgText += `<br>Prochain jet de vie dans ${prochainJet} ${isCritique ? 'round' : 'minute'}${prochainJet > 1 ? 's' : ''} ${isCritique ? '(état critique)' : '(état grave)'}`
}
ChatMessage.create({ content: msgText, whisper: ChatMessage.getWhisperRecipients(this.name) });
}
/* -------------------------------------------- */
@@ -238,7 +256,6 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
return { jetEndurance, sonne }
}
async finDeRoundBlessures() {
const nbGraves = this.filterItems(it => it.isGrave(), 'blessure').length;
if (nbGraves > 0) {

View File

@@ -1,4 +1,5 @@
import { ENTITE_INCARNE } from "../constants.js";
import { TYPES } from "../item.js";
import { STATUSES } from "../settings/status-effects.js";
import { RdDBaseActorSang } from "./base-actor-sang.js";

View File

@@ -115,7 +115,10 @@ export class RdDItemBlessure extends RdDItem {
if (!isMaladeEmpoisonne && rolled.isSuccess && this.peutRetrograder(graviteMoindre, moindres)) {
message.content += ` -- une blessure ${label} cicatrise`;
mergeObject(update, {
system: { gravite: graviteMoindre, fin: { indexDate: timestamp.addJours(graviteMoindre).indexDate } }
system: {
gravite: graviteMoindre,
temporel: { fin: { indexDate: timestamp.addJours(graviteMoindre).indexDate } }
}
});
}
else {

View File

@@ -518,7 +518,7 @@ export class RdDCombat {
let token = canvas.tokens.placeables.find(t => t.id == tokenId)
const actor = token?.actor ?? game.actors.get(actorId);
if (actor?.isOwner) {
actor.jetVie();
actor.jetDeVie();
}
}

View File

@@ -16,6 +16,7 @@ import { RdDDice } from "./rdd-dice.js";
import { STATUSES } from "./settings/status-effects.js";
import { RdDRencontre } from "./item/rencontre.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { TYPES } from "./item.js";
/* -------------------------------------------- */
@@ -110,11 +111,11 @@ export class RdDTMRDialog extends Dialog {
}
get sortsReserve() {
return this.actor.itemTypes['sortreserve'];
return this.actor.itemTypes[TYPES.sortreserve];
}
getSortsReserve(coord) {
return this.actor.itemTypes['sortreserve'].filter(// Reserve sur une case fleuve ou normale
return this.actor.itemTypes[TYPES.sortreserve].filter(// Reserve sur une case fleuve ou normale
TMRUtility.getTMR(coord).type == 'fleuve'
? it => TMRUtility.getTMR(it.system.coord).type == 'fleuve'
: it => it.system.coord == coord
@@ -166,7 +167,7 @@ export class RdDTMRDialog extends Dialog {
return this.rencontresExistantes.map(it => this._tokenRencontre(it));
}
_getTokensSortsReserve() {
return this.actor.itemTypes['sortreserve'].map(it => this._tokenSortEnReserve(it));
return this.actor.itemTypes[TYPES.sortreserve].map(it => this._tokenSortEnReserve(it));
}
/* -------------------------------------------- */

View File

@@ -13,8 +13,8 @@ export class ReserveExtensible extends Draconique {
manualMessage() { return "Vous pouvez re-configurer votre Réserve extensible" }
async onActorCreateOwned(actor, tete) {
const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
const tmr = await TMRUtility.getTMRAleatoire(it => !(it.type == 'fleuve' || existants.includes(it.system.coord)));
await this.createCaseTmr(actor, "Nouvelle Réserve extensible", tmr, tete.id);
const selectedTMR = await TMRUtility.getTMRAleatoire(tmr => !(tmr.type == 'fleuve' || existants.includes(tmr.coord)));
await this.createCaseTmr(actor, "Nouvelle Réserve extensible", selectedTMR, tete.id);
}
code() { return 'reserve_extensible' }

View File

@@ -14,8 +14,8 @@ export class TrouNoir extends Draconique {
async onActorCreateOwned(actor, souffle) {
const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
const tmr = await TMRUtility.getTMRAleatoire(it => !(TMRUtility.isCaseHumide(it) || existants.includes(it.system.coord)));
await this.createCaseTmr(actor, 'Trou noir: ' + tmr.label, tmr, souffle.id);
const selectedTMR = await TMRUtility.getTMRAleatoire(tmr => !(TMRUtility.isCaseHumide(tmr) || existants.includes(tmr.coord)));
await this.createCaseTmr(actor, 'Trou noir: ' + selectedTMR.label, selectedTMR, souffle.id);
}
code() { return 'trounoir' }

View File

@@ -8,15 +8,11 @@ import { Draconique } from "./draconique.js";
export class UrgenceDraconique extends Draconique {
constructor() {
super();
}
type() { return 'queue' }
match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('urgence draconique'); }
manualMessage() { return false }
async onActorCreateOwned(actor, queue) {
const coordSortsReserve = (actor.system.reve.reserve?.list.map(it => it.coord)) ?? [];
const coordSortsReserve = actor.itemTypes[TYPES.sortreserve].map(it => it.system.coord) ?? [];
if (coordSortsReserve.length == 0) {
// La queue se transforme en idée fixe
const ideeFixe = await RdDRollTables.getIdeeFixe();
@@ -26,7 +22,6 @@ export class UrgenceDraconique extends Draconique {
});
await actor.createEmbeddedDocuments('Item', [ideeFixe]);
await actor.deleteEmbeddedDocuments('Item', [queue.id]);
return;
}
else {
const demiReve = actor.getDemiReve();

View File

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

@@ -2,11 +2,11 @@
{{#if effects}}
{{#each effects as |effect key|}}
<span class="active-effect" data-effect="{{effect.flags.core.statusId}}">
<img class="button-effect-img {{#if @root.options.isGM}}delete-active-effect{{/if}}" src="{{effect.icon}}" alt="{{localize effect.label}}" width="24" height="24" />
<img class="button-effect-img {{#if @root.options.isGM}}delete-active-effect{{/if}}" src="{{effect.icon}}" alt="{{localize effect.name}}" width="24" height="24" />
</span>
{{/each}}
{{#if calc.surprise}}<span>{{calc.surprise}}!</span>{{/if}}
{{else}}
{{else}}
Aucun effet actif
{{/if}}
</div>

View File

@@ -66,6 +66,7 @@
Encaisser à {{plusMoins dmg.total}}
{{#if (eq dmg.mortalite 'non-mortel')~}}
(non-mortel) !
{{/if}}
</a>
</span>
</div>

View File

@@ -7,8 +7,8 @@
{{else}}
<input class="resource-content select-effect" type="checkbox" name="{{effect.id}}" {{#if effect.active}}checked{{/if}}/>
{{/if}}
<img class="button-effect-img" height="16" width="16" src="{{effect.icon}}" alt="{{localize effect.label}}" />
<label>{{localize effect.label}}</label>
<img class="button-effect-img" height="16" width="16" src="{{effect.icon}}" alt="{{localize effect.name}}" />
<label>{{localize effect.name}}</label>
</li>
{{/each}}
</ul>