Merge branch 'working' into 'master'

#24 Récupération de rêve par le sommeil

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!18
This commit is contained in:
Leratier Bretonnien 2020-11-16 08:11:54 +00:00
commit 341ca63a88
11 changed files with 300 additions and 115 deletions

View File

@ -299,6 +299,10 @@ export class RdDActorSheet extends ActorSheet {
this.actor.displayTMR( "rapide" ); this.actor.displayTMR( "rapide" );
}); });
html.find('.dormir-une-heure').click((event) => {
this.actor.dormir(1);
} );
// Display info about queue // Display info about queue
html.find('.queuesouffle-label a').click((event) => { html.find('.queuesouffle-label a').click((event) => {
let myID = event.currentTarget.attributes['data-item-id'].value; let myID = event.currentTarget.attributes['data-item-id'].value;
@ -333,6 +337,12 @@ export class RdDActorSheet extends ActorSheet {
reve.value = reveValue; reve.value = reveValue;
this.actor.update( { "data.reve.reve": reve } ); this.actor.update( { "data.reve.reve": reve } );
} ); } );
// On seuil de reve change
html.find('.seuil-reve-value').change((event) => {
console.log("seuil-reve-value", event.currentTarget)
this.actor.setPointsDeSeuil(event.currentTarget.value);
} );
// On competence change // On competence change
html.find('.competence-xp').change((event) => { html.find('.competence-xp').change((event) => {

View File

@ -10,6 +10,8 @@ import { RdDTMRDialog } from "./rdd-tmr-dialog.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { RdDDice } from "./rdd-dice.js";
import { RdDRollTables } from "./rdd-rolltables.js";
export class RdDActor extends Actor { export class RdDActor extends Actor {
@ -88,7 +90,7 @@ export class RdDActor extends Actor {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
getCurrentReve() { getReveActuel() {
return this.data.data.reve.reve.value; return this.data.data.reve.reve.value;
} }
@ -120,11 +122,10 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async performRoll(rollData) { async performRoll(rollData) {
let rolled = await RdDResolutionTable.roll(rollData.carac, rollData.finalLevel);
// Perform the roll
let rolled = await RdDResolutionTable.rollChances(rollData.rollTarget);
//rolled.isPart = true; // Pour tester le particulières //rolled.isPart = true; // Pour tester le particulières
rollData.rolled = rolled; // garder le résultat rollData.rolled = rolled; // garder le résultat
console.log("performRoll", rollData, rolled)
this.currentRollData = rollData; this.currentRollData = rollData;
if (rolled.isPart && rollData.arme && !rollData.attackerRoll) { // Réussite particulière avec attaque -> choix ! if (rolled.isPart && rollData.arme && !rollData.attackerRoll) { // Réussite particulière avec attaque -> choix !
let message = "<strong>Réussite particulière en attaque</strong>"; let message = "<strong>Réussite particulière en attaque</strong>";
@ -221,7 +222,7 @@ export class RdDActor extends Actor {
let chatOptions = { let chatOptions = {
content: "<strong>Test : " + rollData.selectedCarac.label + " / " + resumeCompetence + "</strong>" content: "<strong>Test : " + rollData.selectedCarac.label + " / " + resumeCompetence + "</strong>"
+ "<br>Difficultés <strong>libre : " + rollData.diffLibre + "</strong> / conditions : " + Misc.toSignedString(rollData.diffConditions) +" / état : " + rollData.etat + "<br>Difficultés <strong>libre : " + rollData.diffLibre + "</strong> / conditions : " + Misc.toSignedString(rollData.diffConditions) +" / état : " + rollData.etat
+ "<br>Jet : " + rolled.roll + " sur "+ rolled.score + "% (" + rollData.selectedCarac.value + " à " +Misc.toSignedString(rollData.finalLevel) + ")" + RdDResolutionTable.explain(rolled)
+ "<br><strong>" + quality + "</strong>" + "<br><strong>" + quality + "</strong>"
+ explications + xpmsg, + explications + xpmsg,
user: game.user._id, user: game.user._id,
@ -319,6 +320,76 @@ export class RdDActor extends Actor {
return explications return explications
} }
async dormir(heures=1) {
for (let i=0; i<heures; i++) {
console.log("recuperationReve", this.data.data);
/**
* TODO: récupérer les segment de fatigue
*/
this.recuperationReve();
}
}
async recuperationReve() {
const seuil = this.data.data.reve.seuil.value;
const reve = this.getReveActuel();
console.log("recuperationReve", this.data.data);
let message = { title : "Récupération" }
if (reve > seuil) {
message.content = "Vous avez déjà récupéré suffisament (seuil " + seuil + ", rêve actuel "+reve+")";
}
else {
let deRecuperation = await RdDDice.deDraconique();
console.log("recuperationReve", deRecuperation);
if (deRecuperation>=7)
{
// Rêve de Dragon !
message.content = "Vous faites un <strong>Rêve de Dragon</strong> de " + deRecuperation + " Points de rêve";
message.content += await this.combattreReveDeDragon(deRecuperation);
}
else{
message.content = "Vous récupérez " + deRecuperation + " Points de rêve";
await this.updatePointsDeReve(deRecuperation);
}
}
ChatMessage.create( message );
}
async combattreReveDeDragon(force){
let draconic = this.getBestDraconic();
let niveau = Math.max(0, draconic.data.niveau);
let etat = this.data.data.compteurs.etat.value;
let difficulte = niveau - etat - force;
let reveActuel = this.getReveActuel();
let roll = await RdDResolutionTable.roll(reveActuel, difficulte);
let message = ""
const resultatRdD = await this.appliquerReveDeDragon(roll, force);
return resultatRdD;
}
async appliquerReveDeDragon(roll, force) {
let message = "";
if (roll.isSuccess) {
message += "<br>Vous gagnez " + force + " points de Rêve";
this.updatePointDeSeuil();
await this.updatePointsDeReve(force);
}
if (roll.isPart) {
// TODO: Dialog pour choix entre HR opu général?
let tete = "à déterminer";
message += "<br>Vous gagnez une Tête de dragon: " + tete;
}
if (roll.isEchec) {
message += "<br>Vous subissez une Queue de Dragon";
this.ajouterQueue();
}
if (roll.isETotal) {
message += "<br>A cause de votre échec total, vous subissez une deuxième Queue de Dragon !"
this.ajouterQueue();
}
return message;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async sortMisEnReserve(rollData, sort) { async sortMisEnReserve(rollData, sort) {
let reserve = duplicate(this.data.data.reve.reserve); let reserve = duplicate(this.data.data.reve.reserve);
@ -331,6 +402,11 @@ export class RdDActor extends Actor {
updateCarac( caracName, caracValue ) updateCarac( caracName, caracValue )
{ {
let caracpath = "data.carac." + caracName + ".value" let caracpath = "data.carac." + caracName + ".value"
if (caracName == reve) {
if (caracValue > Misc.toInt(this.data.data.reve.seuil.value)) {
this.setPointDeSeuil(caracValue);
}
}
this.update( { caracpath: caracValue } ); this.update( { caracpath: caracValue } );
} }
@ -364,7 +440,7 @@ export class RdDActor extends Actor {
for(let troncName of troncList) { for(let troncName of troncList) {
message += "<br>" + troncName; message += "<br>" + troncName;
} }
ChatMessage.create( { title : "Compétence Tron", ChatMessage.create( { title : "Compétence Tronc",
content: message } ); content: message } );
} }
const update = {_id: comp._id, 'data.niveau': maxNiveau }; const update = {_id: comp._id, 'data.niveau': maxNiveau };
@ -499,18 +575,47 @@ export class RdDActor extends Actor {
let total = new Roll("d20").roll().total; let total = new Roll("d20").roll().total;
if ( total <= refoulement.value ) { if ( total <= refoulement.value ) {
refoulement.value = 0; refoulement.value = 0;
this.ajouterSouffle();
let souffle = RdDRollTables.getSouffle();
ChatMessage.create( { title : "Souffle de Dragon",
content: game.user.name + " subit un Souffle de Dragon : " + souffle.name } );
this.actor.createOwnedItem(souffle);
ret = "souffle"; ret = "souffle";
} }
await this.update( {"data.reve.refoulement": refoulement } ); await this.update( {"data.reve.refoulement": refoulement } );
return ret; return ret;
} }
ajouterSouffle() {
let souffle = RdDRollTables.getSouffle();
// ChatMessage.create({
// title: "Souffle de Dragon",
// content: this.name + " subit un Souffle de Dragon : " + souffle.name
// });
// this.actor.createOwnedItem(souffle);
}
async ajouterQueue() {
// TODO: Déterminer si Thanatos a été utilisé? => laisser le joueur ne pas choisir Thanatos => choisir sa voie?
let utiliseThanatos = false;
let queue;
if (utiliseThanatos) {
queue = await RdDRollTables.getOmbre();
// mettre à jour: plus d'ombre en vue
}
else {
queue = await RdDRollTables.getQueue();
}
/*
// TODO: convertir la queue obtenue en nouvel item ...
// ou bien l'ajouter à la liste spécifique => this.data.data.reve.queues
this.createOwnedItem(queue);
ChatMessage.create({
title: "Queue de Dragon",
content: this.name + " subit un Queue de Dragon : " + queue.name
});
return queue.name;
*/
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async deleteTMRRencontreAtPosition( ) { async deleteTMRRencontreAtPosition( ) {
@ -552,7 +657,21 @@ export class RdDActor extends Actor {
reve.value = Math.max(reve.value + value, 0); reve.value = Math.max(reve.value + value, 0);
await this.update( {"data.reve.reve": reve } ); await this.update( {"data.reve.reve": reve } );
} }
async updatePointDeSeuil(value=1) {
const seuil = Misc.toInt(this.data.data.reve.seuil.value);
const reve = Misc.toInt(this.data.data.carac.reve.value);
if (seuil < reve) {
await this.setPointsDeSeuil(Math.min(seuil+value, reve));
}
}
async setPointsDeSeuil( value ) {
let seuil = duplicate(this.data.data.reve.seuil);
seuil.value = value;
await this.update( {"data.reve.seuil": seuil } );
}
/* -------------------------------------------- */ /* -------------------------------------------- */
testSiSonne( sante, endurance ) testSiSonne( sante, endurance )
{ {
@ -563,7 +682,7 @@ export class RdDActor extends Actor {
sante.sonne.value = true; sante.sonne.value = true;
if (result == 1) { if (result == 1) {
sante.sonne.value = false; sante.sonne.value = false;
let xp = parseInt(this.data.data.carac.constitution.xp) + parseInt(1); let xp = Misc.toInt(this.data.data.carac.constitution.xp) + 1;
this.update( {"data.carac.constitution.xp": xp } ); // +1 XP ! this.update( {"data.carac.constitution.xp": xp } ); // +1 XP !
// TODO : Output to chat // TODO : Output to chat
} }
@ -767,7 +886,7 @@ export class RdDActor extends Actor {
let carac; let carac;
if ( caracName == "reveActuel") { // Fake carac for Reve Actuel if ( caracName == "reveActuel") { // Fake carac for Reve Actuel
carac = {type: "number", carac = {type: "number",
value: this.data.data.reve.reve.value, value: this.getReveActuel(),
label: "Rêve Actuel" label: "Rêve Actuel"
} }
} else { } else {
@ -804,7 +923,7 @@ export class RdDActor extends Actor {
if (mode != "visu") if (mode != "visu")
{ {
let minReveValue = (isRapide) ? 3 : 2; let minReveValue = (isRapide) ? 3 : 2;
if (this.data.data.reve.reve.value <= minReveValue ) { if (this.getReveActuel() < minReveValue ) {
ChatMessage.create( { title: "Montée impossible !", content: "Vous n'avez plus assez de Points de Reve pour monter dans les Terres Médianes", ChatMessage.create( { title: "Montée impossible !", content: "Vous n'avez plus assez de Points de Reve pour monter dans les Terres Médianes",
whisper: ChatMessage.getWhisperRecipients(game.user.name) } ); whisper: ChatMessage.getWhisperRecipients(game.user.name) } );
return; return;
@ -816,7 +935,7 @@ export class RdDActor extends Actor {
draconic: this.getDraconicList(), draconic: this.getDraconicList(),
sort: this.getSortList(), sort: this.getSortList(),
caracReve: this.data.data.carac.reve.value, caracReve: this.data.data.carac.reve.value,
pointsReve: this.data.data.reve.reve.value, pointsReve: this.getReveActuel(),
isRapide: isRapide isRapide: isRapide
} }
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html', data ); let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html', data );

38
module/rdd-dice.js Normal file
View File

@ -0,0 +1,38 @@
export class RdDDice {
static async deDraconique() {
let roll = new Roll("1d8x8").evaluate();
await this.show(roll);
return roll.total - Math.ceil(roll.total / 8);
}
static async show(roll, rollMode = "roll") {
await this.showDiceSoNice(roll, rollMode);
return roll;
}
/* -------------------------------------------- */
static async showDiceSoNice(roll, rollMode = "roll") {
if (game.modules.get("dice-so-nice") && game.modules.get("dice-so-nice").active) {
let whisper = null;
let blind = false;
switch (rollMode) {
case "blindroll": //GM only
blind = true;
case "gmroll": //GM + rolling player
let gmList = game.users.filter(user => user.isGM);
let gmIDList = [];
gmList.forEach(gm => gmIDList.push(gm.data._id));
whisper = gmIDList;
break;
case "roll": //everybody
let userList = game.users.filter(user => user.active);
let userIDList = [];
userList.forEach(user => userIDList.push(user.data._id));
whisper = userIDList;
break;
}
await game.dice3d.showForRoll(roll, game.user, true, whisper, blind);
}
}
}

View File

@ -1,4 +1,5 @@
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDDice } from "./rdd-dice.js";
/** /**
* difficultés au delà de -10 * difficultés au delà de -10
@ -67,52 +68,38 @@ export class RdDResolutionTable {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getResultat(code) static getResultat(code) {
{
let resultat = reussites.filter(r => code == r.code); let resultat = reussites.filter(r => code == r.code);
if (resultat == undefined) if (resultat == undefined) {
{
resultat = reussites.find(r => r.code == "error"); resultat = reussites.find(r => r.code == "error");
} }
return resultat; return resultat;
} }
/* -------------------------------------------- */ static explain(rolled) {
static roll(carac, difficulte) { let message = "<br>Jet : <strong>" + rolled.roll + "</strong> sur " + rolled.score + "%";
const chances = this.computeChances(carac, difficulte); if (rolled.carac != null && rolled.finalLevel!= null) {
let rolled = this.rollChances(chances); message += " (" + rolled.carac + " à " + Misc.toSignedString(rolled.finalLevel) + ")";
return rolled;
}
/* -------------------------------------------- */
static async showDiceSoNice(roll, rollMode = "roll") {
if (game.modules.get("dice-so-nice") && game.modules.get("dice-so-nice").active) {
let whisper = null;
let blind = false;
switch (rollMode) {
case "blindroll": //GM only
blind = true;
case "gmroll": //GM + rolling player
let gmList = game.users.filter(user => user.isGM);
let gmIDList = [];
gmList.forEach(gm => gmIDList.push(gm.data._id));
whisper = gmIDList;
break;
case "roll": //everybody
let userList = game.users.filter(user => user.active);
let userIDList = [];
userList.forEach(user => userIDList.push(user.data._id));
whisper = userIDList;
break;
}
await game.dice3d.showForRoll(roll, game.user, true, whisper, blind);
} }
return message;
}
/* -------------------------------------------- */
static async roll(carac, finalLevel, showDice=false) {
let chances = this.computeChances(carac, finalLevel);
chances.showDice = showDice;
let rolled = await this.rollChances(chances);
rolled.carac = carac;
rolled.finalLevel = finalLevel;
return rolled;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async rollChances(chances) { static async rollChances(chances) {
let myRoll = new Roll("d100").roll(); let myRoll = new Roll("d100").roll();
await this.showDiceSoNice(myRoll ); if (chances.showDice) {
await RdDDice.showDiceSoNice(myRoll);
}
chances.roll = myRoll.total; chances.roll = myRoll.total;
mergeObject(chances, this._computeReussite(chances, chances.roll)); mergeObject(chances, this._computeReussite(chances, chances.roll));
return chances; return chances;

View File

@ -66,7 +66,7 @@ export class RdDRollDialog extends Dialog {
let rollLevel = RdDRollDialog._computeFinalLevel(rollData); let rollLevel = RdDRollDialog._computeFinalLevel(rollData);
rollData.finalLevel = rollLevel; rollData.finalLevel = rollLevel;
rollData.rollTarget = RdDResolutionTable.computeChances(rollData.selectedCarac.value, rollData.finalLevel); rollData.carac = rollData.selectedCarac.value
// Sort management // Sort management
if ( rollData.selectedSort ) { if ( rollData.selectedSort ) {

View File

@ -103,7 +103,7 @@ export class RdDTMRDialog extends Dialog {
this.updatePreviousRencontres(); this.updatePreviousRencontres();
const draconic = this.actor.getBestDraconic(); const draconic = this.actor.getBestDraconic();
const carac = this.actor.getCurrentReve(); const carac = this.actor.getReveActuel();
// TODO: ajouter l'état général? // TODO: ajouter l'état général?
const etatGeneral = this.actor.data.data.compteurs.etat.value const etatGeneral = this.actor.data.data.compteurs.etat.value
const difficulte = draconic.data.niveau - this.currentRencontre.force; const difficulte = draconic.data.niveau - this.currentRencontre.force;
@ -111,16 +111,15 @@ export class RdDTMRDialog extends Dialog {
let rolled = RdDResolutionTable.roll(carac, difficulte); let rolled = RdDResolutionTable.roll(carac, difficulte);
let message = "<br><strong>Test : Rêve actuel / " + draconic.name + " / " + this.currentRencontre.name + "</strong>" + "<br>" let message = "<br><strong>Test : Rêve actuel / " + draconic.name + " / " + this.currentRencontre.name + "</strong>" + "<br>"
+ "<br>Jet : " + carac + " / " + difficulte + " -> " + rolled.score + "%<br><strong>Résutat : </strong>" + rolled.roll; + RdDResolutionTable.explain(rolled);
if (rolled.isEchec) { if (rolled.isEchec) {
TMRUtility.processRencontreEchec(this.actor, this.currentRencontre); TMRUtility.processRencontreEchec(this.actor, this.currentRencontre, rolled);
this._tellToUser("Vous avez <strong>échoué</strong> à maîtriser un " + this.currentRencontre.name + " de force " + this.currentRencontre.force this._tellToUser("Vous avez <strong>échoué</strong> à maîtriser un " + this.currentRencontre.name + " de force " + this.currentRencontre.force
+ "<br>Vous quittez brutalement les Terres Médianes !" + message);; + "<br>Vous quittez brutalement les Terres Médianes !" + message);
this.close(); this.close();
} else { } else {
TMRUtility.processRencontreReussite(this.actor, this.currentRencontre); TMRUtility.processRencontreReussite(this.actor, this.currentRencontre, rolled);
this._tellToUser("Vous avez <strong>réussi</strong> à maîtriser un " + this.currentRencontre.name + " de force " + this.currentRencontre.force + message); this._tellToUser("Vous avez <strong>réussi</strong> à maîtriser un " + this.currentRencontre.name + " de force " + this.currentRencontre.force + message);
} }
console.log("-> matriser", this.currentRencontre); console.log("-> matriser", this.currentRencontre);
@ -142,13 +141,14 @@ export class RdDTMRDialog extends Dialog {
console.log("manageRencontre", deRencontre, rencontre); console.log("manageRencontre", deRencontre, rencontre);
if (rencontre == undefined) { if (rencontre == undefined) {
if (deRencontre.total == 7) { if (deRencontre.total == 7) {
rencontre = TMRUtility.rencontreTMRRoll(coordTMR, cellDescr); rencontre = await TMRUtility.rencontreTMRRoll(coordTMR, cellDescr);
} }
} }
if (rencontre) { // Manages it if (rencontre) { // Manages it
console.log("manageRencontre", rencontre) console.log("manageRencontre", rencontre)
this.currentRencontre = duplicate(rencontre); this.currentRencontre = duplicate(rencontre);
let dialog = new Dialog({ let dialog = new Dialog({
title: "Rencontre en TMR!", title: "Rencontre en TMR!",
content: "Vous recontrez un " + rencontre.name + " de force " + rencontre.force + "<br>", content: "Vous recontrez un " + rencontre.name + " de force " + rencontre.force + "<br>",
@ -205,7 +205,7 @@ export class RdDTMRDialog extends Dialog {
if (cellDescr.type == "lac" || cellDescr.type == "fleuve" || cellDescr.type == "marais") { if (cellDescr.type == "lac" || cellDescr.type == "fleuve" || cellDescr.type == "marais") {
let draconic = this.actor.getBestDraconic(); let draconic = this.actor.getBestDraconic();
let carac = this.actor.getCurrentReve(); let carac = this.actor.getReveActuel();
// TODO: ajouter l'état général? // TODO: ajouter l'état général?
const etatGeneral = this.actor.data.data.compteurs.etat.value const etatGeneral = this.actor.data.data.compteurs.etat.value
let difficulte = draconic.data.niveau - 7; let difficulte = draconic.data.niveau - 7;
@ -222,7 +222,7 @@ export class RdDTMRDialog extends Dialog {
explication += "Vous êtes entré sur une case humide, et vous avez <strong>réussi</strong> votre maîtrise !" explication += "Vous êtes entré sur une case humide, et vous avez <strong>réussi</strong> votre maîtrise !"
} }
explication += "<br><strong>Test : Rêve actuel / " + draconic.name + " / " + cellDescr.type + "</strong>" explication += "<br><strong>Test : Rêve actuel / " + draconic.name + " / " + cellDescr.type + "</strong>"
+ "<br>Jet : " + carac + " / " + difficulte + " -> " + rolled.score + "%<br><strong>Résutat : </strong>" + rolled.roll; + RdDResolutionTable.explain(rolled);
if (rolled.isETotal) { if (rolled.isETotal) {
let souffle = RdDRollTables.getSouffle(); let souffle = RdDRollTables.getSouffle();

View File

@ -2,7 +2,6 @@
import { TMRUtility } from "./tmr-utility.js"; import { TMRUtility } from "./tmr-utility.js";
import { RdDRollTables } from "./rdd-rolltables.js"; import { RdDRollTables } from "./rdd-rolltables.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js";
const level_category = { const level_category = {
"generale": "-4", "generale": "-4",

View File

@ -1,3 +1,5 @@
import { RdDDice } from "./rdd-dice.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
const TMRMapping = { const TMRMapping = {
A1: { type: "cite", label: "Cité Vide"}, A1: { type: "cite", label: "Cité Vide"},
@ -233,7 +235,7 @@ const rencontresTable = [
{name:"Tourbillon noir", data: { force: "2d8", ignorer: false, derober: true, refoulement: 1, {name:"Tourbillon noir", data: { force: "2d8", ignorer: false, derober: true, refoulement: 1,
cite: "95-97", sanctuaire: "95-97", plaines: "94-97", pont: "94-97", collines: "94-97", forêt: "94-97", monts: "93-97", desert: "93-97", fleuve: "90-97", cite: "95-97", sanctuaire: "95-97", plaines: "94-97", pont: "94-97", collines: "94-97", forêt: "94-97", monts: "93-97", desert: "93-97", fleuve: "90-97",
lac: "90-97", marais: "87-97", gouffre: "90-97", necropole: "81-97", desolation: "81-97" } }, lac: "90-97", marais: "87-97", gouffre: "90-97", necropole: "81-97", desolation: "81-97" } },
{name:"Rêve de Dragon", data: { force: "1d7", ignorer: false, derober: true, refoulement: 2, {name:"Rêve de Dragon", data: { force: "1ddr + 7", ignorer: false, derober: true, refoulement: 2,
cite: "98-00", sanctuaire: "98-00", plaines: "98-00", pont: "98-00", collines: "98-00", forêt: "98-00", monts: "98-00", desert: "98-00", fleuve: "98-00", cite: "98-00", sanctuaire: "98-00", plaines: "98-00", pont: "98-00", collines: "98-00", forêt: "98-00", monts: "98-00", desert: "98-00", fleuve: "98-00",
lac: "98-00", marais: "98-00", gouffre: "98-00", necropole: "98-00", desolation: "98-00" } } lac: "98-00", marais: "98-00", gouffre: "98-00", necropole: "98-00", desolation: "98-00" } }
] ]
@ -264,32 +266,80 @@ export class TMRUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static rencontreTMRRoll( coordTMR, cellDescr ) static async rencontreTMRRoll( coordTMR, cellDescr )
{ {
let val = new Roll("d100").roll().total; let rencontre = this.rencontreTMRTypeCase(cellDescr.type);
//console.log("Rencontre !!!!", val, coordTMR, cellDescr); if (rencontre){
rencontre = duplicate(rencontre);
rencontre.force = await this.evaluerForceRencontre(rencontre);
rencontre.coord = coordTMR;
}
return rencontre;
}
static rencontreTMRTypeCase(typeTMR, roll=undefined) {
if (!roll)
{
roll = new Roll("d100").roll().total;
}
typeTMR = typeTMR.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
for( let rencontre of rencontresTable) { for( let rencontre of rencontresTable) {
let scoreDef = rencontre.data[cellDescr.type]; let scoreDef = rencontre.data[typeTMR];
let min = scoreDef.substr(0,2); let min = scoreDef.substr(0,2);
let max = scoreDef.substr(3,2); let max = scoreDef.substr(3,2);
//console.log(val, scoreDef, min, max); if (max=="00") max = 100;
if ( val >= min && val <= max) { if (roll >= min && roll <= max) {
rencontre.force = new Roll(rencontre.data.force).roll().total;
rencontre.coord = coordTMR
return rencontre; return rencontre;
} }
} }
} }
/* -------------------------------------------- */
/**
* Retourne une recontre en fonction de la case et du tirage
* @param {*} caseName
* @param {*} roll
*/
static async getRencontre( caseName, roll ) {
if (!roll) {
roll = new Roll("1d100").roll().total;
}
if ( !caseName) {
ChatMessage.create({ content: "Un nom de case doit être indiqué (ie /tmrr desert ou /tmrr cite)" });
return false;
}
let rencontre = this.rencontreTMRTypeCase(caseName, roll);
if (rencontre){
let force = await this.evaluerForceRencontre(rencontre);
ChatMessage.create({ content: "Rencontre en " + caseName + "(jet : " + roll + "%)<br>Vous rencontrez un " + rencontre.name + " d'une force de " + force + " Points de Rêve" });
}
return false;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static getRandomLocationType( coordTMR ) { static getRandomLocationType( coordTMR ) {
let descr = this.getTMRDescription( coordTMR ); let descr = this.getTMRDescription( coordTMR );
// TODO random get same type // TODO random get same type
} }
static async evaluerForceRencontre(rencontre) {
if (this.isReveDeDragon(rencontre)) {
let ddr = await RdDDice.deDraconique();
return ddr + 7;
}
else {
const roll = new Roll(rencontre.data.force).evaluate();
return roll.total;
}
}
static isReveDeDragon(rencontre) {
return rencontre.name.toLowerCase() == "Rêve de Dragon".toLowerCase();
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async processRencontreReussite( actor, rencontre ) { static async processRencontreReussite( actor, rencontre, rolled ) {
let msg = "Vous avez réussi votre maîtrise ! "; let msg = "Vous avez réussi votre maîtrise ! ";
console.log("processRencontreReussite", actor, rencontre); console.log("processRencontreReussite", actor, rencontre);
if (rencontre.name == "Messagers des Rêves") { if (rencontre.name == "Messagers des Rêves") {
@ -321,18 +371,18 @@ export class TMRUtility {
msg += "Ce Tourbillon Noir disparait !" msg += "Ce Tourbillon Noir disparait !"
} else if (rencontre.name == "Rêve de Dragon") { } else if (rencontre.name == "Rêve de Dragon") {
msg += "Un Rêve de Dragon survient !" msg += "Vous maîtrisez le Rêve de Dragon !"
msg += actor.appliquerReveDeDragon(rolled, rencontre.force);
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async processRencontreEchec( actor, rencontre ) { static async processRencontreEchec( actor, rencontre, rolled ) {
let msg = "Vous avez échoué à votre maîtrise ! "; let msg = "Vous avez échoué à votre maîtrise ! ";
if (rencontre.name == "Messagers des Rêves") { if (rencontre.name == "Messagers des Rêves") {
msg += "Le Messager des Rêves s'éloigne de vous !"; msg += "Le Messager des Rêves s'éloigne de vous !";
} else if (rencontre.name == "Passeur des Rêves") { } else if (rencontre.name == "Passeur des Rêves") {
msg += "Le Passeur des Rêves s'éloigne de vous !"; msg += "Le Passeur des Rêves s'éloigne de vous !";
@ -342,7 +392,6 @@ export class TMRUtility {
} else if (rencontre.name == "Mangeur de Rêve") { } else if (rencontre.name == "Mangeur de Rêve") {
await actor.updatePointsDeReve( -rencontre.force ); await actor.updatePointsDeReve( -rencontre.force );
msg += "Ce Mangeur des Rêves croque votre Rêve ! Vous perdez " + rencontre.force + " points de rêve actuels, votre nouveau total est de " + actor.data.data.reve.reve.value; msg += "Ce Mangeur des Rêves croque votre Rêve ! Vous perdez " + rencontre.force + " points de rêve actuels, votre nouveau total est de " + actor.data.data.reve.reve.value;
} else if (rencontre.name == "Changeur de Rêve") { } else if (rencontre.name == "Changeur de Rêve") {
let coordTMR = actor.data.data.reve.tmrpos.coord; let coordTMR = actor.data.data.reve.tmrpos.coord;
let newcoordTMR = this.getRandomLocationType(coordTMR); let newcoordTMR = this.getRandomLocationType(coordTMR);
@ -353,15 +402,16 @@ export class TMRUtility {
} else if (rencontre.name == "Reflet d'ancien Rêve") { } else if (rencontre.name == "Reflet d'ancien Rêve") {
msg += "Votre Rêve est Brisé, vous quittez les Terres Médianes"; msg += "Votre Rêve est Brisé, vous quittez les Terres Médianes";
} else if (rencontre.name == "Tourbillon blanc") { } else if (rencontre.name == "Tourbillon blanc") {
msg += "Votre Rêve est Brisé, vous quittez les Terres Médianes"; msg += "Votre Rêve est Brisé, vous quittez les Terres Médianes";
} else if (rencontre.name == "Tourbillon noir") { } else if (rencontre.name == "Tourbillon noir") {
msg += "Votre Rêve est Brisé, vous quittez les Terres Médianes"; msg += "Votre Rêve est Brisé, vous quittez les Terres Médianes";
} else if (rencontre.name == "Rêve de Dragon") {
} else if (rencontre.name == "Rêve de Dragon") {
msg += "Le Rêve de Dragon tourne au cauchemar !"
msg += actor.appliquerReveDeDragon(rolled, rencontre.force);
} }
} }
@ -377,36 +427,6 @@ export class TMRUtility {
return result; return result;
} }
/* -------------------------------------------- */
/**
* Retourne une recontre en fonction de la case ou du tirage
* @param {*} caseName
* @param {*} roll
*/
static getRencontre( caseName, roll ) {
if (!roll) {
roll = new Roll("1d100").roll().total;
}
if ( !caseName) {
ChatMessage.create({ content: "Un nom de case doit être indiqué (ie /tmrr desert ou /tmrr cite)" });
return false;
}
caseName = caseName.toLowerCase();
caseName = caseName.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
//console.log("Case : ", caseName);
for( let renc of rencontresTable) {
let scoreDef = renc.data[caseName];
let min = scoreDef.substr(0,2);
let max = scoreDef.substr(3,2);
if ( roll >= min && roll <= max) {
let force = new Roll(renc.data.force).roll().total;
ChatMessage.create({ content: "Rencontre en " + caseName + "(jet : " + roll + "%)<br>Vous rencontrez un " + renc.name + " d'une force de " + force + " Points de Rêve" });
return false;
}
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/** /**
* *

View File

@ -2,7 +2,7 @@
"name": "foundryvtt-reve-de-dragon", "name": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon", "title": "Rêve de Dragon",
"description": "Rêve de Dragon RPG for FoundryVTT", "description": "Rêve de Dragon RPG for FoundryVTT",
"version": "0.9.48", "version": "0.9.49",
"minimumCoreVersion": "0.7.5", "minimumCoreVersion": "0.7.5",
"compatibleCoreVersion": "0.7.6", "compatibleCoreVersion": "0.7.6",
"templateVersion": 46, "templateVersion": 46,

View File

@ -395,6 +395,11 @@
"value": 0, "value": 0,
"label": "Points de Rêve actuels" "label": "Points de Rêve actuels"
}, },
"seuil": {
"max": 0,
"value": 0,
"label": "Seuil de Rêve"
},
"tmrpos": { "tmrpos": {
"coord": "A1", "coord": "A1",
"label": "Position TMR" "label": "Position TMR"

View File

@ -394,11 +394,18 @@
<div> <div>
<span class="monte-tmr-rapide"><strong><a>Monter en Accéléré dans les Terres Medianes !</a></strong></span> <span class="monte-tmr-rapide"><strong><a>Monter en Accéléré dans les Terres Medianes !</a></strong></span>
</div> </div>
<div>
<span class="dormir-une-heure"><strong><a>Dormir une heure</a></strong></span>
</div>
<div> <div>
<ol class="item-list"> <ol class="item-list">
<li class="item flexrow"> <li class="item flexrow">
<span class="ptreve-actuel"><a>Points de Rêve actuels</a> :</span> <span class="ptreve-actuel"><a>Points de Rêve actuels</a> :</span>
<span><input class="pointsreve-value competence-value" type="text" name="data.reve.reve.value" value="{{data.reve.reve.value}}" data-dtype="Number"/></span> <span><input class="pointsreve-value" type="text" name="data.reve.reve.value" value="{{data.reve.reve.value}}" data-dtype="Number"/></span>
</li>
<li class="item flexrow">
<span class="seuil-reve"><a>Seuil de Rêve</a> :</span>
<span><input class="seuil-reve-value" type="text" name="data.reve.seuil.value" value="{{data.reve.seuil.value}}" data-dtype="Number"/></span>
</li> </li>
{{#if data.isGM}} {{#if data.isGM}}
<li class="item flexrow"> <li class="item flexrow">