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 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;