Gestion des signes draconiques #455

Closed
vincent.vandeme wants to merge 233 commits from v1.4-signes-draconiques into master
23 changed files with 492 additions and 115 deletions
Showing only changes of commit 62261d1748 - Show all commits

View File

@ -11,6 +11,7 @@ import { RdDBonus } from "./rdd-bonus.js";
import { Misc } from "./misc.js";
import { RdDCombatManager } from "./rdd-combat.js";
import { RdDCarac } from "./rdd-carac.js";
import { RdDItem } from "./item.js";
/* -------------------------------------------- */
export class RdDActorSheet extends ActorSheet {
@ -183,7 +184,7 @@ export class RdDActorSheet extends ActorSheet {
/* -------------------------------------------- */
async selectObjetType() {
let typeObjets = ["objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", "monnaie"];
let typeObjets = RdDItem.getTypeObjetsEquipement();
let options = `<span class="competence-label">Selectionnez le type d'équipement</span><select class="item-type">`;
for (let typeName of typeObjets) {
options += `<option value="${typeName}">${typeName}</option>`
@ -205,7 +206,7 @@ export class RdDActorSheet extends ActorSheet {
/* -------------------------------------------- */
async selectTypeOeuvre() {
let typeOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu" ];
let typeOeuvres = RdDItem.getTypesOeuvres();
let options = `<span class="competence-label">Selectionnez le type d'oeuvre</span><select class="item-type">`;
for (let typeName of typeOeuvres) {
options += `<option value="${typeName}">${typeName}</option>`
@ -256,6 +257,12 @@ export class RdDActorSheet extends ActorSheet {
const li = $(ev.currentTarget).parents(".item");
RdDUtility.confirmerSuppression(this, li);
});
html.find('.item-consommer').click(ev => {
const li = $(ev.currentTarget).parents(".item");
const itemId = li.data("item-id");
const item = this.actor.getObjet(itemId);
this.actor.consommer(item);
});
html.find('.subacteur-delete').click(ev => {
const li = $(ev.currentTarget).parents(".item");
RdDUtility.confirmerSuppressionSubacteur(this, li);
@ -545,7 +552,7 @@ export class RdDActorSheet extends ActorSheet {
this.render(true);
});
html.find('#ethylisme-test').click((event) => {
this.actor.ethylismeTest();
this.actor.jetEthylisme();
this.render(true);
});

View File

@ -28,6 +28,7 @@ import { Draconique } from "./tmr/draconique.js";
import { RdDCarac } from "./rdd-carac.js";
import { Monnaie } from "./item-monnaie.js";
import { RdDHerbes } from "./rdd-herbes.js";
import { DialogConsommer } from "./dialog-consommer.js";
/* -------------------------------------------- */
@ -227,8 +228,14 @@ export class RdDActor extends Actor {
return Misc.toInt(Misc.templateData(this).attributs.protection.value);
}
/* -------------------------------------------- */
getEtatGeneral() {
return Misc.toInt(Misc.templateData(this).compteurs.etat?.value);
getEtatGeneral(options = { ethylisme: false }) {
const tplData = Misc.templateData(this);
let etatGeneral = Misc.toInt(tplData.compteurs.etat?.value);
if (options.ethylisme) {
// Pour les jets d'Ethylisme, on ignore le degré d'éthylisme (p.162)
etatGeneral -= Math.min(0, tplData.compteurs.ethylisme.value);
}
return etatGeneral;
}
getMalusArmure() {
return Misc.toInt(Misc.templateData(this).attributs?.malusarmure?.value);
@ -240,7 +247,7 @@ export class RdDActor extends Actor {
return Math.floor(Misc.templateData(this).prixTotalEquipement ?? 0);
}
getSurenc() {
return Misc.toInt(Misc.templateData(this).compteurs.surenc?.value);
return Misc.templateData(this).compteurs.surenc?.value ?? 0;
}
/* -------------------------------------------- */
getCompetence(name) {
@ -349,6 +356,7 @@ export class RdDActor extends Actor {
await this.transformerStress();
await this.retourSeuilDeReve(message);
this.bonusRecuperationPotion= 0; // Reset potion
await this.retourSust(message);
message.content = `A la fin Chateau Dormant, ${message.content}<br>Un nouveau jour se lève`;
ChatMessage.create(message);
}
@ -591,6 +599,26 @@ export class RdDActor extends Actor {
}
}
async retourSust(message) {
const tplData = Misc.templateData(this);
const sustNeeded = tplData.attributs.sust.value;
const sustConsomme = tplData.compteurs.sust.value;
const eauConsomme = tplData.compteurs.eau.value;
if (game.settings.get("foundryvtt-reve-de-dragon", "appliquer-famine-soif").includes('famine') && sustConsomme < sustNeeded) {
const perte = sustConsomme < Math.min(0.5, sustNeeded) ? 3 : (sustConsomme <= (sustNeeded / 2) ? 2 : 1);
message.content += `<br>Vous ne vous êtes sustenté que de ${sustConsomme} pour un appétit de ${sustNeeded}, vous avez faim!
La famine devrait vous faire ${perte} points d'endurance non récupérables, notez le cumul de côté et ajustez l'endurance`;
}
if (game.settings.get("foundryvtt-reve-de-dragon", "appliquer-famine-soif").includes('soif') && eauConsomme < sustNeeded) {
const perte = eauConsomme < Math.min(0.5, sustNeeded) ? 12 : (eauConsomme <= (sustNeeded / 2) ? 6 : 3);
message.content += `<br>Vous n'avez bu que ${eauConsomme} doses de liquide pour une soif de ${sustNeeded}, vous avez soif!
La soif devrait vous faire ${perte} points d'endurance non récupérables, notez le cumul de côté et ajustez l'endurance`;
}
await this.updateCompteurValue('sust', 0);
await this.updateCompteurValue('eau', 0);
}
/* -------------------------------------------- */
async combattreReveDeDragon(force) {
let rollData = {
@ -956,8 +984,9 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
detectSurEncombrement() {
return Math.max(0, Math.ceil(Number(this.data.encTotal) - this.getEncombrementMax()));
return Math.max(0, Math.ceil(Number(this.encTotal) - this.getEncombrementMax()));
}
getEncombrementMax() {
return (this.data.type == 'vehicule')
? Misc.templateData(this).capacite_encombrement
@ -980,17 +1009,11 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
computeEncombrement() {
Misc.templateData(this).encTotal = this.filterItemsData(it => it.data.encombrement)
.map(it => this._calcEncItem(it))
const tplData = Misc.templateData(this);
tplData.encTotal = this.filterItemsData(it => it.data.encombrement != undefined)
.map(it => it.data.encTotal)
.reduce(Misc.sum(), 0);
return Misc.templateData(this).encTotal;
}
_calcEncItem(it) {
it.data.encombrement = Number(it.data.encombrement ?? 0);
it.data.quantite = Math.min(1, Number(it.data.quantite ?? 1));
it.data.encTotal = it.data.encombrement * it.data.quantite;
return it.data.encTotal;
return tplData.encTotal;
}
/* -------------------------------------------- */
@ -1007,17 +1030,12 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
computePrixTotalEquipement() {
let prixTotalEquipement = 0;
// prix total de l'équipement est la somme du cout de chaque équipement multiplié par sa quantité.
for (const itemData of this.filterItemsData(it => it?.data.cout)) {
const cout = Math.min(Number(itemData.data.cout ?? 0), 0);
const quantite = Math.min(Number(itemData.data?.quantite ?? 1), 1);
prixTotalEquipement += cout * quantite;
}
const tplData = Misc.templateData(this);
tplData.prixTotalEquipement = this.filterItemsData(it => it.data.prixTotal)
.map(it => it.data.prixTotal ?? 0)
.reduce(Misc.sum(), 0);
// Mise à jour valeur totale de l'équipement
Misc.templateData(this).prixTotalEquipement = prixTotalEquipement;
return prixTotalEquipement;
return tplData.prixTotalEquipement;
}
/* -------------------------------------------- */
@ -1068,7 +1086,7 @@ export class RdDActor extends Actor {
state += Math.min(0, (actorData.data.compteurs.ethylisme?.value ?? 0));
actorData.data.compteurs.etat.value = state;
if (actorData.data.compteurs && actorData.data.compteurs.surenc) {
if (actorData.data.compteurs?.surenc) {
actorData.data.compteurs.surenc.value = - this.detectSurEncombrement();
}
}
@ -1471,8 +1489,8 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
_calculAjustementMoral(succes, moral, situation) {
switch (situation) {
case 'heureuse': return succes ? 1 : 0;
case 'malheureuse': return succes ? 0 : -1;
case 'heureux': case 'heureuse': return succes ? 1 : 0;
case 'malheureuse': case 'malheureux': return succes ? 0 : -1;
case 'neutre':
if (succes && moral <= 0) return 1;
if (!succes && moral > 0) return -1;
@ -1492,19 +1510,18 @@ export class RdDActor extends Actor {
}
/* -------------------------------------------- */
async ethylismeTest() {
async jetEthylisme(forceAlcool = 0) {
const actorData = Misc.data(this);
let rollData = {
vieValue: actorData.data.sante.vie.value,
etat: this.getEtatGeneral() - Math.min(0, actorData.data.compteurs.ethylisme.value), // Pour les jets d'Ethylisme, on ignore le degré d'éthylisme (p.162)
forceAlcool: forceAlcool,
etat: this.getEtatGeneral({ ethylisme: true }),
diffNbDoses: -Number(actorData.data.compteurs.ethylisme.nb_doses || 0),
finalLevel: 0,
diffConditions: 0,
ajustementsConditions: CONFIG.RDD.ajustementsConditions,
forceAlcool: 0
diffConditions: 0
}
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-roll-ethylisme.html', rollData);
new RdDRollDialogEthylisme(html, rollData, this).render(true);
new RdDRollDialogEthylisme(html, rollData, this, r => this.performEthylisme(r)).render(true);
}
/* -------------------------------------------- */
@ -1531,7 +1548,7 @@ export class RdDActor extends Actor {
? "vous êtes libre de continuer à boire ou pas."
: "vous avez une envie irrépréssible de reprendre un verre.");
msgText += `Vous avez échoué à votre jet d'éthylisme, vous êtes
msgText += `Vous avez échoué à votre jet d'éthylisme, vous êtes
maintenant ${RdDUtility.getNomEthylisme(ajustementEthylique)} (${ajustementEthylique}).
<br> ${RdDResolutionTable.explain(rollVolonte)}
<br>Qui a bu boira : ${quiABuBoira}`;
@ -1566,6 +1583,70 @@ export class RdDActor extends Actor {
}
}
/* -------------------------------------------- */
async consommer(item) {
DialogConsommer.create(this, item, {
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-consommer-nourriture.html',
}, []);
}
async manger(sust) {
if (sust > 0) {
await this.updateCompteurValue('sust', Misc.templateData(this).compteurs.sust.value + sust);
}
}
async boire(eau) {
if (eau > 0) {
await this.actor.updateCompteurValue('eau', Misc.templateData(this).eau.value + this.consommerData.data.desaltere);
}
}
async alcool(forceAlcool) {
const actorTplData = Misc.templateData(this);
const etatGeneral = this.getEtatGeneral({ ethylisme: true });
const nbDoses = -Number(actorTplData.compteurs.ethylisme.nb_doses || 0);
let rollData = {
vieValue: actorTplData.sante.vie.value,
forceAlcool: forceAlcool,
etat: etatGeneral,
diffNbDoses: nbDoses,
finalLevel: nbDoses + forceAlcool + etatGeneral,
diffConditions: 0,
};
await this.performEthylisme(rollData);
}
async apprecierCuisine(consommerData) {
const cuisine = Misc.data(this.getCompetence('cuisine'));
const qualite = consommerData.data.qualite;
if (cuisine && qualite > 0 && qualite > cuisine.data.niveau) {
const rolled = await this.rollCaracCompetence('gout', 'cuisine', qualite, { title: consommerData.data.boisson ? "apprécie la boisson" : "apprécie le plat" });
if (rolled.isSuccess) {
await this.jetDeMoral('heureux');
}
}
}
async surmonterExotisme(consommerData) {
const qualite = consommerData.data.qualite;
if (qualite < 0) {
const rolled = await this.rollCaracCompetence('volonte', 'cuisine', qualite, { title: "tente de surmonter l'exotisme" });
if (rolled.isEchec) {
if (!consommerData.data.seForcer) {
return false;
}
await this.actor.jetDeMoral('malheureux');
}
}
return true;
}
async jetGoutCuisine() {
console.info('Jet de Gout/Cuisine');
return true;
}
/* -------------------------------------------- */
async transformerStress() {
const actorData = Misc.data(this);
@ -1979,7 +2060,7 @@ export class RdDActor extends Actor {
RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-general.html');
}
async rollCaracCompetence(caracName, compName, diff) {
async rollCaracCompetence(caracName, compName, diff, options = { title: "" }) {
const carac = this.getCaracByName(caracName);
if (!carac) {
ui.notifications.warn(`${this.name} n'a pas de caractéristique correspondant à ${caracName}`)
@ -1998,11 +2079,12 @@ export class RdDActor extends Actor {
finalLevel: (competence?.data.niveau ?? 0) + diff,
diffLibre: diff,
showDice: true,
show: { title: "Jets multiples" }
show: { title: options?.title ?? '' }
};
await RdDResolutionTable.rollData(rollData);
this.appliquerExperience(rollData);
RdDResolutionTable.displayRollData(rollData, this)
return rollData.rolled;
}
/* -------------------------------------------- */
@ -3095,7 +3177,7 @@ export class RdDActor extends Actor {
return guerisonData;
}
/* -------------------------------------------- */
/* -------------------------------------------- */
async consommerPotionSoin(potionData) {
potionData.alias = this.name;

124
module/dialog-consommer.js Normal file
View File

@ -0,0 +1,124 @@
import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
export class DialogConsommer extends Dialog {
static async create(actor, item, dialogConfig) {
let consommerData = DialogConsommer.prepareData(actor, item);
if (!consommerData) {
ui.notifications.warn(`Impossible de consommer un ${consommerData.name}, ce n'est pas de la nourriture, une boisson ou une potion`);
return;
}
let conf = {
title: consommerData.title,
content: await renderTemplate(dialogConfig.html, consommerData),
default: consommerData.buttonName,
};
let options = { classes: ["dialogconsommer"], width: 600, height: 500, 'z-index': 99999 };
mergeObject(options, dialogConfig.options ?? {}, { overwrite: true })
console.log('consommer', actor, consommerData, conf, options);
const dialog = new DialogConsommer(actor, consommerData, conf, options);
dialog.render(true);
return dialog;
}
static prepareData(actor, item) {
let consommerData = duplicate(Misc.data(item));
switch (consommerData.type) {
default:
return undefined;
case 'nourritureboisson':
consommerData.doses = 1;
consommerData.title = consommerData.data.boisson ? `${consommerData.name}: boire une dose` : `${consommerData.name}: manger une portion`;
consommerData.buttonName = consommerData.data.boisson ? "Boire" : "Manger";
break;
case 'potion':
buttonName.title = `${consommerData.name}: boire la potion`;
consommerData.buttonName = "Boire";
consommerData.alchimie = Misc.data(actor.getCompetence('alchimie'));
break;
}
consommerData.cuisine = Misc.data(actor.getCompetence('cuisine'));
consommerData.seForcer = false;
return consommerData;
}
constructor(actor, consommerData, conf, options) {
conf.buttons = {
[consommerData.buttonName]: {
label: consommerData.buttonName, callback: it => {
this.consommer();
}
}
};
super(conf, options);
this.actor = actor;
this.consommerData = consommerData;
}
activateListeners(html) {
super.activateListeners(html);
function updateConsommerData(rollData) {
rollData.finalLevel = Number(rollData.etat) + Number(rollData.forceAlcool) + rollData.diffNbDoses;
// Mise à jour valeurs
$("#roll-param").text(rollData.vieValue + " / " + Misc.toSignedString(rollData.finalLevel));
$(".table-resolution").remove();
$("#resolutionTable").append(RdDResolutionTable.buildHTMLTableExtract(rollData.vieValue, rollData.finalLevel));
}
html.find(".consommer-doses").change(event => {
this.u
});
}
/* -------------------------------------------- */
async consommer() {
switch (this.consommerData.type) {
default:
return undefined;
case 'nourritureboisson':
return await this.consommerNourritureBoisson();
case 'potion':
return await this.consommerPotion();
}
}
async consommerNourritureBoisson() {
const surmonteExotisme = await this.actor.surmonterExotisme(this.consommerData);
if (!surmonteExotisme) {
return;
}
await this.actor.apprecierCuisine(this.consommerData);
if (this.isAlcool()) {
await this.actor.alcool(this.consommerData.data.force);
}
await this.actor.manger(this.consommerData.data.sust);
await this.actor.boire(this.consommerData.data.desaltere);
}
isAlcool() {
return this.consommerData.data.boisson && this.consommerData.data.alcoolise;
}
async apprecierCuisine(qualite) {
const jetGoutCuisine = await this.jetGoutCuisine();
if (jetGoutCuisine) {
await this.actor.jetDeMoral('heureux');
}
}
async consommerPotion() {
}
}

View File

@ -1,6 +1,6 @@
import { RdDItemSort } from "./item-sort.js";
import { RdDUtility } from "./rdd-utility.js";
import { RdDItem } from "./item-rdd.js";
import { RdDItem } from "./item.js";
import { RdDAlchimie } from "./rdd-alchimie.js";
import { RdDItemCompetence } from "./item-competence.js";
import { RdDHerbes } from "./rdd-herbes.js";

View File

@ -1,9 +1,32 @@
import { Misc } from "./misc.js";
import { RdDUtility } from "./rdd-utility.js";
const typesObjetsEquipement = ["objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", "nourritureboisson"];
const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"];
/* -------------------------------------------- */
export class RdDItem extends Item {
static getTypeObjetsEquipement() {
return typesObjetsEquipement;
}
static getTypesOeuvres() {
return typesObjetsOeuvres;
}
prepareDerivedData() {
super.prepareDerivedData();
const itemData = this.data;
const tplData = itemData.data;
if (RdDItem.getTypeObjetsEquipement().includes(itemData.type)) {
const quantite = itemData.type == 'conteneur' ? 1 : (tplData.quantite ?? 0);
if (tplData.encombrement != undefined) {
tplData.encTotal = Math.max(tplData.encombrement, 0) * quantite;
}
if (tplData.cout != undefined) {
tplData.prixTotal = Math.max(tplData.cout, 0) * quantite;
}
}
}
/* -------------------------------------------- */
async postItem() {
console.log(this);
@ -17,13 +40,13 @@ export class RdDItem extends Item {
chatData.data.cout_deniers = 0;
let dialogResult = [-1, -1]; // dialogResult[0] = quantité, dialogResult[1] = prix
if (chatData.hasPrice )
{
if (chatData.hasPrice) {
let sols = chatData.data.cout;
chatData.data.cout_deniers = Math.floor(sols * 100);
dialogResult = await new Promise( (resolve, reject) => {new Dialog({
content :
`<p>Modifier la quantité?</p>
dialogResult = await new Promise((resolve, reject) => {
new Dialog({
content:
`<p>Modifier la quantité?</p>
<div class="form-group">
<label> Quantité</label>
<input name="quantity" type="text" value="1"/>
@ -34,43 +57,40 @@ export class RdDItem extends Item {
<input name="price" type="text" value="${chatData.data.cout}"/>
</div>
`,
title : "Quantité & Prix",
buttons : {
post : {
label : "Soumettre",
title: "Quantité & Prix",
buttons: {
post: {
label: "Soumettre",
callback: (dlg) => {
resolve( [ dlg.find('[name="quantity"]').val(), dlg.find('[name="price"]').val() ] )
resolve([dlg.find('[name="quantity"]').val(), dlg.find('[name="price"]').val()])
}
},
}
}).render(true)
})
}
if (dialogResult[0] > 0)
{
if (this.isOwned)
{
}
if (dialogResult[0] > 0) {
if (this.isOwned) {
if (itemData.data.quantite == 0)
dialogResult[0] = -1
else if (itemData.data.quantite < dialogResult[0])
{
else if (itemData.data.quantite < dialogResult[0]) {
dialogResult[0] = itemData.data.quantite;
ui.notifications.notify(`Impossible de poster plus que ce que vous avez. La quantité à été réduite à ${dialogResult[0]}.`)
this.update({"data.quantite" : 0})
ui.notifications.notify(`Impossible de poster plus que ce que vous avez. La quantité à été réduite à ${dialogResult[0]}.`)
this.update({ "data.quantite": 0 })
}
else {
ui.notifications.notify(`Quantité réduite par ${dialogResult[0]}.`)
this.update({"data.quantite" : itemData.data.quantite - dialogResult[0]})
ui.notifications.notify(`Quantité réduite par ${dialogResult[0]}.`)
this.update({ "data.quantite": itemData.data.quantite - dialogResult[0] })
}
}
}
if ( chatData.hasPrice ) {
if (chatData.hasPrice) {
if (dialogResult[0] > 0)
chatData.postQuantity = Number(dialogResult[0]);
if (dialogResult[1] > 0) {
chatData.postPrice = dialogResult[1];
chatData.postPrice = dialogResult[1];
chatData.data.cout_deniers = Math.floor(dialogResult[1] * 100); // Mise à jour cout en deniers
}
chatData.finalPrice = Number(chatData.postPrice) * Number(chatData.postQuantity);
@ -81,14 +101,14 @@ export class RdDItem extends Item {
// Don't post any image for the item (which would leave a large gap) if the default image is used
if (chatData.img.includes("/blank.png"))
chatData.img = null;
// JSON object for easy creation
chatData.jsondata = JSON.stringify(
{
compendium : "postedItem",
payload: itemData,
});
{
compendium: "postedItem",
payload: itemData,
});
renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-item.html', chatData).then(html => {
let chatOptions = RdDUtility.chatDataSetup(html);
ChatMessage.create(chatOptions)

View File

@ -14,7 +14,7 @@ const typeDisplayName = {
"ombre": "Ombre de Thanatos",
"souffle": "Souffle de Dragon",
"tete": "Tête de Dragon",
"ingredient": "Ingrédient",
"nourritureboisson": "Nourriture & boisson",
"rencontresTMR": "Rencontre des TMR",
"competencecreature": "Compétence de créature",
"nombreastral": "Nombre astral",

View File

@ -29,6 +29,7 @@ import { TMRRencontres } from "./tmr-rencontres.js";
import { RdDHotbar } from "./rdd-hotbar-drop.js"
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
import { RdDHerbes } from "./rdd-herbes.js";
import { RdDItem } from "./item.js";
/* -------------------------------------------- */
/* Foundry VTT Initialization */
@ -116,6 +117,20 @@ Hooks.once("init", async function () {
default: true,
type: Boolean
});
/* -------------------------------------------- */
game.settings.register("foundryvtt-reve-de-dragon", "appliquer-famine-soif", {
name: "Notifier de la famine et la soif pour",
hint: "Indique si les cas de famine et de soif seront indiqués durant Château Dormant",
scope: "world",
config: true,
type: String,
choices: {
"aucun": "ni la famine, ni la soif",
"famine": "seulement la famine",
"famine-soif": "la famine et la soif",
},
default: "aucun"
});
/* -------------------------------------------- */
// Set an initiative formula for the system
@ -134,6 +149,7 @@ Hooks.once("init", async function () {
/* -------------------------------------------- */
// Define custom Entity classes
CONFIG.Actor.documentClass = RdDActor;
CONFIG.Item.documentClass = RdDItem;
CONFIG.RDD = {
resolutionTable: RdDResolutionTable.resolutionTable,
carac_array: RdDUtility.getCaracArray(),

View File

@ -8,34 +8,39 @@ import { Misc } from "./misc.js";
export class RdDRollDialogEthylisme extends Dialog {
/* -------------------------------------------- */
constructor(html, rollData, actor) {
let myButtons = {
rollButton: { label: "Test d'éthylisme", callback: html => this.actor.performEthylisme(this.rollData) }
};
constructor(html, rollData, actor, onRoll) {
// Common conf
let dialogConf = { content: html, title: "Test d'éthylisme", buttons: myButtons, default: "rollButton" };
let dialogOptions = { classes: ["rdddialog"], width: 400, height: 220, 'z-index': 99999 }
let dialogConf = {
title: "Test d'éthylisme",
content: html,
default: "rollButton",
buttons: { "rollButton": { label: "Test d'éthylisme", callback: html => this.onButton(html) } }
};
let dialogOptions = { classes: ["rdddialog"], width: 400, height: 220, 'z-index': 99999 }
super(dialogConf, dialogOptions)
//console.log("ETH", rollData);
this.onRoll = onRoll;
this.rollData = rollData;
this.actor = actor;
}
async onButton(html) {
this.onRoll(this.rollData);
}
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
this.bringToTop(); // Ensure top level
// Get the rollData stuff
var rollData = this.rollData;
function updateRollResult(rollData) {
rollData.finalLevel = Number(rollData.etat) + Number(rollData.forceAlcool) + rollData.diffNbDoses;
// Mise à jour valeurs
$("#roll-param").text(rollData.vieValue + " / " + Misc.toSignedString(rollData.finalLevel));
$(".table-resolution").remove();
@ -47,7 +52,7 @@ export class RdDRollDialogEthylisme extends Dialog {
$("#forceAlcool").val(Misc.toInt(rollData.forceAlcool));
updateRollResult(rollData);
});
// Update !
html.find('#forceAlcool').change((event) => {
rollData.forceAlcool = Misc.toInt(event.currentTarget.value); // Update the selected bonus/malus

View File

@ -129,6 +129,7 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/item-ombre-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-monnaie-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-meditation-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-nourritureboisson-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/competence-carac-defaut.html',
'systems/foundryvtt-reve-de-dragon/templates/competence-base.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.html',
@ -248,6 +249,7 @@ export class RdDUtility {
formData.tetes = this.checkNull(formData.itemsByType['tete']);
formData.taches = this.checkNull(formData.itemsByType['tache']);
formData.monnaie = this.checkNull(formData.itemsByType['monnaie']);
formData.nourritureboissons = this.checkNull(formData.itemsByType['nourritureboisson']);
formData.meditations = this.checkNull(formData.itemsByType['meditation']);
formData.chants = this.checkNull(formData.itemsByType['chant']);
formData.danses = this.checkNull(formData.itemsByType['danse']);
@ -263,7 +265,8 @@ export class RdDUtility {
.concat(formData.livres)
.concat(formData.potions)
.concat(formData.herbes)
.concat(formData.ingredients);
.concat(formData.ingredients)
.concat(formData.nourritureboissons);
formData.competences = (formData.itemsByType.competence ?? []).concat(formData.itemsByType.competencecreature ?? []);
}

View File

@ -206,7 +206,9 @@ table {border: 1px solid #7a7971;}
.flex-shrink {
flex: 'flex-shrink' ;
}
.flex-grow {
flex-grow : 3;
}
/* Styles limited to foundryvtt-reve-de-dragon sheets */
.foundryvtt-reve-de-dragon .sheet-header {

View File

@ -2,11 +2,11 @@
"name": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon",
"description": "Rêve de Dragon RPG for FoundryVTT",
"version": "1.4.2",
"version": "1.4.3",
"manifestPlusVersion": "1.0.0",
"minimumCoreVersion": "0.7.5",
"compatibleCoreVersion": "0.7.9",
"templateVersion": 112,
"minimumCoreVersion": "0.8.0",
"compatibleCoreVersion": "0.8.1",
"templateVersion": 113,
"author": "LeRatierBretonnien",
"authors": [
{

View File

@ -576,7 +576,7 @@
"Item": {
"types": ["objet", "arme", "armure", "conteneur", "competence", "sort", "herbe", "ingredient", "livre", "potion", "munition", "rencontresTMR", "queue", "ombre", "souffle",
"tete", "competencecreature", "tarot", "monnaie", "nombreastral", "tache", "meditation", "casetmr", "recettealchimique",
"musique", "chant", "danse", "jeu", "recettecuisine", "maladie", "poison", "oeuvre" ],
"musique", "chant", "danse", "jeu", "recettecuisine", "maladie", "poison", "oeuvre", "nourritureboisson" ],
"objet": {
"description": "",
"quantite": 1,
@ -854,6 +854,18 @@
"remedes": "",
"dommages":"",
"description": ""
},
"nourritureboisson": {
"description": "",
"sust": 0,
"boisson": false,
"desaltere": 0,
"alcoolise": false,
"force": 0,
"qualite": 0,
"encombrement": 0,
"quantite": 1,
"cout": 0
}
}
}

View File

@ -2,15 +2,17 @@
<img class="sheet-competence-img" src="{{item.img}}" title="{{item.name}}"/>
{{#if (eq item.type 'conteneur')}}
<span class="item-name conteneur-name"><a data-item-id="{{item._id}}">+{{item.name}}</a></span>
<span class="item-name conteneur-name flex-grow"><a data-item-id="{{item._id}}">+{{item.name}}</a></span>
{{else}}
<span class="item-name">{{item.name}}</span>
<span class="item-name flex-grow">{{item.name}}</span>
{{/if}}
<span class="item-quantite">{{item.data.quantite}}</span>
<span class="item-quantite">{{numberFormat item.data.encTotal decimals=2}}</span>
<div class="item-controls">
<div class="item-controls flex-grow">
<a class="item-control item-edit" title="Editer"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
{{#if (eq item.type 'nourritureboisson')}}
<a class="item-name item-consommer">Consommer</a>
{{/if}}
</div>
</li>

View File

@ -1,5 +1,3 @@
{{log 'calc' calc}}
<form class="{{cssClass}}" autocomplete="off">
{{!-- Sheet Header --}}
@ -748,23 +746,26 @@
<ul class="item-list alterne-list">
<li class="competence-header flexrow">
<img class="sheet-competence-img" src="systems/foundryvtt-reve-de-dragon/icons/objets/sac_a_dos.webp" title="Equipement"/>
<span class="competence-title competence-label">Nom</span>
<span class="competence-title competence-label">Q.</span>
<span class="competence-title competence-label">Enc.</span>
<span class="competence-title competence-label">Equiper/Editer/Suppr.</span>
<span class="competence-title flex-grow">Nom</span>
<span class="competence-title">Q.</span>
<span class="competence-title">Enc.</span>
<span class="competence-title flex-grow">Equiper/Editer/Suppr.</span>
</li>
{{#each objets as |item id|}}
{{#unless item.estContenu}}
{{#if (ne item.type 'conteneur')}}
<li class="item flexrow list-item" data-item-id="{{item._id}}">
<img class="sheet-competence-img" src="{{item.img}}" title="{{item.name}}"/>
<span class="item-name">{{item.name}}</span>
<span class="item-name flex-grow">{{item.name}}</span>
<span class="item-quantite">{{item.data.quantite}}</span>
<span class="item-quantite">{{numberFormat item.data.encTotal decimals=2}}</span>
<span class="item-controls">
<a class="item-control item-equip" title="Equiper">{{#if item.data.equipe}}<i class="fas fa-circle"></i>{{else}}<i class="fas fa-genderless"></i>{{/if}}</a>
<a class="item-control item-edit" title="Editer"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
<span class="item-controls flex-grow">
<a class="item-control item-equip" title="Equiper">{{#if item.data.equipe}}<i class="fas fa-circle"></i>{{else}}<i class="fas fa-genderless"></i>{{/if}}</a>
<a class="item-control item-edit" title="Editer"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
{{#if (and (eq item.type 'nourritureboisson') item.data.quantite)}}
<a class="item-name item-consommer">Consommer</a>
{{/if}}
</span>
</li>
{{/if}}

View File

@ -0,0 +1,39 @@
<form class="rdddialog">
<div class="form-group">
<label>Quantité de {{name}} à {{#if data.boisson}}boire{{else}}manger{{/if}}</label>
<input class="attribute-value consommer-doses" type="text" name="doses" value="{{doses}}" data-dtype="Number" />
</div>
<div>
{{#if data.sust}}
<p>
Cette {{#if data.boisson}}boisson{{else}}nourriture{{/if}} vous apportera {{data.sust}} de
sustantation.
</p>
{{/if}}
{{#if data.boisson}}
<p>{{#if data.alcoolise}}
C'est une boisson alcoolisée de force {{data.force}}, vous effectuerez un jet d'éthylisme.
{{/if}}
Cette boisson vous apportera {{data.desaltere}} unités d'eau.
</p>
{{/if}}
{{#if (gt data.qualite cuisine.data.niveau)}}
<p>La qualité du plat est telle qu'un jet de Goût/Cuisine à {{numberFormat data.qualite decimals=0 sign=true}}
vous permettra un jet de moral heureux.</p>
{{/if}}
</div>
{{#if (lt data.qualite 0)}}
<div>
<p>
Pour surmonter l'exotisme, vous devez effectuer un jet de Volonté/Cuisine à {{numberFormat data.qualite decimals=0 sign=true}}.
</p>
<p>
<label>En cas d'échec, voulez-vous vous forcer à manger (et subir un jet de moral en situation
malheureuse)?</label>
<input class="attribute-value" type="checkbox" name="se-forcer" />
</p>
</div>
{{/if}}
</form>

View File

@ -1,4 +1,4 @@
<form class="dialog-roll-sort">
<form class="rdddialog">
<div class="form-group">
<ul>
<li><label>Recette : {{recetteName}}</label></li>

View File

@ -1,4 +1,4 @@
<form class="dialog-roll-sort">
<form class="rdddialog">
<div class="form-group">
<ul>
<li><label>Chant : {{oeuvre.name}}</label></li>

View File

@ -1,4 +1,4 @@
<form class="dialog-roll-sort">
<form class="rdddialog">
<div class="form-group">
<label>Vie : {{vieValue}}</label>

View File

@ -1,4 +1,4 @@
<form class="dialog-roll-sort">
<form class="rdddialog">
<div class="form-group">
<ul>
<li><label for="competence-label">Jouer à : {{oeuvre.name}}</label></li>

View File

@ -1,4 +1,4 @@
<form class="dialog-roll-sort">
<form class="rdddialog">
<div class="form-group">
<ul>
<li><label>Jouer une Musique : {{oeuvre.name}}</label></li>

View File

@ -1,4 +1,4 @@
<form class="dialog-roll-sort">
<form class="rdddialog">
<div class="form-group">
<ul>
<li><label>Interpréter une Oeuvre : {{oeuvre.name}}</label></li>

View File

@ -1,4 +1,4 @@
<form class="dialog-roll-sort">
<form class="rdddialog">
<div class="form-group">
<ul>

View File

@ -0,0 +1,64 @@
<form class="{{cssClass}}" autocomplete="off">
<header class="sheet-header">
<img class="profile-img" src="{{img}}" data-edit="img" title="{{name}}" />
<div class="header-fields">
<h1 class="charname"><input name="name" type="text" value="{{name}}" placeholder="Name" /></h1>
</div>
</header>
{{!-- Sheet Body --}}
<section class="sheet-body">
<div class="form-group">
<label>Sustentation</label>
<input class="attribute-value" type="text" name="data.sust" value="{{data.sust}}" data-dtype="Number" />
</div>
<div class="form-group">
<label>Boisson</label>
<input class="attribute-value" type="checkbox" name="data.boisson" {{#if data.boisson}}checked{{/if}} />
</div>
{{#if data.boisson}}
<div class="form-group">
<label>Désaltère de</label>
<input class="attribute-value" type="text" name="data.desaltere" value="{{data.desaltere}}" data-dtype="Number" />
</div>
<div class="form-group">
<label>Alcoolisée</label>
<input class="attribute-value" type="checkbox" name="data.alcoolise" {{#if data.alcoolise}}checked{{/if}} />
</div>
{{#if data.alcoolise}}
<div class="form-group">
<label>Force de l'alcool par dose</label>
<input class="attribute-value" type="text" name="data.force" value="{{data.force}}" data-dtype="Number" />
</div>
{{/if}}
{{/if}}
<div class="form-group">
{{#if (lt data.qualite 0)}}
<label>Exotisme</label>
{{else}}
<label>Qualité</label>
{{/if}}
<input class="attribute-value" type="text" name="data.qualite" value="{{data.qualite}}" data-dtype="Number" />
</div>
<div class="form-group">
<label>Encombrement </label>
<input class="attribute-value" type="text" name="data.encombrement" value="{{data.encombrement}}"
data-dtype="Number" />
</div>
<div class="form-group">
<label>Quantité </label>
<input class="attribute-value" type="text" name="data.quantite" value="{{data.quantite}}" data-dtype="Number" />
</div>
<div class="form-group">
<label>Prix (sols) </label>
<input class="attribute-value" type="text" name="data.cout" value="{{data.cout}}" data-dtype="Number" />
</div>
<div class="flexcol">
<span><label>Description : </label></span>
<div class="form-group editor">
{{editor content=data.description target="data.description" button=true owner=owner editable=editable}}
</div>
</div>
</section>
</form>