forked from derekjones562/5e-spelljammer.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbestiary.js
132 lines (127 loc) · 5.58 KB
/
bestiary.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
const fs = require('fs');
let contents = [];
let check = true; // check the content instead of generating the full JSON
let brief = false; // display the "spellcasting" JSON
let fileInclude = "bestiary-"; // default to all bestiary files
const args = process.argv.slice(2); // omit the first two arguments (node and the path to this script)
let usage = [];
for (let i = 0; i < args.length; i++) {
if (args[i] === "--brief") {
brief = true;
} else if (args[i] === "--generate") {
check = false;
} else if (args[i] === "-F") {
fileInclude += args[i + 1];
}
}
if (!check) brief = false; // if we're generating the full JSON then do not also display "spellcasting" too
function recursiveCheck (file) {
if (file.includes(fileInclude)) checkFile(file);
else if (fs.lstatSync(file).isDirectory()) {
fs.readdirSync(file).forEach(nxt => {
recursiveCheck(`${file}/${nxt}`)
})
}
}
function checkFile (file) {
// if (check) console.log(file);
usage = [];
count = 0;
contents = JSON.parse(fs.readFileSync(file, 'utf8'));
for (let i = 0; i < contents.monster.length; i++) {
let monster = contents.monster[i];
let name = monster.name;
if (monster.trait) {
traitJSON = JSON.stringify(monster.trait);
if (traitJSON.indexOf("cast") !== -1) console.log(`${file}: ${name} has cast in trait`);
if (traitJSON.indexOf("spell") !== -1) console.log(`${file}: ${name} has spell in trait`);
}
if (monster.action) {
traitJSON = JSON.stringify(monster.action);
if (traitJSON.indexOf("cast") !== -1) console.log(`${file}: ${name} has cast in action`);
if (traitJSON.indexOf("spell") !== -1) console.log(`${file}: ${name} has spell in action`);
}
if (monster.reaction) {
traitJSON = JSON.stringify(monster.reaction);
if (traitJSON.indexOf("cast") !== -1) console.log(`${file}: ${name} has cast in reaction`);
if (traitJSON.indexOf("spell") !== -1) console.log(`${file}: ${name} has spell in reaction`);
}
if (monster.legendary) {
traitJSON = JSON.stringify(monster.legendary);
if (traitJSON.indexOf("cast") !== -1) console.log(`${file}: ${name} has cast in legendary`);
if (traitJSON.indexOf("spell") !== -1) console.log(`${file}: ${name} has spell in legendary`);
}
// if (monster.trait) for (let j = 0; j < monster.trait.length; j++) if (monster.trait[j].attack) count++;
// if (monster.action) for (let j = 0; j < monster.action.length; j++) if (monster.action[j].attack) count++;
// if (monster.reaction) for (let j = 0; j < monster.reaction.length; j++) if (monster.reaction[j].attack) count++;
// if (monster.trait) for (let j = 0; j < monster.trait.length; j++) if (monster.trait[j].text) parseAttack(name, monster.trait[j].text);
// if (monster.action) for (let j = 0; j < monster.action.length; j++) if (monster.action[j].text) parseAttack(name, monster.action[j].text);
// if (monster.reaction) for (let j = 0; j < monster.reaction.length; j++) if (monster.reaction[j].text) parseAttack(name, monster.reaction[j].text);
}
if (count) console.log(file, count);
// if (check) console.log(JSON.stringify(usage.sort(), null, 2));
}
function parseAttack (name, text) {
for (let i = 0; i < text.length; i++) {
var actiontext = text[i];
var action_desc = actiontext; // required for later reduction of information dump.
// attack parsing
if (actiontext.indexOf(" Attack:") > -1) {
var attacktype = "";
var attacktype2 = "";
if (actiontext.indexOf(" Weapon Attack:") > -1) {
attacktype = actiontext.split(" Weapon Attack:")[0];
attacktype2 = " Weapon Attack:";
} else if (actiontext.indexOf(" Spell Attack:") > -1) {
attacktype = actiontext.split(" Spell Attack:")[0];
attacktype2 = " Spell Attack:";
}
var attackrange = "";
var rangetype = "";
if (attacktype.indexOf("Melee") > -1) {
attackrange = (actiontext.match(/reach (.*?),/) || ["", ""])[1];
rangetype = "Reach";
} else {
attackrange = (actiontext.match(/range (.*?),/) || ["", ""])[1];
rangetype = "Range";
}
var tohit = (actiontext.match(/\+(.*) to hit/) || ["", ""])[1];
var damage = "";
var damagetype = "";
var damage2 = "";
var damagetype2 = "";
var onhit = "";
damageregex = /\d+ \((\d+d\d+\s?(?:\+|-)?\s?\d*)\) (\S+ )?damage/g;
damagesearches = damageregex.exec(actiontext);
if (damagesearches) {
onhit = damagesearches[0];
damage = damagesearches[1];
damagetype = (damagesearches[2] != null) ? damagesearches[2].trim() : "";
damagesearches = damageregex.exec(actiontext);
if (damagesearches) {
onhit += " plus " + damagesearches[0];
damage2 = damagesearches[1];
damagetype2 = (damagesearches[2] != null) ? damagesearches[2].trim() : "";
}
}
onhit = onhit.trim();
var attacktarget = (actiontext.match(/\.,(?!.*\.,)(.*)\. Hit:/) || ["", ""])[1];
// Cut the information dump in the description
var atk_desc_simple_regex = /Hit: \d+ \((\d+d\d+\s?(?:\+|-)?\s?\d*)\) (\S+ )?damage\.(.*)/g;
var atk_desc_complex_regex = /(Hit:.*)/g;
// is it a simple attack (just 1 damage type)?
var match_simple_atk = atk_desc_simple_regex.exec(actiontext);
if (match_simple_atk != null) {
// if yes, then only display special effects, if any
action_desc = match_simple_atk[3].trim();
} else {
// if not, simply cut everything before "Hit:" so there are no details lost.
var match_compl_atk = atk_desc_complex_regex.exec(actiontext);
if (match_compl_atk != null) action_desc = match_compl_atk[1].trim();
}
var tohitrange = "+" + tohit + ", " + rangetype + " " + attackrange + ", " + attacktarget + ".";
if (usage.indexOf(onhit) === -1) usage.push(onhit);
}
}
}
recursiveCheck("./data/bestiary");