Compétences & herbes personalisées

* permettre d'ajouter des compétences dans un monde, qui seront
  ajoutés aux acteurs créés dans ce monde
* les herbes de repos/soins du monde sont bien considérées comme
  des herbes pour les potions
This commit is contained in:
Vincent Vandemeulebrouck 2022-10-08 14:25:31 +02:00
parent 6d0e5321a2
commit 18039e905b
8 changed files with 95 additions and 78 deletions

View File

@ -120,7 +120,7 @@ export class RdDActor extends Actor {
} }
if (isPersonnage) { if (isPersonnage) {
const competences = await RdDUtility.loadCompendium(RdDItemCompetence.actorCompendium(actorData.type)); const competences = await RdDUtility.loadItems(it => it.isCompetencePersonnage(), 'foundryvtt-reve-de-dragon.competences');
actorData.items = competences.map(i => i.toObject()); actorData.items = competences.map(i => i.toObject());
actorData.items = actorData.items.concat(Monnaie.monnaiesStandard()); actorData.items = actorData.items.concat(Monnaie.monnaiesStandard());
} }
@ -343,7 +343,7 @@ export class RdDActor extends Actor {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
getDraconicList() { getDraconicList() {
return this.items.filter(it => it.type == 'competence' && it.system.categorie == 'draconic') return this.items.filter(it => it.isCompetencePersonnage() && it.system.categorie == 'draconic')
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
getBestDraconic() { getBestDraconic() {
@ -2317,7 +2317,7 @@ export class RdDActor extends Actor {
case "detection d'aura": case "detection d'aura":
return draconicList; return draconicList;
case "annulation de magie": case "annulation de magie":
return draconicList.filter(it => !Grammar.toLowerCaseNoAccent(it.name).includes('thanatos')); return draconicList.filter(it => !RdDItemCompetence.isThanatos(it));
} }
return [RdDItemCompetence.getVoieDraconic(draconicList, sort.system.draconic)]; return [RdDItemCompetence.getVoieDraconic(draconicList, sort.system.draconic)];
} }
@ -4140,7 +4140,7 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async onPreUpdateItem(item, change, options, id) { async onPreUpdateItem(item, change, options, id) {
if (item.type == 'competence' && item.system.defaut_carac && item.system.xp) { if (item.isCompetencePersonnage() && item.system.defaut_carac && item.system.xp) {
await this.checkCompetenceXP(item.name, item.system.xp); await this.checkCompetenceXP(item.name, item.system.xp);
} }
} }

View File

@ -57,8 +57,8 @@ const competence_xp_cumul = _buildCumulXP();
export class RdDItemCompetence extends Item { export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static actorCompendium(actorType) { static actorCompendium(actorType = undefined) {
return compendiumCompetences[actorType]; return compendiumCompetences[actorType ?? 'personnage'];
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -89,22 +89,28 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isCompetenceArme(competence) { static isCompetenceArme(competence) {
switch (competence.system.categorie) { if (competence.isCompetence()) {
case 'melee': switch (competence.system.categorie) {
return competence.name != 'Esquive'; case 'melee':
case 'tir': return !Grammar.toLowerCaseNoAccent(competence.name).includes('esquive');
case 'lancer': case 'tir':
return true; case 'lancer':
return true;
}
} }
return false; return false;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static isArmeUneMain(competence) { static isArmeUneMain(competence) {
return competence.name.toLowerCase().includes("1 main"); return RdDItemCompetence.isCompetenceArme(competence) && competence.name.toLowerCase().includes("1 main");
} }
static isArme2Main(competence) { static isArme2Main(competence) {
return competence.name.toLowerCase().includes("2 main"); return RdDItemCompetence.isCompetenceArme(competence) && competence.name.toLowerCase().includes("2 main");
}
static isThanatos(competence) {
return competence.isCompetencePersonnage() && Grammar.toLowerCaseNoAccent(competence.name).includes('thanatos');
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -133,7 +139,7 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static computeXP(competence) { static computeXP(competence) {
const factor = competence.name.includes('Thanatos') ? 2 : 1; // Thanatos compte double ! const factor = RdDItemCompetence.isThanatos(competence) ? 2 : 1; // Thanatos compte double !
const xpNiveau = RdDItemCompetence.computeDeltaXP(competence.system.base, competence.system.niveau ?? competence.system.base); const xpNiveau = RdDItemCompetence.computeDeltaXP(competence.system.base, competence.system.niveau ?? competence.system.base);
const xp = competence.system.xp ?? 0; const xp = competence.system.xp ?? 0;
const xpSort = competence.system.xp_sort ?? 0; const xpSort = competence.system.xp_sort ?? 0;
@ -213,21 +219,14 @@ export class RdDItemCompetence extends Item {
if (idOrName == undefined) { if (idOrName == undefined) {
return undefined; return undefined;
} }
options = mergeObject(options, { options = mergeObject(options, { preFilter: it => it.isCompetence(), description: 'compétence', });
preFilter: it => RdDItemCompetence.isCompetence(it), return list.find(it => it.id == idOrName && it.isCompetence())
description: 'compétence',
});
return list.find(it => it.id == idOrName && RdDItemCompetence.isCompetence(it))
?? Misc.findFirstLike(idOrName, list, options); ?? Misc.findFirstLike(idOrName, list, options);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static findCompetences(list, name) { static findCompetences(list, name) {
return Misc.findAllLike(name, list, { filter: it => RdDItemCompetence.isCompetence(it), description: 'compétence' }); return Misc.findAllLike(name, list, { filter: it => it.isCompetence(), description: 'compétence' });
}
static isCompetence(item) {
return item.type == 'competence' || item.type == 'competencecreature';
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -90,11 +90,10 @@ export class RdDItemSheet extends ItemSheet {
if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') { if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') {
formData.caracList = duplicate(game.system.model.Actor.personnage.carac) formData.caracList = duplicate(game.system.model.Actor.personnage.carac)
formData.caracList["reve-actuel"] = duplicate(game.system.model.Actor.personnage.reve.reve) formData.caracList["reve-actuel"] = duplicate(game.system.model.Actor.personnage.reve.reve)
formData.competences = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.competences') formData.competences = await RdDUtility.loadItems(it => it.isCompetencePersonnage(), RdDItemCompetence.actorCompendium(this.actor?.type))
} }
if (this.item.type == 'arme') { if (this.item.type == 'arme') {
formData.competences = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.competences', it => RdDItemCompetence.isCompetenceArme(it)); formData.competences = await RdDUtility.loadItems(it => RdDItemCompetence.isCompetenceArme(it), RdDItemCompetence.actorCompendium(this.actor?.type))
console.log(formData.competences)
} }
if (this.item.type == 'recettecuisine') { if (this.item.type == 'recettecuisine') {
formData.ingredients = await TextEditor.enrichHTML(this.object.system.ingredients, {async: true}) formData.ingredients = await TextEditor.enrichHTML(this.object.system.ingredients, {async: true})
@ -115,7 +114,7 @@ export class RdDItemSheet extends ItemSheet {
formData.system.prdate = this.dateUpdated; formData.system.prdate = this.dateUpdated;
this.dateUpdated = undefined; this.dateUpdated = undefined;
} }
RdDHerbes.updatePotionData(formData); await RdDHerbes.updatePotionData(formData);
} }
if (formData.isOwned && this.item.type == 'herbe' && (formData.system.categorie == 'Soin' || formData.system.categorie == 'Repos')) { if (formData.isOwned && this.item.type == 'herbe' && (formData.system.categorie == 'Soin' || formData.system.categorie == 'Repos')) {
formData.isIngredientPotionBase = true; formData.isIngredientPotionBase = true;
@ -160,7 +159,7 @@ export class RdDItemSheet extends ItemSheet {
html.find(".categorie").change(event => this._onSelectCategorie(event)); html.find(".categorie").change(event => this._onSelectCategorie(event));
html.find('.sheet-competence-xp').change((event) => { html.find('.sheet-competence-xp').change((event) => {
if (this.item.type == 'competence') { if (this.item.isCompetencePersonnage()) {
RdDUtility.checkThanatosXP(this.item.name); RdDUtility.checkThanatosXP(this.item.name);
} }
}); });

View File

@ -77,6 +77,9 @@ export class RdDItem extends Item {
return typesObjetsOeuvres return typesObjetsOeuvres
} }
isCompetencePersonnage() {
return this.type == 'competence'
}
isCompetence() { isCompetence() {
return typesObjetsCompetence.includes(this.type) return typesObjetsCompetence.includes(this.type)
} }
@ -180,8 +183,8 @@ export class RdDItem extends Item {
this.system.magique = categorie.includes('enchante'); this.system.magique = categorie.includes('enchante');
if (this.system.magique) { if (this.system.magique) {
if (categorie.includes('soin') || categorie.includes('repos')) { if (categorie.includes('soin') || categorie.includes('repos')) {
// TODO: utiliser calculePointsRepos / calculePointsGuerison // TODO: utiliser calculPointsRepos / calculPointsGuerison
this.system.puissance = RdDHerbes.calculePuissancePotion(this); this.system.puissance = RdDHerbes.calculPuissancePotion(this);
} }
} }
} }

View File

@ -1,76 +1,75 @@
import { RdDUtility } from "./rdd-utility.js"; import { RdDUtility } from "./rdd-utility.js";
import { RdDCalendrier } from "./rdd-calendrier.js"; import { RdDCalendrier } from "./rdd-calendrier.js";
import { Grammar } from "./grammar.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDHerbes extends Item { export class RdDHerbes extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isHerbeSoin( botaniqueItem ) { static async initializeHerbes() {
return botaniqueItem.categorie == 'Soin'; this.herbesSoins = await RdDHerbes.listCategorieHerbes('Soin');
} this.herbesRepos = await RdDHerbes.listCategorieHerbes('Repos');
/* -------------------------------------------- */
static isHerbeRepos( botaniqueItem ) {
return botaniqueItem.categorie == 'Repos';
} }
/* -------------------------------------------- */ static async listCategorieHerbes(categorie) {
static async initializeHerbes( ) { return await RdDUtility.loadItems(
this.herbesSoins = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.botanique', item => this.isHerbeSoin(item)); it => it.type == 'herbe' && it.system.categorie.toLowerCase() == categorie.toLowerCase(),
this.herbesRepos = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.botanique', item => this.isHerbeRepos(item)); 'foundryvtt-reve-de-dragon.botanique');
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static buildHerbesList(listeHerbes, max) { static buildHerbesList(listeHerbes, max) {
let list = {} let list = {}
for ( let herbe of listeHerbes) { for (let herbe of listeHerbes) {
let brins = max - herbe.system.niveau; let brins = max - herbe.system.niveau;
list[herbe.system.name] = `${herbe.system.name} (Bonus: ${herbe.system.niveau}, Brins: ${brins})`; list[herbe.name] = `${herbe.name} (Bonus: ${herbe.system.niveau}, Brins: ${brins})`;
} }
list['Autre'] = 'Autre (Bonus: variable, Brins: variable)' list['Autre'] = 'Autre (Bonus: variable, Brins: variable)'
return list; return list;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static updatePotionData( formData ) { static async updatePotionData(formData) {
formData.herbesSoins = this.buildHerbesList(this.herbesSoins, 12); formData.isSoins = formData.system.categorie.includes('Soin');
formData.herbesRepos = this.buildHerbesList(this.herbesRepos, 7); formData.isRepos = formData.system.categorie.includes('Repos');
if (formData.isSoins) {
RdDHerbes.calculBonusHerbe(formData, this.herbesSoins, 12);
}
if (formData.isRepos) {
RdDHerbes.calculBonusHerbe(formData, this.herbesRepos, 7);
}
formData.herbesSoins = RdDHerbes.buildHerbesList(this.herbesSoins, 12);
formData.herbesRepos = RdDHerbes.buildHerbesList(this.herbesRepos, 7);
formData.jourMoisOptions = RdDCalendrier.buildJoursMois(); formData.jourMoisOptions = RdDCalendrier.buildJoursMois();
formData.dateActuelle = game.system.rdd.calendrier.getDateFromIndex(); formData.dateActuelle = game.system.rdd.calendrier.getDateFromIndex();
formData.splitDate = game.system.rdd.calendrier.getNumericDateFromIndex(formData.system.prdate); formData.splitDate = game.system.rdd.calendrier.getNumericDateFromIndex(formData.system.prdate);
if (formData.system.categorie.includes('Soin') ) {
formData.isHerbe = true;
this.computeHerbeBonus(formData, this.herbesSoins, 12);
} else if (formData.system.categorie.includes('Repos')) {
formData.isRepos = true;
this.computeHerbeBonus(formData, this.herbesRepos, 7);
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static calculePuissancePotion( potion ) { static calculPuissancePotion(potion) {
return potion.system.herbebonus * potion.system.pr; return potion.system.herbebonus * potion.system.pr;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static calculePointsRepos( potion ) { static calculPointsRepos(potion) {
return potion.system.herbebonus * potion.system.pr; return potion.system.herbebonus * potion.system.pr;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static calculePointsGuerison( potion ){ static calculPointsGuerison(potion) {
return potion.system.herbebonus * potion.system.pr; return potion.system.herbebonus * potion.system.pr;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static computeHerbeBonus( formData, herbesList, max) { static calculBonusHerbe(formData, herbesList, max) {
if ( Number(formData.system.herbebrins) ) { if (Number(formData.system.herbebrins)) {
let herbe = herbesList.find(item => item.name.toLowerCase() == formData.system.herbe.toLowerCase() ); let herbe = herbesList.find(item => item.name.toLowerCase() == formData.system.herbe.toLowerCase());
if( herbe ) { if (herbe) {
let brinsBase = max - herbe.system.niveau; const brinsRequis = max - herbe.system.niveau;
formData.system.herbebonus = Math.max(herbe.system.niveau - Math.max(brinsBase - formData.system.herbebrins, 0), 0); const brinsManquants = Math.max(brinsRequis - formData.system.herbebrins, 0);
formData.system.herbebonus = Math.max(herbe.system.niveau - brinsManquants, 0);
} }
} }
} }
} }

View File

@ -2,16 +2,22 @@ export class RdDRollTables {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async genericGetTableResult(tableName, toChat) { static async genericGetTableResult(tableName, toChat) {
let table = game.tables.find(table => table.name.toLowerCase() == tableName.toLowerCase()) let table = RdDRollTables.getWorldTable() ?? (await RdDRollTables.getSystemTable(tableName));
if ( !table) {
const pack = game.packs.get("foundryvtt-reve-de-dragon.tables-diverses");
const index = await pack.getIndex();
const entry = index.find(e => e.name === tableName);
table = await pack.getDocument(entry._id);
}
const draw = await table.draw({ displayChat: toChat, rollMode: "gmroll"}); const draw = await table.draw({ displayChat: toChat, rollMode: "gmroll"});
//console.log("RdDRollTables", tableName, toChat, ":", draw); //console.log("RdDRollTables", tableName, toChat, ":", draw);
return draw.results.length > 0 ? draw.results[0] : undefined; return draw.results.length > 0 ? draw.results[0] : undefined;
}
static getWorldTable() {
return game.tables.find(table => table.name.toLowerCase() == tableName.toLowerCase());
}
static async getSystemTable(tableName) {
const pack = game.packs.get("foundryvtt-reve-de-dragon.tables-diverses");
const index = await pack.getIndex();
const entry = index.find(e => e.name === tableName);
return await pack.getDocument(entry._id);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -683,15 +683,26 @@ export class RdDUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async loadCompendiumData(compendium) { static async loadItems(filter, compendium) {
const pack = game.packs.get(compendium); let items = game.items.filter(filter);
return await pack?.getDocuments() ?? []; if (compendium) {
const ids = items.map(it => it.id);
const names = items.map(it => it.name.toLowerCase());
items = items.concat(await RdDUtility.loadCompendium(compendium, it => !ids.includes(it.id) && !names.includes(it.name.toLowerCase()) && filter(it)));
}
return items;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async loadCompendium(compendium, filter = item => true) { static async loadCompendium(compendium, filter = it => true) {
let compendiumData = await RdDUtility.loadCompendiumData(compendium); let compendiumData = await RdDUtility.loadCompendiumData(compendium);
return compendiumData.filter(filter); return compendiumData.filter(filter);
}
/* -------------------------------------------- */
static async loadCompendiumData(compendium) {
const pack = game.packs.get(compendium);
return await pack?.getDocuments() ?? [];
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -41,7 +41,7 @@
{{/select}} {{/select}}
</select> </select>
</div> </div>
{{#if isHerbe}} {{#if isSoins}}
<div class="form-group"> <div class="form-group">
<label>Herbe</label> <label>Herbe</label>
<select name="system.herbe" class="herbe" data-dtype="String"> <select name="system.herbe" class="herbe" data-dtype="String">
@ -86,7 +86,7 @@
<label for="xp">Permanente ? </label> <label for="xp">Permanente ? </label>
<input class="attribute-value" type="checkbox" name="system.prpermanent" {{#if system.prpermanent}}checked{{/if}}/> <input class="attribute-value" type="checkbox" name="system.prpermanent" {{#if system.prpermanent}}checked{{/if}}/>
</div> </div>
{{#if isHerbe}} {{#if isSoins}}
<div class="form-group"> <div class="form-group">
<label for="xp">Points de guérison </label> <label for="xp">Points de guérison </label>
<label for="xp">{{pointsGuerison}}</label> <label for="xp">{{pointsGuerison}}</label>