feature: generate pdf from actor

This commit is contained in:
Matthieu CAILLEAUX
2021-10-19 00:32:49 +02:00
parent c66feaf642
commit 338315eed6
6 changed files with 267 additions and 16 deletions

View File

@@ -19,7 +19,7 @@ build:
- cp styles/* dist/styles/ - cp styles/* dist/styles/
- cp module.json dist - cp module.json dist
- cd dist - cd dist
- zip wfrp4e-actor-sheet-print.zip -r *.* src lang styles -x ".*" - zip wfrp4e-actor-sheet-print.zip -r *.* elements lang styles -x ".*"
artifacts: artifacts:
name: wfrp4e-actor-sheet-print name: wfrp4e-actor-sheet-print
when: on_success when: on_success
@@ -40,7 +40,7 @@ build_beta:
- cp styles/* dist/styles/ - cp styles/* dist/styles/
- cp module-beta.json dist/module.json - cp module-beta.json dist/module.json
- cd dist - cd dist
- zip wfrp4e-actor-sheet-print.zip -r *.* src lang styles -x ".*" - zip wfrp4e-actor-sheet-print.zip -r *.* elements lang styles -x ".*"
artifacts: artifacts:
name: wfrp4e-actor-sheet-print name: wfrp4e-actor-sheet-print
when: on_success when: on_success

View File

@@ -28,14 +28,16 @@ export class Column extends AbstractElement {
} }
public getHeight(doc): number { public getHeight(doc): number {
return this.elements return this.elements.length > 0
.map((e) => e.getHeight(doc)) ? this.elements
.reduce((p, c, i) => { .map((e) => e.getHeight(doc))
if (i === 0) { .reduce((p, c, i) => {
return c; if (i === 0) {
} return c;
return p + c + 2; }
}); return p + c + 2;
})
: 0;
} }
public getCheckNewPageHeight(doc?: jsPDF): number { public getCheckNewPageHeight(doc?: jsPDF): number {

View File

@@ -25,7 +25,7 @@ export class LabelledValues extends Row {
const labelPercent = 100 - valuePercent; const labelPercent = 100 - valuePercent;
const widthPercent = [labelPercent, valuePercent]; const widthPercent = [labelPercent, valuePercent];
let currentIndex = 0; let currentIndex = 0;
if (labelledValues.length >= this.nbrOfCol) { if (this.nbrOfCol > 1) {
const nbrPerCol = Math.floor(labelledValues.length / this.nbrOfCol); const nbrPerCol = Math.floor(labelledValues.length / this.nbrOfCol);
const rest = labelledValues.length - nbrPerCol * this.nbrOfCol; const rest = labelledValues.length - nbrPerCol * this.nbrOfCol;
const nbrPerCols = [ const nbrPerCols = [

View File

@@ -23,7 +23,7 @@ export class Texts extends Row {
this.nbrOfCol = 4; this.nbrOfCol = 4;
} }
let currentIndex = 0; let currentIndex = 0;
if (texts.length >= this.nbrOfCol) { if (this.nbrOfCol > 1) {
const nbrPerCol = Math.floor(texts.length / this.nbrOfCol); const nbrPerCol = Math.floor(texts.length / this.nbrOfCol);
const rest = texts.length - nbrPerCol * this.nbrOfCol; const rest = texts.length - nbrPerCol * this.nbrOfCol;
const nbrPerCols = [ const nbrPerCols = [

View File

@@ -88,7 +88,7 @@ Hooks.on(
const weaponsMelee = new Texts( const weaponsMelee = new Texts(
0, 0,
0, 0,
actor.itemCategories.weapon Util.getActorItems(actor, 'weapon')
.filter((w) => w.isMelee) .filter((w) => w.isMelee)
.map((item) => { .map((item) => {
return `${item.name} : ${item.WeaponGroup}, ${item.Reach}, ${ return `${item.name} : ${item.WeaponGroup}, ${item.Reach}, ${
@@ -105,7 +105,7 @@ Hooks.on(
const weaponsRanged = new Texts( const weaponsRanged = new Texts(
0, 0,
0, 0,
actor.itemCategories.weapon Util.getActorItems(actor, 'weapon')
.filter((w) => w.isRanged) .filter((w) => w.isRanged)
.map((item) => { .map((item) => {
return `${item.name} : ${item.WeaponGroup}, ${ return `${item.name} : ${item.WeaponGroup}, ${
@@ -124,7 +124,7 @@ Hooks.on(
const ammunitions = new Texts( const ammunitions = new Texts(
0, 0,
0, 0,
actor.itemCategories.ammunition Util.getActorItems(actor, 'ammunition')
.map((item) => { .map((item) => {
return `${item.data.data.quantity.value} ${item.name} : ${ return `${item.data.data.quantity.value} ${item.name} : ${
item.data.data.range.value.length > 0 item.data.data.range.value.length > 0
@@ -143,7 +143,7 @@ Hooks.on(
const armourLocation: string[] = []; const armourLocation: string[] = [];
const armourLabels: { [key: string]: string[] } = {}; const armourLabels: { [key: string]: string[] } = {};
for (const armour of actor.itemCategories.armour) { for (const armour of Util.getActorItems(actor, 'armour')) {
const maxAp = armour.data.data.maxAP; const maxAp = armour.data.data.maxAP;
for (const key of Object.keys(maxAp)) { for (const key of Object.keys(maxAp)) {
if (maxAp[key] > 0) { if (maxAp[key] > 0) {
@@ -174,6 +174,160 @@ Hooks.on(
true true
); );
const petty = new Texts(
0,
0,
actor.itemCategories.spell
.filter((s) => s.lore.value === 'petty')
.map((s) => {
return `${s.name} : ${s.cn.value}, ${s.Range}, ${s.Target}, ${s.Duration}`;
}),
2,
true
);
const spell = new Texts(
0,
0,
actor.itemCategories.spell
.filter((s) => s.lore.value !== 'petty')
.map((s) => {
return `${s.name} : ${s.cn.value}, ${s.Range}, ${s.Target}, ${s.Duration}, ${s.ingredientList.length}`;
}),
2,
true
);
const blessing = new Texts(
0,
0,
actor.itemCategories.prayer
.filter((s) => s.prayerType.value === 'blessing')
.map((s) => {
return `${s.name} : ${s.Range}, ${s.Target}, ${s.Duration}`;
}),
2,
true
);
const miracle = new Texts(
0,
0,
actor.itemCategories.prayer
.filter((s) => s.prayerType.value !== 'blessing')
.map((s) => {
return `${s.name} : ${s.Range}, ${s.Target}, ${s.Duration}`;
}),
2,
true
);
const allMoney = Util.getActorItems(actor, 'money');
const moneyNames: string[] = [];
const moneyByName: { [name: string]: number } = {};
for (const money of allMoney) {
if (!moneyNames.includes(money.name)) {
moneyNames.push(money.name);
}
if (moneyByName[money.name] == null) {
moneyByName[money.name] = 0;
}
moneyByName[money.name] =
moneyByName[money.name] + money.quantity.value;
}
const trappingsHeader = new Texts(
0,
0,
[
`${i18nLocalize('Trappings')} : ${i18nLocalize(
'Money'
)} : ${moneyNames
.map((m) => {
return `${m} : ${moneyByName[m]}`;
})
.join(', ')}`,
],
1,
true
);
const trappings = new Texts(
0,
0,
Util.getAllActorItems(actor, ['container', 'trapping'])
.map((t) => {
const location = t.location.value;
let prefix = '';
if (location != null && location !== 0) {
prefix = `${actor.getEmbeddedDocument('Item', location).name} : `;
}
const qteLabel = t.quantity.value > 1 ? `${t.quantity.value} ` : '';
return `${prefix}${qteLabel}${t.name}`;
})
.sort((a, b) => a.localeCompare(b)),
4,
true
);
const critical = new Texts(
0,
0,
actor.itemCategories.critical.map((i) => {
return i.name;
}),
3
);
const disease = new Texts(
0,
0,
actor.itemCategories.disease.map((i) => {
return i.name;
}),
3
);
const injury = new Texts(
0,
0,
actor.itemCategories.injury.map((i) => {
return i.name;
}),
3
);
const mutationP = new Texts(
0,
0,
actor.itemCategories.mutation
.filter((i) => i.mutationType.value === 'physical')
.map((i) => {
return i.name;
}),
3
);
const mutationM = new Texts(
0,
0,
actor.itemCategories.mutation
.filter((i) => i.mutationType.value === 'mental')
.map((i) => {
return i.name;
}),
3
);
const psychology = new Texts(
0,
0,
actor.itemCategories.psychology.map((i) => {
return i.name;
}),
3
);
const imageWidth = 25; const imageWidth = 25;
const imageY = labelledRowHeight + MARGINS.top + 2; const imageY = labelledRowHeight + MARGINS.top + 2;
const actorImageElement = const actorImageElement =
@@ -353,6 +507,77 @@ Hooks.on(
new Separator(0, 0), new Separator(0, 0),
new Text(0, 0, 'Armour'), new Text(0, 0, 'Armour'),
armours, armours,
new Separator(0, 0),
new Text(
0,
0,
`${i18nLocalize('SHEET.PettySpell')} : ${i18nLocalize(
'Casting Number'
)}, ${i18nLocalize('Range')}, ${i18nLocalize(
'Target'
)}, ${i18nLocalize('Duration')}`
),
petty,
new Separator(0, 0),
new Text(
0,
0,
`${i18nLocalize('SHEET.LoreSpell')} : ${i18nLocalize(
'Casting Number'
)}, ${i18nLocalize('Range')}, ${i18nLocalize(
'Target'
)}, ${i18nLocalize('Duration')}, ${i18nLocalize(
'WFRP4E.TrappingType.Ingredients'
)}`
),
spell,
new Separator(0, 0),
new Text(
0,
0,
`${i18nLocalize('Blessing')} : ${i18nLocalize(
'Range'
)}, ${i18nLocalize('Target')}, ${i18nLocalize('Duration')}`
),
blessing,
new Separator(0, 0),
new Text(
0,
0,
`${i18nLocalize('Miracle')} : ${i18nLocalize(
'Range'
)}, ${i18nLocalize('Target')}, ${i18nLocalize('Duration')}`
),
miracle,
new Separator(0, 0),
trappingsHeader,
trappings,
new Separator(0, 0),
new Text(0, 0, 'Psychology'),
psychology,
new Separator(0, 0),
new Text(0, 0, 'Criticals'),
critical,
new Separator(0, 0),
new Text(0, 0, 'Diseases'),
disease,
new Separator(0, 0),
new Text(0, 0, 'Injuries'),
injury,
new Separator(0, 0),
new Text(
0,
0,
`${i18nLocalize('Mutations')} (${i18nLocalize('Physical')})`
),
mutationP,
new Separator(0, 0),
new Text(
0,
0,
`${i18nLocalize('Mutations')} (${i18nLocalize('Mental')})`
),
mutationM,
]), ]),
]); ]);
docBuilder.doc.save(`${app.actor.name}.pdf`); docBuilder.doc.save(`${app.actor.name}.pdf`);

View File

@@ -4,4 +4,28 @@ export class Util {
public static getHeightFromPx(doc: jsPDF, size: number) { public static getHeightFromPx(doc: jsPDF, size: number) {
return size / doc.internal.scaleFactor; return size / doc.internal.scaleFactor;
} }
public static getAllActorItems(
actor: Actor & any,
keys: string[]
): (Item & any)[] {
const result: (Item & any)[] = [];
for (const key of keys) {
result.push(...this.getActorItems(actor, key));
}
return result;
}
public static getActorItems(actor: Actor & any, key: string): (Item & any)[] {
if (actor.itemCategories[key] == null) {
return [];
}
return actor.itemCategories[key].filter((it) => {
const location = it.location.value;
if (location != null && location !== 0) {
return actor.getEmbeddedDocument('Item', location) != null;
}
return true;
});
}
} }