Compare commits

..

33 Commits

Author SHA1 Message Date
928a60f092 Add flags 2023-03-23 17:03:40 +01:00
e5c2f52b0e Merge pull request 'Version 10.7.3 - Les tisanes de Sémolosse' (#637) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: public/foundryvtt-reve-de-dragon#637
2023-03-23 17:02:56 +01:00
f9391523f8 Version 10.7.3
Les tisanes de Sémolosse
2023-03-23 01:44:35 +01:00
55434762f4 Masquer bonus premiers soins si soins complets 2023-03-23 01:43:41 +01:00
5e6ffc7846 Fix: bonus d'herbe de potion non enchantée 2023-03-23 01:42:48 +01:00
3344e20936 Fix: consommation potion enchantée 2023-03-23 01:41:37 +01:00
5a66e4e741 Fix horloge aiguille des heures
L'aiguille des heures pointe sur l'heure au début de l'heure
draconique, comme pour une montre.

Début couronne, l'aiguille des heures et des minutes sont donc
toutes les deux en haut.
2023-03-21 22:00:24 +01:00
d329724d63 Merge pull request '10.7.2 - les maux de dents de Semolosse' (#636) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: public/foundryvtt-reve-de-dragon#636
2023-03-20 23:32:08 +01:00
8a5405c9f5 Version 10.7.2
les maux de dents de Semolosse
2023-03-20 23:29:46 +01:00
ea992aae46 Fix: récupération des blessures 2023-03-20 23:28:25 +01:00
0bfcfec58f Fix jet carac 2023-03-16 23:17:52 +01:00
88e00c59bc Fix actor 2023-03-16 23:12:08 +01:00
d314dc39a0 Fix actor 2023-03-16 23:10:17 +01:00
30bb803da2 Merge pull request 'v10.7.0 - l'os de Sémolosse' (#635) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: public/foundryvtt-reve-de-dragon#635
2023-03-16 23:09:10 +01:00
dd79e16ea5 Version 10.7.0 2023-03-15 01:29:55 +01:00
83e2d56fd4 Boutons soins&blessures 2023-03-15 01:29:48 +01:00
afc23dfa7b Fix: message sans jet d'endurance 2023-03-15 01:29:48 +01:00
3e189cbe5f Ajout des blessures sur encaissement 2023-03-15 01:29:48 +01:00
d0475e8677 Suppression anciennes blessures 2023-03-15 00:41:48 +01:00
a3694c1673 Cleanup 2023-03-15 00:41:47 +01:00
9e6d5856b1 Gestion des soins avancés
- raccourci soins HUD
- edition rapide des Item blessure
- gestion des taches de soins liées aux blessures
2023-03-15 00:41:47 +01:00
acc880b53f Preparation soins HUD 2023-03-15 00:41:47 +01:00
2598ae3489 Ajout item Blessure 2023-03-15 00:35:22 +01:00
4f5fb63751 Tri alphabétique des constantes 2023-03-15 00:35:21 +01:00
d739a7993a rollCaracCompetence avec dialog 2023-03-15 00:35:21 +01:00
41335cd433 Renommage méthode jet sans dialog 2023-03-15 00:35:21 +01:00
e470d76ea0 Méthode de fenêtre de jet partagée 2023-03-15 00:35:21 +01:00
ffccc819f1 Fix: merge d'options sur token 2023-03-15 00:35:21 +01:00
45bfc69b39 Ajout d'option pour informer si pas de cible
Pour le HUD, on peut vouloir utiliser la cible (soins)
2023-03-15 00:23:21 +01:00
79e9358072 Préparation Calendrier avant migration
Les migrations peuvent avoir besoin du temps courant.
Le calendrier est recréé après.
2023-03-15 00:23:21 +01:00
5cab418e62 Merge pull request 'v10.6.25 - fix erreur synchro astrologie/heure' (#634) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: public/foundryvtt-reve-de-dragon#634
2023-03-14 22:41:45 +01:00
7809f7c21a Version 10.6.25 2023-03-14 22:14:04 +01:00
1bac204071 Fix astrologie 2023-03-14 21:56:59 +01:00
41 changed files with 983 additions and 694 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,6 @@
.vscode/settings.json
.idea
.history
todo.md
/.vscode
/ignored/

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
icons/sante/blessure.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
icons/sante/eraflure.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
icons/sante/mort.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -7,47 +7,48 @@
"TypeVehicule": "Véhicule"
},
"ITEM": {
"TypeObjet": "Objet",
"TypeGemme": "Gemme",
"TypeCompetence": "Compétence",
"TypeCompetencecreature": "Compétence de créature",
"TypeMaladie": "Maladie",
"TypePoison": "Poison",
"TypeNombreastral": "Nombre astral",
"TypeTarot": "Carte de tarot",
"TypeCasetmr": "TMR spéciale",
"TypeRencontre": "Rencontre TMR",
"TypeMunition": "Munition",
"TypeMonnaie": "Monnaie",
"TypeHerbe": "Herbe",
"TypePlante": "Plante",
"TypeIngredient": "Ingrédient",
"TypeFaune": "Faune",
"TypeLivre": "Livre",
"TypePotion": "Potion",
"TypeArme": "Arme",
"TypeArmure": "Armure",
"TypeConteneur": "Conteneur",
"TypeNourritureboisson": "Nourriture & boisson",
"TypeService": "Service",
"TypeBlessure": "Blessure",
"TypeCasetmr": "TMR spéciale",
"TypeChant": "Chant",
"TypeCompetence": "Compétence",
"TypeCompetencecreature": "Compétence de créature",
"TypeConteneur": "Conteneur",
"TypeDanse": "Danse",
"TypeMusique": "Musique",
"TypeOeuvre": "Oeuvre",
"TypeTache": "Tâche",
"TypeExtraitpoetique": "Extrait poetique",
"TypeFaune": "Faune",
"TypeGemme": "Gemme",
"TypeHerbe": "Herbe",
"TypeIngredient": "Ingrédient",
"TypeJeu": "Jeu",
"TypeLivre": "Livre",
"TypeMaladie": "Maladie",
"TypeMeditation": "Méditation",
"TypeMonnaie": "Monnaie",
"TypeMunition": "Munition",
"TypeMusique": "Musique",
"TypeNombreastral": "Nombre astral",
"TypeNourritureboisson": "Nourriture & boisson",
"TypeObjet": "Objet",
"TypeOeuvre": "Oeuvre",
"TypeOmbre": "Ombre de Thanatos",
"TypePlante": "Plante",
"TypePoison": "Poison",
"TypePossession": "Possession",
"TypePotion": "Potion",
"TypeQueue": "Queue de Dragon",
"TypeRecettealchimique": "Recette alchimique",
"TypeRecettecuisine": "Recette de cuisine",
"TypeSort": "Sort",
"TypeMeditation": "Méditation",
"TypeRencontre": "Rencontre TMR",
"TypeService": "Service",
"TypeSignedraconique": "Signe draconique",
"TypeQueue": "Queue de Dragon",
"TypeOmbre": "Ombre de Thanatos",
"TypeSouffle": "Souffle de Dragon",
"TypeTete": "Tête de Dragon",
"TypePossession": "Possession",
"TypeSort": "Sort",
"TypeSortreserve": "Sort en réserve",
"TypeExtraitpoetique": "Extrait poetique"
"TypeSouffle": "Souffle de Dragon",
"TypeTache": "Tâche",
"TypeTarot": "Carte de tarot",
"TypeTete": "Tête de Dragon"
},
"EFFECT": {
"StatusStunned": "Sonné",

View File

@@ -13,6 +13,7 @@ import { STATUSES } from "./settings/status-effects.js";
import { MAINS_DIRECTRICES } from "./actor.js";
import { RdDBaseActorSheet } from "./actor/base-actor-sheet.js";
import { RdDItem } from "./item.js";
import { RdDItemBlessure } from "./item/blessure.js";
/* -------------------------------------------- */
/**
@@ -151,42 +152,31 @@ export class RdDActorSheet extends RdDBaseActorSheet {
this.html.find('.creer-tache').click(async event => {
this.createEmptyTache();
});
this.html.find('.creer-tache-blessure-legere').click(async event => {
this.actor.createTacheBlessure('legere');
});
this.html.find('.creer-tache-blessure-grave').click(async event => {
this.actor.createTacheBlessure('grave');
});
this.html.find('.creer-tache-blessure-critique').click(async event => {
this.actor.createTacheBlessure('critique');
});
this.html.find('.creer-tache-blessure-legere').click(async event => RdDItemBlessure.createTacheSoinBlessure(this.actor, 2));
this.html.find('.creer-tache-blessure-grave').click(async event => RdDItemBlessure.createTacheSoinBlessure(this.actor, 4));
this.html.find('.creer-tache-blessure-critique').click(async event => RdDItemBlessure.createTacheSoinBlessure(this.actor, 6));
this.html.find('.creer-blessure-legere').click(async event => RdDItemBlessure.createBlessure(this.actor, 2));
this.html.find('.creer-blessure-grave').click(async event => RdDItemBlessure.createBlessure(this.actor, 4));
this.html.find('.creer-blessure-critique').click(async event => RdDItemBlessure.createBlessure(this.actor, 6));
this.html.find('.creer-une-oeuvre').click(async event => {
this.selectTypeOeuvreToCreate();
});
// Blessure control
this.html.find('.blessure-control').click(async event => {
const tr = this.html.find(event.currentTarget).parents(".item");
let btype = tr.data("blessure-type");
let index = tr.data('blessure-index');
let active = this.html.find(event.currentTarget).data('blessure-active');
//console.log(btype, index, active);
await this.actor.manageBlessureFromSheet(btype, index, active);
this.html.find('.blessure-premierssoins-done').change(async event => {
const blessure = this.getBlessure(event);
await blessure?.setSoinsBlessure({ premierssoins: { done: event.currentTarget.checked } });
});
// Blessure data
this.html.find('.blessure-soins').change(async event => {
const tr = this.html.find(event.currentTarget).parents(".item");
let btype = tr.data('blessure-type');
let index = tr.data('blessure-index');
let psoins = tr.find('.blessure-premiers_soins').val();
let pcomplets = tr.find('.blessure-soins_complets').val();
let jours = tr.find('.blessure-jours').val();
let loc = tr.find('.blessure-localisation').val();
let psdone = tr.find('.blessure-psdone:checked').val();
let scdone = tr.find('.blessure-scdone:checked').val();
console.log(btype, index, psoins, pcomplets, jours, loc, psdone, scdone);
await this.actor.setDataBlessureFromSheet(btype, index, psoins, pcomplets, jours, loc, psdone, scdone);
this.html.find('.blessure-soinscomplets-done').change(async event => {
const blessure = this.getBlessure(event);
await blessure?.setSoinsBlessure({ soinscomplets: { done: event.currentTarget.checked } })
});
this.html.find('.blessure-premierssoins-bonus').change(async event => {
const blessure = this.getBlessure(event);
await blessure?.setSoinsBlessure({ premierssoins: { bonus: Number(event.currentTarget.value) } })
});
this.html.find('.blessure-soinscomplets-bonus').change(async event => {
const blessure = this.getBlessure(event);
await blessure?.setSoinsBlessure({ soinscomplets: { bonus: Number(event.currentTarget.value) } })
});
// Equip Inventory Item
@@ -426,6 +416,12 @@ export class RdDActorSheet extends RdDBaseActorSheet {
});
}
getBlessure(event) {
const itemId = this.html.find(event.currentTarget).parents(".item-blessure").data('item-id');
const blessure = this.actor.getItem(itemId, 'blessure');
return blessure;
}
isCompetenceAffichable(competence) {
return !this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(competence);
}

View File

@@ -26,7 +26,7 @@ import { DialogConsommer } from "./dialog-item-consommer.js";
import { DialogFabriquerPotion } from "./dialog-fabriquer-potion.js";
import { RollDataAjustements } from "./rolldata-ajustements.js";
import { RdDPossession } from "./rdd-possession.js";
import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
import { ENTITE_INCARNE, ENTITE_NONINCARNE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
import { RdDConfirm } from "./rdd-confirm.js";
import { DialogValidationEncaissement } from "./dialog-validation-encaissement.js";
import { RdDRencontre } from "./item/rencontre.js";
@@ -34,8 +34,8 @@ import { Targets } from "./targets.js";
import { DialogRepos } from "./sommeil/dialog-repos.js";
import { RdDBaseActor } from "./actor/base-actor.js";
import { RdDTimestamp } from "./rdd-timestamp.js";
import { RdDItemTache } from "./item-tache.js";
import { APP_ASTROLOGIE_REFRESH, AppAstrologie } from "./sommeil/app-astrologie.js";
import { RdDItemBlessure } from "./item/blessure.js";
import { AppAstrologie } from "./sommeil/app-astrologie.js";
const POSSESSION_SANS_DRACONIC = {
img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp',
@@ -46,7 +46,6 @@ const POSSESSION_SANS_DRACONIC = {
}
};
const PAS_DE_BLESSURE = { "active": false, "psdone": false, "scdone": false, "premiers_soins": 0, "soins_complets": 0, "jours": 0, "loc": "" };
export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre']
/* -------------------------------------------- */
@@ -332,34 +331,42 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
async roll() {
const carac = mergeObject(
duplicate(this.system.carac),
const carac = mergeObject(duplicate(this.system.carac),
{
'reve-actuel': this.getCaracReveActuel(),
'chance-actuelle': this.getCaracChanceActuelle()
});
let rollData = {
await this._openRollDialog({
name: `jet-${this.id}`,
label: `Jet de ${this.name}`,
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll.html',
rollData: {
carac: carac,
selectedCarac: carac.apparence,
selectedCaracName: 'apparence',
competences: this.itemTypes['competence']
};
},
callbackAction: r => this.$onRollCaracResult(r)
});
}
async _openRollDialog({ name, label, template, rollData, callbackAction }) {
const dialog = await RdDRoll.create(this, rollData,
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll.html' },
{ html: template },
{
name: `jet-${this.id}`,
label: `Jet de ${this.name}`,
name: name,
label: label,
callbacks: [
this.createCallbackExperience(),
this.createCallbackAppelAuMoral(),
{ action: r => this._onRollCaracResult(r) }
{ action: callbackAction }
]
}
);
});
dialog.render(true);
}
async prepareChateauDormant(consigne) {
if (consigne.ignorer) {
return;
@@ -395,7 +402,7 @@ export class RdDActor extends RdDBaseActor {
}
await this._recupereChance();
await this.transformerStress();
this.bonusRecuperationPotion = 0; // Reset potion
await this.setBonusPotionSoin(0);
}
await this.resetInfoSommeil()
ChatMessage.create(message);
@@ -406,11 +413,8 @@ export class RdDActor extends RdDBaseActor {
const maladiesPoisons = this._maladiePoisons(message);
const isMaladeEmpoisonne = maladiesPoisons.length > 0;
this._messageRecuperationMaladiePoisons(maladiesPoisons, message);
const blessures = duplicate(this.system.blessures);
await this._recupererBlessures(message, "legere", blessures.legeres.liste.filter(b => b.active), [], isMaladeEmpoisonne);
await this._recupererBlessures(message, "grave", blessures.graves.liste.filter(b => b.active), blessures.legeres.liste, isMaladeEmpoisonne);
await this._recupererBlessures(message, "critique", blessures.critiques.liste.filter(b => b.active), blessures.graves.liste, isMaladeEmpoisonne);
await this.update({ "system.blessures": blessures });
await this._recuperationBlessures(message, isMaladeEmpoisonne);
await this._recupererVie(message, isMaladeEmpoisonne);
}
@@ -452,7 +456,7 @@ export class RdDActor extends RdDBaseActor {
await this._recupereChance();
await this.transformerStress();
await this.retourSeuilDeReve(message);
this.bonusRecuperationPotion = 0; // Reset potion
await this.setBonusPotionSoin(0);
await this.retourSust(message);
await this.verifierPotionsEnchantees();
if (message.content != "") {
@@ -515,65 +519,37 @@ export class RdDActor extends RdDBaseActor {
}
/* -------------------------------------------- */
async _recupererBlessures(message, type, liste, moindres, isMaladeEmpoisonne) {
if (!this.bonusRecuperationPotion) this.bonusRecuperationPotion = 0;
let count = 0;
const definitions = RdDUtility.getDefinitionsBlessures();
let definition = definitions.find(d => d.type == type);
for (let blessure of liste) {
if (blessure.jours >= definition.facteur) {
let rolled = await this._jetRecuperationConstitution(Misc.toInt(blessure.soins_complets) + this.bonusRecuperationPotion, message);
blessure.soins_complets = 0;
if (!isMaladeEmpoisonne && rolled.isSuccess && this._retrograderBlessure(type, blessure, moindres)) {
message.content += ` -- une blessure ${type} cicatrise`;
count++;
}
else if (rolled.isETotal) {
message.content += ` -- une blessure ${type} s'infecte (temps de guérison augmenté de ${definition.facteur} jours, perte de vie)`;
blessure.jours = 0;
await this.santeIncDec("vie", -1);
}
else {
blessure.jours++;
message.content += ` -- une blessure ${type} reste stable`;
}
}
else {
blessure.jours++;
}
}
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))
await Promise.all(blessures.map(b => b.recuperationBlessure({
actor: this,
timestamp,
message,
isMaladeEmpoisonne,
blessures
})));
await this.supprimerBlessures(it => it.system.gravite <= 0);
}
/* -------------------------------------------- */
_retrograderBlessure(type, blessure, blessuresMoindres) {
if (type != "legere") {
let retrograde = blessuresMoindres.find(b => !b.active);
if (!retrograde) {
return false;
}
mergeObject(retrograde, { "active": true, "psdone": blessure.psdone, "scdone": blessure.scdone, "premiers_soins": 0, "soins_complets": 0, "jours": 0, "loc": blessure.loc });
}
this._supprimerBlessure(blessure);
return true;
}
/* -------------------------------------------- */
_supprimerBlessure(blessure) {
mergeObject(blessure, PAS_DE_BLESSURE);
async supprimerBlessures(filterToDelete) {
const toDelete = this.filterItems(filterToDelete, 'blessure')
.map(it => it.id);
await this.deleteEmbeddedDocuments('Item', toDelete);
}
/* -------------------------------------------- */
async _recupererVie(message, isMaladeEmpoisonne) {
const tData = this.system
let blessures = [].concat(tData.blessures.legeres.liste).concat(tData.blessures.graves.liste).concat(tData.blessures.critiques.liste);
let nbBlessures = blessures.filter(b => b.active);
let vieManquante = tData.sante.vie.max - tData.sante.vie.value;
if (nbBlessures == 0 && vieManquante > 0) {
let bonusSoins = 0;
for (let b of blessures) {
bonusSoins = Math.max(bonusSoins, Misc.toInt(b.soins_complets));
let blessures = this.filterItems(it => it.system.gravite > 0, 'blessure');
if (blessures.length > 0) {
return
}
let rolled = await this._jetRecuperationConstitution(bonusSoins, message)
let vieManquante = tData.sante.vie.max - tData.sante.vie.value;
if (vieManquante > 0) {
let rolled = await this.jetRecuperationConstitution(0, message)
if (!isMaladeEmpoisonne && rolled.isSuccess) {
const gain = Math.min(rolled.isPart ? 2 : 1, vieManquante);
message.content += " -- récupération de vie: " + gain;
@@ -590,8 +566,8 @@ export class RdDActor extends RdDBaseActor {
}
/* -------------------------------------------- */
async _jetRecuperationConstitution(bonusSoins, message = undefined) {
let difficulte = Misc.toInt(bonusSoins) + Math.min(0, this.system.sante.vie.value - this.system.sante.vie.max);
async jetRecuperationConstitution(bonusSoins, message = undefined) {
let difficulte = Math.min(0, this.system.sante.vie.value - this.system.sante.vie.max) + bonusSoins + this.system.sante.bonusPotion;
let rolled = await RdDResolutionTable.roll(this.system.carac.constitution.value, difficulte);
if (message) {
message.content = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/roll/explain.hbs", {
@@ -615,18 +591,14 @@ export class RdDActor extends RdDBaseActor {
const updates = {
'system.sante.endurance.value': this.system.sante.endurance.max
};
if (!this.isEntite([ENTITE_INCARNE, ENTITE_BLURETTE])) {
if (this.system.blessures) {
updates['system.blessures.legeres.liste'] = [PAS_DE_BLESSURE, PAS_DE_BLESSURE, PAS_DE_BLESSURE, PAS_DE_BLESSURE, PAS_DE_BLESSURE];
updates['system.blessures.graves.liste'] = [PAS_DE_BLESSURE, PAS_DE_BLESSURE];
updates['system.blessures.critiques.liste'] = [PAS_DE_BLESSURE];
}
if (this.isPersonnage() || this.isCreature()) {
await this.supprimerBlessures(it => true);
updates['system.sante.vie.value'] = this.system.sante.vie.max;
updates['system.sante.fatigue.value'] = 0;
}
if (this.isPersonnage()) {
updates['system.compteurs.ethylisme'] = { value: 1, nb_doses: 0, jet_moral: false };
}
}
await this.update(updates);
await this.removeEffects(e => e.flags.core.statusId !== STATUSES.StatusDemiReve);
}
@@ -1139,17 +1111,17 @@ export class RdDActor extends RdDBaseActor {
}
/* -------------------------------------------- */
computeResumeBlessure(blessures = undefined) {
blessures = blessures ?? this.system.blessures;
if (!blessures) {
return "Pas de blessures possibles";
}
let nbLegeres = this.countBlessures(blessures.legeres.liste);
let nbGraves = this.countBlessures(blessures.graves.liste);
let nbCritiques = this.countBlessures(blessures.critiques.liste);
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;
if (nbLegeres + nbGraves + nbCritiques == 0) {
return "Aucune blessure";
}
let resume = "Blessures:";
if (nbCritiques > 0 || nbGraves > 0 || nbLegeres > 0) {
if (nbLegeres > 0) {
resume += " " + nbLegeres + " légère" + (nbLegeres > 1 ? "s" : "");
}
@@ -1165,10 +1137,6 @@ export class RdDActor extends RdDBaseActor {
}
return resume;
}
else {
return "Aucune blessure";
}
}
recompute() {
this.computeEtatGeneral();
@@ -1376,11 +1344,11 @@ export class RdDActor extends RdDBaseActor {
ChatMessage.create({ content: `${this.name} n'est plus ${Misc.lowerFirst(game.i18n.localize(effect.system.label))} !` });
}
}
if (this.type == 'personnage') {
// Gestion blessure graves : -1 pt endurance
let nbGraves = this.countBlessuresNonSoigneeByName('graves');
if (this.isPersonnage() || this.isCreature()) {
const nbGraves = this.filterItems(it => it.isGrave(), 'blessure').length
if (nbGraves > 0) {
await this.santeIncDec("endurance", -1);
// Gestion blessure graves : -1 pt endurance par blessure grave
await this.santeIncDec("endurance", - nbGraves);
}
}
}
@@ -1411,20 +1379,8 @@ export class RdDActor extends RdDBaseActor {
}
/* -------------------------------------------- */
countBlessures(blessuresListe) {
return blessuresListe.filter(b => b.active).length
}
/* -------------------------------------------- */
countBlessuresByName(name) {
return this.countBlessures(this.system.blessures[name].liste);
}
countBlessuresNonSoigneeByName(name) {
if (this.system.blessures) {
let blessures = this.system.blessures[name].liste;
return blessures.filter(b => b.active && !b.psdone).length;
}
return 0;
countBlessures(filter = it => !it.isContusion()) {
return this.filterItems(filter, 'blessure').length
}
/* -------------------------------------------- */
@@ -1575,40 +1531,15 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
_computeEnduranceMax() {
let blessures = this.system.blessures;
let diffVie = this.system.sante.vie.max - this.system.sante.vie.value;
let maxEndVie = this.system.sante.endurance.max - (diffVie * 2);
let nbGraves = this.countBlessures(blessures.graves.liste);
let nbCritiques = this.countBlessures(blessures.critiques.liste);
let maxEndGraves = Math.floor(this.system.sante.endurance.max / (2 * nbGraves));
let maxEndCritiques = nbCritiques > 0 ? 1 : this.system.sante.endurance.max;
const diffVie = this.system.sante.vie.max - this.system.sante.vie.value;
const maxEndVie = this.system.sante.endurance.max - (diffVie * 2);
const nbGraves = this.countBlessures(it => it.isGrave()) > 0
const nbCritiques = this.countBlessures(it => it.isCritique()) > 0
const maxEndGraves = Math.floor(this.system.sante.endurance.max / (2 * nbGraves));
const maxEndCritiques = nbCritiques > 0 ? 1 : this.system.sante.endurance.max;
return Math.max(0, Math.min(maxEndVie, maxEndGraves, maxEndCritiques));
}
/* -------------------------------------------- */
async manageBlessureFromSheet(gravite, index) {
let listBlessures = duplicate(this.system.blessures);
let blessure = listBlessures[gravite + "s"].liste[index];
blessure.active = !blessure.active;
if (!blessure.active) {
this._supprimerBlessure(blessure);
}
await this.update({ 'system.blessures': listBlessures });
}
/* -------------------------------------------- */
async setDataBlessureFromSheet(gravite, index, psoins, pcomplets, jours, loc, psdone, scdone) {
let listBlessures = duplicate(this.system.blessures);
let blessure = listBlessures[gravite + "s"].liste[index];
blessure.psdone = psdone;
blessure.scdone = scdone;
blessure.premiers_soins = psoins;
blessure.soins_complets = pcomplets;
blessure.jours = jours;
blessure.loc = loc;
await this.update({ 'system.blessures': listBlessures });
}
/* -------------------------------------------- */
async jetDeMoral(situation, messageReussi = undefined, messageManque = undefined) {
const jetMoral = await this._jetDeMoral(situation);
@@ -1795,7 +1726,7 @@ export class RdDActor extends RdDBaseActor {
async _surmonterExotisme(item) {
const exotisme = Math.min(item.system.exotisme, item.system.qualite, 0);
if (exotisme < 0) {
const rolled = await this.rollCaracCompetence('volonte', 'cuisine', exotisme, { title: `tente de surmonter l'exotisme de ${item.name}` });
const rolled = await this.doRollCaracCompetence('volonte', 'cuisine', exotisme, { title: `tente de surmonter l'exotisme de ${item.name}` });
return rolled.isSuccess;
}
return true;
@@ -1803,7 +1734,7 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
async apprecier(carac, compName, qualite, title) {
const rolled = await this.rollCaracCompetence(carac, compName, qualite, { title: title, apprecier: true });
const rolled = await this.doRollCaracCompetence(carac, compName, qualite, { title: title, apprecier: true });
if (rolled?.isSuccess) {
await this.jetDeMoral('heureux');
}
@@ -2089,22 +2020,21 @@ export class RdDActor extends RdDBaseActor {
}
/* -------------------------------------------- */
filterSortList(sortList, coord) {
$filterSortList(sortList, coord) {
let tmr = TMRUtility.getTMR(coord);
let letfilteredList = []
let filtered = []
for (let sort of sortList) {
if (sort.system.caseTMR.toLowerCase().includes('variable')) {
letfilteredList.push(sort);
filtered.push(sort);
} else if (sort.system.caseTMRspeciale.toLowerCase().includes('variable')) {
letfilteredList.push(sort);
filtered.push(sort);
} else if (sort.system.caseTMR.toLowerCase() == tmr.type) {
letfilteredList.push(sort);
filtered.push(sort);
} else if (sort.system.caseTMR.toLowerCase().includes('special') && sort.system.caseTMRspeciale.toLowerCase().includes(coord.toLowerCase())) {
letfilteredList.push(sort);
filtered.push(sort);
}
}
return letfilteredList;
return filtered;
}
/* -------------------------------------------- */
@@ -2136,52 +2066,39 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
async rollUnSort(coord) {
let sortList = duplicate(this.getSortList()); // Duplication car les pts de reve sont modifiés dans le sort
if (!sortList || sortList.length == 0) {
ui.notifications.info("Aucun sort disponible!");
return;
}
sortList = this.filterSortList(sortList, coord);
if (!sortList || sortList.length == 0) {
ui.notifications.info("Aucun sort disponible pour cette case !");
return;
}
if (EffetsDraconiques.isSortImpossible(this)) {
ui.notifications.error("Une queue ou un souffle vous empèche de lancer de sort!");
return;
}
// Duplication car les pts de reve sont modifiés dans le sort
let sorts = duplicate(this.$filterSortList(this.getSortList(), coord));
if (sorts.length == 0) {
ui.notifications.info(`Aucun sort disponible en ${TMRUtility.getTMR(coord).label} !`);
return;
}
if (this.currentTMR) this.currentTMR.minimize(); // Hide
let draconicList = this.computeDraconicAndSortIndex(sortList);
const draconicList = this.computeDraconicAndSortIndex(sorts);
const reve = duplicate(this.system.carac.reve);
let rollData = {
await this._openRollDialog({
name: 'lancer-un-sort',
label: 'Lancer un sort',
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.html',
rollData: {
carac: { 'reve': reve },
forceCarac: { 'reve': reve },
selectedCarac: reve,
draconicList: draconicList,
competence: draconicList[0],
sortList: sortList,
selectedSort: sortList[0],
sortList: sorts,
selectedSort: sorts[0],
tmr: TMRUtility.getTMR(coord),
diffLibre: RdDItemSort.getDifficulte(sortList[0], -7), // Per default at startup
diffLibre: RdDItemSort.getDifficulte(sorts[0], -7), // Per default at startup
coutreve: Array(30).fill().map((item, index) => 1 + index),
}
const dialog = await RdDRoll.create(this, rollData,
{
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.html',
close: html => { this.currentTMR.maximize() } // Re-display TMR
},
{
name: 'lancer-un-sort',
label: 'Lancer un sort',
callbacks: [
this.createCallbackExperience(),
{ action: r => this._rollUnSortResult(r) }
]
}
);
dialog.render(true);
callbackAction: r => this._rollUnSortResult(r)
});
}
/* -------------------------------------------- */
@@ -2288,34 +2205,35 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
async rollCarac(caracName, jetResistance = undefined) {
let rollData = {
selectedCarac: this.getCaracByName(caracName),
let selectedCarac = this.getCaracByName(caracName)
await this._openRollDialog({
name: 'jet-' + caracName,
label: 'Jet ' + Grammar.apostrophe('de', selectedCarac.label),
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html',
rollData: {
selectedCarac: selectedCarac,
competences: this.itemTypes['competence'],
jetResistance: jetResistance ? caracName : undefined
};
const dialog = await RdDRoll.create(this, rollData,
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html' },
{
name: 'jet-' + caracName,
label: 'Jet ' + Grammar.apostrophe('de', rollData.selectedCarac.label),
callbacks: [
this.createCallbackExperience(),
this.createCallbackAppelAuMoral(),
{ action: r => this._onRollCaracResult(r) }
]
}
);
dialog.render(true);
},
callbackAction: r => this.$onRollCaracResult(r)
});
}
/* -------------------------------------------- */
async _onRollCaracResult(rollData) {
async $onRollCaracResult(rollData) {
// Final chat message
await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-general.html');
}
async rollCaracCompetence(caracName, compName, diff, options = { title: "", apprecier: false }) {
/**
* Méthode pour faire un jet prédéterminer sans ouvrir la fenêtre de dialogue
* @param {*} caracName
* @param {*} compName
* @param {*} diff
* @param {*} options
* @returns
*/
async doRollCaracCompetence(caracName, compName, diff, options = { title: "", apprecier: false }) {
const carac = this.getCaracByName(caracName);
if (!carac) {
ui.notifications.warn(`${this.name} n'a pas de caractéristique correspondant à ${caracName}`)
@@ -2374,24 +2292,22 @@ export class RdDActor extends RdDBaseActor {
// Transformer la competence de créature
RdDItemCompetenceCreature.setRollDataCreature(rollData)
}
console.log("rollCompetence !!!", rollData);
const dialog = await RdDRoll.create(this, rollData,
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' },
{
await this._openRollDialog({
name: 'jet-competence',
label: 'Jet ' + Grammar.apostrophe('de', rollData.competence.name),
callbacks: [
this.createCallbackExperience(),
this.createCallbackAppelAuMoral(),
{ action: r => this.$onRollCompetence(r) }
]
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html',
rollData: rollData,
callbackAction: r => this.$onRollCompetence(r, options)
});
dialog.render(true);
}
/* -------------------------------------------- */
async $onRollCompetence(rollData) {
async $onRollCompetence(rollData, options) {
await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-competence.html')
if (options?.onRollAutomate) {
options.onRollAutomate(rollData);
}
}
/* -------------------------------------------- */
@@ -2419,47 +2335,67 @@ export class RdDActor extends RdDBaseActor {
return tachesExistantes.length > 0 ? tachesExistantes[0] : undefined;
}
async createTacheBlessure(gravite) {
const tache = RdDItemTache.prepareTacheSoin(gravite)
if (tache) {
await this.createEmbeddedDocuments('Item', [tache], { renderSheet: false });
blessuresASoigner() {
// TODO or not TODO: filtrer les blessures poour lesquels on ne peut plus faire de premiers soins?
return this.filterItems(it => it.system.gravite > 0 && it.system.gravite <= 6 && !(it.system.premierssoins.done && it.system.soinscomplets.done), 'blessure')
}
async getTacheBlessure(blesse, blessure) {
const gravite = blessure?.system.gravite ?? 0;
if (gravite > 0) {
const tache = this.listItems('tache').find(it => it.system.itemId == blessure.id)
?? await RdDItemBlessure.createTacheSoinBlessure(this, gravite);
await blessure?.updateTacheSoinBlessure(tache);
return tache
}
return undefined;
}
async rollCaracCompetence(caracName, compName, diff, options = { title: "" }) {
const competence = this.getCompetence(compName);
await this._openRollDialog({
name: 'jet-competence',
label: 'Jet ' + Grammar.apostrophe('de', competence.name),
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html',
rollData: {
alias: this.name,
carac: this.system.carac,
selectedCarac: this.getCaracByName(caracName),
selectedCaracName: caracName,
diffLibre: diff,
competence: competence,
show: { title: options?.title ?? '' }
},
callbackAction: r => this.$onRollCompetence(r, options)
});
}
/* -------------------------------------------- */
async rollTache(id) {
async rollTache(id, options = {}) {
const tacheData = this.getTache(id)
const compData = this.getCompetence(tacheData.system.competence)
compData.system.defaut_carac = tacheData.system.carac; // Patch !
let rollData = {
await this._openRollDialog({
name: 'jet-competence',
label: 'Jet de Tâche ' + tacheData.name,
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html',
rollData: {
competence: compData,
tache: tacheData,
diffLibre: tacheData.system.difficulte,
diffConditions: 0,
use: { libre: false, conditions: true },
carac: {}
};
rollData.carac[tacheData.system.carac] = duplicate(this.system.carac[tacheData.system.carac]); // Single carac
console.log("rollTache !!!", rollData);
const dialog = await RdDRoll.create(this, rollData,
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' },
{
name: 'jet-competence',
label: 'Jet de Tâche ' + tacheData.name,
callbacks: [
this.createCallbackExperience(),
this.createCallbackAppelAuMoral(),
{ action: r => this._tacheResult(r) }
]
carac: {
[tacheData.system.carac]: duplicate(this.system.carac[tacheData.system.carac])
}
},
callbackAction: r => this._tacheResult(r, options)
});
dialog.render(true);
}
/* -------------------------------------------- */
async _tacheResult(rollData) {
async _tacheResult(rollData, options) {
// Mise à jour de la tache
rollData.appliquerFatigue = ReglesOptionelles.isUsing("appliquer-fatigue");
rollData.tache = duplicate(rollData.tache);
@@ -2478,10 +2414,13 @@ export class RdDActor extends RdDBaseActor {
this.santeIncDec("fatigue", rollData.tache.system.fatigue);
await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-tache.html');
if (options?.onRollAutomate) {
options.onRollAutomate(rollData);
}
}
/* -------------------------------------------- */
async _rollArt(artData, selected, oeuvre, callBackResult = r => this._resultArt(r)) {
async _rollArt(artData, selected, oeuvre, callbackAction = r => this._resultArt(r)) {
oeuvre.system.niveau = oeuvre.system.niveau ?? 0;
mergeObject(artData,
{
@@ -2499,18 +2438,14 @@ export class RdDActor extends RdDBaseActor {
artData.forceCarac = {};
artData.forceCarac[selected] = duplicate(this.system.carac[selected]);
}
const dialog = await RdDRoll.create(this, artData,
{ html: `systems/foundryvtt-reve-de-dragon/templates/dialog-roll-${oeuvre.type}.html` },
{
await this._openRollDialog({
name: `jet-${artData.art}`,
label: `${artData.verbe} ${oeuvre.name}`,
callbacks: [
this.createCallbackExperience(),
this.createCallbackAppelAuMoral(),
{ action: r => callBackResult(r) }
]
template: `systems/foundryvtt-reve-de-dragon/templates/dialog-roll-${oeuvre.type}.html`,
rollData: artData,
callbackAction: callbackAction
});
dialog.render(true);
}
/* -------------------------------------------- */
@@ -2779,24 +2714,17 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
async rollAppelChance(onSuccess = () => { }, onEchec = () => { }) {
// Stocke si utilisation de la chance
let rollData = { selectedCarac: this.getCaracByName('chance-actuelle'), surprise: '' };
const dialog = await RdDRoll.create(this, rollData,
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html' },
{
await this._openRollDialog({
name: 'appelChance',
label: 'Appel à la chance',
callbacks: [
this.createCallbackExperience(),
{ action: r => this._appelChanceResult(r, onSuccess, onEchec) },
]
}
);
dialog.render(true);
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html',
rollData: { selectedCarac: this.getCaracByName('chance-actuelle'), surprise: '' },
callbackAction: r => this._appelChanceResult(r, onSuccess, onEchec)
});
}
/* -------------------------------------------- */
async _appelChanceResult(rollData, onSuccess = () => { }, onEchec = () => { }) {
async _appelChanceResult(rollData, onSuccess, onEchec) {
await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-appelchance.html')
if (rollData.rolled.isSuccess) {
await this.setFlag(SYSTEM_RDD, 'utilisationChance', true);
@@ -3106,7 +3034,77 @@ export class RdDActor extends RdDBaseActor {
}
RdDCombat.rddCombatTarget(target, this).attaque(competence, arme);
})
}
async rollSoins(blesse, blessureId) {
const blessure = blesse.blessuresASoigner().find(it => it.id == blessureId);
if (blessure) {
if (!blessure.system.premierssoins.done) {
const tache = await this.getTacheBlessure(blesse, blessure);
return await this.rollTache(tache.id, {
onRollAutomate: async r => blesse.onRollTachePremiersSoins(blessureId, r)
});
}
if (!blessure.system.soinscomplets.done) {
const diff = blessure.system.difficulte + (blessure.system.premierssoins.bonus ?? 0);
return await this.rollCaracCompetence("dexterite", "Chirurgie", diff, {
title: "Soins complets",
onRollAutomate: r => blesse.onRollSoinsComplets(blessureId, r)
})
}
}
}
async onRollTachePremiersSoins(blessureId, rollData) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({ actorId: this.id, method: 'onRollTachePremiersSoins', args: [blessureId, rollData] });
}
const blessure = this.getItem(blessureId, 'blessure')
console.log('TODO update blessure', this, blessureId, rollData, rollData.tache);
if (blessure && !blessure.system.premierssoins.done) {
const tache = rollData.tache;
if (rollData.rolled.isETotal) {
await blessure.update({
'system.difficulte': blessure.system.difficulte - 1,
'system.premierssoins.tache': Math.max(0, tache.system.points_de_tache_courant)
})
}
else {
const bonus = tache.system.points_de_tache_courant - tache.system.points_de_tache
await blessure.update({
'system.premierssoins': {
done: (bonus >= 0),
bonus: Math.max(0, bonus),
tache: Math.max(0, tache.system.points_de_tache_courant)
}
})
if (bonus >= 0) {
await this.deleteEmbeddedDocuments('Item', [tache.id])
}
}
}
}
async onRollSoinsComplets(blessureId, rollData) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({ actorId: this.id, method: 'onRollSoinsComplets', args: [blessureId, rollData] });
}
const blessure = this.getItem(blessureId, 'blessure')
if (blessure && blessure.system.premierssoins.done && !blessure.system.soinscomplets.done) {
// TODO: update de la blessure: passer par le MJ!
if (rollData.rolled.isETotal) {
await blessure.setSoinsBlessure({
difficulte: blessure.system.difficulte - 1,
premierssoins: { done: false, bonus: 0 }, soinscomplets: { done: false, bonus: 0 },
})
}
else {
// soins complets finis
await blessure.setSoinsBlessure({
soinscomplets: { done: true, bonus: Math.max(0, rollData.rolled.ptTache) },
})
}
}
}
/* -------------------------------------------- */
@@ -3236,11 +3234,11 @@ export class RdDActor extends RdDBaseActor {
async _appliquerEncaissement(encaissement, show) {
let santeOrig = duplicate(this.system.sante);
this.ajouterBlessure(encaissement); // Will upate the result table
const blessure = await this.ajouterBlessure(encaissement); // Will upate the result table
const perteVie = this.isEntite()
? { newValue: 0 }
: await this.santeIncDec("vie", -encaissement.vie);
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, encaissement.critiques > 0);
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, blessure?.isCritique());
mergeObject(encaissement, {
alias: this.name,
@@ -3250,6 +3248,7 @@ export class RdDActor extends RdDBaseActor {
jetEndurance: perteEndurance.jetEndurance,
endurance: santeOrig.endurance.value - perteEndurance.newValue,
vie: this.isEntite() ? 0 : (santeOrig.vie.value - perteVie.newValue),
blessure: blessure,
show: show ?? {}
});
@@ -3269,73 +3268,33 @@ export class RdDActor extends RdDBaseActor {
}
/* -------------------------------------------- */
ajouterBlessure(encaissement) {
if (this.type == 'entite') return; // Une entité n'a pas de blessures
if (encaissement.legeres + encaissement.graves + encaissement.critiques == 0) return;
async ajouterBlessure(encaissement) {
if (this.isEntite()) return; // Une entité n'a pas de blessures
if (encaissement.gravite < 0) return;
if (encaissement.gravite > 0) {
while (this.countBlessures(it => it.system.gravite == encaissement.gravite) >= RdDItemBlessure.maxBlessures(encaissement.gravite) && encaissement.gravite <= 6) {
// Aggravation
encaissement.gravite += 2
if (encaissement.gravite > 2) {
encaissement.vie += 2;
}
}
}
const endActuelle = Number(this.system.sante.endurance.value);
let blessures = duplicate(this.system.blessures);
let count = encaissement.legeres;
// Manage blessures
while (count > 0) {
let legere = blessures.legeres.liste.find(it => !it.active);
if (legere) {
this._setBlessure(legere, encaissement);
count--;
}
else {
encaissement.graves += count;
encaissement.legeres -= count;
break;
}
}
count = encaissement.graves;
while (count > 0) {
let grave = blessures.graves.liste.find(it => !it.active);
if (grave) {
this._setBlessure(grave, encaissement);
count--;
}
else {
encaissement.critiques += count;
encaissement.graves -= count;
const blessure = await RdDItemBlessure.createBlessure(this, encaissement.gravite, encaissement.dmg.loc.label);
if (blessure.isCritique()) {
encaissement.endurance = endActuelle;
encaissement.vie = 4;
break;
}
}
count = encaissement.critiques;
while (count > 0) {
let critique = blessures.critiques.liste[0];
if (!critique.active) {
this._setBlessure(critique, encaissement);
count--;
} else {
// TODO: status effect dead
if (blessure.isMort()) {
this.setEffect(STATUSES.StatusComma, true);
encaissement.mort = true;
ChatMessage.create({
content: `<img class="chat-icon" src="icons/svg/skull.svg" alt="charge" />
<strong>${this.name} vient de succomber à une seconde blessure critique ! Que les Dragons gardent son Archétype en paix !</strong>`
});
encaissement.critiques -= count;
encaissement.mort = true;
break;
}
}
encaissement.endurance = Math.max(encaissement.endurance, -endActuelle);
this.update({ "system.blessures": blessures });
}
/* -------------------------------------------- */
_setBlessure(blessure, encaissement) {
blessure.active = true;
blessure.psdone = false;
blessure.scdone = false;
blessure.loc = encaissement.locName;
return blessure;
}
/* -------------------------------------------- */
@@ -3568,42 +3527,28 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
async buildPotionGuerisonList(pointsGuerison) {
let pointsGuerisonInitial = pointsGuerison;
let myData = this.system;
const blessures = duplicate(myData.blessures);
let guerisonData = { list: [], pointsConsommes: 0 }
console.log(blessures);
for (let critique of blessures.critiques.liste) {
if (critique.active && pointsGuerison >= 6) {
pointsGuerison -= 6;
critique.active = false;
guerisonData.list.push("1 Blessure Critique (6 points)");
const pointsGuerisonInitial = pointsGuerison;
const blessures = this.filterItems(it => it.system.gravite > 0, 'blessure').sort(Misc.descending(it => it.system.gravite))
const ids = []
const guerisonData = { list: [], pointsConsommes: 0 }
for (let blessure of blessures) {
if (pointsGuerison >= blessure.system.gravite) {
pointsGuerison -= blessure.system.gravite;
guerisonData.list.push(`1 Blessure ${blessure.system.labelGravite} (${blessure.system.gravite} points)`);
ids.push(blessure.id)
}
}
for (let grave of blessures.graves.liste) {
if (grave.active && pointsGuerison >= 4) {
pointsGuerison -= 4;
grave.active = false;
guerisonData.list.push("1 Blessure Grave (4 points)");
if (ids.length > 0) {
await this.supprimerBlessures(it => ids.includes(it.id));
}
}
for (let legere of blessures.legeres.liste) {
if (legere.active && pointsGuerison >= 2) {
pointsGuerison -= 2;
legere.active = false;
guerisonData.list.push("1 Blessure Légère (2 points)");
}
}
await this.update({ "system.blessures": blessures });
let pvManquants = myData.sante.vie.max - myData.sante.vie.value;
if (blessures.length == ids.length) {
let pvManquants = this.system.sante.vie.max - this.system.sante.vie.value;
let pvSoignees = Math.min(pvManquants, Math.floor(pointsGuerison / 2));
pointsGuerison -= pvSoignees * 2;
guerisonData.list.push(pvSoignees + " Points de Vie soignés");
await this.santeIncDec('vie', +pvSoignees, false);
}
guerisonData.pointsConsommes = pointsGuerisonInitial - pointsGuerison;
return guerisonData;
}
@@ -3622,7 +3567,7 @@ export class RdDActor extends RdDBaseActor {
}
}
if (!potionData.system.magique || potionData.rolled.isSuccess) {
this.bonusRecuperationPotion = potionData.system.herbeBonus;
await this.setBonusPotionSoin(potionData.system.herbebonus);
}
ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
@@ -3630,6 +3575,10 @@ export class RdDActor extends RdDBaseActor {
});
}
async setBonusPotionSoin(bonus) {
await this.update({ 'system.sante.bonusPotion': bonus });
}
/* -------------------------------------------- */
async consommerPotionRepos(potionData) {
potionData.alias = this.name;
@@ -3655,7 +3604,7 @@ export class RdDActor extends RdDBaseActor {
}
}
if (!potionData.system.magique || potionData.rolled.isSuccess) {
this.bonusRepos = potionData.system.herbeBonus;
this.bonusRepos = potionData.system.herbebonus;
}
ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),

View File

@@ -78,6 +78,7 @@ export class RdDBaseActorSheet extends ActorSheet {
/* -------------------------------------------- */
static filterItemsPerTypeForSheet(formData, itemTypes) {
formData.blessures = Misc.arrayOrEmpty(itemTypes['blessure']);
formData.recettescuisine = Misc.arrayOrEmpty(itemTypes['recettecuisine']);
formData.recettesAlchimiques = Misc.arrayOrEmpty(itemTypes['recettealchimique']);
formData.maladies = Misc.arrayOrEmpty(itemTypes['maladie']);

View File

@@ -5,6 +5,7 @@ import { Misc } from "../misc.js";
import { RdDAudio } from "../rdd-audio.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 {
@@ -20,7 +21,6 @@ export class RdDBaseActor extends Actor {
Hooks.on("updateActor", (actor, change, options, actorId) => actor.onUpdateActor(change, options, actorId));
}
static onSocketMessage(sockmsg) {
switch (sockmsg.msg) {
case "msg_remote_actor_call":

View File

@@ -1,18 +0,0 @@
const BASE_TACHE_SOIN_BLESSURE = { type: "tache", img: 'systems/foundryvtt-reve-de-dragon/icons/competence_chirurgie.webp', system: { carac: "dexterite", competence: "Chirurgie", periodicite: "1 round", fatigue: 0, } }
const TACHES_SOIN_BLESSURE = {
'critique': { name: 'Blessure critique', system: { difficulte: -6, points_de_tache: 6 } },
'grave': { name: 'Blessure grave', system: { difficulte: -4, points_de_tache: 4 } },
'legere': { name: 'Blessure légère', system: { difficulte: -2, points_de_tache: 2 } },
}
export class RdDItemTache extends Item {
static prepareTacheSoin(gravite) {
const blessure = TACHES_SOIN_BLESSURE[gravite]
if (blessure) {
return mergeObject(duplicate(BASE_TACHE_SOIN_BLESSURE), blessure)
}
ui.notifications.warn(`Pas de tâche de soins pour une blessure ${gravite}`)
return undefined;
}
}

View File

@@ -31,9 +31,9 @@ const typesInventaire = {
const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"]
const typesObjetsDraconiques = ["queue", "ombre", "souffle", "tete", "signedraconique", "sortreserve", "rencontre"]
const typesObjetsConnaissance = ["meditation", "recettealchimique", "sort"]
const typesObjetsEffet = ["possession", "poison", "maladie"]
const typesObjetsEffet = ["possession", "poison", "maladie", "blessure"]
const typesObjetsCompetence = ["competence", "competencecreature"]
const typesObjetsTemporels = ["poison", "maladie", "queue", "ombre", "souffle", "signedraconique", "rencontre"]
const typesObjetsTemporels = ["blessure", "poison", "maladie", "queue", "ombre", "souffle", "signedraconique", "rencontre"]
const typesEnvironnement = typesInventaireMateriel;
const encBrin = 0.00005; // un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc
const encPepin = 0.0007; /* un pépin de gemme = 1/10 cm3 = 1/1000 l = 3.5/1000 kg = 7/2000 kg = 7/1000 enc
@@ -176,6 +176,7 @@ export class RdDItem extends Item {
isBoisson() { return this.isNourritureBoisson() && this.system.boisson; }
isAlcool() { return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise; }
isHerbeAPotion() { return this.type == 'herbe' && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); }
isBlessure() { return this.type == 'blessure' }
isPresentDansMilieux(milieux) {
return this.getEnvironnements(milieux).length > 0

181
module/item/blessure.js Normal file
View File

@@ -0,0 +1,181 @@
import { RdDItem } from "../item.js";
import { Misc } from "../misc.js";
import { RdDTimestamp } from "../rdd-timestamp.js";
const BASE_TACHE_SOIN_BLESSURE = {
type: "tache",
img: 'systems/foundryvtt-reve-de-dragon/icons/competence_chirurgie.webp',
system: { carac: "dexterite", competence: "Chirurgie", periodicite: "1 round", fatigue: 0, }
}
const TACHES_SOIN_BLESSURE = {
6: { name: 'Blessure critique', system: { difficulte: -6, points_de_tache: 6 } },
4: { name: 'Blessure grave', system: { difficulte: -4, points_de_tache: 4 } },
2: { name: 'Blessure légère', system: { difficulte: -2, points_de_tache: 2 } },
}
const definitionsBlessures = [
{ type: "contusion", gravite: 0, labelGravite: 'Contusion/éraflure', max: 100, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/eraflure.webp" },
{ type: "legere", gravite: 2, labelGravite: 'Légère', max: 5, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
{ type: "grave", gravite: 4, labelGravite: 'Grave', max: 2, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
{ type: "critique", gravite: 6, labelGravite: 'Critique', max: 1, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
{ type: "mort", gravite: 8, labelGravite: 'Mort', max: 1, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/mort.webp" }
]
export class RdDItemBlessure extends RdDItem {
static get defaultIcon() {
return "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp";
}
prepareDerivedData() {
super.prepareDerivedData();
this.system.labelGravite = this.getLabelGravite()
}
static prepareTacheSoin(gravite) {
const tache = TACHES_SOIN_BLESSURE[gravite]
if (!tache) {
ui.notifications.warn(`Pas de tâche de soins pour une blessure ${gravite}`)
return undefined;
}
return mergeObject(duplicate(BASE_TACHE_SOIN_BLESSURE), tache)
}
static async createBlessure(actor, gravite, localisation = '') {
const definition = RdDItemBlessure.getDefinition(gravite)
const blessure = {
name: definition.labelGravite,
type: 'blessure',
img: definition.icon,
system: {
gravite: gravite,
difficulte: - gravite,
localisation: localisation
}
}
const blessures = await actor.createEmbeddedDocuments('Item', [blessure])
return blessures[0]
}
static async createTacheSoinBlessure(actor, gravite) {
const tache = RdDItemBlessure.prepareTacheSoin(gravite)
if (tache) {
const taches = await actor.createEmbeddedDocuments('Item', [tache], { renderSheet: false });
return taches[0];
}
return undefined
}
async updateTacheSoinBlessure(tache) {
if (tache) {
await tache.update({
system: {
itemId: this.id,
difficulte: Math.min(this.system.difficulte, tache.system.difficulte),
points_de_tache_courant: Math.max(0, this.system.premierssoins.tache)
}
});
}
}
async setSoinsBlessure(systemUpdate = {}) {
systemUpdate = mergeObject(systemUpdate, this.system, { overwrite: false }),
systemUpdate.soinscomplets.done = systemUpdate.premierssoins.done && systemUpdate.soinscomplets.done
await this.update({
img: this.getImgSoins(systemUpdate.gravite, systemUpdate.soinscomplets.done),
system: systemUpdate
});
}
async recuperationBlessure({ actor, timestamp, message, isMaladeEmpoisonne, blessures }) {
if (this.parent != actor || actor == undefined) {
return
}
if (new RdDTimestamp(this.system.temporel.fin).compare(timestamp) > 0) {
// attente periode
return
}
if (this.system.gravite > 0) {
const update = { system: { premierssoins: { bonus: 0 }, soinscomplets: { bonus: 0 } } }
const gravite = this.system.gravite;
const graviteMoindre = gravite - 2;
const moindres = blessures.filter(it => it.system.gravite == graviteMoindre, 'blessures').length
const labelGravite = this.getLabelGravite();
let rolled = await actor.jetRecuperationConstitution(this.system.soinscomplets.bonus, message);
if (rolled.isETotal) {
message.content += ` -- une blessure ${labelGravite} s'infecte (temps de guérison augmenté de ${gravite} jours, perte de vie)`;
await actor.santeIncDec("vie", -1);
mergeObject(update, {
system: { fin: { indexDate: timestamp.addJours(gravite).indexDate } }
});
}
else {
if (!isMaladeEmpoisonne && rolled.isSuccess && this.peutRetrograder(graviteMoindre, moindres)) {
message.content += ` -- une blessure ${labelGravite} cicatrise`;
mergeObject(update, {
system: { gravite: graviteMoindre, fin: { indexDate: timestamp.addJours(graviteMoindre).indexDate } }
});
}
else {
message.content += ` -- une blessure ${labelGravite} reste stable`;
}
}
await this.update(update);
}
}
peutRetrograder(graviteMoindre, moindres) {
return moindres < RdDItemBlessure.getDefinition(graviteMoindre).max
}
async calculerFinPeriodeTemporel(debut) {
return await debut.nouveauJour().addJours(this.system.gravite);
}
async onFinPeriode(oldTimestamp, newTimestamp) {
if (this.system.gravite <= 0) {
await super.onFinPeriode(oldTimestamp, newTimestamp)
}
}
getImgSoins(gravite, soins) {
let img = 'blessure'
if (gravite > 6) {
img = 'mort'
}
if (gravite <= 0) {
img = 'eraflure'
}
return `systems/foundryvtt-reve-de-dragon/icons/sante/${soins ? 'blessure-soins' : img}.webp`
}
getLabelGravite() {
return RdDItemBlessure.getDefinition(this.system.gravite).labelGravite
}
static getDefinition(gravite) {
return definitionsBlessures.sort(Misc.ascending(it => it.gravite))
.find(it => it.gravite >= gravite);
}
static maxBlessures(gravite) {
return RdDItemBlessure.getDefinition(gravite).max
}
isContusion() {
return this.system.gravite <= 0
}
isLegere() {
return this.system.gravite > 0 && this.system.gravite <= 2
}
isGrave() {
return this.system.gravite > 2 && this.system.gravite <= 4
}
isCritique() {
return this.system.gravite > 4 && this.system.gravite <= 6
}
isMort() {
return this.system.gravite > 6
}
}

View File

@@ -0,0 +1,29 @@
import { RdDItemSheet } from "../item-sheet.js";
export class RdDBlessureItemSheet extends RdDItemSheet {
static get ITEM_TYPE() { return "blessure" };
async getData() {
const formData = await super.getData();
formData.disabled = formData.options.isGM || formData.options.isOwned ? '' : 'disabled';
return formData;
}
activateListeners(html) {
super.activateListeners(html);
if (!this.options.editable) return;
this.html.find('[name="premierssoins-done"]').change(async event => {
await this.item.setSoinsBlessure({ premierssoins: { done: event.currentTarget.checked } });
});
this.html.find('[name="soinscomplets-done"]').change(async event => {
await this.item.setSoinsBlessure({ soinscomplets: { done: event.currentTarget.checked } })
});
this.html.find('[name="system-gravite"]').change(async event => {
const gravite = Number(event.currentTarget.value)
await this.item.setSoinsBlessure({ gravite: gravite, difficulte: - gravite })
});
}
}

View File

@@ -416,6 +416,49 @@ class _10_5_0_UpdatePeriodicite extends Migration {
}
}
class _10_7_0_MigrationBlessures extends Migration {
get code() { return "migration-blessures"; }
get version() { return "10.7.0"; }
async migrate() {
const timestamp = game.system.rdd.calendrier.getTimestamp()
await Promise.all(game.actors.filter(it => it.isPersonnage() || it.isCreature())
.map(async (actor) => {
const legeres = actor.system.blessures?.legeres.liste.filter(it => it.active).map(it => this.creerBlessure(2, 'légère', it, timestamp)) ?? [];
const graves = actor.system.blessures?.graves.liste.filter(it => it.active).map(it => this.creerBlessure(4, 'grave', it, timestamp)) ?? [];
const critiques = actor.system.blessures?.critiques.liste.filter(it => it.active).map(it => this.creerBlessure(6, 'critique', it, timestamp));
const blessures = legeres.concat(graves).concat(critiques);
if (blessures.length > 0) {
await actor.createEmbeddedDocuments("Item", blessures);
}
await actor.update({
'system.blessures.legeres.liste': [],
'system.blessures.graves.liste': [],
'system.blessures.critiques.liste': []
})
}));
}
creerBlessure(gravite, graviteTexte, blessure, timestamp) {
const dateBlessure = timestamp.addJours(-blessure.jours);
const datePremiereRecup = dateBlessure.addJours(gravite);
return {
name: `Blessure ${graviteTexte}`,
type: 'blessure',
img: `systems/foundryvtt-reve-de-dragon/icons/sante/blessure${blessure.psdone ? '-soins' : ''}.webp`,
system: {
gravite: gravite,
difficulte: -gravite,
debut: { indexDate: dateBlessure.indexDate, indexMinute: 0 },
fin: { indexDate: datePremiereRecup.indexDate, indexMinute: 0 },
premierssoins: { done: blessure.psdone, bonus: blessure.premiers_soins },
soinscomplets: { done: blessure.scdone, bonus: blessure.soins_complets },
localisation: blessure.localisation,
jours: blessure.jours
}
}
}
}
export class Migrations {
static getMigrations() {
return [
@@ -431,6 +474,7 @@ export class Migrations {
new _10_3_17_Monnaies(),
new _10_4_6_ServicesEnCommerces(),
new _10_5_0_UpdatePeriodicite(),
new _10_7_0_MigrationBlessures(),
];
}

View File

@@ -28,7 +28,7 @@ export class RdDBonus {
}
/* -------------------------------------------- */
static dmg(rollData, dmgActor, isCauchemar = false) {
static dmg(rollData, dmgActor, isEntiteIncarnee = false) {
let dmg = { total: 0 };
if (rollData.arme && rollData.arme.name.toLowerCase() == "esquive") {
// Specific case management
@@ -41,7 +41,7 @@ export class RdDBonus {
dmg.dmgSurprise = RdDBonus.dmgBonus(rollData.ajustements?.attaqueDefenseurSurpris.used);
dmg.dmgActor = rollData.selectedCarac ? RdDBonus._dmgPerso(dmgActor, rollData.selectedCarac.label, dmg.dmgArme) : 0;
dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere;
dmg.mortalite = RdDBonus._calculMortalite(rollData, isCauchemar)
dmg.mortalite = RdDBonus._calculMortalite(rollData, isEntiteIncarnee)
}
return dmg;
}
@@ -62,11 +62,8 @@ export class RdDBonus {
}
/* -------------------------------------------- */
static _calculMortalite(rollData, isCauchemar) {
if (isCauchemar) {
return "cauchemar";
}
return isCauchemar ? "cauchemar"
static _calculMortalite(rollData, isEntiteIncarnee) {
return isEntiteIncarnee ? "entiteincarnee"
: rollData.dmg?.mortalite
?? rollData.arme?.system.mortalite
?? "mortel";

View File

@@ -45,6 +45,14 @@ export class RdDCalendrier extends Application {
Hooks.on('updateSetting', async (setting, update, options, id) => this.onUpdateSetting(setting, update, options, id));
}
display() {
let templatePath = "systems/foundryvtt-reve-de-dragon/templates/calendar-template.html";
renderTemplate(templatePath, {}).then(html => {
this.render(true);
});
return this;
}
async onUpdateSetting(setting, update, options, id) {
if (setting.key == SYSTEM_RDD + '.' + WORLD_TIMESTAMP_SETTING) {
this.timestamp = RdDTimestamp.getWorldTime();

View File

@@ -1295,13 +1295,8 @@ export class RdDCombat {
blessuresStatus: actor.computeResumeBlessure(),
SConst: actor.getSConst(),
actorId: actor.id,
isGrave: false,
isCritique: false
}
if (actor.countBlessuresNonSoigneeByName("critiques") > 0) { // Pour éviter le cumul grave + critique
formData.isCritique = true;
} else if (actor.countBlessuresNonSoigneeByName("graves") > 0) {
formData.isGrave = true;
isGrave: actor.countBlessures(it => it.isGrave()) > 0,
isCritique: actor.countBlessures(it => it.isCritique()) > 0
}
ChatUtility.createChatWithRollMode(actor.name, {

View File

@@ -332,7 +332,7 @@ export class RdDCommands {
let competence = length > 1 ? actors[0].getCompetence(Misc.join(params.slice(1, length), ' ')) : { name: undefined };
if (competence) {
for (let actor of actors) {
await actor.rollCaracCompetence(caracName, competence.name, diff);
await actor.doRollCaracCompetence(caracName, competence.name, diff);
}
}
return;

View File

@@ -36,6 +36,7 @@ import { RdDActorVehiculeSheet } from "./actor-vehicule-sheet.js";
import { RdDActorEntiteSheet } from "./actor-entite-sheet.js";
import { RdDItem } from "./item.js";
import { RdDItemBlessure } from "./item/blessure.js";
import { RdDItemService } from "./item/service.js";
import { RdDItemMaladie } from "./item/maladie.js";
import { RdDItemPoison } from "./item/poison.js";
@@ -46,6 +47,7 @@ import { RdDItemSouffle } from "./item/souffle.js";
import { RdDRencontre } from "./item/rencontre.js";
import { RdDItemSheet } from "./item-sheet.js";
import { RdDBlessureItemSheet } from "./item/sheet-blessure.js";
import { RdDServiceItemSheet } from "./item/sheet-service.js";
import { RdDRencontreItemSheet } from "./item/sheet-rencontre.js";
import { RdDHerbeItemSheet } from "./item/sheet-herbe.js";
@@ -74,21 +76,22 @@ export class SystemReveDeDragon {
this.RdDUtility = RdDUtility;
this.RdDHotbar = RdDHotbar;
this.itemClasses = {
service: RdDItemService,
blessure: RdDItemBlessure,
maladie: RdDItemMaladie,
ombre: RdDItemOmbre,
poison: RdDItemPoison,
queue: RdDItemQueue,
ombre: RdDItemOmbre,
souffle: RdDItemSouffle,
rencontre: RdDRencontre,
service: RdDItemService,
signedraconique: RdDItemSigneDraconique,
rencontre: RdDRencontre
souffle: RdDItemSouffle,
}
this.actorClasses = {
commerce: RdDCommerce,
creature: RdDActor,
entite: RdDActor,
personnage: RdDActor,
vehicule: RdDActor,
commerce: RdDCommerce,
}
}
@@ -157,6 +160,7 @@ export class SystemReveDeDragon {
RdDItemSheet.register(RdDPlanteItemSheet);
RdDItemSheet.register(RdDIngredientItemSheet);
RdDItemSheet.register(RdDServiceItemSheet);
RdDItemSheet.register(RdDBlessureItemSheet);
Items.registerSheet(SYSTEM_RDD, RdDItemInventaireSheet, {
types: [
@@ -276,8 +280,8 @@ export class SystemReveDeDragon {
let sidebar = document.getElementById("sidebar");
sidebar.style.width = "min-content";
}
if (Misc.isUniqueConnectedGM()) {
game.system.rdd.calendrier = new RdDCalendrier();
new Migrations().migrate();
}
@@ -286,13 +290,7 @@ export class SystemReveDeDragon {
RdDDice.onReady();
/* -------------------------------------------- */
/* Affiche/Init le calendrier */
let calendrier = new RdDCalendrier();
let templatePath = "systems/foundryvtt-reve-de-dragon/templates/calendar-template.html";
let templateData = {};
renderTemplate(templatePath, templateData).then(html => {
calendrier.render(true);
});
game.system.rdd.calendrier = calendrier; // Reference;
game.system.rdd.calendrier = new RdDCalendrier().display();
// Avertissement si joueur sans personnage
if (!game.user.isGM && game.user.character == undefined) {

View File

@@ -30,9 +30,9 @@ export class RdDEncaisser extends Dialog {
};
}
else if (actor.isEntite([ENTITE_BLURETTE, ENTITE_INCARNE])) {
dialogConf.default = "cauchemar"
dialogConf.default = "entiteincarnee"
dialogConf.buttons = {
"cauchemar": { label: "Cauchemar", callback: html => this.performEncaisser("cauchemar") }
"entiteincarnee": { label: "Entité incarnée", callback: html => this.performEncaisser("entiteincarnee") }
}
}
@@ -70,7 +70,6 @@ export class RdDEncaisser extends Dialog {
total: Number(this.modifier),
ajustement: Number(this.modifier),
encaisserSpecial: this.encaisserSpecial,
loc: { result: 0, label: "" },
mortalite: mortalite
}
});

View File

@@ -7,15 +7,16 @@ export class RdDSheetUtility {
const userRightLevel = game.user.isGM
? CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER
: document.getUserLevel(game.user);
mergeObject(options, {
let newOptions = {
isGM: game.user.isGM,
isOwned: document.parent,
isOwned: document.parent ? true : false,
editable: editable,
cssClass: editable ? "editable" : "locked",
isLimited: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.LIMITED,
isObserver: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER,
isOwner: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER
});
}
mergeObject(options, newOptions);
return options;
}

View File

@@ -252,7 +252,7 @@ export class RdDTimestamp {
get heure() { return Math.floor(this.indexMinute / RDD_MINUTES_PAR_HEURES) }
get minute() { return this.indexMinute % RDD_MINUTES_PAR_HEURES }
get round() { return ROUNDS_PAR_MINUTE * (this.indexMinute - Math.floor(this.indexMinute)) }
get angleHeure() { return this.indexMinute / RDD_MINUTES_PAR_JOUR * 360 - 60 }
get angleHeure() { return this.indexMinute / RDD_MINUTES_PAR_JOUR * 360 - 45 }
get angleMinute() { return this.indexMinute / RDD_MINUTES_PAR_HEURES * 360 + 45}
formatDate() {

View File

@@ -2,6 +2,7 @@
import { HtmlUtility } from "./html-utility.js";
import { Misc } from "./misc.js";
import { RdDCombatManager } from "./rdd-combat.js";
import { Targets } from "./targets.js";
/* -------------------------------------------- */
export class RdDTokenHud {
@@ -18,29 +19,39 @@ export class RdDTokenHud {
}
/* -------------------------------------------- */
static async addExtensionHud(app, html, tokenId) {
static async addExtensionHud(app, html, tokenId, isCombat) {
let token = canvas.tokens.get(tokenId);
let actor = token.actor;
app.hasExtension = true;
// soins
await RdDTokenHud.addExtensionHudSoins(html, actor);
if (isCombat) {
let combatant = game.combat.combatants.find(c => c.tokenId == tokenId);
if (!(combatant?.actor)) {
ui.notifications.warn(`Le combatant ${token.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`)
return;
}
app.hasExtension = true;
let actions = RdDCombatManager.listActionsCombat(combatant);
// initiative
await RdDTokenHud.addExtensionHudInit(html, combatant, actions);
// combat
await RdDTokenHud.addExtensionHudCombat(html, combatant, actions);
}
let actionsCombat = RdDCombatManager.listActionsCombat(combatant);
}
static async addExtensionHudInit(html, combatant, actions) {
const hudData = {
combatant: combatant,
actions: actionsCombat,
combatant, actions,
commandes: [
{ name: "Autre action", command: 'autre' },
{ name: 'Initiative +1', command: 'inc', value: 0.01 },
{ name: 'Initiative -1', command: 'dec', value: -0.01 }]
};
const controlIconCombat = html.find('.control-icon[data-action=combat]');
// initiative
await RdDTokenHud._configureSubMenu(controlIconCombat,
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html',
hudData,
@@ -51,26 +62,47 @@ export class RdDTokenHud {
RdDTokenHud._initiativeCommand(initCommand, combatantId);
} else {
let index = event.currentTarget.attributes['data-action-index'].value;
let action = actionsCombat[index];
let action = hudData.actions[index];
RdDCombatManager.rollInitiativeAction(combatantId, action);
}
});
}
static async addExtensionHudCombat(html, combatant, actions) {
const hudData = { combatant, actions, commandes: [] };
const controlIconTarget = html.find('.control-icon[data-action=target]');
// combat
await RdDTokenHud._configureSubMenu(controlIconTarget, 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', hudData,
(event) => {
const actionIndex = event.currentTarget.attributes['data-action-index']?.value;
const action = actionsCombat[actionIndex];
const action = hudData.actions[actionIndex];
if (action.action == 'conjurer') {
actor.conjurerPossession(actor.getPossession(action.system.possessionid));
const possession = combatant.actor.getPossession(action.system.possessionid);
combatant.actor.conjurerPossession(possession);
}
else {
actor.rollArme(action);
combatant.actor.rollArme(action);
}
});
}
static async addExtensionHudSoins(html, sourceActor) {
const target = Targets.getTarget({ warn: false });
if (target?.actor) {
const hudSoins = { blessures: target.actor.blessuresASoigner() ?? [] };
if (hudSoins.blessures.length > 0) {
// soins
const controlIconTarget = html.find('.control-icon[data-action=combat]');
await RdDTokenHud._configureSubMenu(controlIconTarget,
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-soins.hbs',
hudSoins,
(event) => {
const blessureId = event.currentTarget.attributes['data-blessure-id']?.value;
sourceActor.rollSoins(target.actor, blessureId)
});
}
}
}
static _initiativeCommand(initCommand, combatantId) {
switch (initCommand) {
case 'inc': return RdDCombatManager.incDecInit(combatantId, 0.01);
@@ -83,16 +115,17 @@ export class RdDTokenHud {
/* -------------------------------------------- */
static async addTokenHudExtensions(app, html, tokenId) {
const controlIconCombat = html.find('.control-icon[data-action=combat]');
if (controlIconCombat.length > 0) {
controlIconCombat.click(event => {
if (event.currentTarget.className.includes('active')) {
RdDTokenHud.removeExtensionHud(app, html, tokenId);
} else {
setTimeout(function () { RdDTokenHud.addExtensionHud(app, html, tokenId) }, 200);
setTimeout(() => RdDTokenHud.addExtensionHud(app, html, tokenId), 200);
}
});
if (controlIconCombat.length>0 && controlIconCombat[0].className.includes('active')) {
RdDTokenHud.addExtensionHud(app, html, tokenId);
const isCombat = controlIconCombat[0].className.includes('active');
RdDTokenHud.addExtensionHud(app, html, tokenId, isCombat);
}
}

View File

@@ -66,38 +66,31 @@ const fatigueMarche = {
"tresdifficile": { "4": 4, "6": 6 }
}
/* -------------------------------------------- */
const definitionsBlessures = [
{ type: "legere", facteur: 2 },
{ type: "grave", facteur: 4 },
{ type: "critique", facteur: 6 }
]
/* -------------------------------------------- */
const nomEthylisme = ["Emeché", "Gris", "Pinté", "Pas frais", "Ivre", "Bu", "Complètement fait", "Ivre mort"];
/* -------------------------------------------- */
const definitionsEncaissement = {
"mortel": [
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", eraflures: 0, legeres: 0, graves: 0, critiques: 0 },
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", eraflures: 0, legeres: 1, graves: 0, critiques: 0 },
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "2", eraflures: 0, legeres: 0, graves: 1, critiques: 0 },
{ minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", eraflures: 0, legeres: 0, graves: 0, critiques: 1 },
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1},
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0},
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2},
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "2", gravite: 4},
{ minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", gravite: 6},
],
"non-mortel": [
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", eraflures: 0, legeres: 0, graves: 0, critiques: 0 },
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", eraflures: 0, legeres: 1, graves: 0, critiques: 0 },
{ minimum: 20, maximum: undefined, endurance: "100", vie: "0", eraflures: 0, legeres: 1, graves: 0, critiques: 0 },
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1},
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 2 },
{ minimum: 20, maximum: undefined, endurance: "100", vie: "0", gravite: 2 },
],
"cauchemar": [
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", eraflures: 0, legeres: 0, graves: 0, critiques: 0 },
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
{ minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
"entiteincarnee": [
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1},
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0},
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 0 },
{ minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", gravite: 0 },
]
};
@@ -139,7 +132,7 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/actor/xp-competences.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/combat.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/blessures.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/blessure.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/blessure.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/maladies-poisons.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/possessions.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/taches.html',
@@ -276,7 +269,8 @@ export class RdDUtility {
Handlebars.registerHelper('computeResolutionChances', (row, col) => RdDResolutionTable.computeChances(row, col));
Handlebars.registerHelper('upperFirst', str => Misc.upperFirst(str ?? 'Null'));
Handlebars.registerHelper('lowerFirst', str => Misc.lowerFirst(str ?? 'Null'));
Handlebars.registerHelper('upper', str => str?.toUpperCase() ?? 'NULL');
Handlebars.registerHelper('upper', str => str?.toUpperCase() ?? '');
Handlebars.registerHelper('lowercase', str => str?.toLowerCase() ?? '');
Handlebars.registerHelper('le', str => Grammar.articleDetermine(str));
Handlebars.registerHelper('apostrophe', (article, str) => Grammar.apostrophe(article, str));
Handlebars.registerHelper('un', str => Grammar.articleIndetermine(str));
@@ -472,10 +466,6 @@ export class RdDUtility {
return ajustementsEncaissement;
}
static getDefinitionsBlessures() {
return definitionsBlessures;
}
/* -------------------------------------------- */
static getSegmentsFatigue(maxEnd) {
maxEnd = Math.max(maxEnd, 1);
@@ -616,17 +606,10 @@ export class RdDUtility {
encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;';
encaissement.roll = roll;
encaissement.armure = armure;
encaissement.penetration = rollData.arme?.system.penetration ?? 0;
encaissement.total = jetTotal;
encaissement.vie = await RdDUtility._evaluatePerte(encaissement.vie, over20);
encaissement.endurance = await RdDUtility._evaluatePerte(encaissement.endurance, over20);
encaissement.penetration = rollData.arme?.system.penetration ?? 0;
encaissement.blessures = (
encaissement.critiques > 0 ? "Critique" :
encaissement.graves > 0 ? "Grave" :
encaissement.legeres > 0 ? "Légère" :
encaissement.eraflures > 0 ? "Contusions/Eraflures" :
'Aucune'
);
return encaissement;
}

View File

@@ -39,18 +39,18 @@ export class Targets {
}
}
static getTarget() {
static getTarget(options = { warn: true }) {
const targets = Targets.listTargets();
switch (targets.length) {
case 1:
return targets[0];
case 0:
ui.notifications.warn("Vous devez choisir une cible à attaquer!");
if (options.warn) ui.notifications.warn("Vous devez choisir une cible à attaquer!");
break;
default:
ui.notifications.warn("Vous devez choisir une cible (et <strong>une seule</strong>) à attaquer!");
return;
if (options.warn) ui.notifications.warn("Vous devez choisir une cible (et <strong>une seule</strong>) à attaquer!");
}
return undefined;
}
}

View File

@@ -186,7 +186,7 @@ i:is(.fas, .far) {
}
.system-foundryvtt-reve-de-dragon .sheet-header :is(.header-compteurs,.header-etats,.profile-img, .profile-img-token){
padding: 0 3%;
padding: 0 0.4rem;
}
.system-foundryvtt-reve-de-dragon .sheet-header :is(.profile-img, .profile-img-token) {
@@ -213,11 +213,13 @@ i:is(.fas, .far) {
}
.system-foundryvtt-reve-de-dragon .sheet-header .header-compteurs {
width: calc(60% - 110px - 1rem);
text-align: right;
max-width: fit-content;
}
.system-foundryvtt-reve-de-dragon .sheet-header div.header-etats {
width: calc(40% - 32px - 1rem);
height: 48px;
max-width: fit-content;
flex: initial;
@@ -426,6 +428,7 @@ span.equipement-detail-buttons {
justify-content: center;
text-align: left;
}
.blessure-control {
flex-grow: 1;
flex-direction: row;
@@ -457,14 +460,17 @@ input:is(.blessure-premiers_soins, .blessure-soins_complets) {
.blessure-inactive {
color:rgba(150, 150, 150, 0.4);
}
.blessure-active-2,
.blessure-active-legere {
color:rgba(60, 60, 60, 0.9);
text-shadow: 1px 1px 4px rgba(60, 60, 60, 1);
}
.blessure-active-4,
.blessure-active-grave {
color: rgba(218, 126, 21, 0.9);
text-shadow: 1px 1px 4px rgba(60, 60, 60, 1);
}
.blessure-active-6,
.blessure-active-critique {
color: rgba(173, 36, 26, 0.9);
text-shadow: 1px 1px 4px rgba(60, 60, 60, 1);
@@ -1386,27 +1392,36 @@ table.table-nombres-astraux tr:hover {
}
/* ======================================== */
.tokenhudext {
.token-hud-ext {
display: flex;
flex: 0 !important;
font-family: CaslonPro;
font-weight: 600;
}
.tokenhudext.left {
.token-hud-ext.left {
justify-content: flex-start;
flex-direction: column;
position: absolute;
top: 2.75rem;
right: 4rem;
}
.tokenhudext.right {
.token-hud-ext.soins {
justify-content: flex-start;
flex-direction: column;
position: absolute;
top: 13.2rem;
left: -5rem;
max-width: 8.5rem
}
.token-hud-ext.right {
justify-content: flex-start;
flex-direction: column;
position: absolute;
top: 2.75rem;
left: 4rem;
}
.control-icon.tokenhudicon {
.control-icon.token-hud-icon {
width: fit-content;
height: fit-content;
min-width: 6rem;
@@ -1415,7 +1430,7 @@ table.table-nombres-astraux tr:hover {
line-height: 1rem;
margin: 0.2rem;
}
.control-icon.tokenhudicon.right {
.control-icon.token-hud-icon.right {
margin-left: 8px;
}
.rdd-hud-menu label {

View File

@@ -1,8 +1,8 @@
{
"id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon",
"version": "10.6.24",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.6.24.zip",
"version": "10.7.3",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.7.3.zip",
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v10/system.json",
"compatibility": {
"minimum": "10",

View File

@@ -179,23 +179,8 @@
"value": 10,
"label": "Endurance",
"derivee": false
}
},
"blessures": {
"legeres": {
"liste": [ { "active": false, "psdone": false, "premiers_soins": -1, "scdone": false, "soins_complets": -1, "jours": 0, "localisation": "" },
{ "active": false, "psdone": false, "premiers_soins": -1, "scdone": false, "soins_complets": -1, "jours": 0, "localisation": "" },
{ "active": false, "psdone": false, "premiers_soins": -1, "scdone": false, "soins_complets": -1, "jours": 0, "localisation": "" },
{ "active": false, "psdone": false, "premiers_soins": -1, "scdone": false, "soins_complets": -1, "jours": 0, "localisation": "" },
{ "active": false, "psdone": false, "premiers_soins": -1, "scdone": false, "soins_complets": -1, "jours": 0, "localisation": "" } ]
},
"graves": {
"liste": [ { "active": false, "psdone": false, "premiers_soins": -1, "scdone": false, "soins_complets": -1, "jours": 0, "localisation": "" },
{ "active": false, "psdone": false, "premiers_soins": -1, "scdone": false, "soins_complets": -1, "jours": 0, "localisation": "" } ]
},
"critiques": {
"liste": [ { "active": false, "psdone": false, "premiers_soins": -1, "scdone": false, "soins_complets": -1, "jours": 0, "localisation": "" } ]
}
"bonusPotion": 0
},
"attributs": {
"plusdom": {
@@ -380,23 +365,8 @@
"value": 0,
"label": "Fatigue",
"derivee": true
}
},
"blessures": {
"legeres": {
"liste": [ { "active": false, "premiers_soins": 0, "soins_complets": 0, "jours": 0, "localisation": "" },
{ "active": false, "premiers_soins": 0, "soins_complets": 0, "jours": 0, "localisation": "" },
{ "active": false, "premiers_soins": 0, "soins_complets": 0, "jours": 0, "localisation": "" },
{ "active": false, "premiers_soins": 0, "soins_complets": 0, "jours": 0, "localisation": "" },
{ "active": false, "premiers_soins": 0, "soins_complets": 0, "jours": 0, "localisation": "" } ]
},
"graves": {
"liste": [ { "active": false, "premiers_soins": 0, "soins_complets": 0, "jours": 0, "localisation": "" },
{ "active": false, "premiers_soins": 0, "soins_complets": 0, "jours": 0, "localisation": "" } ]
},
"critiques": {
"liste": [ { "active": false, "premiers_soins": 0, "soins_complets": 0, "jours": 0, "localisation": "" } ]
}
"bonusPotion": 0
},
"attributs": {
"sconst": {
@@ -567,7 +537,7 @@
"monnaie", "nourritureboisson", "gemme",
"service",
"meditation", "rencontre", "queue", "ombre", "souffle", "tete", "casetmr", "signedraconique", "sort", "sortreserve",
"nombreastral", "tache", "maladie", "poison", "possession",
"nombreastral", "tache", "blessure", "maladie", "poison", "possession",
"tarot", "extraitpoetique"
],
"templates": {
@@ -636,6 +606,22 @@
"compteur": 0,
"date": 0
},
"blessure": {
"templates": ["temporel"],
"gravite": 0,
"difficulte": 0,
"premierssoins": {
"tache": 0,
"done": false,
"bonus": 0
},
"soinscomplets": {
"done": false,
"bonus": 0
},
"localisation": "",
"jours": 0
},
"maladie": {
"templates": ["description", "temporel"],
"identifie": false,
@@ -833,7 +819,8 @@
"points_de_tache_courant": 0,
"nb_jet_echec": 0,
"nb_jet_succes": 0,
"cacher_points_de_tache": false
"cacher_points_de_tache": false,
"itemId": ""
},
"sort": {
"templates": ["description"],

View File

@@ -0,0 +1,40 @@
<li class="item item-blessure flexrow list-item blessure-active-{{lowercase system.labelGravite}}" data-item-id="{{id}}">
<span class="blessure-control">
<img class="sheet-competence-img" src="{{img}}" />
<i class="fas fa-skull-crossbones"></i>
{{system.labelGravite}}
</span>
{{#if (gt system.gravite 6)}}
<span class="flexrow"></span>
<span class="flexrow"></span>
{{else}}
<span class="flexrow">
<input type="checkbox" class="blessure-premierssoins-done" name="blessure.{{id}}.premierssoins.done" {{#if system.premierssoins.done}}checked{{/if}}/>
{{#if system.premierssoins.done}}
{{#unless system.soinscomplets.done}}
<input type="text" class="blessure-premierssoins-bonus number-x2" name="blessure.{{id}}.premierssoins.bonus" data-dtype="number" value="{{system.premierssoins.bonus}}"/>
{{/unless}}
{{else}}
<label>{{system.premierssoins.tache}} / {{system.gravite}}</label>
{{/if}}
</span>
<span class="flexrow">
{{#if system.premierssoins.done}}
<input type="checkbox" class="blessure-soinscomplets-done" name="blessure.{{id}}.system.soinscomplets.done" {{#if system.soinscomplets.done}}checked{{/if}}/>
{{#if system.soinscomplets.done}}
<input type="text" class="blessure-soinscomplets-bonus number-x2" name="blessure.{{id}}.system.soinscomplets.bonus" data-dtype="number" value="{{system.soinscomplets.bonus}}"/>
{{/if}}
{{else}}
<label>Difficulté {{system.difficulte}}</label>
{{/if}}
</span>
{{/if}}
<span>
{{system.localisation}}
</span>
<span class="item-controls">
<a class="item-edit" title="Editer"><i class="fas fa-edit"></i></a>
<a class="item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
<a class="item-montrer" title="Montrer"><i class="fas fa-comment"></i></a>
</span>
</li>

View File

@@ -1,27 +0,0 @@
<li class="item flexrow list-item {{#if blessure.active}}blessure-active-{{gravite}}{{else}}blessure-inactive{{/if}}"
data-blessure-type="{{gravite}}"
data-attribute={{key}}
data-blessure-index="{{key}}"
data-blessure-active="{{blessure.active}}">
<span class="blessure-control" title="Blessure {{title}}">
<i class="fas fa-skull-crossbones" name="blessure-{{gravite}}-{{key}}-active"></i>
{{title}}
</span>
{{#if blessure.active}}
<span class="blessure-soins flexrow">
<input class="blessure-psdone" name="blessure-{{gravite}}-{{key}}-psdone" type="checkbox" name="blessure.psdone" {{#if blessure.psdone}}checked{{/if}}/>
<input class="blessure-premiers_soins" type="text" name="blessure-{{gravite}}-{{key}}-premiers_soins" data-dtype="number" value="{{blessure.premiers_soins}}"/>
</span>
<span class="blessure-soins flexrow">
<input class="blessure-scdone" name="blessure-{{gravite}}-{{key}}-scdone" type="checkbox" name="blessure.scdone" {{#if blessure.scdone}}checked{{/if}}/>
<input class="blessure-soins_complets" type="text" name="blessure-{{gravite}}-{{key}}-soins_complets" data-dtype="number" value="{{blessure.soins_complets}}"/>
</span>
<input class="blessure-jours" type="text" name="blessure-{{gravite}}-{{key}}-jours" name="jours" data-dtype="number" value="{{blessure.jours}}"/>
<input class="blessure-localisation" type="text" name="blessure-{{gravite}}-{{key}}-localisation" data-dtype="String" value="{{blessure.loc}}"/>
{{else}}
<span></span>
<span></span>
<span></span>
<span></span>
{{/if}}
</li>

View File

@@ -1,18 +1,20 @@
<h4>blessures</h4>
<div>
<a class="chat-card-button creer-blessure-legere"><i class="fas fa-plus-circle"></i> légère</a>
<a class="chat-card-button creer-blessure-grave"><i class="fas fa-plus-circle"></i> grave</a>
<a class="chat-card-button creer-blessure-critique"><i class="fas fa-plus-circle"></i> critique</a>
</div>
<ul class="item-list alterne-list">
<li class="competence-header flexrow" >
<span>Blessures</span>
<span></span>
<span>Premiers soins</span>
<span>Soins complets</span>
<span>Age (jours)</span>
<span>Localisation</span>
<span>Loc.</span>
<span>Actions</span>
</li>
{{#each system.blessures.legeres.liste as |blessure key|}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/blessure.html" blessure=blessure key=key gravite="legere" title="Légère"}}
{{/each}}
{{#each system.blessures.graves.liste as |blessure key|}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/blessure.html" blessure=blessure key=key gravite="grave" title="Grave"}}
{{/each}}
{{#each system.blessures.critiques.liste as |blessure key|}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/blessure.html" blessure=blessure key=key gravite="critique" title="Critique"}}
{{#each blessures as |blessure|}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/blessure.hbs" blessure}}
{{/each}}
</ul>

View File

@@ -1,7 +1,9 @@
<h4>Soins</h4>
<a class="chat-card-button creer-tache-blessure-legere">Blessure légère</a>
<a class="chat-card-button creer-tache-blessure-grave">Blessure grave</a>
<a class="chat-card-button creer-tache-blessure-critique">Blessure critique</a>
<div>
<a class="chat-card-button creer-tache-blessure-legere"><i class="fas fa-first-aid"></i> légère</a>
<a class="chat-card-button creer-tache-blessure-grave"><i class="fas fa-first-aid"></i> grave</a>
<a class="chat-card-button creer-tache-blessure-critique"><i class="fas fa-first-aid"></i> critique</a>
</div>
<ul class="item-list alterne-list">
{{#each taches as |tache id|}}
{{#if (eq tache.system.competence 'Chirurgie')}}

View File

@@ -1,4 +1,4 @@
<span>
<div>
{{#if effects}}
{{#each effects as |effect key|}}
<span class="active-effect" data-effect="{{effect.flags.core.statusId}}">
@@ -9,4 +9,4 @@
{{else}}
Aucun effet actif
{{/if}}
</span>
</div>

View File

@@ -1,8 +1,8 @@
<div class="flex-group-left header-etats">
<div class="flexcol">
<span>{{system.compteurs.etat.label}}: {{system.compteurs.etat.value}}</span>
<span>Sur-encombrement: {{calc.surenc}}</span>
<span>{{calc.resumeBlessures}}</span>
<div>{{system.compteurs.etat.label}}: {{system.compteurs.etat.value}}</div>
<div>Sur-encombrement: {{calc.surenc}}</div>
<div>{{calc.resumeBlessures}}</div>
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/header-effects.html"}}
</div>
</div>

View File

@@ -1,17 +1,18 @@
{{#if isGM}}
{{log this}}
<span>
{{#if (gt endurance 0)}}
De plus, {{alias}} a perdu {{endurance}} points d'endurance
{{#if (ne vie 0)}}et <span class="rdd-roll-echec">{{vie}} points de vie</span>{{/if}}
{{/if}}
{{#if (gt endurance 1)}}Jet d'endurance : {{jetEndurance}} / {{resteEndurance}} {{/if}}
{{#if (and jetEndurance (gt endurance 1))}}Jet d'endurance : {{jetEndurance}} / {{resteEndurance}} {{/if}}
</span>
{{else}}
<h4>{{alias}} encaisse à
<span>
{{numberFormat dmg.total decimals=0 sign=true}}
{{#if (eq dmg.mortalite 'non-mortel')~}}(coups non mortels)
{{~else if (eq dmg.mortalite 'cauchemar')}}(entité de cauchemar)
{{~else if (eq dmg.mortalite 'entiteincarnee')}}(entité incarnée)
{{~/if}}
</span>
</h4>
@@ -22,15 +23,16 @@
{{~/unless}}, total: <span class="rdd-roll-echec">{{total}}</span>
<br>
{{alias}}
{{#if (eq dmg.mortalite 'cauchemar')}}subit le coup
{{else if eraflures}}subit une contusion
{{else if legeres}}subit une blessure légère
{{else if graves}}subit une blessure grave
{{else if critiques}}subit une blessure critique
{{#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}}
{{else}}subit une contusion
{{~/if~}}
{{else}}s'en sort sans une égratignure
{{~/if~}}
{{~#unless (eq dmg.mortalite 'cauchemar')}}
{{~#unless (eq dmg.mortalite 'entiteincarnee')}}
{{#if dmg.loc.label}}
{{#if (gt roll.total 0)}}({{dmg.loc.label}}){{/if}}
{{/if}}
@@ -39,7 +41,7 @@
{{~#if hasPlayerOwner}}, a perdu {{endurance}} points d'endurance
{{#if (ne vie 0)}}, <span class="rdd-roll-echec">{{vie}} points de vie</span>{{/if}}
{{/if}}
{{#if (ne dmg.mortalite 'cauchemar')}}
{{#if (ne dmg.mortalite 'entiteincarnee')}}
{{#if (gt endurance 1)}}et
{{#if sonne}}est <strong>sonné</strong><img class="chat-icon" src="icons/svg/stoned.svg" alt="charge" height="16" width="16" /> jusqu'à la fin du prochain round{{else}}n'est pas sonné{{/if}}!
{{#if hasPlayerOwner}}Jet d'endurance : Jet d'endurance : {{jetEndurance}} / {{resteEndurance}}{{/if}}

View File

@@ -1,9 +1,9 @@
<div class="control-icon rdd-combat ">
<img class="rdd-hud-togglebutton" src="systems/foundryvtt-reve-de-dragon/icons/heures/hd06.svg" width="36" height="36" title="Attaque"/>
<div class="rdd-hud-list tokenhudext left">
<div class="rdd-hud-list token-hud-ext left">
{{#each actions as |action key|}}
{{#unless action.system.initOnly}}
<div class="control-icon tokenhudicon rdd-hud-menu rdd-attaque"
<div class="control-icon token-hud-icon rdd-hud-menu rdd-attaque"
data-combatant-id="{{../combatant.id}}"
data-action-index="{{action.index}}"
title="{{action.name}}">

View File

@@ -1,8 +1,8 @@
<div class="control-icon rdd-initiative ">
<img class="rdd-hud-togglebutton" src="icons/svg/sword.svg" width="36" height="36" title="Initiative" />
<div class="rdd-hud-list tokenhudext right">
<div class="rdd-hud-list token-hud-ext right">
{{#each actions as |action key|}}
<div class="control-icon tokenhudicon rdd-hud-menu"
<div class="control-icon token-hud-icon rdd-hud-menu"
data-combatant-id="{{../combatant.id}}"
data-action-index="{{action.index}}"
title="{{action.name}}">
@@ -10,7 +10,7 @@
</div>
{{/each}}
{{#each commandes as |commande key|}}
<div class="control-icon tokenhudicon rdd-hud-menu"
<div class="control-icon token-hud-icon rdd-hud-menu"
data-command="{{commande.command}}"
data-combatant-id="{{../combatant.id}}"
data-action-index="{{commande.index}}"

View File

@@ -0,0 +1,12 @@
<div class="control-icon rdd-soins ">
<img class="rdd-hud-togglebutton" src="icons/svg/regen.svg" width="36" height="36" title="Soins" />
<div class="rdd-hud-list token-hud-ext soins">
{{#each blessures as |blessure|}}
<div class="control-icon token-hud-icon rdd-hud-menu"
data-blessure-id="{{blessure.id}}"
title="{{blessure.name}}">
<label>Soigner: {{blessure.name}}</label>
</div>
{{/each}}
</div>
</div>

View File

@@ -0,0 +1,57 @@
<form class="{{cssClass}}" autocomplete="off">
{{>"systems/foundryvtt-reve-de-dragon/templates/header-item.html"}}
<section class="sheet-body">
<div class="form-group">
<label for="system-gravite">Gravité</label>
<select name="system-gravite" class="gravite" data-dtype="Number">
{{#select system.gravite}}
<option value="0">Contusion / Eraflure</option>
<option value="2">Légère</option>
<option value="4">Grave</option>
<option value="6">Critique</option>
<option value="8">Mort</option>
{{/select}}
</select>
</div>
<div class="form-group">
<label for="system.localisation">Localisation</label>
<input class="attribute-value" type="text" name="system.localisation" value="{{system.localisation}}" data-dtype="String"/>
</div>
{{#if (lt system.gravite 7)}}
<div class="form-group">
<label for="system.difficulte">Difficulté des soins</label>
<input class="attribute-value number-x" type="text" name="system.difficulte" value="{{system.difficulte}}" data-dtype="Number"/>
</div>
<div class="form-group">
<label for="premierssoins-done">Premiers soins
<input class="attribute-value" type="checkbox" name="premierssoins-done" {{#if system.premierssoins.done}}checked{{/if}}/>
</label>
{{#if system.premierssoins.done}}
{{#unless system.soinscomplets.done}}
<input class="attribute-value number-x" type="text" name="system.premierssoins.bonus" value="{{system.premierssoins.bonus}}" data-dtype="Number"/>
{{/unless}}
{{else}}
<label for="system.premierssoins.tache">Points de tâches</label>
<input class="attribute-value number-x" type="text" name="system.premierssoins.tache" value="{{system.premierssoins.tache}}" data-dtype="Number"/>
{{/if}}
</div>
{{#if system.premierssoins.done}}
<div class="form-group">
<label for="soinscomplets-done">Soins complets
<input class="attribute-value" type="checkbox" name="soinscomplets-done" {{#if system.soinscomplets.done}}checked{{/if}}/>
</label>
{{#if system.soinscomplets.done}}
<input class="attribute-value number-x" type="text" name="system.soinscomplets.bonus" value="{{system.soinscomplets.bonus}}" data-dtype="Number"/>
{{/if}}
</div>
{{/if}}
{{/if}}
{{#if options.isOwned}}
{{>"systems/foundryvtt-reve-de-dragon/templates/item/temporel.hbs" this labeldebut="Obtenue" labelfin="Prochain jet"}}
{{/if}}
</section>
</form>