-
Notifications
You must be signed in to change notification settings - Fork 574
/
Copy pathCommandMaster.js
5797 lines (5135 loc) · 320 KB
/
CommandMaster.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
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
// Github: https://github.com/Roll20/roll20-api-scripts/tree/master/CommandMaster
// Beta: https://github.com/DameryDad/roll20-api-scripts/tree/CommandMaster/CommandMaster
// By: Richard @ Damery
// Contact: https://app.roll20.net/users/6497708/richard-at-damery
var API_Meta = API_Meta||{}; // eslint-disable-line no-var
API_Meta.CommandMaster={offset:Number.MAX_SAFE_INTEGER,lineCount:-1};
{try{throw new Error('');}catch(e){API_Meta.CommandMaster.offset=(parseInt(e.stack.split(/\n/)[1].replace(/^.*:(\d+):.*$/,'$1'),10)-8);}}
/**
* CommandMaster.js
*
* * Copyright 2020: Richard @ Damery.
* Licensed under the GPL Version 3 license.
* http://www.gnu.org/licenses/gpl.html
*
* This script is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* This script is the GM control capability for the RedMaster series
* of APIs for Roll20. It allows the other RedMaster series APIs to
* register with it with their current commands and ability button specs
* which are used by CommandMaster to build the GM Maintenance Menu,
* and to update Character Sheets that use the commands in abilities
* with the latest command structures. It supports other functions
* useful to the GM as needed.
*
* v0.001 02/05/2021 Initial creation as a clone of attackMaster
* v0.002-1.025 Early development. See v2.027 for details.
* v2.026 27/02/2022 Added Class-DB as a standard database. Fixed 'Specials' action
* button & updated command registration. Fixed command registration errors.
* Added token-setup buttons to add all possible character Powers & Priest
* spells from Class-DB.
* v2.027 10/03/2022 Add sychronisation of Database indexing to ensure happens after
* all databases loaded by all APIs before indexing done. Add
* "Creature" character class. Use AttackMaster version of --check-saves
* to unify character setup. Added token-setup buttons to check who
* controls what Char Sheets & toggle control DM/Player
* v2.030 28/03/2022 Moved all Table Mgt, Ability Mgt, Chat Mgt, Database Mgt to a
* shared library
* v2.031 24/04/2022 Moved all game-specific and character sheet-specific data structures
* to the RPGM game-specific library api.
* v0.2.32 20/07/2022 Converted to use revised internal database structures
* v0.2.33 17/09/2022 Moved additional common RPGMaster functions to Library. Moved common
* help handouts to Library. Optionally allow semi-colons as terminators
* for escaped characters in commands. Improve generating of spell lists
* for Priest classes, and Power lists for all classes. Change --help to
* provide a menu of links to help handouts
* v1.3.00 17/09/2022 First release of RPGMaster APIs with RPG-version-specific Library
* v1.3.01 04/10/2022 Allow Wizard and Priest spells to be stored as powers
* v1.3.02 23/10/2022 Fixed error with Specials action button
* v1.3.03 29/10/2022 Trap initialisation errors. Add All Powers will add race powers from
* the race database. Add Race selection to Class menu.
* v1.3.04 17/11/2022 Added possible creature data attributes, & fixed certain creature
* setup issues. Added weapon data update after race/class/level change
* to support things like attacks/round improvement
* v1.4.01 28/11/2022 Added support for the fighting Styles-DB. Fixed help menu. Improved
* creature attribute dice rolling. Improved creature HD & HP calcs.
* Added creature attribute dexdef dexterity bonus for ranged attacks.
* Added use of alpha indexed drop down for selection of creatures.
* Added suppression of power inheritance. Added function to check
* player, speakingas, token & character names for illegal characters.
* v1.4.02 13/12/2022 Added API button on token & character name checks to support immediate
* correction. Add ability to specify weapons and armour for creatures
* with probability of different sets. Split handling of PC Race specifications
* and Creature specifications, so that Races don't get set up with
* spurious creature specs.
* v1.4.03 16/01/2023 Added creature attkmsg & dmgmsg attributes to support messages to
* display with attack and damage rolls respectively.
* v1.4.04 24/01/2023 Added support for converting manually created character sheets to
* RPGMaster format. Added ability to configure the default token bars.
* Added functions to set token bars for all campaign tokens. Added
* separate Ammo list for Equipment conversion. Tidied up Token-Setup
* menu.
* v1.4.05 02/03/2023 Non-functional update release to maintain version sequence.
* v1.4.06 08/04/2023 Added support for when a magic item character sheet is first dragged
* to the player map, to set it to isdrawing=true and link to the CS.
* v1.4.07 14/04/2023 Fixed bug stopping Token Setup, Add to Spellbook from working.
* v1.5.01 19/05/2023 Non-functional version number synchronisation release.
* v2.1.0 06/06/2023 Made many more functions asynchronous to multi-thread. Parsed a
* creature's description in its database entry and created a Character
* Sheet Bio from it.
* v2.2.0 21/07/2023 Implemented The Aaron's API_Meta error handling. Added senderId override
* capability as id immediately after !magic & before 1st --cmd. Added
* Drag & Drop containers to the Drag & Drop system, using the
* Race-DB-Containers & Locks-Traps-DB databases. Made reSpellSpecs,
* reClassSpecs & reAttr accessible by other APIs from the library.
* Made –initialise command automatic on startup if the defined GM macros
* have changed. Enhanced parseDesc() to cater for both creatures and
* containers, locks & traps. Removed potential setTimeout() issues
* with asynchronous use of variable values – passed as parameters instead.
* Fixed error when cs attribute 'trap-name' is missing or empty.
* v2.3.0 30/09/2023 Added drag & drop query attribute that adds an extra level of query to
* drag & drop creature selection and returns variables based on the selection.
* Fixed parsing of {{prefix=...}} in drag & drop creature descriptions.
* Added new maths evaluation function to support new race 'query' variables.
* Add memorisation of random spells for spell-casting drag & drop creatures.
* Added new dice roll evaluator. Moved characterLevel() to library.
* v2.3.1 19/10/2023 Added "Token Image Quick Copy" --copyimg function. Added ^^gmid^^ field
* for container macros to support TokenMod --api-as parameter. Stop
* specification of races not in the database for now. Ensured spell names
* in spell books are hyphenated to avoid inconsistencies.
* v2.3.2 20/10/2023 Added age: attribute as a condition value for Drag & Drop creature items.
* Improved the maths parser to iterate more deeply. Changed how 'GM-Roll'
* flag builds GM rolls into container macros. Fixed hyphenation of
* reviewed weapons, spells & powers.
* v3.0.0 01/10/2023 Added support for other character sheets & game systems.
* Moved parseData() to library.
* v3.1.0 16/12/2023 Modified to support AD&D1e character sheet and rule set. Fixed weapon
* multi-hand parsing issue, clashing with % chance. Added library functions
* to support different ways of specifying and displaying the class & level
* on the character sheet. Fixed support for Drag & Drop creature hp ranges.
* v3.2.0 08/02/2024 Add proficiency list for AD&D1e version. Fix bug in some creature definitions
* that listed weapons in-hand.
* v3.2.1 23/02/2024 Improved parseStr() handling of undefined or empty strings without erroring.
* v3.3.0 18/03/2024 Non-functional sequencing release to synchronise versions
* v3.4.0 18/03/2024 Non-functional sequencing release to synchronise versions
* v3.5.0 18/03/2024 Non-functional sequencing release to synchronise versions
* v3.5.1 03/08/2024 Fix scaling of container images to match page.
* v4.0.1 20/09/2024 Fix bug in container scaling. Add NPC management, including adding automatic
* rogue table completion with random level mods, and optional random equipment
* and magic items added to items carried. Added weapon proficiencies for Creatures
* & NPCs, default to Proficient. Added Extra Strength calculation for strength of 18
* (if specified for NPC - not class dependent). Corrected allocation of Spell Menu
* action button so all those able to cast spells have it. Allow query results in
* weapon, armour & item specifications for Creatures/NPCs.
*/
var CommandMaster = (function() {
'use strict';
var version = '4.0.1',
author = 'RED',
pending = null;
const lastUpdate = 1738351019;
/*
* Define redirections for functions moved to the RPGMaster library
*/
const getRPGMap = (...a) => libRPGMaster.getRPGMap(...a);
const getHandoutIDs = (...a) => libRPGMaster.getHandoutIDs(...a);
const setAttr = (...a) => libRPGMaster.setAttr(...a);
const attrLookup = (...a) => libRPGMaster.attrLookup(...a);
const getTableField = (...t) => libRPGMaster.getTableField(...t);
const getTable = (...t) => libRPGMaster.getTable(...t);
const getLvlTable = (...t) => libRPGMaster.getLvlTable(...t);
const initValues = (...v) => libRPGMaster.initValues(...v);
const setAbility = (...a) => libRPGMaster.setAbility(...a);
const abilityLookup = (...a) => libRPGMaster.abilityLookup(...a);
const doDisplayAbility = (...a) => libRPGMaster.doDisplayAbility(...a);
const getAbility = (...a) => libRPGMaster.getAbility(...a);
const getDBindex = (...a) => libRPGMaster.getDBindex(...a);
const updateHandouts = (...a) => libRPGMaster.updateHandouts(...a);
const findThePlayer = (...a) => libRPGMaster.findThePlayer(...a);
const findCharacter = (...a) => libRPGMaster.findCharacter(...a);
const fixSenderId = (...a) => libRPGMaster.fixSenderId(...a);
const calcAttr = (...a) => libRPGMaster.calcAttr(...a);
const rollDice = (...a) => libRPGMaster.rollDice(...a);
const evalAttr = (...a) => libRPGMaster.evalAttr(...a);
const getCharacter = (...a) => libRPGMaster.getCharacter(...a);
const classObjects = (...a) => libRPGMaster.classObjects(...a);
const characterLevel = (...a) => libRPGMaster.characterLevel(...a);
const updateClassLevel = (...a) => libRPGMaster.updateClassLevel(...a);
const displayClassLevel = (...a) => libRPGMaster.displayClassLevel(...a);
const addMIspells = (...a) => libRPGMaster.addMIspells(...a);
const getMagicList = (...a) => libRPGMaster.getMagicList(...a);
const rogueLevelPoints = (...a) => libRPGMaster.rogueLevelPoints(...a);
const handleCheckThiefMods = (...a) => libRPGMaster.handleCheckThiefMods(...a);
const handleCheckSaves = (...a) => libRPGMaster.handleCheckSaves(...a);
const handleCheckWeapons = (...a) => libRPGMaster.handleCheckWeapons(...a);
const parseData = (...a) => libRPGMaster.parseData(...a);
const resolveData = (...a) => libRPGMaster.resolveData(...a);
const caster = (...a) => libRPGMaster.caster(...a);
const findPower = (...a) => libRPGMaster.findPower(...a);
const handleSetNPCAttributes = (...a) => libRPGMaster.handleSetNPCAttributes(...a);
const handleGetBaseThac0 = (...a) => libRPGMaster.handleGetBaseThac0(...a);
const creatureWeapDefs = (...a) => libRPGMaster.creatureWeapDefs(...a);
const sendToWho = (...m) => libRPGMaster.sendToWho(...m);
const sendPublic = (...m) => libRPGMaster.sendPublic(...m);
const sendAPI = (...m) => libRPGMaster.sendAPI(...m);
const sendFeedback = (...m) => libRPGMaster.sendFeedback(...m);
const sendResponse = (...m) => libRPGMaster.sendResponse(...m);
const sendResponsePlayer = (...p) => libRPGMaster.sendResponsePlayer(...p);
const sendResponseError = (...e) => libRPGMaster.sendResponseError(...e);
const sendError = (...e) => libRPGMaster.sendError(...e);
const sendCatchError = (...e) => libRPGMaster.sendCatchError(...e);
const sendParsedMsg = (...m) => libRPGMaster.sendParsedMsg(...m);
const sendGMquery = (...m) => libRPGMaster.sendGMquery(...m);
const sendWait = (...m) => libRPGMaster.sendWait(...m);
/*
* Handle for reference to character sheet field mapping table.
* See RPG library for your RPG/character sheet combination for
* full details of this mapping. See also the help handout on
* RPGMaster character sheet setup.
*/
var fields = {
defaultTemplate: 'RPGMdefault',
warningTemplate: 'RPGMwarning',
menuTemplate: 'RPGMmenu',
messageTemplate: 'RPGMmessage',
};
/*
* Handle for the Database Index, used for rapid access to the character
* sheet ability fields used to hold database items.
*/
var DBindex = {};
/*
* Handle for the API Databases in the RPGM Game-specific Library
*/
var dbNames = {};
/*
* Handle for the library object used to pass back RPG & character sheet
* specific data tables.
*/
var RPGMap = {};
const design = {
turncolor: '#D8F9FF',
roundcolor: '#363574',
statuscolor: '#F0D6FF',
statusbgcolor: '#897A87',
statusbordercolor: '#430D3D',
edit_icon: 'https://s3.amazonaws.com/files.d20.io/images/11380920/W_Gy4BYGgzb7jGfclk0zVA/thumb.png?1439049597',
delete_icon: 'https://s3.amazonaws.com/files.d20.io/images/11381509/YcG-o2Q1-CrwKD_nXh5yAA/thumb.png?1439051579',
settings_icon: 'https://s3.amazonaws.com/files.d20.io/images/11920672/7a2wOvU1xjO-gK5kq5whgQ/thumb.png?1440940765',
apply_icon: 'https://s3.amazonaws.com/files.d20.io/images/11407460/cmCi3B1N0s9jU6ul079JeA/thumb.png?1439137300',
open_img: 'https://s3.amazonaws.com/files.d20.io/images/355714477/jouzZ3bALliE0SV-1NWaNg/thumb.png?1692686089',
closed_img: 'https://s3.amazonaws.com/files.d20.io/images/355657918/NcpSVNL3LIpQPNxDcCBpog/thumb.png?1692651167|70|50',
grey_button: '"display: inline-block; background-color: lightgrey; border: 1px solid black; padding: 4px; color: dimgrey; font-weight: extra-light;"',
dark_button: '"display: inline-block; background-color: lightgrey; border: 1px solid black; padding: 4px; color: black; font-weight: normal;"',
selected_button: '"display: inline-block; background-color: white; border: 1px solid red; padding: 4px; color: red; font-weight: bold;"',
boxed_number: '"display: inline-block; background-color: yellow; border: 1px solid blue; padding: 2px; color: black; font-weight: bold;"',
// grey_action: '<span style="display: inline-block; background-color: lightgrey; border: 1px solid black; padding: 4px; color: dimgrey; font-weight: extra-light;">$1$2</span>$4',
grey_action: '<span style="display: inline-block; background-color: lightgrey; border: 1px solid black; padding: 4px; color: dimgrey; font-weight: extra-light;">$1</span>$3',
};
/*
* CommandMaster related help handout information.
*/
const handouts = Object.freeze({
CommandMaster_Help: {name:'CommandMaster Help',
version:4.01,
avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
bio:'<div style="font-weight: bold; text-align: center; border-bottom: 2px solid black;">'
+'<span style="font-weight: bold; font-size: 125%">CommandMaster Help v4.01</span>'
+'</div>'
+'<div style="padding-left: 5px; padding-right: 5px; overflow: hidden;">'
+'<h1>Command Master API</h1>'
+'<h4>for CommandMaster v'+version+' and later</h4>'
+'<h3><span style='+design.selected_button+'>New:</span> in this Help Handout</h3>'
+'<p><span style='+design.selected_button+'>New:</span> Added <i>Drag & Drop</i> help in this help handout</p>'
+'<p><span style='+design.selected_button+'>New:</span> <i>Drag & Drop</i> NPCs added, and enhanced Creature definitions</p>'
+'<p><span style='+design.selected_button+'>New:</span> Allow query results in <i>Drag & Drop</i> weapon, armour & item deinitions</p>'
+'<p>The CommandMaster API is part of the RPGMaster suite of APIs for Roll20, and manages the initialisation of a Campaign to use the RPGMaster APIs, communication and command syntax updates between the APIs and, most importantly for the DM, easy menu-driven setup of Tokens and Character Sheets to work with the APIs.</p>'
+'<h2>Syntax of CommandMaster calls</h2>'
+'<p>The CommandMaster API is called using !cmd.</p>'
+'<pre>!cmd --initialise</pre>'
+'<p>Commands to be sent to the CommandMaster API must be preceded by two hyphens \'--\' as above for the --initialise command. Parameters to these commands are separated by vertical bars \'|\', for example:</p>'
+'<pre>!cmd --register action|description|api-call|api-command|parameters</pre>'
+'<p>Commands can be stacked in the call, for example:</p>'
+'<pre>!cmd --initialise --abilities</pre>'
+'<p>When specifying the commands in this document, parameters enclosed in square brackets [like this] are optional: the square brackets are not included when calling the command with an optional parameter, they are just for description purposes in this document. Parameters that can be one of a small number of options have those options listed, separated by forward slash \'/\', meaning at least one of those listed must be provided (unless the parameter is also specified in [...] as optional): again, the slash \'/\' is not part of the command. Parameters in UPPERCASE are literal, and must be spelt as shown (though their case is actually irrelevant).</p>'
+'[General API Help]'
+'<h2>How CommandMaster Works</h2>'
+'<p>The CommandMaster API coordinates other APIs in the RPGMaster API series and provides the DM with facilities to set the Campaign up to use them. It will initialise a Campaign in Roll20 to use the RPGMaster series APIs. APIs can register their commands with CommandMaster and, should they change in the future, CommandMaster will search all Character Sheets and databases for that command and offer the DM the option to automatically update any or all of those found to the new command structure of that API. Selected Tokens and their associated Character Sheets can be set up with the correct Token Action Buttons, with spell-users given spells in their spell book, fighters given weapon proficiencies, setting saving throws correctly, and linking token circles to standard Character Sheet fields.</p>'
+'<h3>Initialising a Campaign</h3>'
+'<p>Using the <b>--initialise</b> command will add a number of Player Macros for the DM that will run the most-used RPGMater DM commands, which can be flagged to appear in the Macro Bar at the bottom of the DM\'s screen for ease of access.</p>'
+'<h3>Setting up tokens & character sheets</h3>'
+'<p>Selecting one or multiple tokens and running the <b>--abilities</b> command will allow token action buttons and RPGMaster API capabilities to be set up for all the represented Character Sheets at the same time, though all Character Sheets will be set up the same way.</p>'
+'<h3>Registering API commands</h3>'
+'<p>Any API command can be registered with CommandMaster using the <b>--register</b> command. This will allow the command registered to be added as a Token Action Button to Character Sheets by the abilities command, and to be optionally updated in all Character Sheets wherever used should the details of the registration change.</p>'
+'<h3>Editing Character Sheet abilities</h3>'
+'<p><b>Danger:</b> this command is very powerful, and can ruin your campaign if mis-used! The <b>--edit</b> command can be used to change any string in Character Sheet ability macros to any other string, using \'escaped\' characters to replace even the most complex strings. However, use with care!</p>'
+'<h3><span style='+design.selected_button+'>New:</span> <i>Drag & Drop</i> NPCs and Creatures</h3>'
+'<p>CommandMaster can combine all its capabilities for managing character sheets to automatically populate a blank character sheet with data specific to an NPC of a particular race, class and level, or to make that character sheet represent a creature from <i>The Monsterous Compendium</i>. Data held in the <b>Race-DB-NPCs</b> and <b>Race-DB-Creatures</b> databases is used to configure the blank character sheet, and the GM or game creator can add their own bespoke NPC and creature definitions to their own databases to enhance and extend those provided in the same fashion as with other RPGMaster databases and APIs. See the <i>Class & Race Database Help</i> handout for more information.</p>'
+'<p>To create a <i>Drag & Drop</i> NPC or Creature, add a blank character sheet to the Journal using the standard Roll20 [Character+] button at the top of the Roll20 Journal. Give the sheet a name and an image as desired, then close it. Drag the blank sheet onto the map surface to drop a token, select the token just dropped, and down the bottom of the Chat Window a dialog will have appeared, with options to select the [Creature] or [NPC] for the sheet (as well as other options which can be ignored for <i>Drag & Drop</i>). Use the buttons to select the NPC or Creature you want from the Roll Queries that appear on screen, which may also ask for further information (such as level of the NPC, or age of the creature etc). <b>Be patient and wait for the API to set the character sheet up!</b> This is one of the most complex things you can ask RPGMaster APIs to do - just think how long it would take you to set up a character sheet manually... Once complete, a number of dialogs will appear in the Chat Window describing the characteristics of the NPC or creature created. It is then necessary to click away from the token (de-select it) and then select it again to refresh the Action Buttons for the token. The token and character sheet can then be immediately used in play as that NPC or Creature.</p>'
+'<p>It is possible to re-write any character sheet as a different NPC or Creature using the GM\'s [Token Setup] macro-menu button, or using the <b>!cmd --abilities</b> command, with the token representing the character sheet selected, and selecting the [Choose Race/Class] function on the displayed dialog. This displays the same dialog for selecting [NPC] or [Creature] as described above. The GM will be prompted for confirmation of over-writing an already populated sheet.</p>'
+'<h3><span style='+design.selected_button+'>Updated:</span> <i>Drag & Drop</i> Containers</h3>'
+'<p><i>Drag & Drop</i> Containers work in a similar fashion to other <i>Drag & Drop</i> functions for setting up character sheets. Drop a blank character sheet onto a map to drop a token, ensure that token is selected, then go to the dialog that appears at the bottom of the Chat Window. Select the [Container] button, and a list of various types of container appears as a Roll Query from which you can select a type. Then a new dialog appears in the Chat Window asking you to specify the characteristics of the container to create. The container can have a lock of various types (e.g. a combination lock, a password lock, a simple key lock, etc.), and can be trapped with various types of trap (such as a poison dart trap, an explosive runes trap, etc).</p>'
+'<p>The types of container, and the macros used to drive the container\'s actions, are all defined in the <i>Locks-Traps-DB</i>. As with other RPGMaster databases, the GM or game creator can add their own containers, locks and traps by adding their own database. Refer to the <i>Locks and Traps Help</i> handout to get more information.</p>'
+'<br>'
+'<h2>Command Index</h2>'
+'<h3>1. Campaign setup</h3>'
+'<pre>--initialise<br>'
+'--abilities</pre>'
+'<h3>2. Character Sheet configuration</h3>'
+'<pre>--conv-spells<br>'
+'--conv-items<br>'
+'--token-defaults<br>'
+'--check-chars<br>'
+'--class-menu [token_id]<br>'
+'--add-spells [POWERS/MUSPELLS/PRSPELLS] | [level]<br>'
+'--add-profs<br>'
+'--set-prof [NOT-PROF/PROFICIENT/SPECIALIST/MASTERY] | weapon | weapon-type<br>'
+'--set-all-prof<br>'
+'--token-img [token_id]</pre>'
+'<h3>3. Command and Ability maintenance</h3>'
+'<pre>--register action|description|api-call|api-command|parameters<br>'
+'--edit old-string | new-string</pre>'
+'<h3>4. Other commands</h3>'
+'<pre>--help<br>'
+'--debug [ON/OFF]</pre>'
+'<br>'
+'<h2>1. Campaign setup</h2>'
+'<h3>1.1 Initialise for RPGMaster APIs</h3>'
+'<pre>--initialise</pre>'
+'<p>This command creates a number of Player Macros which can be found under the Player Macro tab in the Chat window (the tab that looks like three bulleted lines, next to the cog). These macros hold a number of DM commands that are useful in setting up and running a campaign. It is recommended that the "Show in Bar" flags for these macros are set, and the "Show Macro Bar" flag is set (the macro bar is standard Roll20 functionality - see Roll20 Help Centre for more information).</p>'
+'<p>The buttons added are:</p>'
+'<ul>'
+' <li><i>Maint-menu:</i> Runs the <b>!init --maint</b> command</li>'
+' <li><i>Token-setup:</i> Runs the <b>!cmd --abilities</b> command</li>'
+' <li><i>Add-items:</i> Runs the <b>!magic --gm-edit-mi</b> command</li>'
+' <li><i>End-of-Day:</i> Runs the <b>!init --end-of-day</b> command</li>'
+' <li><i>Initiative-menu:</i> Runs the <b>!init --init</b> command</li>'
+' <li><i>Check-tracker:</i> Runs the <b>!init --check-tracker</b> command</li>'
+'</ul>'
+'<p>The DM can drag Macro Bar buttons around on-screen to re-order them, or even right-click them to change their name and colour of the button. Feel free to do this to make the Macro Bar as usable for you as you desire.</p>'
+'<h3>1.2 Setup Tokens & Character Sheets</h3>'
+'<pre>--abilities</pre>'
+'<p>Displays a menu with which one or more selected tokens and the Character Sheets they represent can be set up with the correct Token Action Buttons and data specific to the RPGMaster APIs, to work with the APIs in the best way. The menu provides buttons to add any command registered with CommandMaster (see <b>--register</b> command) as a Token Action Button, change control of the sheet and set the visibility of the token name to players (which also affects RoundMaster behaviour), set the Character Class and Level of the Character, add spells to spell books, add granted powers, add or change weapon proficiencies and proficiency levels for each weapon, set the correct saving throws based on race, class & level of character / NPC / creature, and optionally clear or set the Token \'circles\' to represent AC (bar 1), base Thac0 (bar 2) and HP (bar 3). Essentially, using this menu accesses the commands in section 2 without the DM having to run them individually.</p>'
+'<p>All tokens selected when menu items are used will be set up the same way: exceptions to this are using the Set Saves button (sets saves for each selected token/character sheet correctly for the specifications of that sheet), and the Set All Profs button (sets weapon proficiencies to proficient based on the weapons in each individual token/character sheet\'s item bag). Different tokens can be selected and set up differently without having to refresh the menu.</p>'
+'<h2>2. Character Sheet configuration</h2>'
+'<p>The commands in this section can be accessed using the --abilities command menu. The individual commands below are used less frequently.</p>'
+'<h3>2.1 Convert Character Sheet Spells</h3>'
+'<pre>--conv-spells</pre>'
+'<p>Works on multiple selected tokens representing several Character Sheets.</p>'
+'<p>For Character Sheets that have not been created using the commands provided by the <i>!cmd --abilities</i> menu, pre-existing from previous Roll20 campaigns using the Advanced D&D2e Character Sheet, this command does its best to convert all spells in tables on the Character Sheet to RPGMaster format and replace them with spells that exist in the RPGMaster spell databases. Those that the system can\'t automatically match are subsequently displayed in a menu, with additional buttons that list the spells that do exist in the databases that can be used to replace them by selecting both the spell to be replaced and the replacement spell.</p>'
+'<p>It is possible that not all spells will be able to be replaced, if the Character Sheet reflects campaign experience where bespoke spells or spells from other handbooks have been available. In this case, the spells can be left unconverted, and the DM might add the spells to their own databases using the information provided in the <i>Magic Database Help</i> handout. Until the spells are added to the databases, they will not work, and cannot be memorised for spell use.</p>'
+'<p>This command can be used on multiple selected tokens, as stated above. All the Character Sheets represented by the selected tokens will be converted, and the displayed list of spells to manually match represents the unmatched spells from all those Character Sheets. As the spells are manually matched, they will be replaced on all of the selected Character Sheets.</p>'
+'<h3>2.2 Convert Character Sheet Equipment</h3>'
+'<pre>--conv-items</pre>'
+'<p>Works on multiple selected tokens representing several Character Sheets.</p>'
+'<p>As for the <i>--conv-spells</i> command, Character Sheets that have not been created using the commands provided by the <i>!cmd --abilities</i> menu, pre-existing from previous Roll20 campaigns using the Advanced D&D2e Character Sheet, this command does its best to convert all weapons, armour, other items of equipment and magical items such as potions, rings etc, in tables on the Character Sheet to RPGMaster format and replace them with weapons, armour and items that exist in the RPGMaster spell databases. Those that the system can\'t automatically match are subsequently displayed in a menu, with additional buttons that list the items that do exist in the databases that can be used to replace the unknown ones by selecting both the item to be replaced and the replacement item.</p>'
+'<p>It is possible that not all weapons, armour, equipment and especially magic items will be able to be matched if the Character Sheet reflects campaign experience where bespoke magic items and equipment or equipment from other handbooks have been available. In this case, the items can be left unconverted, and the DM might add the items to their own databases using the information provided in the <i>Weapon & Armour Database Help</i> or <i>Magic Database Help</i> handouts. Until the items of equipment are added to the databases, if they are weapons they cannot be taken in-hand to fight with, armour will not be counted towards armour class calculations, and items that contribute to saving throws will not do so.</p>'
+'<p>As with the <i>--conv-spells</i> command, this command can be used on multiple selected tokens. All the Character Sheets represented by the selected tokens will be converted, and the displayed list of items to manually match represents the unmatched items from all those Character Sheets. As the items are manually matched, they will be replaced on all of the selected Character Sheets.</p>'
+'<h3>2.3 Set Default Token Bar mappings</h3>'
+'<pre>--token-defaults</pre>'
+'<p>This command uses the selected token as a model to set the default token bar mappings that will be used in future by the RPGMaster APIs.</p>'
+'<p>The standard defaults distributed with the APIs are for token bar1 to represent AC, bar2 to represent Thac0-base, and bar3 to represent HP. However, alternative mappings can be made. <b>It is highly recommended that HP, AC and Thac0-base are represented in some order</b> because these are the most common values to be affected by spells and circumstances, both in and out of combat situations.</p>'
+'<p>If no token is selected, or the token selected to be the model does not have any bars linked to a character sheet, an error message will be displayed. If some but not all the bars are linked, then any bars not linked will be automatically matched to some of the recommended Character Sheet fields of AC, Thac0-base, and HP (in that order of priority).</p>'
+'<p>Once this mapping is done, a menu will be displayed that can be used to map other tokens to the new defaults: either just the selected tokens, or all tokens in the campaign, or just those tokens that have bars currently linked to Character Sheets (i.e. excluding creature mobs with multiple tokens with unlinked bars representing a single character sheet). A button also exists to clear the bar links for all selected tokens to create creature mobs.</p>'
+'<h3>2.4 Check control of Character Sheets</h3>'
+'<pre>--check-chars</pre>'
+'<p>Displays a list of every Character Sheet with a defined Class, Level, or Monster Hit Dice categorised by <i>DM Controlled, Player Controlled PCs & NPCs, Player Controlled Creatures,</i> and <i>Controlled by Everyone.</i> Each name is shown as a button which, if selected, swaps control of that Character Sheet between DM control and the control of a selected Player (the Player, of course, must be one that has already accepted an invite to join the campaign). A button is also provided at the bottom of this menu to toggle the running of this check whenever the Campaign is loaded.</p>'
+'<h3>2.5 Set Character Class, Race & Species</h3>'
+'<pre>--class-menu [token_id]</pre>'
+'<p>Takes an optional ID for a token representing a character. If not specified, takes the currently selected token</p>'
+'<p>Displays a menu from which the Race, Class and Level of a Character can be set, or a Creature species can be selected. Setting the Race, Class and Level of a Character (PC or NPC) enables all other capabilities to be used as appropriate for that character sheet in this and other APIs in the <b>RPGMaster API suite</b>, such as spell use, appropriate race & class powers, selection of allowed weapons, and the like. Selecting a Creature species <i>automatically</i> sets up the Character Sheet in an optimal way for the APIs to use it to represent the chosen creature, including saves, armour class, hit dice and rolling of hit points, as well as special attacks such as paralysation & level drain of high level undead, spell use by the likes of Orc Shamen, regeneration powers, and so on. However, it does not automatically give weapons, armour equipment, or magic items to Creatures - if appropriate this still needs to be done by the DM/Game Creator.</p>'
+'<p>DMs/Game Creatores can add to or amend the Class, Race and Creature definitions. Refer to the appropriate database help handout distributed with the APIs and created as handouts in your campaign for more information.</p>'
+'<h3>2.6 Add spells to spell book</h3>'
+'<pre>--add-spells [POWERS/MUSPELLS/PRSPELLS] | [level]</pre>'
+'<p>Displays a menu allowing spells in the Spells Databases to be added to the Character Sheet(s) represented by the selected Token(s). If no spell type and/or spell level is specified, the initial menu shown is for Level 1 Wizard spells (MUSPELLS). Buttons are shown on the menu that allow navigation to other levels, spell types and powers. For <i>Priests</i>, a button is also provided to add every spell allowed for the Priest\'s Class to their spellbooks at all levels (of course, they will only be able to memorise those that their experience level allows them to). For all Character Classes that have <i>Powers</i> (or Power-like capabilities, such as Priestly <i>Turn Undead</i> or Paladin <i>Lay on Hands</i>), there is a button on the <i>Powers</i> menu to add Powers that the character\'s Class can have.</p>'
+'<p><b>Note:</b> adding spells / powers to a sheet does not mean the Character can immediately use them. They must be <i>memorised</i> first. Use the commands in the <b>MagicMaster API</b> to memorise spells and powers.</p>'
+'<h3>2.7 Choose weapon proficiencies</h3>'
+'<pre>--add-profs</pre>'
+'<p>Displays a menu from which to select proficiencies and level of proficiency for any weapons in the Weapon Databases for the Character Sheet(s) represented by the selected tokens. Also provides a button for making the Character proficient in all weapons carried (i.e. those currently in their Item table).</p>'
+'<p>All current proficiencies are displayed, with the proficiency level of each, which can be changed or removed. It is also now possible to select proficiencies in <b>Fighting Styles</b> as introduced by <i>The Complete Fighter\'s Handbook</i>: these can be found under the <i>Choose Style</i> button, and can also be set as Proficient or Specialised. Selecting a Fighting Style proficiency grants benefits as defined in the Handbook, or as modified by the DM - see the <i>Styles Database Help</i> handout for more information.</p>'
+'<p><b>Note:</b> this does more than just entering the weapon in the proficiency table. It adds the <i>weapon group</i> that the weapon belongs to as a field to the table (see weapon database help handouts for details), which is then used by the <b>AttackMaster API</b> to manage <i>related weapon</i> attacks and give the correct proficiency bonuses or penalties for the class and weapon used.</p>'
+'<h3>2.8 Set weapon proficiencies</h3>'
+'<pre>--set-prof [NOT-PROF/PROFICIENT/SPECIALIST/MASTERY] | weapon | weapon-type </pre>'
+'<p>Sets a specific weapon proficiency to a named level. If the proficiency level is omitted, PROFICIENT is assumed. If the weapon already exists in the proficiencies table, the existing proficiency level is updated to that specified. Otherwise, the weapon (and its weapon group) are added to the table at the specified level.</p>'
+'<p><b>Note:</b> this does more than just entering the weapon in the proficiency table. It adds the weapon group that the weapon belongs to as a field to the table (see weapon database help handouts for details), which is then used by the AttackMaster API to manage related weapon attacks and give the correct proficiency bonuses or penalties for the class and weapon used.</p>'
+'<h3>2.9 Add proficiencies for all carried weapons</h3>'
+'<pre>--set-all-prof</pre>'
+'<p>Adds all currently carried weapons (those in the Items table) to PROFICIENT, saving them and their <i>weapon group</i> to the weapon proficiency table. Those weapons found that are already in the table are reset to PROFICIENT (overwriting any existing different proficiency level). Any other proficiencies already in the table are not altered.</p>'
+'<p><b>Note:</b> this command always adds a weapon proficiency called <i>innate</i>. This proficiency is used for attacks with innate weapons, such as claws and bites, but also for spells that require a <i>touch attack</i>. Indeed, to make this even more specific, the weapons database distributed with the AttackMaster and MagicMaster APIs includes a weapon called <i>Touch</i>.</p>'
+'<p><b>Tip:</b> if using the <b>MagicMaster API</b> then running the <b>!magic --gm-edit-mi</b> command and adding weapons before running this command can speed up setting up character sheets.</p>'
+'<h3>2.10 Change container images & variables</h3>'
+'<pre>--token-img [token_id]</pre>'
+'<p>Displays a menu for changing the images and variables used for containers. The optional token_id (defaults to the selected token) must represent a character sheet, and the dialog expects it to be a character sheet of a container, potentially one set up using the <i>Drag & Drop</i> container functionality. Containers set up using <i>Drag & Drop</i> will have information about the use of images and variables in the "Bio" tab of the Character Sheet.</p>'
+'<h2>3. Command and Ability maintenance</h2>'
+'<h3>3.1 Register an API command</h3>'
+'<pre>--register action|description|api-call|api-command|parameters</pre>'
+'<p>Register an API command with the CommandMaster API to achieve two outcomes: allow the command to be set up as a Token Action Button, and/or automatically maintain & update the syntax of the commands in Character Sheet ability macros and the RPGMaster API databases.</p>'
+'<p>This is a powerful and potentially hazardous command. Registry of an API command is remembered by the system in the state variable, which is preserved throughout the life of the Campaign in Roll20. If a subsequent registration of the same <b>action</b> has different parameters, the system detects this and searches all Character Sheet ability macros for the <i>old version</i> of the command and replaces all of them with the new command. It also changes the parameters, using a syntax including a range of character \'escapes\' to substitute characters that Roll20 might otherwise interpret as commands itself. In detail, the --register command takes:</p>'
+'<table>'
+' <tr><th scope="row">action:</th><td>the unique name given to this command in the whole system. This can be any legal text name including A-Z, a-z, 1-9, -, _ only. Must start with an alpha. Case is ignored.</td></tr>'
+' <tr><th scope="row">description:</th><td>a short description of the command, which is displayed in the menu that allows the command to be added as a Token Action Button.</td></tr>'
+' <tr><th scope="row">api-call:</th><td>the API call <i>without</i> the !, e.g. cmd, or magic, etc</td></tr>'
+' <tr><th scope="row">api-command:</th><td>the command to be passed to the specified API, with the hyphens replaced by ~~ or plusses replaced by **, e.g. ~~cast-spell or **menu.</td></tr>'
+' <tr><th scope="row">parameters:</th><td>the parameters (or initial parameters) to be passed as part of this command to replace the matching existing command parameters. This string is \'escaped\' using the following character replacements:</td></tr>'
+'</table>'
+'<table>'
+' <tr><th scope="row">Character</th><td>Parameter separator</td><td>?</td><td>[</td><td>]</td><td><</td><td>></td><td>@</td><td>-</td><td>|</td><td>:</td><td>&</td><td>{</td><td>}</td></tr>'
+' <tr><th scope="row">Substitute</th><td>%%</td><td>^</td><td><<</td><td>>></td><td> </td><td> </td><td>`</td><td>~</td><td>&#124;</td><td> </td><td>&amp;</td><td>&#123;</td><td>&#125;</td></tr>'
+' <tr><th scope="row">Alternative</th><td> \\vbar;</td><td>\\ques;</td><td>\\lbrak;</td><td>\\rbrak;</td><td>\\lt;</td><td>\\gt;</td><td>\\at;</td><td>\\dash;</td><td>\\vbar;</td><td>\\clon;</td><td>\\amp;</td><td>\\lbrc;</td><td>\\rbrc;</td></tr>'
+'</table>'
+'<p>Commands cannot have a CR (carrage return/new line) in the middle of them, but CR can separate commands in multi-command sequences.</p>'
+'<p>If the parameter string ends with $$, this will ensure that a complete command up to the next CR is to be replaced (including everything up to the CR even if not part of the command). If there is not a $$ on the end of the parameter string, then only the command and parameters that are matched are replaced (using a parameter count of each old and new parameter separated by \'%%\') - the rest of the line (including any remaining parameters not so matched) will be left in place.</p>'
+'<p>Here are some examples of registration commands:</p>'
+'<pre>--register Spells_menu|Open a menu with spell management functions|magic|~~spellmenu |\`{selected|token_id}<br>'
+'--register Use_power|Use a Power|magic|~~cast-spell|POWER%%\`{selected|token_id}<br>'
+'--register Attack_hit|Do an attack where Roll20 rolls the dice|attk|~~attk-hit|\`{selected|token_id}</pre><br>'
+'<h3>3.2 Edit ability macros</h3>'
+'<pre>--edit existing-string | new-string</pre>'
+'<p style="background-color:yellow;"><b>Danger:</b> use this command with extreme care! It can destroy your Campaign! It is recommended that you make a backup copy of your Campaign before using this command. --register is more controlled, as it has been tested with the RPGMaster command strings, and any future releases that change the API commands will be fully tested before release for their effect on Campaigns, with accompanying release notes. Using the --edit function directly can have unintended consequences!</p>'
+'<p>Replaces an existing \'escaped\' string with a new replacement string in all ability macros on all Character Sheets. These strings both use the same escape sequence replacements as for the <b>--register</b> command (see section 3.1) as in fact <b>--register</b> and <b>--edit</b> use the same functionality.</p>'
+'<p>Examples of its use are to change API command calls, or Character Sheet field name access in macros should the field names change.</p>'
+'<br>'
+'<h2>4. Other Commands</h2>'
+'<h3>4.1 Display help on these commands</h3>'
+'<pre>--help</pre>'
+'<p>This command does not take any arguments. It displays a very short version of this document, showing the mandatory and optional arguments, and a brief description of each command.</p>'
+'<h3>4.2 Switch on or off Debug mode</h3>'
+'<pre>--debug (ON/OFF)</pre>'
+'<p>Takes one mandatory argument which should be ON or OFF.</p>'
+'<p>The command turns on a verbose diagnostic mode for the API which will trace what commands are being processed, including internal commands, what attributes are being set and changed, and more detail about any errors that are occurring. The command can be used by the DM or any Player - so the DM or a technical advisor can play as a Player and see the debugging messages.</p>'
+'<br>'
+'</div>',
},
LocksTraps_Help: {name:'Locks and Traps Help',
version:1.03,
avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
bio:'<div style="font-weight: bold; text-align: center; border-bottom: 2px solid black;">'
+'<span style="font-weight: bold; font-size: 125%">Locks and Traps Help v1.03</span>'
+'</div>'
+'<div style="padding-left: 5px; padding-right: 5px; overflow: hidden;">'
+'<h1>Containers, Locks & Traps Databases</h1>'
+'<h6><i>for RPGMaster APIs</i></h6>'
+'<h2>1. General Database information</h2>'
+'<p>The RPGMaster APIs use a number of databases to hold Macros defining races, creatures, character classes, spells, powers, magic items and their effects, and now containers, locks & traps. The version of these databases distributed with the APIs are held internally to the APIs. However, the AttackMaster or MagicMaster API command <b>--extract-db</b> can be used to extract any or all standard databases to Character Sheets for examination and update. The APIs are distributed with many class, spell, power, magic item and container definitions, and DMs can add their own containers, locks, traps, character classes, spells, items, weapons, ammo and armour to additional databases in their own database character sheets, with new definitions for database items held in Ability Macros. Additional database character sheets should be named as follows:</p>'
+'<table>'
+' <tr><th scope="row">Wizard Spells:</th><td>additional databases: MU-Spells-DB-<i>[added name]</i> where <i>[added name]</i> can be replaced with anything you want.</td></tr>'
+' <tr><th scope="row">Priest Spells:</th><td>additional databases: PR-Spells-DB-<i>[added name]</i> where <i>[added name]</i> can be replaced with anything you want.</td></tr>'
+' <tr><th scope="row">Powers:</th><td>additional databases: Powers-DB-<i>[added name]</i> where <i>[added name]</i> can be replaced with anything you want.</td></tr>'
+' <tr><th scope="row">Magic Items:</th><td>additional databases: MI-DB-<i>[added name]</i> where <i>[added name]</i> can be replaced with anything you want.</td></tr>'
+' <tr><th scope="row">Character Classes:</th><td>additional databases: Class-DB-<i>[added name]</i> where <i>[added name]</i> can be replaced with anything you want.</td></tr>'
+' <tr><th scope="row">Races, Creatures & Containers:</th><td>additional databases: Race-DB-<i>[added name]</i> where <i>[added name]</i> can be replaced with anything you want.</td></tr>'
+' <tr><th scope="row">Locks & Traps:</th><td>additional databases: Locks-Traps-DB-<i>[added name]</i> where <i>[added name]</i> can be replaced with anything you want.</td></tr>'
+' <tr><th scope="row">Attack Calculations:</th><td>additional databases: Attacks-DB-<i>[added name]</i> where <i>[added name]</i> can be replaced with anything you want.</td></tr>'
+'</table>'
+'<p><b>However:</b> the system will ignore any database with a name that includes a version number of the form "v#.#" where # can be any number or group of numbers e.g. "MI-DB v2.13" will be ignored. This is so that the DM can version control their databases, with only the current one (without a version number) being live.</p>'
+'<p>There can be as many additional databases as you want. Other Master series APIs come with additional databases, some of which overlap - this does not cause a problem as version control and merging unique macros is managed by the APIs.</p>'
+'<p><b>Important Note:</b> all Character Sheet databases <b><u><i>must</i></u></b> have their <i>\'ControlledBy\'</i> value (found under the [Edit] button at the top right of each sheet) set to <i>\'All Players\'</i>. This must be for all databases, both those provided (set by the API) and any user-defined ones. Otherwise, Players will not be able to run the macros contained in them.</p>'
+'<p>Each added database has a similar structure, with:</p>'
+'<ul>'
+' <li>Ability Macros named as the class, spell, power, magic item, locks or traps specified, and used to describe and provide effects for classes, containers, spells, powers and magic items using the commands in the RPGMaster APIs;</li>'
+' <li>Custom Attributes with the attribute name "ct-ability-macro-name", one per Ability Macro, which defines the casting time and casting cost for spells & powers, and speed and MI type for magic items (not currently used for Class, Race, Container, Lock, Trap or Attack definitions);</li>'
+' <li>An entry in a list on the character sheet in the spell book of the relevant Character Sheet tab (Spell Level of the spell defined, Powers tab, or various spell books for different Classes & Magic Items - see Lock and Trap entries below).</li>'
+'</ul>'
+'<p>As with other RPGMaster suite databases, the GM need not worry about creating anything other than a correctly formatted macro entry, and then can run the <b>!magic --check-db Database-Name</b> command to check the database formatting, create the custom attributes and list entries, and re-index all database entries so that the new entries can be immediately used in live play.</p>'
+'<p>Ability Macros can be whatever the DM wants and can be as simple or as complex as desired. Roll Templates are very useful when defining class, spell, power, magic item, trap and lock ability macros. When a Player or an NPC or Monster views or casts a spell, power or uses a container or magic item the APIs run the relevant Ability Macro from the databases as if it had been run by the Player from the chat window. All Roll20 functions for macros are available.</p>'
+'<h3>1.1 Replacing Locks, Traps, Containers, Races, Classes, Spells & Items</h3>'
+'<p>If you want to replace any Ability Macro provided in any of the databases, you can do so simply by creating an Ability Macro in one of your own databases with exactly the same name as the provided item to be replaced. The API gives preference to Ability Macros in user-defined databases, so yours will be selected in preference to the one provided with the APIs.</p>'
+'<br>'
+'<h2>2. How Container Locks & Traps Work</h2>'
+'<p><span style="color:red">Important Note:</span> In order for <i>Drag & Drop</i> containers to work, you must have the <b>ChatSetAttr</b> and <b>TokenMod</b> Mods loaded as well as RPGMaster suite APIs <span style="color:red"><i><b>and</b></i></span> ChatSetAttr <u>must</u> have "Players can modify all characters" option ticked, <span style="color:red"><i><b>and</b></i></span> TokenMod <u>must</u> have "Players can use --ids" option ticked.</p>'
+'<p>Any token representing a character sheet can be a container. This includes characters, NPCs, and creatures as well as token/character sheet pairs specifically intended to be containers such as chests, barrels, desks, bags and the like. Characters can have equipment such as weapons and armour added to their sheets, and obtain magic items on their quest - this is the character acting as a "container" for these items and equipment. Characters (and NPCs and some creatures) can <i>search</i> containers to find and loot items from them using the <b>!magic --search</b> command (see <i>MagicMaster Help</i> handout) or the <i>MI menu / Search for MIs & Treasure</i> action selection. They can also <i>store</i> items in a container using <b>!magic --pickorput</b> or <i>MI menu / Store MIs</i>. The GM can also store and edit items in any container by using the GM\'s <i>Add Items</i> dialog, which also can configure the number of slots for items in a container, and the type of a container, as well as many other container and item management functions - see the <i>MagicMaster Help</i> handout for more information on the <b>!magic --gm-edit-mi</b> command (which is what the <i>Add Items</i> button calls).</p>'
+'<h3>2.1 Container Management</h3>'
+'<p>When any container is searched by a character (or NPC or creature), depending on the type of container (see below) it will eventually show its contents (if any). The contents can be added by the GM using the GM\'s <i>Add Items</i> dialog, or by characters, NPCs or creatures <i>storing</i> items in the container. The contents of the container are shown to those searching in one of two possible dialogs - one which shows a button for each item or stack of items (long menu), and another which provides a drop-down list of the items (short menu). Either dialog allows the searcher to select items to take from the container and add to their own equipment.</p>'
+'<p>The GM can use the controls on the <i>Add Items</i> menu to mark any container to either show the exact names of the contents in these dialogs, or only show the type of each item: e.g. <i>Potion of Healing</i> might be shown simply as a <i>Potion</i>, or a <i>Broadsword +2</i> be displayed as a <i>Long Blade</i> i.e. only describing what the character sees. When the searcher takes the item into their own equipment it might then be listed in that searcher\'s equipment by its true name (unless the GM has also <i>hidden</i> the item as another item or hidden it automatically with the <i>Looks-Like</i> function: see <i>MagicMaster Help</i> and <i>Magic Database Help</i> handouts).</p>'
+'<p>The GM can also set the maximum number of "slots" that a container has: each unique item or type of item requires a slot to store it in. Once all slots are full, no more items can be stored in the container. Certain types of item can be "stacked": e.g. <i>Flight Arrows</i> can be stacked, with any number of <i>Flight Arrows</i> occupying one slot. However, <i>Flight Arrows</i> and <i>Sheaf Arrows</i> cannot be stacked together, and nor can <i>Flight Arrows</i> and <i>Flight Arrows +1</i>. A wand with multiple charges will perhaps look like a stacked item (as the quantity reflects the number of charges), but another wand of the same type cannot be stacked with it, as each is a unique item. When stacks are looted, a dialog will appear asking how many of the items in the stack want to be taken: alternatively, when a unique item with multiple charges is looted, the whole item will automatically be taken (i.e. a <i>Wand of Missiles</i> with 20 charges cannot be split into two or more with fewer charges).</p>'
+'<h3>2.2 Types of Container</h3>'
+'<p>Not all containers will react the same way when searched. How the container reacts is determined by the type of container set on the character sheet by the GM using the <i>Add Items</i> dialog, or automatically when creatures or containers are <i>Dragged & Dropped</i>. The current types are:</p>'
+'<table>'
+'<tr><th>Type</th><th>#</th><th>Description</th></tr>'
+'<tr><td>Empty Inanimate Object</td><td>0</td><td>A simple container that is not a character, NPC or creature, such as a simple chest or a dead body, does not have a lock or trap, but is empty apart (perhaps) for some text-only treasure descriptions.</td></tr>'
+'<tr><td>Inanimate Container with stuff</td><td>1</td><td>A simple container that is not a character, NPC or creature, does not have a lock or trap, and may contain items and equipment and possibly some text-only treasure descriptions.</td></tr>'
+'<tr><td>Empty Sentient Creature</td><td>2</td><td>A character, NPC or creature that requires its "pocket to be picked" in order to loot stuff, but is empty (or their items are not pick-able) apart (perhaps) for some text-only treasure descriptions.</td></tr>'
+'<tr><td>Sentient Creature with Stuff</td><td>3</td><td>A character, NPC or creature that requires its "pocket to be picked" in order to loot stuff, and may possess items and equipment and possibly some text-only treasure descriptions.</td></tr>'
+'<tr><td>Trapped Container</td><td>4</td><td>A container of any type that may have a lock or trap that must be overcome before items it contains can be looted, and may or may not possess items and equipment and possibly some text-only treasure descriptions.</td></tr>'
+'</table>'
+'<p>The default type for a new character sheet just created is 0, an Empty Inanimate Container. However, if a <i>Drag & Drop</i> creature is created, the type is set to 2 (Empty Sentient Creature), or if a trapped or locked <i>Drag & Drop</i> container is created, the type is set to 4 (Trapped Container). If the <i>Add Items</i> dialog or any character action adds items to an empty container or empty sentient creature, the type is changed to 1 or 3 respectively. As with everything to do with containers, the container type can be changed in the GM\'s <i>Add Items</i> dialog.</p>'
+'<h3>2.3 Picking Pockets of Sentient Creatures</h3>'
+'<p>When an attempt is made to search a container with type 2 or 3 (a sentient creature), the API will ask the searcher to make a "Pick Pockets" roll (whether the searcher is a Rogue or otherwise). The Pick Pockets percentage displayed is that shown on the <i>Rogue</i> tab of the character sheet (minimum 5%). If successful, the looting process is the same as any other container. If failed, the contents are not displayed and, as per the <i>Dungeon Master\'s Guide</i>, the chance of the victim noticing is a percentage equal to 3 x victim\'s experience level. The API notifies the GM with the result of this roll, i.e. whether the victim notices the Pick Pockets attempt or not. The GM can then decide what happens next.</p>'
+'<h3>2.4 Trapped and Locked Containers</h3>'
+'<p>Containers of type 4 are seen by the APIs as perhaps being trapped or locked, and instead of displaying their contents the API runs the Ability Macro on the container\'s character sheet with the name "Trap-@{container-name|trap-version}". Generally, when first called, the attribute "trap-version" on the container character sheet will either not exist (the API will default it to a value of 0) or be 0, so the Ability Macro "Trap-0" will be run. If no Ability Macro with the name "Trap-0" exists on the container\'s sheet, the API tries to run one called just "Trap". If neither of these exist, the API just displays the contents of the container as if no trap or lock existed. The value of the "trap-version" attribute can be used to change the behavior of the container as actions occur, with Ability Macros "Trap-1", "Trap-2", etc having different outcomes on future searches of the same container - e.g. a successful removal of a trap may change the trap-version to 1 and the "Trap-1" macro just display the contents without having to overcome the trap again.</p>'
+'<p>The trap / lock Ability Macros are standard Roll20 macros and can do anything that a standard Roll20 macro can do. See the Roll20 Help Center for more information on macros. Typically, the "Trap-0" macro will ask the searcher to provide some key, password, combination number or perform some other activity in order to unlock its contents without negative consequences. The macro can call other macros, perhaps via API buttons or Roll Queries (see Roll20 help) which offer choices. For those Game Authors and GMs who are less comfortable coding Ability Macros, the RPGMaster suite offers configurable <i>Drag & Drop</i> containers which do all the hard work for you!</p>'
+'<h3>2.5 <i>Drag & Drop</i> Containers</h3>'
+'<p>From v2.2 of RPGMaster suite, <i>Drag & Drop</i> containers are provided with the APIs, alongside a database of Lock & Trap Macros they use to provide their locks and traps. When <i>Dragged & Dropped</i> (in the same way as a <i>Drag & Drop</i> creature: create a new blank character sheet, give it a sensible name, and then just drag it onto the playing surface to drop a token) the <i>Race, Class & Creature</i> dialog pops up, but now also with a new button called [Containers]. Remember to ensure the newly dropped token is selected, then selecting the [Containers] button opens a drop-down list in the centre of the screen allowing you to select a basic container type. Each of these have default images associated with them that will display a token appropriate to the container selected. Select the one you want and a dialog appears supporting the selection of various pre-programmed locks & traps, the ability to change the images used for the container, and to change the effects of some locks and traps by setting different values. Once selected, the token is automatically given a representative icon and all necessary aspects of the character sheet are configured for the trapped / locked container. The GM just needs to (optionally) add items to it using their <i>Add Items</i> dialog.</p>'
+'<p>The description of the container can be looked at (including instructions on configuring it) by opening the "Bio" tab of the container\'s character sheet. Typically, the <i>Drag & Drop</i> container will come with an action button displayed when the container\'s token is selected to close any lock and/or trap without changing its status, so once opened the player characters can close the container and searching it will open it again (often without setting off the trap again!). There is also a new GM <i>Macro Bar</i> macro button added which allows the GM to reset the locks and traps on the container (so you can test the trap/lock and then reset it for others to find) - go to the <i>Collection</i> tab of the Chat Window and enable <i>Reset Container</i> to be in your Macro Bar. The GM\'s [Token Setup] button (or the command <b>!cmd --token-img</b>) can be used to configure the container (give the token new images, choose new locks & traps, and set variables the macros can use to new values). Review the container\'s "Bio" to check what the configuration options are - e.g. how to set a new list of password choices, set a new combination, set the key number that must be possessed, etc.</p>'
+'<h3>2.6 Images and Image URLs</h3>'
+'<p>The <i>Drag & Drop</i> Container system supports images to make tokens dynamic, appearing to change state such as opening, being destroyed and becoming a pile of ash, turning into a summoned creature, etc. To do this it stores image URLs, and the GM can change these images to apear as they desire.</p>'
+'<p>Image URLs must comply with the Roll20 rules for any token image set by Roll20 Mods and APIs. That includes that they can\'t be Premium Asset images, such as those from the Market Place: they must be from your own image library. The images provided in the databases are from "Creative Commons" licenced sources. If you wish to replace the images provided, the best way to do so is to select the Container token, use the GM\'s [Token Setup] button to open the Container Configuration dialogue, then drag an image to the playing surface from your "My Library" image library, ensure that newly dropped image is selected and press the appropriate image button on the configuration dialogue. That will save the correctly formatted URL to the container.</p>'
+'<p>You can add your own images to your "My Library" images using the [Upload] button on the "My Library" tab of the chat. Please source images responsibly.</p>'
+'<h3>2.7 Who Rolls for Finding Traps?</h3>'
+'<p>If you read the Player\'s Handbook when it describes Thieving skills, the roll for <i>Find Traps</i> is normally made by the GM. <i>Drag & Drop</i> containers can work in two ways, depending on the configuration settings: the GM can be prompted to make the roll for the Player (the default setting); or the Player can make the roll. In either case, the result of the roll will be handled by the coding of the <i>Drag & Drop</i> container.</p>'
+'<p>In order to change which of the two options is in operation, use the GM\'s [Config-RPGM] button or the <b>!magic --config</b> command and set the <i>"Thievish Chance"</i> configuration as desired.</p>'
+'<p>There are other rolls that can be made by Players when encountering locked and/or trapped containers: only the <i>Find Traps</i> roll is set by default to be able to be rolled by either the player or the GM, based on the configuration. However, the <i>Locks-Traps-DB</i> includes example "GM-Roll-" versions of the macros involved in making <i>Remove Traps, Pick Locks,</i> and <i>Pick Pockets</i> rolls. The GM or game creator can use these in programming their own containers in their own extensions to the <i>Locks-Traps-DB</i>.</p>'
+'<h3>2.8 Data Inheritance</h3>'
+'<p>In order to save time, effort and data space, any Race definition can "inherrit" data values from a "parent" definition, or even a "parent tree". As containers are considered to be a form of "Race" by the APIs, they too can inherrit data values, meaning that "families" of containers can be created where common data settings can be set once in the root definition. Any inherrited data tags can be overwritten with different values, and additional ones specified just by adding them to a data specification of the same name in the inherriting (child) definition. In the case of container definitions, the data is held as RaceData specifications.</p>'
+'<p>In order to inherrit data, the <i>Specs</i> specification field four (the <i>Supertype</i>) for the inherriting "child" container must name the "parent" to be inherrited from. If the "parent" also has a <i>Specs Supertype</i> field that refers to a "grand-parent" the tree will be followed on upward until a <i>Supertype</i> that does not specify a valid definition of the same database item <i>Class</i> (<i>Specs</i> field two) is encountered: typically in the case of containers the tree would terminate with a database item of <i>Supertype</i> "Container".</p>'
+'<p><b>Note:</b> this inheritance does not work for Lock and Trap definitions in the <i>Locks-Traps-DB</i> as in those definitions the <i>Supertype</i> specifically refers to the stored ability macro, and cannot refer to a parent database item.</p>'
+'<h3>2.9 Roll Template Merging</h3>'
+'<p>Another way of reusing common aspects of database definitions is to use the standard Roll20 macro technique of merging one ability macro specification into another, using the syntax "%{character_name|ability_macro}". However, in the case of use with RPGMaster database entries, the "character_name" can be the name of any internal or external database, or even just a database root name ending in "-DB" (e.g. the root name of the <i>Race-DB-Containers</i> database is <i>Race-DB</i>). This is the case even if the referred to ability is in a database held in code: the merge will occur as if between externally held database macros. As with inheritance, chaining of specifications can occur, and "%{...|...}" entries will be resolved until the point that no unresolved entries remain.</p>'
+'<p>The way the merge progresses means that uniquely named Roll Template fields will all appear in the final display, but those with the same names will only display the data in <i><b>the last specified field</b></i> of that name in the merged templates, but in the <b><i>position in sequence of the first encountered field</i></b> of that name. Also, Roll Template fields with no data after the "=" will not be included in the display: this is also the case for fields defined as "{{}}" (allowing for bracketing of <i>Specs & Data</i> fields that <i><b>must</b></i> be defined <i><b>between</b></i> template fields in very short templates).</p>'
+'<p><b><span style="color:red">Important Note:</span></b> The APIs always find the first <i>Specs=</i> and <i>....Data=</i> specifications in any merged database entries. It is best to ensure that the <i>Specs</i> and <i>Data</i> specifications are as early as possible in the specification, ahead of any "%{...|...}, so that it is those from the called database entry are used.</p>'
+'<h3>2.10 No Whispering</h3>'
+'<p>As with other RPGMaster database items, when updating the existing Lock & Trap items or creating new ones you should not add Roll20 "whispers", "emotes" etc. The APIs do some fairly special stuff with working out where posts should go, in terms of which players, characters, the GM, and also redirecting output when players are not logged on, and the APIs add their own Roll20 posting commands to ensure the right players see the right information at the right time, and don\'t see what they shouldn\'t.</p>'
+'<p>That does not stop players from whispering, using emotes and other commands in chat to each other and the GM, or the GM in using "/desc" and other commands as normal.</p>'
+'<h3>3. <i>Drag & Drop</i> Containers Database</h3>'
+'<p>The <i>Drag & Drop</i> container system draws on definitions for different types of basic containers that are contained in the Containers Database. As with all other RPGMaster suite databases, this Database is distributed with the APIs in code, but can be extracted to review and copy elements by using the <b>!magic --extract-db Race-DB-Containers</b> command, which will extract the database to a character sheet, where the entries can be seen as ability macros. (It is recommended that you do not keep complete extracted databases, but instead copy those elements you want to use to your own database and then delete the extracted database - this will optimise system performance).</p>'
+'<p>The Containers databases have names that start with Race-DB-Containers (or, in fact, can just start with <i>Race-DB</i>) and can have anything put at the end, though those with version numbers of the form v#.# as part of the name will be ignored.</p>'
+'<p>As previously stated, each database definition has 3 parts in the database (see Section 1): an Ability Macro with a name that is unique and describes the type of container, a custom Attribute with the name of the Ability Macro preceded by "ct-", and a listing in the database character sheet of the ability macro name separated by \'|\' along with other container macros. The quickest way to understand these entries is to examine existing entries. Do extract the root databases and take a look (but remember to delete them after exploring the items in them, so as not to slow the system down unnecessarily).</p>'
+'<p><b>Note:</b> The DM creating new containers does not need to worry about anything other than the Ability Macro in the database, as running the <b>!magic -check-db < Database name ></b> command will update all other aspects of the database appropriately, as long as the <i>Specs</i> fields are correctly defined.</p>'
+'<p>Ability macros can be added to a database just by using the [+Add] button at the top of the <i>Abilities</i> column in the <i>Attributes and Abilities</i> tab of the Database Character Sheet, and then using the edit "pencil" icon on the new entry to open it for editing. Ability macros are standard Roll20 functionality and not dependent on the API. Refer to the Roll20 Help Center for more information.</p>'
+'<h3>3.1 Example Container Definition</h3>'
+'<p>The Containers database includes a number of example container definitions, but the GM or game creator can add to these with their own definitions by following the information in this handout (and their own imagination!). Here is an example of a container definition:</p>'
+'<h3>Large Chest</h3>'
+'<p style="display: inline-block; background-color: lightgrey; border: 1px solid black; padding: 4px; color: dimgrey; font-weight: extra-light;">&{template:RPGMdefault}{{title=Large Chest}}{{subtitle=Container}}<mark style="color:green">Specs=[Large Chest,Container,0H,Container]</mark>{{Size=3ft x 2ft x 2ft, capacity 100lbs}}{{Slots=This chest has stackable 18 slots}}<mark style="color:blue">RaceData=[w:Large Chest, slots:18, lock:No-Lock, trap:No-Trap, attr:ac=4|hp=20, cimg:https://s3.amazonaws.com/files.d20.io/images/163011054/ LD6xZDT2SlYSow0Q5QHb3g/thumb.png?1599509586|105|75, oimg:https://s3.amazonaws.com/files.d20.io/images/352175458/ BYTfuvbA_JvbL0IUjeM0Ug/thumb.png?1690472095|105|105</mark>]{{GM Info=Use the GM\'s [Token Setup] button, or the **!cmd --token-img** command to change the token\'s images, locks & traps, and set variables to vary behaviour. Items can be stored in it by using the GM\'s [Add Items] button, or the **!magic --gm-edit-mi** command}}{{desc=This is an ordinary chest, which can be configured to have locks and traps. When searched, after locks and traps have been overcome, it will open and list its contents. Resetting it closes it again and resets the locks and traps.}}</p>'
+'<p>There are a number of important aspects to this definition:</p>'
+'<p><b>Roll Template:</b>The first element of note in this definition is that it is using a <i>Roll Template</i> for formatting the message to the player. Roll Templates are standard Roll20 functionality, generally provided by character sheet authors, but the RPGMaster suite has its own suite of Roll Template definitions, of which RPGMdefault is one. See the <i>RPGMaster Library Help</i> handout for details of RPGMaster Roll Templates</p>'
+'<p><b>Specs:</b> The next item to note is the <i>Specs</i> field, with a format that is standard across all RPGMaster database entries.</p>'
+'<pre>Specs=[Large Chest,Container,0H,Container]</pre>'
+'<p>Slotted between Roll Template fields, the Specs field will not appear to the players, but is only available to the APIs. The first field is always the database item type (or name), the second is the class of database item (in this case a "Container" database item), the third is the handedness of the item (not yet relevant to Container items), and the fourth the Super-type which in the case of Container items is usually "Container": however, if using <i>"Race Definition Inheritance"</i>, the fourth element will be the name of the Container definition that this container inherits its RaceData from (see information on inheritance above).</p>'
+'<p><b>RaceData:</b> As any character or creature can be a container, chests are part of the Race family that use RaceData specifications. Indeed, the preloaded examples include a sleeping character (who will wake if they detect you picking their pockets...) and a "dead(?)" body that transforms into a Zombie (or any other undead you want). RaceData can be <i>"inherited"</i> from another container definition - set the fourth <i>Specs</i> field to be the name of the Container database entry to inherrit from. See information on "Inheritance" above.</p>'
+'<p>The elements in the RaceData specification define data that the locks & traps use during game play, that may affect their behaviour. Some of the relevant data tags are:</p>'
+'<table>'
+'<tr><th>Tag</th><th>Format</th><th>Default</th><th>Description</th></tr>'
+'<tr><td>w:</td><td>Text</td><td>\' \'</td><td>The name of the container</td></tr>'
+'<tr><td>slots:</td><td>#</td><td>18</td><td>The initial maximum number of container slots</td></tr>'
+'<tr><td>lock:</td><td>Text</td><td>\' \'</td><td>The default Lock for this type of container</td></tr>'
+'<tr><td>trap:</td><td>Text</td><td>\' \'</td><td>The default Trap for this type of container</td></tr>'
+'<tr><td>attr:</td><td>Data Tags</td><td>\' \'</td><td>Attribute specifications for the container, typically AC & HP</td></tr>'
+'<tr><td>cimg:</td><td>< url ></td><td>undefined</td><td>The URL of the image to use for a closed container</td></tr>'
+'<tr><td>oimg:</td><td>< url ></td><td>undefined</td><td>The URL of the image to use for an open container</td></tr>'
+'<tr><td>limg#:</td><td>< url >[%%label]</td><td>undefined</td><td>The optional URL of a user-definable image related to locks stored as lock-img# with an optional variable label</td></tr>'
+'<tr><td>timg#:</td><td>< url >[%%label]</td><td>undefined</td><td>The optional URL of a user-definable image related to traps stored as trap-img# with an optional variable label</td></tr>'
+'<tr><td>lvar#:</td><td>< text or # >[%%label]</td><td>\' \'</td><td>An initial setting for <i>lock-var#</i> with an optional variable label</td></tr>'
+'<tr><td>tvar#:</td><td>< text or # >[%%label]></td><td>\' \'</td><td>An initial setting for <i>trap-var#</i> with an optional variable label</td></tr>'
+'</table>'
+'<p>The Large Chest container is specified as having 18 slots, no lock (represented by the <i>"No-Lock"</i> lock type), no trap (represented by the <i>"No-Trap"</i> trap type), an Armour Class of 4, 20 hit points, an image URL for a closed container and an image URL for an open container. No lock or trap variables are preset by this container definition.</p>'
+'<p>Any of the RaceData tags can be inherrited from another container definition as described above, under the description for the <i>Specs</i>. Also, any of these tags can be overwritten by the Locks and/or Traps set for the container (not just the default ones specified in the container definition, but any lock or trap subsequently set).</p>'
+'<p>The <i>"attr"</i> tag allows certain attributes on the character sheet of the container to be set, in the case of the Large Chest setting an Armour Class (AC) of 4 and 20 Hit Points(HP). The data format is for a pipe-delimited string of "< tag >=< value >|< tag >=< value >| ... ". The full list that can be used can be found at the end of this document, and also in more detail in the <i>Class & Race Database Help</i> handout.</p>'
+'<p>The Lock and Trap variables (<i>lvar#</i> and <i>tvar#</i>) can be preset with values and variable names. The names for the variables appear on the Container Configuration dialogue to prompt the user to enter appropriate data. Generally, lock and trap variables are set by the lock & trap definitions.</p>'
+'<p>The Open & Closed Container image URLs must be of the correct format (see above), and are generally set by the container definition (though they can be overwritten by the Lock and Trap definitions if needed). The Open & Closed Container image tags do not accept a name specification, as they are always just those images. Alternate images can be specified for the container, for use by Lock and Trap macros to display when the container enters other states: however, generally speaking, these Lock & Trap images are set by the Lock & Trap definitions.</p>'
+'<h3>3.5 Lock & Trap Status Attributes</h3>'
+'<p>There are a number of character sheet attributes that are set by various conditions and by some macros in the <i>Locks-Traps-DB</i> that can be useful to GMs and game creators that are programming their own locks & traps. The table below gives you an idea of what they are and how they are used, but the best way to learn is to extract the database and view some examples. <b>Note:</b> many of these attributes are set by each <i>Trap-#</i> macro when it is run by using the <i>ChatSetAttr</i> !setAttr command (see database for example <i>Trap-#</i> macros). You can add and set others to your own <i>Trap-#</i> macros as you require. Remember, these attributes can be accessed in the lock & trap macros by using the form <b>@{^^chest^^|attribute-name}</b>.</p>'
+'<table>'
+'<tr><th>Attribute</th><th>Values</th><th>Description</th></tr>'
+'<tr><td>trap-version</td><td>#</td><td>The version of the "trap-" macros that will be called if a --search is conducted: initially 0</td></tr>'
+'<tr><td>trap-status</td><td>Armed or Disarmed</td><td>Flag stating if the trap has already been disarmed</td></tr>'
+'<tr><td>trap-status|max</td><td>Locked or Unlocked</td><td>Flag stating if the container has already been unlocked</td></tr>'
+'<tr><td>gm-rolls</td><td>\'GM-Roll-\' or \' \'</td><td>Set to GM-Roll- if the configuration is for GMs to roll for <i>Find Traps</i></td></tr>'
+'<tr><td>trap-name</td><td>< text ></td><td>The name of the trap on this container</td></tr>'
+'<tr><td>trap-name|max</td><td>< text ></td><td>The name of the lock on this container</td></tr>'
+'<tr><td>chest</td><td>token_id</td><td>The token ID of the container</td></tr>'
+'<tr><td>playerid</td><td>player_id</td><td>The player ID of the player that controls the character that is searching the container</td></tr>'
+'<tr><td>thief</td><td>token_id</td><td>The token ID of the character searching the container</td></tr>'
+'<tr><td>charName</td><td>< text ></td><td>The name of the character that is searching the container</td></tr>'
+'<tr><td>tstr</td><td>#</td><td>The strength score of the character searching the container</td></tr>'
+'<tr><td>tint</td><td>#</td><td>The intelligence score of the character searching the container</td></tr>'
+'<tr><td>tdex</td><td>#</td><td>The dexterity score of the character searching the container</td></tr>'
+'<tr><td>bruteStr</td><td>#</td><td>The "bend-bars" chance of the character searching the container</td></tr>'
+'<tr><td>openLock</td><td>#</td><td>The "open locks" score of the character searching the container</td></tr>'
+'<tr><td>remTrap</td><td>#</td><td>The "find/remove traps" score of the character searching the container</td></tr>'
+'</table>'
+'<p>The attributes "gm-rolls" & "trap-status" are used in the macros as <i>qualifiers</i> to onward macro calls. For example:</p>'
+'<pre>!magic --display-ability @{^^chest^^|thief}|^^chestid^^|@{^^chest^^|gm-rolls}Unlocked</pre>'
+'<p>will either run the macro <code>Unlocked</code> or <code>GM-Roll-Unlocked</code> depending on the current value of "gm-rolls" on that container, where the "Unlocked" macro allows the Player to roll the dice for finding traps, whereas "GM-Roll-Unlocked" has the GM make the roll. And as another example:</p>'
+'<pre>!magic --display-ability @{^^chest^^|thief}|^^chestid^^|Trap-@{^^chest^^|trap-status}</pre>'
+'<p>will run either the macro <code>Trap-Armed</code> or <code>Trap-Disarmed</code> depending on the value of "trap-status" with alternative consequences for the party!</p>'
+'<p>Of course, the ChatSetAttr command !setAttr can be used to change the values of these attributes as the player progresses through the sequence of macros, successfully removing the trap and setting <i>trap-status</i> to "Disarmed", or getting the correct combination and setting the <i>trap-status|max</i> to "Unlocked". Use of these statuses is important when the <b>!magic --find-traps</b> command or the equivalent <i>Items Menu / Find Traps</i> dialog is used, which finds (and possibly removes) the trap before tackling any lock.</p>'
+'<h2>4. Locks & Traps Database</h2>'
+'<p>The <i>Drag & Drop</i> container draws upon ability macro definitions in the Locks & Traps Database to configure their traps and locks. As with all other RPGMaster suite databases, this Database is distributed with the APIs in code, but can be extracted to review and copy elements by using the <b>!magic --extract-db Locks-Traps-DB</b> command, which will extract the database to a character sheet, where the entries can be seen as ability macros. (It is recommended that you do not keep complete extracted databases, but instead copy those elements you want to use to your own database and then delete the extracted database - this will optimise system performance).</p>'
+'<p>The Locks & Traps databases have names that start with Locks-Traps-DB and can have anything put at the end, though those with version numbers of the form v#.# as part of the name will be ignored.</p>'
+'<p>As previously stated, each database definition has 3 parts in the database (see Section 1): an Ability Macro with a name that is unique and matches the trap/lock action, a custom Attribute with the name of the Ability Macro preceded by "ct-", and a listing in the database character sheet of the ability macro name separated by \'|\' along with other trap/lock macros. The quickest way to understand these entries is to examine existing entries. Do extract the root databases and take a look (but remember to delete them after exploring the items in them, so as not to slow the system down unnecessarily).</p>'
+'<p><b>Note:</b> The DM creating new trap/lock macros does not need to worry about anything other than the Ability Macro in the database, as running the <b>!magic -check-db Locks-Traps-DB</b> command will update all other aspects of the database appropriately, as long as the <i>Specs</i> fields are correctly defined.</p>'
+'<p>Ability macros can be added to a database just by using the [+Add] button at the top of the <i>Abilities</i> column in the <i>Attributes and Abilities</i> tab of the Database Character Sheet, and then using the edit "pencil" icon on the new entry to open it for editing. Ability macros are standard Roll20 functionality and not dependent on the API. Refer to the Roll20 Help Center for more information.</p>'
+'<h3>4.1 Trap-# Ability Macros</h3>'
+'<p>Here is an example of a Lock & Trap Database entry for a "Trap-0" type macro. Note that Trap-# macros are somewhat different from other Ability Macros in the Locks-Traps-DB, as they set up the trap/lock on first selection of the locked / trapped container.</p>'
+'<h3>Key Lock</h3>'
+'<p style="display: inline-block; background-color: lightgrey; border: 1px solid black; padding: 4px; color: dimgrey; font-weight: extra-light;">&{template:RPGMmessage}{{title=<span style="color:red">^^chest^^</span>}}<mark style="color:green">Specs=[Key-Lock,Lock|Ability,0H,Trap-0]</mark>{{desc=Do you have the key? [Key @{<span style="color:red">^^chest^^</span>|<span style="color:blue">lock-var1</span>}](!magic --display-ability c|<span style="color:red">^^tid^^</span>|<span style="color:red">^^chest^^</span>|Unlocked). If not are you going to try and pick the lock? To do so [Roll 1d100](~<span style="color:red">^^chest^^</span>|Open-Locks) and get less than your Open Locks percentage, which is [[{ {@{selected|olt} },{5} }kh1]]. If neither, then I suppose you can try [Brute Strength](!magic --display-ability c|<span style="color:red">^^tid^^</span>|<span style="color:red">^^chest^^</span>|Smash-the-Lock)?}}<mark style="color:blue">AbilityData=[w:Key Lock, lvar1:53%%Key Number, ns:11],[cl:AB,w:Open+List],[cl:AB,w:Opened-Lock],[cl:AB,w:Pick-a-Lock],[cl:AB,w:Return-Trap-2],[cl:AB,w:Find-Trap-Roll],[cl:AB,w:Return-Trap-3],[cl:AB,w:Find-Remove-Traps],[cl:AB,w:Smash-Lock],[cl:AB,w:Lock-Smash],[cl:AB,w:Not-Smashed],[cl:AB,w:Reset-Trap,action:1]</mark>{{GM desc=A key lock requires the searcher to have in their possession (though the system does not check) a particular key - or alternatively the searcher can try to pick the lock or smash it. If the lock pick fails or a critical fail is made on smashing the lock, any associated trap is triggered.<br>The GM can set the key name and the critical fail roll by selecting the container token and using the GM\'s [Token Setup] button, or the **!cmd --abilities** command.}}<br><span style="color:blue">!setattr --silent --charid <span style="color:red">^^chestid^^</span> --dexterity|@{<span style="color:red">^^cname^^</span>|dexterity} --thief|<span style="color:red">^^tid^^</span> --chest|<span style="color:red">^^targettid^^</span> --bruteStr|@{<span style="color:red">^^cname^^</span>|bendbar} --strength|@{<span style="color:red">^^cname^^</span>|strength} --openLock|@{<span style="color:red">^^cname^^</span>|olt} --remTrap|@{<span style="color:red">^^cname^^</span>|rtt} --intelligence|@{<span style="color:red">^^cname^^</span>|intelligence} --charName|<span style="color:red">^^cname^^</span></span></p>'
+'<p>There are a number of aspects in common with the Container database entry described in the previous section: it uses a <i>Roll Template</i>, in this case one provided by the RPGMaster suite, it has a <i>Specs</i> specification in common with all RPGMaster database items, and there is a Data specification. However, the Specs and Data specifications have some differences:</p>'
+'<p><b>Specs:</b> the format that is standard across all RPGMaster database entries:</p>'
+'<pre>Specs=[Key-Lock,Lock|Ability,0H,Trap-0]</pre>'
+'<p>Slotted between Roll Template fields, the Specs field will not appear to the players, but is only available to the APIs. The first field is always the database item type (or name), the second is the class of database item (in this case a "Lock|Ability" database item), the third is the handedness of the item (not currently relevant to Lock & Trap items), and the fourth the Super-type which in the case of Lock & Trap items is the name this macro will be stored as in the container character sheet that uses it.</p>'
+'<p><b><span style="color:red">Important Note:</span></b> Lock & Trap database entry names (both the name of the Ability Macro and the first Specs data field) <b><i>must be different from any Super-type Specs field (the fourth field)</i></b>. This ensures the database & character sheet tidying functions don\'t delete the lock & trap macros from trapped / locked container character sheets. Trapped / locked containers run from Roll20 macros stored on the character sheet - if a --tidy function is executed on a trapped / locked container, any ability macros on the character sheet that have the same name as a Locks-Traps-DB data entry will be deleted (the API assumes that they can be read from the database, but in the case of Locks & Traps they can\'t).</p>'
+'<p>The database entry <i>class</i> (the second Specs field) can be one of <b>Lock|Ability, Trap|Ability</b>, or just <b>Ability</b>. The (somewhat obvious) meaning is that those with <i>Lock</i> specify types of lock, and those with <i>Trap</i> specify types of trap. Those with just <i>Ability</i> specify steps in the action of a lock or trap. Locks and traps can be mixed for any container, allowing lots of interesting combinations.</p>'
+'<p><b>AbilityData:</b> AbilityData specifications cannot "inherit" from parent ability definitions, as stated above. The elements in the AbilityData specification define data that the locks & traps use during game play, that may affect their behaviour. The data tags in the <i>AbilityData</i> are very similar to those in <i>RaceData</i> specifications for containers, and will overwrite those in the container definition when selected as a lock or trap for a container. Some of the relevant data tags are:</p>'
+'<table>'
+'<tr><th>Tag</th><th>Format</th><th>Default</th><th>Description</th></tr>'
+'<tr><td>w:</td><td>Text</td><td>\' \'</td><td>The name of the lock/trap</td></tr>'
+'<tr><td>magical:</td><td>[ 0 | 1 ]</td><td>0</td><td>Only for traps: trap is magical in nature (1), so "Remove Trap" rolls have half the chance they would otherwise</td></tr>'
+'<tr><td>cimg:</td><td>url</td><td>undefined</td><td>The URL of the image to use for a closed container</td></tr>'
+'<tr><td>oimg:</td><td>url</td><td>undefined</td><td>The URL of the image to use for an open container</td></tr>'
+'<tr><td>limg#:</td><td>< url >[%%label]</td><td>undefined</td><td>The optional URL of a user-definable image related to locks stored as lock-img# with an optional variable label</td></tr>'
+'<tr><td>timg#:</td><td>< url >[%%label]</td><td>undefined</td><td>The optional URL of a user-definable image related to traps stored as trap-img# with an optional variable label</td></tr>'
+'<tr><td>lvar#:</td><td>< text or # >[%%label]</td><td>\' \'</td><td>An initial setting for <i>lock-var#</i> with an optional variable label</td></tr>'
+'<tr><td>tvar#:</td><td>< text or # >[%%label]></td><td>\' \'</td><td>An initial setting for <i>trap-var#</i> with an optional variable label</td></tr>'
+'<tr><td>ns:</td><td>#</td><td>0</td><td>The number of extra data specifications following the first dataset</td></tr>'
+'<tr><td>cl:</td><td>AB | AC | MI | WP</td><td>\' \'</td><td>The class of the extra dataset. AB = Abilities that form part of this lock/trap</td></tr>'
+'<tr><td>w:</td><td>Ability name</td><td>undefined</td><td>The name of the data item pointed to by the extra dataset, in this case a lock/trap ability</td></tr>'
+'<tr><td>action:</td><td>[ 0 / 1 ]</td><td>0</td><td>A flag indicating if the Ability should appear as a token Action Button</td></tr>'
+'</table>'
+'<p>The <i>Key Lock</i> is defined as: setting user variable 1 as 53 (in this case predefining an expectation that key 53 opens the chest) with a label of "Key Number"; states there are 11 additional extra datasets; all the extra datasets are of the Abilities class; and each of the extra datasets specifies a macro definition from the Locks-Traps-DB that will be processed and stored in the <i>Dragged & Dropped</i> container.</p>'
+'<p><b>Dynamic fields:</b> There are a number of <i>Dynamic Fields</i> used in this macro - the fields of the format ^^...^^. These are dynamically replaced at run time with the data they represent, which is dependent on the specific circumstances at that point in time. Most of these are only valid in "Trap-" macros (any macro with a Supertype (Specs field 4) starting "Trap-"):</p>'
+'<table>'
+'<tr><th>Dynamic Field</th><th>Validity</th><th>Description</th></tr>'
+'<tr><td>^^chest^^</td><td>All macros</td><td>The character sheet name of this particular container</td></tr>'
+'<tr><td>^^chestid^^</td><td>All macros</td><td>The character sheet ID of this particular container</td></tr>'
+'<tr><td>^^cname^^</td><td>Trap- only</td><td>The character name of the character searching (or storing items in) the container</td></tr>'
+'<tr><td>^^tname^^</td><td>Trap- only</td><td>The token name of the character searching (or storing items in) the container</td></tr>'
+'<tr><td>^^cid^^</td><td>Trap- only</td><td>The character sheet ID of the character searching (or storing items in) the container</td></tr>'
+'<tr><td>^^tid^^</td><td>Trap- only</td><td>The token ID of the character searching (or storing items in) the container</td></tr>'
+'<tr><td>^^targetchar^^</td><td>Trap- only</td><td>Another way of specifying the character sheet name of the container (but only in Trap- macros)</td></tr>'
+'<tr><td>^^targettoken^^</td><td>Trap- only</td><td>The token name of the container</td></tr>'
+'<tr><td>^^targetcid^^</td><td>Trap- only</td><td>The character sheet ID of the container</td></tr>'
+'<tr><td>^^targettid^^</td><td>Trap- only</td><td>The token ID of the container</td></tr>'
+'</table>'
+'<p><b>API buttons:</b> The lock & trap macros run using standard Roll20 functionality, and can contain any legitimate functions that Roll20 supports, as well as API calls to loaded mods (such as the RPGMaster suite itself). To support the player (and GM) interacting with the locks and traps, API buttons are used. API buttons are text enclosed in brackets, followed by commands in parentheses e.g. [Button text](command). These are standard Roll20 macro functionality and help on them can be found in the Roll20 Help Center.</p>'
+'<p>The most common use in locks & traps is to have the player run the next macro from a choice of possible actions: the next macro can be called using <i>(~^^chest^^|macro-name)</i> or <i>(!magic --display-ability whisper-type|to-token-ID|^^chest^^|macro-name)</i>. The <i>!magic --display-ability</i> command has the advantage of being able to whisper to a character, player, the GM or publicly, whereas the tilde \'~\' macro call is less flexible, but \'~\' can allow 3D dice rolls, whereas <i>!magic --display-ability</i> will not. See <i>MagicMaster Help</i> handout for more information on the --display-ability command.</p>'
+'<p><b>Use of !setattr:</b> the call to the ChatSetAttr API (see separate documentation) is used to set several local custom attributes on the container\'s character sheet, so that the values can be accessed as the trap / lock sequence of macros progresses. Each of the values stored may not be otherwise available, as the creature doing the searching may lose the focus, and no longer be the "selected" token which otherwise would cause errors.</p>'
+'<h3>4.2 Other Lock & Trap Database Macros</h3>'
+'<p>Ability Macros other than those that represent "Trap-" macros do not have a number of the same features. The <i>Open-Locks</i> macro from the Key Lock sequence is shown below: note that the Ability Macro name in the database is "Pick-a-Lock", following the rule that the database macro name and the Supertype must be different, with the Supertype being the name that will end up in the container:</p>'
+'<h3>Pick a Lock</h3>'
+'<p style="display: inline-block; background-color: lightgrey; border: 1px solid black; padding: 4px; color: dimgrey; font-weight: extra-light;">&{template:RPGMdefault}{{title=<span style="color:red">^^chest^^</span>}}<mark style="color:green">Specs=[Pick-a-Lock,Ability,0H,Open-Locks]</mark>{{desc=You are trying to pick the lock of <span style="color:red">^^chest^^</span>. Your success is determined against your Open Locks percentage}}{{Target=[[{ {5},{@{<span style="color:red">^^chest^^</span>|openLock} } }kh1]]%}}{{Roll=[[?{Roll to Pick the Lock|1d100}]]}}{{Result=Roll<=Target}}{{successcmd=<span style="color:blue">!magic ~~display-ability c¦`{<span style="color:red">^^chest^^</span>¦thief}¦<span style="color:red">^^chest^^</span>¦Unlocked</span>}}{{failcmd=<span style="color:blue">!magic ~~display-ability public¦`{<span style="color:red">^^chest^^</span>¦thief}¦<span style="color:red">^^chest^^</span>¦Triggered</span>}}</p>'
+'<p>Here it can be seen that the <i>Specs</i> database specifier shows that the database name is "Pick-a-Lock" (the first field), but it is saved in the container character sheet as "Open-Locks" (the 4th field). The macro also uses the value of <i>OpenLock</i>, a custom attribute that was stored using the ChatSetAttr API call in the "Trap-" macro call, as it cannot be guaranteed at this point in the process that the searching character token is still selected. It is also the case that the only dynamic fields available in macros other than the "Trap-" macros are "^^chest^^" and "^^chestid^^", which will always be replaced with the character sheet name and ID (respectively) of the container when it is built by the <i>Drag & Drop</i> process and the ability macros are added to its sheet.</p>'
+'<p><b>Note:</b> This macro is using some specialised features of the RPGMaster Roll Templates: in this case the <i>Result</i> field tag will actually run a comparison of the numbers in the <i>Roll</i> and <i>Target</i> fields and display a green "Success" bar or a red "Failed" bar, depending on the result. The template will also run either the command string in the "successcmd" field, or the command string in the "failcmd" field, depending on the result, thus automatically affecting the macro sequence.</p>'
+'<p>The other macros required to make the Key Locked Chest work are defined and used in a similar fashion. See an extracted database for more examples.</p>'
+'<h3>4.3 Trap/Lock Variables</h3>'
+'<p>The author of the container ability macros can, of course, use the ChatSetAttr API command !setattr to store new custom attributes on any character sheet (but most typically the container\'s character sheet) to make changes in behavior. However, up to nine lock variables and nine trap variables exist that can be set using the RPGMaster container management dialog without going into the macro code. The AbilityData specification in any <i>Lock|Ability</i> or <i>Trap|Ability</i> macro can give them initial values and labels (using the syntax "lvar#:value%%label" or "tvar#:value%%label" with the %%label being optional), and those values altered for each individual dropped container to achieve changes in behavior as documented in each container specification. In the Ability Macros, these are then accessed either with @{^^chest^^|lock-var#} or @{^^chest^^|trap-var#}.</p>'
+'<h3>4.4 Token Images</h3>'
+'<p>There are up to 20 image URL variables that can be set by the <i>Drag & Drop</i> container system, each of which are paired with values for the width and height to set the token to. Two of these are reserved for the URLs of the images of the <i>closed</i> and <i>open</i> containers, nine are available for use by locks, and another nine for use by traps.</p>'
+'<table>'
+'<tr><th>Data Tag</th><th>Image variable</th><th>Width variable</th><th>Height variable</th><th>Used for</th></tr>'
+'<tr><td>cimg</td><td>closed-img</td><td>closed-img-size</td><td>closed-img-size|max</td><td>The image URL for a closed container</td></tr>'
+'<tr><td>oimg</td><td>open-img</td><td>open-img-size</td><td>open-img-size|max</td><td>The image URL for an open container</td></tr>'
+'<tr><td>limg1</td><td>lock-img1</td><td>lock-img1-size</td><td>lock-img1-size|max</td><td>The image URL for the first user-defined lock image</td></tr>'
+'<tr><td>limg2</td><td>lock-img2</td><td>lock-img2-size</td><td>lock-img2-size|max</td><td>The image URL for the second user-defined lock image</td></tr>'
+'<tr><td>limg#</td><td>... </td><td>... </td><td>... </td><td>The image URL for the #th user-defined lock image</td></tr>'
+'<tr><td>limg9</td><td>lock-img9</td><td>lock-img9-size</td><td>lock-img9-size|max</td><td>The image URL for the ninth user-defined lock image</td></tr>'
+'<tr><td>timg1</td><td>trap-img1</td><td>trap-img1-size</td><td>trap-img1-size|max</td><td>The image URL for the first user-defined trap image</td></tr>'
+'<tr><td>timg#</td><td>... </td><td>... </td><td>... </td><td>The image URL for the #th user-defined trap image</td></tr>'
+'<tr><td>timg9</td><td>trap-img9</td><td>trap-img9-size</td><td>trap-img9-size|max</td><td>The image URL for the ninth user-defined trap image</td></tr>'
+'</table>'
+'<p>All the variables and the images can be set using RaceData tags in the container specification, can be added to or overwritten by the AbilityData tags in the lock and trap specifications, and altered individually for each dropped container using the GM\'s [Token Setup] button or the <b>!cmd --token-img token_id</b> command. An example of the use of the <i>trap-img1</i> is below:</p>'
+'<h3>Chest 4 Poison Dart trap</h3>'
+'<p style="display: inline-block; background-color: lightgrey; border: 1px solid black; padding: 4px; color: dimgrey; font-weight: extra-light;">&{template:RPGMwarning}{{name=Poison Dart trap}}<mark style="color:green">Specs=[Poison-dart-trap,Trap|Ability,0H,Triggered]</mark>{{desc=Oh no! You\'ve triggered a trap and four poison darts fly out, one from each side of the <span style="color:red">^^chest^^</span>, each doing [[@{<span style="color:red">^^chest^^</span>|<span style="color:blue">trap-var1</span>}]]HP piercing damage and [[@{<span style="color:red">^^chest^^</span>|<span style="color:blue">trap-var2</span>}]]HP poison damage (@{<span style="color:red">^^chest^^</span>|<span style="color:blue">trap-var3</span>})}}<mark style="color:blue">AbilityData=[w:Poison Dart trap, magical:0, tvar1:1%%Dart Damage Roll, tvar2:2d4%%Poison Damage Roll, tvar3:Poison Type C%%Poison Type, timg1:https://s3.amazonaws.com/files.d20.io/images/352954823/u8yGNHOGKcTsoJQB_A3b6Q/thumb.png?1690920737|280%%Dart Ranges, ns:3],[cl:AB,w:Poison-dart-trap-noticed],[cl:AB,w:Remove-Trap-Roll],[cl:AB,w:Reset-trap,action:1]</span>{{GM desc=The poison dart trap will shoot poison darts from the container if triggered. The GM can set the damage done by the darts, the damage done by the poison, the name of the poison type (DMG p73), and set trap image 1 displaying the ranges of the poison darts by selecting the container token and then using the GM\'s [Token Setup] button, or the **!cmd --abilities**.}}<br><span style="color:orange">!token-mod --ignore-selected --ids @{^^chest^^|chest} --set imgsrc|@{^^chest^^|trap-img1} width|@{^^chest^^|trap-img1-size} height|@{^^chest^^|trap-img1-size|max}</span></p>'
+'<p>The key part of this macro is the <b>!token-mod</b> call to the TokenMod API that changes the <i>imgsrc, width,</i> and <i>height</i> values of the container token, to the image stored in <i>trap-img1</i> which in this case shows the chest with the ranges of the four poisoned darts that are ejected by the trap on this chest.</p>'
+'<h3>3.4 Types of Container Traps and Locks</h3>'
+'<p>The container database that comes with the APIs has examples of a number of different types of lock and trap:</p>'
+'<ul><li>A key lock that asks if those looting have a specific key</li>'
+'<li>A Password-based lock requiring the right password to open</li>'
+'<li>A three-digit Combination Lock</li>'
+'<li>An unlocked spell book to which a trap can be added</li>'
+'<li>A poison dart trap, with specifiable damage & poison type</li>'
+'<li>A wizard\'s spell trap, with specifiable spell and area of effect</li>'
+'<li>An exploding runes trap that turns the container to ash</li>'
+'<li>A dead body that can "come to life" as any specifiable <i>Drag & Drop</i> creature</li>'
+'<li>A sleeping character that wakes on an unsuccessful pick-pockets roll</li></ul>'
+'<p>There may also be more than these - this is the list at the time of writing. And each lock can be matched to any trap (or none) - so matching a combination with "Wake the Dead" and get the combination wrong a Lich is summoned! These can be extracted from the APIs using the command <b>!magic --extract-db Locks-Traps-DB</b> and used as examples.</p>'
+'<h2>4. Structure of a Locked/Trapped Container</h2>'
+'<p>As you will recognise if you have reviewed the earlier sections of this document, there are a number of different Roll20 ability macros that are inserted into a container\'s character sheet by the <i>Drag & Drop</i> Container system. The combination of macros inserted to the character sheet is important to make sure the container locks and traps work. It is key that there is a starting point for a character searching and looting the container, and that this starting point leads on to a sequence of macros that lead the character on a journey to either open the container and the ability to loot its items, or to suffer the consequences of a lack of caution.</p>'
+'<h3>4.1 The Starting Point</h3>'
+'<p>The starting point is always a macro of database item Supertype (Specs field 4) <i>Trap-#</i> (generally <i>Trap-0</i>) (or just <i>Trap</i>). This macro will include text to describe to the player what they are faced with as a lock &/or trap, in the current state of the lock & trap. The state of the container will be determined by the <i>Trap-version</i> attribute of the container:</p>'
+'<table>'
+'<tr><th>Trap-version</th><th>State represented</th></tr>'
+'<tr><th>0</th><th>Locks & Traps (if any) are in tact and in a locked & set state</th></tr>'
+'<tr><th>1</th><th>Locks & Traps have all been overcome and the container is easily lootable</th></tr>'
+'<tr><th>2</th><th>Lock partially overcome, or lock open and awaiting a hunt for traps</th></tr>'
+'<tr><th>3</th><th>Found a trap and awaiting the removal of the trap</th></tr>'
+'<tr><th>#</th><th>Other numbers can represent additional states the container can be left in</th></tr>'
+'</table>'
+'<p>When a character conducts a search of the container, the RPGMaster APIs will start by calling a macro on the container called <i>Trap-#</i>, where "#" is the current value of the <i>Trap-version</i>. Thus, the character encounters the container in its current state.</p>'
+'<p>The <i>Trap-0</i> macro is a special case: it not only is an entry point lock macro, but it defines the whole structure of the lock, the other database items that make it up, and the initial state of variables and images. It is always of database item class <b><i>Lock|Ability</i></b>. Its name will be the name of the lock displayed when specifying the lock for the container with the <b>!cmd --token-img</b> command, or the [Token Setup] action. It is the only lock macro to have an <i>AbilityData</i> specification. The AbilityData includes a number of repeating data sets, one for each additional Locks-Traps-DB database item that makes up the lock. Each of these extra data sets is of cl: type "AB" (although they can also include type "AC", "MI" or "WP" to add items, equipment or weapons to the container), and a w: of the database item name (not the Supertype of the item).</p>'
+'<h3>Other Lock Macros</h3>'
+'<p>Each of the database items named in the <i>Trap-0</i> macro must have a Specs specification with:</p>'
+'<ul>'
+'<li><b>First field:</b> Type (or name) of the database item</li>'
+'<li><b>Second Field:</b> "Ability"</li>'
+'<li><b>Third field:</b> Handedness (not yet used for Lock or Trap macros)</li>'
+'<li><b>Forth field:</b> Supertype - the name the macro will be given in the container sheet</li>'
+'</ul>'
+'<p>The Supertypes of the lock must form links via API button calls (or other means of linking) in a meaningful sequence. The paths must lead to a hand-off to the macros that define any trap that is associated with the container. In general, the lock also accepts an interface from the trap macro path to a macro with a Supertype of <i>"Opens-list"</i> which is included in the Lock specification. The lock may also provide macros of Supertypes <i>"Trap-1"</i> and <i>"Trap-2"</i>.</p>'
+'<h3>Macros Specifying a Trap</h3>'
+'<p>The trap macros will have entry points of <i>"Triggered"</i> and <i>"Trap-Noticed"</i>. In this case, the special case is the macro of Supertype <i>Triggered</i>, with the database item class <b><i>Trap|Ability</i></b>. This macro is the one who\'s name will be listed when selecting a trap for the container with the <b>!cmd --token-img</b> command, or the [Token Setup] action. It is also the only trap macro to have an <i>AbilityData</i> specification specifying initial states for trap-var# attributes, any token images used by the trap which, like the lock "Trap-0" macro, includes a number of repeating data sets, one for each additional Locks-Traps-DB database item that makes up the trap. Each of these extra data sets is of cl: type "AB", and a w: of the database item name (not the Supertype of the item).</p>'
+'<h3>Other Trap Macros</h3>'
+'<p>Each of the database items named in the <i>Triggered</i> macro must have a Specs specification of the same structure as the lock macros. As with locks, the Supertypes of the trap macros must form links via API button calls (or other means of linking) in a meaningful sequence. The paths typically lead to a conclusion that either results in inflicting some sort of penalty on the character trying to loot the container, or the container opening and revealing its contents. The opening is generally by handing off to a macro provided by the lock of Supertype <i>"Opens-list"</i>.</p>'
+'<p>A macro of Supertype <i>"Trap-Noticed"</i> will be called by the lock macros if a trap has been found by the character, and they want to attempt to remove it. The <i>Trap-Noticed"</i> macro will do what is necessary to determine if the particular trap selected can be removed successfully, or if the trap is actually triggered, calling other macros in sequence as necessary, often including calling the <i>Triggered</i> macro if the trap is not removed successfully.</p>'
+'<h3>Example Lock/Trap Ability Flow</h3>'
+'<p>Here is an example of how a lock and a trap, taken from the Locks-Traps-DB, create a sequence of ability macros in the chosen container character sheet. It is based on the Key Lock and Poison Dart Trap already introduced earlier in this help handout.</p>'
+'<table>'
+'<tr><td colspan="9" style="background-color:beige">Yellow = A part of the Lock</td><td colspan="10" style="background-color:aquamarine">Green = A part of the Trap</td></tr>'
+'<tr><td style="background-color:beige">Trap-1</td><td colspan="17">=></td><td rowspan="2" style="background-color:beige">Opens-List</td></tr>'
+'<tr><td style="background-color:aquamarine">Trap-3</td><td colspan="12">=></td><td rowspan="2" style="background-color:aquamarine">Trap-Noticed</td><td rowspan="2">=></td><td rowspan="2" style="background-color:aquamarine">Unlocked-Remove-Trap</td><td>[Success]</td><td>=></td></tr>'
+'<tr><td style="background-color:beige">Trap-2</td><td colspan="7">=></td><td rowspan="3" style="background-color:beige">Unlocked</td><td rowspan="3">=></td><td rowspan="3" style="background-color:beige">Unlocked-Find-Trap</td><td>[Success]</td><td>=></td><td>[Fail]</td><td>=></td><td rowspan="6" style="background-color:aquamarine">Triggered</td></tr>'
+'<tr><td rowspan="6" style="background-color:beige">Trap-0</td><td>[Have Key]</td><td colspan="6">=></td><td rowspan="2">[Fail]</td><td rowspan="2" colspan="6">=></td></tr>'
+'<tr><td rowspan="2" style="background-color:beige">[Pick the Lock]</td><td rowspan="2">=></td><td rowspan="2" style="background-color:beige">Open-Locks</td><td>[Success]</td><td colspan="3">=></td></tr>'
+'<tr><td>[Fail]</td><td colspan="13">=></td></tr>'
+'<tr><td rowspan="3">[Brute Strangth]</td><td rowspan="3">=></td><td rowspan="3" style="background-color:beige">Smash-The-Lock</td><td rowspan="3">=></td><td rowspan="3" style="background-color:beige">Smashed-Lock-Check</td><td>[Success]</td><td>=></td><td style="background-color:beige">Unlocked</td><td>^^^</td><td colspan="8"> </td></tr>'
+'<tr><td>[Critical Fail]</td><td colspan="11">=></td></tr>'
+'<tr><td>[Fail]</td><td colspan="11">=></td><td style="background-color:beige">Still-Locked</td></tr>'
+'</table>'
+'<h2>5. Specs & Data field values</h2>'
+'<p>Below are lists of the current possible values for the Lock and Trap database Ability macro sections.</p>'
+'<h3>5.1 Specs sections</h3>'
+'<pre>Specs=[Lock Type, Lock|Ability, Handedness, Trap-0 (or Trap)]</pre>'
+'<pre>Specs=[Lock Type, Ability, Handedness, Supertype]</pre>'
+'<pre>Specs=[Trap Type, Trap|Ability, Handedness, Triggered]</pre>'
+'<pre>Specs=[Trap Type, Ability, Handedness, Supertype]</pre>'
+'<p>If the item class (field 2) is "Lock|Ability", the Supertype must be "Trap-0" or "Trap", and visa-versa.</p>'
+'<p>If the item class (field 2) is "Trap|Ability", the Supertype must be "Triggered", and visa-versa.</p>'
+'<p>All fields must be explicitly specified.</p>'
+'<h4>5.1(a) Lock and Trap Types</h4>'
+'<p>There is an infinite list of lock types: the type of the "Lock|Ability" macro is the Lock name.</p>'
+'<p>There is an infinite list of trap types: the type of the "Trap|Ability" macro is the Trap name.</p>'
+'<h4>5.1(b) Macro Class</h4>'
+'<p>Classes: One of "Lock|Ability", "Trap|Ability", or just "Ability". This field is used to add the Lock or Trap name to the right base list for selection by the GM to configure the container.</p>'
+'<h4>5.1(c) Handedness</h4>'
+'<p>Handedness for Locks & Traps are not currently restricted or used by the system. In future, the number of hands specified for a lock or trap might indicate how many hands need to be contributed to enact the opening of a lock or the removal of a trap.</p>'
+'<h4>5.1(d) Lock & Trap Supertypes</h4>'
+'<p>The following Supertypes must exist for each defined lock:</p>'
+'<pre>Trap-0 (or Trap), Opens-list</pre>'
+'<p>The following Supertypes must be called by each defined lock:</p>'
+'<pre>Triggered</pre>'
+'<p>The following Supertypes must exist for each defined trap:</p>'
+'<pre>Triggered, Trap-Noticed</pre>'
+'<p>Below is a table of the Supertypes currently provided and used in the Locks-Traps-DB as distributed with the APIs. Each Supertype may be used by several lock or trap sequence macros, each having a slightly different effect for that stage in the sequence. Some Supertypes require different processing for certain Locks/Traps if the Player is rolling for skills as opposed to the GM (set by the <b>!magic --config</b> command) - the appropriate macro will be used depending on the configuration for who rolls for skills at the point the <i>Drag & Drop</i> container is built. <b>Note:</b> changing the configuration after the container is built will not alter the behaviour of the container. The container must be rebuilt if you wish the behaviour to change.</p>'
+'<table>'
+'<tr><th rowspan="2">Supertype</th><th colspan="2">Macro Versions</th></tr>'
+'<tr><th>Player Rolls</th><th>GM Rolls</th></tr>'
+'<tr><td>Trap-0</td><td colspan="2">Combination-Lock<br>Key-Lock<br>Password-Lock<br>No-Lock<br>Sleeping-Creature<br>Undead-Body</td></tr>'
+'<tr><td>Triggered</td><td colspan="2">Four-Dart-Trap<br>Destroying-Spell-Trap<br>Single-Poison-Dart-Trap<br>Summon-Undead<br>Summon-Creature<br>Wizard-Spell-Trap<br>Combination-Wrong-No-Trap<br>Explosive-Runes-Trap<br>No-Trap</td></tr>'
+'<tr><td></td></tr>'
+'<tr><td>First-Digit-0</td><td colspan="2">First-Digit-Right</td></tr>'
+'<tr><td>First-Digit-1</td><td colspan="2">First-Digit-Wrong</td></tr>'
+'<tr><td>Second-Digit-0</td><td colspan="2">Second-Digit-Right</td></tr>'
+'<tr><td>Second-Digit-1</td><td colspan="2">Second-Digit-Wrong</td></tr>'
+'<tr><td>Third-Digit-0</td><td colspan="2">Third-Digit-Right</td></tr>'
+'<tr><td>Third-Digit-1</td><td colspan="2">Third-Digit-Wrong</td></tr>'
+'<tr><td>Attempt-Right</td><td colspan="2">Password-Right</td></tr>'
+'<tr><td>Attempt-Wrong</td><td colspan="2">Password-Wrong</td></tr>'
+'<tr><td>Open-Locks</td><td>Pick-a-Lock<br>Pick-a-Pocket</td><td>GM-Roll-Pick-a-Lock<br>GM-Roll-Pick-a-Pocket</td></tr>'
+'<tr><td>Lock-Unlocked</td><td colspan="2">Unlocked-Lock</td></tr>'
+'<tr><td rowspan="2">Unlocked</td><td>Find-Traps</td><td>GM-Roll-Find-Traps</td></tr>'
+'<tr><td colspan="2">Successful-PP</td></tr>'
+'<tr><td>Unlocked-Find-Trap</td><td>Find-Trap-Roll</td><td>GM-Roll-Find-Trap-Roll</td></tr>'
+'<tr><td>Open-Or-Find-Traps</td><td colspan="2">No-Traps-Found</td></tr>'
+'<tr><td>Unlocked-Remove-Trap</td><td>Remove-Trap-Roll</td><td>GM-Roll-Remove-Trap</td></tr>'
+'<tr><td>Trap-Not-Removed</td><td colspan="2">Trap-Remains</td></tr>'
+'<tr><td>Detected-Runes</td><td colspan="2">Detect-Runes</td></tr>'
+'<tr><td>Smash-the-Lock</td><td>Smash-Lock</td><td>GM-Roll-Smash-Lock</td></tr>'
+'<tr><td>Smashed-Lock-Check</td><td>Lock-Smash</td><td>GM-Roll-Lock-Smash</td></tr>'
+'<tr><td>Still-Locked</td><td colspan="2">Not-Smashed</td></tr>'
+'<tr><td rowspan="2">Trap-Noticed</td><td>Poison-dart-trap-noticed<br>Found-Trap</td><td>GM-Roll-Dart-Trap-Noticed<br>GM-Roll-Found-Trap</td></tr>'
+'<tr><td colspan="2">No-Trap-Noticed<br>Runes-Trap-Noticed</td></tr>'
+'<tr><td>No-Lock-Trap</td><td colspan="2">No-Lock-No-Trap<br>No-Lock-Is-Trapped</td></tr>'
+'<tr><td>Trake-Damage</td><td colspan="2">Taken-Damage</td></tr>'
+'<tr><td>Opens-List</td><td colspan="2">Open+List<br>Open-the-Spellbook</td></tr>'
+'<tr><td>Trap-1</td><td colspan="2">Opened-Lock<br>Opened-the-Spellbook</td></tr>'
+'<tr><td>Trap-2</td><td colspan="2">Return-Trap-2</td></tr>'
+'<tr><td>Trap-3</td><td colspan="2">Return-Trap-3</td></tr>'
+'<tr><td>Trap-4</td><td colspan="2">Destroyed-Container<br>Destroyed-the-Spellbook</td></tr>'
+'<tr><td>Close</td><td colspan="2">Close-Container</td></tr>'
+'<tr><td>Reset</td><td colspan="2">Reset-Trap</td></tr>'
+'</table>'
+'<br>'
+'<h3>5.2 Trap-version Values</h3>'
+'<table>'
+'<tr><th>Trap-version</th><th>Mandatory</th><th>State represented</th></tr>'
+'<tr><td>0 (or none)</td><td>Yes</td><td>Locks & Traps (if any) are in tact and in a locked & set state</td></tr>'
+'<tr><td>1</td><td>No</td><td>Locks & Traps have all been overcome and remain so and the container is easily lootable</td></tr>'
+'<tr><td>2</td><td>No</td><td>Lock partially overcome, or lock open and awaiting a hunt for traps</td></tr>'
+'<tr><td>3</td><td>No</td><td>Found a trap and awaiting the removal of the trap</td></tr>'
+'<tr><td>#</td><td>No</td><td>Other numbers can represent additional states the container can be left in</td></tr>'
+'</table>'
+'<h3>5.3 Data Sections</h3>'
+'<p>Below are the definitions for each of the possible RaceData fields.</p>'
+'<p><b>Note:</b> Always refer to the database specification definitions in other sections above for detailed information on the use of these Field specifiers. Not all specifiers have an obvious use. Square brackets \'[...]\' indicate optional data - don\'t include the brackets when specifying the optional data.</p>'
+'<table>'
+' <thead>'
+' <tr>'
+' <th scope="col">Field</th>'
+' <th scope="col">Format</th>'
+' <th scope="col">Default Value</th>'
+' <th scope="col">Attribute</th>'
+' <th scope="col">Description</th>'
+' </tr>'
+' </thead>'
+' <tr><th scope="row">w:</th><td>< text ></td><td>\' \'</td><td> </td><td>Name of the database item</td></tr>'
+' <tr><th scope="row">magical:</td><td>[ 0 | 1 ]</td><td>0</td><td>Only for traps: trap is magical in nature (1), so "Remove Trap" rolls have half the chance they would otherwise</td></tr>'
+' <tr><th scope="row">slots:</th><td>#</td><td>18</td><td>container-size</td><td>Number of slots available in the container</td></tr>'
+' <tr><th scope="row">lvar#:</th><td>< text ></td><td>undefined</td><td>lock-var#</td><td>Variable used for lock processing. # can be 1 to 9</td></tr>'
+' <tr><th scope="row">tvar#:</th><td>< text ></td><td>undefined</td><td>trap-var#</td><td>Variable used for trap processing. # can be 1 to 9</td></tr>'
+' <tr><th scope="row">cimg:</th><td>URL [| width [| height ]]</td><td>Image of a closed chest</td><td>closed-img</td><td>URL of image of closed container, in a valid Roll20 format. Can be followed by width and/or height in pixels separated by pipes \'|\'</td></tr>'
+' <tr><th scope="row">oimg:</th><td>URL [| width [| height ]]</td><td>Image of an open chest</td><td>open-img</td><td>URL of image of open container, in a valid Roll20 format. Can be followed by width and/or height in pixels separated by pipes \'|\'</td></tr>'
+' <tr><th scope="row">limg#:</th><td>URL [| width [| height ]] [%% name]</td><td>undefined</td><td>lock-img#<br>lock-img#-size<br>lock-img#-size|max</td><td>URL of alternate lock image of container, in a valid Roll20 format. Can be followed by width and/or height in pixels separated by pipes \'|\', and a label for the image preceded by %%</td></tr>'
+' <tr><th scope="row">timg#:</th><td>URL [| width [| height ]] [%% name]</td><td>undefined</td><td>trap-img#<br>trap-img#-size<br>trap-img#-size|max</td><td>URL of alternate trap image of container, in a valid Roll20 format. Can be followed by width and/or height in pixels separated by pipes \'|\', and a label for the image preceded by %%</td></tr>'
+' <tr><th scope="row">ns:</th><td>< # ></td><td>0</td><td> </td><td>Number of repeating data sets</td></tr>'
+' <tr><th scope="row">cl:</th><td>< AB | MI | AC | WP ></td><td>\' \'</td><td> </td><td>Type of the repeating data set, AB = Lock / Trap ability</td></tr>'
+' <tr><th scope="row">w:</th><td>< text ></td><td>\' \'</td><td> </td><td>In repeating data set, database item name of macro to include in a lock or trap flow</td></tr>'
+'</table>'
+'<br>'
+'<h3>5.4 Character Sheet data fields</h3>'
+'<p>The Character Sheet field mapping to the API script can be altered using the definition of the fields object, the definition for which can be found at the top of the relevant <b>RPGMaster Library</b> API. You can find the complete mapping for all APIs in the RPGMaster series, with an explanation of each, in a separate document - ask the API Author for a copy.</p>'
+'</div>',
},
});
/*
* Handles for other RPG and Character Sheet specific data tables
* obtained from the RPGMaster Library.
*/
var fieldGroups;
var primeClasses;
var classLevels;
var spellLevels;
var saveLevels;
var baseSaves;
var raceSaveMods;
var clTypeLists;
var miTypeLists;
var spTypeLists;
var classMap;
var reSpellSpecs;
var reClassSpecs;
var reAttr;
var reNPCThiefSpecs;
var rogueSkills;
var baseThac0table;
const PR_Enum = Object.freeze({
YESNO: 'YESNO',
CUSTOM: 'CUSTOM',
});
const messages = Object.freeze({
noChar: '&{template:'+fields.warningTemplate+'} {{name=^^tname^^\'s\nMagic Items Bag}}{{desc=^^tname^^ does not have an associated Character Sheet, and so cannot attack}}',
initMsg:'&{template:'+fields.menuTemplate+'} {{name=Initialisation Complete}}{{desc=Initialisation complete. Command macros created. Go to Macro tab (next to the cog at the top of the Chat window), and select them to show In Bar, and turn on the Macro Quick Bar. Then start by dragging some characters on to the map to create tokens, and use Token-setup and Add-Items on each}}',
waitMsg:'&{template:'+fields.warningTemplate+'} {{name=Please Wait}}{{desc=Gathering data. Please wait for the menu to appear.}}',
convMsg:'&{template:'+fields.warningTemplate+'} {{name=Sheet Conversion}}{{Section1=You are about to convert the selected sheets to work with RPGMaster. This will move data from current tables and other places where it has previously been entered, and move it to where RPGMaster can make use of it. This means that the Character Sheets will probably become unusable in the way you were previously playing. <span style="color:red">***This cannot be undone!***</span> **It is highly recommended that you make copies of the Character Sheets before converting them** or, even better, make a complete copy of the campaign to use with RPGMaster in case you wish to reload any part from a previous version.}}',
imgMsg: '&{template:'+fields.warningTemplate+'}{{name=Can\'t Copy Marketplace Image}}{{desc=Unfortunately, it is not possible to use a token image quick copy to copy an image from a token with a marketplace image. Please select a token with an image from your own image library.}}',
});
const MenuState = Object.freeze({
ENABLED: false,
DISABLED: true,
});
const Attk = Object.freeze({
TO_HIT: 'TO_HIT',
ROLL: 'ROLL',
TARGET: 'TARGET',
});
const TwoWeapons = Object.freeze({
SINGLE: 0,
PRIMARY: 2,
SECONDARY: 4,
NOPENALTY: ['ranger'],
});
const BT = Object.freeze({
ALL_PRSPELLS: 'ALL_PRSPELLS',
ALL_POWERS: 'ALL_POWERS',
STOREITEM: 'STOREITEM',
CS_RIGHT: 'CS_PRIMARY',
CS_LEFT: 'CS_OFFHAND',
CS_BOTH: 'CS_BOTH',
CS_HAND: 'CS_HAND',
CLEAR_CTRL: 'CLEAR_CTRL',
PLAYER_CTRL: 'PLAYER_CTRL',
SWITCH_CS_CHECK: 'SWITCH_CS_CHECK',
CLASS_F: 'CLASS_F',
CLASS_W: 'CLASS_W',
CLASS_P: 'CLASS_P',
CLASS_R: 'CLASS_R',
CLASS_PSI: 'CLASS_PSI',
LEVEL_F: 'LEVEL_F',
LEVEL_W: 'LEVEL_W',
LEVEL_P: 'LEVEL_P',
LEVEL_R: 'LEVEL_R',
LEVEL_PSI: 'LEVEL_PSI',
RACE: 'RACE',
CREATURE: 'CREATURE',
NPC: 'NPC',
CONTAINER: 'CONTAINER',
CREATURE_CKD: 'CREATURE_CKD',
CONTAINER_CKD: 'CONTAINER_CKD',
RESET_CONTAINER: 'RESET_CONTAINER',
TRAPTYPE: 'TRAPTYPE',
LOCKTYPE: 'LOCKTYPE',
SET_CLASS: 'SET_CLASS',
SET_CLASS_TYPE: 'SET_CLASS_TYPE',
REVIEW_CLASS: 'REVIEW_CLASS',
REVIEW_RACE: 'REVIEW_RACE',
REVIEW_STYLE: 'REVIEW_STYLE',
CHANGE_NAME: 'CHANGE_NAME',
ABILITY: 'ABILITY',
AB_PC: 'AB_PC',
AB_DM: 'AB_DM',
AB_OTHER: 'AB_OTHER',
AB_REPLACE: 'AB_REPLACE',
AB_SIMPLE: 'AB_SIMPLE',
AB_FULL: 'AB_FULL',
AB_CLASSES: 'AB_CLASSES',
AB_SAVES: 'AB_SAVES',
AB_MANAGE_TOKEN: 'AB_MANAGE_TOKEN',
AB_ASK_TOKENBARS: 'AB_ASK_TOKENBARS',
AB_SET_TOKENBARS: 'AB_SET_TOKENBARS',
AB_RESET_TOKENBARS: 'AB_RESET_TOKENBARS',
AB_TOKEN: 'AB_TOKEN',
AB_TOKEN_NONE: 'AB_TOKEN_NONE',
AB_TOKEN_ASK_LINKED:'AB_TOKEN_ASK_LINKED',
AB_TOKEN_SET_LINKED:'AB_TOKEN_SET_LINKED',
AB_TOKEN_SET_ALL: 'AB_TOKEN_SET_ALL',
AB_TOKEN_ASK_ALL: 'AB_TOKEN_ASK_ALL',
AB_SILENT: 'AB_SILENT',
STR_REPLACE: 'STR_REPLACE',
SPELLCONV_MENU: 'SPELLCONV_MENU',
FROMSPELL: 'FROMSPELL',
TOSPELL: 'TOSPELL',
CONVSPELL: 'CONVSPELL',
REVIEW_SPELL: 'REVIEW_SPELL',
FROMITEM: 'FROMITEM',
TOITEM: 'TOITEM',
STORE_ITEM: 'STORE_ITEM',
REVIEW_ITEM: 'REVIEW_ITEM',
ITEMCONV_MENU: 'ITEMCONV_MENU',
TOKEN_IMG: 'TOKEN_IMG',
});
/*
* Object defining simple RPGMaster series ability actions to
* their respective APIs and registered API actions.
*/
const redMaster = Object.freeze({
init_menu: {api:'init',action:'menu'},
attk_hit: {api:'attk',action:'attk_hit'},
attk_roll: {api:'attk',action:'attk_roll'},
attk_target: {api:'attk',action:'attk_target'},
attk_menu: {api:'attk',action:'menu'},
other_actions: {api:'attk',action:'other_actions'},
cast_mu: {api:'magic',action:'cast_mu_spell'},
cast_pr: {api:'magic',action:'cast_pr_spell'},
cast_spell: {api:'magic',action:'cast_spell'},
spells_menu: {api:'magic',action:'spells_menu'},
use_power: {api:'magic',action:'use_power'},
powers_menu: {api:'magic',action:'powers_menu'},
use_mi: {api:'magic',action:'use_mi'},
mi_menu: {api:'magic',action:'mi_menu'},
rest: {api:'magic',action:'rest'},
});
const reIgnore = /[\s\-\_]*/gi;
const reInvalid = /[\'\"\[\]\(\)\|\$\%\@\?\{\}\\]/g;
const reAction = /abilitydata\s*=\s*\[[^\]]*?action:([01]).*?[,\]]/im;
const reDiceSpec = /(\d+)(?:d(\d+))?([-+]\d+(?:d\d+)?(?:[-+]\d+)?)?(?:r(\d+))?/i;
const reMod = /([-+]\d+)(?:d(\d+))?([-+]\d+)?/i;
const reRaceData = /}}\s*?RaceData\s*?=.*?{{/im;
const replacers = [
[/\\api;?/g, "!"],
[/\\lbrc;?/g, "{"],
[/\\rbrc;?/g, "}"],
[/\\gt;?/gm, ">"],
[/\\lt;?/gm, "<"],
[/<<|«/g, "["],
[/\\lbrak;?/g, "["],
[/>>|»/g, "]"],
[/\\rbrak;?/g, "]"],
[/\\\^/g, "?"],
[/\\ques;?/g, "?"],
[/`/g, "@"],
[/\\at;?/g, "@"],
[/~/g, "-"],
[/\\dash;?/g, "-"],
[/\\n/g, "\n"],
[/¦/g, "|"],
[/\\vbar;?/g, "|"],
[/\\clon;?/g, ":"],
[/\\amp;?/g, "&"],
[/\\lpar;?/g, "("],
[/\\rpar;?/g, ")"],
[/\\cr;?/g, "\n"],
[/\\comma;?/g, ","],
];
const encoders = [
[/\r?\n/gm,'\\n'],
[/'/gm,"\\'"],
[/&/gm,"\\\\amp;"],
[/>/gm,"\\\\gt;"],
[/</gm,"\\\\lt;"]
];