Bouton "don de haut-rêve"

Pour permettre au MJ de rendre un personnage haut rêvant
sans avoir à chercher dans les compendiums
This commit is contained in:
Vincent Vandemeulebrouck 2024-12-03 23:25:58 +01:00
parent 39ce66a26c
commit 91717a3290
11 changed files with 175 additions and 127 deletions

View File

@ -214,6 +214,8 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
});
// Boutons spéciaux MJs
this.html.find('.forcer-tmr-aleatoire').click(async event => this.actor.reinsertionAleatoire("Action MJ"))
this.html.find('.don-de-haut-reve').click(async event => this.actor.addDonDeHautReve())
this.html.find('.afficher-tmr').click(async event => this.actor.changeTMRVisible())
}

View File

@ -38,6 +38,8 @@ import { RdDCoeur } from "./coeur/rdd-coeur.js";
import { DialogChoixXpCarac } from "./dialog-choix-xp-carac.js";
import { RdDItemArme } from "./item-arme.js";
import { RdDCombatManager } from "./rdd-combat.js";
import { RdDItemTete } from "./item/tete.js";
import { SystemCompendiums } from "./settings/system-compendiums.js";
export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre']
@ -87,7 +89,7 @@ export class RdDActor extends RdDBaseActorSang {
}
$computeIsHautRevant() {
this.system.attributs.hautrevant.value = this.itemTypes['tete'].find(it => Grammar.equalsInsensitive(it.name, 'don de haut-reve'))
this.system.attributs.hautrevant.value = this.itemTypes[ITEM_TYPES.tete].find(it => RdDItemTete.isDonDeHautReve(it))
? "Haut rêvant"
: "";
}
@ -989,6 +991,16 @@ export class RdDActor extends RdDBaseActorSang {
});
}
/* -------------------------------------------- */
async addDonDeHautReve() {
if (!game.user.isGM || this.isHautRevant()) {
return
}
const donHR = await RdDItemTete.teteDonDeHautReve()
if (donHR) {
this.createEmbeddedDocuments('Item', [donHR.toObject()])
}
}
/* -------------------------------------------- */
async reinsertionAleatoire(raison, accessible = tmr => true) {

View File

@ -5,12 +5,12 @@ import { RdDBaseActorReve } from "../actor/base-actor-reve.js";
import { Grammar } from "../grammar.js";
import { Misc } from "../misc.js";
import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js";
import { RdDItemTete } from "../item/tete.js";
const WHITESPACES = "\\s+"
const NUMERIC = "[\\+\\-]?\\d+"
const NUMERIC_VALUE = "(?<value>" + NUMERIC + ")"
const XREGEXP_NAME = "(?<name>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)"
const XREGEXP_COMP_CREATURE = WHITESPACES + "(?<carac>\\d+)"
+ WHITESPACES + NUMERIC_VALUE
+ "(" + WHITESPACES + "(?<init>\\d+)?\\s+?(?<dommages>[\\+\\-]?\\d+)?" + ")?"
@ -23,10 +23,11 @@ const compParser = {
}
const XREGEXP_SORT_VOIE = "[OHNT\\/]+"
const XREGEXP_SORT_NAME = "(?<name>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-']+)"
const XREGEXP_SORT_CASE = "\\((?<case>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)\\)";
const XREGEXP_SORT = "(" + XREGEXP_SORT_VOIE
+ WHITESPACES + XREGEXP_NAME
+ WHITESPACES + XREGEXP_SORT_NAME
+ WHITESPACES + XREGEXP_SORT_CASE
+ WHITESPACES + "R(?<diff>([\\-\\d]+|(\\w|\\s)+))"
+ WHITESPACES + "r(?<reve>(\\d+(\\+)?|\\s\\w+))"
@ -104,7 +105,7 @@ export class RdDStatBlockParser {
return "vaisseau";
}
static async parseStatBlock(statString, type = "npc") {
static async parseStatBlock(statString) {
//statString = statBlock03;
if (!statString) {
@ -122,10 +123,10 @@ export class RdDStatBlockParser {
statString = statString.trim();
// TODO: check for entite
let actorType = RdDStatBlockParser.parseActorType(statString);
let type = RdDStatBlockParser.parseActorType(statString);
// Now start carac
let actorData = foundry.utils.deepClone(game.model.Actor[actorType]);
let actorData = foundry.utils.deepClone(game.model.Actor[type]);
for (let key in actorData.carac) {
let caracDef = actorData.carac[key];
// Parse the stat string for each caracteristic
@ -136,7 +137,7 @@ export class RdDStatBlockParser {
}
// If creature we need to setup additionnal fields
switch (actorType) {
switch (type) {
case "creature":
RdDStatBlockParser.parseCreature(statString, actorData)
break
@ -147,14 +148,14 @@ export class RdDStatBlockParser {
let items = [];
// Get skills from compendium
const competences = await SystemCompendiums.getCompetences(actorType);
const competences = await SystemCompendiums.getCompetences(type);
//console.log("Competences : ", competences);
for (let comp of competences) {
let compMatch = XRegExp.exec(statString, XRegExp(comp.name + compParser[actorType], 'giu'));
let compMatch = XRegExp.exec(statString, XRegExp(comp.name + compParser[type], 'giu'));
if (compMatch) {
comp = comp.toObject()
comp.system.niveau = Number(compMatch.value);
if (actorType == "creature" || actorType == "entite") {
if (type == "creature" || type == "entite") {
comp.system.carac_value = Number(compMatch.carac);
if (compMatch.dommages != undefined) {
comp.system.dommages = Number(compMatch.dommages);
@ -163,7 +164,7 @@ export class RdDStatBlockParser {
}
items.push(comp)
}
else if (actorType == "personnage") {
else if (type == "personnage") {
comp = comp.toObject()
items.push(comp)
}
@ -213,82 +214,89 @@ export class RdDStatBlockParser {
}
}
// Attemp to detect spell
let hautRevant = false
let sorts = await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-oniros")
sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-hypnos"))
sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-narcos"))
sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-thanatos"))
if (type == "personnage") {
// Attemp to detect spell
await RdDStatBlockParser.parseHautReve(statString, items);
RdDStatBlockParser.parsePersonnage(statString, actorData);
}
let name = RdDStatBlockParser.extractName(type, statString);
let newActor = RdDBaseActorReve.create({ name, type: type, system: actorData, items });
// DUmp....
console.log(actorData);
}
static async parseHautReve(statString, items) {
let hautRevant = false;
let sorts = await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-oniros");
sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-hypnos"));
sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-narcos"));
sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-thanatos"));
XRegExp.forEach(statString, XRegExp(XREGEXP_SORT, 'giu'),
function (matchSort, i) {
let sort = sorts.find(s => Grammar.equalsInsensitive(s.name, matchSort.name))
let sort = sorts.find(s => Grammar.equalsInsensitive(s.name, matchSort.name));
if (sort) {
hautRevant = true
hautRevant = true;
sort = sort.toObject();
if (matchSort.bonus && matchSort.bonuscase) {
sort.system.bonuscase = `${matchSort.bonuscase}:${matchSort.bonus}`
sort.system.bonuscase = `${matchSort.bonuscase}:${matchSort.bonus}`;
}
items.push(sort);
}
});
if (hautRevant) {
let tetes = await SystemCompendiums.getWorldOrCompendiumItems("tete", "tetes-de-dragon-pour-tous-personnages")
let donHR = tetes.find(t => Grammar.equalsInsensitive(t.name, "Don de Haut-Rêve"))
const donHR = await RdDItemTete.teteDonDeHautReve();
if (donHR) {
items.push(donHR.toObject());
}
}
if (actorType == "personnage") {
}
let feminin = XRegExp.exec(statString, XRegExp("né(?<value>e?) à", 'giu'));
actorData.sexe = (feminin?.value == 'e') ? 'féminin' : 'masculin'
static parsePersonnage(statString, actorData) {
let feminin = XRegExp.exec(statString, XRegExp("né(?<value>e?) à", 'giu'));
actorData.sexe = (feminin?.value == 'e') ? 'féminin' : 'masculin';
// Get hour name : heure du XXXXX
let heure = XRegExp.exec(statString, XRegExp("heure (du|de la|des|de l\')\\s*(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s]+),", 'giu'));
actorData.heure = this.getHeureKey(heure?.value || "Vaisseau");
// Get hour name : heure du XXXXX
let heure = XRegExp.exec(statString, XRegExp("heure (du|de la|des|de l\')\\s*(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s]+),", 'giu'));
actorData.heure = this.getHeureKey(heure?.value || "Vaisseau");
// Get age
let age = XRegExp.exec(statString, XRegExp("(?<value>\\d+) ans", 'giu'));
if (age?.value) {
actorData.age = Number(age.value);
}
// Get height
let taille = XRegExp.exec(statString, XRegExp("(?<value>\\d+m\\d+)", 'giu'));
if (taille?.value) {
actorData.taille = taille.value;
}
// Get weight
let poids = XRegExp.exec(statString, XRegExp("(?<value>\\d+) kg", 'giu'));
if (poids?.value) {
actorData.poids = poids.value;
}
// Get cheveux
let cheveux = XRegExp.exec(statString, XRegExp("kg,\\s+(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+),\\s+yeux", 'giu'));
if (cheveux?.value) {
actorData.cheveux = cheveux.value;
}
// Get yeux
let yeux = XRegExp.exec(statString, XRegExp("yeux\\s+(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+), Beau", 'giu'));
if (yeux?.value) {
actorData.yeux = yeux.value;
}
// Get beauty
let beaute = XRegExp.exec(statString, XRegExp("beauté\\s+(?<value>\\d+)", 'giu'));
if (beaute?.value) {
actorData.beaute = Number(beaute.value);
}
// Get age
let age = XRegExp.exec(statString, XRegExp("(?<value>\\d+) ans", 'giu'));
if (age?.value) {
actorData.age = Number(age.value);
}
// Get height
let taille = XRegExp.exec(statString, XRegExp("(?<value>\\d+m\\d+)", 'giu'));
if (taille?.value) {
actorData.taille = taille.value;
}
// Get weight
let poids = XRegExp.exec(statString, XRegExp("(?<value>\\d+) kg", 'giu'));
if (poids?.value) {
actorData.poids = poids.value;
}
// Get cheveux
let cheveux = XRegExp.exec(statString, XRegExp("kg,\\s+(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+),\\s+yeux", 'giu'));
if (cheveux?.value) {
actorData.cheveux = cheveux.value;
}
// Get yeux
let yeux = XRegExp.exec(statString, XRegExp("yeux\\s+(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+), Beau", 'giu'));
if (yeux?.value) {
actorData.yeux = yeux.value;
}
// Name is all string before ', né'
let name = RdDStatBlockParser.extractName(actorType, statString);
let newActor = RdDBaseActorReve.create({ name: name || "Importé", type: actorType, system: actorData, items: items });
// DUmp....
console.log(actorData);
// Get beauty
let beaute = XRegExp.exec(statString, XRegExp("beauté\\s+(?<value>\\d+)", 'giu'));
if (beaute?.value) {
actorData.beaute = Number(beaute.value);
}
}
static parseCreature(statString, actorData) {
@ -350,24 +358,17 @@ export class RdDStatBlockParser {
static extractName(actorType, statString) {
switch (actorType) {
case "personnage": return RdDStatBlockParser.extractNamePersonnage(statString);
case "creature": return RdDStatBlockParser.extractNameCreature(statString);
case "personnage":
// Name is all string before first comma ','
const namePersonnage = XRegExp.exec(statString, XRegExp("(?<value>[\\p{Letter}\\s\\d]+),", 'giu'));
if (namePersonnage?.value) {
return Misc.upperFirst(namePersonnage?.value);
}
}
return RdDStatBlockParser.extractNameCreature(statString);
}
static extractNamePersonnage(statString) {
let name = XRegExp.exec(statString, XRegExp("(?<value>[\\p{Letter}\\s\\d]+),", 'giu'));
if (!name?.value) {
name = XRegExp.exec(statString, XRegExp("(?<value>.+)\\s+taille", 'giu'));
}
return Misc.upperFirst(name?.value || "Importé");
}
static extractNameCreature(statString) {
const name = XRegExp.exec(statString, XRegExp("(?<value>.+)\\s+taille", 'giu'));
return Misc.upperFirst(name?.value || "Importé");
}
}
/************************************************************************************/

25
module/item/tete.js Normal file
View File

@ -0,0 +1,25 @@
import { Grammar } from "../grammar.js"
import { ITEM_TYPES, RdDItem } from "../item.js"
import { SystemCompendiums } from "../settings/system-compendiums.js"
const DON_HAUT_REVE = "Don de Haut-Rêve"
export class RdDItemTete extends RdDItem {
static get defaultIcon() {
return "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp"
}
static isDonDeHautReve(tete) {
return tete.type == ITEM_TYPES.tete && Grammar.equalsInsensitive(tete.name, DON_HAUT_REVE)
}
static async teteDonDeHautReve() {
const tetes = await SystemCompendiums.getItems("tetes-de-dragon-pour-tous-personnages", ITEM_TYPES.tete)
const tete = tetes.find(it => RdDItemTete.isDonDeHautReve(it))
if (!tete) {
ui.notifications.warn(`Impossible de trouver la tête "${DON_HAUT_REVE}", vérifiez le compendium de têtes pour tous personnages`)
}
return tete
}
}

View File

@ -70,6 +70,7 @@ import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.
import { RdDActorExportSheet } from "./actor/export-scriptarium/actor-encart-sheet.js"
import { RdDStatBlockParser } from "./apps/rdd-import-stats.js"
import { RdDItemSort } from "./item-sort.js"
import { RdDItemTete } from "./item/tete.js"
/**
* RdD system
@ -97,6 +98,7 @@ export class SystemReveDeDragon {
ombre: RdDItemOmbre,
poison: RdDItemPoison,
queue: RdDItemQueue,
tete: RdDItemTete,
rencontre: RdDRencontre,
service: RdDItemService,
signedraconique: RdDItemSigneDraconique,

View File

@ -145,8 +145,8 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/chirurgie.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queue.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-souffles.html',

View File

@ -1,5 +1,6 @@
import { ChatUtility } from "../chat-utility.js";
import { HIDE_DICE, SYSTEM_RDD } from "../constants.js";
import { Grammar } from "../grammar.js";
import { RdDItem } from "../item.js";
import { Misc } from "../misc.js";
import { RdDDice } from "../rdd-dice.js";
@ -84,15 +85,14 @@ export class SystemCompendiums extends FormApplication {
static async getWorldOrCompendiumItems(itemType, compendium) {
let items = game.items.filter(it => it.type == itemType)
if (compendium) {
const ids = items.map(it => it.id);
const names = items.map(it => it.name.toLowerCase());
const compendiumItems = await SystemCompendiums.getItems(compendium);
items = items.concat(compendiumItems
.filter(it => it.type == itemType)
const ids = items.map(it => it.id)
const names = items.map(it => Grammar.toLowerCaseNoAccent(it.name))
const compendiumItems = await SystemCompendiums.getItems(compendium, itemType)
return items.concat(compendiumItems
.filter(it => !ids.includes(it.id))
.filter(it => !names.includes(it.name.toLowerCase())));
.filter(it => !names.includes(Grammar.equalsInsensitive(it.name))))
}
return items;
return items
}
static async loadDocument(document) {

View File

@ -129,11 +129,10 @@
<div>
{{#if system.attributs.hautrevant.value}}
<h3>Haut rêvant</h3>
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.html"}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.hbs"}}
{{else}}
<h3>Vous n'avez pas le don de haut-rêve</h3>
<p>Attribuer la Tête de Dragon 'Don de Haut Rêve' pour rendre le personnage Haut-Rêvant.</p>
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.html"}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.hbs"}}
{{/if}}
<br><br>
</div>

View File

@ -26,7 +26,7 @@
{{/if}}
</span>
</li>
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.html"}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.hbs"}}
<hr>
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/hr-signes-draconiques.html"}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/hr-rencontres.html"}}

View File

@ -0,0 +1,41 @@
{{#if (not system.attributs.hautrevant.value)}}
<p>Attribuer la Tête de Dragon
{{#if options.isGM}}
<a class="chat-card-button don-de-haut-reve" data-tooltip="Donner le don de haut-rêve">Don de Haut Rêve</a>
{{else}}
'Don de Haut Rêve'
{{/if}}
pour rendre le personnage Haut-Rêvant.</p>
{{/if}}
<li class="item flexrow">
<span class="competence-label">Seuil de Rêve :</span>
<span>
{{#if options.isGM}}
<input class="competence-value seuil-reve-value" type="text" name="system.reve.seuil.value" value="{{system.reve.seuil.value}}" data-dtype="Number"/>
{{else}}
{{system.reve.seuil.value}}
{{/if}}
</span>
</li>
<li class="item flexrow" >
<span class="competence-label">Refoulement : </span>
<span>
{{#if options.isGM}}
<input class="competence-value" type="text" name="system.reve.refoulement.value" value="{{system.reve.refoulement.value}}" data-dtype="Number"/>
{{else}}
{{system.reve.refoulement.value}}
{{/if}}
</span>
</li>
{{#if system.reve.reve.thanatosused}}
<li class="item flexrow" >
<span class="competence-label">La prochaine queue est une Ombre</span>
<span>
<img class="sheet-competence-img" src="systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp"/>
</span>
</li>
{{/if}}
<hr>
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.html"}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-souffles.html"}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-tetes.html"}}

View File

@ -1,34 +0,0 @@
<ul class="item-list">
<li class="item flexrow">
<span class="competence-label">Seuil de Rêve :</span>
<span>
{{#if options.isGM}}
<input class="competence-value seuil-reve-value" type="text" name="system.reve.seuil.value" value="{{system.reve.seuil.value}}" data-dtype="Number"/>
{{else}}
{{system.reve.seuil.value}}
{{/if}}
</span>
</li>
<li class="item flexrow" >
<span class="competence-label">Refoulement : </span>
<span>
{{#if options.isGM}}
<input class="competence-value" type="text" name="system.reve.refoulement.value" value="{{system.reve.refoulement.value}}" data-dtype="Number"/>
{{else}}
{{system.reve.refoulement.value}}
{{/if}}
</span>
</li>
{{#if system.reve.reve.thanatosused}}
<li class="item flexrow" >
<span class="competence-label">La prochaine queue est une Ombre</span>
<span>
<img class="sheet-competence-img" src="systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp"/>
</span>
</li>
{{/if}}
</ul>
<hr>
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.html"}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-souffles.html"}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-tetes.html"}}