-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcharacter_sheet.html
1765 lines (1641 loc) · 112 KB
/
character_sheet.html
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<style>
header {background-color: grey; padding: 15px; font-family: Arial; text-align: center; color: white; height: 250px;}
body {position: relative;}
table {font-family: Arial; text-align: center; font-size: 18px; background-color: gray; float: left;}
th {background-color: gray; color: white;}
tr:nth-child(even) {background-color: white;}
tr:nth-child(odd) {background-color: lightgray;}
ul {font-family: Arial;}
div {float: left; position: relative;}
table#GOD {width: 100%; background-color: white; border: 1px solid white;}
table#Abilities {width: 100%;}
div#Features-and-Traits {width 100%; background-color: grey; border: 1px solid red; font-family: Arial;}
dl#Features-and-Traits {width: 100%; background-color: white;}
table#Skills {width: 100%; left: 0%; border: 1px solid purple;}
.btn {border: none; color: white; padding: 14px 28px; font-size: 16px; cursor: pointer;}
.lightgray {background-color: lightgray;}
.lightgray:hover {background-color: #AAAAAA;}
.switch {position: relative; display: inline-block; width: 60px; height: 34px;}
.switch input {opacity: 0; width: 0; height: 0;}
.slider {position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; -webkit-transition: .4s; transition: .4s;}
.slider:before { position: absolute; content: ""; height: 26px; width: 26px; left: 4px; bottom: 4px; background-color: white; -webkit-transition: .4s; transition: .4s;}
input:checked + .slider { background-color: lightgray;}
input:focus + .slider {box-shadow: 0 0 1px lightgray;}
input:checked + .slider:before {-webkit-transform: translateX(26px); -ms-transform: translateX(26px); transform: translateX(26px);}
.slider.round {border-radius: 34px;}
.slider.round:before {border-radius: 50%;}
</style>
</head>
<body>
<header>
<h1 align=center style="color: white">Character Sheet</h1>
<table>
<tr>
<colgroup><col span="3" width=33%></colgroup>
<th><button class="btn lightgrey" style="border-radius: 34px;" onclick="RollCharacter()">Go</button></th>
<th>
<table>
<tr>
<th>Point Buy Stats</th>
<th><label class="switch"><input type="checkbox" id="RollCheck"><span class="slider round"></span></label></th>
<th>Roll for Stats</th>
</tr>
</table>
</th>
<th>
<table>
<tr>
<th>Random Character</th>
<th><label class="switch"><input type="checkbox" id="SmartDumb"><span class="slider round"></span></label></th>
<th>Smart Character</th>
</tr>
</table>
</th>
</tr>
</table>
<table width=100% style="border: 1px solid white">
<col width=35%> <col width=20%> <col width=20%> <col width=5%> <col width=20%>
<tr style="font-size: 20px"> <th>Name</th> <th>Race</th> <th>Class</th> <th>Level</th> <th>Background</th> </tr>
<tr style="background-color: white; font-size: 20px; color: black"> <td id="Name"></td> <td id="Race"></td> <td id="Class"></td> <td>1</td> <td id="Background"></td> </tr>
</table>
</header>
<div style="width: 100%">
<p> </p>
</div>
<!-- <table id="GOD">
<col width=25%>
<col width=50%>
<col Width=25%>
<tr style="background-color: white;">
<td> -->
<figure width=20%>
<table id="Abilities">
<colgroup><col span="3" width=33%></colgroup>
<tr> <th>Ability</th> <th>Score</th> <th>Modifier</th> </tr>
<tr> <td>STR</td> <td id="STR"></td> <td id="STRm"></td> </tr>
<tr> <td>DEX</td> <td id="DEX"></td> <td id="DEXm"></td> </tr>
<tr> <td>CON</td> <td id="CON"></td> <td id="CONm"></td> </tr>
<tr> <td>INT</td> <td id="INT"></td> <td id="INTm"></td> </tr>
<tr> <td>WIS</td> <td id="WIS"></td> <td id="WISm"></td> </tr>
<tr> <td>CHA</td> <td id="CHA"></td> <td id="CHAm"></td> </tr>
</table>
</figure>
<!-- </td> -->
<!-- <td> -->
<div width="50%" style="background-color: white; border: 1px solid orange;">
<table>
<tr> <th>Height</th> <th>Weight</th> </tr>
<tr> <td id="Height"></td> <td id="Weight"></td> </tr>
<tr> <th>Age</th> <th>Sex</th> </tr>
<tr> <td id="Age"></td> <td id="Sex"></td> </tr>
</table>
<table>
<tr> <th>Max HP</th> </tr>
<tr> <td id="HP"></td> </tr>
<tr> <th>Hit Dice</th> </tr>
<tr> <td id="Hitdice"></td> </tr>
</table>
<table>
<tr> <th>AC</th> <th>Initiative</th> <th>Speed</th> </tr>
<tr> <td></td> <td id="Init"></td> <td id="Speed"></td> </tr>
</table>
</div>
<!-- </td> -->
<!-- <td rowspan="2"> -->
<div id="Features-and-Traits">
<p style="font-family: Arial; font-size: 20px; color: white; background-color: grey; text-align: center"><b>Features and Traits</b></p>
<dl id="Features-and-Traits">
<dt>Test</dt>
<dd>- Filler</dd>
<dt>Tea</dt>
<dd>- Filler</dd>
<dt>Milk</dt>
<dd>- Filler</dd>
</dl>
</div>
<div>
<p style="font-family: Arial; font-size: 20px; color: white; background-color: grey; text-align: center"><b>Languages</b></p>
<ul id="Languages">
<li>Test</li>
<li>Tea</li>
<li>Milk</li>
</ul>
</div>
<!-- </td>
</tr>
<tr>
<td> -->
<div>
<table id="Skills">
<col width="15%"> <col width="55%"> <col width="15%"> <col width="15%">
<tr> <th>P/E</th> <th colspan="2">Skill</th> <th>Mod</th> </tr>
<tr> <td id=Acrobatics></td> <td>Acrobatics</td> <td>(DEX)</td> <td id=AcrobaticsF></td> </tr>
<tr> <td id="Animal Handling"></td> <td>Animal Handling</td> <td>(WIS)</td> <td id="Animal HandlingF"></td> </tr>
<tr> <td id=Arcana></td> <td>Arcana</td> <td>(INT)</td> <td id=ArcanaF></td> </tr>
<tr> <td id=Athletics></td> <td>Athletics</td> <td>(STR)</td> <td id=AthleticsF></td> </tr>
<tr> <td id=Deception></td> <td>Deception</td> <td>(CHA)</td> <td id=DeceptionF></td> </tr>
<tr> <td id=History></td> <td>History</td> <td>(INT)</td> <td id=HistoryF></td> </tr>
<tr> <td id=Insight></td> <td>Insight</td> <td>(WIS)</td> <td id=InsightF></td> </tr>
<tr> <td id=Intimidation></td> <td>Intimidation</td> <td>(CHA)</td> <td id=IntimidationF></td> </tr>
<tr> <td id=Investigation></td> <td>Investigation</td> <td>(INT)</td> <td id=InvestigationF></td> </tr>
<tr> <td id=Medicine></td> <td>Medicine</td> <td>(WIS)</td> <td id=MedicineF></td> </tr>
<tr> <td id=Nature></td> <td>Nature</td> <td>(INT)</td> <td id=NatureF></td> </tr>
<tr> <td id=Perception></td> <td>Perception</td> <td>(WIS)</td> <td id=PerceptionF></td> </tr>
<tr> <td id=Performance></td> <td>Performance</td> <td>(CHA)</td> <td id=PerformanceF></td> </tr>
<tr> <td id=Persuasion></td> <td>Persuasion</td> <td>(CHA)</td> <td id=PersuasionF></td> </tr>
<tr> <td id=Religion></td> <td>Religion</td> <td>(INT)</td> <td id=ReligionF></td> </tr>
<tr> <td id="Sleight of Hand"></td> <td>Sleight of Hand</td> <td>(DEX)</td> <td id="Sleight of HandF"></td> </tr>
<tr> <td id="Stealth"></td> <td>Stealth</td> <td>(DEX)</td> <td id="StealthF"></td> </tr>
<tr> <td id="Survival"></td> <td>Survival</td> <td>(WIS)</td> <td id=SurvivalF></td> </tr>
<tr> <th colspan="4">P: Proficiency - E: Expertise</th> </tr>
</table>
</div>
<div>
<table id="Ability Saving Throws">
<colgroup><col span="3" width=33%></colgroup>
<tr> <th>Ability</th> <th>Save</th> </tr>
<tr> <td>STR</td> <td id="STRs"></td> </tr>
<tr> <td>DEX</td> <td id="DEXs"></td> </tr>
<tr> <td>CON</td> <td id="CONs"></td> </tr>
<tr> <td>INT</td> <td id="INTs"></td> </tr>
<tr> <td>WIS</td> <td id="WISs"></td> </tr>
<tr> <td>CHA</td> <td id="CHAs"></td> </tr>
</table>
</div>
<!-- </td>
</tr>
</table> -->
<script> function RollCharacter(){ try{
//REFERENCE INFORMATION
const Sexes = new Set(["Male", "Female"])
const Races = new Set(["Dwarf", "Elf", "Halfling", "Human", "Dragonborn", "Gnome", "Half-Elf", "Half-Orc", "Tiefling"])
const Subraces = new Map([
["Dwarf", new Set(["Hill", "Mountain"])],
["Elf", new Set(["High", "Wood", "Dark"])],
["Halfling", new Set(["Lightfoot", "Stout"])],
["Human", new Set([""])],
["Dragonborn", new Set(["Black", "Blue", "Brass", "Bronze", "Copper", "Gold", "Green", "Red", "Silver", "White"])],
["Gnome", new Set(["Forest", "Rock"])],
["Half-Elf", new Set([""])],
["Half-Orc", new Set([""])],
["Tiefling", new Set([""])]
])
// Elemental Evil Player's Companion
//"Aarakocra": [""]
//"Genasi": ["Air", "Earth", "Fire", "Water"]
//"Gnome": ["Deep (Svirfneblin)"] DUPLICATE
//"Goliath": [""] DUPLICATE
//Sword Coast Adventurer's Guide
//"Dwarf": ["Grey (Duergar)"]
//"Halfling": ["Ghostwise"]
//"Gnome": ["Deep (Svirfneblin)"] DUPLICATE
// TIEFLING VARIANTS?
//Volo's Guide to Monsters
//"Aasimar": ["Protector", "Scourge", "Fallen"]
//"Firbolg": [""]
//"Goliath": [""] DUPLICATE
//"Kenku": [""]
//"Lizardfolk": [""]
//"Tabaxi": [""]
//"Triton": [""]
//"Bugbear": [""]
//"Goblin": [""]
//"Hobgoblin": [""]
//"Kobold": [""] URD?
//"Orc": [""]
//"Yuan-Ti Pureblood": [""]
// One Grung Above
//"Grung": [""]
//The Tortle Package
//"Tortle": [""]
//NAMES
//DWARF NAMES
const DwarfNameMale = new Set(["Adrik", "Alberich", "Baern", "Barendd", "Beloril", "Brottor", "Dain", "Dalgal", "Darrak", "Delg", "Duergath", "Dworic",
"Eberk", "Einkil", "Elaim", "Erias", "Fallond", "Fargrim", "Gardain", "Gilthur", "Gimgen", "Gimurt", "Harbek", "Kildrak",
"Kilvar", "Morgran", "Morkral", "Nalral", "Nordak", "Nuraval", "Oloric", "Olunt", "Orsik", "Oskar", "Rangrim", "Reirak",
"Rurik", "Taklinn", "Thoradin", "Thorin", "Thradal", "Tordek", "Traubon", "Travok", "Ulfgar", "Uraim", "Veit", "Vonbin",
"Vondal", "Whurbin"])
const DwarfNameFemale = new Set(["Anbera", "Artin", "Audhild", "Balifra", "Barbena", "Bardryn", "Bolhild", "Dagnal", "Dariff", "Delre", "Diesa", "Eldeth",
"Eridred", "Falkrunn", "Fallthra", "Finellen", "Gillydd", "Gunnloda", "Gurdis", "Helgret", "Helja", "Hlin", "Ilde", "Jarana",
"Kathra", "Kilia", "Kristryd", "Liftrasa", "Marastyr", "Mardred", "Morana", "Nalaed", "Nora", "Nurkara", "Oriff", "Ovina",
"Riswynn", "Sannl", "Therlin", "Thodris", "Torbera", "Tordrid", "Torgga", "Urshar", "Valida", "Vistra", "Vonana", "Werydd",
"Whudred", "Yurgunn"])
const DwarfNameClan = new Set(["Aranore", "Balderk", "Battlehammer", "Bigtoe", "Bloodkith", "Bofdann", "Brawnanvil", "Brazzik", "Broodfist", "Burrowfound",
"Caebrek", "Daerdahk", "Dankil", "Daraln", "Deepdelver", "Durthane", "Eversharp", "Fallak", "Fireforge", "Foamtankard",
"Frostbeard", "Glanhig", "Goblinbane", "Goldfinder", "Gorunn", "Greybeard", "Hammerstone", "Helcral", "Holderhek", "Ironfist",
"Loderr", "Lutgehr", "Morigak", "Orcfoe", "Rakankrak", "Ruby-Eye", "Rumnaheim", "Silveraxe", "Silverstone", "Steelfist",
"Stoutale", "Strakeln", "Strongheart", "Thrahak", "Torevir", "Torunn", "Trollbleeder", "Trueanvil", "Trueblood", "Ungart"])
//ELF NAMES
const ElfNameMale = new Set(["Adran", "Aelar", "Ardeth", "Ahvain", "Aramil", "Arannis", "Aust", "Azaki", "Beiro", "Berrian", "Caeldrim", "Carric", "Dayereth",
"Dreali", "Efferil", "Eiravel", "Enialis", "Erdan", "Erevan", "Fivin", "Galinndan", "Gennal", "Hadarai", "Halimath", "Heian",
"Himo", "Immeral", "Ivellios", "Korfel", "Lamlis", "Laucian", "Lucan", "Mindartis", "Naal", "Nutae", "Paelias", "Peren",
"Quarion", "Riardon", "Rolen", "Soveliss", "Suhnae", "Thamior", "Tharivol", "Theren", "Theriatis", "Thervan", "Uthemar",
"Vanuath", "Varis"])
const ElfNameFemale = new Set(["Adrie", "Ahinar", "Althea", "Anastrianna", "Andraste", "Antinua", "Arara", "Baelitae", "Bethrynna", "Birel", "Caelynn", "Chaedi",
"Claira", "Dara", "Drusilia", "Elama", "Enna", "Faral", "Felosial", "Hatae", "Ielenia", "Ilanis", "Irann", "Jarsali", "Jelenneth",
"Keyleth", "Leshanna", "Lia", "Maiathah", "Malquis", "Meriele", "Mialee", "Myathethil", "Naivara", "Quelenna", "Quillathe",
"Ridaro", "Sariel", "Shanairla", "Shava", "Silaqui", "Sumnes", "Theirastra", "Thiala", "Tiaathque", "Traulam", "Vadania",
"Valanthe", "Valna", "Xanaphia"])
const ElfNameChild = new Set(["Ael", "Ang", "Ara", "Ari", "Arn", "Aym", "Broe", "Bryn", "Cael", "Cy", "Dae", "Del", "Eli", "Eryn", "Faen", "Fera", "Gael", "Gar",
"Innil", "Jarsali", "Kan", "Koeth", "Lael", "Lue", "Mai", "Mara", "Mella", "Mya", "Naeris", "Naill", "Nim", "Phann", "Py", "Rael",
"Raer", "Ren", "Rinn", "Rua", "Sael", "Sai", "Sumi", "Syllin", "Ta", "Thia", "Tia", "Traki", "Vall", "Von", "Wil", "Za"])
const ElfNameFamily = new Set(["Aloro", "Amakiir", "Amastacia", "Ariessus", "Arnuanna", "Berevan", "Caerdonel", "Caphaxath", "Casilltenirra", "Cithreth",
"Dalanthan", "Eathalena", "Erenaeth", "Ethanasath", "Fasharash", "Firahel", "Floshem", "Galanodel", "Goltorah", "Hanali",
"Holimion", "Horineth", "Iathrana", "Ilphelkiir", "Iranapha", "Koehlanna", "Lathalas", "Liadon", "Meliamne", "Mellerelel",
"Mystralath", "Naïlo", "Netyoive", "Ofandrus", "Ostoroth", "Othronus", "Qualanthri", "Raethran", "Rothenel", "Selevarun",
"Siannodel", "Suithrasas", "Sylvaranth", "Teinithra", "Tiltathana", "Wasanthi", "Withrethin", "Xiloscient", "Xistsrith",
"Yaeldrin"])
//HALFLING NAMES
const HalflingNameMale = new Set(["Alton", "Ander", "Bernie", "Bobbin", "Cade", "Callus", "Corrin", "Dannad", "Danniel", "Eddie", "Egart", "Eldon", "Errich",
"Fildo", "Finnan", "Franklin", "Garret", "Garth", "Gilbert", "Gob", "Harol", "Igor", "Jasper", "Keith", "Kevin", "Lazam", "Lerry",
"Lindal", "Lyle", "Merric", "Mican", "Milo", "Morrin", "Nebin", "Nevil", "Osborn", "Ostran", "Oswalt", "Perrin", "Poppy", "Reed",
"Roscoe", "Sam", "Shardon", "Tye", "Ulmo", "Wellby", "Wendel", "Wenner", "Wes"])
const HalflingNameFemale = new Set(["Alain", "Andry", "Anne", "Bella", "Blossom", "Bree", "Callie", "Chenna", "Cora", "Dee", "Dell", "Eida", "Eran", "Euphemia",
"Georgina", "Gynnie", "Harriet", "Jasmine", "Jillian", "Jo", "Kithri", "Lavinia", "Lidda", "Maegan", "Marigold", "Merla",
"Myria", "Nedda", "Nikki", "Nora", "Olivia", "Paela", "Pearl", "Pennie", "Philomena", "Portia", "Robbie", "Rose", "Saral",
"Seraphina", "Shaena", "Stacee", "Tawna", "Thea", "Trym", "Tyna", "Vani", "Verna", "Wella", "Willow"])
const HalflingNameFamily = new Set(["Appleblossom", "Bigheart", "Brightmoon", "Brushgather", "Cherrycheeks", "Copperkettle", "Deephollow", "Elderberry", "Fastfoot",
"Fatrabbit", "Glenfellow", "Goldfound", "Goodbarrel", "Goodearth", "Greenbottle", "Greenleaf", "High-Hill", "Hilltopple",
"Hogcollar", "Honeypot", "Jamjar", "Kettlewhistle", "Leagallow", "Littlefoot", "Nimblefingers", "Porridgepot", "Quickstep",
"Reedfellow", "Shadowquick", "Silvereyes", "Smoothhands", "Stonebridge", "Stoutbridge", "Stoutman", "Strongbones", "Sunmeadow",
"Swiftwhistle", "Tallfellow", "Tealeaf", "Tenpenny", "Thistletop", "Thorngage", "Tosscobble", "Underbough", "Underfoot",
"Warmwater", "Whispermouse", "Wildcloak", "Wildheart", "Wiseacre"])
//HUMAN NAMES
const HumanNameMale = new Set(["Aseir", "Bardeid", "Haseid", "Khemed", "Mehmen", "Sudeiman", "Zasheir", "Darvin", "Dorn", "Evendur", "Gorstag", "Grim", "Helm",
"Malark", "Morn", "Randal", "Stedd", "Ander", "Blath", "Bran", "Frath", "Geth", "Lander", "Luth", "Malcer", "Stor", "Taman",
"Urth", "Aoth", "Bareris", "Ephut-Ki", "Kethoth", "Mumed", "Ramas", "So-Kehur", "Thazar-De", "Urhur", "Borivik", "Faurgar",
"Jandar", "Kanithar", "Madislak", "Ralmevik", "Shaumar", "Vladislak", "An", "Chen", "Chi", "Fai", "Jiang", "Jun", "Lian",
"Long", "Meng", "On", "Shan", "Shui", "Wen", "Anton", "Diero", "Marcon", "Pieron", "Rimardo", "Romero", "Slazar", "Umbero"])
const HumanNameFemale = new Set(["Atala", "Ceidil", "Hama", "Jasmal", "Meilil", "Seipora", "Yasheira", "Zasheida", "Arveene", "Esvele", "Jhessail", "Kerri",
"Lureene", "Miri", "Rowan", "Shandri", "Tessele", "Amafrey", "Betha", "Cefrey", "Kethra", "Mara", "Olga", "Silifrey", "Westra",
"Arizima", "Chathi", "Nephis", "Nulara", "Murithi", "Sefris", "Thola", "Umara", "Zolis", "Fyevarra", "Hulmarra", "Immith", "Imzel",
"Navarra", "Shevarra", "Tammith", "Yuldra", "Bai", "Chao", "Jia", "Lei", "Meilil", "Qiao", "Shui", "Tai", "Balama", "Dona", "Faila",
"Jalana", "Luisa", "Marta", "Quara", "Selise", "Vonda"])
const HumanNameFamily = new Set(["Basha", "Dumein", "Jassan", "Khalid", "Mostana", "Pashar", "Rein", "Amblecrown", "Buckman", "Dundragon", "Evenwood", "Greycastle",
"Tallstag", "Brightwood", "Helder", "Hornraven", "Lackman", "Stormwind", "Windrivver", "Ankhalab", "Anskuld", "Fezim", "Hahpet",
"Nathandem", "Sepret", "Uuthrakt", "Chergoba", "Dyernina", "Iltazyara", "Murnyethara", "Stayanoga", "Ulmokina", "Chien", "Huang",
"Kao", "Kung", "Lao", "Ling", "Mei", "Pin", "Shin", "Sum", "Tan", "Wan", "Agosto", "Astorio", "Calabra", "Domine", "Falone",
"Marivaldi", "Pisacar", "Ramondo"])
//DRAGONBORN NAMES
const DragonbornNameMale = new Set(["Adrex", "Arjhan", "Azzakh", "Balasar", "Baradad", "Bharash", "Bidreked", "Dadalan", "Dazzazn", "Direcris", "Donaar", "Fax",
"Gargax", "Ghesh", "Gorbundus", "Greethen", "Heskan", "Hirrathak", "Ildrex", "Kaladan", "Kerkad", "Kiirith", "Kriv", "Maagog",
"Medrash", "Mehen", "Mozikth", "Mreksh", "Mugrunden", "Nadarr", "Nithther", "Norkuuth", "Nykkan", "Pandjed", "Patrin", "Pijjirik",
"Quarethon", "Rathkran", "Rhogar", "Rivaan", "Sethrekar", "Shamash", "Shedinn", "Srorthen", "Tarhun", "Torinn", "Trynnicus",
"Valorean", "Vrondiss", "Zedaar"])
const DragonbornNameFemale = new Set(["Akra", "Aasathra", "Antara", "Arava", "Biri", "Blendaeth", "Burana", "Chassath", "Daar", "Dentratha", "Doudra", "Driindar",
"Eggren", "Farideh", "Findex", "Furrele", "Gesrethe", "Gilkass", "Harann", "Havilar", "Hethress", "Hillanot", "Jaxi", "Jezean",
"Jheri", "Kadana", "Kava", "Korinn", "Megren", "Mijira", "Mishann", "Nala", "Nuthra", "Perra", "Pogranix", "Pyxrin", "Quespa",
"Raiann", "Rezena", "Ruloth", "Saphara", "Savaran", "Sora", "Surina", "Synthrin", "Tatyan", "Thava", "Uadjit", "Vezera", "Zykroff"])
const DragonbornNameClan = new Set(["Akambherylliax", "Argenthrixus", "Baharoosh", "Beryntolthropal", "Bhenkumbryrznaax", "Caavylteradyn", "Chumbyxirinnish",
"Clethtinthiallor", "Daardedrian", "Delmirev", "Dhyrktelonis", "Ebynichtomonis", "Esstyrlynn", "Fharngnarthnost", "Ghaallixirn",
"Grrrmmballhyst", "Gygazzylyshrift", "Hashphronyxadyn", "Hshhsstoroth", "Imbixtellrhyst", "Jerynomonis", "Jharthraxyn", "Kerrhylon",
"Kimbatuul", "Lhamboldennish", "Linxakasendalor", "Mohradyllion", "Mystan", "Nemmonis", "Norixius", "Ophinshtalajiir", "Orexijandilin",
"Pfaphnyrennish", "Phrahdrandon", "Pyraxtallinost", "Qyxpahrgh", "Raghthroknaar", "Shestendeliath", "Skaarzborroosh", "Sumnarghthrysh",
"Tiammanthyllish", "Turnuroth", "Umbyrphrael", "Vangdondalor", "Verthisathurgiesh", "Wivvyrholdalphiax", "Wystongjiir", "Xephyrbahnor",
"Yarjerit", "Zzzxaaxthroth"])
//GNOME NAMES
const GnomeNameMale = new Set(["Alston", "Alvyn", "Anverth", "Arumawann", "Bilbron", "Bodynock", "Brocc", "Burgell", "Cockaby", "Crampernap", "Dabbledob", "Delebean",
"Dimble", "Eberdeb", "Eldon", "Erky", "Fablen", "Fibblestib", "Fonkin", "Frouse", "Frug", "Gerbo", "Gimble", "Glim", "Igden", "Jabble",
"Jebeddo", "Kellen", "Kipper", "Namfoodle", "Oppleby", "Orryn", "Paggen", "Pallabar", "Pog", "Qualen", "Ribbles", "Rimple", "Roondar",
"Sapply", "Seebo", "Senteq", "Sindri", "Umpen", "Warryn", "Wiggens", "Wobbles", "Wrenn", "Zaffrab", "Zook"])
const GnomeNameFemale = new Set(["Abalaba", "Bimpnottin", "Breena", "Buvvie", "Callybon", "Caramip", "Carlin", "Cumpen", "Dalaba", "Donella", "Duvamil", "Ella",
"Ellyjoybell", "Ellywick", "Enidda", "Lilli", "Loopmottin", "Lorilla", "Luthra", "Mardnab", "Meena", "Menny", "Mumpena", "Nissa",
"Numba", "Nyx", "Oda", "Oppah", "Orla", "Panana", "Pyntle", "Quilla", "Ranala", "Reddlepop", "Roywyn", "Salanop", "Shamil", "Siffress",
"Symma", "Tana", "Tenena", "Tervaround", "Tippletoe", "Ulla", "Unvera", "Veloptima", "Virra", "Waywocket", "Yebe", "Zanna"])
const GnomeNameClan = new Set(["Albaratie", "Bafflestone", "Beren", "Boondiggles", "Cobblelob", "Daergel", "Dunben", "Fabblestabble", "Fapplestamp", "Fiddlefen",
"Folkor", "Garrick", "Gimlen", "Glittergem", "Gobblefirn", "Gummen", "Horcusporcus", "Humplebumple", "Ironhide", "Leffery", "Lingenhall",
"Loofollue", "Maekkelferce", "Miggledy", "Munggen", "Murning", "Musgraben", "Nackle", "Ningrel", "Nopenstallen", "Nucklestamp", "Offund",
"Oomtrowl", "Pilwicken", "Pingun", "Quillsharpener", "Raulnor", "Reese", "Rofferton", "Scheppen", "Shadowcloak", "Silverthread", "Sympony",
"Tarkelby", "Timbers", "Turen", "Umbodben", "Waggletop", "Welber", "Wildwander"])
//HALF-ORC NAMES
const HalfOrcNameMale = new Set(["Argran", "Braak", "Brug", "Cagak", "Dench", "Dorn", "Dren", "Druuk", "Feng", "Gell", "Gnarsh", "Grumbar", "Gubrash", "Hagren", "Henk",
"Hogar", "Holg", "Imsh", "Karash", "Karg", "Keth", "Korag", "Krusk", "Lubash", "Megged", "Mhurren", "Mord", "Morg", "Nil", "Nybarg",
"Odorr", "Ohr", "Rendar", "Resh", "Ront", "Rrath", "Sark", "Scrag", "Sheggen", "Shump", "Tanglar", "Tarak", "Thar", "Thokk", "Trag",
"Ugarth", "Varg", "Vilberg", "Yurk", "Zed"])
const HalfOrcNameFemale = new Set(["Arha", "Baggi", "Bendoo", "Bilga", "Brakka", "Creega", "Drenna", "Ekk", "Emen", "Engong", "Fistula", "Gaaki", "Gorga", "Grai",
"Greeba", "Grigi", "Gynk", "Hrathy", "Huru", "Ilga", "Kabbarg", "Kansif", "Lagazi", "Lezre", "Murgen", "Murook", "Myev", "Nagrette",
"Neega", "Nella", "Nogu", "Oolah", "Ootah", "Ovak", "Ownka", "Puyet", "Reeza", "Shautha", "Silgre", "Sutha", "Tagga", "Tawar", "Tomph",
"Ubada", "Vanchu", "Vola", "Volen", "Vorka", "Yevelda", "Zagga"])
//TIEFLING NAMES
const TieflingNameMale = new Set(["Abad", "Ahrim", "Akmen", "Amnon", "Andram", "Astaro", "Balam", "Barakas", "Bathin", "Caim", "Chem", "Cimer", "Cressel", "Damakos",
"Ekemon", "Euron", "Fenriz", "Forcas", "Habor", "Iados", "Kairon", "Leucis", "Mamnen", "Mantus", "Marbas", "Melech", "Merihim", "Modean",
"Mordai", "Moromo", "Morthos", "Nicor", "Nirgel", "Oriax", "Paymon", "Pelaios", "Purson", "Qemuel", "Raam", "Rimmon", "Sammal", "Skamos",
"Tethren", "Thamuz", "Therai", "Valafar", "Vassago", "Xappan", "Zepar", "Zephan"])
const TieflingNameFemale = new Set(["Akta", "Anakis", "Armara", "Astaro", "Aym", "Azza", "Beleth", "Bryseis", "Bune", "Criella", "Damaia", "Decarabia", "Ea", "Gadreel",
"Gomory", "Hecat", "Ishte", "Jezebeth", "Kali", "Kallista", "Kasdeya", "Lerissa", "Lilith", "Makaria", "Manea", "Markosian", "Mastema",
"Naamah", "Nemeia", "Nija", "Orianna", "Osah", "Phelaia", "Prosperine", "Purah", "Pyra", "Rieta", "Ronobe", "Ronwe", "Seddit", "Seere",
"Sekhmet", "Semyaza", "Shava", "Shax", "Sorath", "Uzza", "Vapula", "Vepar", "Verin"])
const TieflingNameVirtue = new Set(["Ambition", "Art", "Carrion", "Chant", "Creed", "Death", "Debauchery", "Despair", "Doom", "Doubt", "Dread", "Ecstasy", "Ennui",
"Entropy", "Excellence", "Fear", "Glory", "Gluttony", "Grief", "Hate", "Hope", "Horror", "Ideal", "Ignominy", "Laughter", "Love",
"Lust", "Mayhem", "Mockery", "Murder", "Muse", "Music", "Mystery", "Nowhere", "Open", "Pain", "Passion", "Poetry", "Quest", "Random",
"Reverence", "Revulsion", "Sorrow", "Temerity", "Torment", "Tragedy", "Vice", "Virtue", "Weary", "Wit"])
const Names = new Map([ ["Dwarf", new Map([["Male", DwarfNameMale],
["Female", DwarfNameFemale],
["Family", DwarfNameClan],
["Alt", new Set()]
])],
["Elf", new Map([["Male", ElfNameMale],
["Female", ElfNameFemale],
["Family", ElfNameFamily],
["Alt", ElfNameChild]
])],
["Halfling", new Map([["Male", HalflingNameMale],
["Female", HalflingNameFemale],
["Family", HalflingNameFamily],
["Alt", new Set()]
])],
["Human", new Map([["Male", HumanNameMale],
["Female", HumanNameFemale],
["Family", HumanNameFamily],
["Alt", new Set()]
])],
["Dragonborn", new Map([["Male", DragonbornNameMale],
["Female", DragonbornNameFemale],
["Family", DragonbornNameClan],
["Alt", new Set()] //nicknames
])],
["Gnome", new Map([["Male", GnomeNameMale],
["Female", GnomeNameFemale],
["Family", GnomeNameClan],
["Alt", new Set()] //nicknames
])],
["Half-Orc", new Map([["Male", HalfOrcNameMale],
["Female", HalfOrcNameFemale],
["Family", new Set()],
["Alt", new Set()]
])],
["Tiefling", new Map([["Male", TieflingNameMale],
["Female", TieflingNameFemale],
["Family", new Set()],
["Alt", TieflingNameVirtue]
])]
])
//SPELLS
BardCantrips = new Set (["Blade Ward", "Dancing Lights", "Friends", "Light", "Mage Hand", "Mending", "Message", "Minor Illusion", "Prestidigitation", "True Strike", "Vicious Mockery"])
BardLevelOne = new Set (["Animal Friendship", "Bane", "Charm Person", "Comprehend Languages", "Cure Wounds ", "Detect Magic", "Disguise Self", "Dissonant Whispers", "Faerie Fire ",
"Feather Fall", "Healing Word", "Heroism", "Identify", "Illusory Script", "Longstrider", "Silent Image", "Sleep ", "Speak with Animals", "Tasha's Hideous Laughter",
"Thunderwave", "Unseen Servant"])
ClericCantrips = new Set (["Guidance", "Light", "Mending", "Resistance", "Sacred Flame", "Spare the Dying ", "Thaumaturgy"])
ClericLevelOne = new Set (["Bane", "Bless", "Command", "Create or Destroy Water", "Cure Wounds", "Detect Evil and Good", "Detect Magic", "Detect Poison and Disease", "Guiding Bolt",
"Healing Word", "Inflict Wounds", "Protection from Evil and Good", "Purify Food and Drink", "Sanctuary", "Shield of Faith"])
KnowledgeLevelOne = new Set (["Command", "Identify"])
LifeLevelOne = new Set (["Bless", "Cure Wounds"])
LightLevelOne = new Set (["Burning Hands", "Faerie Fire"])
NatureLevelOne = new Set (["Animal Friendship", "Speak with Animals"])
TempestLevelOne = new Set (["Fog Cloud", "Thunderwave"])
TrickeryLevelOne = new Set (["Charm Person", "Disguise Self"])
WarLevelOne = new Set (["Divine Favor", "Spiritual Weapon"])
DruidCantrips = new Set (["Druidcraft", "Guidance", "Mending", "Poison Spray", "Produce Flame", "Resistance", "Shillelagh", "Thorn Whip"])
DruidLevelOne = new Set (["Animal Friendship", "Charm Person", "Create or Destroy Water", "Cure Wounds", "Detect Magic", "Detect Poison and Disease", "Entangle", "Faerie Fire",
"Fog Cloud", "Goodberry", "Healing Word", "Jump", "Longstrider", "Purify Food and Drink", "Speak with Animals", "Thunderwave"])
SorcererCantrips = new Set (["Acid Splash", "Blade Ward", "Chill Touch", "Dancing Lights", "Fire Bolt", "Friends", "Light", "Mage Hand", "Mending", "Message", "Minor Illusion",
"Poison Spray", "Prestidigitation", "Ray of Frost", "Shocking Grasp", "True Strike"])
SorcererLevelOne = new Set (["Burning Hands", "Charm Person", "Chromatic Orb", "Color Spray", "Comprehend Languages", "Detect Magic", "Disguise Self", "Expeditious Retreat", "False Life",
"Feather Fall", "Fog Cloud", "Jump", "Mage Armor", "Magic Missile", "Ray of Sickness", "Shield", "Silent Image", "Sleep", "Thunderwave", "Witch Bolt"])
WarlockCantrips = new Set (["Blade Ward", "Chill Touch", "Eldritch Blast", "Friends", "Mage Hand", "Minor Illusion", "Poison Spray", "Prestidigitation", "True Strike"])
WarlockLevelOne = new Set (["Armor of Agathys", "Arms of Hadar", "Charm Person", "Comprehend Languages", "Expeditious Retreat", "Hellish Rebuke", "Hex", "Illusory Script",
"Protection from Evil and Good", "Unseen Servant", "Witch Bolt"])
WizardCantrips = new Set (["Acid Splash", "Blade Ward", "Chill Touch", "Dancing Lights", "Fire Bolt", "Friends", "Light", "Mage Hand", "Mending", "Message", "Minor Illusion",
"Poison Spray", "Prestidigitation", "Ray of Frost", "Shocking Grasp", "True Strike"])
WizardLevelOne = new Set (["Alarm", "Burning Hands", "Charm Person", "Chromatic Orb", "Color Spray", "Comprehend Languages", "Detect Magic", "Disguise Self", "Expeditious Retreat",
"False Life", "Feather Fall", "Find Familiar", "Fog Cloud", "Grease", "Identify", "Illusory Script", "Jump", "Longstrider", "Mage Armor", "Magic Missile",
"Protection from Evil and Good", "Ray of Sickness", "Shield", "Silent Image", "Sleep", "Tasha's Hideous Laughter", "Tenser's Floating Disk", "Thunderwave",
"Unseen Servant", "Witch Bolt"])
//EQUIPMENT
//Weapons, artisan tools, instruments, and gaming sets are below as Maps to track proficiencies
const ArmorLight = new Set (["Padded Armor", "Leather Armor", "Studded Leather Armor"])
const ArmorMedium = new Set (["Hide Armor", "Chain Shirt", "Scale Mail", "Breastplate", "Half Plate"])
const ArmorHeavy = new Set (["Ring Mail", "Chain Mail", "Splint Armor", "Full Plate"])
const ArmorShield = new Set (["Shield"])
const FocusDruidic = new Set (["Sprig Of Mistletoe", "Totem", "Wooden Staff", "Yew Wand"])
const FocusArcane = new Set (["Crystal", "Orb", "Rod", "Staff", "Wand"])
const FocusHolySymbol = new Set (["Amulet", "Emblem", "Reliquary"])
const StuffReal = new Set (["Abacus", "Acid (Vial)", "Alchemist's Fire (Flask)", "Arrows (20)","Blowgun Needles (50)",
"Crossbow Bolts (20)", "Sling Bullets (20)", "Antitoxin (Vial)", "Backpack",
"Ball Bearings (Bag Of 1000)", "Barrel", "Basket", "Bedroll", "Bell", "Blanket",
"Block And Tackle", "Book", "Bottle, Glass", "Bucket", "Caltrops (Bag Of 20)",
"Candle", "Case, Crossbow Bolt", "Case, Map Or Scroll", "Chain (10 Feet)",
"Chalk (1 Piece)", "Chest", "Climber's Kit", "Clothes, Common", "Clothes, Costume",
"Clothes, Fine", "Clothes, Traveler", "Component Pouch", "Crowbar", "Fishing Tackle",
"Flask", "Tankard", "Grappling Hook", "Hammer", "Hammer, Sledge", "Healer's Kit",
"Holy Water (Flask)", "Hourglass", "Hunting Trap", "Ink (1 Ounce Bottle)", "Ink Pen",
"Jug", "Pitcher", "Ladder (10-Foot)", "Lamp", "Lantern, Bullseye",
"Lantern, Hooded", "Lock", "Magnifying Glass", "Manacles", "Mess Kit", "Mirror, Steel",
"Oil (Flask)", "Paper (1 Sheet)","Parchment (1 Sheet)", "Perfume (Vial)",
"Pick, Miner's", "Piton", "Poison, Basic (Vial)", "Pole (10-Foot)", "Pot, Iron",
"Potion Of Healing", "Pouch", "Quiver", "Ram, Portable", "Rations (1 Day)", "Robes",
"Rope, Hempen (50 Feet)", "Rope, Silk (50 Feet)", "Sack", "Scale, Merchant's",
"Sealing Wax", "Shovel", "Signal Whistle", "Signet Ring", "Soap", "Spellbook",
"Spikes, Iron (10)", "Spyglass", "Tent, Two-Person", "Tinderbox", "Torch", "Vial",
"Waterskin (Full)", "Whetstone"])
const StuffFake = new Set (["Book, Prayer", "Incense, Stick", "Bottle Of Colored Liquid", "Weighted Dice",
"Marked Cards", "Fake Duke's Signet Ring", "String (10 Feet)", "Alms Box", "Incense, Block",
"Censer", "Vestments", "Little Bag Of Sand", "Knife, Small", "Book, Lore", "Love Letter",
"Lock Of Hair", "Trinket", "Guild Letter Of Introduction", "Purse", "Scroll Of Pedigree",
"Trophy, Animal", "Trophy, Enemy", "Letter From A Dead Colleague Posing A Question You Have Not Yet Been Able To Answer",
"Insignia Of Rank", "Map, Home City", "Pet, Mouse"])
const Classes = new Set (["Barbarian", "Bard", "Cleric", "Druid", "Fighter", "Monk", "Paladin", "Ranger", "Rogue", "Sorcerer", "Warlock", "Wizard"])
const Backgrounds = new Set (["Acolyte", "Charlatan", "Criminal", "Entertainer", "Folk Hero", "Guild Artisan", "Hermit", "Noble", "Outlander",
"Sage", "Sailor", "Soldier", "Urchin"])
const Skill2Ability = new Map ([["Acrobatics","DEX"], ["Animal Handling","WIS"], ["Arcana","INT"], ["Athletics","STR"], ["Deception","CHA"], ["History","INT"],
["Insight","WIS"], ["Intimidation","CHA"], ["Investigation","INT"], ["Medicine","WIS"], ["Nature","INT"], ["Perception","WIS"],
["Performance","CHA"], ["Persuasion","CHA"], ["Religion","INT"], ["Sleight of Hand","DEX"], ["Stealth","DEX"], ["Survival","WIS"]])
const StandardLanguages = new Set (["Dwarvish", "Elvish", "Giant", "Gnomish", "Goblin", "Halfling", "Orc"])
const ExoticLanguages = new Set (["Abyssal", "Celestial", "Draconic", "Deep Speech", "Infernal", "Primordial", "Sylvan", "Undercommon"])
//CHARACTER INFO
var Name
var Age
var Sex
var Race
var Subrace
var SubraceAltText = ""
var Class
var Subclass = ""
var Background
var AbilityScores = new Map ([["STR",0], ["DEX",0], ["CON",0], ["INT",0], ["WIS",0], ["CHA",0]])
var AbilityMods = new Map ([["STR",0], ["DEX",0], ["CON",0], ["INT",0], ["WIS",0], ["CHA",0]])
var SavingThrows = new Map ([["STR",0], ["DEX",0], ["CON",0], ["INT",0], ["WIS",0], ["CHA",0]])
var Skills = new Map ([["Acrobatics",0], ["Animal Handling",0], ["Arcana",0], ["Athletics",0], ["Deception",0], ["History",0],
["Insight",0], ["Intimidation",0], ["Investigation",0], ["Medicine",0], ["Nature",0], ["Perception",0],
["Performance",0], ["Persuasion",0], ["Religion",0], ["Sleight of Hand",0], ["Stealth",0], ["Survival",0]])
var Resistances = new Map ([["Acid",0], ["Bludgeoning",0], ["Cold",0], ["Fire",0], ["Force",0], ["Lightning",0], ["Necrotic",0],
["Piercing",0], ["Poison",0], ["Psychic",0], ["Radiant",0], ["Slashing",0], ["Thunder",0]])
var ArmorProfs = new Map ([["Light",0], ["Medium",0], ["Heavy",0], ["Shield",0]])
var SimpleMelee = new Map ([["Club",0], ["Dagger",0], ["Greatclub",0], ["Handaxe",0], ["Javelin",0], ["Light Hammer",0], ["Mace",0],
["Quarterstaff",0], ["Sickle",0], ["Spear",0]])
var SimpleRanged = new Map ([["Light Crossbow",0], ["Dart",0], ["Shortbow",0], ["Sling",0]])
var MartialMelee = new Map ([["Battleaxe",0], ["Flail",0], ["Glaive",0], ["Greataxe",0], ["Greatsword",0], ["Halberd",0], ["Lance",0], ["Longsword",0], ["Maul",0],
["Morningstar",0], ["Pike",0], ["Rapier",0], ["Scimitar",0], ["Shortsword",0], ["Trident",0], ["War Pick",0], ["Warhammer",0], ["Whip",0]])
var MartialRanged = new Map ([["Blowgun",0], ["Hand Crossbow",0], ["Heavy Crossbow",0], ["Longbow",0], ["Net",0]])
var ArtisanTools = new Map ([["Alchemist's Supplies",0], ["Brewer's Supplies",0], ["Calligrapher's Supplies",0], ["Carpenter's Tools",0],
["Cartographer's Tools",0], ["Cobbler's Tools",0], ["Cook's Utensils",0], ["Glassblower's Tools",0], ["Jeweler's Tools",0],
["Leatherworker's Tools",0], ["Mason's Tools",0], ["Painter's Supplies",0], ["Potter's Tools",0], ["Smith's Tools",0],
["Tinker's Tools",0], ["Weaver's Tools",0], ["Woodcarver's Tools",0]])
var GamingSets = new Map ([["Dice Set",0], ["Dragonchess Set",0], ["Playing Card Set",0], ["Three-Dragon Ante Set",0]])
var Instruments = new Map ([["Bagpipes",0], ["Drum",0], ["Dulcimer",0], ["Flute",0], ["Lute",0], ["Lyre",0], ["Horn",0], ["Pan Flute",0], ["Shawm",0], ["Viol",0]])
var OtherTools = new Map ([["Navigator's Tools",0], ["Poisoner's Kit",0], ["Thieves' Tools",0], ["Herbalism Kit",0], ["Disguise Kit",0], ["Forgery Kit",0]])
var Vehicles = new Map ([["Land",0], ["Water",0]])
const AllItems = new Set([ ...ArmorLight, ...ArmorMedium, ...ArmorHeavy, ...ArmorShield, ...FocusDruidic, ...FocusArcane, ...FocusHolySymbol, ...StuffReal, ...StuffFake,
...SimpleMelee.keys(), ...SimpleRanged.keys(), ...MartialMelee.keys(), ...MartialRanged.keys(), ...ArtisanTools.keys(), ...GamingSets.keys(),
...Instruments.keys(), ...OtherTools.keys(), ...Vehicles.keys()
])
var Equipment = new Map()
var GP = 0
var Traits = new Set()
var Actives = new Set()
var SpecialSkills = new Set()
var SpecialSavingThrows = new Set()
var BackgroundFeatures = new Set()
var KnownLanguages = new Set(["Common"])
var Speed = 25
var Size = "Medium"
var Height
var Weight
var HP = 0
var Hitdice
//HELPER FUNCTIONS
function setdif(setA, setB){
let dif = new Set(setA)
for (let x of setB) {
dif.delete(x);
}
return dif;
}
function setunion(setA, setB){
let union = new Set(setA)
for (let x of setB){
union.add(x)
}
return union
}
function shuffle(a) {
//Fisher-Yates
a = a.slice()
for (let i=a.length-1; i>0; i--) {
const j = Math.floor(Math.random() * (i+1))
let temp = a[i]
a[i] = a[j]
a[j] = temp
}
return a
}
function ROLL(die_count, die_type) {
let sum = 0
for (let i=0; i<die_count; i++) {
sum += Math.floor(Math.random() * die_type + 1)
}
return sum
}
function CHOOSE(choice_pool, number_items, exceptions){
//Returns *number_items* random items from *choice_pool* as a Set. Samples uniformly without replacement.
//*choice_pool* can be an Array, Set, or Map.
//*exceptions* can be an Array or Set.
//If *number_items* == 1 (or undefined), returns the item itself instead of a singleton Set.
if (number_items === undefined){
//*number_items* is optional
var number_items = 1
}
if (exceptions === undefined){
//*exceptions* is optional
var exceptions = []
}
//If *exceptions* is an Array, turn it into a Set.
exceptions = new Set(exceptions)
//If *choice_pool* is a Map, turn it into an Array.
if (choice_pool instanceof Map){
choice_pool = [...choice_pool.keys()]
}
//Remove exceptions from the choice pool and make sure *choice_pool* is an Array.
choice_pool = [...setdif(choice_pool, exceptions)]
if (choice_pool.length < number_items){
throw new Error("Attempted to choose more items than are in the choice pool minus exceptions.")
}
let picks = new Set()
for (let i=0; i<number_items; i++){
do{
var x = ROLL(1, choice_pool.length)-1
}while (picks.has(choice_pool[x]))
picks.add(choice_pool[x])
}
return (picks.size===1 ? [...picks][0] : picks)
}
function ProfIn(Mappy, lvl){
//Takes a map of profincies, and returns an array of the things they're proficient in.
if (lvl === undefined){
var lvl = 1 //Just in case you want to use this function for Expertise: pass lvl=2.
}
return Array.from(Mappy.keys()).filter(k=>Mappy.get(k)>=lvl)
}
function SetWeapProf(WeapArray){
//Sets profinciency in the array of weapons given, regardless of which group they belong to.
//Also accepts the names of groups themselves, as long as they are elements in the array.
for (let weap of WeapArray){
breaktarget:{ //To avoid the throw-statement if a match is found
for (let WeapGroup of [SimpleRanged, SimpleMelee, MartialRanged, MartialMelee]){
if (weap==WeapGroup){
WeapGroup.forEach(function(p,w){WeapGroup.safeset(w,1)})
break breaktarget
}
else if (WeapGroup.has(weap)){
WeapGroup.safeset(weap,1)
break breaktarget
}
}
throw new Error(`SetWeapProf couldn't find ${weap} in any group of weapons.`)
}
}
}
function AddEquip(item,count){
//Adds the given item(s) to the character's *Equipment* map.
if (Array.isArray(item) && item.length===2){
var count = item[1]
var item = item[0]
}
if (AllItems.has(item)){
if (count === undefined){
var count = 1
}
if (Equipment.has(item)){
Equipment.set(item, Equipment.get(item) + count)
}
else{
Equipment.set(item, count)
}
}
else{ throw new Error(`${item} doesn't appear in AllItems`) }
}
function IncAbility(key, add){
//Increases the character's given ability score by the given amount in the *AbilityScores* map.
if (AbilityScores.has(key)){
AbilityScores.set(key, AbilityScores.get(key) + add)
}
else{
throw new Error(`AbilityScores has no key: ${key}`)
}
}
//Don't @ me
Map.prototype.safeset = function(key,val){
if (this.has(key)){
this.set(key,val)
}
else{
throw new Error(`${this} \nhas no key: ${key}`)
}
}
//STARTING CHARACTER GENERATION
Sex = CHOOSE(Sexes)
Race = CHOOSE(Races)
Subrace = CHOOSE(Subraces.get(Race))
Class = CHOOSE(Classes)
Background = CHOOSE(Backgrounds)
//ABILITY SCORE GENERATION
let scores = []
if (document.getElementById("RollCheck").checked){
for (let i=0; i<6; i++){
let rolls = []
for (let i=0; i<4; i++){
rolls[i] = ROLL(1,6)
}
rolls.sort((a,b)=>a-b)
scores.push(rolls[1]+rolls[2]+rolls[3])
}
}
else{
let score2cost = new Map([[8,0], [9,1], [10,2], [11,3], [12,4], [13,5], [14,7], [15,9]])
let pointBank = 27
for (let i=0; i<6; i++){
score2cost = new Map([...score2cost].filter(e=> e[1]<=pointBank && e[1]+9*(5-i)>=pointBank))
let score = CHOOSE(score2cost)
if (i==2){
//To avoid leaving 24 points available for the last two picks,
//since they that would force 15 or 17 points to be left for the last pick.
while (pointBank-score2cost.get(score)==24){
score = CHOOSE(score2cost)
}
}
if (i==3){
//To avoid leaving 15 or 17 points available for the last two picks,
//since they that would force 6 or 8 points to be left for the last pick.
while (pointBank-score2cost.get(score)==15 || pointBank-score2cost.get(score)==17){
score = CHOOSE(score2cost)
}
}
if (i==4){
//To avoid leaving 6 or 8 points available for the last pick, since they can't be spent.
while (pointBank-score2cost.get(score)==8 || pointBank-score2cost.get(score)==6){
score = CHOOSE(score2cost)
}
}
scores.push(score)
pointBank -= score2cost.get(score)
}
}
//ABILITY SCORE ALLOCATION
if (!document.getElementById("SmartDumb").checked){
scores = shuffle(scores)
let index = 0
AbilityScores.forEach(function(score,ability){
IncAbility(ability, scores[index])
index++
})
}
else{
scores.sort((a,b)=>a-b)
if (Class === "Barbarian"){
IncAbility("STR", scores[5])
IncAbility("CON", scores[4])
IncAbility("DEX", scores[3])
scores = shuffle(scores.slice(0,3))
IncAbility("INT", scores[0])
IncAbility("WIS", scores[1])
IncAbility("CHA", scores[2])
}
if (Class === "Bard"){
IncAbility("CHA", scores[5])
IncAbility("DEX", scores[4])
IncAbility("CON", scores[3])
scores = shuffle(scores.slice(0,3))
IncAbility("STR", scores[0])
IncAbility("INT", scores[1])
IncAbility("WIS", scores[2])
}
if (Class === "Cleric"){
IncAbility("WIS", scores[5])
if (ROLL(1,2)===1){
IncAbility("STR", scores[4])
IncAbility("CON", scores[3])
}
else{
IncAbility("CON", scores[4])
IncAbility("STR", scores[3])
}
scores = shuffle(scores.slice(0,3))
IncAbility("DEX", scores[0])
IncAbility("INT", scores[1])
IncAbility("CHA", scores[2])
}
if (Class === "Druid"){
IncAbility("WIS", scores[5])
IncAbility("CON", scores[4])
scores = shuffle(scores.slice(0,4))
IncAbility("STR", scores[0])
IncAbility("DEX", scores[1])
IncAbility("INT", scores[2])
IncAbility("CHA", scores[3])
}
if (Class === "Fighter"){
let roll = ROLL(1,3)
if (roll === 1){
IncAbility("STR", scores[5])
IncAbility("CON", scores[4])
IncAbility("DEX", scores[3])
}
if (roll === 2){
IncAbility("DEX", scores[5])
IncAbility("CON", scores[4])
IncAbility("STR", scores[3])
}
if (roll === 3){
IncAbility("CON", scores[5])
IncAbility("STR", scores[4])
IncAbility("DEX", scores[3])
}
scores = shuffle(scores.slice(0,3))
IncAbility("INT", scores[0])
IncAbility("WIS", scores[1])
IncAbility("CHA", scores[2])
}
if (Class === "Monk"){
IncAbility("DEX", scores[5])
if (ROLL(1,2)===1){
IncAbility("WIS", scores[4])
IncAbility("CON", scores[3])
}
else{
IncAbility("CON", scores[4])
IncAbility("WIS", scores[3])
}
scores = shuffle(scores.slice(0,3))
IncAbility("STR", scores[0])
IncAbility("INT", scores[1])
IncAbility("CHA", scores[2])
}
if (Class === "Paladin"){
IncAbility("STR", scores[5])
if (ROLL(1,2)===1){
IncAbility("CHA", scores[4])
IncAbility("CON", scores[3])
}
else{
IncAbility("CON", scores[4])
IncAbility("CHA", scores[3])
}
scores = shuffle(scores.slice(0,3))
IncAbility("DEX", scores[0])
IncAbility("INT", scores[1])
IncAbility("WIS", scores[2])
}
if (Class === "Ranger"){
IncAbility("DEX", scores[5])
IncAbility("CON", scores[4])
IncAbility("WIS", scores[3])
scores = shuffle(scores.slice(0,3))
IncAbility("INT", scores[0])
IncAbility("STR", scores[1])
IncAbility("CHA", scores[2])
}
if (Class === "Rogue"){
IncAbility("DEX", scores[5])
IncAbility("CON", scores[4])
if (ROLL(1,2)===1){
IncAbility("CHA", scores[3])
IncAbility("INT", scores[2])
}
else{
IncAbility("INT", scores[3])
IncAbility("CHA", scores[2])
}
scores = shuffle(scores.slice(0,2))
IncAbility("STR", scores[0])
IncAbility("WIS", scores[1])
}
if (Class == "Sorcerer"){
IncAbility("CHA", scores[5])
IncAbility("CON", scores[4])
IncAbility("DEX", scores[3])
scores = shuffle(scores.slice(0,3))
IncAbility("STR", scores[0])
IncAbility("INT", scores[1])
IncAbility("WIS", scores[2])
}
if (Class === "Warlock"){
IncAbility("CHA", scores[5])
IncAbility("CON", scores[4])
IncAbility("DEX", scores[3])
scores = shuffle(scores.slice(0,3))
IncAbility("STR", scores[0])
IncAbility("INT", scores[1])
IncAbility("WIS", scores[2])
}
if (Class === "Wizard"){
IncAbility("INT", scores[5])
IncAbility("CON", scores[4])
IncAbility("DEX", scores[3])
scores = shuffle(scores.slice(0,3))
IncAbility("STR", scores[0])
IncAbility("WIS", scores[1])
IncAbility("CHA", scores[2])
}
}
//RACES AND SUBRACES
if (Race === "Dwarf"){
Age = 40 + ROLL(1,250)
Name = CHOOSE(Names.get("Dwarf").get(Sex)) + " " + CHOOSE(DwarfNameClan)
IncAbility("CON",2)
KnownLanguages.add("Dwarvish")
SetWeapProf(["Battleaxe", "Handaxe", "Light Hammer", "Warhammer"])
SpecialSavingThrows.add(["Dwarven Resilience", "You have advantage on saving thros against poison."])
Resistances.safeset("Poison",1) //Dwarven Resilience
ArtisanTools.safeset(CHOOSE(["Smith's Tools", "Brewer's Supplies", "Mason's Tools"],1,ProfIn(ArtisanTools)),1)
SpecialSkills.add(["Darkvision", "Accustomed to life underground, you have superior vision in dark and dim conditions."
+" You can see in dim light within 60 feet of you as if it were bright light, and in"
+" darkness as if it were dim light. You can't discern color in darkness, only shades of gray."])
Traits.add(["Heavy Armor Aptitude", "Your speed is not reduced by wearing heavy armor."])
SpecialSkills.add(["Stonecunning", "Whenever you make an Intelligence (History) check related to the"
+" origin of stonework, you are considered proficient in the History skill and add double"
+" your proficiency bonus to the check, instead of your normal proficiency bonus."])
if (Subrace === "Hill"){
let temp = ROLL(2,4)
Height = 44 + temp
Weight = 115 + temp * ROLL(2,6)
IncAbility("WIS",1)
HP += 1
Traits.add(["Dwarven Toughness", "Your hit point maximum increases by 1 per level."])
}
if (Subrace === "Mountain"){
let temp = ROLL(2,4)
Height = 48 + temp
Weight = 130 + temp * ROLL(2,6)
IncAbility("STR",2)
ArmorProfs.safeset("Light",1)
ArmorProfs.safeset("Medium",1)
}
}
if (Race === "Elf"){
Age = 60 + ROLL(1,650)
Name = CHOOSE(Names.get("Elf").get(Age>110 ? Sex : "Alt")) + " " + CHOOSE(ElfNameFamily)
IncAbility("DEX",2)
Speed = 30
KnownLanguages.add("Elvish")
Skills.safeset("Perception",1) //Keen Senses
SpecialSavingThrows.add(["Fey Ancestry", "You have advantage on saving throws against being charmed, and magic can't put you to sleep"])
Traits.add(["Trance", "Elves don't need to sleep. Instead, they meditate deeply, remaining semiconscious, for 4 hours a day."
+" While meditating, you can dream after a fashion; such dreams are actually mental exercise that"
+" have become reflexive through years of practice. After resting in this way, you gain the same"
+" benefit that a human does after 8 hours of sleep."])
if (Subrace === "High"){
let temp = ROLL(2,10)
Height = 54 + temp
Weight = 90 + temp * ROLL(1,4)
IncAbility("INT",1)
if (Math.random() > .3){ KnownLanguages.add(CHOOSE(StandardLanguages,1,KnownLanguages)) }
else{ KnownLanguages.add(CHOOSE(ExoticLanguages,1,KnownLanguages)) }
SetWeapProf(["Longsword", "Shortsword", "Shortbow", "Longbow"])