Compare commits
1 Commits
v13
...
3f82347e7a
| Author | SHA1 | Date | |
|---|---|---|---|
| 3f82347e7a |
@@ -25,7 +25,4 @@ Merci à eux !!
|
||||
|
||||
Toute la propriété intellectuelle leur appartient, ce système est une adaptation destinée à fonctionner sous FoundryVTT.
|
||||
|
||||
L'ensemble du code est sous licence Creative Commons.
|
||||
|
||||
# Licences
|
||||
- L'export pdf utilise la librairie [pdf-lib](https://pdf-lib.js.org/) sous licence [MIT](pdf-lib-LICENSE.md)
|
||||
L'ensemble du code est sous licence Creative Commons.
|
||||
Binary file not shown.
15
changelog.md
15
changelog.md
@@ -1,24 +1,9 @@
|
||||
# 13.0
|
||||
## 13.0.16 - La paix d'Illysis
|
||||
|
||||
- Export de personnages sous forme de feuille de personnage pdf
|
||||
- Correction d'un problème à l'ouverture de personnages saisis dans d'anciennes versions
|
||||
- Fenêtre de jet v2
|
||||
- on peut faire des jets en dehors des combats
|
||||
|
||||
## 13.0.15 - Les pièces d'Illysis
|
||||
|
||||
- On peut de nouveau acheter dans les commerces
|
||||
- Corrections V13
|
||||
- Les textes sur fond "parchemin" ne sont plus affichés en blanc
|
||||
|
||||
## 13.0.14 - Le familier d'Illysis
|
||||
|
||||
- Les réussites particulières en demi-surprise sont de simples réussites
|
||||
- Les images des scènes par défaut sont corrigées
|
||||
- Ajout d'une image de status "sur-encombré"
|
||||
- Correction V13
|
||||
- couleur lisible dans les sommaires des journaux et des compendiums
|
||||
- Amélioration des entités:
|
||||
- l'attaquant ne sait plus que c'est une entité de cauchemar (surprise!)
|
||||
- l'encaissement indique une blessure dans le tchat... même si ce n'est que de l'endurance
|
||||
|
||||
@@ -1378,9 +1378,6 @@ select,
|
||||
margin: 0.1rem 0;
|
||||
align-items: center;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .prosemirror menu {
|
||||
background-color: var(--color-background-chat-message);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .app.sheet .editor.prosemirror {
|
||||
height: fit-content;
|
||||
min-height: 5rem;
|
||||
@@ -1572,70 +1569,22 @@ select,
|
||||
.system-foundryvtt-reve-de-dragon .type-compendium {
|
||||
font-size: 0.6rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar {
|
||||
background: url(../assets/ui/bg_left.webp) no-repeat left top;
|
||||
color: var(--rdd-color-text-primary);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body label,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content label,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar label,
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body .hint,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content .hint,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar .hint,
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body .permissions-list,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content .permissions-list,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar .permissions-list,
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body nav.tabs,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content nav.tabs,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar nav.tabs,
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body nav.tabs button,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content nav.tabs button,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar nav.tabs button,
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body nav.tabs button .count,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content nav.tabs button .count,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar nav.tabs button .count,
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body button,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content button,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar button {
|
||||
color: var(--rdd-color-text-primary);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body a,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content a,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar a {
|
||||
color: var(--color-dark-3);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body a.filter.active,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content a.filter.active,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar a.filter.active {
|
||||
color: var(--color-dark-1);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content {
|
||||
background: url(../assets/ui/bg_left.webp) no-repeat left top;
|
||||
color: var(--rdd-color-text-primary);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header {
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-header {
|
||||
background: #011d33 url(../assets/ui/bg_header.webp) no-repeat left top;
|
||||
color: #ffffff;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header label,
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header .hint,
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header .permissions-list,
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header nav.tabs,
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header nav.tabs button,
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header nav.tabs button .count,
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header div,
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header button {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header input {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-header :is(
|
||||
input[type="text"],
|
||||
input[type="number"],
|
||||
input[type="password"],
|
||||
input[type="datetime-local"],
|
||||
input[type="date"],
|
||||
input[type="time"]) {
|
||||
color: rgba(255, 255, 255, 0.75);
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border: 0 none;
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header input[type="checkbox"] {
|
||||
color: rgba(255, 255, 255, 0.75);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon input[type="number"] {
|
||||
text-align: right;
|
||||
padding-right: 0.5rem;
|
||||
@@ -1676,7 +1625,7 @@ select,
|
||||
width: calc(100% - 2px);
|
||||
height: var(--form-field-height);
|
||||
margin: 0;
|
||||
color: var(--rdd-color-text-primary);
|
||||
color: var(--color-text-dark-primary);
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon form.app-personnage-aleatoire h2 {
|
||||
|
||||
@@ -656,15 +656,9 @@
|
||||
margin: 0.1rem 0;
|
||||
align-items: center;
|
||||
}
|
||||
.prosemirror {
|
||||
menu{
|
||||
background-color: var(--color-background-chat-message);
|
||||
}
|
||||
}
|
||||
.app.sheet .editor.prosemirror {
|
||||
height: fit-content;
|
||||
min-height: 5rem;
|
||||
|
||||
}
|
||||
.app.sheet .editor.prosemirror .editor-container {
|
||||
min-height: 5rem;
|
||||
@@ -871,60 +865,26 @@
|
||||
.type-compendium {
|
||||
font-size: 0.6rem;
|
||||
}
|
||||
.window-app.sheet .window-content .sheet-body,
|
||||
.application .window-content,
|
||||
.journal-entry .journal-sidebar {
|
||||
background: url(../assets/ui/bg_left.webp) no-repeat left top;
|
||||
color: var(--rdd-color-text-primary);
|
||||
label ,
|
||||
.hint ,
|
||||
.permissions-list ,
|
||||
nav.tabs,
|
||||
nav.tabs button,
|
||||
nav.tabs button .count,
|
||||
button {
|
||||
color: var(--rdd-color-text-primary);
|
||||
}
|
||||
a {
|
||||
color: var(--color-dark-3);
|
||||
}
|
||||
a.filter.active {
|
||||
color: var(--color-dark-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ======================================== */
|
||||
/* Sheet */
|
||||
.window-app .window-content{
|
||||
background: url(../assets/ui/bg_left.webp) no-repeat left top;
|
||||
color: var(--rdd-color-text-primary);
|
||||
|
||||
.sheet-header {
|
||||
background: #011d33 url(../assets/ui/bg_header.webp) no-repeat left top;
|
||||
|
||||
label ,
|
||||
.hint ,
|
||||
.permissions-list ,
|
||||
nav.tabs,
|
||||
nav.tabs button,
|
||||
nav.tabs button .count,
|
||||
div,
|
||||
button {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
input {
|
||||
//color: rgba(255, 255, 255, 0);
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
border: 0 none;
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
input[type="checkbox"] {
|
||||
// background-color: hsla(268, 41%, 56%, 0.9);
|
||||
color: rgba(255, 255, 255, 0.75);
|
||||
}
|
||||
}
|
||||
}
|
||||
.window-app.sheet .window-content .sheet-header{
|
||||
background: #011d33 url(../assets/ui/bg_header.webp) no-repeat left top;
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
.window-app.sheet .window-content .sheet-header :is(
|
||||
input[type="text"],
|
||||
input[type="number"],
|
||||
input[type="password"],
|
||||
input[type="datetime-local"],
|
||||
input[type="date"],
|
||||
input[type="time"]) {
|
||||
color: rgba(255, 255, 255, 0.75);
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border: 0 none;
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
text-align: right;
|
||||
@@ -968,7 +928,7 @@
|
||||
width: calc(100% - 2px);
|
||||
height: var(--form-field-height);
|
||||
margin: 0;
|
||||
color: var(--rdd-color-text-primary);
|
||||
color: var(--color-text-dark-primary);
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
form.app-personnage-aleatoire {
|
||||
|
||||
@@ -190,7 +190,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
const forceRequise = RdDItemArme.valeurMain(arme.system.force ?? 0, main)
|
||||
const ecaillesEfficacite = arme.system.magique ? arme.system.ecaille_efficacite : 0;
|
||||
|
||||
const comp = this.getCompetence(arme.getCompetenceAction(main))
|
||||
const comp = this.getCompetence(RdDActor.$getCompetenceAction(arme, main))
|
||||
const unique = [comp.id, arme.name, dommages, forceRequise, ecaillesEfficacite].join('|');
|
||||
if (uniques.includes(unique)) {
|
||||
return
|
||||
@@ -219,12 +219,15 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
}
|
||||
|
||||
addAttaque(RdDItemArme.empoignade(this), ATTAQUE_TYPE.CORPS_A_CORPS)
|
||||
|
||||
this.itemTypes[ITEM_TYPES.arme]
|
||||
.filter(it => it.isAttaque())
|
||||
.sort(Misc.ascending(it => it.name))
|
||||
.forEach(arme => arme.getTypeAttaques().forEach(t => addAttaque(arme, t)))
|
||||
|
||||
.forEach(arme => {
|
||||
if (arme.system.unemain && arme.system.competence && arme.system.resistance > 0) { addAttaque(arme, ATTAQUE_TYPE.UNE_MAIN) }
|
||||
if (arme.system.deuxmains && arme.system.competence && arme.system.resistance > 0) { addAttaque(arme, ATTAQUE_TYPE.DEUX_MAINS) }
|
||||
if (arme.system.lancer && arme.system.resistance > 0) { addAttaque(arme, ATTAQUE_TYPE.LANCER) }
|
||||
if (arme.system.tir) { addAttaque(arme, ATTAQUE_TYPE.TIR) }
|
||||
})
|
||||
addAttaque(RdDItemArme.pugilat(this), ATTAQUE_TYPE.CORPS_A_CORPS)
|
||||
|
||||
return actions
|
||||
@@ -241,6 +244,16 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
}
|
||||
}
|
||||
|
||||
static $getCompetenceAction(arme, main) {
|
||||
switch (main) {
|
||||
case ATTAQUE_TYPE.UNE_MAIN: return arme.competence1Mains()
|
||||
case ATTAQUE_TYPE.DEUX_MAINS: return arme.competence2Mains()
|
||||
case ATTAQUE_TYPE.LANCER: return arme.system.lancer
|
||||
case ATTAQUE_TYPE.TIR: return arme.system.tir
|
||||
default: return arme.system.competence
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async $perteReveEnchantementsChateauDormants() {
|
||||
const toUpdate = this.items.filter(it => [ITEM_TYPES.potion, ITEM_TYPES.gemme].includes(it.type))
|
||||
|
||||
@@ -1,288 +0,0 @@
|
||||
import { ACTOR_TYPES, ITEM_TYPES } from "../../constants.js"
|
||||
import { Grammar } from "../../grammar.js"
|
||||
import { RdDItemArme } from "../../item/arme.js"
|
||||
import { CATEGORIES_COMPETENCE_COMBAT } from "../../item/base-items.js"
|
||||
import { Misc } from "../../misc.js"
|
||||
import { RdDTimestamp } from "../../time/rdd-timestamp.js"
|
||||
import { PDFDocument } from "./pdf-lib/pdf-lib.esm.js"
|
||||
|
||||
|
||||
|
||||
const copyProperty = (actor, path) => foundry.utils.getProperty(actor, path)
|
||||
|
||||
// const findItem = (actor, itemType, itemName) => actor.itemTypes[itemType].find(it => Grammar.equalsInsensitive(formCompName(it.name), formCompName(itemName)))
|
||||
// const findItemPos = (actor, itemType, pos) => actor.itemTypes[itemType].length <= pos ? actor.itemTypes[itemType][pos] : length
|
||||
// const findProperty = (it, path) => it ? foundry.utils.getProperty(it, path) : undefined
|
||||
|
||||
// const findItemProperty = (actor, itemType, itemName, path) => findProperty(findItem(actor, itemType, itemName), path)
|
||||
// const findItemPosProperty = (actor, itemType, pos, path) => findProperty(findItemPos(actor, itemType, pos), path)
|
||||
|
||||
// const findArmeProperty = (actor, pos, path) => findProperty(findItemPos(actor, ITEM_TYPES.arme, pos), path)
|
||||
// const findSortProperty = (actor, pos, path) => findProperty(findItemPos(actor, ITEM_TYPES.sort, pos), path)
|
||||
|
||||
// const itemFormPath = (type, pos, property) => `${type}s.${pos}.${property}`
|
||||
|
||||
|
||||
const ACTOR_TO_FORM_MAPPING = [
|
||||
{ path: 'name' },
|
||||
{ path: 'system.carac.taille.value' },
|
||||
{ path: 'system.carac.apparence.value' },
|
||||
{ path: 'system.carac.apparence.xp' },
|
||||
{ path: 'system.carac.constitution.value' },
|
||||
{ path: 'system.carac.constitution.xp' },
|
||||
{ path: 'system.carac.force.value' },
|
||||
{ path: 'system.carac.force.value' },
|
||||
{ path: 'system.carac.force.xp' },
|
||||
{ path: 'system.carac.agilite.value' },
|
||||
{ path: 'system.carac.agilite.xp' },
|
||||
{ path: 'system.carac.dexterite.value' },
|
||||
{ path: 'system.carac.dexterite.xp' },
|
||||
{ path: 'system.carac.vue.value' },
|
||||
{ path: 'system.carac.vue.xp' },
|
||||
{ path: 'system.carac.ouie.value' },
|
||||
{ path: 'system.carac.ouie.xp' },
|
||||
{ path: 'system.carac.odoratgout.value' },
|
||||
{ path: 'system.carac.odoratgout.xp' },
|
||||
{ path: 'system.carac.volonte.value' },
|
||||
{ path: 'system.carac.volonte.xp' },
|
||||
{ path: 'system.carac.empathie.value' },
|
||||
{ path: 'system.carac.empathie.xp' },
|
||||
{ path: 'system.carac.intellect.value' },
|
||||
{ path: 'system.carac.intellect.xp' },
|
||||
{ path: 'system.carac.reve.value' },
|
||||
{ path: 'system.carac.reve.xp' },
|
||||
{ path: 'system.carac.chance.value' },
|
||||
{ path: 'system.carac.chance.xp' },
|
||||
|
||||
{ path: 'system.age' },
|
||||
{ path: 'system.sexe' },
|
||||
{ path: 'system.taille' },
|
||||
{ path: 'system.poids' },
|
||||
{ path: 'system.cheveux' },
|
||||
{ path: 'system.yeux' },
|
||||
{ path: 'system.beaute' },
|
||||
{ path: 'system.main' },
|
||||
{ path: 'system.heure' },
|
||||
{ path: 'computed.hn.heure', getter: actor => (RdDTimestamp.definition(actor.system.heure)?.heure ?? 0) + 1 },
|
||||
{ path: 'computed.hn.label', getter: actor => RdDTimestamp.definition(actor.system.heure)?.avecArticle },
|
||||
|
||||
{ path: 'system.carac.melee.value' },
|
||||
{ path: 'system.carac.tir.value' },
|
||||
{ path: 'system.carac.lancer.value' },
|
||||
{ path: 'system.carac.derobee.value' },
|
||||
{ path: 'system.sante.vie.value' },
|
||||
{ path: 'system.sante.endurance.value' },
|
||||
|
||||
{ path: 'system.attributs.sust.value' },
|
||||
{ path: 'system.attributs.sconst.value' },
|
||||
{ path: 'system.attributs.encombrement.value' },
|
||||
{ path: 'system.attributs.plusdom.value', getter: actor => Misc.toSignedString(actor.system.attributs.plusdom.value) },
|
||||
|
||||
// , getter: actor => actor.get
|
||||
]
|
||||
|
||||
export default class ExportPdf {
|
||||
|
||||
static init() {
|
||||
Hooks.on("getActorContextOptions", (actorDirectory, menus) => { ExportPdf.onActorDirectoryMenu(actorDirectory, menus) })
|
||||
}
|
||||
|
||||
static onActorDirectoryMenu(actorDirectory, menus) {
|
||||
menus.push({
|
||||
name: 'Export PDF',
|
||||
icon: '<i class="fa-regular fa-file-pdf"></i>',
|
||||
condition: target => actorDirectory.id == 'actors' && ExportPdf.$isActorPersonnage(this.$getActor(target)),
|
||||
callback: async target => await ExportPdf.exportActor(target)
|
||||
})
|
||||
}
|
||||
|
||||
static $getActor(target) {
|
||||
const entryId = $(target).closest(".directory-item")?.data("entryId")
|
||||
return game.actors.get(entryId)
|
||||
}
|
||||
|
||||
static $isActorPersonnage(actor) {
|
||||
return actor?.type == ACTOR_TYPES.personnage
|
||||
}
|
||||
|
||||
static async exportActor(target) {
|
||||
const actor = ExportPdf.$getActor(target)
|
||||
if (!ExportPdf.$isActorPersonnage(actor)) {
|
||||
ui.notifications.error("Pas de personnage sélectionné")
|
||||
return
|
||||
}
|
||||
const templatePdf = '/systems/foundryvtt-reve-de-dragon/assets/feuille-personnage.pdf';
|
||||
|
||||
const pdfBytes = await fetch(templatePdf).then(res => res.arrayBuffer())
|
||||
const pdfDoc = await PDFDocument.load(pdfBytes)
|
||||
|
||||
const exporter = new ExportPdf(actor, pdfDoc)
|
||||
exporter.generateFeuillePersonnage()
|
||||
}
|
||||
|
||||
constructor(actor, pdfDoc) {
|
||||
this.pdfDoc = pdfDoc
|
||||
this.form = this.pdfDoc.getForm()
|
||||
this.actor = actor
|
||||
this.allComps = this.actor.itemTypes[ITEM_TYPES.competence]
|
||||
this.comps = this.allComps
|
||||
.filter(it => !it.isNiveauBase())
|
||||
.sort(Misc.ascending(it => it.name))
|
||||
|
||||
this.compsNonArmes = this.comps.filter(it => !ExportPdf.isCompCombat(it))
|
||||
this.compsArmes = this.comps.filter(it => ExportPdf.isCompCombat(it))
|
||||
this.addedComps = new Set([])
|
||||
}
|
||||
|
||||
static isCompCombat(comp) {
|
||||
return CATEGORIES_COMPETENCE_COMBAT.includes(comp.system.categorie) && !Grammar.includesLowerCaseNoAccent(comp.name, "corps à corps") && !Grammar.includesLowerCaseNoAccent(comp.name, "esquive")
|
||||
}
|
||||
|
||||
async generateFeuillePersonnage() {
|
||||
|
||||
this.$exportActorFields()
|
||||
this.$exportCompetences()
|
||||
this.$exportArchetype()
|
||||
this.$exportArmes()
|
||||
this.$exportSorts()
|
||||
|
||||
const pdfBytes = await this.pdfDoc.save();
|
||||
const filename = `rdd-${this.actor.name.slugify()}.pdf`;
|
||||
foundry.utils.saveDataToFile(pdfBytes, "application/pdf", filename);
|
||||
}
|
||||
|
||||
$exportActorFields() {
|
||||
ACTOR_TO_FORM_MAPPING.forEach(async (mapping) => {
|
||||
const path = mapping.path
|
||||
const value = mapping.getter ? mapping.getter(this.actor) : copyProperty(this.actor, path)
|
||||
this.$setFormValue(path, value)
|
||||
})
|
||||
}
|
||||
|
||||
$exportCompetences() {
|
||||
this.compsNonArmes
|
||||
.filter(it => !this.addedComps.has(it.id))
|
||||
.forEach(comp => {
|
||||
const formCompName = Grammar.toLowerCaseNoAccent(comp.name.replaceAll(/(\s|-|\')/g, '_'))
|
||||
this.$setFormCompetence(formCompName, comp)
|
||||
})
|
||||
const musique = this.compsNonArmes.filter(it => Grammar.includesLowerCaseNoAccent(it.name, 'musique'))
|
||||
.sort(Misc.descending(it => it.system.niveau))
|
||||
.filter(it => !this.addedComps.has(it.id))
|
||||
.find(it => true)
|
||||
if (musique) {
|
||||
this.$setFormCompetence('musique', musique)
|
||||
}
|
||||
}
|
||||
|
||||
$exportArchetype() {
|
||||
this.allComps.sort(Misc.ascending(it => it.system.niveau_archetype))
|
||||
.forEach(comp => {
|
||||
let formCompName = Grammar.toLowerCaseNoAccent(comp.name.replaceAll(/(\s|-|\')/g, '_'))
|
||||
if (formCompName.includes('musique')) {
|
||||
formCompName = 'musique'
|
||||
}
|
||||
this.$setFormValue(`competences.${formCompName}.niveau_archetype`, comp.system.niveau_archetype)
|
||||
})
|
||||
}
|
||||
|
||||
$setFormCompetenceArchetype(formCompName, comp, baseFormName = 'competences') {
|
||||
}
|
||||
|
||||
$exportArmes() {
|
||||
const uniques = new Set([])
|
||||
const armes = this.actor.itemTypes[ITEM_TYPES.arme].map(arme => arme.getTypeAttaques()
|
||||
.map(main => {
|
||||
const compName = arme.getCompetenceAction(main)
|
||||
const dommages = RdDItemArme.valeurMain(arme.system.dommages, main)
|
||||
const forceRequise = RdDItemArme.valeurMain(arme.system.force ?? 0, main)
|
||||
const comp = this.compsArmes.find(it => Grammar.equalsInsensitive(it.name, compName)) ?? this.actor.findItemLike(compName, ITEM_TYPES.competence)
|
||||
const unique = [comp.id, arme.name, dommages, forceRequise].join('|');
|
||||
if (uniques.has(unique)) {
|
||||
return undefined
|
||||
}
|
||||
uniques.add(unique)
|
||||
return { arme: arme, comp: comp, main: main }
|
||||
}))
|
||||
.reduce((a, b) => a.concat(b))
|
||||
.filter(it => it != undefined && !it.comp.isNiveauBase())
|
||||
.sort(Misc.descending(it => it.comp.niveau))
|
||||
|
||||
for (let pos = 0; pos < armes.length; pos++) {
|
||||
const it = armes[pos]
|
||||
this.$setFormArmeCompetence(pos, it.comp, it.arme, it.main, it.main)
|
||||
}
|
||||
|
||||
// TODO: list comps without weapons
|
||||
// TODO: list other comps not in the standard list -- use an instance of ExportPdf to hold state/built list
|
||||
const otherComps = this.comps.filter(it => !this.addedComps.has(it.id))
|
||||
for (let pos = 0; pos < otherComps.length; pos++) {
|
||||
const comp = otherComps[pos]
|
||||
this.$setFormCompetence(pos, comp, 'competences')
|
||||
this.$setFormValue(`competences.${pos}.name`, comp.name)
|
||||
}
|
||||
}
|
||||
|
||||
$setFormCompetence(formCompName, comp, baseFormName = 'competences') {
|
||||
|
||||
if (this.form.getFieldMaybe(`${baseFormName}.${formCompName}.niveau`)) {
|
||||
this.addedComps.add(comp.id)
|
||||
}
|
||||
if (comp.system.niveau != comp.system.base) {
|
||||
this.$setFormValue(`${baseFormName}.${formCompName}.niveau`, comp.system.niveau)
|
||||
}
|
||||
if (comp.system.xp > 0) {
|
||||
this.$setFormValue(`${baseFormName}.${formCompName}.xp`, comp.system.xp)
|
||||
}
|
||||
if (comp.system.xp_sort > 0) {
|
||||
this.$setFormValue(`${baseFormName}.${formCompName}.xp_sort`, comp.system.xp_sort)
|
||||
}
|
||||
if (CATEGORIES_COMPETENCE_COMBAT.includes(comp.system.categorie)) {
|
||||
this.$setFormValue(`${baseFormName}.${formCompName}.init`, comp.getBaseInit())
|
||||
}
|
||||
}
|
||||
|
||||
$setFormArmeCompetence(pos, comp, arme, main) {
|
||||
this.$setFormCompetence(pos, comp, 'armes')
|
||||
this.$setFormValue(`armes.${pos}.name`, arme.name)
|
||||
this.$setFormValue(`armes.${pos}.main`, main)
|
||||
this.$setFormValue(`armes.${pos}.plusdom`, RdDItemArme.valeurMain(arme.system.dommages, main))
|
||||
}
|
||||
|
||||
$exportSorts() {
|
||||
const sorts = this.actor.itemTypes[ITEM_TYPES.sort].sort(Misc.ascending(s => ExportPdf.$orderDraconic(s) + s.name))
|
||||
|
||||
for (let pos = 0; pos < sorts.length; pos++) {
|
||||
const sort = sorts[pos]
|
||||
this.$setFormSort(pos, sort)
|
||||
}
|
||||
}
|
||||
|
||||
$setFormSort(pos, sort) {
|
||||
this.$setFormValue(`sorts.${pos}.name`, sort.name)
|
||||
this.$setFormValue(`sorts.${pos}.voie`, sort.system.draconic)
|
||||
this.$setFormValue(`sorts.${pos}.tmr`, sort.system.caseTMRSpeciale ?? sort.system.caseTMR)
|
||||
this.$setFormValue(`sorts.${pos}.diff`, sort.system.difficulte)
|
||||
this.$setFormValue(`sorts.${pos}.reve`, sort.system.ptreve)
|
||||
this.$setFormValue(`sorts.${pos}.bonuscase`, sort.system.bonuscase)
|
||||
}
|
||||
|
||||
static $orderDraconic(s) {
|
||||
switch (s.system.draconic.substring(0, 1)) {
|
||||
case 'O': return 1
|
||||
case 'H': return 2
|
||||
case 'N': return 3
|
||||
case 'T': return 4
|
||||
}
|
||||
return 5
|
||||
}
|
||||
|
||||
$setFormValue(path, value) {
|
||||
const hasField = this.form.getFieldMaybe(path)
|
||||
if (hasField && value != undefined) {
|
||||
const field = this.form.getTextField(path)
|
||||
field.setText(value.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
16
module/actor/export-pdf/pdf-lib/pdf-lib.min.js
vendored
16
module/actor/export-pdf/pdf-lib/pdf-lib.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -20,11 +20,11 @@ export class RdDInitiative {
|
||||
return "1d6" + (base >= 0 ? "+" : "") + base
|
||||
}
|
||||
|
||||
static ajustementInitiative(caracValue, niveau, bonus = 0) {
|
||||
static ajustementInitiative(caracValue, niveau, bonus) {
|
||||
return niveau + Math.floor(caracValue / 2) + bonus
|
||||
}
|
||||
|
||||
static formule(phase, carac, niveau, bonusMalus = 0) {
|
||||
static formule(phase, carac, niveau, bonusMalus) {
|
||||
const ajustement = RdDInitiative.ajustementInitiative(carac, niveau, bonusMalus)
|
||||
return { phase, ajustement }
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { RdDInitiative } from "./initiative.mjs";
|
||||
import { RdDItem } from "./item.js";
|
||||
import { CATEGORIES_COMPETENCE_COMBAT, CATEGORIES_COMPETENCES, SANS_COMPETENCE } from "./item/base-items.js";
|
||||
import { CATEGORIES_COMPETENCES, SANS_COMPETENCE } from "./item/base-items.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
const competenceTroncs = [["Esquive", "Dague", "Corps à corps"],
|
||||
@@ -47,30 +46,6 @@ export class RdDItemCompetence extends RdDItem {
|
||||
|
||||
static get defaultIcon() { return "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp" }
|
||||
|
||||
isNiveauBase() {
|
||||
return this.system.niveau == this.system.base && this.system.xp == 0
|
||||
}
|
||||
|
||||
getBaseInit() {
|
||||
const carac = this.getInitCarac()
|
||||
if (carac == undefined) {
|
||||
return undefined
|
||||
}
|
||||
return RdDInitiative.ajustementInitiative(carac.value, this.system.niveau)
|
||||
}
|
||||
|
||||
getInitCarac() {
|
||||
if (!this.actor) {
|
||||
return undefined
|
||||
}
|
||||
switch (this.system.categorie) {
|
||||
case CATEGORIES_COMPETENCES.melee.key: return this.actor.system.carac.melee
|
||||
case CATEGORIES_COMPETENCES.tir.key: return this.actor.system.carac.tir
|
||||
case CATEGORIES_COMPETENCES.lancer.key: return this.actor.system.carac.lancer
|
||||
case CATEGORIES_COMPETENCES.draconic.key: return this.actor.system.carac.reve
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static getLabelCategorie(category) {
|
||||
return CATEGORIES_COMPETENCES[category].label;
|
||||
|
||||
@@ -62,7 +62,7 @@ export class RdDItemSort extends Item {
|
||||
|
||||
|
||||
static diffReve(sort) { return RdDItemSort.toVar((sort.system.difficulte.match(/\-?(\d)+/) ? 'R' : 'R ') + sort.system.difficulte) }
|
||||
static coutReve(sort) { return RdDItemSort.toVar((Number.isInteger(sort.system.ptreve || sort.system.ptreve.match(/(\d)+\+?/)) ? 'r' : 'r ') + sort.system.ptreve) }
|
||||
static coutReve(sort) { return RdDItemSort.toVar((sort.system.ptreve.match(/(\d)+\+?/) ? 'r' : 'r ') + sort.system.ptreve) }
|
||||
static getDraconicsSort(competencesDraconic, sort) {
|
||||
// se baser sur la voie du sort?
|
||||
switch (Grammar.toLowerCaseNoAccent(sort.name)) {
|
||||
|
||||
@@ -45,16 +45,6 @@ export class RdDItemArme extends RdDItem {
|
||||
isParade() { return this.system.resistance > 0 && this.system.categorie_parade }
|
||||
isBouclier() { return RdDItemArme.getCategorieParade(this).includes('bouclier') }
|
||||
|
||||
|
||||
getCompetenceAction(main) {
|
||||
switch (main) {
|
||||
case ATTAQUE_TYPE.UNE_MAIN: return this.competence1Mains()
|
||||
case ATTAQUE_TYPE.DEUX_MAINS: return this.competence2Mains()
|
||||
case ATTAQUE_TYPE.LANCER: return this.system.lancer
|
||||
case ATTAQUE_TYPE.TIR: return this.system.tir
|
||||
default: return this.system.competence
|
||||
}
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static valeurMain(valeurs, main) {
|
||||
valeurs = valeurs?.toString() ?? ""
|
||||
@@ -88,26 +78,17 @@ export class RdDItemArme extends RdDItem {
|
||||
return arme.name
|
||||
case ITEM_TYPES.arme:
|
||||
switch (maniement) {
|
||||
case ATTAQUE_TYPE.COMPETENCE: return arme.system.competence
|
||||
case ATTAQUE_TYPE.COMPETENCE: return arme.system.competence;
|
||||
case ATTAQUE_TYPE.UNE_MAIN: return arme.competence1Mains()
|
||||
case ATTAQUE_TYPE.DEUX_MAINS: return arme.competence2Mains()
|
||||
case ATTAQUE_TYPE.TIR: case 'tir': return arme.system.tir
|
||||
case ATTAQUE_TYPE.LANCER: case 'lancer': return arme.system.lancer
|
||||
case ATTAQUE_TYPE.LANCER: case 'lancer': return arme.system.lancer;
|
||||
case ATTAQUE_TYPE.CORPS_A_CORPS: return CORPS_A_CORPS
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
getTypeAttaques() {
|
||||
return [
|
||||
...(this.system.unemain && this.system.competence && this.system.resistance > 0) ? [ATTAQUE_TYPE.UNE_MAIN] : [],
|
||||
...(this.system.deuxmains && this.system.competence && this.system.resistance > 0) ? [ATTAQUE_TYPE.DEUX_MAINS] : [],
|
||||
...(this.system.lancer && this.system.resistance > 0) ? [ATTAQUE_TYPE.LANCER] : [],
|
||||
...(this.system.tir) ? [ATTAQUE_TYPE.TIR] : [],
|
||||
]
|
||||
}
|
||||
|
||||
static computeNiveauArmes(armes, competences) {
|
||||
for (const arme of armes) {
|
||||
arme.system.niveau = RdDItemArme.niveauCompetenceArme(arme, competences);
|
||||
|
||||
@@ -14,28 +14,27 @@ export const SANS_COMPETENCE = {
|
||||
description: "",
|
||||
descriptionmj: "",
|
||||
defaut_carac: "",
|
||||
},
|
||||
},
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.webp"
|
||||
}
|
||||
}
|
||||
|
||||
export const CATEGORIES_COMPETENCES = {
|
||||
generale: { key: 'generale', base: -4, label: "Générales" },
|
||||
particuliere: { key: 'particuliere', base: -8, label: "Particulières" },
|
||||
specialisee: { key: 'specialisee', base: -11, label: "Spécialisées" },
|
||||
connaissance: { key: 'connaissance', base: -11, label: "Connaissances" },
|
||||
draconic: { key: 'draconic', base: -11, label: "Draconic" },
|
||||
melee: { key: 'melee', base: -6, label: "Mêlée" },
|
||||
tir: { key: 'tir', base: -8, label: "Tir" },
|
||||
lancer: { key: 'lancer', base: -8, label: "Lancer" }
|
||||
"generale": { base: -4, label: "Générales" },
|
||||
"particuliere": { base: -8, label: "Particulières" },
|
||||
"specialisee": { base: -11, label: "Spécialisées" },
|
||||
"connaissance": { base: -11, label: "Connaissances" },
|
||||
"draconic": { base: -11, label: "Draconic" },
|
||||
"melee": { base: -6, label: "Mêlée" },
|
||||
"tir": { base: -8, label: "Tir" },
|
||||
"lancer": { base: -8, label: "Lancer" }
|
||||
}
|
||||
export const CATEGORIES_COMPETENCE_COMBAT = [CATEGORIES_COMPETENCES.melee, CATEGORIES_COMPETENCES.tir, CATEGORIES_COMPETENCES.lancer].map(it => it.key)
|
||||
|
||||
export const CATEGORIES_COMPETENCES_CREATURES = {
|
||||
generale: { key: 'generale', base: 0, label: "Générale" },
|
||||
naturelle: { key: 'naturelle', base: 0, label: "Arme naturelle" },
|
||||
melee: { key: 'melee', base: 0, label: "Mêlée" },
|
||||
parade: { key: 'parade', base: 0, label: "Parade" },
|
||||
tir: { key: 'tir', base: 0, label: "Tir" },
|
||||
lancer: { key: 'lancer', base: 0, label: "Lancer" },
|
||||
possession: { key: 'possession', base: 0, label: "Possession" },
|
||||
"generale": { base: 0, label: "Générale" },
|
||||
"naturelle": { base: 0, label: "Arme naturelle" },
|
||||
"melee": { base: 0, label: "Mêlée" },
|
||||
"parade": { base: 0, label: "Parade" },
|
||||
"tir": { base: 0, label: "Tir" },
|
||||
"lancer": { base: 0, label: "Lancer" },
|
||||
"possession": { base: 0, label: "Possession" },
|
||||
}
|
||||
|
||||
@@ -12,13 +12,12 @@ const _SPACEHOLDER = { placeholder: true }
|
||||
|
||||
const _VENDRE = {
|
||||
code: 'item-vendre', label: 'Vendre ou donner', icon: it => 'fa-solid fa-comments-dollar',
|
||||
filter: it => Misc.toInt(it.system.quantite) > 0 || it.parent?.type == ACTOR_TYPES.commerce,
|
||||
filter: it => Misc.toInt(it.system.quantite) > 0,
|
||||
action: (item, actor) => item.proposerVente()
|
||||
}
|
||||
const _ACHETER = {
|
||||
code: 'item-acheter', label: 'Acheter', icon: it => 'fa-regular fa-coins',
|
||||
filter: it => it.parent?.type == ACTOR_TYPES.commerce,
|
||||
allowLimited: true,
|
||||
filter: it => Misc.toInt(it.system.quantite) > 0 && it.parent?.type == ACTOR_TYPES.commerce,
|
||||
action: (item, actor) => actor.vente(item)
|
||||
}
|
||||
const _MONTRER = {
|
||||
|
||||
@@ -58,9 +58,9 @@ export class RdDCombatManager extends Combat {
|
||||
|
||||
|
||||
static getCombatant(actorId, tokenId) {
|
||||
return game.combat?.combatants.find(it => it.actor.id == actorId &&
|
||||
return game.combat.combatants.find(it => it.actor.id == actorId &&
|
||||
it.token.id == tokenId
|
||||
)
|
||||
);
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
async nextRound() {
|
||||
|
||||
@@ -89,7 +89,6 @@ import { Migrations } from './migrations.js'
|
||||
|
||||
import RollDialog from "./roll/roll-dialog.mjs"
|
||||
import ChatRollResult from "./roll/chat-roll-result.mjs"
|
||||
import ExportPdf from "./actor/export-pdf/export-pdf.mjs"
|
||||
|
||||
/**
|
||||
* RdD system
|
||||
@@ -297,7 +296,6 @@ export class SystemReveDeDragon {
|
||||
RdDPossession.init()
|
||||
TMRRencontres.init()
|
||||
ExportScriptarium.init()
|
||||
ExportPdf.init()
|
||||
RollDialog.init()
|
||||
ChatRollResult.init()
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ export class StatusEffects extends FormApplication {
|
||||
}
|
||||
|
||||
static prepareActiveEffect(effectId) {
|
||||
let status = rddStatusEffects.find(it => it.statuses? it.statuses.has(effectId) : it.id == effectId)
|
||||
let status = rddStatusEffects.find(it => it.statuses.has(effectId))
|
||||
if (status) {
|
||||
status = foundry.utils.duplicate(status)
|
||||
status.statuses = new Set([effectId])
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
"dependencies": {
|
||||
"gulp": "^5.0.0",
|
||||
"gulp-less": "^5.0.0",
|
||||
"pdf-lib": "^1.17.1",
|
||||
"rollup-plugin-visualizer": "^5.12.0"
|
||||
},
|
||||
"repository": {
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Andrew Dillon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -40,7 +40,6 @@
|
||||
</div>
|
||||
<hr>
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire.hbs"}}
|
||||
{{log @root.options}}
|
||||
{{#unless system.illimite}}
|
||||
{{#if @root.options.isObserver}}
|
||||
<hr>
|
||||
|
||||
Reference in New Issue
Block a user