feature: generate pdf from actor
This commit is contained in:
@@ -19,7 +19,7 @@ build:
|
||||
- cp styles/* dist/styles/
|
||||
- cp module.json 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:
|
||||
name: wfrp4e-actor-sheet-print
|
||||
when: on_success
|
||||
@@ -40,7 +40,7 @@ build_beta:
|
||||
- cp styles/* dist/styles/
|
||||
- cp module-beta.json dist/module.json
|
||||
- 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:
|
||||
name: wfrp4e-actor-sheet-print
|
||||
when: on_success
|
||||
|
||||
@@ -28,14 +28,16 @@ export class Column extends AbstractElement {
|
||||
}
|
||||
|
||||
public getHeight(doc): number {
|
||||
return this.elements
|
||||
.map((e) => e.getHeight(doc))
|
||||
.reduce((p, c, i) => {
|
||||
if (i === 0) {
|
||||
return c;
|
||||
}
|
||||
return p + c + 2;
|
||||
});
|
||||
return this.elements.length > 0
|
||||
? this.elements
|
||||
.map((e) => e.getHeight(doc))
|
||||
.reduce((p, c, i) => {
|
||||
if (i === 0) {
|
||||
return c;
|
||||
}
|
||||
return p + c + 2;
|
||||
})
|
||||
: 0;
|
||||
}
|
||||
|
||||
public getCheckNewPageHeight(doc?: jsPDF): number {
|
||||
|
||||
@@ -25,7 +25,7 @@ export class LabelledValues extends Row {
|
||||
const labelPercent = 100 - valuePercent;
|
||||
const widthPercent = [labelPercent, valuePercent];
|
||||
let currentIndex = 0;
|
||||
if (labelledValues.length >= this.nbrOfCol) {
|
||||
if (this.nbrOfCol > 1) {
|
||||
const nbrPerCol = Math.floor(labelledValues.length / this.nbrOfCol);
|
||||
const rest = labelledValues.length - nbrPerCol * this.nbrOfCol;
|
||||
const nbrPerCols = [
|
||||
|
||||
@@ -23,7 +23,7 @@ export class Texts extends Row {
|
||||
this.nbrOfCol = 4;
|
||||
}
|
||||
let currentIndex = 0;
|
||||
if (texts.length >= this.nbrOfCol) {
|
||||
if (this.nbrOfCol > 1) {
|
||||
const nbrPerCol = Math.floor(texts.length / this.nbrOfCol);
|
||||
const rest = texts.length - nbrPerCol * this.nbrOfCol;
|
||||
const nbrPerCols = [
|
||||
|
||||
233
src/main.ts
233
src/main.ts
@@ -88,7 +88,7 @@ Hooks.on(
|
||||
const weaponsMelee = new Texts(
|
||||
0,
|
||||
0,
|
||||
actor.itemCategories.weapon
|
||||
Util.getActorItems(actor, 'weapon')
|
||||
.filter((w) => w.isMelee)
|
||||
.map((item) => {
|
||||
return `${item.name} : ${item.WeaponGroup}, ${item.Reach}, ${
|
||||
@@ -105,7 +105,7 @@ Hooks.on(
|
||||
const weaponsRanged = new Texts(
|
||||
0,
|
||||
0,
|
||||
actor.itemCategories.weapon
|
||||
Util.getActorItems(actor, 'weapon')
|
||||
.filter((w) => w.isRanged)
|
||||
.map((item) => {
|
||||
return `${item.name} : ${item.WeaponGroup}, ${
|
||||
@@ -124,7 +124,7 @@ Hooks.on(
|
||||
const ammunitions = new Texts(
|
||||
0,
|
||||
0,
|
||||
actor.itemCategories.ammunition
|
||||
Util.getActorItems(actor, 'ammunition')
|
||||
.map((item) => {
|
||||
return `${item.data.data.quantity.value} ${item.name} : ${
|
||||
item.data.data.range.value.length > 0
|
||||
@@ -143,7 +143,7 @@ Hooks.on(
|
||||
|
||||
const armourLocation: 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;
|
||||
for (const key of Object.keys(maxAp)) {
|
||||
if (maxAp[key] > 0) {
|
||||
@@ -174,6 +174,160 @@ Hooks.on(
|
||||
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 imageY = labelledRowHeight + MARGINS.top + 2;
|
||||
const actorImageElement =
|
||||
@@ -353,6 +507,77 @@ Hooks.on(
|
||||
new Separator(0, 0),
|
||||
new Text(0, 0, 'Armour'),
|
||||
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`);
|
||||
|
||||
24
src/util.ts
24
src/util.ts
@@ -4,4 +4,28 @@ export class Util {
|
||||
public static getHeightFromPx(doc: jsPDF, size: number) {
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user