pf2e-sage-stats 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +143 -0
- package/dist/app.js +409 -0
- package/dist/index.js +199 -0
- package/eslint.config.mjs +11 -0
- package/jest.config.ts +11 -0
- package/package.json +40 -0
- package/src/app.ts +623 -0
- package/src/index.ts +198 -0
- package/src/types.d.ts +5 -0
- package/test/app.test.ts +67 -0
- package/tsconfig.json +14 -0
package/README.md
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
## PC Macros
|
|
2
|
+
```
|
|
3
|
+
sage! macro set name=flat dice="[{o:m} d20 >= {0} flat {...}]" cat=Misc
|
|
4
|
+
```
|
|
5
|
+
```
|
|
6
|
+
sage! macro set name="roll" dice="[{o:m} {f} {dice:1}d20+{{pc:pc}::{0}} {map:-0} {mod:+0} {dc} {{pc:pc}::name}: {{pc:pc}::{0}.desc}; {...}]" cat=PC
|
|
7
|
+
```
|
|
8
|
+
```
|
|
9
|
+
sage! macro set name="melee" dice="[{o:m} {f} {dice:1}d20+{{pc:pc}::melee.{s:default}} {map:-0} {mod:+0} {ac} {{pc:pc}::name}: {{pc:pc}::melee.{s:default}.desc} {...}; {{pc:pc}::melee.{s:default}.damage} {damage}]" cat=PC
|
|
10
|
+
```
|
|
11
|
+
```
|
|
12
|
+
sage! macro set name="ranged" dice="[{o:m} {f} {dice:1}d20+{{pc:pc}::melee.{s:default}} {map:-0} {mod:+0} {ac} {{pc:pc}::name}: {{pc:pc}::ranged.{s:default}.desc} {...}; {{pc:pc}::ranged.{s:default}.damage} {damage}]" cat=PC
|
|
13
|
+
```
|
|
14
|
+
```
|
|
15
|
+
sage! macro set name="spell" dice="[{o:m} {f} {dice:1}d20+{{pc:pc}::spells} {map:-0} {mod:+0} {ac} {{pc:pc}::name}: {{pc:pc}::spells.desc}; {...}]" cat=PC
|
|
16
|
+
```
|
|
17
|
+
```
|
|
18
|
+
sage! macro set name="dc" dice="[{o:xs} 0d0+{{pc:pc}::dc.{0}} {mod:+0} {...}]" cat=PC
|
|
19
|
+
```
|
|
20
|
+
## NPC Macros
|
|
21
|
+
## Misc
|
|
22
|
+
```
|
|
23
|
+
sage! macro set name="npc.fp" dice="[{flat::{o:xs}_{f:none}} {...}]" cat=Misc
|
|
24
|
+
```
|
|
25
|
+
```
|
|
26
|
+
sage! macro set name=flat dice="[{o:m} d20 >= {0} flat {...}]" cat=Misc
|
|
27
|
+
```
|
|
28
|
+
### Strikes
|
|
29
|
+
```
|
|
30
|
+
sage! macro set name="npc.melee" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::melee.{s:default}} {vnpc::{m:+0}} {ac} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} {{0}::melee.{s:default}.desc} {e}; {{0}::melee.{s:default}.damage} {...}]" cat=Strikes
|
|
31
|
+
```
|
|
32
|
+
```
|
|
33
|
+
sage! macro set name="npc.mstrike" dice="[npc.melee {0} o={o:xs} f={f:none} d={d:1} m={m:+0} ac=({{1}::ac}{vnpc::{c:+0}}) v={v:+0} s={s:default} e='vs {{1}::name}{anpc::{c:+0}}' {...}]" cat=Strikes
|
|
34
|
+
```
|
|
35
|
+
```
|
|
36
|
+
sage! macro set name="npc.ranged" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::ranged.{s:default}} {vnpc::{m:+0}} {ac} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} {{0}::ranged.{s:default}.desc} {e}; {{0}::ranged.{s:default}.damage} {...}]" cat=Strikes
|
|
37
|
+
```
|
|
38
|
+
```
|
|
39
|
+
sage! macro set name="npc.rstrike" dice="[npc.ranged {0} o={o:xs} f={f:none} d={d:1} m={m:+0} ac=({{1}::ac}{vnpc::{c:+0}}) v={v:+0} s={s:default} e='vs {{1}::name}{anpc::{c:+0}}' {...}]" cat=Strikes
|
|
40
|
+
```
|
|
41
|
+
### Saves
|
|
42
|
+
```
|
|
43
|
+
sage! macro set name="npc.fort" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::fortitude} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Fortitude Save {...}]" cat=Saves
|
|
44
|
+
```
|
|
45
|
+
```
|
|
46
|
+
sage! macro set name="npc.ref" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::reflex} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Reflex Save {...}]" cat=Saves
|
|
47
|
+
```
|
|
48
|
+
```
|
|
49
|
+
sage! macro set name="npc.will" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::will} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Will Save {...}]" cat=Saves
|
|
50
|
+
```
|
|
51
|
+
### Initiative
|
|
52
|
+
```
|
|
53
|
+
sage! macro set name="npc.init" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::{s:Perception}} {vnpc::{m:+0}} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Initiative ({s:Perception}) {...}]" cat=Initiative
|
|
54
|
+
```
|
|
55
|
+
### Skills
|
|
56
|
+
```
|
|
57
|
+
sage! macro set name="npc.acrobatics" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::acrobatics} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Acrobatics Check {...}]" cat=Skills
|
|
58
|
+
```
|
|
59
|
+
```
|
|
60
|
+
sage! macro set name="npc.arcana" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::arcana} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Arcana Check {...}]" cat=Skills
|
|
61
|
+
```
|
|
62
|
+
```
|
|
63
|
+
sage! macro set name="npc.athletics" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::athletics} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Athletics Check {...}]" cat=Skills
|
|
64
|
+
```
|
|
65
|
+
```
|
|
66
|
+
sage! macro set name="npc.crafting" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::crafting} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Crafting Check {...}]" cat=Skills
|
|
67
|
+
```
|
|
68
|
+
```
|
|
69
|
+
sage! macro set name="npc.deception" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::deception} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Deception Check {...}]" cat=Skills
|
|
70
|
+
```
|
|
71
|
+
```
|
|
72
|
+
sage! macro set name="npc.diplomacy" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::diplomacy} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Diplomacy Check {...}]" cat=Skills
|
|
73
|
+
```
|
|
74
|
+
```
|
|
75
|
+
sage! macro set name="npc.intimidation" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::intimidation} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Intimidation Check {...}]" cat=Skills
|
|
76
|
+
```
|
|
77
|
+
```
|
|
78
|
+
sage! macro set name="npc.medicine" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::medicine} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Medicine Check {...}]" cat=Skills
|
|
79
|
+
```
|
|
80
|
+
```
|
|
81
|
+
sage! macro set name="npc.nature" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::nature} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Nature Check {...}]" cat=Skills
|
|
82
|
+
```
|
|
83
|
+
```
|
|
84
|
+
sage! macro set name="npc.occultism" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::occultism} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Occultism Check {...}]" cat=Skills
|
|
85
|
+
```
|
|
86
|
+
```
|
|
87
|
+
sage! macro set name="npc.perfomance" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::perfomance} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Perfomance Check {...}]" cat=Skills
|
|
88
|
+
```
|
|
89
|
+
```
|
|
90
|
+
sage! macro set name="npc.religion" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::religion} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Religion Check {...}]" cat=Skills
|
|
91
|
+
```
|
|
92
|
+
```
|
|
93
|
+
sage! macro set name="npc.society" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::society} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Society Check {...}]" cat=Skills
|
|
94
|
+
```
|
|
95
|
+
```
|
|
96
|
+
sage! macro set name="npc.stealth" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::stealth} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Stealth Check {...}]" cat=Skills
|
|
97
|
+
```
|
|
98
|
+
```
|
|
99
|
+
sage! macro set name="npc.survival" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::survival} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Survival Check {...}]" cat=Skills
|
|
100
|
+
```
|
|
101
|
+
```
|
|
102
|
+
sage! macro set name="npc.thievery" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::thievery} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Thievery Check {...}]" cat=Skills
|
|
103
|
+
```
|
|
104
|
+
```
|
|
105
|
+
sage! macro set name="npc.perception" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::perception} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} Perception Check {...}]" cat=Skills
|
|
106
|
+
```
|
|
107
|
+
```
|
|
108
|
+
sage! macro set name="npc.skill" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::{1}} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} {1} Check {...}]" cat=Skills
|
|
109
|
+
```
|
|
110
|
+
```
|
|
111
|
+
sage! macro set name="npc.lore" dice="[npc.fp o={o:xs} f={f:none} {d:1}d20+{{0}::lore.{1}} {vnpc::{m:+0}} {dc} {v:+0} {{0}::name}:{mnpc::{m:+0}}{dicename::{d:1}} {{0}::lore.{1}.name} Lore Check {...}]" cat=Skills
|
|
112
|
+
```
|
|
113
|
+
### Actions
|
|
114
|
+
```
|
|
115
|
+
sage! macro set name="npc.grapple" dice="[npc.athletics {0} o={o:xs} f={f:none} d={d:1} m={m:+0} dc=({{1}::dc.fortitude}{vnpc::{c:+0}}) v={v:+0} to Grapple {{1}::name}{dnpc::{c:+0}} {...}]" cat=Actions
|
|
116
|
+
```
|
|
117
|
+
```
|
|
118
|
+
sage! macro set name="npc.trip" dice="[npc.athletics {0} o={o:xs} f={f:none} d={d:1} m={m:+0} dc=({{1}::dc.reflex}{vnpc::{c:+0}}) v={v:+0} to Trip {{1}::name}{dnpc::{c:+0}} {...}]" cat=Actions
|
|
119
|
+
```
|
|
120
|
+
```
|
|
121
|
+
sage! macro set name="npc.shove" dice="[npc.athletics {0} o={o:xs} f={f:none} d={d:1} m={m:+0} dc=({{1}::dc.fortitude}{vnpc::{c:+0}}) v={v:+0} to Shove {{1}::name}{dnpc::{c:+0}} {...}]" cat=Actions
|
|
122
|
+
```
|
|
123
|
+
```
|
|
124
|
+
sage! macro set name="npc.disarm" dice="[npc.athletics {0} o={o:xs} f={f:none} d={d:1} m={m:+0} dc=({{1}::dc.reflex}{vnpc::{c:+0}}) v={v:+0} to Disarm {{1}::name}{dnpc::{c:+0}} {...}]" cat=Actions
|
|
125
|
+
```
|
|
126
|
+
```
|
|
127
|
+
sage! macro set name="npc.demoralize" dice="[npc.intimidation {0} o={o:xs} f={f:none} d={d:1} m={m:+0} dc=({{1}::dc.will}{vnpc::{c:+0}}) v={v:+0} to Demoralize {{1}::name}{dnpc::{c:+0}} {...}]" cat=Actions
|
|
128
|
+
```
|
|
129
|
+
```
|
|
130
|
+
sage! macro set name="npc.feint" dice="[npc.deception {0} o={o:xs} f={f:none} d={d:1} m={m:+0} dc=({{1}::dc.perception}{vnpc::{c:+0}}) to Feint vs {{1}::name}{dnpc::{vnpc::{c:+0}}} {...}]" cat=Actions
|
|
131
|
+
```
|
|
132
|
+
```
|
|
133
|
+
sage! macro set name="npc.diversion" dice="[npc.deception {0} o={o:xs} f={f:none} d={d:1} m={m:+0} to Create a Diversion {...}]" cat=Actions
|
|
134
|
+
```
|
|
135
|
+
```
|
|
136
|
+
sage! macro set name="npc.escape" dice="[npc.skill {0} {s:Acrobatics} o={o:xs} f={f:none} d={d:1} m={m:+0} dc=({{1}::dc.athletics}{vnpc::{c:+0}}) v={v:+0} to Escape from {{1}::name}{dnpc::{c:+0}} {...}]" cat=Actions
|
|
137
|
+
```
|
|
138
|
+
```
|
|
139
|
+
sage! macro set name="npc.recall" dice="[npc.skill {0} {1} o={o:xs} f={f:none} d={d:1} m={m:+0} dc=({{2}::dc.recall.{a:default}}{vnpc::{c:+0}}) v={v:+0} to Recall Knowledge{adj::{a:default}} on {{2}::name}{dnpc::{c:+0}} {...}]" cat=Actions
|
|
140
|
+
```
|
|
141
|
+
```
|
|
142
|
+
sage! macro set name="npc.recall.lore" dice="[npc.lore {0} {1} o={o:xs} f={f:none} d={d:1} m={m:+0} dc=({{2}::dc.recall.{a:default}}{vnpc::{c:+0}}) v={v:+0} to Recall Knowledge{adj::{a:default}} on {{2}::name}{dnpc::{c:+0}} {...}]" cat=Actions
|
|
143
|
+
```
|
package/dist/app.js
ADDED
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.formatHP = exports.formatTable = exports.formatCommand = exports.formatTSV = exports.flatten = exports.parseStatblock = exports.parseJSON = exports.formatJSON = exports.fromatMap = exports.adjustmentMap = exports.diceMap = exports.diceNameMap = exports.valueMap = exports.valueNameMap = exports.flatMap = exports.prediceateMap = exports.stub = void 0;
|
|
7
|
+
const zod_1 = __importDefault(require("zod"));
|
|
8
|
+
const tsv_1 = require("tsv");
|
|
9
|
+
const lodash_1 = require("lodash");
|
|
10
|
+
const dedent_js_1 = __importDefault(require("dedent-js"));
|
|
11
|
+
const abbreviate_1 = __importDefault(require("abbreviate"));
|
|
12
|
+
const pluralize_1 = __importDefault(require("pluralize"));
|
|
13
|
+
const schema = zod_1.default.object({
|
|
14
|
+
name: zod_1.default.string(),
|
|
15
|
+
alias: zod_1.default.string().optional(),
|
|
16
|
+
level: zod_1.default.coerce.number().default(0),
|
|
17
|
+
maxhp: zod_1.default.coerce.number().default(0),
|
|
18
|
+
attributes: zod_1.default.object({
|
|
19
|
+
strength: zod_1.default.coerce.number().default(0),
|
|
20
|
+
dexterity: zod_1.default.coerce.number().default(0),
|
|
21
|
+
constitution: zod_1.default.coerce.number().default(0),
|
|
22
|
+
intelligence: zod_1.default.coerce.number().default(0),
|
|
23
|
+
wisdom: zod_1.default.coerce.number().default(0),
|
|
24
|
+
charisma: zod_1.default.coerce.number().default(0),
|
|
25
|
+
}).default({}),
|
|
26
|
+
saves: zod_1.default.object({
|
|
27
|
+
fortitude: zod_1.default.coerce.number().default(0),
|
|
28
|
+
reflex: zod_1.default.coerce.number().default(0),
|
|
29
|
+
will: zod_1.default.coerce.number().default(0),
|
|
30
|
+
}).default({}),
|
|
31
|
+
ac: zod_1.default.coerce.number().default(10),
|
|
32
|
+
perception: zod_1.default.coerce.number().default(0),
|
|
33
|
+
skills: zod_1.default.object({
|
|
34
|
+
acrobatics: zod_1.default.coerce.number().optional(),
|
|
35
|
+
arcana: zod_1.default.coerce.number().optional(),
|
|
36
|
+
athletics: zod_1.default.coerce.number().optional(),
|
|
37
|
+
crafting: zod_1.default.coerce.number().optional(),
|
|
38
|
+
deception: zod_1.default.coerce.number().optional(),
|
|
39
|
+
diplomacy: zod_1.default.coerce.number().optional(),
|
|
40
|
+
intimidation: zod_1.default.coerce.number().optional(),
|
|
41
|
+
medicine: zod_1.default.coerce.number().optional(),
|
|
42
|
+
nature: zod_1.default.coerce.number().optional(),
|
|
43
|
+
occultism: zod_1.default.coerce.number().optional(),
|
|
44
|
+
perfomance: zod_1.default.coerce.number().optional(),
|
|
45
|
+
religion: zod_1.default.coerce.number().optional(),
|
|
46
|
+
society: zod_1.default.coerce.number().optional(),
|
|
47
|
+
stealth: zod_1.default.coerce.number().optional(),
|
|
48
|
+
survival: zod_1.default.coerce.number().optional(),
|
|
49
|
+
thievery: zod_1.default.coerce.number().optional(),
|
|
50
|
+
}).default({}),
|
|
51
|
+
lores: zod_1.default.record(zod_1.default.string(), zod_1.default.object({
|
|
52
|
+
mod: zod_1.default.coerce.number().default(0),
|
|
53
|
+
name: zod_1.default.string(),
|
|
54
|
+
})).default({}),
|
|
55
|
+
melee: zod_1.default.record(zod_1.default.string(), zod_1.default.object({
|
|
56
|
+
mod: zod_1.default.coerce.number().default(0),
|
|
57
|
+
desc: zod_1.default.string(),
|
|
58
|
+
damage: zod_1.default.string(),
|
|
59
|
+
})).default({}),
|
|
60
|
+
ranged: zod_1.default.record(zod_1.default.string(), zod_1.default.object({
|
|
61
|
+
mod: zod_1.default.coerce.number().default(0),
|
|
62
|
+
desc: zod_1.default.string(),
|
|
63
|
+
damage: zod_1.default.string(),
|
|
64
|
+
})).default({}),
|
|
65
|
+
spells: zod_1.default.object({
|
|
66
|
+
attack: zod_1.default.coerce.number().optional(),
|
|
67
|
+
dc: zod_1.default.coerce.number().optional(),
|
|
68
|
+
}).default({}),
|
|
69
|
+
extra: zod_1.default.record(zod_1.default.string(), zod_1.default.coerce.number()).default({}),
|
|
70
|
+
extraDCs: zod_1.default.record(zod_1.default.string(), zod_1.default.coerce.number()).default({}),
|
|
71
|
+
extraDice: zod_1.default.record(zod_1.default.string(), zod_1.default.coerce.string()).default({}),
|
|
72
|
+
improvisation: zod_1.default.boolean().default(false),
|
|
73
|
+
});
|
|
74
|
+
exports.stub = {
|
|
75
|
+
name: 'name',
|
|
76
|
+
alias: 'nm',
|
|
77
|
+
level: 0,
|
|
78
|
+
maxhp: 0,
|
|
79
|
+
attributes: {
|
|
80
|
+
strength: 0,
|
|
81
|
+
dexterity: 0,
|
|
82
|
+
constitution: 0,
|
|
83
|
+
intelligence: 0,
|
|
84
|
+
wisdom: 0,
|
|
85
|
+
charisma: 0,
|
|
86
|
+
},
|
|
87
|
+
saves: {
|
|
88
|
+
fortitude: 0,
|
|
89
|
+
reflex: 0,
|
|
90
|
+
will: 0,
|
|
91
|
+
},
|
|
92
|
+
ac: 10,
|
|
93
|
+
perception: 0,
|
|
94
|
+
skills: {
|
|
95
|
+
acrobatics: 0,
|
|
96
|
+
arcana: 0,
|
|
97
|
+
athletics: 0,
|
|
98
|
+
crafting: 0,
|
|
99
|
+
deception: 0,
|
|
100
|
+
diplomacy: 0,
|
|
101
|
+
intimidation: 0,
|
|
102
|
+
medicine: 0,
|
|
103
|
+
nature: 0,
|
|
104
|
+
occultism: 0,
|
|
105
|
+
perfomance: 0,
|
|
106
|
+
religion: 0,
|
|
107
|
+
society: 0,
|
|
108
|
+
stealth: 0,
|
|
109
|
+
survival: 0,
|
|
110
|
+
thievery: 0,
|
|
111
|
+
},
|
|
112
|
+
lores: {},
|
|
113
|
+
melee: {
|
|
114
|
+
fist: { mod: 7, desc: 'fist (agile, finesse)', damage: '1d4 bludgeoning' }
|
|
115
|
+
},
|
|
116
|
+
ranged: {},
|
|
117
|
+
spells: {},
|
|
118
|
+
extra: {},
|
|
119
|
+
extraDCs: {},
|
|
120
|
+
extraDice: {},
|
|
121
|
+
improvisation: false,
|
|
122
|
+
};
|
|
123
|
+
const formatMap = {
|
|
124
|
+
xxs: 'xxs',
|
|
125
|
+
xs: 'xs',
|
|
126
|
+
s: 's',
|
|
127
|
+
m: 'm',
|
|
128
|
+
l: 'l',
|
|
129
|
+
xl: 'xl',
|
|
130
|
+
xxl: 'xxl',
|
|
131
|
+
};
|
|
132
|
+
exports.prediceateMap = Object.assign(Object.assign({}, ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20].map((v) => ([`${v}`, `d20 >= ${v} flat;`])).reduce((p, [k, v]) => { p[k] = v; return p; }, {}))), { c: 'd20 >= 5 flat;', concealed: 'd20 >= 5 flat;', h: 'd20 >= 11 flat;', hidden: 'd20 >= 11 flat;', none: '' });
|
|
133
|
+
exports.flatMap = Object.entries(exports.prediceateMap).flatMap(([k, v]) => Object.entries(formatMap).map(([fk, fv]) => ([`${fk}_${k}`, `${fv} ${v}`]))).reduce((p, [k, v]) => { p[k] = v; return p; }, {});
|
|
134
|
+
const valueNameMap = (tag) => (Object.assign(Object.assign(Object.assign(Object.assign({}, ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20].map((v) => ([`+${v}`, tag ? ` ⟮+${v} ${tag}⟯` : ` ⟮+${v}⟯`])).reduce((p, [k, v]) => { p[k] = v; return p; }, {}))), ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20].map((v) => ([`${v}`, tag ? ` ⟮+${v} ${tag}⟯` : ` ⟮+${v}⟯`])).reduce((p, [k, v]) => { p[k] = v; return p; }, {}))), ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20].map((v) => ([`-${v}`, tag ? ` ⟮-${v} ${tag}⟯` : ` ⟮-${v}⟯`])).reduce((p, [k, v]) => { p[k] = v; return p; }, {}))), { '+0': '', '0': '' }));
|
|
135
|
+
exports.valueNameMap = valueNameMap;
|
|
136
|
+
const valueMap = () => (Object.assign(Object.assign(Object.assign(Object.assign({}, ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20].map((v) => ([`+${v}`, `+${v}`])).reduce((p, [k, v]) => { p[k] = v; return p; }, {}))), ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20].map((v) => ([`${v}`, `+${v}`])).reduce((p, [k, v]) => { p[k] = v; return p; }, {}))), ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20].map((v) => ([`-${v}`, `-${v}`])).reduce((p, [k, v]) => { p[k] = v; return p; }, {}))), { '+0': '+0', '0': '+0' }));
|
|
137
|
+
exports.valueMap = valueMap;
|
|
138
|
+
const diceNameMap = () => (Object.assign(Object.assign({}, ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20].map((v) => ([`(${v})`, ` ⟮take ${v}⟯`])).reduce((p, [k, v]) => { p[k] = v; return p; }, {}))), { '1': '', '+1': '', '-1': '', '2': ' ⟮fortune⟯', '+2': ' ⟮fortune⟯', '-2': ' ⟮misfortune⟯', 'a': ' ⟮fortune⟯', 'adv': ' ⟮fortune⟯', 'advantage': ' ⟮fortune⟯', 'd': ' ⟮misfortune⟯', 'dis': ' ⟮misfortune⟯', 'disadvantage': ' ⟮misfortune⟯', 'f': ' ⟮fortune⟯', 'for': ' ⟮fortune⟯', 'fortune': ' ⟮fortune⟯', 'm': ' ⟮misfortune⟯', 'mis': ' ⟮misfortune⟯', 'misfortune': ' ⟮misfortune⟯' }));
|
|
139
|
+
exports.diceNameMap = diceNameMap;
|
|
140
|
+
const diceMap = () => (Object.assign(Object.assign({}, ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20].map((v) => ([`(${v})`, `(${v})`])).reduce((p, [k, v]) => { p[k] = v; return p; }, {}))), { '1': '1', '+1': '1', '-1': '1', '2': '+2', '+2': '+2', '-2': '-2', 'a': '+2', 'adv': '+2', 'advantage': '+2', 'd': '-2', 'dis': '-2', 'disadvantage': '-2', 'f': '+2', 'for': '+2', 'fortune': '+2', 'm': '-2', 'mis': '-2', 'misfortune': '-2' }));
|
|
141
|
+
exports.diceMap = diceMap;
|
|
142
|
+
const adjustmentMap = () => ({
|
|
143
|
+
'incredibly-easy': ' ⟮Incredibly Easy⟯',
|
|
144
|
+
'very-easy': ' ⟮Very Easy⟯',
|
|
145
|
+
'easy': ' ⟮Easy⟯',
|
|
146
|
+
'default': '',
|
|
147
|
+
'hard': ' ⟮Hard⟯',
|
|
148
|
+
'very-hard': ' ⟮Very Easy⟯',
|
|
149
|
+
'incredibly-hard': ' ⟮Incredibly Hard⟯',
|
|
150
|
+
});
|
|
151
|
+
exports.adjustmentMap = adjustmentMap;
|
|
152
|
+
const fromatMap = (name, map) => {
|
|
153
|
+
return tsv_1.TSV.stringify([Object.assign({ name }, map)]);
|
|
154
|
+
};
|
|
155
|
+
exports.fromatMap = fromatMap;
|
|
156
|
+
const dcByLevel = [13, 14, 15, 16, 18, 19, 20, 22, 23, 24, 26, 27, 28, 30, 31, 32, 34, 35, 36, 38, 39, 40, 42, 44, 46, 48, 50];
|
|
157
|
+
const formatJSON = (stats) => JSON.stringify(stats, undefined, 2);
|
|
158
|
+
exports.formatJSON = formatJSON;
|
|
159
|
+
const parseJSON = (json) => schema.parse(JSON.parse(json));
|
|
160
|
+
exports.parseJSON = parseJSON;
|
|
161
|
+
const locateName = (statblock) => {
|
|
162
|
+
const regex = /^([^()]+?)(\s+\(\d+\))?\s+\S+\s+(-?\d+)$/m;
|
|
163
|
+
const match = statblock.match(regex);
|
|
164
|
+
if (match && match[1] && match[3]) {
|
|
165
|
+
return { name: (0, pluralize_1.default)((0, lodash_1.startCase)((0, lodash_1.toLower)(match[1].replace(/\s+/, ' ').trim())), 1), level: parseInt(match[3]) };
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
};
|
|
169
|
+
const locateInt = (name, statblock, section = null, signed = true, alias) => {
|
|
170
|
+
const match = statblock.match(new RegExp(`${section ? `(${section}|,)\\s+` : '()'}${alias !== null && alias !== void 0 ? alias : (0, lodash_1.capitalize)(name)}\\s+(${signed ? '[+-]' : '-?'}\\d+)`));
|
|
171
|
+
if (match && match[2]) {
|
|
172
|
+
return { [name]: parseInt(match[2]) };
|
|
173
|
+
}
|
|
174
|
+
return null;
|
|
175
|
+
};
|
|
176
|
+
const locateInts = (statblock, section, alias, signed = true) => {
|
|
177
|
+
const regex = new RegExp(`(${section}|,)([^,]*?)${alias}\\s+(${signed ? '[+-]' : '-?'}\\d+)`, 'g');
|
|
178
|
+
let matches = null;
|
|
179
|
+
const output = [];
|
|
180
|
+
// eslint-disable-next-line no-cond-assign
|
|
181
|
+
while (matches = regex.exec(statblock)) {
|
|
182
|
+
const [, , name, mod] = matches;
|
|
183
|
+
if (name && mod) {
|
|
184
|
+
output.push([
|
|
185
|
+
name.toLowerCase().trim().replace(/\s+/g, '-'),
|
|
186
|
+
name.trim(),
|
|
187
|
+
parseInt(mod),
|
|
188
|
+
]);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return output.reduce((p, [key, name, value]) => { p[key] = { mod: value, name: name }; return p; }, {});
|
|
192
|
+
};
|
|
193
|
+
const locateIntsAfter = (statblock, alias, signed = true) => {
|
|
194
|
+
const regex = new RegExp(`${alias}([\\s\\S]*?)(${signed ? '[+-]' : '-?'}\\d+)`, 'g');
|
|
195
|
+
let matches = null;
|
|
196
|
+
const output = [];
|
|
197
|
+
// eslint-disable-next-line no-cond-assign
|
|
198
|
+
while (matches = regex.exec(statblock)) {
|
|
199
|
+
const [, name, mod] = matches;
|
|
200
|
+
if (name && mod) {
|
|
201
|
+
output.push([
|
|
202
|
+
name.toLowerCase().trim().replace(/\s+/g, '-'),
|
|
203
|
+
name.trim(),
|
|
204
|
+
parseInt(mod),
|
|
205
|
+
]);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return output.reduce((p, [key, name, value]) => { p[key] = { mod: value, name: name }; return p; }, {});
|
|
209
|
+
};
|
|
210
|
+
const locateStrikes = (statblock, alias) => {
|
|
211
|
+
const regex = new RegExp(`${alias}(\\s+\\[.+\\])?\\s+(.+?)\\s+(\\(x\\d+\\)\\s+)?([+-]\\d+)\\s*([\\S\\s]*?),\\s+(Damage|Effect)\\s+(\\S+\\s+\\S+.*?)(?=$|\\s+Melee|\\s+Ranged)`, 'gm');
|
|
212
|
+
let matches = null;
|
|
213
|
+
const output = [];
|
|
214
|
+
// eslint-disable-next-line no-cond-assign
|
|
215
|
+
while (matches = regex.exec(statblock)) {
|
|
216
|
+
const [, , name, , attack, traits, , dice] = matches;
|
|
217
|
+
if (name && attack && dice) {
|
|
218
|
+
const _name = name.toLowerCase()
|
|
219
|
+
.replace(/\s+/g, ' ')
|
|
220
|
+
.replace(/\+\d/g, '')
|
|
221
|
+
.replace(/Weapon\s+Striking(\s+\((Greater|Major)\))?/gi, '')
|
|
222
|
+
.replace(/\(Agile\)/gi, '')
|
|
223
|
+
.replace(/\(\+\)/gi, '')
|
|
224
|
+
.trim();
|
|
225
|
+
const bps = /(?<=[^\w']|^)[BbPpSs](?=[^\w]|$)/g;
|
|
226
|
+
let _traits = traits && traits.toLowerCase()
|
|
227
|
+
.replace(/\s+/g, ' ')
|
|
228
|
+
.replace(bps, (m) => m.toUpperCase())
|
|
229
|
+
.replace(/1d/, 'd')
|
|
230
|
+
.trim();
|
|
231
|
+
const _dice = dice
|
|
232
|
+
.replace(/\s+/g, ' ')
|
|
233
|
+
.replace(bps, (m) => { var _a; return ((_a = { b: 'bludgeoning', p: 'piercing', s: 'slashing' }[m.toLowerCase()]) !== null && _a !== void 0 ? _a : m); })
|
|
234
|
+
.trim();
|
|
235
|
+
const twoHand = _traits.match(/(two-hand|two-handed)\s+(d\d+)/);
|
|
236
|
+
if (twoHand && twoHand[2]) {
|
|
237
|
+
_traits = _traits.replace(/(two-hand|two-handed)\s+d\d+/g, 'two-hand');
|
|
238
|
+
const dice2h = _dice.replace(/(?<=\d)d\d+/, twoHand[2]);
|
|
239
|
+
output.push([
|
|
240
|
+
_name.replace(/\s+/g, '-') + '-2h',
|
|
241
|
+
parseInt(attack),
|
|
242
|
+
`2h ${_traits ? `${_name} ${_traits}` : _name}`,
|
|
243
|
+
dice2h,
|
|
244
|
+
], [
|
|
245
|
+
_name.replace(/\s+/g, '-') + '-1h',
|
|
246
|
+
parseInt(attack),
|
|
247
|
+
`1h ${_traits ? `${_name} ${_traits}` : _name}`,
|
|
248
|
+
_dice,
|
|
249
|
+
]);
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
output.push([
|
|
253
|
+
_name.replace(/\s+/g, '-'),
|
|
254
|
+
parseInt(attack),
|
|
255
|
+
_traits ? `${_name} ${_traits}` : _name,
|
|
256
|
+
_dice,
|
|
257
|
+
]);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return output.reduce((p, [key, m, t, d]) => {
|
|
262
|
+
p[key] = {
|
|
263
|
+
mod: m,
|
|
264
|
+
desc: t,
|
|
265
|
+
damage: d,
|
|
266
|
+
};
|
|
267
|
+
return p;
|
|
268
|
+
}, {});
|
|
269
|
+
};
|
|
270
|
+
const locateSpells = (statblock) => {
|
|
271
|
+
const match = statblock.match(new RegExp(/Spells\s+DC\s+(\d+)(,\s+[Aa]ttack\s+([+-]\d+))?/));
|
|
272
|
+
if (match && match[1]) {
|
|
273
|
+
return Object.assign({ dc: parseInt(match[1]) }, (match[3] ? { attack: parseInt(match[3]) } : null));
|
|
274
|
+
}
|
|
275
|
+
return null;
|
|
276
|
+
};
|
|
277
|
+
const parseStatblock = (name, _statblock, alias) => {
|
|
278
|
+
var _a;
|
|
279
|
+
const defaults = schema.parse({ name: name !== null && name !== void 0 ? name : 'Unknown' });
|
|
280
|
+
const statblock = _statblock
|
|
281
|
+
.replace(/^Items.*$/m, '')
|
|
282
|
+
.replace(/–/g, '-') + '\n';
|
|
283
|
+
const improvisation = !!statblock.match(/Untrained\s+Improvisation/);
|
|
284
|
+
const basic = locateName(statblock);
|
|
285
|
+
return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, defaults), basic), (name && { name: name })), { alias: alias !== null && alias !== void 0 ? alias : (0, abbreviate_1.default)((_a = name !== null && name !== void 0 ? name : basic === null || basic === void 0 ? void 0 : basic.name) !== null && _a !== void 0 ? _a : defaults.name, { length: 3 }).toLowerCase() }), locateInt('perception', statblock)), locateInt('ac', statblock, null, false, 'AC')), locateInt('maxhp', statblock, null, false, 'HP')), { attributes: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, defaults.attributes), locateInt('strength', statblock, null, true, 'Str')), locateInt('dexterity', statblock, null, true, 'Dex')), locateInt('constitution', statblock, null, true, 'Con')), locateInt('intelligence', statblock, null, true, 'Int')), locateInt('wisdom', statblock, null, true, 'Wis')), locateInt('charisma', statblock, null, true, 'Cha')), saves: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, defaults.saves), locateInt('fortitude', statblock, null, true, 'Fortitude')), locateInt('reflex', statblock, null, true, 'Reflex')), locateInt('fortitude', statblock, null, true, 'Fort')), locateInt('reflex', statblock, null, true, 'Ref')), locateInt('will', statblock, null, true, 'Will')), skills: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, defaults.skills), locateInt('acrobatics', statblock, 'Skills')), locateInt('arcana', statblock, 'Skills')), locateInt('athletics', statblock, 'Skills')), locateInt('crafting', statblock, 'Skills')), locateInt('deception', statblock, 'Skills')), locateInt('diplomacy', statblock, 'Skills')), locateInt('intimidation', statblock, 'Skills')), locateInt('medicine', statblock, 'Skills')), locateInt('nature', statblock, 'Skills')), locateInt('occultism', statblock, 'Skills')), locateInt('perfomance', statblock, 'Skills')), locateInt('religion', statblock, 'Skills')), locateInt('society', statblock, 'Skills')), locateInt('stealth', statblock, 'Skills')), locateInt('survival', statblock, 'Skills')), locateInt('thievery', statblock, 'Skills')), lores: Object.assign(Object.assign({}, locateInts(statblock, 'Skills', 'Lore')), locateIntsAfter(statblock, 'Lore:')), melee: Object.assign({}, locateStrikes(statblock, 'Melee')), ranged: Object.assign({}, locateStrikes(statblock, 'Ranged')), spells: Object.assign({}, locateSpells(statblock)), extra: {}, extraDCs: Object.assign({}, locateInt('stealth', statblock, null, false, 'Stealth DC')), extraDice: {}, improvisation });
|
|
286
|
+
};
|
|
287
|
+
exports.parseStatblock = parseStatblock;
|
|
288
|
+
const dc2DC = (secret) => ([key, value]) => [`dc.${key}`, secret ? `||${value}||` : `${value}`];
|
|
289
|
+
const mod2DC = (secret) => ([key, value]) => [`dc.${key}`, secret ? `||${10 + value}||` : `${10 + value}`];
|
|
290
|
+
const toLore = ([key, value]) => [[`lore.${key}`, value.mod], [`lore.${key}.name`, value.name]];
|
|
291
|
+
const toMelee = ([key, value]) => [
|
|
292
|
+
[`melee.${key}`, value.mod],
|
|
293
|
+
[`melee.${key}.desc`, value.desc],
|
|
294
|
+
[`melee.${key}.damage`, value.damage],
|
|
295
|
+
];
|
|
296
|
+
const toRanged = ([key, value]) => [
|
|
297
|
+
[`ranged.${key}`, value.mod],
|
|
298
|
+
[`ranged.${key}.desc`, value.desc],
|
|
299
|
+
[`ranged.${key}.damage`, value.damage],
|
|
300
|
+
];
|
|
301
|
+
const recallDCs = (level, secret) => ((value) => [
|
|
302
|
+
['dc.recall.incredibly-easy', secret ? `||${value - 10}||` : `${value - 10}`],
|
|
303
|
+
['dc.recall.very-easy', secret ? `||${value - 5}||` : `${value - 5}`],
|
|
304
|
+
['dc.recall.easy', secret ? `||${value - 2}||` : `${value - 2}`],
|
|
305
|
+
['dc.recall.default', secret ? `||${value}||` : `${value}`],
|
|
306
|
+
['dc.recall', secret ? `||${value}||` : `${value}`],
|
|
307
|
+
['dc.recall.hard', secret ? `||${value + 2}||` : `${value + 2}`],
|
|
308
|
+
['dc.recall.very-hard', secret ? `||${value + 5}||` : `${value + 5}`],
|
|
309
|
+
['dc.recall.incredibly-hard', secret ? `||${value + 10}||` : `${value + 10}`],
|
|
310
|
+
])(dcByLevel[Math.max(Math.min(level + 1, dcByLevel.length - 1), 0)]);
|
|
311
|
+
const flatten = (stats, secretDC = false, defaultSkills = false, recallDC = false, desc) => {
|
|
312
|
+
const untrained = stats.improvisation ? (stats.level >= 7 ? stats.level : stats.level >= 5 ? stats.level - 1 : stats.level - 2) : 0;
|
|
313
|
+
const skills = defaultSkills ? Object.assign({ acrobatics: untrained + stats.attributes.dexterity, arcana: untrained + stats.attributes.intelligence, athletics: untrained + stats.attributes.strength, crafting: untrained + stats.attributes.intelligence, deception: untrained + stats.attributes.charisma, diplomacy: untrained + stats.attributes.charisma, intimidation: untrained + stats.attributes.charisma, medicine: untrained + stats.attributes.wisdom, nature: untrained + stats.attributes.wisdom, occultism: untrained + stats.attributes.intelligence, perfomance: untrained + stats.attributes.charisma, religion: untrained + stats.attributes.wisdom, society: untrained + stats.attributes.intelligence, stealth: untrained + stats.attributes.dexterity, survival: untrained + stats.attributes.wisdom, thievery: untrained + stats.attributes.dexterity }, stats.skills) : stats.skills;
|
|
314
|
+
let melee = (0, lodash_1.entries)(stats.melee);
|
|
315
|
+
if (melee.length > 0) {
|
|
316
|
+
melee = [
|
|
317
|
+
['default', melee[0][1]],
|
|
318
|
+
...melee,
|
|
319
|
+
];
|
|
320
|
+
}
|
|
321
|
+
let ranged = (0, lodash_1.entries)(stats.ranged);
|
|
322
|
+
if (ranged.length > 0) {
|
|
323
|
+
ranged = [
|
|
324
|
+
['default', ranged[0][1]],
|
|
325
|
+
...ranged,
|
|
326
|
+
];
|
|
327
|
+
}
|
|
328
|
+
return [
|
|
329
|
+
['name', stats.name],
|
|
330
|
+
...(stats.alias ? [['alias', stats.alias]] : []),
|
|
331
|
+
['gamesystem', 'pf2e'],
|
|
332
|
+
['level', stats.level],
|
|
333
|
+
['lvl', stats.level],
|
|
334
|
+
['maxhp', stats.maxhp],
|
|
335
|
+
...(0, lodash_1.entries)(stats.attributes),
|
|
336
|
+
...(0, lodash_1.entries)(stats.attributes).map(([key, value]) => [key.substring(0, 3), value]),
|
|
337
|
+
['ac', secretDC ? `||${stats.ac}||` : stats.ac],
|
|
338
|
+
...(0, lodash_1.entries)(stats.saves),
|
|
339
|
+
['fort', stats.saves.fortitude],
|
|
340
|
+
['ref', stats.saves.reflex],
|
|
341
|
+
['perception', stats.perception],
|
|
342
|
+
...(0, lodash_1.entries)(skills),
|
|
343
|
+
...(0, lodash_1.entries)(stats.lores).flatMap(toLore),
|
|
344
|
+
...(desc ? [
|
|
345
|
+
...(0, lodash_1.entries)(stats.saves).map(([key]) => [`${key}.desc`, `${(0, lodash_1.capitalize)(key)} Save`]),
|
|
346
|
+
['fort.desc', 'Fortitude Save'],
|
|
347
|
+
['ref.desc', 'Reflex Save'],
|
|
348
|
+
['perception.desc', 'Perception Check'],
|
|
349
|
+
...(0, lodash_1.entries)(skills).map(([key]) => [`${key}.desc`, `${(0, lodash_1.capitalize)(key)} Check`]),
|
|
350
|
+
...(0, lodash_1.entries)(stats.lores).map(([key, value]) => [`lore.${key}.desc`, `${value.name} Lore Check`]),
|
|
351
|
+
...(stats.spells.attack ? [['spells.desc', 'Spell Attack']] : []),
|
|
352
|
+
] : []),
|
|
353
|
+
...melee.flatMap(toMelee),
|
|
354
|
+
...ranged.flatMap(toRanged),
|
|
355
|
+
...(0, lodash_1.entries)(stats.extra),
|
|
356
|
+
...(stats.spells.attack ? [['spells', stats.spells.attack]] : []),
|
|
357
|
+
...(stats.spells.dc ? [dc2DC(secretDC)(['spells', stats.spells.dc])] : []),
|
|
358
|
+
...(0, lodash_1.entries)(stats.extraDCs).map(dc2DC(secretDC)),
|
|
359
|
+
...(0, lodash_1.entries)(stats.extraDice),
|
|
360
|
+
...(secretDC ? [
|
|
361
|
+
...(0, lodash_1.entries)(stats.saves).map(mod2DC(true)),
|
|
362
|
+
mod2DC(true)(['perception', stats.perception]),
|
|
363
|
+
mod2DC(true)(['fort', stats.saves.fortitude]),
|
|
364
|
+
mod2DC(true)(['ref', stats.saves.reflex]),
|
|
365
|
+
...(0, lodash_1.entries)(skills).map(mod2DC(true)),
|
|
366
|
+
...(0, lodash_1.entries)(stats.extra).map(mod2DC(true)),
|
|
367
|
+
] : []),
|
|
368
|
+
...(recallDC ? [
|
|
369
|
+
...recallDCs(stats.level, secretDC),
|
|
370
|
+
] : []),
|
|
371
|
+
].reduce((p, [key, value]) => { p[key] = value; return p; }, {});
|
|
372
|
+
};
|
|
373
|
+
exports.flatten = flatten;
|
|
374
|
+
const formatTSV = (stats, secretDC = false, defaultSkills = false, recallDC = false, desc = false) => (tsv_1.TSV.stringify([(0, exports.flatten)(stats, secretDC, defaultSkills, recallDC, desc)]));
|
|
375
|
+
exports.formatTSV = formatTSV;
|
|
376
|
+
const formatCommand = (stats, secretDC = false, defaultSkills = false, recallDC = false, desc = false) => (Object.entries((0, exports.flatten)(stats, secretDC, defaultSkills, recallDC, desc)).map(([k, v]) => `${k}="${v}"`).join(' '));
|
|
377
|
+
exports.formatCommand = formatCommand;
|
|
378
|
+
const formatTable = (table, season, scenario, _name, gm, players) => {
|
|
379
|
+
const name = _name.replace(/[\s-_]/g, ' ').replace(/[^a-zA-Z0-9 ]/g, '');
|
|
380
|
+
const gameName = `PF2 T${table} S${season} ${String(scenario).padStart(2, '0')} ${name}`;
|
|
381
|
+
const tableName = `pf2-t${table}-s${season}${String(scenario).padStart(2, '0')}-${(0, lodash_1.kebabCase)(name)}`;
|
|
382
|
+
return (0, dedent_js_1.default) `
|
|
383
|
+
\`\`\`
|
|
384
|
+
@TableBot create "${gameName}" --gm ${gm} --players ${players} --table-name ${tableName} --ooc-table-name ooc-${tableName} --category Game Tables
|
|
385
|
+
\`\`\`
|
|
386
|
+
\`\`\`
|
|
387
|
+
sage! game create name="${gameName}" gameSystem="pf2e" ic=" #${tableName} " ooc=" #ooc-${tableName} " gms=" ${gm} " players=" @${gameName} " dialogPost="post" diceSecret="gm" diceCrit="timestwo" diceOutput=M gmCharName="Хронист" diceSecret="gm"
|
|
388
|
+
\`\`\`
|
|
389
|
+
`;
|
|
390
|
+
};
|
|
391
|
+
exports.formatTable = formatTable;
|
|
392
|
+
const _formatHP = (hp, maxhp) => {
|
|
393
|
+
const base32 = Math.ceil(hp * 32 / maxhp);
|
|
394
|
+
const slabs = Math.floor(base32 / 8);
|
|
395
|
+
const tail = base32 % 8;
|
|
396
|
+
const tails = [' ', '▏', '▎', '▍', '▌', '▋', '▊', '▉'];
|
|
397
|
+
return `▕${new Array(slabs).fill(0).map(() => '█').join('')}${[tails[tail], ...new Array(3).fill(0).map(() => ' ')].slice(0, 4 - slabs).join('')}▏`;
|
|
398
|
+
};
|
|
399
|
+
const formatHP = (arg) => {
|
|
400
|
+
const match = arg.match(/^(m)?(\d+)\/(\d+)$/);
|
|
401
|
+
if (!match) {
|
|
402
|
+
throw new Error('No match');
|
|
403
|
+
}
|
|
404
|
+
const negative = !!match[1];
|
|
405
|
+
const hp = parseInt(match[2]);
|
|
406
|
+
const maxhp = parseInt(match[3]);
|
|
407
|
+
return _formatHP(negative ? maxhp - hp : hp, maxhp);
|
|
408
|
+
};
|
|
409
|
+
exports.formatHP = formatHP;
|