Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fd96be439e | |||
| 238d99fa9b | |||
| 490de5882b | |||
| 4fc06a449c | |||
| 929d6af173 | |||
| e15ed9d05d | |||
| 3699bc19b8 | |||
| 15510b99d8 | |||
| fa30705989 | |||
| 04f550dd21 | |||
| 850cae3979 | |||
| 7b514d5159 | |||
| d78ede4f59 |
20
changelog.md
20
changelog.md
@@ -1,12 +1,30 @@
|
||||
# 13.0
|
||||
|
||||
## 13.0.31 - Les choix multiples d'Illysis
|
||||
|
||||
- les défauts de caractéristique/difficulté des compétences ne sont pris que si aucun autre choix n'est fait
|
||||
- lors d'une attaque à deux mains avec une arme à une ou deux mains, les dommages à deux mains sont bien utilisés
|
||||
|
||||
## 13.0.30 - Le pansement d'Illysis
|
||||
|
||||
- les soins d'un joueur à l'autre fonctionne de nouveau
|
||||
- la fenêtre de jet de compétence s'ouvre avec la caractéristique et la difficulté par défaut
|
||||
- on peut saisir des valeurs négatives au clavier en sélectionnant les conditions/difficultés
|
||||
|
||||
## 13.0.29 - Le tricorne d'Illysis
|
||||
|
||||
- gestion des attaques avec jets V2 depuis l'onglet de combat
|
||||
- les jets de résistance en mode V2 fonctionnent sans sélection de compétence
|
||||
- affichage de l'expérience correspondant aux sorts pour aider à la création
|
||||
- affichage de l'équivallent d'expérience des caractéristiques
|
||||
|
||||
## 13.0.28 - La quadrature d'Illysis
|
||||
|
||||
- Les ajustements de portée sont calculés pour les attaques à distance
|
||||
- L'appel au moral dans le tchat ne déplace plus les boutons d'appel à la chance
|
||||
- Correction d'apparence V13
|
||||
- la fenêtre de choix des status utilisés est affichée correctement
|
||||
- la fenêtrre d'astrologir MJ est affichée correctement
|
||||
- la fenêtre d'astrologie MJ est affichée correctement
|
||||
|
||||
## 13.0.27 - Les lunettes d'Illysis
|
||||
|
||||
|
||||
@@ -893,7 +893,7 @@ body {
|
||||
max-width: 1.4rem;
|
||||
max-height: 1.4rem;
|
||||
border: 1px;
|
||||
background: center / contain no-repeat url("../../icons/templates/icone_parchement_vierge.webp");
|
||||
background: center / contain no-repeat url("../icons/templates/icone_parchement_vierge.webp");
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .sheet-header .header-compteurs {
|
||||
width: calc(60% - 110px - 1rem);
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
max-height: 1.4rem;
|
||||
border: 1px;
|
||||
background: center / contain no-repeat
|
||||
url("../../icons/templates/icone_parchement_vierge.webp");
|
||||
url("../icons/templates/icone_parchement_vierge.webp");
|
||||
}
|
||||
|
||||
.sheet-header .header-compteurs {
|
||||
|
||||
@@ -19,6 +19,7 @@ import { RdDCoeur } from "./coeur/rdd-coeur.js";
|
||||
import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.js";
|
||||
import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
|
||||
import { MORAL } from "./moral/apprecier.mjs";
|
||||
import { RdDItemSort } from "./item-sort.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/**
|
||||
@@ -52,6 +53,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
|
||||
surprise: RdDBonus.find(this.actor.getSurprise(false)).label,
|
||||
resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures),
|
||||
caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute),
|
||||
caracTotalXp: RdDCarac.computeTotalXp(this.actor.system.carac, this.actor.system.beaute),
|
||||
surEncombrementMessage: this.actor.isSurenc() ? "Sur-Encombrement!" : "",
|
||||
malusArmure: this.actor.getMalusArmure()
|
||||
})
|
||||
@@ -61,9 +63,13 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
|
||||
if (formData.type == ACTOR_TYPES.personnage) {
|
||||
formData.options.mainsDirectrices = MAINS_DIRECTRICES;
|
||||
formData.byCateg = Misc.classify(formData.competences, it => it.system.categorie)
|
||||
formData.calc.comptageArchetype = RdDItemCompetence.computeResumeArchetype(formData.competences);
|
||||
formData.calc.competenceXPTotal = RdDItemCompetence.computeTotalXP(formData.competences);
|
||||
formData.calc.fatigue = RdDUtility.calculFatigueHtml(formData.system.sante.fatigue.value, formData.system.sante.endurance.max);
|
||||
foundry.utils.mergeObject(formData.calc, {
|
||||
comptageArchetype: RdDItemCompetence.computeResumeArchetype(formData.competences),
|
||||
competenceXPTotal: RdDItemCompetence.computeTotalXP(formData.competences),
|
||||
sortsXPTotal: RdDItemSort.computeTotalXP(this.actor.itemTypes[ITEM_TYPES.sort]),
|
||||
fatigue: RdDUtility.calculFatigueHtml(formData.system.sante.fatigue.value, formData.system.sante.endurance.max)
|
||||
|
||||
})
|
||||
|
||||
formData.competences.forEach(item => {
|
||||
item.system.isHidden = this.options.recherche
|
||||
|
||||
@@ -2504,9 +2504,9 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
const blessure = blesse.blessuresASoigner().find(it => it.id == blessureId);
|
||||
if (blessure) {
|
||||
if (!blessure.system.premierssoins.done) {
|
||||
const tache = await this.getTacheBlessure(blesse, blessure);
|
||||
return await this.rollTache(tache.id, {
|
||||
callbacks: [async r => await blesse.onRollTachePremiersSoins(blessureId, r, this.id)],
|
||||
const tacheId = (await this.getTacheBlessure(blesse, blessure))?.id
|
||||
return await this.rollTache(tacheId, {
|
||||
callbacks: [async r => await blesse.callbackPremiersSoins(blessureId, r, this.id)],
|
||||
title: 'Premiers soins', forced: true
|
||||
});
|
||||
}
|
||||
|
||||
@@ -56,8 +56,6 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
|
||||
getTaille() { return Misc.toInt(this.system.carac.taille?.value) }
|
||||
getConstitution() { return this.getReve() }
|
||||
getVie() { return this.getReve() }
|
||||
getCaracVie() { return { [CARACS.VIE]: { label: "Vie", value: this.getVieMax(), type: "number" } } }
|
||||
|
||||
getForce() { return this.getReve() }
|
||||
getAgilite() { return this.getForce() }
|
||||
@@ -484,17 +482,15 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
|
||||
async rollCompetence(idOrName, options = { tryTarget: true, arme: undefined }) {
|
||||
RdDEmpoignade.checkEmpoignadeEnCours(this)
|
||||
|
||||
const competence = this.getCompetence(idOrName);
|
||||
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
||||
const rollData = {
|
||||
ids: { actorId: this.id },
|
||||
type: { allowed: options.arme ? ATTAQUE_ROLL_TYPES : DEFAULT_ROLL_TYPES },
|
||||
type: { allowed: DEFAULT_ROLL_TYPES },
|
||||
selected: {
|
||||
carac: competence.type == ITEM_TYPES.competencecreature ? { key: competence.name } : undefined,
|
||||
comp: { key: competence.name },
|
||||
diff: { type: options.arme ? DIFF.ATTAQUE : DIFF.LIBRE, value: competence.system.default_diffLibre ?? 0 },
|
||||
attaque: options.arme ? { arme: { key: options.arme.id } } : undefined
|
||||
diff: { type: DIFF.LIBRE, value: competence.system.default_diffLibre ?? 0 },
|
||||
}
|
||||
}
|
||||
return await RollDialog.create(rollData)
|
||||
@@ -566,7 +562,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
type: {
|
||||
allowed: [ROLL_TYPE_ATTAQUE], current: ROLL_TYPE_ATTAQUE
|
||||
}
|
||||
};
|
||||
}
|
||||
return await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
|
||||
}
|
||||
})
|
||||
@@ -575,16 +571,18 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
|
||||
/** --------------------------------------------
|
||||
* @param {*} arme item d'arme/compétence de créature
|
||||
* @param {*} categorieArme catégorie d'attaque à utiliser: competence (== melee), lancer, tir; naturelle, possession
|
||||
* @param {*} maniement catégorie d'attaque à utiliser: competence (== melee), lancer, tir; naturelle, possession
|
||||
* @returns
|
||||
*/
|
||||
rollArme(arme, categorieArme = 'competence', token = undefined) {
|
||||
async rollArme(arme, maniement = 'competence', token = undefined) {
|
||||
token = token ?? RdDUtility.getSelectedToken(this)
|
||||
const compToUse = RdDItemArme.getCompetenceArme(arme, categorieArme)
|
||||
const compToUse = RdDItemArme.getCompetenceArme(arme, maniement)
|
||||
|
||||
if (!RdDItemArme.isUtilisable(arme)) {
|
||||
ui.notifications.warn(`Arme inutilisable: ${arme.name} non équipée ou avec une résistance de 0 ou moins`)
|
||||
return
|
||||
}
|
||||
|
||||
if (!Targets.hasTargets()) {
|
||||
RdDConfirm.confirmer({
|
||||
settingConfirmer: "confirmer-combat-sans-cible",
|
||||
@@ -596,7 +594,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
onAction: async () => {
|
||||
this.rollCompetence(compToUse, { tryTarget: false, arme: arme })
|
||||
}
|
||||
});
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -606,11 +604,12 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
return
|
||||
}
|
||||
|
||||
const competence = this.getCompetence(compToUse)
|
||||
if (competence.isCompetencePossession()) {
|
||||
return RdDPossession.onAttaquePossession(target, this, competence);
|
||||
const comp = this.getCompetence(compToUse)
|
||||
if (comp.isCompetencePossession()) {
|
||||
// TODO: vérifier si c'est possible, sinon simplifier
|
||||
return RdDPossession.onAttaquePossession(target, this, comp);
|
||||
}
|
||||
RdDCombat.rddCombatTarget(target, this, token).attaque(competence, arme);
|
||||
RdDCombat.rddCombatTarget(target, this, token).attaque(comp, arme, maniement)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import { RdDItemBlessure } from "../item/blessure.js";
|
||||
import { ChatUtility } from "../chat-utility.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { RdDBaseActor } from "./base-actor.js";
|
||||
import { CARACS } from "../rdd-carac.js";
|
||||
|
||||
/**
|
||||
* Classe de base pour les acteurs qui peuvent subir des blessures
|
||||
@@ -178,19 +179,24 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
|
||||
return result
|
||||
}
|
||||
|
||||
async onRollTachePremiersSoins(blessureId, rollData, soigneurId) {
|
||||
async callbackPremiersSoins(blessureId, rollData, soigneurId) {
|
||||
await this.onRollTachePremiersSoins(blessureId,
|
||||
rollData.v2 ? rollData.current.tache.tache : rollData.tache,
|
||||
rollData.rolled.isETotal,
|
||||
soigneurId)
|
||||
}
|
||||
async onRollTachePremiersSoins(blessureId, tache, isETotal, soigneurId) {
|
||||
if (!this.isOwner) {
|
||||
return RdDBaseActor.remoteActorCall({
|
||||
tokenId: this.token?.id,
|
||||
actorId: this.id,
|
||||
method: 'onRollTachePremiersSoins', args: [blessureId, rollData, soigneurId]
|
||||
method: 'onRollTachePremiersSoins', args: [blessureId, tache, isETotal, soigneurId]
|
||||
})
|
||||
}
|
||||
|
||||
const blessure = this.getItem(blessureId, 'blessure')
|
||||
if (blessure && !blessure.system.premierssoins.done) {
|
||||
const tache = rollData.v2 ? rollData.current.tache.tache : rollData.tache
|
||||
if (rollData.rolled.isETotal) {
|
||||
if (isETotal) {
|
||||
await blessure.update({
|
||||
'system.difficulte': blessure.system.difficulte - 1,
|
||||
'system.premierssoins.tache': Math.max(0, tache.system.points_de_tache_courant)
|
||||
|
||||
@@ -136,7 +136,7 @@ export class RdDItemCompetence extends RdDItem {
|
||||
return troncList;
|
||||
}
|
||||
}
|
||||
return [];
|
||||
return []
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
@@ -41,6 +41,11 @@ export class RdDItemSort extends RdDItem {
|
||||
return value ? value.replace('variable', 'var') : ''
|
||||
}
|
||||
|
||||
static computeTotalXP(sorts) {
|
||||
return sorts.map(sort => RdDItemSort.isDifficulteVariable(sort) ? 70 : -10 * Misc.toInt(sort.system.difficulte))
|
||||
.reduce(Misc.sum(), 0)
|
||||
}
|
||||
|
||||
static isSortOnCoord(sort, coord) {
|
||||
let tmr = TMRUtility.getTMR(coord)
|
||||
const caseTMR = sort.system.caseTMR.toLowerCase();
|
||||
|
||||
@@ -168,10 +168,18 @@ export class RdDCarac {
|
||||
const total = Object.values(carac ?? {}).filter(c => !c.derivee)
|
||||
.map(it => parseInt(it.value))
|
||||
.reduce(Misc.sum(), 0);
|
||||
const beauteSuperieur10 = Math.max((beaute ?? 10) - 10, 0);
|
||||
const beauteSuperieur10 = Math.max((beaute ?? 10) - 10, 0)
|
||||
return total + beauteSuperieur10;
|
||||
}
|
||||
|
||||
static computeTotalXp(carac, beaute = undefined) {
|
||||
const totalXp = Object.values(carac ?? {}).filter(c => !c.derivee)
|
||||
.map(it => RdDCarac.getCaracXp(0, Misc.toInt(it.value)) + Misc.toInt(it.xp))
|
||||
.reduce(Misc.sum(), 0);
|
||||
const beauteXp = beaute > 10 ? RdDCarac.getCaracXp(10, beaute) : 0
|
||||
return totalXp + beauteXp;
|
||||
}
|
||||
|
||||
static levelUp(it) {
|
||||
it.xpNext = RdDCarac.getCaracNextXp(it.value);
|
||||
it.isLevelUp = (it.xp >= it.xpNext);
|
||||
@@ -184,12 +192,16 @@ export class RdDCarac {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getCaracNextXp(value) {
|
||||
const nextValue = Number(value) + 1;
|
||||
value = Number(value);
|
||||
const nextValue = value + 1;
|
||||
// xp est le coût pour atteindre cette valeur, on regarde donc le coût de la valeur+1
|
||||
return RdDCarac.getCaracXp(nextValue);
|
||||
return RdDCarac.getCaracXp(value, nextValue)
|
||||
}
|
||||
|
||||
static getCaracXp(targetValue) {
|
||||
return RdDCarac.getCaracDerivee(targetValue)?.xp ?? 200;
|
||||
static getCaracXp(from, to) {
|
||||
return Array.from({ length: to - from },
|
||||
(_, i) => from + i + 1)
|
||||
.map(it => RdDCarac.getCaracDerivee(it)?.xp ?? 200)
|
||||
.reduce(Misc.sum(), 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,8 +518,8 @@ export class RdDCombat {
|
||||
/* -------------------------------------------- */
|
||||
attaqueChanceuse(attackerRoll) {
|
||||
ui.notifications.info("L'attaque est rejouée grâce à la chance")
|
||||
attackerRoll.essais.attaqueChance = true;
|
||||
this.attaque(attackerRoll, attackerRoll.arme);
|
||||
attackerRoll.essais.attaqueChance = true
|
||||
this.attaque(attackerRoll, attackerRoll.arme)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -646,11 +646,11 @@ export class RdDCombat {
|
||||
}
|
||||
}
|
||||
|
||||
async attaqueV2() {
|
||||
async attaqueV2(options = undefined) {
|
||||
if (!await this.attacker.accorder(this.defender, 'avant-attaque')) {
|
||||
return
|
||||
}
|
||||
await this.doRollAttaque({
|
||||
const rollData = {
|
||||
ids: {
|
||||
actorId: this.attackerId,
|
||||
actorTokenId: this.attackerTokenId,
|
||||
@@ -658,8 +658,19 @@ export class RdDCombat {
|
||||
opponentTokenId: this.defenderTokenId,
|
||||
},
|
||||
type: { allowed: ['attaque'], current: 'attaque' },
|
||||
selected: {},
|
||||
passeArme: foundry.utils.randomID(16),
|
||||
})
|
||||
}
|
||||
if (options) {
|
||||
rollData.selected = {
|
||||
attaque: {
|
||||
comp: { id: options.comp.id },
|
||||
arme: { id: options.arme.id },
|
||||
main: options.main
|
||||
}
|
||||
}
|
||||
}
|
||||
await this.doRollAttaque(rollData)
|
||||
}
|
||||
|
||||
async doRollAttaque(rollData, callbacks = []) {
|
||||
@@ -740,12 +751,14 @@ export class RdDCombat {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async attaque(competence, arme) {
|
||||
async attaque(competence, arme, main) {
|
||||
if (!await this.attacker.accorder(this.defender, 'avant-attaque')) {
|
||||
return
|
||||
}
|
||||
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
||||
return this.attacker.rollCompetence(competence.name, { arme: arme })
|
||||
return this.attaqueV2(
|
||||
{ comp: competence, arme: arme, main: main }
|
||||
)
|
||||
}
|
||||
if (arme.system.cac == EMPOIGNADE) {
|
||||
RdDEmpoignade.onAttaqueEmpoignade(this.attacker, this.defender)
|
||||
@@ -754,7 +767,7 @@ export class RdDCombat {
|
||||
RdDEmpoignade.checkEmpoignadeEnCours(this.attacker)
|
||||
|
||||
let rollData = this._prepareAttaque(competence, arme)
|
||||
console.log("RdDCombat.attaque >>>", rollData);
|
||||
console.log("RdDCombat.attaque >>>", rollData)
|
||||
if (arme) {
|
||||
this.attacker.verifierForceMin(arme);
|
||||
}
|
||||
|
||||
@@ -116,6 +116,7 @@ export class RdDCommands {
|
||||
this.registerCommand({
|
||||
path: ["/xp", "carac"], func: (content, msg, params) => this.getCoutXpCarac(msg, params),
|
||||
descr: `Détermine le coût d'expérience pour augmenter une caractéristique. Exemples:
|
||||
<br>/xp carac 12 15: coût pour passer de 12 15
|
||||
<br>/xp carac 15: coût pour atteindre 15 (depuis 14)`
|
||||
});
|
||||
|
||||
@@ -440,13 +441,18 @@ export class RdDCommands {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getCoutXpCarac(msg, params) {
|
||||
if (params && params.length == 1) {
|
||||
let to = Number(params[0]);
|
||||
return RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${to - 1} à ${to}: ${RdDCarac.getCaracXp(to)}`);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
if (params) {
|
||||
if (params.length == 1) {
|
||||
const to = Number(params[0])
|
||||
return RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${to - 1} à ${to}: ${RdDCarac.getCaracXp(to - 1, to)}`);
|
||||
}
|
||||
if (params.length == 2) {
|
||||
const from = Number(params[0]);
|
||||
const to = Number(params[1]);
|
||||
return RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${from} à ${to}: ${RdDCarac.getCaracXp(from, to)}`);
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
async creerSignesDraconiques() {
|
||||
|
||||
@@ -101,7 +101,7 @@ export class RdDHotbar {
|
||||
}
|
||||
|
||||
/** Roll macro */
|
||||
static rollMacro(itemName, itemType, categorieArme = 'competence') {
|
||||
static rollMacro(itemName, itemType, maniement = 'competence') {
|
||||
const speaker = ChatMessage.getSpeaker();
|
||||
let actor;
|
||||
if (speaker.token) actor = game.actors.tokens[speaker.token];
|
||||
@@ -117,10 +117,10 @@ export class RdDHotbar {
|
||||
// Trigger the item roll
|
||||
switch (item.type) {
|
||||
case ITEM_TYPES.arme:
|
||||
return actor.rollArme(item, categorieArme);
|
||||
return actor.rollArme(item, maniement);
|
||||
case ITEM_TYPES.competence:
|
||||
if (item.isCorpsACorps()) {
|
||||
switch (categorieArme) {
|
||||
switch (maniement) {
|
||||
case PUGILAT:
|
||||
return actor.rollArme(RdDItemArme.pugilat(actor));
|
||||
case EMPOIGNADE:
|
||||
@@ -130,7 +130,7 @@ export class RdDHotbar {
|
||||
return actor.rollCompetence(item);
|
||||
case ITEM_TYPES.competencecreature:
|
||||
return item.system.iscombat
|
||||
? actor.rollArme(item, categorieArme)
|
||||
? actor.rollArme(item, maniement)
|
||||
: actor.rollCompetence(item);
|
||||
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
|
||||
foundry.applications.handlebars.loadTemplates(ALL_ROLL_TYPES.map(m => m.chatResultTemplate))
|
||||
foundry.applications.handlebars.loadTemplates(ROLL_PARTS.map(p => p.template))
|
||||
ROLL_PARTS.forEach(p => p.onReady())
|
||||
ROLL_PARTS.forEach(p => p.onReady(ROLL_PARTS))
|
||||
|
||||
Handlebars.registerHelper('roll-centered-array', (base, show) => {
|
||||
show = Math.abs(show)
|
||||
|
||||
@@ -52,11 +52,13 @@ export class RollPartAttaque extends RollPartSelect {
|
||||
|
||||
restore(rollData) {
|
||||
const saved = this.getSaved(rollData) ?? {}
|
||||
this.setCurrent(rollData, {
|
||||
key: saved.key,
|
||||
tactique: saved.tactique,
|
||||
dmg: saved.dmg
|
||||
})
|
||||
if (saved.key) {
|
||||
this.setCurrent(rollData, {
|
||||
key: saved.key,
|
||||
tactique: saved.tactique,
|
||||
dmg: saved.dmg
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
store(rollData, targetData) {
|
||||
@@ -70,9 +72,11 @@ export class RollPartAttaque extends RollPartSelect {
|
||||
|
||||
|
||||
findAttaque(attaques, saved) {
|
||||
return attaques.find(at => at.arme.id == saved?.arme?.id &&
|
||||
at.comp.id == saved?.comp?.id
|
||||
)
|
||||
return attaques.find(it => it.key == saved.key) ??
|
||||
attaques.find(it => it.arme.id == (saved?.arme?.id ?? it.arme.id)
|
||||
&& it.comp.id == (saved?.comp?.id ?? it.comp.id)
|
||||
&& it.main == (saved?.main ?? it.main)
|
||||
)
|
||||
}
|
||||
|
||||
choices(refs) { return refs.attaques }
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Grammar } from "../grammar.js"
|
||||
import { Misc } from "../misc.js"
|
||||
import { PART_CARAC } from "./roll-part-carac.mjs"
|
||||
import { PART_DIFF } from "./roll-part-diff.mjs"
|
||||
import { RollPartSelect } from "./roll-part-select.mjs"
|
||||
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
|
||||
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
|
||||
|
||||
export const PART_COMP = "comp"
|
||||
|
||||
@@ -15,15 +17,21 @@ export class RollPartComp extends RollPartSelect {
|
||||
get name() { return 'Compétences' }
|
||||
get section() { return ROLLDIALOG_SECTION.COMP }
|
||||
|
||||
onReady(rollParts) {
|
||||
this.rollPartCarac = rollParts.find(it => it.code == PART_CARAC)
|
||||
this.rollPartDiff = rollParts.find(it => it.code == PART_DIFF)
|
||||
}
|
||||
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
const selected = this.getSelected(rollData)
|
||||
const all = this.$getActorComps(rollData)
|
||||
if (selected.forced) {
|
||||
refs.all = all.filter(comp => Grammar.equalsInsensitive(comp.label, selected.key))
|
||||
const selectedComp = selected.key
|
||||
if (selected.forced && selectedComp) {
|
||||
refs.all = all.filter(comp => Grammar.equalsInsensitive(comp.label, selectedComp))
|
||||
if (refs.all.length == 0) {
|
||||
if (selected.key.length > 0) {
|
||||
refs.all = all.filter(comp => Grammar.includesLowerCaseNoAccent(comp.label, selected.key))
|
||||
if (selected.key && selected.key.length > 0) {
|
||||
refs.all = all.filter(comp => Grammar.includesLowerCaseNoAccent(comp.label, selectedComp))
|
||||
}
|
||||
else {
|
||||
refs.all = all.filter(comp => comp == SANS_COMPETENCE)
|
||||
@@ -35,6 +43,13 @@ export class RollPartComp extends RollPartSelect {
|
||||
}
|
||||
refs.comps = refs.all
|
||||
this.$selectComp(rollData)
|
||||
if (rollData.type.current == PART_COMP && selectedComp) {
|
||||
const current = this.getCurrent(rollData)
|
||||
const selectedCarac = RollPart.getSelectedPart(rollData, PART_CARAC)
|
||||
const selectedDiff = RollPart.getSelectedPart(rollData, PART_DIFF)
|
||||
this.rollPartCarac.selectByKey(rollData, selectedCarac?.key ?? current.comp.system.defaut_carac)
|
||||
this.rollPartDiff.setDiff(rollData, selectedDiff?.value ?? current.comp.system.default_diffLibre)
|
||||
}
|
||||
}
|
||||
|
||||
choices(refs) { return refs.comps }
|
||||
@@ -71,6 +86,7 @@ export class RollPartComp extends RollPartSelect {
|
||||
refs.comps.sort(sorting)
|
||||
}
|
||||
this.$selectComp(rollData)
|
||||
|
||||
}
|
||||
|
||||
prepareContext(rollData) {
|
||||
|
||||
@@ -10,7 +10,7 @@ export class RollPartConditions extends RollPart {
|
||||
settingMin() { return RollPart.settingKey(this, 'min') }
|
||||
settingMax() { return RollPart.settingKey(this, 'max') }
|
||||
|
||||
onReady() {
|
||||
onReady(rollParts) {
|
||||
game.settings.register(SYSTEM_RDD, this.settingMin(),
|
||||
{
|
||||
name: "Malus maximal de conditions",
|
||||
@@ -65,12 +65,7 @@ export class RollPartConditions extends RollPart {
|
||||
async _onRender(rollDialog, context, options) {
|
||||
const input = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="${this.code}"]`)
|
||||
|
||||
input?.addEventListener("input", e => this.onInputChange(e, rollDialog))
|
||||
}
|
||||
|
||||
onInputChange(event, rollDialog) {
|
||||
this.getCurrent(rollDialog.rollData).value = parseInt(event.currentTarget.value)
|
||||
rollDialog.render()
|
||||
input?.addEventListener("input", e => this.onNumericInputChange(e, rollDialog))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
|
||||
export const PART_CUISINE = "cuisine"
|
||||
|
||||
export class RollPartCuisine extends RollPartSelect {
|
||||
onReady() {
|
||||
onReady(rollParts) {
|
||||
foundry.applications.handlebars.loadTemplates({ 'roll-oeuvre-recettecuisine': `systems/foundryvtt-reve-de-dragon/templates/roll/roll-oeuvre-recettecuisine.hbs` })
|
||||
}
|
||||
|
||||
|
||||
@@ -73,12 +73,7 @@ export class RollPartDiff extends RollPart {
|
||||
async _onRender(rollDialog, context, options) {
|
||||
const input = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="${this.code}"]`)
|
||||
|
||||
input?.addEventListener("input", e => this.onInputChange(e, rollDialog))
|
||||
}
|
||||
|
||||
onInputChange(event, rollDialog) {
|
||||
this.getCurrent(rollDialog.rollData).value = parseInt(event.currentTarget.value)
|
||||
rollDialog.render()
|
||||
input?.addEventListener("input", e => this.onNumericInputChange(e, rollDialog))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,7 +24,7 @@ const ARTS = [
|
||||
]
|
||||
|
||||
export class RollPartOeuvre extends RollPartSelect {
|
||||
onReady() {
|
||||
onReady(rollParts) {
|
||||
ARTS.forEach(art => art.label = Misc.typeName('Item', art.type))
|
||||
ARTS.map(it => `roll-oeuvre-${it.type}`)
|
||||
.forEach(art =>
|
||||
|
||||
@@ -12,7 +12,7 @@ export const PART_SORT = "sort"
|
||||
|
||||
export class RollPartSort extends RollPartSelect {
|
||||
|
||||
onReady() {
|
||||
onReady(rollParts) {
|
||||
// TODO: utiliser un hook pour écouter les déplacements dans les TMRs?
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { ALL_ROLL_TYPES } from "./roll-dialog.mjs"
|
||||
|
||||
export const ROLLDIALOG_SECTION = {
|
||||
ACTION: 'action',
|
||||
CARAC: 'carac',
|
||||
@@ -7,12 +5,11 @@ export const ROLLDIALOG_SECTION = {
|
||||
CHOIX: 'choix',
|
||||
CONDITIONS: 'conditions',
|
||||
AJUSTEMENTS: 'ajustements',
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class RollPart {
|
||||
static settingKey(rollPart, key) { return `roll-part-${rollPart.code}.${key}` }
|
||||
|
||||
|
||||
get code() { throw new Error(`Pas dse code définie pour ${this}`) }
|
||||
get name() { return this.code }
|
||||
/** la section de la fenêtre ou le paramêtre apparaît */
|
||||
@@ -20,30 +17,37 @@ export class RollPart {
|
||||
get priority() { return 0 /* TODO */ }
|
||||
/** le template handlebars pour affichage */
|
||||
get template() { return `systems/foundryvtt-reve-de-dragon/templates/roll/roll-part-${this.code}.hbs` }
|
||||
|
||||
|
||||
static getSelectedPart(rollData, code) {
|
||||
return rollData.selected[code] ?? {}
|
||||
}
|
||||
static setSelectedPart(rollData, code, saved) {
|
||||
rollData.selected[code] = saved
|
||||
}
|
||||
|
||||
/** l'acteur actif du jet */
|
||||
getActor(rollData) { return rollData.active.actor }
|
||||
/** le conteneur de données du RollPart */
|
||||
getRefs(rollData) {
|
||||
return rollData.refs[this.code]
|
||||
}
|
||||
}
|
||||
|
||||
/** les informations de sélection du paramètre */
|
||||
getCurrent(rollData) {
|
||||
return rollData.current[this.code]
|
||||
}
|
||||
}
|
||||
setCurrent(rollData, current) {
|
||||
rollData.current[this.code] = current
|
||||
}
|
||||
}
|
||||
|
||||
/** les informations minimales représentant la sélection dans le rollData permettant de restaurer la fenêtre */
|
||||
getSelected(rollData) { return this.getSaved(rollData) }
|
||||
getSaved(rollData) {
|
||||
return rollData.selected[this.code] ?? {}
|
||||
}
|
||||
return RollPart.getSelectedPart(rollData, this.code)
|
||||
}
|
||||
setSaved(rollData, saved) {
|
||||
rollData.selected[this.code] = saved
|
||||
}
|
||||
RollPart.setSelectedPart(rollData, this.code, saved)
|
||||
}
|
||||
|
||||
restore(rollData) { }
|
||||
|
||||
@@ -75,7 +79,7 @@ export class RollPart {
|
||||
isValid(rollData) { return true }
|
||||
visible(rollData) { return true }
|
||||
|
||||
onReady() { }
|
||||
onReady(rollParts) { }
|
||||
loadRefs(rollData) { }
|
||||
|
||||
prepareContext(rollData) { }
|
||||
@@ -103,4 +107,13 @@ export class RollPart {
|
||||
async _onRender(rollDialog, context, options) { }
|
||||
|
||||
getHooks() { return [] }
|
||||
|
||||
onNumericInputChange(event, rollDialog, setValue = value => this.getCurrent(rollDialog.rollData).value = value) {
|
||||
if (isNaN(event.currentTarget.value) || event.currentTarget.value == "") {
|
||||
return
|
||||
}
|
||||
setValue(parseInt(event.currentTarget.value))
|
||||
rollDialog.render()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,8 +5,6 @@ const DEFAULT_DIFF_TYPES = [DIFF.LIBRE, DIFF.IMPOSEE, DIFF.DEFAUT]
|
||||
|
||||
export class RollType {
|
||||
|
||||
onReady() { }
|
||||
|
||||
get code() { throw new Error(`Pas de code défini pour ${this}`) }
|
||||
get name() { return this.code }
|
||||
get icon() { return `systems/foundryvtt-reve-de-dragon/assets/actions/${this.code}.svg` }
|
||||
|
||||
@@ -3,4 +3,10 @@
|
||||
<span class="carac-label" name="carac-total">Total Caractéristiques</span>
|
||||
<span class="competence-value" name="carac-total-value">{{calc.caracTotal}} </span>
|
||||
</li>
|
||||
{{#if @root.options.isGM}}
|
||||
<li class="caracteristique flexrow">
|
||||
<span class="carac-label" name="carac-total">Total XP Caractéristiques</span>
|
||||
<span class="competence-value" name="carac-total-xp">{{calc.caracTotalXp}} </span>
|
||||
</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
<span class="generic-label">Total XP compétences</span>
|
||||
<span class="competence-value">{{calc.competenceXPTotal}}</span>
|
||||
</li>
|
||||
<li class="flexrow">
|
||||
<span class="generic-label">Total XP sorts</span>
|
||||
<span class="competence-value">{{calc.sortsXPTotal}}</span>
|
||||
</li>
|
||||
{{/if}}
|
||||
<li> </li>
|
||||
</ul>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<label for="{{code}}">Conditions</label>
|
||||
{{numberInput current.value
|
||||
name=name
|
||||
step=1
|
||||
min=current.min
|
||||
max=current.max
|
||||
disabled=rollData.type.retry
|
||||
}}
|
||||
<input type="number"
|
||||
name="{{name}}"
|
||||
value="{{current.value}}"
|
||||
pattern="^(-|+)?\d+$"
|
||||
min="{{current.min}}" max="{{current.max}}" step="1"
|
||||
{{#if rollData.type.retry}}disabled{{/if}}>
|
||||
|
||||
@@ -9,24 +9,23 @@
|
||||
{{#if current.recette}}
|
||||
<selected-numeric-value>{{plusMoins current.value}}</selected-numeric-value>
|
||||
{{else if current.ingredient}}
|
||||
{{numberInput current.value
|
||||
name='diff-var'
|
||||
step=1
|
||||
min=-10
|
||||
max=0
|
||||
disabled=rollData.type.retry
|
||||
}}
|
||||
<input type="number"
|
||||
name='diff-var'
|
||||
value="{{current.value}}"
|
||||
pattern="^(-|+)?\d+$"
|
||||
min="-10" max="0" step="1"
|
||||
{{#if rollData.type.retry}}disabled{{/if}}>
|
||||
{{/if}}
|
||||
</subline>
|
||||
<subline>
|
||||
<label for="proportions">Proportions</label>
|
||||
{{numberInput current.proportions
|
||||
<input type="number"
|
||||
name='proportions'
|
||||
step=1
|
||||
min=1
|
||||
max=(either current.proportionsMax 10)
|
||||
disabled=rollData.type.retry
|
||||
}}
|
||||
value="{{current.proportions}}"
|
||||
pattern="^\d+$"
|
||||
min="1" max="{{either current.proportionsMax 10}}" step="1"
|
||||
{{#if rollData.type.retry}}disabled{{/if}}>
|
||||
|
||||
{{#if (and current.sust (ne current.sust 1))}}<span>(× {{current.sust}})</span>{{/if}}
|
||||
</subline>
|
||||
<subline>
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<subline>
|
||||
<label for="{{code}}">{{current.label}} </label>
|
||||
{{numberInput current.value
|
||||
name=name
|
||||
step=1
|
||||
min=current.min
|
||||
max=current.max
|
||||
disabled=(or rollData.type.retry current.disabled)
|
||||
}}
|
||||
<input type="number"
|
||||
name="{{name}}"
|
||||
value="{{current.value}}"
|
||||
pattern="^(-|+)?\d+$"
|
||||
min="{{current.min}}" max="{{current.max}}" step="1"
|
||||
{{#if (or rollData.type.retry current.disabled)}}disabled{{/if}}>
|
||||
</subline>
|
||||
|
||||
@@ -6,10 +6,9 @@
|
||||
{{current.label}}
|
||||
</label>
|
||||
<label for="malusenc"></label>
|
||||
{{numberInput current.value
|
||||
<input type="number"
|
||||
name='malusenc'
|
||||
step=1
|
||||
min=-30
|
||||
max=0
|
||||
disabled=rollData.type.retry
|
||||
}}
|
||||
value="{{current.value}}"
|
||||
pattern="^(-)?\d+$"
|
||||
min="-30" max="0" step="1"
|
||||
{{#if rollData.type.retry}}disabled{{/if}}>
|
||||
|
||||
@@ -8,13 +8,12 @@
|
||||
{{selectOptions refs.sorts selected=current.key valueAttr="key" labelAttr="label"}}
|
||||
</select>
|
||||
{{#if current.isDiffVariable}}
|
||||
{{numberInput current.value
|
||||
<input type="number"
|
||||
name='diff-var'
|
||||
step=1
|
||||
min=-20
|
||||
max=-1
|
||||
disabled=rollData.type.retry
|
||||
}}
|
||||
value="{{current.value}}"
|
||||
pattern="^(-)?\d+$"
|
||||
min="-20" max="-1" step="1"
|
||||
{{#if rollData.type.retry}}disabled{{/if}}>
|
||||
{{else}}
|
||||
<selected-numeric-value>{{plusMoins current.value}}</selected-numeric-value>
|
||||
{{/if}}
|
||||
@@ -23,13 +22,13 @@
|
||||
<label for="ptreve-var">Rêve {{itemSort-coutReve current.sort}} </span>
|
||||
</label>
|
||||
{{#if current.isReveVariable}}
|
||||
{{numberInput current.ptreve
|
||||
<input type="number"
|
||||
name='ptreve-var'
|
||||
step=1
|
||||
min=1
|
||||
max=30
|
||||
disabled=rollData.type.retry
|
||||
}}
|
||||
value="{{current.ptreve}}"
|
||||
pattern="^\d+$"
|
||||
min="{{1}}" max="{{60}}" step="1"
|
||||
{{#if rollData.type.retry}}disabled{{/if}}>
|
||||
|
||||
{{/if}}
|
||||
<span> (actuel: {{rollData.active.actor.system.reve.reve.value}})</span>
|
||||
</subline>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<label for="{{name}}">Forcer </label>
|
||||
<img src="systems/foundryvtt-reve-de-dragon/assets/ui/d100.svg" data-tooltip="Forcer le résultat du jet de dé"/>
|
||||
{{numberInput current.resultat
|
||||
name=name
|
||||
step=1
|
||||
min=-1
|
||||
max=100
|
||||
}}
|
||||
<input type="number"
|
||||
name="{{name}}"
|
||||
value="{{current.resultat}}"
|
||||
pattern="^(-|+)?\d+$"
|
||||
min="-1" max="100" step="1">
|
||||
|
||||
Reference in New Issue
Block a user