Skip to content

Commit 253fb4a

Browse files
committed
Handle stuff in the compendium static class stuff
1 parent 533a024 commit 253fb4a

File tree

2 files changed

+132
-112
lines changed

2 files changed

+132
-112
lines changed

index.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ <h2 class="title">Spell Compendium</h2>
4141
<div id="left_school_tags" class="tagselect"></div>
4242
<div style="font-weight: bold; width:100%; text-align:center">TAGS</div>
4343
<div id="left_regular_tags" class="tagselect"></div>
44+
<div style="font-weight: bold; width:100%; text-align:center">FORBIDDEN</div>
45+
<div id="left_forbidden_tags" class="tagselect"></div>
4446
</div>
4547
<div id="compendium_center" style="width:900px">
4648
<div class="tierselect">
@@ -55,7 +57,7 @@ <h2 class="title">Spell Compendium</h2>
5557
<button value="0" class="selector" id="tier9">Tier 9</button>
5658
</div>
5759
<div style="height:80vh; overflow:auto;">
58-
<table>
60+
<table class="spelltable">
5961
<tbody id="spelltable">
6062
<tr style="font-weight: bold;">
6163
<td>Name</td>

src/spell_compendium.js

Lines changed: 129 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,122 +1,186 @@
11
class SpellCompendium {
2-
static ftag_desc(functional_tags, tag) {
3-
return functional_tags[
4-
Object.keys(functional_tags).find(f_tag => tag.includes(f_tag))
2+
static UI = {
3+
LeftDiv: document.getElementById('compendium_left'),
4+
RightDiv: document.getElementById('compendium_right'),
5+
SchoolList: document.getElementById('left_school_tags'),
6+
TagList: document.getElementById('left_regular_tags'),
7+
ForbiddenList: document.getElementById('left_forbidden_tags'),
8+
};
9+
10+
static TagDescriptions = {
11+
Functional: {
12+
Cantrip: 'When cast, this spell is treated as a tier 1 spell in all regards, including MP cost.',
13+
Concentration: 'You need to concentrate on this spell. Taking damage forces you to make a Constitution saving throw against DC 10 or half the damage done, whichever is higher. On a failure, the spell ends. When you cast a spell with Concentration while you are concentrating on a different spell, the first spell ends. You lose concentration if you are at 0 hit points.',
14+
Delayed: 'You can pay for this spell\'s AP cost over multiple turns. While you have at least 1 AP set towards the spell, you are concentrating on the spell.',
15+
Forbidden: 'You can\'t learn this spell normally. You need a general talent that automatically unlocks these spells for you once taken.',
16+
Mastery: 'If you have all the tags for this spell, reduce the MP cost of the spell by two tiers.',
17+
Potent: 'You can cast this spell at a higher tier for an increased effect.',
18+
Sign: 'This spell creates a field around you that does not move. It ends if you leave the field or cast another Sign spell.',
19+
Ritual: 'This spell takes too much time to cast during combat.',
20+
Silent: 'You do not need to speak to cast this spell.',
21+
Still: 'You do not need to move to cast this spell.',
22+
Deprecated: 'This spell is considered for removal. Please do not select this spell during playtesting.',
23+
},
24+
School: {
25+
Conjuration: '',
26+
Evocation: '',
27+
Transmutation: '',
28+
Necromancy: '',
29+
Abjuration: '',
30+
Enchantment: '',
31+
Illusion: '',
32+
Divination: '',
33+
Forbidden: '',
34+
}
35+
};
36+
37+
static TagCounts = {
38+
Regular: {},
39+
Functional: {},
40+
School: {},
41+
Forbidden: {},
42+
};
43+
static {
44+
SpellDatabase.forEach( (spell) => {
45+
spell.tags.forEach( (tag) => {
46+
if (tag.includes('Forbidden')) {
47+
SpellCompendium.TagCounts.Forbidden[tag] ??= 0;
48+
SpellCompendium.TagCounts.Forbidden[tag] ++;
49+
} else if (tag in SpellCompendium.TagDescriptions.Functional) {
50+
SpellCompendium.TagCounts.Functional[tag] ??= 0;
51+
SpellCompendium.TagCounts.Functional[tag] ++;
52+
} else if (tag in SpellCompendium.TagDescriptions.School) {
53+
SpellCompendium.TagCounts.School[tag] ??= 0;
54+
SpellCompendium.TagCounts.School[tag] ++;
55+
} else {
56+
SpellCompendium.TagCounts.Regular[tag] ??= 0;
57+
SpellCompendium.TagCounts.Regular[tag] ++;
58+
}
59+
})
60+
});
61+
}
62+
63+
static tagSelection = new Set();
64+
static tierSelection = new Set();
65+
66+
static tagDescription(tag) {
67+
return SpellCompendium.TagDescriptions.Functional[
68+
Object.keys(SpellCompendium.TagDescriptions.Functional).find(fTag => tag.includes(fTag))
569
];
670
}
771

872
// Generate full-sized spell description
9-
static spellCard(spellData, functional_tags) {
73+
static spellCard(spell) {
1074
const card = document.createElement('table');
1175
const cardBody = card.appendChild(document.createElement('tbody'));
1276
card.className = 'spell';
13-
77+
1478
const spellName = cardBody.appendChild(document.createElement('tr')).appendChild(document.createElement('td'));
1579
spellName.className = 'spellname';
1680
spellName.colSpan = 2;
17-
spellName.innerHTML = spellData.name;
18-
19-
if (spellData.author) {
81+
spellName.innerHTML = spell.name;
82+
83+
if (spell.author) {
2084
const author = cardBody.appendChild(document.createElement('tr')).appendChild(document.createElement('td'));
2185
author.className = 'spelltier';
2286
author.colSpan = 2;
23-
author.innerHTML = `by ${spellData.author}`;
87+
author.innerHTML = `by ${spell.author}`;
2488
}
25-
89+
2690
const tier = cardBody.appendChild(document.createElement('tr')).appendChild(document.createElement('td'));
2791
tier.className = 'spelltier';
2892
tier.colSpan = 2;
29-
tier.innerHTML = `Tier ${spellData.tier}`;
30-
93+
tier.innerHTML = `Tier ${spell.tier}`;
94+
3195
const tagsRow = cardBody.appendChild(document.createElement('tr'));
3296
const tagsH = tagsRow.appendChild(document.createElement('td'));
3397
const tagsD = tagsRow.appendChild(document.createElement('td'));
3498
tagsH.className = 'spellheaders';
3599
tagsD.className = 'spelltags';
36100
tagsH.textContent = 'Tags:';
37-
tagsD.innerHTML = spellData.tags
38-
.map(tag => Object.keys(functional_tags).some(f_tag => tag.includes(f_tag)) ? `<span class='fTag' title='${SpellCompendium.ftag_desc(functional_tags, tag)}'>${tag}</span>` : tag)
101+
tagsD.innerHTML = spell.tags
102+
.map(tag => Object.keys(SpellCompendium.TagDescriptions.Functional).some(fTag => tag.includes(fTag)) ? `<span class='fTag' title='${SpellCompendium.tagDescription(tag)}'>${tag}</span>` : tag)
39103
.join(', ')
40104
;
41-
105+
42106
const costRow = cardBody.appendChild(document.createElement('tr'));
43107
const costH = costRow.appendChild(document.createElement('td'));
44108
const costD = costRow.appendChild(document.createElement('td'));
45109
costH.className = 'spellheaders';
46110
costD.className = 'spelldata';
47111
costH.textContent = 'Cost:';
48-
costD.innerHTML = spellData.cost;
49-
112+
costD.innerHTML = spell.cost;
113+
50114
const rangeRow = cardBody.appendChild(document.createElement('tr'));
51115
const rangeH = rangeRow.appendChild(document.createElement('td'));
52116
const rangeD = rangeRow.appendChild(document.createElement('td'));
53117
rangeH.className = 'spellheaders';
54118
rangeD.className = 'spelldata';
55119
rangeH.textContent = 'Range:';
56-
rangeD.innerHTML = spellData.range;
57-
120+
rangeD.innerHTML = spell.range;
121+
58122
const durationRow = cardBody.appendChild(document.createElement('tr'));
59123
const durationH = durationRow.appendChild(document.createElement('td'));
60124
const durationD = durationRow.appendChild(document.createElement('td'));
61125
durationH.className = 'spellheaders';
62126
durationD.className = 'spelldata';
63127
durationH.textContent = 'Duration:';
64-
durationD.innerHTML = spellData.duration;
65-
128+
durationD.innerHTML = spell.duration;
129+
66130
const desc = cardBody.appendChild(document.createElement('tr')).appendChild(document.createElement('td'));
67131
desc.colSpan = 2;
68-
desc.innerHTML = spellData.desc;
69-
70-
if (spellData.empower) {
132+
desc.innerHTML = spell.desc;
133+
134+
if (spell.empower) {
71135
const empowerRow = cardBody.appendChild(document.createElement('tr'));
72136
const empowerH = empowerRow.appendChild(document.createElement('td'));
73137
const empowerD = empowerRow.appendChild(document.createElement('td'));
74138
empowerH.className = 'spellheaders';
75139
empowerD.className = 'spelldesc';
76140
empowerH.textContent = 'Empower:';
77-
empowerD.innerHTML = spellData.empower;
141+
empowerD.innerHTML = spell.empower;
78142
}
79-
143+
80144
return card;
81145
}
82146

83147
// Generate spell table entry
84-
static spellBrief(spellData, functional_tags) {
148+
static spellBrief(spell) {
85149
const brief = document.createElement('tr');
86-
brief.id = `spell_${spellData.name.replaceAll(' ', '_')}`;
87-
150+
brief.id = `spell_${spell.name.replaceAll(' ', '_')}`;
151+
88152
[
89-
spellData.name,
90-
spellData.tier,
91-
spellData.range,
92-
spellData.duration,
93-
spellData.tags
94-
.map(tag => Object.keys(functional_tags).some(f_tag => tag.includes(f_tag)) ? `<span class='fTag' title='${SpellCompendium.ftag_desc(functional_tags, tag)}'>${tag}</span>` : tag)
153+
spell.name,
154+
spell.tier,
155+
spell.range,
156+
spell.duration,
157+
spell.tags
158+
.map(tag => Object.keys(SpellCompendium.TagDescriptions.Functional).some(fTag => tag.includes(fTag)) ? `<span class='fTag' title='${SpellCompendium.tagDescription(tag)}'>${tag}</span>` : tag)
95159
.join(', ')
96160
].forEach(data => {
97161
const td = brief.appendChild(document.createElement('td'));
98162
td.className = 'spelldata';
99163
td.innerHTML = data;
100164
});
101-
165+
102166
brief.onclick = function() {
103-
const card = SpellCompendium.spellCard(spellData, functional_tags);
167+
const card = SpellCompendium.spellCard(spell, SpellCompendium.TagDescriptions.Functional);
104168
const compendiumRight = document.getElementById('compendium_right');
105169
compendiumRight.replaceChild(card, compendiumRight.firstElementChild);
106170
};
107-
171+
108172
return brief;
109173
}
110174

111175
// Generate spell table
112-
static generate_brief_spell_table(SpellDatabase, tag_select, tier_select, functional_tags) {
176+
static generateSpellTable() {
113177
const oldTable = document.querySelector('#spelltable');
114178
const newTable = oldTable.cloneNode(false);
115179

116180
SpellDatabase.forEach(spell => {
117-
if (tag_select.size > 0 && !spell.tags.some(tag => tag_select.has(tag))) return;
118-
if (tier_select.size > 0 && !tier_select.has(spell.tier)) return;
119-
newTable.appendChild(SpellCompendium.spellBrief(spell, functional_tags));
181+
if (SpellCompendium.tagSelection.size > 0 && !spell.tags.some(tag => SpellCompendium.tagSelection.has(tag))) return;
182+
if (SpellCompendium.tierSelection.size > 0 && !SpellCompendium.tierSelection.has(spell.tier)) return;
183+
newTable.appendChild(SpellCompendium.spellBrief(spell, SpellCompendium.TagDescriptions.Functional));
120184
});
121185

122186
oldTable.parentNode.replaceChild(newTable, oldTable);
@@ -137,11 +201,11 @@ class SpellCompendium {
137201
} else {
138202
confirm("No spell has been selected!");
139203
}
140-
204+
141205
}
142206

143-
static tag_buttons(tag_list, tag_set, container, render_callback) {
144-
Object.entries(tag_list).sort((a, b) => {
207+
static tagButtons(tags, container) {
208+
Object.entries(tags).sort((a, b) => {
145209
if (a[1] == b[1]) {
146210
return (a[0] == b[0]) ? 0 : (a[0] > b[0]) ? 1 : -1;
147211
} else {
@@ -151,7 +215,7 @@ class SpellCompendium {
151215
const div = container.appendChild(document.createElement('button'));
152216
const img = div.appendChild(document.createElement('img'));
153217
const text = div.appendChild(document.createElement('div'));
154-
218+
155219
img.width = 14;
156220
img.style.paddingRight = '2px';
157221

@@ -168,94 +232,48 @@ class SpellCompendium {
168232
switch (S) {
169233
case 0:
170234
div.value = S+1;
171-
tag_set.add(tag);
235+
SpellCompendium.tagSelection.add(tag);
172236
break;
173237
case 1:
174238
div.value = 0;
175-
tag_set.delete(tag);
239+
SpellCompendium.tagSelection.delete(tag);
176240
break;
177241
}
178-
render_callback();
242+
SpellCompendium.generateSpellTable();
179243
}
180244
});
181245
}
182246

183247
static render() {
184-
const compendiumLeft = document.getElementById('compendium_left');
185-
const compendiumRight = document.getElementById('compendium_right');
186-
const compendiumSchoolList = document.getElementById('left_school_tags');
187-
const compendiumTagList = document.getElementById('left_regular_tags');
188-
189-
const tag_list = {};
190-
const functional_tag_list = {};
191-
const school_tag_list = {};
192-
193-
const functional_tags = {
194-
Cantrip: 'When cast, this spell is treated as a tier 1 spell in all regards, including MP cost.',
195-
Concentration: 'You need to concentrate on this spell. Taking damage forces you to make a Constitution saving throw against DC 10 or half the damage done, whichever is higher. On a failure, the spell ends. When you cast a spell with Concentration while you are concentrating on a different spell, the first spell ends. You lose concentration if you are at 0 hit points.',
196-
Delayed: 'You can pay for this spell&apos;s AP cost over multiple turns. While you have at least 1 AP set towards the spell, you are concentrating on the spell.',
197-
Forbidden: 'You can&apos;t learn this spell normally. You need a general talent that automatically unlocks these spells for you once taken.',
198-
Mastery: 'If you have all the tags for this spell, reduce the MP cost of the spell by two tiers.',
199-
Potent: 'You can cast this spell at a higher tier for an increased effect.',
200-
Sign: 'This spell creates a field around you that does not move. It ends if you leave the field or cast another Sign spell.',
201-
Ritual: 'This spell takes too much time to cast during combat.',
202-
Silent: 'You do not need to speak to cast this spell.',
203-
Still: 'You do not need to move to cast this spell.',
204-
Deprecated: 'This spell is considered for removal. Please do not select this spell during playtesting.',
205-
};
206-
const school_tags = ['Conjuration', 'Evocation', 'Transmutation', 'Necromancy', 'Abjuration', 'Enchantment', 'Illusion', 'Divination', 'Forbidden'];
207-
208-
SpellDatabase.forEach(spell =>
209-
spell.tags.forEach(tag => {
210-
if (tag.includes('Forbidden')) {
211-
if (!tag_list[tag]) tag_list[tag] = 1;
212-
else tag_list[tag] += 1;
213-
} else if (Object.keys(functional_tags).includes(tag)) {
214-
if (!functional_tag_list[tag]) functional_tag_list[tag] = 1;
215-
else functional_tag_list[tag] += 1;
216-
} else if (school_tags.includes(tag)) {
217-
if (!school_tag_list[tag]) school_tag_list[tag] = 1;
218-
else school_tag_list[tag] += 1;
219-
} else {
220-
if (!tag_list[tag]) tag_list[tag] = 1;
221-
else tag_list[tag] += 1;
222-
}
223-
})
224-
);
225-
226-
const tag_select = new Set();
227-
const tier_select = new Set();
228-
const gen_spelltable = () => SpellCompendium.generate_brief_spell_table(SpellDatabase, tag_select, tier_select, functional_tags);
229-
230248
// TAGS
231-
SpellCompendium.tag_buttons(school_tag_list, tag_select, compendiumSchoolList, gen_spelltable);
232-
SpellCompendium.tag_buttons(tag_list, tag_select, compendiumTagList, gen_spelltable);
233-
249+
SpellCompendium.tagButtons(SpellCompendium.TagCounts.School, SpellCompendium.UI.SchoolList);
250+
SpellCompendium.tagButtons(SpellCompendium.TagCounts.Regular, SpellCompendium.UI.TagList);
251+
234252
// TIERS
235253
for (let i = 1; i <= 9; i++) {
236-
const tier_button = document.querySelector(`#tier${i}`);
237-
tier_button.dataset.i = i;
254+
const tierButton = document.querySelector(`#tier${i}`);
255+
tierButton.dataset.i = i;
238256
const tier = i;
239-
tier_button.onclick = function() {
240-
const S = parseInt(tier_button.value);
257+
tierButton.onclick = function() {
258+
const S = parseInt(tierButton.value);
241259
switch (S) {
242260
case 0:
243-
tier_button.value = S+1;
244-
tier_select.add(tier);
261+
tierButton.value = S+1;
262+
SpellCompendium.tierSelection.add(tier);
245263
break;
246264
case 1:
247-
tier_button.value = 0;
248-
tier_select.delete(tier);
265+
tierButton.value = 0;
266+
SpellCompendium.tierSelection.delete(tier);
249267
break;
250268
}
251-
gen_spelltable();
269+
SpellCompendium.generateSpellTable();
252270
}
253271
}
254272

255-
compendiumRight.appendChild(SpellCompendium.spellCard(SpellDatabase[0], functional_tags));
256-
gen_spelltable();
257-
258-
const downloadButton = compendiumRight
273+
SpellCompendium.UI.RightDiv.appendChild(SpellCompendium.spellCard(SpellDatabase[0], SpellCompendium.TagDescriptions.Functional));
274+
SpellCompendium.generateSpellTable();
275+
276+
const downloadButton = SpellCompendium.UI.RightDiv
259277
.appendChild(document.createElement('center'))
260278
.appendChild(document.createElement('button'));
261279
downloadButton.textContent = "SAVE (.png)";

0 commit comments

Comments
 (0)